news 2026/9/7 17:23:32

LangChain多智能体实战:用LangGraph编排Agent构建婚礼策划系统

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LangChain多智能体实战:用LangGraph编排Agent构建婚礼策划系统

很多开发者第一次接触 LangChain 多智能体时,容易把“多 Agent”想成让一堆大模型角色互相聊天,最后有一条主线把结论串起来。这个思路没有错,但落到真实业务里往往不稳定:消息来回传、上下文互相污染、工具调用混乱,方案生成出来像“开盲盒”。婚礼策划就是一个非常典型的场景——预算、场地、餐饮、摄影、时间线,每个环节都有独立的专业判断标准,如果全部压进一个超长 Prompt,模型很容易前后矛盾:预算只有几万,却推荐五星级酒店;200 人婚礼,却安排进只能容纳 50 人的宴会厅。

本文的核心判断是:LangChain 做多智能体项目,真正的价值不在“让多个 Agent 自由聊天”,而在“把复杂任务拆成有边界的专业角色,再用图编排把它们串成一条可控的流水线”。一套能落地、可维护、运行成本可控的“中配”方案,比看起来炫酷但无法复现的高配架构更有意义。下面我会用“婚礼策划师”这个极易理解的场景,带你从零实现一套基于 LangChain + LangGraph + Streamlit 的多智能体应用。

这套方案定位为“中配”:不需要本地 GPU,不需要自建向量数据库,不需要微服务,只需要一个支持工具调用的模型 API,以及一台能跑 Python 的普通开发机。读完本文,你可以得到一份完整可运行的代码,学会如何设计 Agent、如何给 Agent 配工具、如何用 LangGraph 控制多智能体协作,以及如何用 Streamlit 在浏览器中做出交互界面。这套思路可以直接迁移到旅游规划、活动执行、装修报价、企业顾问等任何“多角色协同出方案”的业务场景。

1. 为什么婚礼策划需要“多智能体”

1.1 婚礼策划是典型的多角色协作场景

婚礼策划的内容看起来很统一,就是“出一份婚礼方案”,但实际上它至少包含五个专业模块:预算分配、场地选择、餐饮菜单、摄影摄像、时间线执行。每一个模块的决策依据都来自不同的专业经验。预算规划师关注的是“总预算如何在十几个项目之间分配”,场地顾问关心的是“城市、人数、风格与场地类型的匹配”,餐饮顾问要考虑“人均餐标和宴席形式”,摄影顾问则要判断“机位数量与拍摄风格”。

这些模块之间还有明显的依赖关系:只有先确定总预算,才能推算餐饮和摄影的资金比例;只有确定了场地类型,才能判断菜单适合圆桌宴席还是自助冷餐;只有前面所有模块都落定,时间线才能排得出来。这种“有先后、有依赖、有专业分工”的任务结构,恰恰就是多智能体最擅长处理的场景。如果全部依赖单个模型,把 5 个角色的职责塞进同一个上下文里,不仅 Prompt 会变得非常长,而且模型在生成过程中很难始终如一地扮演所有角色。

1.2 单智能体与多智能体的边界

单智能体方案其实也能生成婚礼方案,它适合需求简单、输出篇幅短、不需要反复调用外部工具的场景。但一旦需求复杂,它的劣势就会放大:工具堆积过多时,模型可能调用错误工具;上下文过长时,模型会遗忘前面的约束;修改某个模块的需求,往往会牵连其他模块的生成结果。

多智能体方案把任务按专业角色切分,每个 Agent 拥有独立的系统提示词、独立的工具集合、独立的上下文。预算 Agent 只看到预算相关的工具,场地 Agent 只看到场地相关的工具,互相之间通过共享状态传递关键结果,而不是把所有原始信息全部灌给同一个模型。这样做的好处是:任务边界清晰,Prompt 不会互相污染;新增一个模块时,只需增加一个节点;某个 Agent 出错时,可以单独调试,不影响其他节点。

下面是单智能体与多智能体在婚礼策划场景下的对比:

对比维度单智能体方案多智能体方案
任务边界所有职责混在一个上下文每个角色拥有独立上下文
工具管理全部工具堆在一起,容易误用按角色分配工具,误用率低
扩展性增加新模块会让 Prompt 越来越长增加新节点即可,影响面小
可维护性改一个需求容易牵动全局各节点独立修改、独立测试
生成一致性长上下文中容易前后矛盾节点间只传递关键结果,一致性更可控

1.3 中配方案适合谁

我之所以强调“中配”,是想把方案定位在大多数开发者都能实际跑通的范围内。它适合用来自学多智能体原理、做毕业设计、做作品集,也适合中小型团队在没有专门基建的情况下快速搭建内部效率工具。如果你想做一个高并发的 C 端产品、有严格的实时性要求,或者业务流程中必须有人工审批环节,那本文方案还需要在工程层继续加固,比如增加队列、审核节点、限流和监控。

换句话说,中配方案的价值在于“以最小的成本把多智能体跑通”,而不是一步到位实现生产级系统。先跑通,再迭代,这是最务实的路径。

2. LangChain 多智能体的核心概念与使用边界

2.1 Agent:以一个 LLM 为中心的执行单元

Agent 是 LangChain 生态里的核心抽象。一个 Agent 最少包含三部分:LLM 模型、系统提示词、可用工具列表。模型根据用户输入和系统提示词判断下一步动作:直接回答,还是调用某个工具,然后再基于工具返回的结果继续推理。

在多智能体项目中,每个 Agent 通常只负责一个专业角色。以婚礼策划为例,预算 Agent 的系统提示词会写“你是一位严谨的婚礼预算规划师”,它的工具列表里只有一个预算计算工具;场地 Agent 的系统提示词会写“你是一位熟悉婚礼场地的选址顾问”,它的工具列表里只有一个场地推荐工具。这种“一个角色一套上下文和一套工具”的设计,会明显降低模型误用工具的概率。

2.2 Tool:把外部能力暴露给模型

Tool 的本质是一个带有描述信息的函数。LangChain 通过@tool装饰器把普通 Python 函数包装成 Agent 可以识别的工具,函数名和 docstring 会被作为“说明书”交给模型。模型在看到用户问题后,会判断是否需要调用函数,并自动填充参数。

这里有一个容易忽略的点:工具描述写得越具体,模型调用越准确。比如recommend_venue(city: str, guest_count: int, style: str, budget: float)这个函数,docstring 必须写清楚每个参数的含义,否则模型就可能把预算的单位搞错,或者把宾客人数和预算位置传反。

2.3 LangGraph:用图来编排多智能体

LangGraph 是 LangChain 生态中的图编排框架,专门用于管理 Agent 之间的调用关系。它基于StateGraph构建流程:State 是全局共享的数据结构,Node 是具体的执行单元,Edge 定义了 Node 之间的流转方向。

在本文的婚礼策划项目中,State 里既包含用户输入的原始信息,也包含每个 Agent 产出的中间结果。每个 Node 从 State 读取自己所需的字段,执行完成后再把结果写回 State。最终由一个汇总 Node 读取所有中间结果,生成完整方案。这样做的好处是:流程结构可视化、节点职责单一、状态流转清晰。

2.4 与 LangChain、CrewAI、MCP 的关系

初学者经常会混淆这几个概念。LangChain 是一个组件库,提供 LLM 封装、Prompt 模板、Tool 定义、Memory 等基础能力;LangGraph 是 LangChain 生态中的编排框架,专注流程控制。两者不是替代关系,而是组合关系:用 LangChain 的模型和工具组件构造节点能力,用 LangGraph 把节点编排成图。

CrewAI 是另一套流行的多智能体框架,它更偏“角色协作”,强调用声明式配置定义角色、任务和流程,上手快,但对复杂控制流的掌控能力不如 LangGraph。MCP(Model Context Protocol)则是模型接入外部工具和数据的标准化协议,本文使用的@tool是本地函数绑定,MCP 把工具作为独立服务暴露,更适合跨项目复用。理解了这层关系,你就知道什么时候该选 LangGraph、什么时候该选 CrewAI、什么时候该引入 MCP。

3. 环境准备与项目初始化

3.1 前置环境要求

本文方案需要的运行环境并不高,推荐配置如下:

  • 操作系统:Windows / macOS / Linux 均可。
  • Python 版本:建议 3.10 或 3.11,3.12 在部分依赖组合下可能有兼容问题。
  • 模型 API:任意支持工具调用(function calling)的 OpenAI 兼容接口,本文示例默认使用 OpenAI 模型名,如果你接入其他模型服务商,只需修改ChatOpenAI的配置。
  • 开发工具:VS Code 或其他 Python IDE,能用命令行执行 Python 脚本即可。

建议在项目目录下创建 Python 虚拟环境,避免依赖污染系统环境。

3.2 安装依赖

在项目根目录创建requirements.txt,写入以下依赖:

langchain>=0.2.0 langchain-openai>=0.1.0 langgraph>=0.2.0 streamlit>=1.39.0 python-dotenv>=1.0.0

然后在终端执行安装:

pip install -r requirements.txt

如果你后续想用其他模型服务商,还需要额外安装对应的 LangChain 集成包,例如langchain-anthropiclangchain-google-genai等。具体以你的模型服务商文档为准。

3.3 配置模型 API

在项目根目录创建.env文件,写入你的 API Key 和模型名:

OPENAI_API_KEY=sk-xxxxxxxxxxxxxxxx OPENAI_MODEL=gpt-4o-mini

注意两点:第一,OPENAI_API_KEY不要硬编码在代码里,也不要提交到 Git 仓库,建议把.env加入.gitignore;第二,如果你接入的是其他兼容 OpenAI 协议的模型服务商,可以在代码里通过base_url参数指定接入地址,具体配置以服务商文档为准。

4. 项目整体设计

4.1 架构总览

整个项目包含 6 个 Agent,分别是预算 Agent、场地 Agent、餐饮 Agent、摄影 Agent、时间线 Agent 和汇总 Agent。用户请求先进入预算 Agent,再依次经过场地、餐饮、摄影、时间线节点,最后由汇总 Agent 输出完整方案。这个流程是线性的,每一步都依赖前一步的结果:

用户输入(城市、预算、人数、风格、特殊要求)→ 预算方案 → 场地建议 → 餐饮建议 → 摄影建议 → 时间线 → 汇总方案

这种顺序单链结构是最容易理解和调试的多智能体结构。你可以在任意两个节点之间增加条件路由,比如预算较低时跳过某些高级模块,或者在某一步结果不合格时退回上一步重新生成。

4.2 状态数据结构

LangGraph 里 State 的设计直接决定了多智能体协作的灵活性。本文定义的状态字段如下:

字段名类型含义
messageslist全局消息记录,用于保留上下文
citystr举办城市
budgetfloat总预算,单位万元
guest_countint宾客人数
stylestr婚礼风格
special_requirementstr用户特殊要求
budget_planstr预算 Agent 输出
venue_planstr场地 Agent 输出
menu_planstr餐饮 Agent 输出
photo_planstr摄影 Agent 输出
timeline_planstr时间线 Agent 输出
final_planstr汇总后的完整方案

其中messages使用add_messages注解,LangGraph 会自动把多个节点写入的消息合并,而不是简单覆盖。

4.3 多智能体协作流程

每个 Agent 在图中是一个 Node。Node 函数从 State 中读取需要的字段,拼成新消息,调用对应的 Agent,最后把返回结果写入 State。通过add_edge把节点按顺序连接起来,就构成了一个多智能体流水线。

这种设计的关键在于“节点之间只传递必要信息”。预算 Agent 输出的完整文本会进入budget_plan字段,场地 Agent 不需要重新理解用户的原始需求,只需要读取预算方案和自己的输入信息即可。信息隔离做得越好,模型在长流程里的表现就越稳定。

5. 核心代码实现

5.1 工具层实现

创建tools.py,定义 4 个工具函数。这些工具使用模拟规则生成结果,你可以把它们替换成真实 API 调用或数据库查询。

# tools.py from langchain_core.tools import tool @tool def compute_budget_plan(total_budget: float, guest_count: int) -> str: """根据婚礼总预算(万元)和预计宾客人数,输出各项目的预算分配区间。""" if guest_count <= 0: guest_count = 1 per_guest = total_budget * 10000 / guest_count plan = { "场地与搭建": total_budget * 0.35, "餐饮酒水": total_budget * 0.25, "摄影摄像": total_budget * 0.12, "婚纱礼服与妆造": total_budget * 0.10, "策划与执行": total_budget * 0.08, "甜品伴手礼": total_budget * 0.06, "应急预留": total_budget * 0.04, } lines = [f"- {name}: {amount:.2f} 万元" for name, amount in plan.items()] lines.append(f"按 {guest_count} 人估算,人均餐饮预算约 {per_guest * 0.25:.0f} 元/人") return "\n".join(lines) @tool def recommend_venue(city: str, guest_count: int, style: str, budget: float) -> str: """根据城市、宾客人数、婚礼风格和总预算(万元),推荐合适的场地类型与筛选建议。""" if guest_count > 300: venue_type = "大型宴会厅或会展中心" elif guest_count >= 100: venue_type = "中大型酒店宴会厅或户外草坪场地" elif guest_count >= 30: venue_type = "精品酒店或私密餐厅" else: venue_type = "私人会所或露台餐厅" if budget < 5: budget_note = "预算偏低,建议压缩桌数和布置规模,优先保证餐饮体验。" elif budget < 20: budget_note = "预算适中,建议选择本地口碑较好的酒店,利用当季花材降低布置成本。" else: budget_note = "预算充足,可考虑拥有独立草坪、宴会厅和婚房的综合场地。" return ( f"推荐类型:{venue_type}\n" f"建议城市:{city}\n" f"匹配风格:{style}\n" f"预算提示:{budget_note}" ) @tool def recommend_menu(style: str, per_guest_budget: float) -> str: """根据婚礼风格和人均餐标预算(元/人),给出菜单搭配建议。""" if style in ["中式", "复古"]: base = "中式圆桌宴席,冷菜八道、热菜十道、主食汤品各一" elif style in ["森系", "户外草坪"]: base = "自助冷餐或西式分餐,搭配海鲜台、甜品台和低度酒水" elif style == "海边": base = "海鲜自助为主,辅以烧烤档和鲜榨饮品" else: base = "混搭自助餐,中西菜式各半,设置饮品台" if per_guest_budget >= 500: quality = "可加入龙虾、鲍鱼等高阶食材,并配备位上菜服务。" elif per_guest_budget >= 300: quality = "以当季食材为主,保持出品稳定,可设置一至两道招牌菜。" else: quality = "建议精选家常菜,重点保证分量和出餐速度。" return f"菜单形式:{base}\n品质建议:{quality}" @tool def recommend_photo_package(style: str, budget_ratio: float) -> str: """根据婚礼风格和摄影预算占比(小数),推荐摄影摄像服务方案。""" if budget_ratio > 0.15: level = "双机位摄影 + 双机位摄像 + 婚前微电影" elif budget_ratio > 0.08: level = "双机位摄影 + 单机位摄像,保留精修原片和短视频快剪" else: level = "单机位摄影 + 重要环节拍摄,选择性价比工作室" if style in ["森系", "户外草坪", "海边"]: recommend = "适合胶片风格或自然光线,建议与摄影师提前踩点。" else: recommend = "适合大气宴会厅拍摄,注意现场灯光与摇臂机位的协调。" return f"套餐建议:{level}\n拍摄建议:{recommend}"

这些工具函数本身不依赖真实外部接口,因此你可以直接运行。在真实的工程项目里,建议把recommend_venue替换为酒店场所库查询,把recommend_menu替换为菜品数据库或 AI 影像库,工具层和智能体层可以完全解耦。

5.2 智能体层实现

创建agents.py,定义角色 Agent。这里使用langgraph.prebuilt.create_agent来创建“模型 + 系统提示词 + 工具”的执行体,它比手写 Agent 循环更简洁。

# agents.py import os from typing import TypedDict, Annotated from dotenv import load_dotenv from langchain_core.messages import HumanMessage, SystemMessage from langchain_openai import ChatOpenAI from langgraph.graph import StateGraph, START, END from langgraph.graph.message import add_messages from langgraph.prebuilt import create_agent from tools import ( compute_budget_plan, recommend_menu, recommend_photo_package, recommend_venue, ) load_dotenv() MODEL_NAME = os.getenv("OPENAI_MODEL", "gpt-4o-mini") llm = ChatOpenAI(model=MODEL_NAME, temperature=0.3) budget_agent = create_agent( model=llm, tools=[compute_budget_plan], system_prompt=( "你是一位严谨的婚礼预算规划师。" "你会收到城市、总预算、宾客人数、婚礼风格等信息," "请优先调用 compute_budget_plan 计算各项目预算区间," "然后结合经验给出 3 条预算优化建议。" ), ) venue_agent = create_agent( model=llm, tools=[recommend_venue], system_prompt=( "你是一位熟悉全国婚礼场地的选址顾问。" "你会收到城市、宾客人数、婚礼风格和整体预算等信息," "请调用 recommend_venue 获取场地建议," "再补充与场地相关的注意事项,例如签约、档期和停车。" ), ) menu_agent = create_agent( model=llm, tools=[recommend_menu], system_prompt=( "你是一位婚宴餐饮顾问。" "你会收到婚礼风格和人均餐标预算," "请调用 recommend_menu 获得菜单框架,再补充酒水搭配和试菜建议。" ), ) photo_agent = create_agent( model=llm, tools=[recommend_photo_package], system_prompt=( "你是一位婚礼摄影摄像顾问。" "你会收到婚礼风格和摄影预算占比," "请调用 recommend_photo_package 获得套餐建议,再补充拍摄流程安排。" ), ) timeline_agent = create_agent( model=llm, tools=[], system_prompt=( "你是一位婚礼执行导演。" "你会收到预算、场地、餐饮、摄影等模块结果," "请按时间顺序输出婚礼当天从早到晚的执行流程表," "包含每个环节的时间、负责人、注意事项。" ), ) merge_agent = create_agent( model=llm, tools=[], system_prompt=( "你是一位经验丰富的婚礼策划总监。" "你会收到预算、场地、餐饮、摄影、时间线等模块方案," "请将它们整合成一份结构清晰、语言自然、可执行的完整婚礼策划书。" "最终输出需要包含:方案概览、预算分配、场地建议、餐饮安排、" "摄影摄像建议、执行时间线、重点提醒。" ), )

每个 Agent 的system_prompt就是它的“岗位说明书”。你可以根据实际需要调整语气和职责描述。工具列表为空的时间线 Agent,意味着它只能依靠模型自身能力生成内容,这也是多智能体中常见的“纯推理型角色”。

5.3 编排层:用 LangGraph 构建流程

agents.py中继续定义状态结构和节点函数。

# agents.py 追加内容 class WeddingState(TypedDict): messages: Annotated[list, add_messages] city: str budget: float guest_count: int style: str special_requirement: str budget_plan: str venue_plan: str menu_plan: str photo_plan: str timeline_plan: str final_plan: str def budget_node(state: WeddingState): result = budget_agent.invoke({ "messages": [HumanMessage( content=( f"用户基本信息:\n" f"城市:{state['city']}\n" f"总预算:{state['budget']} 万元\n" f"宾客人数:{state['guest_count']} 人\n" f"婚礼风格:{state['style']}\n" f"特殊要求:{state['special_requirement']}\n\n" "请制定预算方案。" ) )] }) return {"budget_plan": result["messages"][-1].content} def venue_node(state: WeddingState): result = venue_agent.invoke({ "messages": [HumanMessage( content=( f"城市:{state['city']}\n" f"宾客人数:{state['guest_count']} 人\n" f"婚礼风格:{state['style']}\n" f"总预算:{state['budget']} 万元\n" f"预算方案:\n{state['budget_plan']}\n\n" "请给出场地建议。" ) )] }) return {"venue_plan": result["messages"][-1].content} def menu_node(state: WeddingState): per_guest_budget = state["budget"] * 10000 * 0.25 / state["guest_count"] result = menu_agent.invoke({ "messages": [HumanMessage( content=( f"婚礼风格:{state['style']}\n" f"人均餐标预算:{per_guest_budget:.0f} 元/人\n" f"场地建议:\n{state['venue_plan']}\n\n" "请给出餐饮建议。" ) )] }) return {"menu_plan": result["messages"][-1].content} def photo_node(state: WeddingState): result = photo_agent.invoke({ "messages": [HumanMessage( content=( f"婚礼风格:{state['style']}\n" f"摄影预算占比参考:0.12\n" f"餐饮建议:\n{state['menu_plan']}\n\n" "请给出摄影摄像服务建议。" ) )] }) return {"photo_plan": result["messages"][-1].content} def timeline_node(state: WeddingState): result = timeline_agent.invoke({ "messages": [HumanMessage( content=( f"预算方案:\n{state['budget_plan']}\n\n" f"场地建议:\n{state['venue_plan']}\n\n" f"餐饮建议:\n{state['menu_plan']}\n\n" f"摄影建议:\n{state['photo_plan']}\n\n" "请输出婚礼当天的执行时间线。" ) )] }) return {"timeline_plan": result["messages"][-1].content} def merge_node(state: WeddingState): content = ( f"预算方案:\n{state['budget_plan']}\n\n" f"场地建议:\n{state['venue_plan']}\n\n" f"餐饮建议:\n{state['menu_plan']}\n\n" f"摄影建议:\n{state['photo_plan']}\n\n" f"时间线:\n{state['timeline_plan']}\n\n" "请整合成一份完整的婚礼策划书。" ) result = merge_agent.invoke({ "messages": [HumanMessage(content=content)] }) return {"final_plan": result["messages"][-1].content}

接下来把这些节点编译成图:

# agents.py 追加内容 graph = StateGraph(WeddingState) graph.add_node("budget", budget_node) graph.add_node("venue", venue_node) graph.add_node("menu", menu_node) graph.add_node("photo", photo_node) graph.add_node("timeline", timeline_node) graph.add_node("merge", merge_node) graph.add_edge(START, "budget") graph.add_edge("budget", "venue") graph.add_edge("venue", "menu") graph.add_edge("menu", "photo") graph.add_edge("photo", "timeline") graph.add_edge("timeline", "merge") graph.add_edge("merge", END) wedding_graph = graph.compile() def run_wedding_planner( city: str, budget: float, guest_count: int, style: str, special_requirement: str = "暂无", ) -> str: initial_state = { "messages": [SystemMessage(content="这是一个多智能体婚礼策划项目。")], "city": city, "budget": budget, "guest_count": guest_count, "style": style, "special_requirement": special_requirement, "budget_plan": "", "venue_plan": "", "menu_plan": "", "photo_plan": "", "timeline_plan": "", "final_plan": "", } final_state = wedding_graph.invoke(initial_state) return final_state["final_plan"]

这段代码的关键在于:每个 Node 都只读取自己需要的 State 字段,并返回自己负责的字段。LangGraph 会把返回值合并到全局 State 中,最终merge节点拿到所有子方案,生成一份完整策划书。

5.4 Streamlit 交互层实现

创建app.py,用 Streamlit 搭建一个可视化交互界面。

# app.py import streamlit as st from agents import run_wedding_planner st.set_page_config(page_title="LangChain多智能体婚礼策划师", layout="wide") st.title("LangChain 多智能体婚礼策划师") st.markdown("输入婚礼基本信息,点击按钮生成完整策划方案。") with st.sidebar: st.header("婚礼基本信息") city = st.text_input("举办城市", value="杭州") budget = st.number_input( "总预算(万元)", min_value=1.0, max_value=500.0, value=20.0, step=1.0, ) guest_count = st.number_input( "宾客人数", min_value=10, max_value=2000, value=200, step=10, ) style = st.selectbox( "婚礼风格", ["中式", "西式", "户外草坪", "海边", "森系", "复古"], ) special_requirement = st.text_area( "特殊要求", placeholder="例如:希望有户外宣誓环节、需要宠物友好场地", ) if st.button("生成婚礼方案", type="primary"): if not special_requirement: special_requirement = "暂无" with st.spinner("多智能体正在协作生成方案,请稍候..."): try: plan = run_wedding_planner( city=city, budget=float(budget), guest_count=int(guest_count), style=style, special_requirement=special_requirement, ) st.success("方案生成完成") st.markdown(plan) except Exception as e: st.error(f"生成失败:{e}")

如果你希望每次生成前清空历史消息,可以在按钮逻辑中直接调用一个新的run_wedding_planner,它每次都会从空状态开始,天然避免了会话累积导致的上下文污染。

6. 运行效果与验证

在终端执行以下命令启动 Streamlit 应用:

streamlit run app.py

正常情况下,终端会输出本地访问地址,浏览器自动打开http://localhost:8501。在侧边栏填写城市、预算、人数、风格和特殊要求,点击“生成婚礼方案”按钮后,页面会显示加载提示,等待多个 Agent 依次执行。

判断运行成功的标准有两个:第一,浏览器页面最终出现完整方案,而不是报错或空白;第二,终端没有任何 Python 异常堆栈。如果方案缺失某个模块,比如只有预算没有场地,优先检查对应 Node 是否有返回、invoke结果中messages是否为空。

这里需要提醒一个常见误区:由于每个 Agent 都会调用模型,整体耗时会比单次调用更长,通常在十几秒到几十秒之间。这是多智能体的正常代价,不是代码卡死。你可以在每个 Node 函数里加一行print日志,观察执行进度:

print("预算节点完成") print("场地节点完成")

这种方式在调试阶段比任何可视化工具都直接。

7. 常见问题与排查

多智能体项目第一次跑不起来,大概率是环境问题或 API 配置问题。下面按出现频率整理:

问题现象可能原因排查方式解决方案
模块导入报错:ModuleNotFoundError: langgraphlanggraph 未安装或版本过低执行pip show langgraph查看版本执行pip install -U langgraph
create_agent无法导入langgraph 版本过旧查看报错中的导入路径升级到支持langgraph.prebuilt.create_agent的版本
模型调用超时网络不通或模型服务商不可达检查服务商状态页,用 curl 测试接口更换接入地址,或改用其他兼容模型
生成结果缺字段某个 Node 返回了空字符串在各 Node 函数内打印返回值检查对应 Agent 的 invoke 结果结构
页面转圈后无输出异常被吞或 API 返回格式异常查看终端完整报错except中打印 traceback

如果你使用的是非 OpenAI 官方的兼容接口,还要重点确认两点:第一,模型名是否真的支持该平台的 function calling;第二,base_url是否正确,不同的服务商路径前缀差异很大。很多“多智能体不工作”的问题,本质上是模型根本不会调用工具,而不是框架出问题。

8. 工程化改进与上线建议

8.1 提示词管理

系统提示词是多智能体质量的第一个杠杆。建议把每个 Agent 的system_prompt抽到独立的配置文件或数据库里,而不是硬编码在 Python 文件中。这样调整角色语气、增加规则、做 A/B 测试都更灵活。

8.2 状态与上下文清理

长会话场景下,历史消息会一直累积,既增加 token 成本,也可能干扰模型判断。Streamlit 每次点击按钮都重新调用run_wedding_planner,所以暂时不存在这个问题。但如果以后要扩展成真正的对话系统,就需要设计消息窗口或定期清理机制。

8.3 稳定性与成本控制

多智能体流程串行调用多次模型,成本会成倍增加。控成本的思路有三个:第一,选择便宜且支持工具调用的模型;第二,在节点入口增加缓存,相同输入直接返回历史结果;第三,对于不需要模型生成的模块,用规则逻辑替代 LLM。例如本文的预算计算其实完全可以用函数完成,保留 Agent 只是为了演示多智能体结构。

8.4 安全与权限

如果未来接入真实的场地库、供应商 API,必须增加权限校验、敏感数据脱敏和操作审计。工具层是模型与外部系统交互的边界,建议对传入参数做白名单校验,避免模型构造恶意参数。

8.5 可观测性

多智能体的调试难度比单个模型调用高得多,建议在正式项目中接入 LangSmith 或至少做好结构化日志。日志至少包含:每个节点的开始时间、结束时间、输入摘要、输出摘要、token 消耗。这样即使某个节点出错,也能快速定位。

9. 总结与进阶方向

这篇文章通过一个婚礼策划场景,完整实现了“中配”多智能体应用:用 LangChain 构造模型与工具,用 LangGraph 编排 6 个专业 Agent,用 Streamlit 提供交互界面。整套代码不依赖 GPU,普通开发机就能跑通,适合拿来学习、做毕设,也可以作为内部工具的原型。

下一步你可以做的改进有三个方向。第一,把模拟工具替换成真实 API,例如接场地库存接口、餐饮供应商接口,让方案真正可预订。第二,在 LangGraph 中加入条件路由,比如当预算小于 5 万时跳过摄影 Agent,走精简方案,这样可以进一步控制成本。第三,对比一下 CrewAI 的声明式多智能体写法,你会更理解 LangGraph 的图编排在复杂流程中的优势。

多智能体不是“把多个 AI 堆在一起”,而是通过合理的任务切分、状态流转和工具隔离,让每个模型的注意力集中在一件有边界的事情上。先把这套婚礼策划师跑通,再换一个业务领域,你会发现架构完全不用改,只是角色和工具变了而已。建议收藏备用,动手跑一遍代码,才能真正理解多智能体的价值边界在哪里。

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

FlagOS深度解析:一套开源软件栈如何打通异构算力算子库

算力荒折腾了两年&#xff0c;我现在最深的体会是&#xff1a;大模型训练和部署的瓶颈早就不单是卡本身&#xff0c;而是软件栈被各家芯片厂商牢牢锁死。A卡一个生态&#xff0c;B卡一个生态&#xff0c;C卡又是一个半成品生态&#xff0c;每换一批卡就要把框架、算子、通信库重…

作者头像 李华
网站建设 2026/9/7 17:21:52

AI辅助FPGA开发实测:从Vivado报错到RTL生成的边界

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 17:21:48

Stable Diffusion与LoRA模型实现AI角色随机生成技术详解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 17:19:24

数据备份系统设计与实现:从3-2-1原则到增量备份恢复实操

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华