意图识别结构化输出失败如何修复
从 Prompt 工程、解码控制和微调三角度给出策略
原题:在基于大语言模型的意图识别任务中,若模型输出的结构化格式不理想,有哪些有效的优化策略?请从提示工程、解码控制和微调角度进行分析。
模型微调 · 小红书真题
回答与解析
一、提示工程层面
核心思路:给模型明确的"格式模板"和"思考空间"
- 结构化指令:用
### 输出格式 ###明确分隔,指定字段名、类型、可选值 - Few-shot示例:提供2-3个输入→推理过程→标准输出的完整样例
- 思维链引导:要求模型先分析用户意图关键词,再输出结构,减少跳步导致的格式错乱
示例框架:
用户输入:{input}
分析:用户提到"退款"和"订单号",属于售后意图
输出:{"intent": "after_sales", "confidence": 0.95, "slots": {"type": "refund"}}
二、解码控制层面
核心思路:用采样参数和API特性约束输出空间
| 策略 | 具体做法 |
|---|---|
| 降低随机性 | temperature=0~0.3,top_p=0.9,减少格式变异 |
| JSON Mode | 强制模型输出合法JSON(OpenAI/GPT-4等支持) |
| Function Calling | 预定义schema,模型只填充参数,不生成自由文本 |
| 约束解码 | 用logit_bias或grammar约束(如llama.cpp的GBNF) |
小红书场景建议:优先用Function Calling,将意图定义为工具函数,slot作为参数
三、微调策略层面
核心思路:让模型"见过"各种边界情况
数据构造:
- 正样本:覆盖口语化、省略主语、多意图等复杂输入
- 负样本:加入格式错误的输出作为对比学习(如字段缺失、类型错误)
训练配置:
- LoRA微调即可,r=64~128,target_modules包含q_proj/v_proj
- 学习率2e-4,早停监控格式合法性指标
损失设计:除next-token loss外,可加格式验证的辅助loss
四、实际落地建议
分层防御:提示工程兜底 → 解码控制约束 → 微调提升上限 → 后校验修复(JSON解析失败时fallback到规则兜底)
学习建议
建议系统学习该知识点
口语版讲法(约4分钟)
- 一句话定位:意图识别格式问题本质是输出空间控制
- 提示工程兜底:给模板和思考空间
- 解码控制:降低随机性、用Function Calling或JSON Mode
- 微调提升上限:LoRA加正负样本
- 分层防御与风险判断
这道题问的是大模型意图识别输出格式不理想怎么优化,其实本质是同一个问题:怎么在模型自由生成的文本和我们要的结构化数据之间,搭一座桥。不是让模型学会写JSON,而是让它只在我们划定的输出空间里选择。
具体我会从三个层面来拆解,先说提示工程,这是最轻量、见效最快的。核心做法是给模型一个明确的格式模板,比如用 输出格式 把字段名、类型、可选值都写清楚。再给两三个Few-shot示例,而且示例里要包含推理过程,就是让模型先分析用户输入里的关键词,再输出结构。举个例子,用户说“我要退款,订单号是12345”,你让模型先写一句分析“用户提到退款和订单号,属于售后意图”,再输出JSON。这样能大幅减少跳步导致的格式错乱。
但提示工程有个明显的边界:它管不了模型生成的随机性。同一个提示,temperature高一点就可能多出个逗号或者字段名写错。所以第二层是解码控制,说白了就是用参数和API特性把输出空间锁死。最简单的做法是把temperature调到0.1以下,top p用0.9,减少格式变异。如果模型支持JSON Mode,直接强制输出合法JSON。更推荐的是Function Calling,你把意图定义成工具函数,slot作为参数,模型只负责填充参数,根本不生成自由文本。这在小红书这类场景里非常实用,因为用户query短且意图明确,Function Calling几乎零格式错误。
第三层是微调,适合前面两层兜不住、或者需要处理大量边界情况的时候。微调的目标不是让模型变聪明,而是让它见过各种格式错误。构造数据时,正样本要覆盖口语化输入、省略主语、多意图等复杂情况;负样本要加入字段缺失、类型错误、多余字段的输出,让模型学会对比。用LoRA微调就行,r设到128,target modules选q proj和v proj,学习率2e-4,早停监控格式合法性指标。这里有个坑:微调数据里格式正确的样本和格式错误的样本比例,我一般控制在4:1左右,负样本太多会让模型过于保守,反而不敢输出。
所以真正落地的时候,我不会只押一个方案。我会用分层防御的思路:提示工程先兜底,保证90%的场景格式正确;解码控制作为第二道防线,用Function Calling或者低temperature锁死输出;微调提升处理极端输入的上限;最后再加一道后校验,JSON解析失败时用规则兜底,比如正则提取字段。这里有个前提:如果业务对格式的硬性要求极高,比如金融风控的意图识别,那Function Calling加后校验是必须的,提示工程只能当辅助。
另外,我最近在思考一个问题:当意图类别特别多、比如超过50个时,Function Calling的schema会变得很臃肿,模型反而容易混淆。这种情况下,是不是应该把意图识别拆成两步,先用模型粗分类,再针对子类用Function Calling提取槽位?这个取舍我还没完全想清楚,但感觉是个值得深挖的方向。
总的来说,我更倾向把格式优化看成一套组合拳,而不是依赖单一技巧。先分层防御,再根据业务场景调优,最后用后校验兜底。
关键一句:当意图类别超过50个时,Function Calling的schema会变得臃肿,模型容易混淆,可能需要拆成粗分类加细粒度提取两步。
面试官还可能这样问
- 问法 1 · 场景切入
假设你在做一个电商客服的意图识别,用户说‘我要退单号123的那个’,模型有时输出的是{'intent':'refund','order':'123'},有时候却乱成‘退款意图,订单号123’这种非结构化文本。你一般怎么处理这种格式不稳定问题?
- 问法 2 · 层层追问
你平时做大模型的意图识别,输出格式怎么控制?……如果提示词里给了明确模板,但模型有时候照样不听话,你还会考虑哪些手段?……除了改提示词,解码或微调层面有没有什么能做的?
- 问法 3 · 直球架构
从提示工程、解码控制和微调三个层面,讲一下大模型意图识别中结构化输出不理想时有哪些优化策略?先说提示工程怎么设计,再讲解码参数怎么调,最后说微调数据怎么构造。