基于 LangGraph 的领域智能体(Agent)架构实践与落地参考
模块一:认知重塑 —— 从“副驾驶”到“自动产线”
在构建系统之前,团队必须统一对大模型(LLM)的认知。
- 过去的认知 (Copilot 模式): 大模型是一个“超级字典”。我们输入文本,它补全文本。人类是驾驶员,AI 只是辅助。
- 现在的认知 (Agentic Workflow 模式): 大模型是系统的“中央处理器(CPU)”。我们不直接让它写最终答案,而是让它根据环境,去调用外部工具(API、数据库),并通过自我反思不断循环。系统是一条“自动化流水线”,人类是负责在关键节点拍板的“车间主任”。
核心共识:构建 Agent 系统,本质上不是在做算法调优,而是在做复杂的工程系统编排。
模块二:标准架构 —— “1+3” 多智能体协同模型
不要试图用一个巨无霸 Prompt 让一个大模型干完所有事(会导致上下文爆炸、指令遗忘)。工业级的标准做法是分层解耦。我们需要在系统里设立 4 个专职的虚拟员工:
- 路由大脑 (Router):入口调度员
- 职责: 意图分类。判断用户是简单的法规名词解释(走问答),还是复杂的“起草一份医疗数据合规条例”(走工作流)。
def router_logic(state: WorkflowState) -> str: """ 根据用户输入,动态决定去向哪个子系统。 """ # 调用轻量级 LLM 或规则引擎判断意图 intent = llm_classifier.invoke(state["user_input"]) if intent == "complex_project": return "planner_node" # 复杂任务,交给规划者拆解 elif intent == "simple_qa": return "qa_node" # 简单问答,直接去单轮对话节点 else: return "end"
- 规划大脑 (Planner):架构师 / 业务主管
- 职责: 降维拆解。它不干具体活,只负责把大需求拆解为包含依赖关系的任务图谱(DAG)。强制输出严格的 JSON 任务队列。
from pydantic import BaseModel, Field# 定义强类型 JSON 输出结构class TaskPlan(BaseModel): tasks: List[Dict] = Field(description="拆解出的任务列表")def planner_node(state: WorkflowState): """ 节点:接收原始需求,输出结构化任务队列。 """ print("🧠 Planner 正在拆解任务...") # 1. 组装 Prompt,注入环境上下文 prompt = f""" 请根据以下环境:{state['workspace_context']} 拆解用户需求:{state['user_input']} 请严格遵循 TaskPlan 结构输出。 """ # 2. 强制 LLM 结构化输出 structured_llm = llm.with_structured_output(TaskPlan) plan_result = structured_llm.invoke(prompt) # 3. 返回状态增量(引擎会自动将 task_queue 覆盖到全局 State 中) return { "task_queue": plan_result.tasks, "execution_logs": ["Planner: 任务拆解完毕,共生成 {} 个子任务".format(len(plan_result.tasks))] }
- 执行大脑 (Executor):核心打工人(可并发 N 个)
- 职责: 系统的“手脚”。从队列里领走任务,进入 ReAct (思考->行动) 循环。它被赋予极高的工具权限(如读写文件、查询私有数据库)。
def executor_node(state: WorkflowState): """节点:Executor 不直接执行工具,而是思考并输出 Tool Call 指令""" pending_tasks = [t for t in state["task_queue"] if t["status"] == "pending"] ifnot pending_tasks: return {} current_task = pending_tasks[0] # 将之前的历史记录 (messages) 喂给大模型 messages = state.get("messages", []) prompt = f"当前任务:{current_task['desc']}。请执行必要的工具来完成此任务。" # 调用 LLM,此时它可能输出最终文本,也可能输出 tool_calls 指令 response = llm_with_tools.invoke([prompt] + messages) state_update = { "messages": [response], "execution_logs": [f"Executor: 针对任务 {current_task['id']} 进行了思考"] } # 【核心逻辑闭环】:如果没有触发工具调用,说明干完活了,把内容存为最终草案供审查 ifnot hasattr(response, 'tool_calls') ornot response.tool_calls: state_update["current_draft"] = response.content return state_update
- 审查大脑 (Reviewer):质量质检员
- 职责: 质量兜底。执行者干完活后,它负责调用静态检查工具(如法言法语冲突检测、中药配伍禁忌检测)。如果报错,直接打回重做。
def reviewer_node(state: WorkflowState): """ 节点:对当前生成的草案进行严格的质量检查。 """ print("🕵️ Reviewer 正在审查质量...") draft = state["current_draft"] # 1. 运行本地的硬编码规则检查 (例如:中药禁忌、法言法语正则匹配、代码 Lint) rule_errors = run_static_lint(draft) # 2. 运行大模型语义审查 (Judge LLM) semantic_errors = llm_judge.invoke(f"请挑出这段草案中的逻辑错误:{draft}") all_errors = rule_errors + extract_errors(semantic_errors) # 3. 返回状态增量(只要 errors 数组不为空,接下来的路由就会将其打回) if all_errors: return {"errors": all_errors, "execution_logs": ["Reviewer: 发现致命错误,准备打回"]} else: return {"errors": [], "execution_logs": ["Reviewer: 审查通过绿灯"]}
模块三:调度引擎 —— 状态机与动态图底层原理
多个 Agent 之间如何通信?如何避免死锁?这是系统的骨架。
- 全局状态 (Global State):唯一的真理之源
- Agent 之间不互相传参。它们共同读写一个存在于内存中的大型 JSON 对象。Planner 写入待办任务,Executor 写入执行结果,所有动作都是对 State 的修改。
from typing import TypedDict, Annotated, List, Dictimport operatorfrom langchain_core.messages import BaseMessage, add_messages# 定义全局状态(所有智能体共享的内存白板)class WorkflowState(TypedDict): user_input: str # 用户的原始需求 workspace_context: str # 环境上下文 task_queue: List[Dict] # 任务队列 current_draft: str # 累计生成的草案或代码 # 【关键细节】:报错日志必须是覆盖模式,以便修复后能清空错误 errors: List[str] # 【核心机制】:LLM 与 ToolNode 通信的专用通道 (自动追加历史) messages: Annotated[list[BaseMessage], add_messages] # 运行日志,使用追加模式 execution_logs: Annotated[List[str], operator.add]
:::infoState 的覆写与追加机制 在 LangGraph 中,当节点函数返回字典时(如 return {"current_draft": "新代码"}),默认行为是**完全覆盖(Overwrite)掉原来的同名字段。 如果你希望数据是追加(Append)**的(比如日志、报错列表、多轮对话的历史消息),必须在定义 State 时使用 Annotated[..., operator.add]。这是图引擎流转时保证记忆不丢失的核心秘诀。
:::
- 图节点 (Nodes):无状态的纯函数
- 每一个 Agent 本质上就是一个 Python 函数。节点接收 State,交给大模型推理,返回增量数据(如
{"errors": ["发现违规条款"]}),引擎会自动合并到全局 State 中。
- 条件边 (Conditional Edges):图的动态神经
- 决定下一步谁来执行的“交警”。通过一段极简代码读取 State(如
if len(state.errors) > 0: return "Executor"),动态改变图的走向,实现“自我纠错循环”。
def check_workflow_status(state: WorkflowState) -> str: """ 条件边逻辑:每次 Reviewer 执行完后,由它来决定下一步的去向。 """ # 场景 1:如果 Reviewer 发现了错误 -> 打回给 Executor 重做 (Reflection 闭环) if len(state["errors"]) > 0: return"go_to_executor" # 场景 2:如果 Reviewer 没发现错误,检查还有没有剩下的任务 pending_tasks = [t for t in state["task_queue"] if t["status"] == "pending"] if len(pending_tasks) > 0: return"go_to_executor"# 继续干下一个任务 # 场景 3:没错误,也没剩余任务了 -> 完美杀青 return"finish"
模块四:物理交互 —— 工具调用 (Tool Calling) 揭秘
大模型是如何“查询内部法规数据库”或“生成 Word 报告”的?
- 给大模型看说明书 (JSON Schema): 提取 Python 查库函数的参数类型,喂给大模型。告诉它:“你有一把叫
query_db的锤子,需要传入keyword”。 - 大模型输出指令 (LLM Output): 大模型推理后,吐出一串 JSON:
{"tool": "query_db", "args": {"keyword": "医疗器械"}}。 - 系统拦截与物理执行 (Backend Execution): 后端(如 FastAPI)拦截到这个 JSON,找到本地真正的 Python 函数执行,然后把结果作为观察值(Observation)塞回给大模型。
开发者如何绑定工具: 开发者不需要手写复杂的 JSON,只需写普通的 Python 函数并加上 @tool 装饰器。
:::info ** 防坑警示:** > 1. 注释就是指令: 工具函数下方的 """文档注释""" 会被原封不动地翻译给大模型。必须写清楚“何时使用”以及“参数格式要求”,绝对不能敷衍。 2. 屏蔽原生异常: 必须在工具内部 try-except 捕获异常,并返回友好的报错字符串。如果让原生报错炸出函数,整个图引擎会直接崩溃。
:::
from langchain_core.tools import toolimport json# 1. 开发者写具体的业务逻辑,加上 @tool 装饰器和明确的类型注解@tooldef query_tcm_knowledge_db(keyword: str) -> str: """ 用于查询中药学名、配伍禁忌或法规条款。 注意:输入参数 keyword 必须是标准的中医药材学名或法规全称。 """ try: # 这里写真实的查库代码... return"查到的业务资料内容" except Exception as e: # 必须把物理报错转化为文本,让大模型看到并触发自我纠错 returnf"查询失败,数据库响应超时或关键字无效。详细错误: {str(e)}。请尝试更换关键字重新查询。"# 2. 系统在后台自动将其转换为 JSON Schema,并绑定给大模型llm_with_tools = llm.bind_tools([query_tcm_knowledge_db])
真正在沙箱里扣动扳机的 **ToolNode**: 大模型输出指令后,官方提供了预置节点 ToolNode 来无脑执行体力活:
from langgraph.prebuilt import ToolNode# 将我们定义的工具打包成一个专门用来“干体力活”的节点tools = [query_tcm_knowledge_db, write_file]tool_executor_node = ToolNode(tools)# 在编译图时,直接将它作为 Executor 之后的下游节点workflow.add_node("tools", tool_executor_node)
这样,Executor(大脑)负责想用什么工具,ToolNode(手脚)负责在后端的 Docker 沙箱里无脑执行并把结果返回给大脑,职责进一步解耦。
:::info 一旦引入了 ToolNode,我们的图里其实就多了一个隐藏的微循环:
Executor思考后,输出一个带 Tool Call 的 Message 到 State 中,图流向ToolNode。ToolNode在沙箱里执行完,把结果 Message 追加到 State 中,**图必须再流回 ****Executor**。Executor看到工具执行的结果后,得出最终结论,再往下流给Reviewer。 这种LLM -> Tool -> LLM的乒乓球式微循环,才是智能体能够“与物理世界互动”的真正基石。
:::
模块五:从实验室到生产线 ——核心工程护城河
在局域网/政企真实环境中,画出流程图只是第一步。当 100 个真实用户同时涌入,且服务器随时可能波动时,我们必须依靠以下 5 大工程机制保命:
1. 记忆持久化与中断恢复 (State Checkpointing)
- 痛点: 流程需要在“人工审批”节点挂起。如果服务器重启,内存里的 State 丢失,工作流直接崩溃。
- 解法: 引入 Checkpointer。每次节点流转完毕,系统自动将当前 State 序列化存入关系型数据库(如 PostgreSQL)。用户第二天点击确认,系统瞬间“读档复活”。
from langgraph.graph import StateGraph, START, ENDfrom langgraph.checkpoint.postgres import PostgresSaverfrom langgraph.prebuilt import tools_conditionworkflow = StateGraph(WorkflowState)# 1. 注册节点workflow.add_node("planner_node", planner_node)workflow.add_node("executor_node", executor_node)workflow.add_node("reviewer_node", reviewer_node)workflow.add_node("tools", tool_executor_node)# 2. 定义连线与微循环workflow.add_edge(START, "planner_node")workflow.add_edge("planner_node", "executor_node")# 【核心交警】:如果有 tool_calls 去 tools 节点,否则去 reviewerworkflow.add_conditional_edges( "executor_node", tools_condition, {"tools": "tools", "__end__": "reviewer_node"})workflow.add_edge("tools", "executor_node") # 工具用完回传给大脑workflow.add_conditional_edges( "reviewer_node", check_workflow_status, {"go_to_executor": "executor_node", "finish": END})# 3. 配置持久化与编译 (支持 HITL 挂起)memory = PostgresSaver.from_conn_string("postgresql://user:pass@localhost/db")app = workflow.compile( checkpointer=memory, interrupt_before=["executor_node"] # 强制挂起,等待人类确认)
进阶操作:人类“车间主任”抢过方向盘 在流程挂起时,人类不仅能点击“同意继续”,还能直接强行修改大模型生成的错误状态。
:::info师避坑提示: 在使用 **resume=True** 时,必须导入 LangGraph 官方的 **Command** 类型,否则运行时会抛出未定义异常。
:::
from langgraph.types import Command# 1. 业务专家在前端审查,并修改了任务队列modified_task_queue = user_edited_tasks # 2. 后端强制覆写数据库里的 Stateapp.update_state(config, {"task_queue": modified_task_queue})# 3. 带着修改后的正确路线,让图继续流转app.invoke(Command(resume=True), config=config)
2. 多租户隔离与并发控制 (Thread ID)
- 痛点: 法务部的 A 正在起草合同,B 正在审查合规。如果共用 State,A 的数据会污染 B 的草案。
- 解法: 强制隔离。每次调用图引擎,必须注入唯一的
Thread_ID。引擎严格根据 ID 在数据库中开辟独立沙箱,确保万级并发互不干扰。
# 实际运行时的调用方式(多租户并发隔离)config = {"configurable": {"thread_id": "project_weimin_tcm_001"}}# 用户发送需求for output in app.stream({"user_input": "请帮我分析这份健康档案"}, config=config): print(output)
3. 事件流推送 (Event Streaming UX)
- 痛点: Agent 执行耗时极长。传统的单一 LLM 流式输出无法透视复杂图谱的内部流转。
- 解法: 后端监听图的内部事件流(
astream_events),通过 SSE 向前端不仅推送文本 Tokens,还要实时推送节点切换状态(如“正在调用搜索工具…”、“正在审查代码…”),打造极佳的交互体验。
async def stream_agent_events(): # 使用 astream_events 监听底层的所有微观动作 (version="v2" 是必须的) asyncfor event in app.astream_events({"user_input": "起草方案"}, config=config, version="v2"): kind = event["event"] # 捕捉大模型打字机事件 if kind == "on_chat_model_stream": yieldf"data: {event['data']['chunk'].content}\n\n" # 捕捉节点切换与工具调用事件(前端用来画进度条和状态灯) elif kind == "on_tool_start": yieldf"data: [系统提示] 正在调用内部工具: {event['name']}...\n\n"
4. 越权防御与物理沙箱 (Security & Sandbox)
- 痛点: 外部输入的文档可能暗藏 Prompt Injection(提示词注入),诱导执行者 Agent 执行恶意脚本或越权查询。
- 解法: 最小权限原则。代码执行必须放入无外网、限 CPU 的独立 Docker 容器;敏感业务接口前置规则清洗器,防死恶意指令覆写。
5. 不确定性测试 (Agentic Evals)
- 痛点: 传统的
assert单元测试无法评估大模型输出的长文本草案质量。 - 解法: 建立“裁判大模型(Judge LLM)”机制。每次系统迭代,后台自动跑 100 个历史基准任务,由裁判模型根据“合规性、逻辑严密性”进行量化打分。
附录:AI 自动化工厂标准工程脚手架 (FastAPI + LangGraph)
为了贯彻“高内聚、低耦合”的架构思想,保证团队多人协作时互不干扰,我们在真实落地时,请严格按照以下目录结构初始化项目。
将 API 接口层与底层的 Agent 核心逻辑完全物理隔离:
ai_agent_factory/├── app/│ ├── api/ # 暴露给前端的 FastAPI 路由层│ │ ├── dependencies.py # 鉴权、数据库 Session 等依赖│ │ └── routes.py # 定义 /chat/stream 等接口,调用底层的 workflow│ ││ ├── agent/ # 🧠 核心:智能体工作流引擎层│ │ ├── __init__.py│ │ ├── state.py # 对应【模块三】:定义 WorkflowState (唯一的真理之源)│ │ ├── graph.py # 对应【模块五】:StateGraph 的组装、连线与 Checkpointer 编译│ │ ││ │ ├── nodes/ # 对应【模块二】:所有的纯函数大脑│ │ │ ├── __init__.py│ │ │ ├── planner.py # 规划大脑逻辑 (结构化输出 DAG)│ │ │ ├── executor.py # 执行大脑逻辑 (ReAct 循环与工具唤醒)│ │ │ └── reviewer.py # 审查大脑逻辑 (规则拦截与大模型裁判)│ │ ││ │ ├── edges/ # 对应【模块三】:所有的路由交警│ │ │ ├── __init__.py│ │ │ ├── routers.py # router_logic 等静态分发逻辑│ │ │ └── conditions.py # check_workflow_status 等动态循环回退逻辑│ │ ││ │ └── tools/ # 对应【模块四】:所有的物理交互工具箱│ │ ├── __init__.py│ │ ├── db_tools.py # 数据库读写工具 (如 query_legal_db, query_tcm_db)│ │ └── os_tools.py # 文件读写、终端脚本等系统工具│ ││ ├── core/ # ⚙️ 基础设施层│ │ ├── config.py # 环境变量 (API Keys, 数据库连接串)│ │ ├── llm_factory.py # 大模型统一初始化 (配置 DeepSeek/Qwen 等基座模型)│ │ └── database.py # PostgreSQL / Checkpointer 的连接池管理│ ││ └── main.py # FastAPI 启动入口,挂载路由和中间件│├── tests/ # 对应【模块五】:不确定性测试 (Agentic Evals)│ ├── test_nodes.py # 对单个 Agent 节点进行单元测试│ └── eval_judge.py # 基于历史数据集的 LLM 自动化打分脚本│├── requirements.txt # 核心依赖:fastapi, langgraph, langchain, psycopg, pydantic 等└── Dockerfile # 对应【模块五】:物理沙箱封装隔离
:::info
为什么这么拆?
- 并行开发: 负责写具体业务工具的同事只管在
tools/里加函数;负责写 Prompt 调优的同事只管改nodes/;两者互不冲突。 - 状态解耦: 所有节点共享
state.py,任何一个 Agent 如果需要新增“记忆字段”,必须在统一的地方修改,避免了“幽灵变量”的乱窜。 - 安全隔离: FastAPI 的
routes.py只负责接收 HTTP 请求和管理 SSE 异步流,它把用户的输入打包好塞给graph.py,由引擎代为执行。实现了 Web 层和 Agent 逻辑层的完美剥离。
学AI大模型的正确顺序,千万不要搞错了
🤔2026年AI风口已来!各行各业的AI渗透肉眼可见,超多公司要么转型做AI相关产品,要么高薪挖AI技术人才,机遇直接摆在眼前!
有往AI方向发展,或者本身有后端编程基础的朋友,直接冲AI大模型应用开发转岗超合适!
就算暂时不打算转岗,了解大模型、RAG、Prompt、Agent这些热门概念,能上手做简单项目,也绝对是求职加分王🔋

📝给大家整理了超全最新的AI大模型应用开发学习清单和资料,手把手帮你快速入门!👇👇
学习路线:
✅大模型基础认知—大模型核心原理、发展历程、主流模型(GPT、文心一言等)特点解析
✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑
✅开发基础能力—Python进阶、API接口调用、大模型开发框架(LangChain等)实操
✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用
✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代
✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经
以上6大模块,看似清晰好上手,实则每个部分都有扎实的核心内容需要吃透!
我把大模型的学习全流程已经整理📚好了!抓住AI时代风口,轻松解锁职业新可能,希望大家都能把握机遇,实现薪资/职业跃迁~
这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

更多推荐


所有评论(0)