通用模型负责生成回复、Xing4.0-29B-Intent 负责判定意图

文章导读
要不要在通用模型之外再加一个 Xing4.0-29B-Intent,判断标准不是模型数量,而是意图判错的代价会不会以不可挽回的方式带进最终回复。只要对话里存在两条以上真正的分支动作——转人工、查订单、发起退款、追问补全——意图判定就值得单独成一个环节;如果只是单轮闲聊或固定栏目问答,所有输入最终都走同一段生成逻辑,拆开的收益通常低于多维护一套服务的成本。拆开之后,通用模型只对一段已经确定意图的话负
📋 目录
  1. 壹 把一次对话拆成意图判定和回复生成两个环节
  2. 贰 限定意图判定环节只吃必要上下文
  3. 叁 分别看两种失败的代价
  4. 肆 给判定环节单独设计兜底分支
  5. 伍 排出串行调用的顺序与超时处理
A A

要不要在通用模型之外再加一个 Xing4.0-29B-Intent,判断标准不是模型数量,而是意图判错的代价会不会以不可挽回的方式带进最终回复。只要对话里存在两条以上真正的分支动作——转人工、查订单、发起退款、追问补全——意图判定就值得单独成一个环节;如果只是单轮闲聊或固定栏目问答,所有输入最终都走同一段生成逻辑,拆开的收益通常低于多维护一套服务的成本。拆开之后,通用模型只对一段已经确定意图的话负责,判定环节用更小、更快的模型控制分支走向,两者职责不同,失败代价也不同,兜底必须分开设计。

适用场景:对话存在多条可执行分支,需要稳定的分流、转人工或业务动作判定。操作动作:把意图判定从通用模型里拆出来,只喂当前轮文本和少量必要字段,输出受限意图标签加置信度;通用模型只在既定意图下生成措辞。验证方式:按 trace id 在日志里对齐“意图标签、置信度、走的分支、最终回复”,看判错样本落在哪一类兜底。风险边界:多一套服务就多一次超时和一次版本变更,必须预先定义判定失败不阻断回复的降级路径。

把一次对话拆成意图判定和回复生成两个环节

先划边界,再决定拆不拆。判定环节回答的是“这句话要去哪条路”,生成环节回答的是“在这条路上怎么说”。两者对延迟的容忍度不一样,这也是它们适合分成两次调用的主要原因。

环节输入输出可接受的延迟量级
Xing4.0-29B-Intent 判定当前轮用户文本、渠道或页面来源、登录态、已确认槽位、上一轮意图标签单一意图标签、置信度、可选槽位补全结果通常要求与生成首包同一量级,不宜让用户先等判定再等回复;具体数值需结合部署和网络确认
通用模型生成意图标签、用户原文、必要会话摘要、业务口径提示自然语言回复,或流式片段几百毫秒到数秒可被接受,流式首包更敏感

这张表的作用是让你能对外解释:为什么判定环节的输出必须是结构化的、字段少的,而生成环节可以自由发挥。只要判定输出不是一个有限的标签集合,兜底分支就无从设计。

限定意图判定环节只吃必要上下文

判定被带偏,多数不是模型不行,而是输入里塞了不该塞的东西。整段会话拼进去,上一轮助手的长回复、推荐话术、营销文案会强烈影响分类结果,尤其是用户只回了一个“嗯”“好的”的时候。

  • 建议送进判定:当前轮用户文本、渠道或页面来源、登录态或用户类型、会话中已确认的关键槽位、上一轮意图标签。
  • 建议剔除:历史助手回复全文、营销与推荐话术、系统角色提示词、超长会话的全量拼接。
  • 截断策略:用户文本按字符数截断,保留开头和结尾,不要只留开头。

剔除前后的对比要留下可查记录,最省事的做法是在判定日志里直接标出本次用了哪些字段,同名会话跑两版输入,比较标签是否变化。

{
  trace_id: 'a1b2c3',
  intent: 'order_query',
  confidence: 0.71,
  intent_input_fields: ['user_text','channel','login_state','last_intent'],
  intent_input_version: 'slim_v2',
  intent_status: 'ok'
}

intent_input_version 是这条记录的关键,没有它就无法说明“标签变了是因为输入变了还是模型变了”。切换输入版本时,建议先双跑一段时间再切主路径。

分别看两种失败的代价

判定环节值得单独做,是因为它的错误在时间和位置上都可控,而生成环节的错误往往要等用户反馈才暴露。

通用模型负责生成回复、Xing4.0-29B-Intent 负责判定意图
失败类型下游影响发现时间差异
判错意图错误进入分支:该转人工没转、该查单走了闲聊;生成环节会把错误意图“合理化”,用户需要二次纠正才能回到正轨较早。意图标签在调用后立即落地,按分支统计和低置信度样本就能看出异常
生成跑偏意图正确但措辞、事实、口径出错,例如政策表述、金额说明、承诺范围;这类问题不会触发任何分支异常较晚。通常要等用户投诉、抽检或人工复核才发现

结论很直接:判定环节的错误靠日志和阈值就能前置拦截,生成环节的错误只能靠抽检和口径约束收敛。把判定单独拆出来,本质是给自己加一个可观测的前置闸门;如果这个闸门在你的业务里没有分支可拦,那就不必拆。

给判定环节单独设计兜底分支

兜底要写在判定之后、生成之前,让判错不至于原样进入回复。三类分支各有触发条件,不要用同一个阈值糊在一起。

  1. 低置信度转人工:置信度低于设定阈值,或 top1 与 top2 的差值过小,或意图落在高风险集合(退款、投诉、账号申诉)。动作是进入人工队列,回复用固定话术模板,不交给通用模型自由组织。
  2. 追问补全:意图大类可判但槽位不足,或输入过短无法区分分支。动作是让通用模型生成一句追问,明确问缺失的那一项,不执行任何业务动作。
  3. 默认分流:判定超时、返回非法标签、服务报错。动作是落到安全默认意图(通用咨询),标记 degraded,回复照常生成,不阻塞会话。
# 可替换示例:阈值按自己的日志分布调,不要直接照抄
intent:
  timeout_ms: 800          # 超过即走默认分流
  confidence_threshold: 0.6
  margin_threshold: 0.15   # top1 与 top2 差值下限
  high_risk_intents: [refund, complaint]
  fallback_intent: general_consult

这些阈值先用可观测的初值上线,再按 intent_status 和 confidence 的分布回调;不要在没有日志分布的情况下直接定死。

排出串行调用的顺序与超时处理

顺序是串行的:预处理 → 判定 → 分支 → 生成 → 记录 → 返回。判定在生成之前,但判定失败不能把整条链路卡住。

用户输入
  → 预处理(脱敏、截断、取必要字段)
  → 调用 Xing4.0-29B-Intent(timeout_ms 上限)
      ├─ 成功且置信度足 → 进入对应分支,调通用模型生成
      ├─ 低置信度      → 追问补全 / 转人工模板
      └─ 超时或非法返回 → 默认意图 + 通用模型生成,intent_status=degraded
  → 写 trace(intent、confidence、status、input_version)
  → 返回回复

几个执行细节值得固定下来:

  • 判定超时后不在同一请求内重试,重试会叠加延迟;把超时计数交给监控,靠整体指标判断是否需要扩容。
  • 判定结果作为可空入参传给生成:为空或非法时,提示词里走通用口径,回复照常输出。
  • 调用前先用白名单校验返回标签,避免模型输出自由文本直接当分支键使用。
  • 降级请求单独打标,便于事后区分“本来就该这么答”和“因为判定失败才这么答”。
# 调用骨架,字段名按自己的接入方式替换
resp = intent_client.classify({
  'text': user_text,
  'channel': channel,
  'login_state': login_state,
  'last_intent': prev_intent
}, timeout_ms=800)

intent = resp.get('intent')
if intent not in ALLOWED_INTENTS:
    intent, status = FALLBACK_INTENT, 'degraded'

reply = chat_model.generate(intent=intent, text=user_text, style=policy_style)
log(trace_id, intent, resp.get('confidence'), status)

验证方式很朴素:在预发或测试环境分别制造一次正常判定、一次低置信度、一次超时,确认三条路径都能返回回复,并且日志里的 intent_status 各不相同。如果超时那次会让用户看到空白或报错,说明降级还没有真正接上。