news 2026/10/2 5:21:37

多智能体辩论驱动的A股投研AI:从对抗到可解释裁决

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
多智能体辩论驱动的A股投研AI:从对抗到可解释裁决

这个项目本质上干了一件事:把A股个股分析从“问AI要一个结论”改成了“让AI做一场多空辩论,再出裁决报告”。这套系统跑起来之后,身边几个做投研的朋友都跑来问我要思路,原因很简单——市面上能直接生成“看多/看空/中性”结论的AI工具不少,但几乎没有能解释清楚这个结论到底是怎么推出来的。而这个系统会把每次判断拆成一份完整的辩论记录,多空双方的论据、引用、反驳过程全部可见,谁看了都能顺着逻辑再查一遍。

为什么说它有价值?因为A股的分析场景天然适合辩论。一只股票背后永远存在两种叙事,有人看到增长,有人看到风险,传统AI的毛病是两头都想要、两头都说不透。给AI装上一个“必须互相对抗”的辩论机制,反而逼着它把每一面都说到极致,最后再由第三方做裁决。这个过程本质上不是让AI更聪明,而是让它的结论更有可追溯性,适合任何一个需要做研究对象复盘的投资者、分析师或AI开发者参考。

1. 为什么A股需要“会辩论”的AI

1.1 传统AI分析股票的死穴在哪

先说个大模型直接分析个股时会犯的通病:立场骑墙。你问一个没有角色的模型“XX股票能不能买”,它会非常礼貌地给出三面结论——正面有亮点,负面有风险,最后建议你谨慎决策,等于什么都没说。这不是模型不聪明,而是任务目标本身没有约束。更麻烦的是,大模型存在很强的顺杆爬倾向,如果你的提问方式里带有乐观倾向,它输出的结论也会莫名乐观;如果换成悲观问法,结论又会变保守。这在单次基本面研究里不是致命伤,但放到投资决策链条里就是明显的不可靠信号。

A股还有一层特殊性:市场对信息的反应路径非常复杂。财报数字是硬约束,但真正的股价驱动往往来自预期差、资金流向和情绪面。传统AI直接把新闻标题丢进模型里,很容易被短期噪音带偏;而如果将多方和空方分开建模,再强制双方围绕同一份数据反复交锋,就不容易被某一类叙事带节奏。更直白地说,没有对抗机制的单模型输出,本质上是模型在替你脑补逻辑,而不是在验证逻辑。

1.2 辩论机制到底解决什么问题

我参考了学术界multi-agent debate的做法,把它从论文场景搬到了A股投研场景。多轮辩论的本质是让两个目标函数不同的Agent互相攻击,迫使每一方都必须回到事实层面来证明自己、推翻对方。这个机制带来的直接效果有四个。

第一,立场约束。多方只能从成长性、盈利质量、行业空间等角度构建论点,空方只能从估值偏高、现金流恶化、竞争加剧等角度寻找破绽,谁也不能骑墙。第二,证据压力。在一次有效辩论里,空方不会接受“公司很好”这种空话,它会追问“净利润同比增长32%的数据出自哪份财报,是否剔除了非经常性损益”,多方必须给出具体来源才能站住脚。

第三,暴露盲区。绝大多数模型对“坏消息”不敏感,因为训练语料里乐观表述占比更高。引入空方角色后,系统会被强制挖掘利空因素,把商誉减值、股东减持、应收账款激增这类问题全部摆上台面。第四,可解释性。裁判最终给出的不是一句抽象结论,而是一份带引用、带论证链条的裁决书,拿着这份报告去做二次研究,比对着大模型的一个分数靠谱得多。

2. 整体架构与关键技术选型

2.1 从单模型到多智能体协作

整个系统可以拆成四个角色,分别是多方Agent、空方Agent、裁判Agent,以及一个负责拉取和检索数据的Context模块。多方和空方共享同一个知识库,但检索与推理方向被刻意隔开,目的就是避免双方带着同样的预设去翻资料。

角色核心任务关键输出
多方Agent从成长、盈利、趋势角度构建看多论证论点列表、证据引用、置信度
空方Agent从估值、风险、现金流角度构建看空论证反论点、风险清单、证据引用
裁判Agent综合双方辩论内容,输出裁决结论方向判断、置信度、完整证据摘要
Context模块检索财报、公告、行情、研报切片结构化上下文片段、引用ID

这样的结构意味着,单纯调用一个大模型的提示词工程只占一半,另一半是数据如何在不同角色之间流动。我一开始犯过一个错误:让多方和空方直接共享所有检索结果,结果两边引用完全相同的段落,辩论变成了复读机。后来把检索结果按“成长类指标”和“风险类指标”先做粗分,再分别投喂给两方,才真正形成信息差。

2.2 技术栈与部署方案

用的技术栈其实不花哨,关键在于每个环节各司其职。基础框架是Python 3.11,服务层用FastAPI对外提供HTTP接口,工作流引擎用了LangGraph的思路管理Agent状态,底层缓存用Redis。向量检索这块,我试过Chroma和Milvus,小规模验证阶段用Chroma就够了,因为数据量不大,Milvus更适合生产环境的数据规模。

模型层我没有押注单一模型,而是根据角色任务灵活调用。多方、空方建议用推理能力够用的国产开源模型,裁判角色则用参数更大、指令遵循能力更强的模型,因为裁决需要对双方论据做横向比较,不是简单地打一个分。整个系统部署在一台带8GB显存的消费级显卡上就能跑,一次完整辩论大约耗时20到50秒,成本消耗取决于调用的模型单价,实测平均每次辩论的token消耗在8千到1.5万之间。

2.3 为什么选“辩论”而不是“投票”或“聚合”

构建这套系统之前,我认真考虑过另外两种方案:多模型投票结果聚合,以及多模型各自打分后取加权平均。这两者都有一个共同问题:独立决策之间没有交互,模型A说看多,模型B说看空,系统只能机械地数票,无法解释为什么会出现分歧,也无法判断哪个模型的理由更站得住脚。

方案输出质量可解释性成本适用场景
单模型直接输出低,容易骑墙弱最低快速信息摘要
多模型投票聚合中,能消除随机误差弱中惯例判断
多Agent辩论高,强制对抗与证据校验强高深度投研辅助

辩论方案把一个模糊的“判断问题”转化成了“论证问题”,这是它最大的优势。裁判Agent不是在两个结论之间选边,而是在两份论证过程之间做比较,看谁的证据链更完整、谁的反驳更有效。这种输出来自对抗过程,所以它天然比单模型输出的可复核性高一个量级。

3. 核心功能拆解与实现细节

3.1 多空双方的角色设定与提示词设计

角色提示词是整个系统最重要的部分,直接决定辩论质量。我给多方设定的系统提示词里会明确写:你必须以成长型基本面分析师的视角出发,专注于发现目标公司的增长潜力和竞争优势,禁止表达模棱两可的观点,必须引用财报、公告、宏观数据中的具体数字支撑论点。

下面是一份可直接参考的多方提示词模板:

你是A股基本面研究中的多方分析师,专注于识别上市公司被低估的证据。 你的任务: 1. 从营收增速、净利润质量、现金流结构、行业空间等维度构建看多论证; 2. 每个论点必须包含至少一个来自上下文中的具体数字或事实; 3. 在回复对手方时,指出对方逻辑中的漏洞或数据取舍问题; 4. 严禁使用“需谨慎”“注意风险”等骑墙表述。 输出格式(严格遵守): { "stance": "bullish", "points": [ { "claim": "核心观点", "evidence": ["证据原文片段"], "source": "财报/公告/新闻/研报", "confidence": 0.0-1.0 } ] }

空方提示词遵循同样的结构,但视角完全相反,要求它优先关注估值泡沫、营收质量下滑、股东减持、现金流恶化、行业竞争加剧等风险因素。裁判提示词则要求它先忽略双方阵营,只根据证据质量给出裁决。

这里有几个实操心得可以分享。第一,必须强制结构化输出,最好用JSON格式,否则辩论到第二轮你会面对一大段无法解析的散文。第二,每轮输出要限制token上限,比如每个观点不超过100字,否则模型会写小作文,既浪费时间又难以提取核心信息。第三,让双方记住自己“只能赢”,可以大幅提升对抗强度。

3.2 数据层:怎么让AI“看懂”A股

没有干净的数据,辩论就是空中楼阁。我从数据源上分了四层:财务报表数据、公告与研报、行情与资金数据、宏观与行业数据。财务报表主要抓营收、净利润、毛利率、经营性现金流、资产负债率等指标;公告和研报需要解析PDF与文本内容;行情数据包含历史价格、成交量和资金流向;行业数据用来辅助判断景气度。

处理流程上,我先把PDF财报解析成结构化表格,再转换成有利于向量检索的文本切片。这里最关键的坑是数值切片必须独立成段。如果像处理普通文章一样把一大段财报描述切成长文本块,嵌入向量时数值信息会被稀释,AI检索到的可能是“净利润同比增长”这个模糊概念,而不是具体的32.6%。所以我专门抽取财务指标表,把每个指标名称、数值、报告期组成一段独立文本再入库。

检索时,我会让Context模块先按股票代码拉取最新财报和最近三个月的公告,再按“成长类关键词”和“风险类关键词”分别检索,最后拼接成两份差异化上下文。分化后的数据一个是偏正面的素材包,一个是偏负面的素材包,多空双方拿到的原始素材不完全相同,辩论才有真正的信息差。

3.3 辩论流程引擎与裁决机制

辩论流程用状态机来管理,状态依次是:等待多方首论、等待空方反驳、等待多方回应、判断是否收敛、进入裁决。我实测下来,三轮交锋是质量与成本的平衡点。两轮辩论往往不够充分,很多冲突点刚展开就被截断;四轮以上边际收益很差,且容易出现双方开始重复观点的情况。

每一轮辩论记录都会存入上下文,并带上一个回合编号,方便裁判定位。裁决模块会从四个维度给分:事实性,即引用内容是否真实存在且与上下文一致;逻辑强度,即推导链条是否完整;相关性,即论点是否直指投资决策核心;风险覆盖,即空方是否系统性地识别了主要利空因素。

最终的评审规则是综合分超过60且事实性得分不低于70,才允许输出看多或看空判断,否则一律降级为中性。这个规则救了我很多次,因为模型偶尔会引用出错误数据,如果不能通过事实性校验,宁可输出没有观点,也不能输出错误观点。

3.4 与用户的交互方式

交互层我做了两套入口。第一套是Web页面,用户输入股票代码或公司名称,点击就开始分析,页面会实时展示辩论进展,像看直播一样看到多方发言、空方反驳,最后生成一份裁决报告。第二套是开放API,对接外部系统,一次POST请求传入股票代码,返回结构化的辩论结果。

裁决报告的结构分为五块:核心结论、辩论时间线、事实证据链、风险提示、争议焦点。核心结论是一句话判断,辩论时间线是双方交锋的完整记录,事实证据链是报告引用的所有来源列表,风险提示是空方识别出的主要风险,争议焦点则是裁判认为双方分歧最深的关键问题。整体输出是可读性很强的Markdown文档,方便二次转发或导入其他分析工具。

4. 实操过程:从0到1搭建一个A股辩论AI

4.1 数据准备与特征工程

写代码之前先花时间把数据清理干净。我以“某白酒龙头企业”作为测试标的说一说流程。先调用公开财经数据接口抓取最近五个报告期的财务摘要,包括营业收入、净利润、扣非净利润、经营现金流、销售毛利率、应收账款周转天数等核心指标,同时抓取近一个月的公司公告标题和摘要。

以下是一段简化版的取数代码,用akshare这类开源财经数据接口实现:

import akshare as ak def fetch_financials(symbol: str): # 获取主要财务指标(实际字段名可能随接口版本变化) df = ak.stock_financial_abstract(symbol=symbol) latest = df.iloc[-1] return { "revenue_yoy": latest.get("营业收入同比增长率"), "net_profit_yoy": latest.get("净利润同比增长率"), "gross_margin": latest.get("销售毛利率"), "ocf": latest.get("经营活动现金流量净额"), "roe": latest.get("净资产收益率"), }

特征工程这一步不需要做得太复杂,关键是产出可供Agent引用的结构化指标。我会在每条数据后面加上报告期标签,比如“2024年三季报”,这样AI在辩论时能精确说出“根据2024年三季报数据,净利润同比增速为15.2%”,而不是含糊地说“最近业绩不错”。

4.2 模型选型与调用

模型选型上我遵循“角色分级”原则。多方和空方Agent使用推理能力中等、成本较低的模型,因为它们只需要基于给定素材构建论点;裁判Agent则使用更强的模型,因为它要做归因分析和横向比较。实测下来,同一个模型家族内,裁判用大一号的参数版本,最终裁决的稳定性会明显提升。

调用层面的关键是缓存和重试。多空辩论是一次高延迟操作,模型接口偶尔会超时,所以每次调用都必须设置合理的超时时间和指数退避重试。同时,我用Redis缓存最热门标的的辩论结果,缓存时间为两小时,避免同一只股票被反复分析导致资源浪费。

4.3 辩论循环的实现

核心的实现逻辑可以简化成一段伪代码,用异步方式编排多轮辩论:

async def run_debate(symbol: str, rounds: int = 3): # 1. 拉取并切分数据上下文 bull_data, bear_data = retrieve_context(symbol) # 2. 多方首论 debate = [] bull_open = await bull_agent.declare(bull_data) debate.append(bull_open) # 3. 多轮交锋 for turn in range(rounds): bear_reply = await bear_agent.rebuttal(debate, bear_data) bull_reply = await bull_agent.respond(bear_reply, bull_data) debate.append(bear_reply) debate.append(bull_reply) # 4. 如果双方论点不再新增,提前收敛 if not has_new_argument(debate[-2], debate[-1]): break # 5. 裁判裁决 verdict = await judge_agent.decide(debate) return {"debate": debate, "verdict": verdict}

这段代码看起来简单,实际的坑在Agent状态管理。每个Agent内部必须保留自己的历史发言记录,避免在回应对方时把自己前面的论点忘记了。另外,生成回应的prompt里要把“你上一轮的发言”和“对方最新的发言”一起拼接,否则第二轮开始就会出现各说各话的情况。

4.4 结果输出与可视化

辩论结束后,我会把结论渲染成一份带编号的报告。报告正文包含五部分,其中“争议焦点”部分最有用,因为它是裁判从双方辩论中提取出的核心分歧点,比如“市场争议的焦点在于高端产品提价能力是否可持续,多方认为提价空间仍在,空方认为增速已近天花板”。这种聚焦信息比单纯看多空结论更能引发深入思考。

可视化方面,每一轮辩论可以用时间线展示,论点按发言顺序排列,证据引用则用高亮链接指向具体数据来源。系统还会生成一个雷达图,从事实性、逻辑强度、相关性、风险覆盖度四个维度画给读者看,让人一眼看出这次判断是靠硬核数据支撑还是靠逻辑演绎支撑。

5. 常见问题与排查技巧实录

5.1 模型幻觉与事实性校验

实际运行中遇到最多的就是模型幻觉。有一次空方Agent在辩论里言之凿凿地说“该企业2023年营收同比下降18%”,但我核对上下文里的财报数字,发现根本没有这个数,完全是从训练语料里编出来的。这类错误对投研场景是致命的。

解决的思路分三层。第一层是做引用ID强制对齐,要求Agent在输出每个论点时,必须附带引用来源的片段ID,如果这个ID在上下文中不存在,直接判定该论点无效。第二层是后处理数值校验,用规则把所有与财务指标相关的数字提取出来,跟结构化数据逐项比对,不一致的自动打上存疑标签。第三层是建一个证据命中率指标,统计每一轮辩论中被校验通过的论据占比,用这个指标持续评估系统质量。

5.2 辩论论点同质化

第二个困扰是两边的论点越来越像,尤其是在多轮辩论后期,空方会引述多方提到的“营收增速”来反驳,多方又会围绕同一指标辩解,最后变成对同一个数字的口水战。原因是双方共享了太多基准数值,自然会在同一指标上纠缠。

我后来加入了指标分组机制,不让他们完全共享同一个数据池:多方优先引用成长性相关的指标,比如营收增速、行业渗透率、在建产能;空方优先引用风险相关的指标,比如商誉占比、应收账款周转天数、质押比例。只有到最终裁决阶段,裁判才会获取全部上下文。这个改动让多空双方真正形成了差异化论证。

5.3 实时性与成本之间的平衡

辩论机制的实时性天然偏慢,因为一次完整分析可能要调用七八次大模型,再加上检索耗时,很难做到秒级响应。为了照顾体验,我做了两个优化:一是高频标的预计算,把热度最高的几十只股票在开盘前就提前跑完,用户访问时直接读缓存;二是轻量模型初筛,对明显缺乏数据支撑的提问直接返回提示,不进入完整辩论流程。

成本方面,一次完整辩论在8千到1.5万token区间,如果全部使用商用大模型接口,每天跑几百个标的也是一笔不小的开销。所以我用开源模型部署了多方和空方Agent,只在裁判环节调用更贵的商用模型,实测总成本能压缩一半以上。核心思路很朴素:能用小模型完成的高频动作绝不上大模型,大模型只留给最关键的一次判断。

5.4 合规与风险控制

必须把风控放在所有设计前面。系统产出的所有报告都会在顶部强制标注“内容由AI生成,仅供研究参考,不构成任何投资建议”,同时屏蔽所有涉及具体投资建议的指令,例如“快买”“清仓”这类词语会被后处理过滤掉。个股预测类表达也被限制,系统只输出“看多/看空/中性”的概率语义描述,不输出目标价或精准收益预测。

数据来源我也做了合规审查,只使用公开可获取的财报、公告和新闻,不抓取任何付费数据源的泄露内容。这套系统定位是投研辅助工具,不是荐股软件,所以在架构上就尽量不设置任何可能被解读为“荐股”的功能。保持边界清晰,能省掉很多后续麻烦。

我个人在实际操作中的体会是,决定这套系统上限的不是模型智商,而是数据加工和角色约束。所谓“会辩论的AI”,底层逻辑其实很朴素:让双方都极端一点,再让裁判理性一点。如果你也想搭一套类似的东西,建议先别急着接复杂的行情接口,就选一只你熟悉的股票,把财报数据整理成结构化文本,两个Agent加一个裁判,半天就能跑通第一版。等你觉得辩论的效果真的能帮你看清一个标的了,再去堆数据源和优化成本也不迟。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 5:20:32

Spark 3.2.0 预编译版实战:从解压到 YARN 集群提交

简介:spark-3.2.0-bin-hadoop3.2.tgz 是 Apache Spark 3.2.0 面向 Hadoop 3.2 环境编译的官方二进制发行包,适合大数据开发工程师、数据科学家及高校学生快速搭建分布式计算与机器学习实验环境。压缩包共 1476 个文件,约 287.02MB&#xff0c…

作者头像 李华
网站建设 2026/10/2 5:19:26

img2threejs实战:用AI将图片生成Three.js 3D代码

1. 一张图变3D模型,这个项目到底在解决什么问题第一次看到 img2threejs 这个项目的时候,我正被一个需求折磨得够呛——客户丢过来十几张产品白底图,要求一周内出一套可以在网页里旋转、缩放、拆解的 3D 展示方案。传统路子无非两条&#xff1…

作者头像 李华
网站建设 2026/10/2 5:19:22

随机森林工程落地:从可复现训练到SHAP可解释性

简介:本资源是一套面向机器学习初学者与数据科学实践者的随机森林模型全栈学习包,聚焦分类与回归任务建模,助力掌握集成学习核心算法原理与工程实现。压缩包共66个文件,涵盖14个C源码(含RF核心算法实现)、1…

作者头像 李华
网站建设 2026/10/2 5:19:22

Nacos服务注册失败排查:客户端、网络、服务端全链路指南

1. 从一次真实的服务注册失败说起凌晨一点半,本地起了一个新的微服务,控制台日志刷过去几屏,服务列表里就是看不到它的身影。日志末尾只留下一句轻飘飘的nacos registry, DEFAULT_GROUP xxx register failed,没有堆栈,…

作者头像 李华
网站建设 2026/10/2 5:18:57

探地雷达图像数据处理实战:从A-scan到B-scan的全流程

简介:一份探地雷达图像数据处理领域的学术研究文献,面向地质探测、考古、土木工程检测等方向的技术人员与研究者,聚焦解决雷达图像信噪比低、目标识别受噪声干扰的问题。内容系统梳理了探地雷达单道数据构成模型,针对直达波、地表…

作者头像 李华