Files
news/configs/llm_models.yaml
T
simon ff911cf6f7 feat: Token Plan 迁移与 .env 热加载,并修复日报 AI 摘要为空
Token Plan 迁移 / 配置热加载:
- configs/llm_models.yaml: 各场景切到 Token Plan(deepseek-v4.1-flash / qwen3.6-flash)
- 新增 configs/runtime_env.py: .env 按 (mtime_ns, size) 热加载并同步 os.environ,
  统一 env_get 取值;llm / embedding / vectorstore / mcp / pipeline 改用 env_get
- configs/loader.py / scripts/run_scheduler.py 等配套调整
- 新增 tests/test_hot_reload.py

日报 AI 摘要为空修复(2026-09-25):
- 根因: 推理模型的 reasoning token 与正文共用 max_tokens, 预算 1500 被"思考"
  占满 -> text_tokens=0 / finish_reason=length, 摘要静默为空且不重试
- daily_report 场景新增 max_tokens(默认 4000, YAML 保存即热生效);
  LLMConfig 支持可选 max_tokens; 分块预算 800 -> 2000
- _llm_call 拆出 _call_once, 正文为空时自动加倍预算重试(上限 16000),
  用尽才降级返回空串; 网络异常重试语义不变
- docs/user-guide.md 新增 FAQ; continuation.md 记录本次排查
- 已重跑 2026-09-25 日报(report_id=357)补回 466 字摘要

测试: 相关用例 56 passed(test_hot_reload 12 passed);
      ruff 无新增问题; 3 个 crawler 既有失败与本改动无关
2026-09-25 11:13:37 +08:00

138 lines
8.7 KiB
YAML

# =============================================================================
# configs/llm_models.yaml —— 大模型使用场景配置
#
# 本文件集中配置本项目所有调用 AI 大模型的地方,每个场景可独立指定
# provider(厂商/服务类型)与 model(模型名),互不影响、单独切换。
#
# ── 配置优先级(从高到低)──────────────────────────────────────────────────────
# 1. 代码 / 命令行显式参数(如 --provider qwen --model qwen-plus)
# 2. 本文件 scenes.<场景>.xxx
# 3. 环境变量 / .env(LLM_PROVIDER、DEEPSEEK_MODEL 等,向后兼容)
# 4. 代码内置默认值
#
# ── 规则 ─────────────────────────────────────────────────────────────────────
# · provider 取值:
# 对话大模型: deepseek | qwen(OpenAI 兼容 chat 接口)
# 向量嵌入模型: dashscope | local-bge(仅 embedding 场景)
# · model 留空 = 该场景不覆盖模型 → 回退 .env(如 DEEPSEEK_MODEL / QWEN_MODEL /
# LLM_MODEL);若全部缺失则直接报错,绝不静默使用内置默认模型。
# · api_key_env / base_url_env 为可选字段,填写存放 API Key / 服务地址的
# 环境变量名;API Key 一律放 .env,禁止写入本文件(安全规范)。
# · 修改后无需重启常驻服务即可生效:configs/loader.py 以 (mtime, size) 失效缓存,
# 保存后下一次调用即读到新值;.env 的改动由 configs/runtime_env.py 在约 2s 内热更新。
# =============================================================================
# ---- 全局默认参数(各场景可覆盖;低于 .env,高于代码内置默认)----
defaults:
timeout_sec: 60
temperature: 0.1
scenes:
# ------------------------------------------------------------------------- #
# 场景 1: 投资事件抽取(M4 核心)
# ------------------------------------------------------------------------- #
# 用途:对每条唯一新闻调用大模型,抽取结构化投资事件
# (stock_codes / company_names / industries / sentiment / importance /
# event_type / summary),输出严格 JSON,经 Pydantic 校验后落盘。
# 调用方: llm/extractor.py、scripts/run_event_extraction.py、
# scheduler/pipeline.py 的 llm 步骤。
# 频率:每日数百~数千篇;建议异步并发(--concurrency,默认 3)。
# 使用方式:
# uv run a-share events # 读本场景配置
# uv run a-share events --provider qwen # CLI 临时覆盖 provider
# uv run a-share events --model qwen-max # CLI 临时覆盖模型
# 对模型的要求:
# · 必须支持 OpenAI 兼容 chat/completions 接口;
# · 必须支持 JSON 结构化输出(response_format=json_object,硬性要求);
# · 上下文窗口 ≥ 16K tokens(单篇正文最多截断到 8000 字符);
# · 中文理解能力强,能区分 A 股事件类型(业绩预告/投资并购/宏观政策等 23 类);
# · 低 temperature(0.1)保证抽取稳定,避免字段抖动。
# 建议模型: deepseek-v4-flash(生产实测) / deepseek-chat / qwen-plus / qwen-max
event_extraction:
provider: qwen # 建议 deepseek | qwen;留空则回退 .env 的 LLM_PROVIDER
model: qwen3.6-flash # Token Plan 模型;注意 Token Plan 无 qwen3.7-flash
api_key_env: QWEN_API_KEY # Token Plan 计费账号(sk-sp-…);勿用 DASHSCOPE_API_KEY
base_url_env: QWEN_BASE_URL # .env 指向 token-plan.*.maas.aliyuncs.com
temperature: 0.1
timeout_sec: 60
max_attempts: 3 # 单篇解析失败的最大重试次数
# ------------------------------------------------------------------------- #
# 场景 2: 日报 AI 摘要
# ------------------------------------------------------------------------- #
# 用途:每天汇总「新闻联播 + 过去 24h 高重要度新闻 + 近 N 日重要公告/调研」,
# 生成 500 字以内的日报要点摘要,渲染进 HTML 日报。
# 调用方: scheduler/reporter.py 的 _generate_ai_summary → _llm_summarize。
# 频率:每天 1 次(07:00 定时任务,与 pipeline 同批)。
# 使用方式:无需手动触发,定时任务自动执行;失败自动降级(日报留空,不影响入库)。
# 对模型的要求:
# · OpenAI 兼容 chat 接口(不需要 JSON 输出);
# · 输出长度 ≥ max_tokens 配置值(见下,输出超长会被截断并记 WARNING);
# · 中文摘要能力强、要点化输出稳定(每条一行,以 "- " 开头);
# · 上下文窗口 ≥ 8K tokens(素材按 3000 字符/块分块,多块先分段再合并);
# · temperature 0.3 左右,兼顾稳定与表达;网络失败按指数退避重试 3 次。
# · max_tokens 说明:推理模型(deepseek-v4.1-flash 等)的 reasoning token 与
# 正文共用该预算;预算过小时"思考"会占满配额导致正文为空
# (finish_reason=length、0 字符,日报因此没有 AI 摘要)。代码兜底见
# scheduler/reporter.py: 正文为空时自动加倍预算重试(最多 2 次,上限 16000)。
# 建议模型: deepseek-v4-flash(生产实测) / deepseek-chat / qwen-plus
daily_report:
provider: qwen # Token Plan 计费账号
model: deepseek-v4.1-flash
api_key_env: QWEN_API_KEY
base_url_env: QWEN_BASE_URL
temperature: 0.3
timeout_sec: 60
max_tokens: 4000 # 单块/合并摘要输出预算(需为 reasoning token 预留余量)
# ------------------------------------------------------------------------- #
# 场景 3: 个股 AI 要点分析
# ------------------------------------------------------------------------- #
# 用途:针对观察清单中的单只股票,汇总其近期公告/调研/新闻/互动问答,
# 生成 5-8 条要点分析,渲染进个股日报。
# 调用方: scheduler/stock_reporter.py 的 _generate_ai_summary。
# 频率:每交易日 1 次(07:30),对 watchlist 内每只股票各调用一次。
# 使用方式:定时任务自动执行;单次失败不影响其他股票(该股显示"AI 摘要暂不可用")。
# 对模型的要求:
# · OpenAI 兼容 chat 接口(不需要 JSON 输出);
# · 输出长度 ≥ 500 tokens(max_tokens=500);
# · 中文要点分析能力,输入素材最多 3500 字符(公告+调研+新闻+互动问答);
# · temperature 0.3 左右。
# · 输出长度需求:约 500 tokens(代码内置,不在本文件配置)。
# 建议模型: deepseek-v4-flash(生产实测) / deepseek-chat / qwen-plus
stock_report:
provider: qwen # Token Plan(个股日报当前禁用,配置好以防将来启用时漏计费)
model: qwen3.6-flash
api_key_env: QWEN_API_KEY
base_url_env: QWEN_BASE_URL
temperature: 0.3
timeout_sec: 60
# ------------------------------------------------------------------------- #
# 场景 4: 文本向量化 Embedding(新闻/事件入库 + 语义检索)
# ------------------------------------------------------------------------- #
# 用途:把新闻正文/事件文本转为向量,写入 Qdrant 知识库;检索时对查询文本
# 同样向量化后做相似度搜索。M5 入库、MCP 检索、pipeline 均复用本场景。
# 调用方: embedding/remote.py(远程)、embedding/local.py(本地)、
# embedding/factory.py、scripts/run_embedding.py、mcp_server/tools.py。
# 使用方式:
# uv run a-share embed # 读本场景配置
# uv run a-share embed --provider local-bge # 临时切换本地模型
# 注意:这是「嵌入模型」而非对话大模型,二选一:
# · provider: dashscope → 阿里百炼 text-embedding-v3(远程,需 API key);
# · provider: local-bge → 本地 BGE-M3(离线,需 uv sync --extra
# local-embedding,首次加载约 2.3GB)。
# 对模型的要求:
# · 输出固定维度向量(本项目默认 1024 维,DashScope 与本地 BGE-M3 兼容);
# · 中文语义匹配效果好,支持 batch 输入(单批上限 batch_limit 条);
# · 远程需 OpenAI 兼容 embeddings 接口。
# 建议模型: text-embedding-v3(远程) / BAAI/bge-m3(本地)
embedding:
provider: # 建议 dashscope | local-bge;留空则回退 .env 的 EMBEDDING_PROVIDER
model: # 留空则回退 .env(DASHSCOPE_EMBEDDING_MODEL / LOCAL_EMBEDDING_MODEL)
api_key_env: # 例如: DASHSCOPE_EMBEDDING_API_KEY / DASHSCOPE_API_KEY
base_url_env: # 例如: DASHSCOPE_EMBEDDING_BASE_URL
timeout_sec: 60
max_attempts: 3 # 单批请求失败重试次数
batch_limit: 10 # 单批最大条数(百炼实测上限 10,勿调大)