From 5bc69ad9ce337b0ec37b3dd81a0ed7122515ac9c Mon Sep 17 00:00:00 2001 From: root Date: Fri, 24 Apr 2026 18:24:25 +0500 Subject: [PATCH] fix(cfai): handle Llama 4 Scout direct JSON array response in Generate() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Llama 4 Scout returns the model output directly as a JSON array in the 'response' field rather than as a plain string or [{"generated_text":"..."}]. The old fallback parsed it as [{"generated_text":""}] (Go JSON ignores unknown fields) and silently returned an empty string — causing chapter-names jobs to finish with results:null in the payload despite items_done matching items_total. Fix: only accept the generated_text fallback when the value is non-empty; otherwise return the raw JSON bytes as a string so callers (parseChapterTitlesJSON etc.) can extract what they need. --- backend/internal/cfai/text.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/backend/internal/cfai/text.go b/backend/internal/cfai/text.go index 5c9688d..c62bf10 100644 --- a/backend/internal/cfai/text.go +++ b/backend/internal/cfai/text.go @@ -237,14 +237,18 @@ func (c *textGenHTTPClient) Generate(ctx context.Context, req TextRequest) (stri if err := json.Unmarshal(wrapper.Result.Response, &text); err == nil { return text, nil } - // Fall back: array of objects with a "generated_text" field. + // Fall back: array of objects with a "generated_text" field + // (older CF AI models return [{"generated_text":"..."}]). var arr []struct { GeneratedText string `json:"generated_text"` } - if err := json.Unmarshal(wrapper.Result.Response, &arr); err == nil && len(arr) > 0 { + if err := json.Unmarshal(wrapper.Result.Response, &arr); err == nil && len(arr) > 0 && arr[0].GeneratedText != "" { return arr[0].GeneratedText, nil } - return "", fmt.Errorf("cfai/text: model %s: unrecognised response shape: %s", req.Model, wrapper.Result.Response) + // Final fallback: model returned the result directly as a JSON value + // (e.g. Llama 4 Scout returns [{"number":1,"title":"..."},...] directly). + // Return the raw JSON bytes as a string so callers can parse it themselves. + return string(wrapper.Result.Response), nil } // Models returns all supported text generation model metadata.