3 个人工作记录——分析师子图实现
3 分析师子图实现
本文记录 analyst 阶段从“可跑通”到“可控、可回溯、可下游消费”的落地过程。
核心目标是:让分析报告严格建立在工具证据上,并且能稳定下游阶段。
关键代码入口:
backend/app/graph/analyst_subgraph.py:四分析师 ReAct 子图、工具轮次控制、报告产出backend/app/dataflows/interface.py:工具到 vendor 的路由与回退backend/app/dataflows/vendors/akshare_vendor.py:A 股主数据源(默认)backend/app/dataflows/vendors/tushare_vendor.py:可选回退数据源backend/app/core/llm.py:OpenAI 兼容模型工厂(含本地 Ollama 自动探测)backend/app/graph/runner.py:主流程编排与阶段状态落盘
一、当前子图目标:先“取证闭环”,再“结论输出”
当前 analyst_subgraph 不是简单的“LLM 一次成文”,而是围绕三件事设计:
- 证据闭环:每个分析角色(如技术面、新闻面)必须先调用工具拿到数据,证据不够就不能结束。
- 过程可控:系统给每个角色设置了最少/最多工具调用次数,还会在证据不足时自动提醒重试,避免太早结束或无限循环。
- 结果可消费:输出统一为 data-first report,直接供下游 LLM 阶段使用。
这使分析阶段从“依赖模型自觉”升级为“流程层保障质量底线”。
二、数据层:抽象工具 + Vendor 路由 + 回退链
当前数据层保持“图层无感知 vendor”的原则:图只调用抽象工具,不直接耦合 AKShare/TuShare。
route_to_vendor(...) 现在支持:
- 先读
tool_vendors(工具级配置),再读data_vendors(类别级配置)。 - 失败时按回退链继续尝试,不把单一数据源抖动直接放大到图层失败。
- 覆盖股票、技术指标、财务三表、新闻/宏观/高管交易等工具族。
实践效果:上层提示词和图编排只关心“证据字段是否可用”,不需要写 vendor 分支逻辑。
三、LangGraph 子图编排:四角色串联 + 每角色 ReAct 循环
1)角色顺序与职责
当前顺序来自 selected_analysts(),默认链路是:
四类角色分别覆盖:
market:价格与技术面(get_stock_data+get_indicators)social:舆情与讨论线索(当前以get_news聚合相关新闻语料)news:公司/宏观事件 + global news + insider transactionsfundamentals:财务摘要与三表(利润表/资产负债表/现金流)
2)单角色内部机制
每个角色都采用一致的 ReAct 流程:
和早期版本相比,当前多了三道质量护栏:
- 最小工具轮次:
market=2、social=2、news=3、fundamentals=3 - 重试提醒机制:轮次不足会注入补证据提醒消息,强制继续取证
- 最大工具轮次上限:达到上限后强制收口,防止无限循环
四、报告形态升级:从“模型自由发挥”到“Data-First Report”
当前每个角色最终写入 *_report 时,会走 _build_data_first_report(...),统一产出结构:
- 工具原始数据摘录(按工具分块)
- 基于证据的分析结论(过滤客服式/建议式噪音)
- 研究关注点与角色边界说明
- 关键要点表(证据来源、结论口径、备注)
其中 market 角色还增加了程序化增强段,包括:
- 指标数值提取与偏离计算
- 条件化解读(偏多/中性/偏空触发条件)
- 状态合成与不确定性声明
这让报告从“只看模型文风”转为“证据块 + 结论块并存”,更利于审计和复盘。
五、LLM 接入:统一工厂 + 本地 Ollama 兜底
由于api还没下发,采用本地模型ollama。backend/app/core/llm.py 的当前策略是:
llm_enabled()关闭时直接降级,不阻塞流程。- 显式配置
base_url时优先使用该配置。 - 未显式配置时可自动探测本地 Ollama OpenAI 兼容接口(
localhost:11434/v1)。 - 对 Ollama 场景使用
trust_env=False的 httpx client,规避系统代理导致的本地 502 问题。
因此模型层做到了“可云端、可本地、可降级”,而图层逻辑无需改动。
六、主流程对齐:analyst 输出已接入全链路阶段编排
当前主图 runner.py 链路:
analyst 阶段完成后,会把以下核心文本资产注入后续阶段:
market_reportsocial_reportnews_reportfundamentals_reportanalyst_react_summary(轨迹摘要)
同时每个阶段都会更新 stage_log 并落盘运行快照,前端可实时查看进度,而不是“跑完才有结果”。
七、两次大试错:从“能跑”到“可用”的两次关键转向
这一部分保留本周最核心的试错过程,避免文档只剩结果、看不出迭代路径。
1)提示词策略试错:从强约束模板到证据密度优先
早期为了防止跑偏,我给提示词加了较强格式约束(固定段落、固定句式、严格模板)。
实际运行后发现副作用明显:
- 模型把注意力放在“格式合规”而不是“证据充分”;
- 虽然输出整齐,但数据引用不足,分析深度偏浅;
- 经常出现“结论有了,证据不够扎实”的情况。
后来改为“证据密度优先”策略:
- 放松文风与句式限制,减少模板绑死;
- 强化关键判断必须附带可核验数据(日期、来源、字段、数值);
- 允许明确写出不确定性和数据缺口,而不是强行给确定结论。
这次转向直接促成了当前的 data-first 报告形态,也让 ReAct 的价值真正体现出来。
2)节点间传递试错:从碎片 JSON 到连续 report
早期我尝试把 analyst 输出拆成较细 JSON 字段传给下游,初衷是程序友好。
但在 LLM 下游消费时,出现了几个问题:
- 字段齐全但语义被切碎,下游难以恢复完整上下文;
- 下游更容易“补字段”而不是做真正推理;
- 角色间字段风格不一致时,跨节点理解会偏移。
现在改为“report 主传递 + 必要结构化补充”后:
- 下游读取的是可连续推理语义单元,稳定性更高;
- 证据与结论在同一文本上下文中,语义损耗更小;
research_debate、trader、risk_review的输入口径更统一,调试成本显著下降。
这部分经验也是当前文档保留“试错过程”的核心价值:不仅说明做了什么,更说明为什么要这么做。
八、总结
目前 analyst 子图已经从“能跑通”推进到“可控、可追溯、可被下游稳定消费”的阶段:在编排层通过最小轮次、重试提醒和最大轮次上限建立了取证质量护栏;在数据层通过 route_to_vendor(...) 的优先选择与回退链降低了单一数据源抖动带来的失败风险;在报告层通过 data-first 结构把工具证据与分析结论绑定输出,减少了“结论先行、证据不足”的问题。整体上,这轮改动把分析质量从“依赖模型自觉”转为“由流程保障底线”,也让主流程后续节点(研究辩论、交易、风控)对 analyst 产物的利用率明显提升。
但目前分析师节点输出的四个报告仍然有一丝缺陷,将在下一篇报告中完全完善并且展示。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)