ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于Solon ReActAgent构建智能工单处理系统:从原理到实践

基于Solon ReActAgent构建智能工单处理系统:从原理到实践 1. 从“人工分拣”到“智能路由”为什么我们需要AI Agent来处理工单如果你在任何一个有客服团队的公司待过或者自己处理过用户反馈你肯定对下面这个场景不陌生每天成百上千条工单像雪花一样涌进来内容五花八门——“我的订单没收到”、“App闪退了”、“发票怎么开”、“我想投诉某个功能”……客服同学需要像高速运转的分拣机快速阅读、理解、然后手动将工单拖拽到对应的处理队列技术、财务、客诉、产品。这个过程我们称之为“工单路由”。这个活儿听起来简单做起来却全是坑。首先它极度依赖个人经验。一个新来的客服可能分不清“支付失败”是该归技术排查还是该归财务核对退款。其次用户表达千奇百怪。一句“你们的东西坏了”可能是物理损坏物流售后可能是软件Bug技术也可能是不会用用户运营。最后也是最要命的——枯燥和疲劳。重复的、高强度的文本分类工作很容易让人精神涣散导致分错、漏分。一个本该技术紧急处理的崩溃问题被分到了普通咨询池可能几小时后才被捞起来用户体验直接跌到谷底。所以我们一直想把这个“人工分拣”的环节自动化掉。早期的思路是基于关键词规则工单里出现“崩溃”、“闪退”就分给技术出现“退款”、“发票”就分给财务。这方法在初期有效但很快就不够用了。用户不会按你的词典说话他们会说“App一打开就黑屏然后自己关了”这是闪退或者说“钱付了但没看到订单能把钱退我吗”这需要技术先查单再触发财务。规则越写越复杂维护成本极高还总有覆盖不到的“长尾问题”。直到大模型和AI Agent技术成熟我们看到了彻底解决这个痛点的曙光。大模型LLM拥有强大的自然语言理解能力能像人一样读懂用户的“言外之意”而AI Agent框架比如我们今天要深入讨论的Solon AI ReActAgent则提供了将这种理解能力转化为具体、可执行、可追溯的“动作”的蓝图。它不再是被动的分类器而是一个主动的“虚拟坐席”能理解、思考、决策并调用工具去完成任务。简单说我们想实现的不是一个简单的文本分类器而是一个能真正“读懂”工单并自动完成“理解-分析-决策-执行”全流程的智能体。这不仅能将客服人力从重复劳动中解放出来更能实现秒级的精准路由和预处理大幅提升问题解决效率和用户满意度。下面我就结合Solon框架下的ReActAgent来拆解如何一步步将这个构想落地。2. 技术选型为什么是Solon ReActAgent当我们决定用AI Agent来改造工单系统时技术栈的选择就成了第一个关键决策。市面上相关的框架和概念很多比如LangChain、LlamaIndex以及各种云厂商提供的AI工作流。最终我们锁定了Solon框架及其ReActAgent模块这不是盲目跟风而是基于几个非常实际的工程化考量。2.1 核心诉求轻量、高效、易集成我们的工单系统是典型的Java技术栈Spring Boot日均处理十万级工单对响应延迟和系统稳定性有苛刻要求。因此Agent框架首先要“轻”不能引入过重的依赖和复杂的架构其次要“快”思考-行动循环的延迟必须可控最后要“顺”最好能与现有Java技术栈无缝融合降低学习和集成成本。许多流行的Python系Agent框架如LangChain功能强大但生态庞大通过HTTP服务集成会引入额外的网络开销和运维复杂度。而Solon本身就是一个高性能的Java全栈开发框架其Solon AI模块是“原生”的Java实现。这意味着ReActAgent可以直接运行在咱们的JVM里内存数据交互避免了序列化/反序列化和网络IO的损耗这在追求低延迟的工单处理场景下是决定性的优势。2.2 ReAct模式契合工单处理的思考逻辑ReActReasoning Acting是让AI Agent变得“智能”的关键范式。它让模型不只是生成文本回答而是模仿人类的思考过程先推理Reasoning再行动Acting根据行动结果再进一步推理形成循环。这个模式完美匹配工单处理流程。比如收到工单“付了钱没看到订单”推理用户的核心诉求是“订单状态异常”可能涉及支付系统和订单系统。需要先确认支付是否成功再查询订单。行动调用【支付查询接口】传入用户ID和交易号。推理接口返回支付成功。那么问题可能出在订单生成环节或页面显示。行动调用【订单查询接口】按支付单号查询。推理接口返回订单存在且状态正常。那么可能是前端缓存或用户操作问题。行动调用【通知接口】给用户发送一条包含订单号的提示消息并建议其刷新页面或检查“我的订单”列表。最终响应将整个推理过程和结果摘要作为工单的初步处理备注。你看这个过程不是一步到位的分类而是一个动态的、基于事实的排查链路。Solon的ReActAgent为我们提供了实现这一模式的清晰编程模型。2.3 Solon AI的生态与生产就绪度Solon框架在Java社区以高性能和简洁著称Solon AI模块虽然相对较新但其设计理念一致强调契约化接口和插件化扩展。对于工单处理场景我们需要接入内部多个系统的API用户中心、订单、支付、物流这些都可以被封装成标准的“工具”Tool通过简单的注解或配置注册到ReActAgent中供其调度调用。此外生产环境离不开可观测性。我们需要知道每个工单被Agent处理时它“想”了什么推理链做了什-么调用了哪些工具输入输出是什么。Solon ReActAgent内部提供了清晰的执行链路日志可以方便地对接我们的监控和审计系统这对于问题回溯和效果优化至关重要。注意技术选型时切忌被“热闹”的功能迷惑。对于企业内部系统集成尤其是对延迟敏感的场景运行时的轻量级、与主技术栈的亲和度、以及对核心模式如ReAct的清晰实现往往比“全能”更重要。Solon AI ReActAgent在这几点上做到了很好的平衡。3. 构建智能工单处理Agent的核心步骤确定了技术栈接下来就是动手搭建。整个过程可以分解为几个核心步骤我会结合代码片段和配置细节来说明。假设我们有一个最简单的工单模型包含工单ID、用户ID、问题描述和当前状态。3.1 环境准备与依赖引入首先在你的Solon应用可以是Spring Boot兼容模式的pom.xml中引入必要依赖。核心是solon.ai模块同时我们需要一个具体的大模型API客户端这里以国内常用的通义千问为例你也可以替换为OpenAI、DeepSeek等。dependency groupIdorg.noear/groupId artifactIdsolon.ai/artifactId version2.7.0/version !-- 请使用最新稳定版本 -- /dependency dependency groupIdorg.noear/groupId artifactIdsolon.ai.cloud.qianwen/artifactId !-- 通义千问云服务适配器 -- version1.0.0/version /dependency !-- 其他如数据访问、Web等依赖根据你的项目现有情况添加 --接着在app.yml或application.yml中配置模型连接。这里的关键是保护好你的API Key。solon.ai: cloud: qianwen: api-key: ${QIANWEN_API_KEY:你的API密钥} # 强烈建议从环境变量读取 model: qwen-max # 根据需求选择模型qwen-max综合能力强qwen-turbo更快3.2 定义工单处理的“工具”ToolsReActAgent的强大在于能调用工具。对于工单处理我们需要将内部系统的能力封装成工具。每个工具都是一个Java方法用Tool注解标记。Solon会自动发现并注册它们。假设我们有三个核心系统用户服务、订单服务、支付服务。import org.noear.solon.ai.annotation.Tool; import org.springframework.stereotype.Component; Component // 确保被Spring管理 public class TicketTools { // 工具1查询用户基本信息 Tool(name get_user_info, description 根据用户ID查询用户基本信息包括注册时间、等级等。) public UserInfo getUserInfo(Tool.Param(用户ID) String userId) { // 这里应该是调用用户服务的RPC或HTTP客户端 // 模拟返回 return userServiceClient.getUserById(userId); } // 工具2根据订单号查询订单状态 Tool(name get_order_status, description 根据订单号查询订单的详细状态如待付款、待发货、已完成、已取消等。) public OrderStatus getOrderStatus(Tool.Param(订单号) String orderNo) { return orderServiceClient.queryOrder(orderNo); } // 工具3根据支付流水号查询支付结果 Tool(name get_payment_result, description 根据支付流水号查询支付是否成功、支付方式、金额和时间。) public PaymentResult getPaymentResult(Tool.Param(支付流水号) String paymentId) { return paymentServiceClient.queryPayment(paymentId); } // 工具4发送一条内部处理备注模拟Agent执行动作 Tool(name add_ticket_remark, description 为当前处理的工单添加一条处理备注。) public String addTicketRemark(Tool.Param(工单ID) String ticketId, Tool.Param(备注内容) String remark) { ticketService.addRemark(ticketId, AI Agent, remark); return 备注添加成功; } // 工具5将工单路由到指定部门队列 Tool(name route_ticket_to, description 将工单路由到指定的处理部门或队列。) public String routeTicketTo(Tool.Param(工单ID) String ticketId, Tool.Param(目标队列) String targetQueue) { ticketService.updateQueue(ticketId, targetQueue); return 工单已路由至队列: targetQueue; } }3.3 组装ReActAgent并设计提示词Prompt有了工具我们需要创建ReActAgent的实例并给它一个清晰的“任务说明书”也就是系统提示词System Prompt。这个提示词决定了Agent的思考范式和边界。import org.noear.solon.ai.ReActAgent; import org.noear.solon.ai.ReActAgentFactory; import org.noear.solon.ai.models.LLM; import org.noear.solon.ai.models.openai.OpenAiModel; import org.noear.solon.annotation.Component; import org.noear.solon.annotation.Inject; Component public class TicketAgentService { Inject private LLM llm; // 由Solon AI根据配置自动注入的模型客户端 private ReActAgent ticketAgent; Init // Solon的初始化注解 public void init() { String systemPrompt 你是一个智能工单处理助手。你的任务是分析用户提交的工单描述通过调用工具获取必要信息经过推理后决定如何处理该工单。 处理方式包括 1. 添加分析备注将你的推理过程和发现的事实通过add_ticket_remark工具记录到工单。 2. 自动路由如果问题明确属于某个部门如技术、财务、客诉、物流使用route_ticket_to工具将工单转到对应队列。 3. 直接回复如果问题简单已有明确结论如告知用户操作步骤可以直接在最终响应中给出答案。 你必须遵守以下规则 - 每次思考后必须调用一个工具不能连续思考。 - 优先使用get_user_info、get_order_status、get_payment_result等工具查询信息再做出判断。 - 如果工单描述中缺少必要参数如订单号且无法通过用户信息查询到则在备注中说明“需要用户补充订单号”。 - 对于无法明确判断或涉及重大投诉如“我要举报”、“法律诉讼”的工单路由到“人工高级客服”队列。 - 你的所有操作和推理都必须通过工具留下记录。 ; this.ticketAgent ReActAgentFactory.builder(llm) .systemPrompt(systemPrompt) .maxIterations(10) // 防止无限循环 .build(); } }这个提示词非常关键它定义了Agent的角色、目标、可用动作和规则。其中maxIterations限制了ReAct循环的最大次数防止在复杂或异常情况下陷入死循环。3.4 实现工单处理流程最后我们创建一个服务方法接收原始工单交给Agent处理并返回处理结果。public TicketProcessResult handleTicket(String ticketId, String userInput, String userId) { // 1. 准备Agent的初始上下文。我们可以把工单ID、用户ID等信息作为初始输入。 String initialInput String.format( 工单ID%s 用户ID%s 问题描述%s 请开始处理。 , ticketId, userId, userInput); // 2. 执行ReActAgent String agentResponse ticketAgent.chat(initialInput); // 3. 解析并包装结果 TicketProcessResult result new TicketProcessResult(); result.setTicketId(ticketId); result.setAgentResponse(agentResponse); // 这里包含Agent的最终总结 // 可以从Agent的执行日志中提取出它实际调用的工具和路由决定更新到工单实体 // 例如通过监听或拦截器获取工具调用记录 result.setFinalQueue(determineFinalQueueFromAgentActions()); // 4. 记录完整的交互链思考行动到数据库或日志系统用于审计和优化 logAgentExecutionChain(ticketId, agent.getExecutionChain()); return result; }到这里一个最基础的智能工单处理Agent的骨架就搭建完成了。它已经能够“读懂”用户描述自主调用工具查询信息并根据规则做出路由决策或添加备注。4. 从Demo到生产关键细节与避坑指南把Demo跑通只是第一步要让这个Agent真正在生产线稳定、高效地工作还有大量的细节需要打磨。下面是我在实践过程中总结的几个关键点和踩过的坑。4.1 工具设计的“粒度”与“容错”最初我们设计工具时犯了一个错误工具太“粗”。比如我们做了一个handle_order_issue的工具期望Agent直接把订单问题描述传进去这个工具内部再去调用五六个子服务。结果发现Agent经常无法正确使用这个复杂工具或者工具内部一个子调用失败整个工具就失败了Agent也不知道如何回退。心得工具应该设计得“小而专”一个工具最好只做一件事并且有清晰、稳定的输入输出。就像get_order_status输入订单号返回状态对象。这样有几个好处第一Agent更容易理解和调用第二单个工具失败不影响整个链路Agent可以尝试其他路径第三便于测试和监控。同时每个工具必须有强大的容错能力。内部RPC调用可能超时、返回异常码。工具方法内部必须捕获这些异常并返回一个结构化的错误信息而不是抛出异常导致Agent会话崩溃。例如Tool(name get_order_status, description ...) public OrderStatusResult getOrderStatus(Tool.Param(订单号) String orderNo) { try { return orderServiceClient.queryOrder(orderNo); } catch (ServiceTimeoutException e) { return new OrderStatusResult(null, ERROR, 订单服务查询超时请稍后重试或联系人工客服。); } catch (Exception e) { log.error(查询订单状态异常, e); return new OrderStatusResult(null, ERROR, 系统暂时无法获取订单信息。); } }4.2 提示词工程用“规则”约束“想象力”大模型很有想象力但这在工单处理中可能是灾难。比如用户说“我心情不好因为订单没到”模型可能开始调用工具查询“用户心情”服务或者生成一段安慰的话。这偏离了我们的核心目标。因此提示词必须足够具体和具有约束性。我们的经验是明确指令用“必须”、“只能”、“优先”等词。如“你必须优先调用以下工具查询信息...”。定义清晰边界告诉它什么不能做。如“禁止对用户进行情感安慰禁止生成与问题解决无关的闲聊内容”。提供范例Few-Shot在提示词中给出几个正确处理的例子。这对于规范输出格式、教会它使用工具特别有效。结构化输出要求如果希望Agent的最终响应是特定格式比如JSON直接在提示词中说明。4.3 成本、延迟与流式响应直接使用云上大模型API每一次Agent的“思考-行动”循环都可能产生Token消耗。一个复杂的工单可能需要多轮循环成本不可忽视。优化策略包括选择性价比模型对于路由这类任务不一定需要最顶级的模型。qwen-turbo或ernie-speed这类速度优化模型在保证基本理解能力的前提下成本更低、响应更快。设置思考深度限制maxIterations不要设置过高一般5-10轮足够处理大多数工单。对于未能在限制内解决的自动降级到人工。缓存与索引对于一些频繁查询的静态信息如产品常见问题解答可以将其向量化后存入本地向量数据库如Milvus。Agent可以先尝试从本地索引中搜索相似问题和解决方案搜索无果再调用模型推理。这能大幅减少对大模型的依赖和等待时间。延迟方面除了选择快模型还要关注工具调用的并行化。如果Agent需要先后调用用户服务和订单服务而这两个服务之间没有依赖可以考虑在工具层面支持异步调用或者由Agent并行发起这需要框架或提示词的支持。4.4 可观测性与持续迭代Agent不是“黑盒”绝不能把Agent当成一个部署完就完事的黑盒。我们必须能看清它的“思考过程”。全链路日志记录每一次用户输入、模型的每一次“思考”Reasoning、每一次工具调用输入、输出、耗时、以及最终响应。这不仅是审计需要更是我们优化提示词和工具的核心依据。关键指标监控自动解决率工单被Agent处理后无需人工介入直接关闭的比例。准确路由率Agent路由的工单与事后人工复核认为路由正确的比例。平均处理时长从工单创建到被Agent完成预处理添加备注或路由的时间。工具调用错误率各个工具调用失败的比例帮助发现下游系统接口问题。建立评估与反馈闭环定期抽样一批工单由资深客服评估Agent的处理是否合理。将评估结果好/坏以及原因作为新的数据可以用于微调模型如果你有足够的计算资源和数据可以对基础模型进行微调让它更懂你的业务。优化提示词发现某一类问题总是处理不好就在提示词里增加针对性的规则或例子。增补工具发现Agent总是“想”做某件事却没有工具就开发一个新工具。5. 超越路由Agent在客服场景的进阶想象当基础的工单路由稳定运行后我们可以探索更深入的智能化应用让AI Agent从“分拣员”升级为“初级客服代表”。5.1 自动信息收集与补全很多工单之所以流转慢是因为信息不全。用户只说“订单有问题”客服需要反复追问“订单号是什么”“手机尾号多少”。我们可以让Agent主动发起追问。实现思路在ReAct循环中当Agent发现执行某个工具缺少必要参数如调用get_order_status需要订单号而通过已有信息用户ID也无法关联出订单时它可以中断当前的任务链转而调用一个ask_user_for_info的工具。这个工具会向用户端通过工单系统回复、短信或应用内推送发送一条结构化的追问消息并将对话状态挂起。待用户回复后再将新信息注入继续之前的处理流程。这相当于实现了多轮对话的工单处理。5.2 基于知识库的自动解答对于大量重复的咨询类工单如“如何修改密码”“运费是多少”理想状态是直接由Agent从知识库中找到答案并回复用户实现“秒级关单”。技术整合这需要将向量数据库如Milvus, Weaviate与ReActAgent结合。当工单进来后先走一个“快速判断”分支用嵌入模型Embedding Model将用户问题向量化在知识库向量中搜索最相关的几条答案。如果相似度超过一个很高的阈值比如0.95且答案置信度高则直接调用add_ticket_remark和reply_to_user工具结束工单。如果相似度不高或问题复杂则再进入常规的ReAct推理流程。这构成了一个“检索增强生成RAG 自主智能体”的混合架构。5.3 情感识别与预警升级虽然我们禁止Agent进行情感安慰但可以让它识别用户情绪用于优先级调度。例如用户描述中充满“非常生气”、“投诉到底”等词汇即使问题本身可能不复杂也应被标记为高优先级或直接路由到“客诉专家”队列。实现方式可以在工单进入Agent流程前加一个轻量级的“情感分析”预处理步骤。使用一个专门的情感分析模型或调用大模型的相应能力快速判断文本的情绪极性积极、中性、消极、愤怒和紧急程度。将这个结果作为元数据Metadata附加到工单上下文中Agent在推理和路由时可以将其作为一个重要参考因素。这比让Agent在思考过程中自己去分析情绪更高效、更可控。5.4 与人类客服的协同工作流AI Agent不应该完全取代人工而是作为超级助手。设计好人机协同的流程至关重要。前置处理Agent对所有工单进行第一轮处理完成信息补全、基础问答、精准路由。这能过滤掉可能30%-50%的简单工单。辅助坐席对于需要人工处理的复杂工单Agent可以将自己之前的推理过程、查询到的相关信息如用户信息、订单快照、支付记录整理成清晰的摘要直接展示在客服工作台的侧边栏。客服一眼就能看到关键信息无需再手动去多个系统查询极大提升了人工处理效率。事后学习客服在处理完一个复杂工单后可以有一个“一键优化”按钮。如果客服发现Agent之前的处理有误或不足可以修正并提交。这个修正案例可以自动进入我们前面提到的评估反馈池用于持续优化Agent。从简单的路由到复杂的协同AI Agent在客服场景的落地是一个循序渐进的工程。它不是一个“魔法开关”而是一个需要精心设计、持续喂养数据和迭代优化的系统。用Solon ReActAgent作为技术底座给了我们一个清晰、可控、高性能的起点让这场效率革命得以在Java技术栈中稳步推进。
返回列表