一、理论部分
1. 为什么写作任务更适合用“图(Graph)”而不是“线性链(Chain)”
传统的链式调用通常是单向的:Prompt → LLM → Output。它适合一次性生成类任务,但不擅长表达真实写作过程中的“循环改稿”:
- 先构思大纲(Planner)
- 再写初稿(Writer)
- 再审阅并提出修改意见(Critique)
- 如果不满意:回到写作节点继续修改,直到满意或达到修改上限
这种“写不好就重写”的结构本质上是一个循环(Loop)。LangGraph 的核心优势就是用图结构来描述可循环、可分支、可控终止的流程。
2. State(状态)是图编排的核心:把“过程记忆”显式化
在多轮节点执行中,系统必须持续携带关键上下文。LangGraph 通过 State 把这些数据显式建模并在节点间传递。
本项目使用的状态字段包括:
topic:写作主题plan:写作大纲draft:当前草稿critique:审阅意见revision_number:当前修改轮次max_revisions:最大修改轮次(用于防止死循环)
与“聊天记忆”不同,这里 State 更像是一个明确的“工作流上下文对象”,每个节点只读写自己负责的字段,流程更可控。
3. 三类节点(Nodes):Planner / Writer / Critique 的职责分离
为了让系统可维护,我们将写作过程拆成三个职责清晰的节点:
- Planner:根据主题生成写作大纲(结构与要点)
- Writer:根据大纲生成初稿;或根据批评意见修改草稿
- Critique:以“主编/审稿人”角色审阅草稿,指出问题与修改建议
这种职责分离的设计能有效减少 Prompt 混乱,便于后续加入更多节点(例如 Research 搜索、引用校验、风格统一等)。
4. 条件边(Conditional Edge):如何决定继续修改还是结束
图的关键不只是节点,还包括“边”的控制逻辑。本项目用一个should_continue函数作为条件路由:
若
revision_number >= max_revisions:强制结束(避免无限循环)
几乎所有“可自我迭代”的 Agent 都必须有这种上限保护。若 Critique 返回
PERFECT:提前结束(认为已经满意)
否则回到 Writer,进入下一轮“根据意见重写”。
二、实战部分
1. 项目目标
实现一个基于 LangGraph 的智能写作系统,具备:
- 自动生成大纲(Planner)
- 自动撰写初稿(Writer)
- 自动审阅并提出修改意见(Critique)
- 自动循环改稿(最多修改 N 次,或主编通过即停止)
2. 运行准备
请确保本地已安装依赖并配置环境变量(不要把真实密钥写进代码或公开仓库):
依赖安装(示例):
pipinstall-rrequirements.txt环境变量(示例):
DEEPSEEK_API_KEYDEEPSEEK_BASE_URL
说明:
- 本项目使用
langgraph构建图,使用langchain_openai.ChatOpenAI连接 DeepSeek(OpenAI 兼容接口)。 - 若希望更稳定输出,可以适当降低
temperature,或对 Planner/Writer/Critique 使用不同温度。
3. 项目代码(核心实现)
本项目代码集中在一个脚本中,包含:State 定义、三个节点函数、条件边逻辑、图构建与运行入口。下面给出完整核心代码(可直接运行):
importosfromtypingimportTypedDictfromdotenvimportload_dotenvfromlangchain_openaiimportChatOpenAIfromlangchain_core.messagesimportSystemMessage,HumanMessagefromlanggraph.graphimportStateGraph,END load_dotenv()classAgentState(TypedDict):topic:strplan:strdraft:strcritique:strrevision_number:intmax_revisions:intllm=ChatOpenAI(model="deepseek-chat",openai_api_key=os.getenv("DEEPSEEK_API_KEY"),openai_api_base="https://api.deepseek.com",temperature=0.7,)defplan_node(state:AgentState):print(f"--- [Planner] 正在为主题 '{state['topic']}' 生成大纲 ---")messages=[SystemMessage(content="你是一名专业的内容策略师。你的目标是为博客文章创建一个详细的大纲。"),HumanMessage(content=f"请为这个主题创建一个大纲:{state['topic']}"),]response=llm.invoke(messages)return{"plan":response.content}defwrite_node(state:AgentState):print(f"--- [Writer] 正在撰写草稿 (第{state['revision_number']+1}版) ---")ifstate["revision_number"]==0:content=f"根据这个大纲写一篇博客文章:\n\n{state['plan']}"else:content=(f"这是你之前的草稿:\n{state['draft']}\n\n"f"这是主编的修改意见:\n{state['critique']}\n\n""请根据意见修改并重写这篇文章。")messages=[SystemMessage(content="你是一名专业的技术作家。文风通俗易懂,逻辑严密。"),HumanMessage(content=content),]response=llm.invoke(messages)return{"draft":response.content,"revision_number":state["revision_number"]+1}defcritique_node(state:AgentState):print("--- [Critique] 正在审阅草稿 ---")messages=[SystemMessage(content="你是一名严格的主编。请指出文章中的逻辑漏洞、啰嗦的部分或缺失的信息。如果文章已经非常完美,只需回复 'PERFECT'。"),HumanMessage(content=f"请审阅这篇草稿:\n{state['draft']}"),]response=llm.invoke(messages)return{"critique":response.content}defshould_continue(state:AgentState):critique=state.get("critique","")ifstate["revision_number"]>=state["max_revisions"]:print("--- [System] 已达到最大修改次数,停止 ---")returnENDif"PERFECT"incritique.upper():print("--- [System] 主编已通过,停止 ---")returnENDprint("--- [System] 需要进一步修改 ---")return"writer"workflow=StateGraph(AgentState)workflow.add_node("planner",plan_node)workflow.add_node("writer",write_node)workflow.add_node("critique",critique_node)workflow.set_entry_point("planner")workflow.add_edge("planner","writer")workflow.add_edge("writer","critique")workflow.add_conditional_edges("critique",should_continue,{"writer":"writer",END:END,},)app=workflow.compile()if__name__=="__main__":print("="*50)print("🤖 AI 智能写作助手 (基于 LangGraph)")print("="*50)user_topic=input("请输入你要写作的主题 (直接回车使用默认主题): ").strip()ifnotuser_topic:user_topic="Agentic AI (智能体人工智能) 在 2025 年的发展趋势"print(f"⚠️ 未检测到输入,将使用默认主题:{user_topic}")initial_state={"topic":user_topic,"max_revisions":2,"revision_number":0,"plan":"","draft":"","critique":"",}print(f"\n🚀 开始策划与写作:{user_topic}...")final_state=app.invoke(initial_state)print("\n"+"="*50)print("✅ 最终完成的稿件:")print("="*50)print(final_state["draft"])print("="*50)4. 如何运行
在项目根目录执行:
python stage_04_enterprise_frameworks/project_06_research_agent/main.py启动后输入主题即可。如果直接回车,将使用默认主题并开始自动写作与迭代改稿。
5. 运行结果示例
运行过程的典型日志形态如下(内容会随模型生成有所变化):
================================================== 🤖 AI 智能写作助手 (基于 LangGraph) ================================================== 请输入你要写作的主题 (直接回车使用默认主题): ⚠️ 未检测到输入,将使用默认主题: Agentic AI (智能体人工智能) 在 2025 年的发展趋势 🚀 开始策划与写作: Agentic AI (智能体人工智能) 在 2025 年的发展趋势... --- [Planner] 正在为主题 'Agentic AI (智能体人工智能) 在 2025 年的发展趋势' 生成大纲 --- --- [Writer] 正在撰写草稿 (第 1 版) --- --- [Critique] 正在审阅草稿 --- --- [System] 需要进一步修改 --- --- [Writer] 正在撰写草稿 (第 2 版) --- --- [Critique] 正在审阅草稿 --- --- [System] 已达到最大修改次数,停止 --- ================================================== ✅ 最终完成的稿件: ================================================== (最终文章正文内容...) ==================================================6. 项目总结
- LangGraph 用图结构表达“循环改稿”的真实写作流程,比线性链更适配复杂可迭代任务。
- State 将过程上下文显式化,使各节点职责清晰、数据流可控,便于扩展更多能力节点。
- 通过条件边实现“满意即止 / 达上限即止”,是防止无限迭代的工程必需项。
- 该模式可自然扩展:增加 Research 节点做资料检索、增加 Human-in-the-loop 节点做人工审核、增加引用校验节点提升事实性。