【山东大学项目实训FinAgent】进度报告:并行分析师、指标批量拉取与进度LRU扩容实现单股分析耗时优化
FinAgent 单股分析耗时优化:并行分析师、指标批量拉取与进度LRU扩容
摘要:本文基于单股分析时间慢的问题,分析耗时原因,并实现三类改动缩短单股分析时间:技术指标批量拉取同一截OHLCV、进程内LRU扩容与四分析师子图并行。
一、耗时因素分析
从任务进入到分析师阶段产出四份分析师报告(market_report等)为止,耗时过长的决定因素包括:LLM 与工具的往返次数、行情/新闻等I/O、分析师分析过程是否串行叠加,以及云厂商或本机 Ollama 的限流与队列。
二、为什么“换更快模型”不够
本人从ollama将模型换成deepseek-v4,但是分析师阶段是典型的多专科 × 多轮 ReAct:模型bind_tools后反复推理 → 调工具 → 再看结果,总耗时更接近:
阶段数×工具往返×(网络延迟+LLM 延迟)
当工具轮次已经较多时,Flash/Pro这类单次提速对耗时优化的贡献就容易被忽略,因此本人尝试后感觉时间优化上效果不大。
因此工程上选择了三类不改变下游仍读四个字符串报告的优化方向:
- 减少重复行情拉取(同一轮工具调用里多指标合并);
- 将无相互依赖的四专科从串行改为并行(墙钟由四段相加变为近似最慢一段);
- 用细粒度进度字段 + 轮询签名改善体感,避免误判「无进展」而导致轮询越来越稀。
三、Market 侧:get_indicators批量路径与 LRU
3.1 Market 分析师会调哪些工具、慢在哪
技术面分析师阶段里,模型通常会用到两类与行情相关的工具:
get_stock_data:按日期区间拉日线OHLCV,给模型一段原始 K 线文本,用来写走势、支撑压力等叙述。get_indicators:在当前日期等时间或天数限制下,拉足够长的 OHLCV,在服务端算出RSI、MACD、布林带等技术指标,再格式化成Markdown还给模型。
耗时往往不在算MACD公式,而在反复访问AkShare/网络:每调用一次 fetch_stock_ohlcv都可能是一次真实拉数或至少一次缓存查找前的准备。如果一轮对话里模型要6~8个指标,而底层实现成每个指标各自拉一遍全量 OHLCV,就等于同一标的、同一段时间窗的数据被重复下载多遍,耗时就会增大。
本节针对的就是:减少无效重复拉网(批内合并)和提高命中进程内缓存的概率(LRU 容量);不改变算出来的指标含义和返回给模型的文本格式。
3.1 批量路径在干什么
改造前(逻辑上等价于):模型在一次思考里需要多个指标时,若底层多次走「单指标 get_indicators」,每次内部都会 fetch_stock_ohlcv 一次,再算一个指标、输出一段 Markdown;最后把多段用空行拼起来。
改造后:模型仍在一次工具调用里用**indicator="rsi,macd,boll,..."(英文逗号分隔)表达我要一串指标。工具层识别到逗号后,只路由一次get_indicators_batch→ AkShare 的get_indicators_akshare_batch,就是说整条链路只调用一次fetch_stock_ohlcv 拿到一块 OHLCV DataFrame,然后在内存里循环调用同一个格式化函数,生成多段Markdown,再用\n\n拼成最终字符串。
这样做的直接效果是:一次用户可见的工具往返里,网下行情次数从指标个数降为 1,返回内容和以前多次单指标再拼接也是对齐的。
_format_indicator_report_from_ohlcv 为什么要抽出来:单指标路径 get_indicators_akshare 与批量路径共用同一套从OHLCV 算指标→写 Markdown的实现。否则很容易出现线上批量路径修了 bug、单指标路径没修的错误或反之,维护成本高。
3.2 LRU
fetch_stock_ohlcv带了一个lru_cache,就是说同样的股票代码+起始日+结束日,第二次再来问,直接用内存里缓存的答案,不必再打一遍外部数据源。
缓存只能记有限条数。以前是32条,分析任务里如果出现多个标的、多个时间窗,很容易把旧条目挤掉;下一轮又问到同一窗口,就得重新拉网。改成128 条,同一进程里能多记一些组合,重复命中的概率高一些。
四、分析师子图:四专科并行
4.1 为何可以并行
Market、舆情、新闻、基本面四个角色 互不依赖对方的对话上下文。串行时,墙钟近似 四段耗时相加*;并行后近似取四段中的最大值(外加线程池调度开销)。下游辩论等阶段仍读取四个*_report 字符串,接口契约不变。
4.2 实现要点
实现集中在 backend/app/graph/analyst_subgraph.py,核心可概括为下表:
| 组件 | 作用 |
|---|---|
_compile_single_role_graph(role) |
单专科 ReAct:analyst → tools/retry,结束直达END;并行时不使用msg_clear(各子图轨迹隔离)。 |
analyst_parallel(内部 _parallel_analyst_node) |
对每个selected_analysts()分析师独立 invoke,共享初始化模板、state 互相独立。 |
| 合并 | 按配置顺序合并四个*_report、analyst_react_summaries;messages 前加分析师角色说明;工具轮次类字典update。 |
4.3 注意
- 云 API 限流或本机 Ollama 实质串行时,并行加速会打折扣。
- 同一任务 四路同时打模型,RPM、TPM、费用及本机显存压力都会上升。
- 文档层面预留
FINAGENT_ANALYST_PARALLEL=0一类开关回退串行。
五、其它配套改动(简述)
-
阶段进度 UI:只根据已结束阶段加权,避免假进度条(
analysisProgress.ts、SingleStockAnalysisPage.tsx与后端stage_log)。
-
DeepSeek:thinking 模式与
tool_calls易 400,默认关 thinking,环境变量可控(config.py、llm.py)。 -
Windows启动脚本:注意
FINAGENT_ENABLED_STAGES与goto分支不要互相跳过。
六、总结
FinAgent把分析慢拆成了三件事——技术面get_indicators多指标合并成一次拉 OHLCV(避免同一次调用里重复打网)、fetch_stock_ohlcv 的LRU扩容(同一进程里多标的多窗口更容易命中缓存)、以及四个分析师LangGraph子图并行(由四段相加变为近似最慢一段,仍受API/Ollama限流约束)。
最终实现了从十多分钟到五分钟左右的耗时优化!!
其他进度报告
【山东大学项目实训FinAgent】本周进度报告:AKshare 数据接入与测试
【山东大学项目实训FinAgent】 周报(2026-04-19):Dataflow分层设计与FastAPI路由协作实践
更多推荐



所有评论(0)