尧图精选

ReAct架构实战:打造会查资料、调工具的智能客服Agent

🕒 发布时间:2026/9/16 9:33:33 📁 来源:尧图网络
很多做客服机器人的团队都有一个共同的困惑模型接进来了知识库也灌进去了但问“我的订单为什么还没发货”机器人要么答非所问要么直接甩一句“请咨询人工客服”。问题往往不是大模型不够聪明而是你只教会了它“背答案”没教会它“查资料、算结果、再回答”这一整套动作。ReAct架构解决的就是这件事它让模型在回答之前先“想一下需要什么信息”然后“调用工具去拿”最后“基于拿到的结果组织语言”。这篇文章我把从业务分析到代码实现的完整链路拆开讲清楚适合正在做智能客服落地、或者想从RAG升级到Agent方案的工程师参考。1. 动手前先想清楚智能客服的业务边界与ReAct的适用性1.1 客服系统的三类典型问答场景先别急着写代码落地一个客服系统第一步是搞清楚你的业务到底有哪些问题。我把常见客服请求归成三类每一类的技术方案完全不同。第一类是静态知识问答典型的问题比如“你们退货政策是什么”“发票怎么开”“发货一般几天到”。这类问题的特征是答案基本固定散落在官网、帮助文档、内部知识库里模型只要“找到对的文档”就能回答。传统RAG方案对这类场景足够流程是召回相关文档片段拼进上下文让模型总结。第二类是动态数据查询典型比如“我的订单到哪了”“我账户里有多少余额”“这个月话费多少”。这类问题的特征是答案不在文档里而在业务系统的数据库或API里而且通常需要带上用户身份去查。你不可能把每个用户的订单状态提前写进知识库所以必须让模型具备调接口的能力。第三类是复杂任务操作典型比如“帮我把收货地址改成XX”“取消订单”“申请退款”。这类问题不仅是查数据还要写数据涉及权限校验、风控判断、操作确认对准确率要求极高出错代价大。ReAct适合的场景主要是第二类以及第三类中偏查询和预检的部分。第一类用纯RAG更快更省第三类建议ReAct只负责收集信息和生成操作参数真正的写操作仍走人工确认或工单系统。我在实际项目中见过不少团队一上来就追求全自动取消订单结果模型参数填错引发客诉后来都老实改成确认制了。1.2 ReAct和纯RAG、纯Prompt提示之间到底差在哪RAG解决的是“模型不知道”的问题它把外部知识库检索到的内容塞进上下文模型就能回答。但RAG有个天然局限模型只能基于你喂给它的静态信息回答自己不能主动做事。用户问“订单到哪了”RAG检索不到任何文档能回答因为答案压根不存在于知识库中。纯Prompt提示则是让模型“装成客服”去回答比如在system prompt里写“你是客服要耐心友好”。这解决的是语气和风格问题但对事实准确性毫无帮助。模型的参数里没有你客户的实时数据你提示词写得再漂亮它也编不出真实订单状态。ReAct的核心是让模型在“推理”和“行动”之间循环先分析当前问题需要哪些信息然后调用工具获取信息观察工具返回结果再推理下一步怎么做直到有足够信息生成最终回答。这个“思考-行动-观察”的循环就是ReAct原文里Reasoning Acting的由来。从效果上看它把大模型从一个“背诵者”变成了一个“会用工具的思考者”这也是它和RAG、纯Prompt之间最本质的差别。1.3 为什么选ReAct而不是Agent框架全家桶现在Agent框架很多LangChain、AutoGPT、MetaGPT名字一个比一个响。很多朋友一上来就上LangChain的AgentExecutor但落地后发现问题很难排查内部prompt被框架封装死了工具调用失败的原因不好定位升级框架版本还可能改变行为。我个人的建议是客服这个场景不要迷信框架自己用几十行代码实现一个ReAct循环完全可控业务逻辑透明出问题能肉眼debug。ReAct的工程实现难度不高核心就是一个while循环加一个解析函数模型返回的内容如果是“需要调用工具”你就执行工具并把结果作为observation返回给模型如果模型觉得信息够了就让它生成最终答案。这样一套东西写下来也就一百多行核心代码但你对整个链路的理解会远超直接调框架。另外客服场景对可控性的要求很高自动调用工具涉及用户数据权限、风控、审计都得能插进链路。自己实现ReAct循环你可以在“行动”之前自由插入鉴权逻辑、敏感操作拦截、日志上报这些在抽象过的框架里做起来反而麻烦。所以我的结论是自研精简版ReAct不依赖重框架做客服Agent是性价比最高的选择。2. 架构与数据流设计把“想”和“做”拆清楚2.1 整体模块划分ReAct客服系统的整体架构可以拆成五个模块对话入口、主控循环、工具层、知识检索层、记忆与上下文管理层。对话入口负责接收用户消息和返回结果通常是FastAPI或者Spring Boot之类的服务主控循环就是ReAct的核心决定什么时候调用工具、什么时候结束工具层封装对业务系统的访问包括订单查询、物流查询、知识检索这些能力知识检索层对应RAG链路负责从文档库中召回答案素材记忆层管理多轮对话的上下文避免模型忘记前面聊了什么。数据流向是这样的用户发消息进来主控循环把“历史对话摘要当前问题工具描述列表”组装成prompt发给大模型模型第一次返回的结果有两种可能要么是“我可以直接回答了”要么是“我需要调用某个工具参数是XXX”。如果是前者直接返回用户如果是后者主控循环解析出工具名和参数调用工具层拿到结果把结果作为observation追加到上下文再次发给模型。如此循环直到模型给出最终回答或者达到最大迭代次数。这个流程里有一个关键点主控循环只负责调度不负责具体业务逻辑。工具层才是真正接触订单系统、知识库的地方。这样做的好处是职责清晰模型只需要学会“决定调用哪个工具”而不用关心工具内部怎么实现业务系统升级改造不会波及推理循环。2.2 工具集设计三类必选工具工具设计直接决定Agent的上限。我给客服Agent设计工具集时遵循一个原则每个工具只做一件简单明确的事描述写清楚什么时候用、参数是什么。模型是根据工具描述来决定调用哪个工具的描述写得含糊模型就会乱选。客服场景里有三类工具是必选的。第一类是知识检索工具输入是用户问题输出是相关文档片段主要用于回答退货政策、使用方法这类静态知识。第二类是业务查询工具比如订单查询、物流查询、会员信息查询输入通常包含用户ID或订单号输出是结构化的业务数据。第三类是操作确认类工具比如校验地址是否可配送、计算退款金额这类工具不真正改数据而是为最终回复提供判断依据。工具描述建议写成“工具名 用途 参数说明 返回值说明”四段式。举个例子一个订单查询工具的描述可以这样写工具名: query_order_status 用途: 根据订单号查询订单当前状态包括是否发货、物流单号、预计送达时间 参数: order_id (string, 必填, 用户提供的订单号) 返回值: JSON字符串包含order_id、status、tracking_number、estimated_delivery这样描述之后模型看到“我的订单到哪了”这类问题会自然联想到query_order_status并从对话里提取order_id参数。实际调试中发现模型对“何时使用”的理解往往取决于描述里的场景词所以描述里一定要包含典型用户问法比如“当用户询问订单状态、物流进度时使用”。2.3 记忆与上下文的处理方案多轮对话的记忆是ReAct落地中的一个隐蔽难点。第一轮用户问“我的订单到哪了”模型调用工具查到了结果第二轮用户紧接着说“那地址呢”这里的“地址”指的显然是订单的收货地址模型如果只看当前这一句话根本不知道在说什么。处理多轮记忆我建议做两层。第一层是短期会话级记忆直接用messages数组把历史上的用户输入、模型回复、工具调用结果都存下来每次都发给模型。这样做的优点是信息完整不丢失缺点是随着对话变长token消耗会上升而且工具调用产生的observation可能很长反而干扰模型。第二层是关键信息提取也就是在每轮对话开始前用模型或规则把当前轮需要用到的关键实体抽取出来比如订单号、用户ID、产品型号然后填进当前轮的prompt中而不是把整段历史都塞进去。实际操作中我常用一个精简摘要消息把前面几轮的意图和已获取的信息压缩成两三句话例如“用户查询了订单OD20240101的状态已查到已发货物流单号SF123456”。这样模型既知道上下文又不会被冗长的工具返回结果干扰。这里要特别提醒原始工具返回的observation不要无脑保留到多轮以后。代码实现里可以把每轮的工具结果存到一个session_data字典里后续轮次从里面取值直接拼进prompt这样能有效控制上下文长度。2.4 安全与兜底机制ReAct让模型可以调用工具这既是优势也是风险。在客服场景权限和兜底是必须提前设计好的不能等上线后出问题再补。权限控制的第一层是用户身份绑定。模型想查询订单状态不能只传一个订单号还必须传用户身份标识工具层要校验这个订单号是否属于当前用户。我见过一个案例客服机器人因为没做身份校验用户输入任意订单号就能查到别人的收货地址这是严重的越权漏洞。所以工具接口里一定要有user_id参数服务端强制校验归属关系。第二层是操作分级。查询类工具可以宽松一些只读不写基本无风险。写操作类工具比如修改地址、申请退款要做到“模型不直接执行只生成参数”真正执行前让用户明确确认或者转入工单系统人工处理。我通常给所有写操作工具名加上“Confirm”后缀让模型即使要执行也必须先走确认流程。第三层是最大迭代次数限制。ReAct循环理论上是可收敛的但实际运行中模型偶尔会陷入无限循环比如不停调用同一个工具或者反复查询同一个参数。一定要设置max_iterations我一般设为5超过就强制终止并返回兜底话术“抱歉我没能查到您需要的信息请转人工客服”。除此之外还要对所有工具调用做日志记录字段包含用户ID、时间、工具名、参数、返回摘要这样出问题才能回溯。3. 核心代码实现ReAct循环、工具注册与检索链路3.1 技术选型与依赖准备代码实现前先统一技术栈。我这次的示例用Python因为生态最全后续接LangChain或其他工具也方便。核心依赖只有三个openai用来调用大模型fastapi和uvicorn用来起服务faiss-cpu和numpy用来做向量检索。如果你所在公司的模型是通过HTTP网关暴露的也可以直接用requests替代openaiSDK不影响整体逻辑。环境准备只需一行pip命令pip install openai fastapi uvicorn faiss-cpu numpy大模型的选择上ReAct对模型的要求比普通问答要高一些模型需要能够理解工具描述、输出结构化的工具调用指令。建议选择推理能力较强、支持Function Calling的模型比如GPT-4系列、Claude 3.5、或者国产的GLM-4、Qwen-Max。如果模型不支持Function Calling也可以用“让模型输出JSON格式的工具调用指令”的折中方案我会在下面代码中给出。3.2 工具定义与注册工具层是整个系统的地基。我先定义了一个统一的工具函数签名要求所有工具接收一个参数字典返回一个JSON字符串。这样主控循环解析和处理时不需要关心每个工具的参数差异统一按字符串处理方便拼prompt。下面是订单查询和知识检索两个工具的实现示例import json import requests def query_order_status(args: dict) - str: 查询订单状态。真实场景中这里会调用业务系统的API。 order_id args.get(order_id) user_id args.get(user_id) # 实际开发时这里的请求头需要带上登录凭证服务端做归属校验 resp requests.get( fhttps://api.example.com/order/{order_id}/status, headers{X-User-Id: str(user_id)}, timeout5 ) if resp.status_code ! 200: return json.dumps({error: query failed, order_id: order_id}) data resp.json() return json.dumps({ order_id: data[order_id], status: data[status], tracking_number: data.get(tracking_number, ), estimated_delivery: data.get(estimated_delivery, ) }) def search_knowledge_base(args: dict) - str: 从知识库中检索与问题相关的文档片段。 query args.get(query) top_k int(args.get(top_k, 3)) results vector_search(query, top_k) # 3.4节实现 return json.dumps(results, ensure_asciiFalse)工具写好后需要注册到一个统一的TOOLS字典里同时把描述整理成列表喂给模型。这里的关键是描述直接决定模型的调用准确率描述语言要贴近客服业务。TOOLS { query_order_status: query_order_status, search_knowledge_base: search_knowledge_base } TOOL_DESCRIPTIONS [ { name: query_order_status, description: 当用户询问订单状态、物流进度、预计送达时间时使用。参数order_id表示订单号user_id表示当前登录用户ID。, parameters: { type: object, properties: { order_id: {type: string, description: 订单号}, user_id: {type: string, description: 用户ID} }, required: [order_id, user_id] } }, { name: search_knowledge_base, description: 当用户询问退货政策、开发票、使用方法等知识类问题时使用。参数query表示用户的原始问题。, parameters: { type: object, properties: { query: {type: string, description: 用户问题}, top_k: {type: integer, description: 返回的文档片段数量默认3} }, required: [query] } } ]3.3 大模型接入与ReAct主循环主控循环是ReAct的灵魂。我手写了一个精简版循环没有用LangChain原因前面讲过可控、易排查、不依赖框架升级。设计上每一轮循环都往messages里追加内容用户问题、可选的工具结果、以及引导模型输出的格式说明。模型输出我采用JSON格式的思考过程包含thought、action、action_input三个字段这样解析起来比纯文本更稳定。import json from openai import OpenAI client OpenAI( api_keyyour-api-key, base_urlhttps://api.example.com/v1 # 换成你们公司的网关地址 ) SYSTEM_PROMPT 你是一个智能客服Agent。你可以使用多种工具来获取信息进而回答用户的问题。 请严格按照以下JSON格式输出你的思考过程 {thought: 你分析当前情况的想法, action: 要调用的工具名如果没有需要调用的工具则为null, action_input: {参数名: 参数值}} 注意事项 1. 如果用户的问题需要查询实时数据必须先调用工具。 2. 如果工具返回结果不足以回答可以再次调用工具补充信息。 3. 如果用户的问题不需要任何工具可以在thought中写明理由action直接置为null。 4. 你最多可以调用5次工具。 def react_loop(user_message: str, session: dict): messages [ {role: system, content: SYSTEM_PROMPT}, {role: user, content: user_message} ] # session中保存历史摘要和已获取的key-value信息 if session.get(context_summary): messages.insert(1, {role: system, content: 对话历史摘要 session[context_summary]}) for step in range(5): resp client.chat.completions.create( modelgpt-4o, messagesmessages, temperature0.2 ) content resp.choices[0].message.content.strip() # 提取JSON try: start content.index({) end content.rindex(}) 1 parsed json.loads(content[start:end]) except Exception: # 模型没有输出JSON直接当成最终回答 return {reply: content, finish_reason: direct_answer} action parsed.get(action) if action is None: return {reply: parsed.get(thought, ), finish_reason: normal} # 执行工具调用 tool_func TOOLS.get(action) if not tool_func: messages.append({role: assistant, content: content}) messages.append({role: tool, content: json.dumps({error: funknown tool: {action}})}) continue # 参数中默认注入当前用户ID action_input parsed.get(action_input, {}) action_input[user_id] session.get(user_id, ) observation tool_func(action_input) # 将思考和工具结果追加到消息列表 messages.append({role: assistant, content: content}) messages.append({role: tool, content: observation}) # 超过最大步数走兜底 return {reply: 抱歉我暂时无法处理这个问题请转人工客服。, finish_reason: max_iterations}这段代码核心就一个for循环每轮做三件事给模型发消息解析模型输出如果是工具调用就执行并把结果追加回来。值得注意的有两点一是模型输出虽然要求JSON但实际返回时可能带前后缀文字所以用截取{}的方式做容错解析二是在参数注入时把当前用户ID塞进action_input避免模型漏传身份信息。3.4 RAG检索与知识库构建知识检索工具对外的接口很简单但内部需要提前构建好向量索引。构建路径是文档切块、向量化、存入FAISS索引。我直接用了一个轻量化的实现方式避免引入过重的服务组件。import numpy as np import faiss def build_knowledge_index(documents: list[str], embed_func): 将文档列表向量化并构建FAISS索引。 documents: 文档片段列表 embed_func: 文本转向量的函数返回list[float] vectors [embed_func(doc) for doc in documents] dim len(vectors[0]) index faiss.IndexFlatIP(dim) # 内积相似度 index.add(np.array(vectors).astype(float32)) return index, documents def vector_search(query: str, top_k: int 3): q_vec np.array([embed_func(query)]).astype(float32) distances, indices index.search(q_vec, top_k) results [] for idx in indices[0]: results.append({content: documents[idx], score: float(distances[0][0])}) return results这里有一个工程细节要说明IndexFlatIP用内积做相似度计算前提是你的embedding模型已经做了归一化或者直接用余弦相似度。如果embedding没有归一化内积会被向量长度干扰导致检索结果不准确。我踩过这个坑后来统一在embedding之后做L2归一化检索质量稳定了很多。另外文档切块的大小直接影响检索效果。切得太粗一个块里混杂多个主题召回后噪声大切得太细语义信息不完整模型也难以利用。我实测下来按300到500字切成一块相邻块保留约50字重叠在中文客服文档场景下效果比较均衡。具体切分可以用langchain_text_splitters的RecursiveCharacterTextSplitter也可以自己用正则按段落切后者更可控。3.5 多轮对话状态管理多轮状态我用一个简单的SessionStore来管理内存中维护会话ID和session数据的映射。session里保存了三类信息用户的提问历史、模型的回答历史、以及已经查到的工具结果摘要。import uuid from datetime import datetime class SessionStore: def __init__(self): self.sessions {} def create_session(self, user_id: str): session_id str(uuid.uuid4()) self.sessions[session_id] { user_id: user_id, created_at: datetime.now().isoformat(), history: [], context_summary: , tool_results: {} } return session_id def get_session(self, session_id: str): return self.sessions.get(session_id) def update_summary(self, session_id: str, new_summary: str): # 更新摘要保持简洁超过3轮就把更早的信息压缩掉 session self.sessions[session_id] session[context_summary] new_summary当对话超过三轮我会调用一次大模型把context_summary和最近的往返压缩成一段新的摘要替换掉旧的。这一步用模型做摘要效果远好于直接截断消息。你可能会觉得这样会多一次模型调用成本变高但对客服场景来说准确理解上下文比节省一次模型调用的成本重要得多。3.6 用FastAPI将对话能力暴露成服务本地跑通react_loop函数之后把它包一层HTTP接口就可以联调了。我用FastAPI写了一个/chat接口请求体包含session_id和用户消息响应体返回Agent的回复。接口层还加了简单的鉴权逻辑生产环境中这里应该接公司的统一登录体系。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() store SessionStore() class ChatRequest(BaseModel): session_id: str user_message: str user_id: str class ChatResponse(BaseModel): session_id: str reply: str finish_reason: str app.post(/chat, response_modelChatResponse) def chat(req: ChatRequest): if not req.session_id: session store.create_session(req.user_id) session_id session[session_id] if isinstance(session, dict) else session session_id req.user_id _ session_id if False else session_id else: session_id req.session_id session store.get_session(session_id) if session is None: # 会话过期重建 session store.create_session(req.user_id) session_id session[session_id] if isinstance(session, dict) else session_id result react_loop(req.user_message, session) # 更新session历史 session[history].append({role: user, content: req.user_message}) session[history].append({role: assistant, content: result[reply]}) return ChatResponse( session_idsession_id, replyresult[reply], finish_reasonresult[finish_reason] ) if __name__ __main__: import uvicorn uvicorn.run(app, host0.0.0.0, port8000)启动之后用几行测试代码就可以快速验证链路curl -X POST http://localhost:8000/chat \ -H Content-Type: application/json \ -d {session_id: , user_message: 我的订单OD20240101到哪了, user_id: U12345}如果一切正常你会在返回里看到Agent先调用query_order_status拿到物流信息再生成自然语言回答。4. 部署之外的细节把Agent从“能跑”变成“可用”4.1 日志设计每一轮推理都要能回放ReAct系统的调试难度比普通FAQ机器人高很多因为同样的用户问题模型在不同上下文下可能做出不同决策。如果没有完整的日志线上出问题只能靠猜。我强烈建议从第一天就把日志做好。日志至少要记录以下几类信息用户消息、系统生成的prompt、模型每步的输出、工具名和参数、工具返回结果、最终回复、每轮耗时的token数。一个推荐的做法是将每次请求的完整ReAct轨迹单独存成一个JSON文件或一条文档记录字段包括trace_id、session_id、timestamp、steps数组。steps数组里按顺序记录每一步的模型输出和工具调用结果。这样出了问题用trace_id一条命令就能回放全过程。成本层面日志还要记录模型调用次数和token汇总。ReAct一个明显的特点是单次对话模型调用次数变多了普通RAG一次问答可能只要一次模型调用而ReAct往往要两到五次。如果之前没有预估月底看账单容易吓一跳。上线前最好统计一下线上平均调用次数并把token成本纳入指标监控。4.2 效果观测准确率、兜底率和工具失败率客服机器人的效果不能只凭感觉要定义清晰的指标。我常用的有三个知识命中率也就是模型回答中引用检索结果的占比工具调用成功率指工具函数执行成功的比例业务系统报错、参数缺失都算失败兜底触发率也就是触发人工转接的比例。前两个指标越高越好最后一个指标要控制在合理范围内太说明Agent处理不了问题太低说明Agent可能在不懂装懂。还有一个容易被忽略的指标是用户纠偏率。用户在一轮回答后又追问“不是这个意思”“我指的是XXX”说明模型理解错了意图。这个指标可以通过分析会话内第二轮问题是否包含否定词来粗略统计值太高意味着意图识别和工具选择需要优化。4.3 知识库更新与工具扩展知识库不是建好就一劳永逸的。业务政策每个月都可能变比如退货时长从7天改成15天如果索引里的文档没有及时更新模型就会按旧政策回答并引发客诉。我给知识库设计了一个简单的更新流程运营人员提交新文档后台校验格式、自动切块、生成向量、加入索引同时标记旧版本失效。整个过程类似一个“发布”操作可以做成管理后台的功能而非每次改代码。工具层的扩展也类似新增一个工具时只需要写函数、注册描述、做一轮评估测试核心代码无需改动。这也是把工具注册和主控循环解耦带来的直接收益。5. 落地过程中常见问题与排查记录5.1 模型反复调用同一个工具不收敛这个问题我在调试中遇到过很多次。典型表现是模型已经拿到了工具结果但下一步仍然继续调用同样的工具循环到超最大次数。排查思路主要是看observation中的返回内容是否对模型“有用”。如果工具返回的是大段JSON但关键信息淹没在其中模型就会觉得“信息不够”继续调。解决方法是精简工具返回值比如订单查询只返回关键字段并附加一句“该订单已查到最终状态无需再次查询”。还有一种做法是在system prompt里加一条规则如果工具返回结果与上次完全相同直接基于已有信息回答。5.2 检索不到知识导致模型乱答知识库召回率低是另一个高频问题。用户问“你们能不能开专票”知识库里明明有但检索召回的前三段都是别的发票相关的内容模型就没有用到正确文档。除了调embedding模型和切块策略之外一个很实用的技巧是在检索工具返回结果时将文档标题也拼进去提升关键信息的判别度。比如每条检索结果都带“文档标题发票说明”模型更容易定位到相关性。另外如果检索结果的相关度分数普遍很低可以让模型直接回答“这个问题我暂时无法确认请咨询人工”而不是硬答。5.3 对话历史污染推理当上下文里积累了过多早期工具调用的observation时模型容易被干扰表现为答非所问。我的处理方式是定期做消息压缩用一次模型调用来生成对话摘要替换掉历史明细。实测中摘要压缩后ReAct的准确率不降反升因为模型终于把注意力集中在当前目标上了。下表是几种常见异常模式的快速排查对照异常现象常见原因排查建议模型不调用工具直接瞎答工具描述不够明确检查描述中是否有典型问法示例工具被调用但参数解析错误参数名与工具描述不一致检查prompt中的参数名是否与代码一致循环调用工具不终止observation信息不足或重复简化返回值增加“无需再次查询”提示检索结果不相关切块策略或embedding不匹配调切块大小检查归一化多轮后回答漂移上下文过长干扰决策做消息摘要压缩保留关键实体5.4 模型输出JSON格式不稳定部分模型对复杂指令的遵循能力不足输出的JSON里会混入解释性文字。我用了“截取首尾花括号”的容错解析能解决大部分问题。如果解析仍然失败可以在提取JSON失败后把模型上一次输出作为错误信息回传让模型自我修正。如果模型本身不支持JSON模式也可以改用XML或纯文本标记的方式来描述工具调用比如用toolquery_order_status/toolargs.../args包裹。解析虽然稍麻烦一点但很多开源模型对这种格式的遵循度反而更高。你可以用小样本集同时测试两种格式选准确率更高的那一种。5.5 生产环境排障工具最后分享一个实用的排障小工具做一个基于trace_id的对话轨迹查看页。把每轮对话的thought、action、action_input、observation、最终回复全部打印出来。对于客服场景这个功能的价值甚至高于模型调优因为老板和运营在接收到客诉后半小时之内就需要看清机器人到底哪里做错了。我现在带的团队没有这个查看页不会让客服Agent上线。6. 从ReAct再往前走一步ReAct落地智能客服最核心的收益是让大模型从“背知识”升级为“用工具”。它不算复杂一个循环加几个工具函数就能跑通真正的难点在业务拆解和工程细节比如权限校验、日志回放、知识更新、兜底策略这些才是决定线上效果的东西。我在实际落地中最大的体会是不要指望模型一步到位做对所有的工具调用而要把每一条工具返回结果、每一次模型误判都当成优化素材持续去调工具描述的措辞和observation的返回形式。跑起来只需要一个下午调好用可能要一两周但后者才决定用户是满意还是转人工。这套方案后续还能扩展的方向很多比如在工具层接入更多业务接口做售后自动化或者在记忆层引入用户画像做个性化应答底层架构都不用动这也是ReAct思路最大的价值。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →