☰
基于LangGraph与多Agent协作的PRD自动生成系统设计
2026/10/21 6:27:30 网站建设 项目流程

前一段时间,有个做产品经理的朋友跟我吐槽,整天要花大把时间写PRD,而且改来改去特别烦。当时我就琢磨,能不能做一个自动生成PRD的工具。市面上虽然有不少大模型套壳应用,但大多数就是单次对话,让模型直接输出一版PRD,痛点很明显:文档结构不稳定、逻辑不连贯、缺少多维度审查,只适合用来找灵感,离能落地的标准差得远。直到后来我把通义千问(Qwen)和LangGraph组合起来,做了一个多Agent协作的PRD自动生成系统,才算是把这个问题真正解决了。

这个项目的核心思路,就是让几个不同角色的Agent一起协作,来模拟一个完整产品团队的工作流。每个Agent负责一个环节,有的负责梳理业务背景,有的负责拆解功能需求,有的负责画信息架构,还有的负责评审挑毛病。通过LangGraph把这些Agent连接成有状态的工作流,让上下文在各个Agent之间有序传递,最终产出一份结构完整、逻辑自洽的PRD文档。

这篇文章会完整拆解整个系统的设计与实现过程,包括Agent的角色划分、LangGraph的图编排方案、提示词策略、结构化输出设计,以及我在实际开发中踩过的坑和解决方案。如果你是AI应用开发者、产品经理,或者正在研究多Agent协作方案,这篇文章的内容应该能帮你在自己的场景里复现这套架构。

1. 项目定位与整体设计思路

先把这个项目到底在解决什么问题说清楚。市面上的AI写作PRD工具,大多停留在"你输入需求,模型输出初稿"这种单轮对话模式。试过的人都有体会,第一次生成的内容通常会包含提纲挈领的部分,但细节层次非常单薄,往往缺少竞品分析、业务异常流、埋点规划这些产品经理真正在意的东西。

我当时定下的设计目标是:把PRD的生成过程改造成一条流水线,不同环节由不同的Agent专门负责,上一个Agent的输出作为下一个Agent的上下文输入。这样做的好处有三个:

第一是专业化分工。让一个模型同时扮演"需求分析师"和"交互设计师"的角色,往往两头都不讨好。如果把角色拆开,每个Agent只需要聚焦一个窄领域,模型的输出质量会明显提升。这和人类团队的分工逻辑是一致的。

第二是上下文的有序传递。PRD是一个长文档,如果一次性让模型生成,很容易写到后面忘了前面。多Agent流水线让每一段生成都有了明确的前置上下文,比如功能拆解Agent必须基于业务背景Agent输出的产品定位来写,就不会出现前后矛盾。

第三是可插拔的评审机制。在关键节点插入评审Agent,专门负责挑毛病,被挑出的问题会以结构化意见的形式反馈给生成节点,驱动修改。这个机制是单轮生成完全做不到的。

选择通义千问作为大模型底座,主要看中它两点:一是中文语义理解能力在同类模型中处于第一梯队,这直接关系到PRD中文表达的自然度;二是它对函数调用和结构化输出的支持很完整,方便我让Agent输出JSON来对接下游程序。而LangGraph负责的是编排层,它把各个Agent看成图上的节点,把Agent之间的信息传递看成边,整个协作过程是一个有状态、可中断、可恢复的图流转,这比简单的Chain链式调用要灵活得多,也比较容易追踪和调试。

LangGraph的另一个特性是内置了记忆持久化。PRD生成过程中,业务背景、功能清单、评审意见这些中间状态都需要被保存,LangGraph的State机制天然支持这种需求,每个节点都可以读写共享状态。这样整个系统就不再是"无状态地调API",而是一个有记忆的协作系统。

2. 多Agent协作架构拆解

一个好的多Agent系统,设计Agent角色时不能拍脑袋,得先想清楚PRD生成到底需要哪些能力。我复盘了整个PRD写作流程,最终确定了五个角色:策划Agent、分析Agent、架构Agent、填充Agent和评审Agent。

2.1 五个Agent的角色定位与职责边界

策划Agent负责业务背景分析。它接收用户的原始输入,比如一句话产品想法、目标用户描述、业务限制条件,然后输出产品定位、目标用户画像和核心价值主张。这个Agent的输出质量非常关键,因为后面所有环节都建立在这个既定方向上。

分析Agent负责竞品分析和差异化。这里我会让它基于策划Agent输出的产品定位,去输出竞品格局、核心竞品功能对比、以及这个产品可能的差异化切入点。它输出的内容不一定非常翔实,重点是让后续的功能设计有参照系。

架构Agent负责信息架构和功能模块拆解。它会输出产品的功能模块列表、每个模块下面的核心功能点,以及模块之间的依赖关系。这是一个承上启下的环节,相当于把PRD的骨架搭出来。

填充Agent负责具体的PRD条目撰写。根据架构Agent输出的功能清单,逐个功能写出完整的需求描述,包括功能说明、业务规则、交互细节、异常处理。因为功能点比较多,这个节点会循环执行多次,每次处理一个功能模块。

评审Agent负责质量评审。它会在关键节点介入,按照我预设的PRD质量标准,检查前面几个Agent的输出是否有遗漏、逻辑漏洞、需求模糊等问题,然后输出结构化评审意见,送回到对应节点进行修正。

这里要特别说一下Agent不是越多越好。我最初设计过七个Agent,多了一个"数据模型Agent",专门设计数据库表结构,但跑了几轮之后发现这一块对普通PRD来说有点过度设计了,只有纯后台系统类的产品才需要。后来我把这个Agent从主流程里摘除,改为按需加入的旁路节点,整体效率和结果质量都合理了。

2.2 LangGraph中的图编排方案

LangGraph的核心是"有状态图"。在代码层面,我需要定义一个状态对象,它贯穿整个图执行周期。状态对象的数据结构是典型的字典类型,包含了原始需求、产品定位、竞品分析、架构拆解、PRD正文、评审意见这些元素。

图本身的流转逻辑是这样的:

  • 用户输入进入策划Agent节点,产出产品定位,写入状态
  • 状态流转到分析Agent节点,产出竞品分析,写入状态
  • 再流转到架构Agent节点,产出功能模块清单,写入状态
  • 进入填充Agent节点前,需要做一个条件判断,决定是继续填写下一个功能模块,还是所有模块填写完毕
  • 填充完成后进入评审Agent节点,如果评审通过则直接结束,不通过则根据评审意见回到对应节点进行修正

这段逻辑用文字描述比较抽象,我用LangGraph代码来展示核心的图结构定义。实际开发中,图的构建和使用并不复杂,关键是把逻辑分支理清。以LangGraph的经典写法,代码大致是这样的:

from langgraph.graph import StateGraph, END # 定义状态对象结构 class PRDState(TypedDict): user_input: str # 用户原始输入 product_position: str # 产品定位 competitor_analysis: str # 竞品分析 module_structure: str # 功能模块结构 prd_sections: list # 已生成的PRD段落列表 review_result: str # 评审结果 revision_round: int # 迭代轮次 # 构建状态图 graph = StateGraph(PRDState) # 添加节点 graph.add_node("planner", planner_agent) graph.add_node("analyst", analyst_agent) graph.add_node("architect", architect_agent) graph.add_node("writer", writer_agent) graph.add_node("reviewer", reviewer_agent) # 添加边:主线流程 graph.add_edge("planner", "analyst") graph.add_edge("analyst", "architect") graph.add_edge("architect", "writer") graph.add_edge("writer", "reviewer") # 条件路由:评审通过则结束,否则根据意见返回 graph.add_conditional_edges( "reviewer", should_revise, { "revise_planner": "planner", "revise_architect": "architect", "revise_writer": "writer", "end": END } ) graph.set_entry_point("planner") app = graph.compile()

这里的should_revise是一个路由函数,它读取review_result字段中的评审意见,判断本次需要返工的角色,返回对应的key,LangGraph会根据这个key自动流转到适当节点。这种状态机式的编排方式,让整个流程表现得非常可控,也方便每轮人工介入。

2.3 为什么用LangGraph而不是其他编排方式

我团队之前也尝试过用简单的LangChain Sequential Chain来实现这种协作,效果并不理想。原因在于Sequential Chain本质上是一条直线的调用序列,很难表达条件分支和循环回流,评审不通过要回炉这种需求,需要在代码层级做很多额外的hack。如果是直接用裸代码编排,本质上是写一堆if-else调用大模型,代码会层层嵌套,维护成本极高。

LangGraph把这些编排逻辑提升为图结构,节点之间是显式声明的边,条件分支用路由函数来表达。图中任何一个节点都可以访问共享状态,这意味着任何Agent都能看到前面所有Agent产出的内容。这种设计还有一个隐性的好处,就是当图运行到某一步卡住时,我可以非常直观地定位到是哪个节点的问题,调试体验比看一堆链条日志要愉快很多。

3. 通义千问模型选型与提示词策略

3.1 模型选型的具体考量

通义千问目前提供了多个尺寸和定位不同的模型。我在这套系统里主用qwen-plus作为生成模型,原因有几个方面要展开说一下。

第一是上下文窗口长度。一个PRD文档动辄上万字,加上前面各环节的中间输出,整张状态对象的内容会对上下文占用有要求。qwen-plus的上下文窗口足够容纳这轮协作过程中的完整信息,这点在实际测试中表现稳定。

第二是结构化输出的稳定性。我的Agent需要输出JSON格式的数据,方便程序解析。之前试过一些开源模型,让它们输出JSON很容易在生成中插入多余文字,导致解析失败。qwen系列模型在系统提示里明确指定JSON输出时,生成结果通常会保持JSON规范格式,这对要跑自动化流程的场景来说很重要。

第三是工具调用能力。LangGraph节点在实现时,会有参数解析的需求,Agent需要按照预定义的工具格式生成结构化调用请求。qwen系列对工具调用的支持属于成熟梯队,返回的格式错误率比较低。

如果你想要完全本地化部署,也可以考虑用qwen系列开源模型,比如通过量化和推理框架部署在单卡上。对于数据敏感的内部使用场景,这是一个合理选项,但模型的推理速度和输出质量会弱于云端API版本,我建议在实际适用前做一轮针对PRD语料的质量评测。

3.2 各Agent的提示词模板设计细节

提示词是所有Agent行为的核心。我的提示词设计原则是:给角色、给流程、给输出格式、给质量标准,而不是只给一个笼统的任务描述。

拿架构Agent的提示词举个例子。它的系统提示语大致是这样组织的:

你是一名资深产品架构师,负责把产品定位和竞品分析转化为清晰的功能模块结构。 你输出的模块结构将直接作为后续PRD详细编写的依据。 请遵循以下要求: 1. 划分功能模块时,遵循MECE原则,模块之间避免重叠 2. 每个模块用一句话说明核心职责 3. 每个功能点需要标注优先级(P0必须/P1建议/P2可选) 4. 功能描述必须完整,包含主流程、分支流程和异常流说明 输出格式为JSON,字段结构如下: { "modules": [ { "module_name": "模块名称", "module_desc": "模块职责描述", "features": [ { "feature_name": "功能名称", "feature_desc": "功能描述", "priority": "P0" } ] } ] }

注意这里有一个很关键的细节:每个Agent的提示词里都会明确写上你输出的内容会被哪个下游角色使用,以及使用方式来指导生成重点。这种"上下游感知"能显著提升输出对最终目标的适配度。填充Agent的系统提示词里甚至嵌入了评审Agent的评分标准,让它在写需求时就知道哪些点会被检查,这也让你的整体流程多了一层内建质量约束。

3.3 结构化输出的设计与解析方案

PRD生成过程中需要频繁地和JSON打交道。为了让解析环节更省心,我做了三件事。

第一是统一输出协议。我在所有Agent提示词的输出格式部分约定了一套基础字段规范:内容项文本、数据属性、修改标记、确定性等级。改动标记用来标注这个条目是新增内容还是修正内容;确定性等级用来标记模型对这条内容的把握程度,方便后期人工复核。

第二是解析容错方案。尽管qwen的JSON输出很规范,但在实际运行中偶尔还是会出现JSON被截断的情况。我的方案是在解析层做多层兜底,第一层用严格的JSON解析器和schema校验;如果解析失败,就用正则提取代码块中的内容,再二次尝试解析;如果还是失败,就把这个节点的输出标记为格式异常,走人工修订流程,而不是让整个图崩溃。

第三是Schema校验。解析出的JSON会立即用预定义好的数据Schema做结构校验。这里我用了Pydantic模型来定义每个环节的输出结构。校验不通过同样会把问题返回给对应节点,让它重新生成。这个机制极大程度上减少了结构化数据项内容的无效传输和后续处理时的类型错误。

4. 实操过程与核心实现

4.1 环境准备与依赖安装

开发这套系统时,我建议在一个干净的虚拟环境里操作。项目依赖相对简单,主要包括几个Python库:LangGraph作为编排框架,通义千问的Python SDK用于模型调用,以及用于结构化输出的Pydantic和相关工具库。

依赖安装指令大致如下:

pip install langgraph qwen-api-sdk pydantic python-dotenv

环境变量这里要单独设置一个API密钥,我在项目根目录创建一个.env文件,写入密钥配置信息。这里有个经验,不要在代码里硬编码密钥,因为一旦代码分享出去或者推到远端仓库,密钥就暴露了,实际项目里出过这种事,教训比较深刻。

4.2 搭建基础模型调用层

模型调用层封装了所有通义千问的通信逻辑。核心是两个函数,一个负责普通文本对话补全,一个负责结构化输出解析。

基础调用函数的实现思路是先读取模型名称、温度和最大Token数这几个核心参数,然后调用API接口,获取返回文本。结构化输出函数则是在普通调用基础上额外指定了系统提示中输出JSON格式的要求,并加上了我在前面说的多层解析兜底。这个抽象层让后面每个Agent的实现变得干净,Agent节点不需要关心底层的API差异。

这里分享我当时调试中对温度参数的踩坑过程。最初我让填充Agent用默认温度值,结果生成的PRD文本非常发散,每轮跑出来的写法差异很大。后来经过多次调整,我把大部分生成节点的温度调低到一个比较保守的档位,而把评审Agent的温度维持在稍高一些,让它能更有想象力地发现问题,修改Agent的温度也调到较低档位,避免大幅改写原有的语义表达。效果对比下来,确实稳定了不少。温度参数的调优,不是一个死参数,而要根据Agent职责属性来定。

4.3 构建状态对象的节点函数

每个Agent在LangGraph里其实就是接收当前状态、返回更新状态的一个纯函数。我用填充Agent的实现来说明这种节点的写法,因为它的逻辑涵盖了格式化组装、调用模型、解析结果的全过程。

填充Agent的简化代码结构大致是这样的:

def writer_agent(state: PRDState): # 获取当前待处理的功能模块 remaining_modules = state["module_structure"]["modules"] current_module = remaining_modules[state["current_module_index"]] # 组装提示词:包含业务背景、竞品分析、当前模块结构 prompt = build_writer_prompt( state["product_position"], state["competitor_analysis"], current_module ) # 调用qwen模型,获取该模块的PRD正文 response = call_qwen_structured( system_prompt=prompt["system"], user_prompt=prompt["user"], schema=FeaturePRDSchema ) # 更新状态:添加新生成的PRD段落,推进模块索引 return { "prd_sections": state["prd_sections"] + [response], "current_module_index": state["current_module_index"] + 1 }

这段代码的核心思路是:每个Agent节点做的事情是从状态拿输入、组装提示词、调用模型、解析结果、更新状态。并且因为它是一个纯函数,方便你单独把每个Agent拉出来做单元测试,大大降低了调试复杂度。

4.4 实现多轮修正流程

多轮修正机制是系统的一个核心特色。这个能力让PRD生成过程具备了"自我迭代"的属性,也是跟单轮Prompt生成拉开差距的地方。

评审Agent的职责按照四个维度来验收PRD:业务完整性、功能逻辑自洽性、异常流覆盖度、表达明确性。它输出一个结构化评审结果,大体字段包括:整体结论,做过的验证项,发现的关键问题清单,每个问题关联的功能模块,以及修改意见。这个结果会被路由函数读取,决定流向哪个Agent进行修正。

修正流程设计时,我加了一个最大迭代轮次限制,防止系统在极端情况陷入无限循环。我设置了评审通过条件:如果关键问题数量为零,或者连续两轮评审意见重复率过高,都会结束流程,避免不需要的重复调用。连续意见重复率检测这个细节,逻辑也比较简单,就是把上轮评审意见与当前轮做文本相似度对比,超过一定阈值就认为进入了循环。

4.5 主流程执行与运行监控

系统主流程的执行入口,我设计成接收两个参数:产品名称和原始需求描述。入口函数创建一个初始状态字典,然后调用编译好的LangGraph应用执行。

执行过程中,LangGraph提供了逐步日志回放的能力。我可以在开发模式下打开调试开关,实时看到每个节点的执行顺序、耗时和状态变化。对于生产环境,我把执行日志写入一个队列系统,方便后续分析每个Agent的调用占比和响应耗间,做性能优化时看数据会更有依据。

系统的可观测性不仅对开发者有意义,对产品验收也很有用。产品经理可以从执行日志里看到"哪个Agent在哪个环节做了哪些决策",这在评审PRD质量时,提供了决策依据层面的透明性。

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

多Agent系统的调试经验和单Agent应用很不一样,问题往往不是模型能力导致的,而是出在流程编排、状态管理和输出格式这些环节。我实际运行过程中积累了一些典型问题,可以整理成一份速查手册。

5.1 输出信息在Agent之间传递时丢失

这个问题在多轮修正流程中最常见。最初我把评审Agent的修改意见作为独立字段写入状态,传给被修正节点,但是被修正节点在重新生成时,并没有把上一版内容作为上下文带入,结果修改后输出反而丢失了原来正确的部分,整体内容甚至没有原来那么完整。

排查思路是检查状态对象中每个节点的输入依赖。修正节点重新运行时,不能只依赖评审意见,还需要把上一轮生成的内容原文作为一个信息源读取进来,让模型在原有基础上做增量修改。修复后,我在状态里保留了原始版本、修改意见和修改后版本三个字段,一方面保证模型有足够上下文,另一方面也方便做版本对比。

5.2 结构化输出频繁出现解析失败

Qwen模型在多数情况下能保持JSON输出格式规范,但在输出较长内容时,偶尔还是会出现截断,或者JSON的末尾被中断。最初遇到这种情况,整个流程会直接抛出解析异常,让多轮协作终止。

我的解决方案是双层容灾。第一层,在调用结构化输出函数时,把输出的Token上限留足余量。比如原本预计该条内容需要1000个token,我会把上限设置为更宽裕的数值,给模型足够的生成空间。第二层,在解析失败时启动修复流程,对返回文本做截断裁剪,补全缺失的括号,试图恢复成合法JSON,只有修复失败才请求重生成。这套方案让系统的异常率从最初某个较高比例下降到了极低的零散水平。

5.3 Agent之间上下文不一致

在早期版本中我发现,架构Agent输出的模块数量是六个,但是填充Agent最终只生成了四个模块的PRD,另外两个模块被静默跳过了。原因是填充Agent的循环退出条件没有对齐架构Agent的模块总数索引,这个属于典型的逻辑边界问题。

排查时我通过状态对象的可视化回放,立刻看到了循环退出的定位逻辑不准确。修复方式是在路由函数里增加一个显式判断:如果当前模块索引小于总模块数,说明还有未完成的功能模块,继续进入填充节点;否则才进入评审节点。看似简单的边界修正,背后涉及的是状态机Graph里数据结构在流转中的一致性维护,这个思路值得留意。

排查技巧:梳理跨Agent信息流时,先核对每个节点对下游节点做了何种假定,再检查这个假定在流程中是否被遵守,这类偏差在议程集成式Agent里尤为隐蔽。

5.4 生成文本的迭代质量异常

还有一种现象是,经过多轮修正之后,PRD的篇幅不增反降,内容越来越浓缩,重要的细节在修正过程中被裁剪掉了。这是因为修正节点面对大量上下文时,模型会出现"过度概括"的倾向。

我在修正节点的提示词中加了一条强制约束:指示模型仅修正评审意见里有问题的部分,未涉及到的内容必须逐字保留,不得删改。这个方法让多轮修正从"重写模式"切换到"精准补丁模式",内容完整性的保持效果好多了。如果你想复现这套系统,这个提示词细节值得直接引过去用。

6. 效果评估与实际使用建议

系统构建完成后,我对它的实际效果做了一轮对比测试。我用同一份原始需求,分别跑通了单轮直接生成和多Agent协作生成两种路径,对比结果差异很明显。

单轮直接生成的问题是结构基本完整,但内容深度不足。比如某个核心功能的业务规则,只写了一句话,谈不上异常流描述;竞品分析也只是泛泛的套话。这显然不够支撑开发排期用。

多Agent协作生成的版本,业务规则描述详细,包含了完整的主流程和异常流,评审Agent还真的挑出了一个逻辑矛盾:前端展示的某个状态在后台数据流中没有对应的处理逻辑。这种问题是单轮生成难捕捉到的,因为产生该问题的上下文分散在两个不同的Agent输出里,只有评审Agent站在全局视角才能发现。

结合这套项目经验,我总结了几条使用建议。如果只是想快速产出PRD初稿,单轮生成足够;但如果你想产出接近人工编写质量、能直接拿给开发和测试阅读的PRD,多Agent协作方案的价值就会体现得很明显。实际使用时,不太建议直接全自动生成后不经过人工审核。最合理的流程是让系统自动产出完整草稿,然后产品经理把精力集中在评审意见和关键决策环节的人工确认上,生产效率会高不少。

这套架构的可迁移性也很强,换个提示词和状态字段,就可以把同样的流程迁移到其他岗位角色的文档生成场景,比如技术方案设计、运营活动策划、数据分析报告。多Agent协作本质上是把复杂任务拆解成多个专业视角的协作生产,在文档生成这个大类下,它的价值是有示范性的。我实际测试过程中,多次看到评审Agent能发现一些容易忽略的需求漏洞,这种全局质量兜底是这套架构给我留下最深印象的地方。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询