From fefb1b473633d1cdc059db3c7756ff44946cda86 Mon Sep 17 00:00:00 2001 From: Sakurasan <26715255+Sakurasan@users.noreply.github.com> Date: Wed, 2 Sep 2026 14:10:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=AE=B0=E5=BD=95=E5=B9=B6=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E6=AF=8F=E6=AC=A1=E7=94=9F=E6=88=90=E6=B6=88=E8=80=97?= =?UTF-8?q?=E7=9A=84LLM=E8=B0=83=E7=94=A8=E6=AC=A1=E6=95=B0=EF=BC=88llm=5F?= =?UTF-8?q?calls=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/database.py | 2 ++ backend/routes/admin.py | 2 +- backend/routes/ai_analysis.py | 2 +- backend/services/ai_service.py | 16 +++++++++++----- src/lib/ai-analysis-api.ts | 1 + src/routes/ai-analysis.tsx | 1 + 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/backend/database.py b/backend/database.py index 74d626d..eda4d25 100644 --- a/backend/database.py +++ b/backend/database.py @@ -83,6 +83,7 @@ CREATE TABLE IF NOT EXISTS ai_reports ( model TEXT NOT NULL, tokens_used INTEGER, generation_count INTEGER NOT NULL DEFAULT 1, + llm_calls INTEGER, created_at TEXT NOT NULL DEFAULT (datetime('now','localtime')), updated_at TEXT, UNIQUE(trade_date, report_type) @@ -121,6 +122,7 @@ def init_db(): for alter_sql in ( "ALTER TABLE ai_reports ADD COLUMN generation_count INTEGER NOT NULL DEFAULT 1", "ALTER TABLE ai_reports ADD COLUMN updated_at TEXT", + "ALTER TABLE ai_reports ADD COLUMN llm_calls INTEGER", ): try: conn.execute(alter_sql) diff --git a/backend/routes/admin.py b/backend/routes/admin.py index 19e77c9..ca10aa5 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -144,7 +144,7 @@ async def admin_list_reports(request: Request): try: rows = conn.execute( "SELECT id, trade_date, report_type, title, summary, tools_used, model, tokens_used, " - "generation_count, created_at, updated_at " + "generation_count, llm_calls, created_at, updated_at " "FROM ai_reports ORDER BY trade_date DESC, id DESC LIMIT 50" ).fetchall() items = [] diff --git a/backend/routes/ai_analysis.py b/backend/routes/ai_analysis.py index 1ff66fa..5ebe5ce 100644 --- a/backend/routes/ai_analysis.py +++ b/backend/routes/ai_analysis.py @@ -64,7 +64,7 @@ async def list_reports(): try: rows = conn.execute( "SELECT id, trade_date, report_type, title, summary, tools_used, model, tokens_used, " - "generation_count, created_at, updated_at " + "generation_count, llm_calls, created_at, updated_at " "FROM ai_reports ORDER BY trade_date DESC, id DESC LIMIT 50" ).fetchall() items = [] diff --git a/backend/services/ai_service.py b/backend/services/ai_service.py index 3d08ccb..cdb7d37 100644 --- a/backend/services/ai_service.py +++ b/backend/services/ai_service.py @@ -227,11 +227,13 @@ async def collect_ai_analysis(trade_date: str) -> dict: # ── 阶段一:工具轮(只获取数据,模型若直接开写报告则丢弃,由阶段二重写) ── tools_used = [] total_tokens = 0 + llm_calls = 0 was_truncated = False max_rounds = 8 for i in range(max_rounds): response = await call_llm(messages, tools=TOOLS) + llm_calls += 1 total_tokens += response.get("usage", {}).get("total_tokens", 0) choice = response["choices"][0] @@ -277,6 +279,7 @@ async def collect_ai_analysis(trade_date: str) -> dict: "content": part_prompt.format(title=trade_date) if part_idx == 0 else part_prompt, }] response = await call_llm(part_messages) + llm_calls += 1 total_tokens += response.get("usage", {}).get("total_tokens", 0) choice = response["choices"][0] part_content = choice["message"].get("content") or "" @@ -292,9 +295,10 @@ async def collect_ai_analysis(trade_date: str) -> dict: final_content += (final_content and "\n\n" or "") + part_content summary = _extract_summary(final_content) - report_id = _save_report(trade_date, final_content, summary, tools_used, total_tokens) + report_id = _save_report(trade_date, final_content, summary, tools_used, total_tokens, llm_calls) + print(f"[ai-service] 生成完成:LLM调用 {llm_calls} 次,tokens {total_tokens}") - return {"id": report_id, "tokens_used": total_tokens, "tools_used": tools_used, "truncated": was_truncated} + return {"id": report_id, "tokens_used": total_tokens, "llm_calls": llm_calls, "tools_used": tools_used, "truncated": was_truncated} def _extract_summary(content: str) -> str: @@ -416,14 +420,14 @@ def _get_prev_snapshot_section(trade_date: str) -> str: conn.close() -def _save_report(trade_date: str, content: str, summary: str, tools_used: list, tokens_used: int) -> int: +def _save_report(trade_date: str, content: str, summary: str, tools_used: list, tokens_used: int, llm_calls: int = 0) -> int: """保存报告到数据库(同日重生成:覆盖内容、generation_count+1、tokens 记当次消耗)""" conn = get_connection() try: conn.execute( """INSERT INTO ai_reports - (trade_date, report_type, title, content, summary, tools_used, model, tokens_used, updated_at) - VALUES (?, 'daily', ?, ?, ?, ?, ?, ?, datetime('now','localtime')) + (trade_date, report_type, title, content, summary, tools_used, model, tokens_used, llm_calls, updated_at) + VALUES (?, 'daily', ?, ?, ?, ?, ?, ?, ?, datetime('now','localtime')) ON CONFLICT(trade_date, report_type) DO UPDATE SET title = excluded.title, content = excluded.content, @@ -431,6 +435,7 @@ def _save_report(trade_date: str, content: str, summary: str, tools_used: list, tools_used = excluded.tools_used, model = excluded.model, tokens_used = excluded.tokens_used, + llm_calls = excluded.llm_calls, updated_at = excluded.updated_at, generation_count = ai_reports.generation_count + 1""", ( @@ -441,6 +446,7 @@ def _save_report(trade_date: str, content: str, summary: str, tools_used: list, json.dumps(tools_used), AI_MODEL, tokens_used, + llm_calls, ), ) conn.commit() diff --git a/src/lib/ai-analysis-api.ts b/src/lib/ai-analysis-api.ts index ecbd884..8ea6a6c 100644 --- a/src/lib/ai-analysis-api.ts +++ b/src/lib/ai-analysis-api.ts @@ -15,6 +15,7 @@ export interface AiReport { model: string; tokens_used: number; generation_count?: number; + llm_calls?: number | null; issue_number?: number; created_at: string; updated_at?: string | null; diff --git a/src/routes/ai-analysis.tsx b/src/routes/ai-analysis.tsx index 4c89fcb..4b44bb8 100644 --- a/src/routes/ai-analysis.tsx +++ b/src/routes/ai-analysis.tsx @@ -132,6 +132,7 @@ function AiAnalysisPage() { {report.updated_at || report.created_at} {report.tokens_used?.toLocaleString()} tokens + {report.llm_calls ? {report.llm_calls} 次 LLM 调用 : null} {(report.generation_count ?? 1) > 1 && ( 第 {report.generation_count} 次生成 )}