跳到正文

LLM 封闭标签如何强约束?

提示工程、解码约束与微调三种手段对比

原题:假设你有一个大型语言模型(LLM),希望其输出严格限定在一个预定义的封闭标签集合内,应采用哪些技术手段(如提示工程、解码约束、微调等)来确保输出的准确性和一致性?

模型微调

30 秒回答

  1. 提示工程(Few-shot + 格式约束)是基础手段
  2. 约束解码(Constrained Decoding)是核心保障
  3. 微调/SFT提升指令遵循能力
  4. Function Calling/JSON Schema是工程实践标准方案

回答与解析

答案要点

  • 提示工程(Few-shot + 格式约束)是基础手段
  • 约束解码(Constrained Decoding)是核心保障
  • 微调/SFT提升指令遵循能力
  • Function Calling/JSON Schema是工程实践标准方案
  • 后处理校验作为兜底机制

核心思路

封闭标签输出本质是可控生成问题,需多层防护:提示工程 → 模型能力 → 解码约束 → 后处理校验。


技术手段(按优先级)

1. 提示工程(基线)

  • Zero-shot:明确指令 + 标签列表 + "只能从以下选择"
  • Few-shot:提供输入→标签的示例,稳定输出格式
  • 加格式约束:"输出必须是以下之一:[A, B, C],不要解释"

2. 约束解码(强保障)

  • 原理:在解码每一步,只保留合法标签token的logits,非法token概率置-∞
  • 实现:用FSM(有限状态机)或CFG(上下文无关文法)定义合法输出空间
  • 工具:Outlines、Guidance、lm-format-enforcer等库
  • 优势:100%保证输出合法性,不依赖模型"自觉"

3. Function Calling / JSON Schema(工程标准)

  • OpenAI/Claude等原生支持,强制输出符合预定义schema
  • 底层即约束解码实现,但API封装易用
  • 适合标签需附带置信度、理由等结构化场景

4. 微调/SFT(能力强化)

  • 构造指令-标签数据对,训练模型指令遵循能力
  • 配合LoRA高效微调,适合领域标签(如医疗诊断分类)
  • 注意:单独SFT无法100%保证封闭性,需配合解码约束

5. 后处理校验(兜底)

  • 正则匹配提取标签,非法输出fallback到默认/重试
  • 多标签场景用投票或一致性检查

选型建议

场景 推荐方案
快速验证 Few-shot + 后处理
生产部署 Function Calling / 约束解码库
领域定制 SFT + 约束解码双层保障
动态标签 约束解码(无需改模型)

口语版讲法(约4分钟)

  • 一句话定位:封闭标签输出本质是可控生成问题
  • 提示工程:基线手段但不够可靠
  • 约束解码:核心保障,保证100%合法
  • 微调与后处理:辅助和兜底
  • 选型取舍与风险提醒

这道题其实问的是,怎么让大模型输出严格限定在我们指定的几个标签里,比如客服场景里,用户问退款问题,模型只能输出“退款中、已退款、退款失败”这几个状态,不能自由发挥。这本质上是可控生成问题,我有几层手段,从轻到重,但真正落地的时候,我不会只依赖一层。

先说提示工程,这是最基础的。我会在系统提示里明确给出标签列表,加上类似“只能从以下选择,不要解释”的指令。再给几个例子,就是 Few-shot,让模型模仿。但说实话,这层只能管住大部分情况,模型还是可能跑偏,尤其面对复杂表述或者对抗性输入时,它可能会自己发明一个标签。所以提示工程只是基线,不能当唯一保障。

再一个,约束解码,这是核心。原理很简单:在模型生成每一步,只保留合法标签对应的 token 概率,其他 token 的概率直接置成负无穷。比如标签是“退款中”和“已退款”,那模型生成“退”之后,下一个 token 只能是“款”,不能是别的。这能 100% 保证输出合法,因为它从解码层面就锁死了。实现上可以用 有限状态机 或者上下文无关文法来定义合法输出空间,有现成的库比如 Outlines、Guidance。生产环境我一般会用这层做主力。

然后微调,也就是 SFT,可以提升模型对指令的遵循能力。比如我收集一批指令-标签对,让模型学会在特定格式下输出。但注意,单独微调也不能保证百分之百,尤其模型没见过的新变体。所以我会把微调和约束解码结合起来,微调让模型更听话,约束解码兜住最后的底线。

另外还有 Function Calling,现在很多模型原生支持,你给它一个 JSON Schema,它必须输出符合 schema 的结构。底层其实就是约束解码,但 API 封装得很好用。如果标签还需要附带置信度或者理由,这个方案就特别合适。

最后是后处理校验,用正则匹配提取标签,如果匹配不到就 fallback 到默认标签或者重试。这层是兜底,不能依赖它,但加上去能提高鲁棒性。

选型上,我的经验是分场景。快速验证,用提示工程加后处理就够了。生产部署,我会优先用约束解码库或者 Function Calling,因为可靠性高。如果领域很特殊,比如医疗诊断分类,我还会加一层微调,让模型更理解领域语义。另外有个前提:标签集必须是静态且有限的,如果标签动态变化,那约束解码就比微调灵活得多,因为不需要重新训练模型。

这里有个常见失败场景:你用了约束解码,但模型第一个 token 就生成了非法字符,比如空格或者标点,那解码器可能直接卡住。所以我会在约束文法里允许一些空白和标点前缀,或者用更宽松的规则先过滤。还有,如果标签本身有歧义,比如“退款中”和“退款处理中”语义相近,模型可能混淆,那就需要靠微调或者更好的标签设计来区分。

另外,如果标签集特别大,比如上千个,约束解码的性能会下降,因为每一步要过滤的 token 太多。这时候我会考虑用分层标签,先输出大类再输出小类,或者用向量检索先缩小候选集,再让模型从候选中选。这其实变成了检索加精排的思路。

所以总的来说,我的做法是多层防护:提示工程打底,约束解码做核心保障,微调提升能力,后处理兜底。具体用哪几层,取决于你对可靠性的要求、标签的规模和动态性。我更倾向于在解码层下功夫,因为它最可控,不依赖模型“自觉”。

关键一句:当标签集非常大时,约束解码性能可能下降,需要分层或检索辅助。

面试官还可能这样问

  1. 问法 1 · 场景切入

    假设你做电商客服,需要把用户问题分类到“售后/物流/退货”等十几个固定类别里,怎么确保LLM只输出这些标签,不会乱说别的?

  2. 问法 2 · 层层追问

    让LLM输出固定标签,你一般怎么做?……如果模型偶尔输出不在集合里的词怎么办?……有没有办法从解码层面强制它只生成合法标签?

  3. 问法 3 · 直球架构

    设计一个系统,要求LLM输出严格限定在预定义的封闭标签集合内,你会从提示工程、解码约束、微调、后处理这几个层面分别怎么设计?优先级怎么排?

同模块相关题目