From 5c953289b1e40ce69b00102a322c84ebf9f35d9f Mon Sep 17 00:00:00 2001 From: asepharyana Date: Tue, 15 Sep 2026 21:15:49 +0700 Subject: [PATCH] =?UTF-8?q?fix:=20report=20504=20=E2=80=94=20cap=20triase?= =?UTF-8?q?=20LLM=205=20artikel,=20narasi=5Fawam=20persist=20ke=20payload;?= =?UTF-8?q?=20report=20FE=20bahasa=20awam?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/internal/agents/sentiment.go | 7 ++++++- backend/internal/reports/report.go | 5 +++-- web/src/pages/Report.tsx | 12 +++++++----- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/backend/internal/agents/sentiment.go b/backend/internal/agents/sentiment.go index 5f23693..a69edeb 100644 --- a/backend/internal/agents/sentiment.go +++ b/backend/internal/agents/sentiment.go @@ -52,12 +52,17 @@ func AnalyzeSentiment(ctx context.Context, d Deps, ticker string) model.AgentRes pos, neg, neu := 0, 0, 0 var keyEvents []string useLLM := d.LLM != nil && d.LLM.Available() + // Cap LLM triage calls: each is one HTTP round-trip to OmniRoute + // (~5-15s). More than 5 articles and report generation exceeds the + // 60s reverse-proxy read timeout -> 504 with a persisted-but-stale + // report. Rules path covers the rest via keywordSentiment. + const maxLLMTriage = 5 for i, a := range news.Results { if i >= 20 { break } label, conf := "neutral", 0.5 - if useLLM { + if useLLM && i < maxLLMTriage { label, conf = d.LLM.SentimentTriage(ctx, d.TriageModel, a.Title, a.Body) } else { label, conf = keywordSentiment(a.Title + " " + a.Body) diff --git a/backend/internal/reports/report.go b/backend/internal/reports/report.go index 458b445..9bbd540 100644 --- a/backend/internal/reports/report.go +++ b/backend/internal/reports/report.go @@ -76,7 +76,8 @@ func (b *Builder) Build(ctx context.Context, ticker, profile string) (Report, in all = append(all, s.Citations...) } all = model.MarkStale(all, model.StaleSession(time.Now())) - raw, _ := json.Marshal(map[string]any{"ticker": ticker, "sections": sections, "synthesis": synth}) + narasi := b.narasiAwam(ctx, ticker, synth, sections) + raw, _ := json.Marshal(map[string]any{"ticker": ticker, "sections": sections, "synthesis": synth, "narasi_awam": narasi}) citesRaw, _ := json.Marshal(all) id, err := b.DB.SaveReport(ticker, string(raw), string(citesRaw)) if err != nil { @@ -86,7 +87,7 @@ func (b *Builder) Build(ctx context.Context, ticker, profile string) (Report, in Ticker: ticker, GeneratedAt: todayStr(), Sections: sections, Synthesis: synth, AgentScores: results, AllCitations: all, - NarasiAwam: b.narasiAwam(ctx, ticker, synth, sections), + NarasiAwam: narasi, }, id, nil } diff --git a/web/src/pages/Report.tsx b/web/src/pages/Report.tsx index 3f196ca..b42ec53 100644 --- a/web/src/pages/Report.tsx +++ b/web/src/pages/Report.tsx @@ -2,6 +2,7 @@ import { createSignal, For, Show, onMount } from "solid-js"; import { useParams } from "@solidjs/router"; import { api, type ReportPayload } from "../lib/api"; import { Citations } from "../components/Citations"; +import { Term } from "../components/Awam"; import { PageHead, RecBadge } from "../components/ui"; import { Badge } from "../components/ui/badge"; import { Button } from "../components/ui/button"; @@ -84,16 +85,17 @@ export default function Report() { - {(s) => {s.name}

{s.body}

} + {(s) => {s.name}

{s.body}

}
- Interrogate this report + Tanya soal report ini 💬
- setQuestion(e.currentTarget.value)} /> - + setQuestion(e.currentTarget.value)} /> +
-

{answer()}

+

{answer()}

+

Jawaban diambil dari data report ini + — bukan karangan.