"诱导取消相关问题"的排查功能
通过 AI 分析司乘通话录音文本,自动判断司机是否存在诱导用户取消订单的行为。
整体架构概览
意图识别:区分用户是想查"诱导取消"还是其他问题。
Agent 初始化:加载针对风控场景的 System Prompt 和专用工具。
ReAct 推理循环:AI 获取订单信息 -> 获取通话记录 -> 对照四级风险标准进行判定。
算法对比(特色):在 AI 给出结论的同时,后台会调用传统算法模型进行判责,并打印对比日志用于优化 AI 效果。
详细流程与代码细节
第一阶段:意图识别 (Intention Recognition)
模型选择:使用 Qwen-Turbo。参数设置:temperature=0.1。
为什么这么设:意图识别要求极高的稳定性,必须准确区分 INDUCED_CANCEL 和 INVOICE 等意图,不允许 AI 发挥创意。
Prompt 约束:INTENTION_PROMPT 明确要求只返回枚举名称(如 INDUCED_CANCEL),禁止输出解释性文字,便于程序直接解析。
第二阶段:Agent 核心初始化 (InducedCancelAgent.init())
模型选择:Qwen-Max (ModelTypeEnum.QWEN3_MAX)。
为什么用 Max:通话记录通常包含大量口语、方言甚至噪音,需要极强的语义理解能力来识别"暗示性"话术。
工具注册:
1、查询订单基础信息(如订单状态、是否已取消)。
2、核心工具,查询司乘通话的 ASR(语音转文字)结果。
拦截器:
作用:这是一个自定义拦截器,专门捕获 通话记录文本 工具的返回结果。
为什么需要:为了在不重复调用工具的情况下,将通话文本提取出来传给后端的"传统算法模型"进行对比验证。
钩子限制:限制最大模型调用次数8次(防止死循环)。限制最大工具调用次数20次。
第三阶段:ReAct 推理与判定
角色设定:专业的配送风控分析师。四级风险分类标准(判定的核心依据):
1、司机诱导取消:明确或暗示用户取消(如"你取消吧"、"我送不了")。
2、假接通:接通后长时间沉默或无有效语义。
3、司机个人原因:因吃饭、上厕所、收车等自身原因无法配送。
4、没油没电:因电量/油量不足导致无法配送。
排除条件(硬约束):
如果用户先提出非合规要求(如要求拍视频),司机说"取消",则不算诱导。
如果司机说明困难但明确表示"马上过去",则不算风险。
为什么这么设:通过显式的"排除情形",防止 AI 误判正常的业务沟通为违规。
执行步骤:
1、Thought:AI 思考:"要判断是否诱导取消,我必须先听到他们说了什么。"
2、Action:调用 通话记录和订单详情
3、Observation:获取到一段长长的对话文本。
4、Thought:AI 逐句分析司机发言,对照"四级风险标准"。
例:司机说"我在充电,要等半小时",命中"没油没电"类别,且不满足"马上过去"的排除条件。
Final Answer:按照 OUTPUT_SCHEMA 输出结构化结论。
第四阶段:算法对比与日志
1、从拦截器中取出 AI 刚刚调用的通话记录文本。
2、提取订单号 orderId,调用算法判责服务
3、对比打印:将 AI 的结论(如"存在诱导取消")与传统算法模型的结论(如"高风险")打印在同一行日志中。
为什么这么做:
灰度验证:在传统算法已经上线的情况下,通过对比日志观察 AI 的准确率。
数据回流:如果 AI 和算法结论不一致,人工可以介入标注,用于后续微调模型或优化 Prompt。
第五阶段:结果反馈
总结:"诱导取消"功能的核心在于**"规则驱动的语义分析"。它不仅仅是一个简单的问答机器人,而是一个内置了复杂业务规则(四级风险、排除条件)的风控专家。通过引入拦截器对比机制**,该项目还实现了 AI 与传统算法的并行验证,为后续的模型迭代提供了宝贵的数据支持。
"发票问题排查"功能
通过 AI Agent 自动诊断用户遇到的发票申请失败、开票超时或状态异常等问题。该功能基于 Spring AI Alibaba 的 ReAct (Reasoning + Acting) 模式,结合了动态上下文组装和多工具协同工作。
整体架构
接入层:钉钉 Stream 长连接接收 @机器人 的消息。
路由层:HSF 服务入口进行意图识别,判断是否为"发票排查"场景。
上下文组装层:从 Diamond 配置中心读取业务规则,动态组装 Prompt。
Agent 核心层:QueryInvoicesAgent 执行 ReAct 推理循环,调用工具获取数据。
反馈层:将排查结论通过钉钉消息返回给用户。
第一阶段:消息接入与意图识别
触发点:用户在钉钉群聊中 @机器人 提问(例如:"帮我查一下订单 123456 为什么开不出票")。
意图识别:区分用户是想查"发票问题排查"问题。
模型:使用 Qwen-Turbo(轻量、快速)。
参数:temperature=0.1(追求稳定性,确保分类准确)。
目的:区分用户是想"查发票"、"查物流"还是"闲聊"。
路由分发:如果意图是 INVOICE,则进入发票排查流程,组装上下文。
第二阶段:动态上下文组装
读取配置,注入业务规则,加载 PROMPT。
内容:包含"订单过期判定标准"(如:下单超过 7 天未开票算过期)、"反幻觉约束"(禁止 AI 编造订单状态)。
组装 Final Prompt:将 <用户问题> + <可用数据源描述> + <业务规则> 拼接成完整的 System Prompt。
第三阶段:Agent 核心初始化
模型选择:Qwen-Max (ModelTypeEnum.QWEN3_MAX)。
参数设置:temperature=0.7(允许一定的创造性思维来尝试不同的排查路径)。
工具注册 (FunctionToolCallback):
1、查询订单基础信息(CP代码、下单时间、订单状态)。
2、查询 SLS 日志(获取报错堆栈、TraceId)。
3、本地计算逻辑,判断是否超过开票时效 + 获取服务商名称和对应的钉钉支持群。
第四阶段:ReAct 推理循环 (QueryInvoicesAgent.call())
这是整个功能的核心,AI 会按照 "思考-行动-观察" 的循环逐步排查:
1、Thought (思考):AI 分析用户问题:"用户想知道为什么开不出票,我需要先查订单详情,看看是哪个 CP 的,以及下单时间。"
2、Action (行动):AI 选择工具:查询订单详情和状态。
3、Observation (观察):工具返回结果:{服务商id: "CP001", gmtCreate: "2026-05-01", state: "FINISHED"}。
4、循环推理:Thought:"查到是 CP001,下单时间是 5月1日,现在 6月5日,超过 30 天了。根据规则,可能已经过期了。我再调 isInvoiceExpired 确认一下。"
5、Action:调用 isInvoiceExpired。
6、Observation:返回 true(已过期)。
7、Thought:"既然已过期,那就不需要查日志了,直接给出结论:订单已过开票时效。"
8、Final Answer (最终结论):AI 生成 Markdown 格式的结论,包含:结论、风险类型、分析过程、订单状态。
第五阶段:结果反馈
将 AI 生成的 Markdown 结论通过钉钉 API 发送回群聊。
为什么这么设:确保用户能在原聊天窗口直接看到排查结果,形成闭环。
总结
"发票问题排查"功能的核心在于**"分层治理"**:
用轻量模型做分流(意图识别);用重型模型做推理(ReAct Agent)。
用工具链(Tools)连接外部真实数据(订单库、SLS)。
用钩子(Hooks)和规则(Prompts)控制边界和安全。