前言
传统研报分析师的一天:在东方财富翻财报、在 Excel 算比率、在 Word 里敲字,最后发现数据还弄错了。用 ChatGPT 帮忙?三座大山挡住去路:
- 数据幻觉:AI 会编造一个看起来完美的”同比增长 12%”
- 上下文限制:几年的财报塞进去,AI 很快就”断片”
- 逻辑碎片化:无法自主完成”找对手 -> 算指标 -> 出结论”的长链路
解决方案:流水线思维。把任务拆成一条流水线,每个工位只负责一件事。本文基于 LangGraph 构建一个 6 节点的研报自动化工作流。
一、工作流
| 序号 | 节点 | 功能 | 包含子任务 |
|---|---|---|---|
| 1 | collect_market_data | 市场数据采集 | 深度搜索行业信息、提取竞品、下载财报 |
| 2 | calculate_financials | 财务指标计算 | 计算毛利率、ROE 等核心指标 |
| 3 | analyze_and_visualize | 分析与可视化 | 趋势分析、对比分析、生成 ECharts 图表 |
| 4 | collect_company_profile | 公司概况采集 | 主营业务、股东结构、基本信息(并行) |
| 5 | consolidate_analysis | 整合分析 | 估值模型、汇总所有数据 |
| 6 | generate_report | 生成报告 | 递归生成深度研报 HTML |
二、核心实现
2.1 AkShare 桥接:跨语言数据采集
JS 生态缺少像 AkShare 这样成熟的金融数据库增么办呢?答案是构建 Python 桥梁,让 Node.js 通过 child_process 调用 Python 脚本。
TypeScript 端封装静态类:
1 | // akshare.ts |
Python 端接收参数,调用 AkShare,返回 JSON:
1 | # akshare_bridge.py |
2.2 状态定义
Agent 的”记忆”用 LangGraph 的 Annotation 定义:
1 | // types.ts |
2.3 节点 1:市场数据采集
这是流水线的”情报员”,一次性完成三件事:深度搜索行业信息、结构化提取竞品、采集财务报表。
Prompt 1 - 深度搜索行业信息 (get_competitor_and_industry_data_prompt):
1 | 请分析以下公司的竞争对手以及所处行业: |
Prompt 2 - 结构化提取竞品 (get_competitor_info_prompt):
1 | 请从以下内容中,将竞争对手公司信息提取出来。 |
核心代码:
1 | export async function collectMarketData(state: typeof OverallState.State) { |
输出示例:
1 | competitor_info: { |
2.4 节点 2:财务指标计算
不要让 LLM 算数!预定义 11 个计算工具,让 Agent 自主调用。
System Prompt (analyze_system_prompt):
1 | 你是一名财务分析师,你的任务是根据用户传入的财务指标和三大会计表数据,完成如下的数据获取与计算任务。 |
User Prompt (analyze_user_prompt):
1 | 以下是{company_name} {year}年度的财务指标与三大会计表数据: |
核心代码:
1 | const agent = createReactAgent({ |
输出示例:
1 | { |
生成文件: data/financial_caculates/600519_2024年度财务计算结果.csv
2.5 节点 3:分析与可视化
一个节点完成趋势分析、对比分析、ECharts 图表生成。
趋势分析 User Prompt (analyze_financial_data_user_prompt):
1 | 以下是{company_name} 公司的过去三年财务数据: |
对比分析 User Prompt (compare_company_report_user_prompt):
1 | 以下是基准公司:{source_name} 公司的过去三年财务数据: |
System Prompt - ECharts 图表生成 (analyze_financial_data_system_prompt_web):
1 | 你是一名资深财务分析师,能够根据用户需求生成数据分析和 ECharts 可视化代码。 |
两个动作的使用时机:
LLM 在分析过程中通过动作进行”状态切换”,形成一个简单的循环:
1 | 开始 → generate_chart → generate_chart → ... → analysis_complete → 结束 |
generate_chart:每次生成一个图表,图表会被保存到this.charts数组中,可多次调用analysis_complete:终止信号,输出最终报告后结束循环
举个例子:分析贵州茅台时,LLM 可能会:
generate_chart→ 生成”营收趋势折线图”(保存到 charts 数组)generate_chart→ 生成”利润结构饼图”(保存到 charts 数组)analysis_complete→ 输出完整分析报告,循环结束
核心代码:
1 | export async function analyzeAndVisualize(state: typeof OverallState.State) { |
输出示例:
1 | 生成文件: |
2.6 节点 4:公司概况采集
三个子任务并行执行,提升效率。
主营业务 Prompt (get_business_info_prompt):
1 | 请获取以下公司的主营业务与核心竞争力: |
公司基本信息 Prompt (collect_stock_info_prompt):
1 | 你是一个专业的股票信息整理师,请根据以下公司信息,整理其基本介绍信息: |
核心代码:
1 | export async function collectCompanyProfile(state: typeof OverallState.State) { |
输出示例:
1 | 生成文件: |
2.7 节点 5&6:整合与生成
整合所有数据,然后递归生成深度研报。
估值模型 Prompt (buildValuationModelPrompt 动态生成):
1 | 你是一名金融分析师,请根据以下{company_name} 公司的信息,构建估值与预测模型, |
大纲生成 Prompt (outline_prompt):
1 | 你是一位顶级金融分析师和研报撰写专家。请基于以下背景和财务研报汇总内容, |
章节生成 Prompt (generate_section_prompt):
1 | 你是一位顶级金融分析师和研报撰写专家。请基于以下内容,直接输出"{part_title}"这一部分的完整研报内容。 |
核心代码:
1 | // 节点5:整合分析 |
输出示例:
1 | 节点5 - 整合分析: |
四、运行效果


五、总结
这套系统的核心是”结构化计算 + AI 推理”:前半段用 Python 桥接 AkShare 采集数据并计算指标,后半段让 LLM 生成分析报告和 ECharts 可视化。通过 LangGraph 串成 6 个节点,每个节点只做一件事。
未来可以往两个方向走:一是接入更多数据源(如新闻舆情、研报库),让 AI 分析更全面;二是加入实时监控和定时任务,把单次生成改造成持续跟踪系统。技术上可以尝试用 Agent 自主决策采集哪些数据、生成哪些图表,而不是写死流程。