在一个由 9 个 AI Agent 组成的研究团队里,行业分析师是最容易被误会的角色。它看起来只需要读资料、写行业综述,实际搭建之后才会发现,这个角色的价值不在于描述一个行业有多大,而在于回答一个更克制的问题:这个行业的宏大叙事,是否真的能作为我们进入这个行业的理由。这个判断如果做不好,后面的公司分析、财务建模、风险复核都会建立在一个虚浮的地基上。
这个“AI 九人研究团队”系列,目标是搭出一套能完成研究闭环的多智能体系统。前面几篇完成了总体架构、任务路由和第一批角色定义,这一篇把“行业分析师”单独抽出来做细。行业分析师处在宏观研究之后、公司分析之前,负责把宏观趋势翻译成产业机会,再把产业机会拆解成可验证、可反驳、可追踪的研究结论。
本文将围绕这个角色完成四件事:定义职责边界、设计系统提示词与任务流程、用最小可运行代码跑通一个行业分析师 Agent、以及实现最关键的一项机制——让 Agent 学会隔离“行业宏大叙事”与“入场理由”。
1. 先给行业分析师 Agent 定好边界:它的核心问题不是“行业好不好”
1.1 行业分析师在 9 人团队中的位置
9 人研究团队的划分方式可以根据项目不同做调整,但有一个相对稳定的角色骨架:项目管理 Agent 负责任务分发,宏观分析师处理经济环境,行业分析师判断产业机会,公司分析师筛选具体标的,财务分析师搭建财务模型,风险分析师识别下行风险,反方 Agent 负责挑战结论,数据工程师负责数据获取,资深分析师负责最终合并与质量控制。
行业分析师处于整条链路的中间位置。它接收上游宏观分析输出的经济环境、利率预期、技术周期变化,也要接收下游公司分析对特定公司的疑问,然后返回一套行业层面的判断。它并不是一个独立写报告的岗位,而是一个信号转换器:把宏观信号转换成行业机会,把行业机会转换成后续角色可以继续验证的问题。
它的职责边界要足够窄。行业分析师不负责给出具体的买入或投资决策,也不负责公司估值。它只负责回答三个问题:这个行业当前处于什么阶段,行业需求是否真实,以及在什么条件下值得进入。超出这三个范围的内容,应该由团队里的其他角色接走。
1.2 “宏大叙事”是输入信号,不是输出结论
行业研究里最常出现的表述是这样的:行业空间接近万亿,复合增长率超过 20%,是未来十年的确定性方向,政策持续加码,技术拐点已经到来。这类表述并不是没有价值,它告诉我们这个行业值得花时间研究。但如果研究中只有这类表述,那它只能算宏大的叙事,不能作为入场的理由。
问题出在逻辑跳跃。市场规模大,不代表产业里每个参与者都能赚钱;增速高,不代表当下时点能切入;政策鼓励,不代表商业模式已经成立;趋势不可逆,不代表你的资源配置能等到趋势兑现。行业分析师容易被这类叙事吸引,还因为大模型本身就有生成叙事的倾向。训练语料里有大量增长故事,模型接触到的“行业分析”文本多数在讲前景、讲趋势、讲想象空间,缺少对数据的交叉验证和反面讨论。如果系统提示词不加以约束,Agent 输出的第一版大概率是一篇漂亮的行业前景展望。
所以启动研究流程之前,就要明确:宏大叙事是研究输入,不是研究结论。Agent 必须在输出的每个关键判断旁边标注证据类型,把“数据”“推断”“叙事”“观点”分开放,不能拿叙事冒充事实。更具体地说,行业分析师输出的最终结论,必须是一张包含结论分级和入场条件的决策前置表。
1.3 这个角色要输出的是一张决策前置表
下面这个表格定义了行业分析师的输入输出边界,适合直接写进提示词或任务说明中:
| 本角色负责 | 本角色不负责 |
|---|---|
| 判断行业当前所处阶段 | 给出具体交易或买入决策 |
| 判断行业需求是否真实、可验证 | 用市场规模数字替代逻辑论证 |
| 拆解宏大叙事并标记证据等级 | 汇总行业全部新闻与事件 |
| 输出结论分级和入场触发条件 | 代替公司分析师筛选个股 |
| 为下游角色提供证据清单 | 代替财务分析师搭建财务模型 |
这个边界要先定下来,否则 Agent 很容易越界。实际开发中常见的情况是,行业分析师输出里混入了大量公司层面的判断,比如“某公司具备较强的产品力”,这种内容应当交给公司分析师,而不是由行业分析师输出。边界一旦模糊,后续多智能体协作就会出现职责重叠和结论冲突。
2. 搭建前先做角色拆解:人设、研究流程、输出规范、验收标准
2.1 角色人设的系统提示词
搭建行业分析师 Agent,第一件事不是写代码,而是定义系统提示词。系统提示词是在每次调用大模型时固定发送的角色指令。它会决定 Agent 的立场、工作原则和输出风格。
设计原则是:提示词要短,规则要硬,边界要明确。不要写几百字的人物背景故事,那样只会增加模型的随机性。真正重要的是几条硬性约束。
下面是一个可以直接使用的最小系统提示词示例:
INDUSTRY_ANALYST_PROMPT = """ 你是研究团队中的「行业分析师」。 你的职责不是给行业写综述,而是回答一个问题: 这个行业当前是否值得进入,以及在什么条件下值得进入。 工作原则: 1. 区分事实、推断和叙事。 - 事实:有来源、有时间的数字和事件。 - 推断:基于事实推出的趋势。 - 叙事:口号、类比、行业故事。 2. 推断必须给出逻辑链,叙事必须单独列出,不能用来证明结论。 3. 对每一个看多逻辑,至少生成三个反向问题。 4. 如果证据不足,直接输出“证据不足”,不要用篇幅掩盖。 5. 最终结论必须落到 A/B/C/D 四级,禁止使用“前景广阔”这类模糊表达。 输出格式: 严格按照 JSON 输出,包含字段:industry、conclusion_level、 conclusion、entry_conditions、key_facts、narratives、 opposing_questions、confidence。 """这段提示词的关键点有三个。第一,用“你是什么角色+你要回答什么问题”开头,让模型明确任务。第二,用“工作原则”给出硬性约束,其中把证据分级写进规则。第三,指定输出字段,强迫模型以结构化方式返回结果,而不是自由写作。
2.2 研究任务结构
系统提示词解决的是“这个角色怎么思考”,任务结构解决的是“每次研究具体做什么”。在进行任何大模型调用之前,先定义研究任务的输入格式。推荐使用 JSON 结构:
{ "industry": "智能家居行业示范样例", "research_scope": "家庭安防与能源管理两个细分方向", "research_window": "未来 12 个月", "research_question": "当前是否具备进入该行业的窗口", "input_materials": [ "材料1:某机构发布的智能家居行业白皮书摘要", "材料2:最近三个季度的智能家居设备出货量统计" ], "priority": "high" }字段含义如下:
| 字段 | 作用 | 说明 |
|---|---|---|
| industry | 研究对象 | 明确到行业,必要时带上细分领域 |
| research_scope | 研究边界 | 防止 Agent 把范围扩大到无关方向 |
| research_window | 研究时间窗口 | 行业结论必须带时间属性 |
| research_question | 本次要回答的问题 | 不同项目可以有不同的核心问题 |
| input_materials | 输入材料清单 | 如果为空,必须提示证据不足 |
| priority | 任务优先级 | 供调度 Agent 使用 |
任务结构要先定,是因为大模型在自由状态下会倾向于扩大范围。一旦研究范围不明确,行业分析师可能会把智能家居安防研究写成整个物联网行业的宏观报告,导致后续无法使用。
2.3 六步研究流程
行业分析师 Agent 不能只靠一次大模型调用完成全部工作,建议拆成六个步骤。每一步都有明确产物,这样方便检查质量问题,也方便定位出错环节。
第一步,问题生成。根据任务结构中的 research_question,将核心问题拆成子问题,比如需求真实性、竞争结构、进入壁垒、政策影响、技术成熟度、替代风险。
第二步,材料收集。根据子问题,将输入材料按主题归入对应问题,或者调用检索工具搜索外部信息。这一步的产物是一个“材料与问题对应表”。
第三步,证据标注。将材料中的关键语句提取出来,逐条标记证据类型、来源、时间、置信度。这一步是防止宏大叙事夹带的关键。
第四步,交叉验证。检查是否存在互相矛盾的数据,检查数据口径是否一致,检查结论是否有多个独立来源支持。
第五步,反向复核。对每一个看多逻辑提出至少一个反向问题,必要时单独调用一次“反方审查”提示词。这一步是为了避免模型被单方向叙事拉扯。
第六步,结论分级。根据以上信息,输出 A/B/C/D 结论分级和入场条件清单。
流程设计的核心思路是:每一步都把模型的一次自由生成拆解成一个有边界的子任务。拆得越细,越容易控制质量。
2.4 输出规范与验收清单
流程执行完毕后,Agent 需要输出结构化的 JSON 结果。必须包含以下字段:
| 输出字段 | 含义 | 质量要求 |
|---|---|---|
| industry | 行业名称 | 与任务输入一致 |
| conclusion_level | 结论分级 | 只能是 A/B/C/D |
| conclusion | 核心结论 | 一句话说清,不能含糊 |
| entry_conditions | 入场条件清单 | 每条必须可验证 |
| key_facts | 关键事实 | 必须含来源、时间、证据类型 |
| narratives | 识别出的宏大叙事 | 单独列出,不与事实混用 |
| opposing_questions | 反向问题 | 每个看多逻辑至少一个 |
| confidence | 总体置信度 | high/medium/low/unverified |
验收清单可以设计成下面这样,每次任务结束后逐项检查:
- 结论分级是否为 A/B/C/D 之一,且与正文一致。
- 关键事实是否包含来源和时间,是否标注了证据类型。
- 是否输出了至少 3 个反向问题。
- 是否将宏大叙事单独提取到 narratives 字段。
- 是否存在缺少证据但仍给出强结论的关键判断。
- 输出是否可以直接被下一个角色解析,而不是需要人工重新整理。
提示:在验收清单里增加一项“是否存在不可验证的绝对化表达”,例如“必然”“一定”“毫无风险”。这类表达出现时,应将对应结论降级。
3. 用最小可运行案例跑通一个行业分析师 Agent
3.1 环境准备与依赖
为了快速验证角色设计,可以用 Python 脚本搭建一个最小可运行案例。需要准备 Python 3.10 或更高版本,安装两个依赖即可:
pip install openai python-dotenv这里以 OpenAI 兼容的 Chat Completions 接口为例,因为大量大模型服务都支持该协议。在项目目录下创建.env文件,写入访问配置:
LLM_API_KEY=你的密钥 LLM_BASE_URL=https://你的服务地址 LLM_MODEL=你的模型名称如果是学习环境,可以直接使用支持 OpenAI 协议的服务;如果是生产环境,建议统一通过网关或者代理服务接入,避免把密钥散落在业务代码里。加载配置:
import os from dotenv import load_dotenv load_dotenv() MODEL_NAME = os.getenv("LLM_MODEL", "your-model") client = OpenAI( api_key=os.getenv("LLM_API_KEY", "your-key"), base_url=os.getenv("LLM_BASE_URL", "https://api.example.com"), )实际项目中请根据自己使用的模型和服务地址替换这些配置。不要照抄这里的示例地址。
3.2 定义数据模型
先把研究过程中需要用到的基础结构定义出来。使用标准库的 dataclass 就可以,不需要为了演示引入太重型的依赖。
from dataclasses import dataclass, field @dataclass class Evidence: statement: str evidence_type: str # data / inference / narrative / opinion source: str time: str confidence: str # high / medium / low / unverified @dataclass class OpposingQuestion: logic: str # 被反问的原始逻辑 question: str # 反向问题 severity: str # mild / moderate / severe @dataclass class IndustryConclusion: industry: str conclusion_level: str # A / B / C / D conclusion: str entry_conditions: list[str] key_facts: list[Evidence] narratives: list[str] opposing_questions: list[OpposingQuestion] confidence: str这些数据结构的价值在于,强制 Agent 的输出是可验证的。如果conclusion_level被设置成 A,那么entry_conditions里就必须有可验证的条件;如果key_facts为空,那么confidence就不允许是 high。这类约束可以在后续处理代码中继续校验。
3.3 实现行业分析师 Agent 类
接着实现核心的 Agent 类。这里给出一个骨架实现,重点展示流程调用而不是堆砌复杂代码。
import json from openai import OpenAI class IndustryAnalystAgent: def __init__(self, llm_client: OpenAI, model: str): self.llm = llm_client self.model = model def _ask_llm(self, system_prompt: str, user_prompt: str) -> str: response = self.llm.chat.completions.create( model=self.model, messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": user_prompt}, ], temperature=0.2, ) return response.choices[0].message.content def _build_sub_questions(self, task: dict) -> list[str]: prompt = ( "根据以下行业研究任务,输出 6 个需要研究的子问题。\n" f"任务:{json.dumps(task, ensure_ascii=False)}\n" "输出 JSON 数组,例如:[\"需求真实性\", \"竞争结构\"]" ) content = self._ask_llm(INDUSTRY_ANALYST_PROMPT, prompt) return json.loads(content) def _collect_evidence(self, task: dict, sub_questions: list[str]) -> str: # 真实项目中这里会接入检索、爬虫或知识库。 # 最小演示直接基于 task 中的 input_materials 处理。 return json.dumps(task.get("input_materials", []), ensure_ascii=False) def _draft_analysis(self, task: dict, materials: str) -> dict: prompt = f""" 请基于以下材料完成行业分析。 研究任务: {json.dumps(task, ensure_ascii=False)} 已有材料: {materials} 要求: - 关键结论必须标注证据类型。 - 识别并单独列出宏大叙事。 - 对每个看多逻辑提出反向问题。 - 输出符合 INDUSTRY_ANALYST_PROMPT 中定义的 JSON 结构。 """ content = self._ask_llm(INDUSTRY_ANALYST_PROMPT, prompt) return self._parse_json(content) def _parse_json(self, content: str) -> dict: # 如果接口支持 response_format,优先使用 JSON mode。 # 这里保留一个简单的容错处理。 try: return json.loads(content) except json.JSONDecodeError: start = content.find("{") end = content.rfind("}") + 1 return json.loads(content[start:end]) def research(self, task: dict) -> dict: sub_questions = self._build_sub_questions(task) materials = self._collect_evidence(task, sub_questions) result = self._draft_analysis(task, materials) result["sub_questions"] = sub_questions return result关键点有三个。第一,temperature设置为 0.2,降低随机性,保证行业研究这类事实型任务输出稳定。第二,_ask_llm是统一调用入口,之后想接入日志、监控、重试机制都在这一个位置扩展。第三,research方法按照“拆问题、找材料、写分析”的顺序执行,这与人工研究员的路径一致。
3.4 运行一个演示任务
编写入口函数,跑一个演示任务。下面用“智能家居行业”作为示例,所有数字都是示意数据,仅为展示输出结构。
def main(): task = { "industry": "智能家居行业(演示样例)", "research_scope": "家庭安防与能源管理", "research_window": "未来 12 个月", "research_question": "当前是否具备进入该行业的窗口", "input_materials": [ "材料1:某白皮书显示行业出货量连续两年增长(示意数据)", "材料2:市场仍有多种通信协议并存,互操作问题未解决" ], "priority": "high", } agent = IndustryAnalystAgent(llm_client=client, model=MODEL_NAME) result = agent.research(task) print(json.dumps(result, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()运行成功后,输出会是一个 JSON 结构,形式上类似下面这样:
{ "industry": "智能家居行业(演示样例)", "conclusion_level": "B", "conclusion": "行业需求在增长,但当前缺少可验证的触发信号,建议等待关键指标改善后再进入", "entry_conditions": [ "头部设备连接标准出现收敛趋势", "用户复购率出现可量化的提升", "安装服务成本下降到可接受范围" ], "key_facts": [ { "statement": "智能家居设备出货量连续两年增长(示意数据)", "evidence_type": "data", "source": "材料1", "time": "最近两年", "confidence": "medium" }, { "statement": "通信协议并存,互操作问题未解决", "evidence_type": "fact", "source": "材料2", "time": "研究窗口内", "confidence": "high" } ], "narratives": [ "万物互联是必然趋势" ], "opposing_questions": [ "如果主要增长来自低端设备,用户渗透率提升是否还能代表需求真实改善?", "协议并存问题是否会让早期用户产生更换顾虑,进而限制规模的进一步扩展?", "如果安装服务成本短期无法下降,这个行业是否只能停留在小众人群?" ], "confidence": "medium" }注意,这只是演示结构,不是真实行业结论。真正运行时要替换成自己的材料和真实数据。输出中把“万物互联是必然趋势”放进了 narratives 字段,而不是作为支持结论的事实,这正是设计要达成的效果。
4. 关键机制:让 Agent 不被宏大叙事绑架
4.1 把事实、推断、叙事和观点分开
前面已经提到证据类型,这里展开讲清楚。行业研究报告的质量差异,很大程度上取决于是否区分这四种信息:
| 证据类型 | 含义 | 示例 | 能否直接支持结论 |
|---|---|---|---|
| data | 有来源、有时间、有数字的事实 | 某地区出货量环比增长 5% | 可以 |
| inference | 基于事实的推断 | 出货量增长说明需求在改善 | 可以,但需要逻辑链 |
| narrative | 行业故事、类比、口号 | 万物互联是必然趋势 | 不可以 |
| opinion | 专家或报告作者的观点 | 某机构认为行业将加速洗牌 | 参考,需标注立场 |
在系统提示词里要明确要求:所有支持结论的内容,至少要是“data”或者带完整逻辑链的“inference”。如果一段分析全部由 narrative 组成,应该直接判定为证据不足。
实际测试中,大模型经常会把“某行业报告显示市场规模超过万亿”当作事实使用,但如果没有来源、时间、统计口径,这句话其实已经退化成叙事。要解决问题,不能在提示词里写一句“请提供准确数据”就算了,而是要在结构化输出中让模型填写source和time,无法填写时就只能降低置信度。
4.2 强制反向研究
防止宏大叙事绑架结论的最有效手段,是强制生成反向问题。一个看多逻辑如果没有经历反向质疑,它就不是研究结论,只是观点。
可以在每次分析完成后,额外调用一次反向审查。单独设计一个提示词,效果比在主提示词里加一句“请考虑风险”好得多。原因在于,一次对话中模型已经输出了看多逻辑,再次要求它自我否定时,它往往会温和地修正,而不是真正推翻。
REVERSE_REVIEW_PROMPT = """ 你是行业分析的反方审查者。 下面是行业分析师给出的一系列看多逻辑: {analysis} 请逐条提出反向问题。要求: 1. 每条逻辑至少一个反向问题。 2. 问题必须具体,不能是“存在风险”这种空话。 3. 可以从假设被证伪、数据口径改变、竞争加剧、 技术路线变化、下游需求不及预期等角度出发。 4. 输出 JSON 数组,每个元素包含 logic、question、severity。 """然后,将返回的反向问题合并进最终的 JSON 输出。如果某个看多逻辑对应的反向问题数量不足,质量检查环节应当直接扣分。
4.3 结论分级和入场条件检查清单
结论分级是这个角色的核心出口。分级设计越简单,越容易执行。建议使用四级制:
| 等级 | 含义 | 使用场景 |
|---|---|---|
| A | 当前具备入场条件 | 核心条件已验证,且有多来源支撑 |
| B | 等待触发信号 | 方向成立,但关键条件还不满足 |
| C | 暂不关注 | 叙事明显强于事实,或者行业进入下行期 |
| D | 证据不足 | 无法判断,需补充材料后再评估 |
等级为 B 时,必须在entry_conditions里写明具体触发信号,例如“头部厂商统一连接标准”“某个关键原材料价格下降到 X”。这样下游 Agent 可以持续跟踪。等级为 D 时,建议返回明确的“缺失证据清单”,而不是勉强选一个方向。
提示:“证据不足”不是失败结论,而是行业分析师最常用且最安全的合法结论。要允许 Agent 说不知道。
4.4 数据来源、时间窗口和置信度
行业研究经常犯一个错误:把过去的数据当作未来趋势的证据。因此每个关键事实都要带上时间。置信度可以分四级:high、medium、low、unverified。
如果输入材料里没有相关内容,模型必须输出“未在输入材料中找到”,而不是自行脑补。这一点需要在提示词中写成硬性规则。比如:“当材料中没有某个事实时,在对应字段填写'未找到',并将置信度设为 unverified,不得用常见知识补全。”
实际项目里,这条规则能显著减少行业分析师的幻觉输出。因为行业研究涉及大量市场规模、增速、渗透率等数字,如果没有强制“未找到”机制,模型非常容易生成看起来合理但实际不存在的统计数字。
5. 运行验证:怎么判断行业分析师 Agent 的输出合格
5.1 用三个行业案例做行为测试
Agent 搭建完成后,不要只用一个案例验证。建议准备三个差异明显的行业案例,观察输出是否具备区分度。
第一个案例,高叙事但缺验证的行业。例如某个正处于概念期的新兴行业,材料里只有市场规模预测和趋势描述,没有客户验证、订单数据和成本结构。合格输出应该是 D 或 B,并且narratives字段要能识别出那些未经证实的趋势口号。
第二个案例,周期性行业出现可验证信号。例如航运周期或工程机械周期,材料里有明确的运价指数、库存天数、新签订单数据。合格输出应该能判断当前处于周期什么位置,给出 B 或 A,并指出哪些数据是判断依据。
第三个案例,成熟行业巨头主导。例如某个已经高度集中的消费行业,材料显示头部份额持续提升,新进入者缺少差异化空间。合格输出应该是 C,除非模型能在细分市场里找到明确的空白点。
这三个案例分别对应“叙事多于事实”“事实可验证”“事实已经表明格局稳定”三种情况。如果一个 Agent 对三类案例都输出“前景广阔、值得关注”,说明它的结论分级机制没有生效。
5.2 输出质量评分卡
为了自动评估 Agent 输出,可以设计一张评分卡。每个维度 1 到 5 分,总分达到 90 分以上才允许进入下游环节。
| 维度 | 满分标准 | 扣分点 |
|---|---|---|
| 结论分级正确性 | A/B/C/D 与事实匹配 | 明显证据不足却给 A |
| 证据标注完整度 | 每条事实均有来源、时间、类型 | 存在无来源关键数字 |
| 叙事隔离程度 | narratives 字段完整、准确 | 将趋势口号当作事实使用 |
| 反向研究数量与质量 | 每个看多逻辑至少一个问题 | 反向问题是“注意风险”式空话 |
| 结构化可解析性 | 能被下游角色直接消费 | JSON 字段缺失或无法解析 |
| 语言克制度 | 结论使用条件句、限制词 | 频繁使用“必然”“一定” |
这个评分卡既是验收工具,也是调试工具。如果某一批任务质量偏低,可以先看扣分集中在哪个维度。比如永远在“叙事隔离程度”扣分,就说明提示词里对 narratives 的约束不够。
5.3 日志与中间过程追踪
多智能体系统最难排查的问题之一,是不知道哪一步产生了错误输出。行业分析师 Agent 内部建议做三件日志工作:记录每次大模型调用的耗时与 token 消耗,保存每个子问题的材料集合,给最终结论附上可追踪的中间结果。
以下是一段简易的日志实现思路:
import logging logging.basicConfig(level=logging.INFO) class IndustryAnalystAgent: def research(self, task: dict) -> dict: logging.info("开始行业分析任务: %s", task["industry"]) sub_questions = self._build_sub_questions(task) logging.info("子问题: %s", sub_questions) materials = self._collect_evidence(task, sub_questions) logging.info("材料数量: %d", len(materials)) result = self._draft_analysis(task, materials) logging.info("结论分级: %s", result.get("conclusion_level")) return result日志的作用不只是排查错误,还可以用来评估提示词修改是否有效。每次修改 prompt 后,跑同一批测试任务并对比输出质量,不要凭印象判断。
6. 行业分析师如何融入多智能体协作链路
6.1 它在工作流中的前后端接口
在 9 人研究团队中,行业分析师不是独立完成研究的孤岛。一条典型的工作流是:项目管理 Agent 解析研究需求,把任务分发给宏观分析师;宏观分析师输出经济与政策环境后,把任务转给行业分析师;行业分析师输出行业结论后,公司分析师开始筛选值得深入研究的公司;之后财务分析师、风险分析师、反方 Agent 依次介入;最终由资深分析师角色合并结论。
行业分析师与上下游之间的交互,建议全部使用 JSON 格式,而不是自然语言长段落。这样可以避免下游 Agent 解析文本时丢失信息。比如行业分析师输出给公司分析师的,应该是一个包含“行业关键变量、值得关注的公司名单、行业风险清单”的 JSON 对象。
6.2 给下游角色的“可消费”输出
不同下游角色关心不同类型的信息。行业分析师在输出时要考虑这些角色:
| 下游角色 | 需要的行业信息 | 建议输出字段 |
|---|---|---|
| 公司分析师 | 值得研究的公司范围、行业关键变量 | candidate_directions |
| 财务分析师 | 产业链结构、成本传导、毛利影响因素 | industry_cost_drivers |
| 风险分析师 | 不可证伪的假设、单一来源数据 | unverifiable_assumptions |
| 反方 Agent | 可反驳的看多逻辑 | opposing_questions |
| 项目管理 Agent | 任务状态、后续需要补充的材料 | missing_evidence |
不要把所有内容都塞进conclusion字段。字段越细,下游越容易处理。实际开发中,长文本结论会导致后续每个角色都要先做一次语义解析,不仅耗时,还容易产生歧义。
6.3 重跑、版本与缓存
行业结论具有时效性。三个月前成立的结论,三个月后可能已经失效。生产环境中,行业内 Agent 的任务需要支持三个能力:定期重跑、输入快照、版本对比。
定期重跑是指按照固定频率,或者在关键事件发生时重新执行研究流程。输入快照是指在每次研究启动时,保存输入材料列表和配置。版本对比是指在重跑完成后,把新旧结论的差异输出出来。比如:
{ "changed_fields": ["conclusion_level"], "old_level": "B", "new_level": "A", "change_reason": "关键原材料价格在最新一期数据中下降到触发区间" }这种对比能力对用户判断非常有用,也是行业分析师从“一次性报告生成器”升级为“持续跟踪研究系统”的关键一步。
7. 常见问题与排查路径
7.1 常见现象、原因和处理方式
行业分析师 Agent 在开发过程中会出现几类高频问题。下面用表格列出常见现象与排查建议:
| 问题现象 | 常见原因 | 检查方式 | 处理建议 |
|---|---|---|---|
| 输出像营销软文 | 提示词中缺少证据约束 | 检查 key_facts 是否有来源和时间 | 加入 evidence_type 硬性标注 |
| 结论永远偏向 A/B | 没有设置最低证据标准 | 查看结论分级分布 | 加入“无法验证则 D”规则 |
| 输出大量编造数据 | 模型不认识输入材料的边界 | 抽查某个数字能否在材料中找到 | 强制“未找到”机制 |
| 反向问题全是空话 | 反向提示词不够具体 | 检查 questioning 字段质量 | 要求给出数字或场景 |
| JSON 解析频繁失败 | 未使用 JSON mode,temperature 过高 | 查看响应原文 | 打开 response_format,调低温度 |
| 与下游角色无法衔接 | 输出字段设计不合用 | 观察下游 agent 抛错日志 | 重新设计输出 schema |
7.2 典型排查:输出全是宏大叙事
这是最常见的失败模式。现象是:Agent 输出很长,看起来结构完整,但key_facts大多是“行业空间巨大”“增长迅速”这类描述,缺少来源和时间。
排查顺序如下:
第一步,检查提示词。确认系统提示词中是否明确要求输出source和time。如果没有,先补上,同时要求没有来源的事实不得出现在 key_facts 中。
第二步,检查输入材料。如果输入材料本身就只有行业白皮书的摘要,没有具体数据,那么结论分级不应该是 A,更不应该是“值得重点关注”,而应该是 D,并返回“缺失证据清单”。
第三步,检查解析结果。将模型原始响应与最终解析输出做对比,确认是不是解析阶段把 narratives 字段丢掉了。实践中常见的情况是模型原本已经区分了叙事和事实,但程序解析时只保留了结论字段。
第四步,如果以上都没问题,再考虑升级约束。在提示词中增加一条:当关键事实没有来源时,在对应字段填写“未找到”,并将置信度设置为 unverified。这通常会立刻减少编造情况。
7.3 约束不要靠堆提示词,要靠结构
新手常犯的错误是,看到模型输出宏大叙事,就不断往提示词里加约束词。加了“注意不要用模糊词汇”,又加“必须使用来源”,再加“不要编造数据”。提示词越来越长,问题却没有彻底解决。
原因是,模型对一条 800 字的提示词和一条 1500 字的提示词,遵循程度并不会成比例提升。提示词过长反而会让模型将重点放在最后几条指令上,忽略中间规则。
更有效的方式是引入结构性约束。把输出从“自然语言报告”改成“JSON 字段表”,模型被迫在字段层面填写来源、时间、证据类型,不能通过模糊措辞逃避。把“结论分级”从可选项变成必选项,模型必须选择一个具体等级。把“反向问题”从软性要求变成独立流程,单独调用一次反方审查。
结构比措辞更稳定。在实际项目中,遇到质量问题时,优先增加流程步骤和输出字段,而不是继续堆砌提示词。
8. 生产环境落地建议和扩展方向
8.1 学习环境与生产环境的差别
本地脚本能跑通,距离生产环境可用还有相当距离。两者的差别主要集中在以下方面:
| 维度 | 学习环境 | 生产环境 |
|---|---|---|
| 材料输入 | 手工粘贴 | 知识库、数据库、资讯源自动接入 |
| 检索能力 | 无 | 网络检索、RAG、实体链接 |
| 模型输出 | 直接调用 | 通过网关统一管理密钥、限额、审计 |
| 质量保障 | 人工目测 | 评分卡自动拦截、人工抽检 |
| 结论版本 | 无记录 | 输入快照、输出版本、变更对比 |
| 任务调度 | 手动运行 | 定时触发、事件触发、队列调度 |
| 失败恢复 | 无 | 重试、降级、告警、人工复核 |
把上面表格逐行落实,才算真正从演示脚本走向可用系统。尤其是“人工复核”这条不能省:行业研究结论可能影响后续一系列动作,生产环境至少要保留“高级分析师角色”对 A 级结论进行复核的环节。
8.2 扩展方向
行业分析师 Agent 可以往几个方向扩展。
第一个方向是接入真实数据源。把新闻资讯、行业数据库、上市公司公告通过接口接入,让 Agent 不再依赖用户手工粘贴材料。这需要增加数据清洗和去重流程,因为行业信源大量重复。
第二个方向是增加检索工具。通过函数调用或者自定义工具,让 Agent 在“材料收集”阶段自动搜索外部信息。搜索结果的来源、标题、时间必须一起进入系统,而不是只把正文丢给模型。
第三个方向是建设行业知识图谱。将上下游关系、供应商、替代品、价格传导路径结构化存储。行业分析师在有知识图谱支撑后,可以完成更复杂的推演,例如“某种原料涨价会向行业哪个环节传导”。
第四个方向是引入多语言信源。真实行业研究往往需要阅读海外报告,跨语言信源的引入可以让 Agent 发现国内材料不常提到的信号,减少信息盲区。
8.3 给后续角色的复用思路
行业分析师这个角色的设计模式,可以直接复用到团队里的其他角色。最重要的是三件事:把角色边界写进系统提示词,把输出结构化成可解析的 JSON,把质量保障拆成独立检查流程。
后续搭建财务分析师时,可以把行业分析师提供的industry_cost_drivers字段作为财务模型的输入,同时沿用证据分级和结论分级机制。搭建风险分析师时,可以复用unverifiable_assumptions和opposing_questions,把它们作为风险清单的基础素材。搭建反方 Agent 时,它天然依赖行业分析师输出的narratives字段——那些被识别出的宏大叙事,正是最有价值的反驳靶子。
行业分析师是 9 人研究团队里非常基础但非常关键的节点。它负责把宏观趋势翻译成可被后续角色验证或反驳的行业判断,同时也是第一道拦截宏大叙事的闸门。搭建这个角色时,真正要做的不是让它更像一个分析师,而是让它学会区分两件事:行业是否值得研究,以及现在是否值得入场。前者靠流程,后者靠证据。只要把证据标注、反向研究、结论分级这三件事做实,这个 Agent 在团队里的价值就会立刻显现。后续搭建财务分析师或风险官时,可以继续沿用这套结构化方法,把同样严谨的研究纪律复制到整个团队。