多智能体架构如何重写智能客服技术选型:LangGraph实战指南
1. 为什么多智能体架构正在重写智能客服的技术选型1.1 从单模型问答到多智能体协作的演进逻辑做过客服系统的人都有一个共同体会单靠一个大模型接口加一段提示词能做出演示效果但一上生产就露馅。用户问“我上个月买的那台机器坏了发票也找不到了能不能换一台新的”这里面同时包含订单查询、售后政策判断、发票补开、换货流程四个子任务单模型要么一次性胡编一个答案要么在长上下文里丢失关键信息。这不是模型能力不够而是架构不对。多智能体协作的核心思路是把一个复杂的客服会话拆解成若干个职责单一的智能体每个智能体只负责自己擅长的领域由一个调度层负责分派任务、汇总结果、决定下一步走向。这套思路在工程上对应的就是LangGraph这类图编排框架——它把智能体之间的流转关系显式地建模成一张有向图节点是智能体或工具边是条件跳转逻辑。相比链式调用图结构最大的好处是支持循环、分支和状态回传这正是客服场景里“追问—澄清—执行—确认”这类多轮交互所需要的。我自己的判断是2024年之后新立项的智能客服项目如果还在用“一个提示词打天下”的方案基本等于给自己埋雷。原因很简单企业客服的知识库是异构的FAQ、工单、产品文档、订单系统业务动作是有副作用的退款、改地址、发验证码这两点决定了你必须把“理解”“决策”“执行”三层分开而多智能体加图编排是目前开源生态里最成熟的落地路径。1.2 这套系统到底解决了哪些真实痛点先把话说直白这套开源方案不是给个人开发者做着玩的玩具它的目标场景是中大型企业的客服中台。具体解决的痛点有这么几个。第一是意图路由的准确率问题。传统方案用分类模型做意图识别训练数据一变化就得重新标注重新训练。多智能体方案里路由本身由一个轻量智能体承担它读的是自然语言描述的路由规则新增业务线只需要加一条规则和对应的子智能体不用动模型。第二是多轮对话的状态管理。LangGraph 内置了状态机语义每一轮对话的上下文、已收集的槽位、当前所处的流程节点都保存在图的状态对象里不会因为模型上下文窗口限制而丢失。这一点在退换货、投诉升级这类长流程场景里是刚需。第三是人工坐席的平滑接管。热词里“智能客服转人工”出现频率很高说明这是用户最在意的体验点。多智能体架构里转人工不是一个异常分支而是一个正常的图节点——当置信度低于阈值、用户明确要求、或触发了敏感操作时调度智能体把当前完整状态打包推给人工坐席坐席看到的是结构化的会话摘要而不是一堆原始聊天记录。第四是可观测与可迭代。每个智能体的输入输出、每次工具调用的参数和返回、每个路由决策的依据全部落在图执行的轨迹里。出了问题能定位到具体是哪个节点判断错了而不是对着一个黑盒模型干瞪眼。1.3 适合什么样的团队上手这套东西不是零基础能直接吃透的。我的建议是团队里至少要有一个人熟悉 Python 异步编程、了解 LangChain 的基本抽象Tool、Retriever、Memory并且对状态机或工作流引擎有概念。如果团队之前做过 RAG 知识库问答那上手会快很多因为检索增强那部分逻辑是复用的。反过来如果团队完全没有后端工程能力只想拖拽出一个客服机器人那这套开源方案反而会带来负担——你需要自己部署向量库、自己接业务系统 API、自己写前端对话界面。它给你的是骨架和大脑血肉还得自己填。2. 核心架构拆解多智能体到底怎么分工2.1 调度智能体与领域智能体的职责边界一套能跑通的多智能体客服系统通常包含这么几类角色。我用一张表把职责和典型实现方式列清楚方便你对照自己的业务做裁剪。智能体角色核心职责典型实现是否必须调度智能体意图识别、任务分派、结果汇总、决定是否转人工LLM 结构化输出必须知识问答智能体基于企业知识库回答产品、政策类问题RAG 检索 LLM 生成必须业务操作智能体调用订单、退款、工单等业务 APILLM 工具调用按业务定澄清智能体当信息不足时主动追问补全槽位LLM 槽位校验推荐情绪安抚智能体识别负面情绪并调整话术分类模型 话术模板可选人工接管节点打包状态、生成摘要、转坐席图节点 消息队列必须调度智能体是整个系统的大脑但它不应该什么都干。我见过不少项目把调度写成“万能提示词”结果就是调度层越来越臃肿最后退化成单模型方案。正确的做法是让调度只做三件事判断用户这句话属于哪个领域、判断当前信息是否足够、判断下一步该走哪个节点。具体的知识检索和业务执行全部下沉到领域智能体。领域智能体之间不直接通信所有流转都经过调度层。这个约束看起来增加了开销但换来的是可观测性和可测试性——你可以单独对某个领域智能体做单元测试也可以在图层面做端到端的轨迹回放。2.2 LangGraph 图结构的设计要点LangGraph 的核心抽象是 StateGraph你需要先定义状态对象State再往图里加节点Node和边Edge。状态对象决定了智能体之间能传递什么信息这是整个设计里最关键的一步。一个客服场景的状态对象通常长这样from typing import TypedDict, Annotated, List from langgraph.graph.message import add_messages class CustomerServiceState(TypedDict): messages: Annotated[List, add_messages] # 对话历史 user_id: str # 用户标识 intent: str # 当前识别到的意图 slots: dict # 已收集的槽位信息 retrieved_docs: List[str] # 检索到的知识片段 tool_results: dict # 业务工具调用结果 need_human: bool # 是否需要转人工 confidence: float # 当前决策置信度这里有个细节值得展开messages字段用了add_messages这个 reducer意思是每次节点返回新的消息时框架会自动追加而不是覆盖。这个设计避免了手动管理对话历史的麻烦但也要注意如果某个节点需要“重写”历史比如人工坐席介入后要重置上下文就得显式处理。边的设计上条件边conditional edge是灵魂。调度节点执行完后不是固定跳转到下一个节点而是根据状态里的intent和confidence动态决定。LangGraph 里用add_conditional_edges来实现路由函数返回一个字符串框架据此选择目标节点。def route_after_dispatch(state: CustomerServiceState) - str: if state[need_human] or state[confidence] 0.6: return human_handoff if state[intent] knowledge_query: return knowledge_agent if state[intent] business_action: return business_agent return clarify_agent graph.add_conditional_edges(dispatch, route_after_dispatch)注意路由函数必须是纯函数不能在里面做网络请求或数据库查询。所有需要的信息都应该在进入路由前已经写进状态对象。我踩过的坑就是在路由函数里调了一次向量检索结果每次路由都多花几百毫秒而且因为路由可能被多次调用检索结果还不一致。2.3 状态管理与上下文传递的工程细节多智能体系统里状态膨胀是个隐蔽的杀手。对话轮次一多messages列表越来越长每次调用 LLM 都要把全部历史塞进提示词token 成本飙升不说模型注意力还会被稀释。我的处理办法是分层管理上下文。短期上下文最近3到5轮完整保留中期上下文本次会话的槽位和意图轨迹用结构化字段保存长期上下文用户历史偏好、历史工单走检索按需注入。具体实现上可以在调度节点里加一个“上下文压缩”步骤把超过阈值的早期对话用 LLM 总结成一段摘要替换掉原始消息。另一个细节是槽位slots的校验时机。不要等到调用业务 API 的时候才发现缺参数应该在澄清智能体里就做完整性校验。校验规则可以用 JSON Schema 描述这样新增业务动作时只需要加一份 Schema不用改代码逻辑。3. 从零搭建可复现的实操流程3.1 环境准备与依赖选型先把技术栈定下来。以下是我实测下来比较稳的一套组合版本号建议锁死避免依赖漂移。python3.11 langgraph0.2.x langchain0.3.x langchain-openai0.2.x fastapi0.115.x uvicorn0.32.x pydantic2.9.x redis5.0.x # 会话状态持久化 pgvector0.3.x # 向量检索也可换 Milvus/Chroma模型侧调度和澄清这类需要强推理的节点用大参数模型知识问答和话术生成可以用小参数模型或经过微调的领域模型。热词里“大模型微调”和“大模型选择”出现很多次说明大家都在纠结这个问题。我的经验是客服场景里调度和工具调用对模型的指令遵循能力要求最高这部分不要省话术润色和摘要生成可以用便宜模型效果差距不明显。向量库的选择上如果数据量在百万级以内pgvector 足够用而且能和业务库放在同一个 PostgreSQL 实例里运维成本最低。超过这个量级再考虑专用向量库。3.2 知识库构建与检索增强的落地方法知识问答智能体的效果八成取决于知识库的质量而不是模型。我见过太多团队把 PDF 直接丢进向量库就完事结果检索出来的片段驴唇不对马嘴。正确的做法是分三步走。第一步是文档预处理把 PDF、Word、网页统一转成 Markdown保留标题层级因为标题信息在切分时能作为上下文注入。第二步是语义切分不要按固定字数切而是按语义边界切——一个完整的政策条款、一个完整的操作步骤应该是一个 chunk。LangChain 里的RecursiveCharacterTextSplitter配合自定义分隔符可以做到但更推荐用基于标题层级的切分策略。第三步是元数据标注每个 chunk 打上产品线、文档类型、生效日期等标签检索时可以按标签过滤避免把过期政策检索出来。检索策略上纯向量检索在客服场景里不够用因为用户经常用产品型号、订单号这类精确词。我的方案是混合检索向量检索召回 Top 20BM25 关键词检索召回 Top 20用 RRF倒数排名融合合并后取 Top 5 送给 LLM。实测下来混合检索相比纯向量检索在包含型号和编号的查询上准确率提升明显。def hybrid_retrieve(query: str, top_k: int 5): vector_hits vector_store.similarity_search(query, k20) keyword_hits bm25_retriever.get_relevant_documents(query)[:20] # RRF 融合 scores {} for rank, doc in enumerate(vector_hits): scores[doc.id] scores.get(doc.id, 0) 1 / (60 rank) for rank, doc in enumerate(keyword_hits): scores[doc.id] scores.get(doc.id, 0) 1 / (60 rank) ranked sorted(scores.items(), keylambda x: x[1], reverseTrue) return [doc_map[doc_id] for doc_id, _ in ranked[:top_k]]提示RRF 里的常数 60 是原论文的经验值不用改。融合前要确保两个检索器返回的文档 ID 体系一致否则融合逻辑会失效。3.3 工具调用与业务系统对接的注意事项业务操作智能体要调用真实系统这里的安全边界必须划清楚。我的原则是读操作可以自动执行写操作必须二次确认。查订单、查物流这类只读接口智能体可以直接调退款、改地址、取消订单这类有副作用的操作必须生成一个确认卡片让用户点击确认确认后再执行。工具定义上用 Pydantic 模型描述参数让 LLM 通过结构化输出生成调用参数。LangGraph 里可以用ToolNode配合bind_tools实现但要注意工具描述的质量直接决定调用准确率。工具描述里要写清楚这个工具做什么、什么情况下用、参数的含义和格式、返回值的结构。我见过调用失败最多的原因就是工具描述写得太简略模型不知道什么时候该用。from pydantic import BaseModel, Field class RefundInput(BaseModel): order_id: str Field(description订单编号格式为 ORD 开头加12位数字) reason: str Field(description退款原因必须是以下之一质量问题、七天无理由、发错货、其他) amount: float Field(description退款金额单位元不能超过订单实付金额) tool(create_refund, args_schemaRefundInput) def create_refund(order_id: str, reason: str, amount: float) - dict: 创建退款工单。仅在用户明确要求退款且订单状态为已支付时调用。 # 实际业务逻辑 ...工具调用的超时和重试也要处理。业务系统响应慢是常态设置 5 秒超时超时后返回“系统繁忙请稍后重试”而不是让整个图卡死。重试只对幂等的读操作做写操作不自动重试避免重复退款。3.4 转人工流程的完整实现转人工不是简单地把对话丢给坐席就完事。完整的流程包含四个环节触发判断、状态打包、坐席分配、上下文同步。触发判断上我设置了三个条件用户连续两次表达不满、调度置信度低于阈值、用户明确说“转人工”。这三个条件任一满足就触发。注意不要只靠关键词匹配“转人工”用户可能说“我要找个人”“机器人听不懂”之类这些要靠意图识别覆盖。状态打包是把当前图状态序列化成一份结构化摘要包括用户基本信息、本次会话的意图轨迹、已收集的槽位、已执行的业务操作、检索到的关键知识片段、以及一段 LLM 生成的会话摘要。坐席看到这份摘要能在几秒内了解上下文不用翻聊天记录。坐席分配可以用简单的轮询或按技能组路由。上下文同步通过 WebSocket 或消息队列推送给坐席工作台。这里有个细节转人工后图并没有结束而是进入一个等待状态坐席的回复通过一个特殊节点注入回图里这样如果坐席解决不了又转回智能体状态是连续的。4. 上线后最容易踩的坑与排查手册4.1 意图误判与路由死循环路由死循环是多智能体系统里最典型的问题。表现是调度把任务分给澄清智能体澄清智能体追问后用户回答调度又分给澄清智能体来回循环。根因通常是澄清智能体没有正确更新槽位或者调度判断“信息是否足够”的逻辑有漏洞。排查方法是在图执行时打印每个节点的状态快照对比进入澄清前后的slots字段有没有变化。如果没变化说明澄清智能体没有正确解析用户回答。解决思路是给澄清智能体加一个槽位提取的校验步骤提取失败时换一种问法连续两次失败直接转人工。另一个常见问题是意图边界模糊。比如“我要退货”和“退货政策是什么”前者是业务操作后者是知识问答。调度智能体如果分错用户体验会很差。我的做法是在调度提示词里给每个意图配 3 到 5 个正例和反例并且要求模型输出置信度低于阈值时走澄清而不是硬猜。4.2 检索召回不准的调优路径检索不准的表现是知识库明明有答案但智能体回答“我不知道”或者答非所问。排查要按顺序来。先看切分是否合理。把检索到的 chunk 打印出来如果发现一个完整的政策被切成了两半那就是切分策略的问题。再看 embedding 模型是否匹配语种和领域中文客服场景用中文优化的 embedding 模型效果明显好于通用模型。然后看检索策略纯向量检索对精确词不敏感加上 BM25 混合检索。最后看提示词检索到的内容有没有被正确注入到生成提示词里有没有被其他指令挤掉。我整理了一份速查表遇到问题按这个顺序排查基本能覆盖九成情况。现象可能原因排查动作解决方向答非所问检索片段不相关打印 Top 5 chunk改切分策略或加混合检索回答“不知道”召回为空或阈值过高看检索得分分布降低阈值或扩充知识库答案过时检索到旧版本文档检查元数据过滤加生效日期过滤答案不完整chunk 太小看 chunk 长度增大 chunk 或加父子检索型号查不到向量检索对精确词弱测试关键词检索启用混合检索4.3 工具调用失败的分类处理工具调用失败分三类参数错误、业务拒绝、系统异常。参数错误是模型生成的参数不符合 Schema比如订单号格式不对、金额为负。这类要在工具层做校验返回明确的错误信息让模型重新生成而不是直接抛异常。业务拒绝是业务系统返回的合法拒绝比如“订单已发货不能退款”。这类要把业务系统的错误码和提示原样返回给模型让模型据此生成解释话术。千万不要把业务错误吞掉否则模型会编一个“退款成功”的假消息。系统异常是超时、连接失败这类。这类要区分读操作和写操作读操作可以重试一次写操作直接返回“系统繁忙”并记录日志人工介入。实操心得给每个工具加一个调用日志记录入参、出参、耗时、是否成功。上线初期每天看一遍失败日志能发现大量提示词和 Schema 的问题。这个习惯帮我省了至少两周的调试时间。4.4 成本与延迟的平衡技巧多智能体系统的成本主要来自 LLM 调用次数。一次用户提问可能触发调度、检索、生成、校验四次调用token 消耗是单模型方案的三到四倍。延迟也相应增加用户等待时间可能到 5 秒以上。优化手段有几个。一是模型分级调度和校验用大模型生成和摘要用小模型。二是缓存相同或相似问题的检索结果和回答缓存起来客服场景里重复问题比例很高缓存命中率能到三成以上。三是并行化检索和槽位提取可以并行执行LangGraph 支持节点并行。四是流式输出生成节点用流式返回用户看到首字的时间能缩短一半以上。延迟这块我的底线是首字响应不超过 2 秒完整回答不超过 8 秒。超过这个阈值用户就会觉得“卡”。如果业务复杂导致延迟压不下来就在等待时给一个“正在为您查询”的中间态提示体验会好很多。5. 二次开发与能力扩展的方向5.1 接入企业自有模型的改造点很多企业出于数据合规考虑要用自己部署的模型。改造点主要在 LLM 客户端的封装层。LangChain 的ChatOpenAI类支持自定义base_url只要你的模型服务兼容 OpenAI 接口协议改一个地址就能接上。不兼容的话需要自己实现一个BaseChatModel子类实现_generate和_stream两个方法。微调模型的接入要注意提示词格式。微调时用的提示词模板要和推理时一致否则效果会打折扣。热词里“大模型微调实战”和“大模型提示词工程”是关联的微调不是替代提示词工程而是补充。我的建议是先把提示词工程做到位确认瓶颈确实在模型能力上再考虑微调。5.2 多模态能力的扩展思路客服场景里图片是刚需用户经常发截图问“这个报错什么意思”“这个按钮在哪”。扩展多模态能力需要在状态对象里加一个images字段在调度节点判断是否包含图片包含的话路由到多模态理解节点用视觉模型生成图片描述再把描述注入后续流程。这块的工程复杂度主要在图片的存储和传输。建议图片走对象存储状态里只存 URL需要时再下载。视觉模型的调用成本比文本高不少要做好频率限制和缓存。5.3 从客服到全场景智能助手的演进这套架构的复用性其实很强。把领域智能体换一换调度规则改一改就能变成内部 IT 助手、HR 助手、销售助手。核心的图编排、状态管理、工具调用、转人工机制都是通用的。我在实际项目里做过一次迁移把客服系统改造成内部工单助手只花了三天——换知识库、换工具集、调调度提示词图结构基本没动。这也是我推荐这套架构的原因它给你的不是一个固定功能的成品而是一套可生长的骨架。业务变了加节点加边就行不用推倒重来。最后分享一个我在调试期常用的小技巧给图加一个“回放”模式把历史会话的状态轨迹存下来可以逐节点回放看每一步的输入输出。这个功能在排查偶发问题时特别有用因为很多问题只在特定对话路径下出现靠日志很难还原。实现上就是在每个节点包一层装饰器把状态快照写进 Redis 或本地文件回放时按顺序读出来。代码量不大但省下的调试时间是以天计的。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →