跳到正文

LLM 封闭标签方法对比

封闭标签分类的 Prompt、约束解码、后处理和微调对比

原题:假设你有一个通用大语言模型(LLM),希望将其应用于封闭集合标签分类任务(如情感分类、意图识别等),有哪些有效的方法可以确保模型输出严格限定在预定义标签范围内?请比较不同方法的优劣。

RAG基础

30 秒回答

  1. 方法全面性(至少覆盖3种以上方法)
  2. 方法原理清晰,能讲清"如何限制输出"
  3. 优劣对比有实际考量(如延迟、准确率、灵活性)
  4. 提及工程落地细节(如缓存、并发)

回答与解析

答案要点

  • 方法全面性(至少覆盖3种以上方法)
  • 方法原理清晰,能讲清"如何限制输出"
  • 优劣对比有实际考量(如延迟、准确率、灵活性)
  • 提及工程落地细节(如缓存、并发)

核心方法对比

1. 提示工程 + 输出解析(最简单)

  • 做法:Prompt里明确列出可选标签,要求模型单选;用正则/规则过滤非法输出
  • 优点:零改造成本,快速验证
  • 缺点:不可靠,模型可能幻觉、格式不统一;需兜底逻辑

2. Function Calling / Tool Use(推荐)

  • 做法:定义工具schema,强制模型输出结构化JSON(如{"label": "positive"}
  • 优点:输出格式严格可控;主流模型(GPT-4、Claude、Qwen等)原生支持
  • 缺点:模型需支持该能力;旧模型/小模型可能不支持

3. 约束解码(Constrained Decoding)

  • 做法:在解码阶段限制每一步只能生成合法token序列,如用FSM、CFG或Outlines、Guidance等库
  • 优点理论上100%保证合法性,无需后处理;适合高合规场景
  • 缺点:实现复杂,可能增加推理延迟;需修改推理引擎(如vLLM的guided decoding)

4. 分类头微调(SFT/LoRA)

  • 做法:加线性层映射到标签空间,改为传统分类任务
  • 优点:输出绝对可控,延迟低,小模型也适用
  • 缺点:失去LLM的通用性;需标注数据训练

选型建议

场景 推荐方案
快速验证/原型 提示工程 + 解析
生产环境、模型支持 Function Calling
强合规、零容忍错误 约束解码
极致性能、标签固定 分类头微调

实际落地常组合使用:Function Calling为主,约束解码兜底关键路径。

口语版讲法(约4分钟)

  • 本质问题:如何让生成模型变成分类模型
  • 方案一:提示工程,快但不可靠
  • 方案二:Function Calling,生产首选
  • 方案三:约束解码,万无一失但代价高
  • 方案四:微调,极致性能但通用性差
  • 落地组合与风险

这道题其实问的是,怎么把一个通用生成模型硬掰成分类模型,让它只输出我们想要的那几个标签。我做过一些落地,聊一下我的思路。

先说最简单的,提示工程加输出解析。就是在Prompt里把可选标签全列出来,告诉模型只能选一个,然后后面用正则或者规则把输出兜住。这个方案的好处是零改造成本,你甚至不用微调,拿个Prompt就能跑。但说实话,它非常不可靠。模型可能自己造个标签出来,或者格式乱七八糟,你解析的时候就得各种兜底。所以它只适合快速验证或者Demo,真正上线我不太敢只用它。

真正生产环境我比较推荐Function Calling。大部分主流模型,像GPT-4、Claude、Qwen这些都原生支持。你定义一个工具schema,比如{"name": "classify", "parameters": {"type": "object", "properties": {"label": {"type": "string", "enum": ["positive", "negative"]}}}},模型就必须输出一个结构化的JSON,格式上完全可控。而且它还能跟后续的业务逻辑无缝衔接,比如直接解析出标签去触发动作。不过有个前提,就是你的模型得支持这个能力,有些老模型或者小模型可能不行,那就得换方案。

再一个方案是约束解码。这个理解起来很简单,就是在模型生成每个token的时候,用有限状态机或CFG去限制它只能走合法的路径。比如标签只有positive和negative,那模型生成完posi之后,下一个token只能接tive,不能接别的。理论上它能100%保证合法性,而且不需要后处理。但代价也大,实现起来很复杂,得改推理引擎,像vLLM的guided decoding,而且会增加延迟。所以它适合那种零容忍错的场景,比如金融风控,你绝对不能输出一个不存在的标签。

最后一个方案是分类头微调。把LLM的最后一层换成线性层,直接映射到标签空间,本质上变成了传统分类模型。这样输出绝对可控,延迟也低,小模型就能跑。但代价是你失去了LLM的通用性,而且需要标注数据。所以它适合那种标签固定、数据量够、对延迟要求极高的场景,比如电商客服的退款原因分类,几毫秒就要出结果。

实际落地我很少只用一种方案,往往是组合使用。比如主链路用Function Calling,因为它兼顾了可控性和灵活性,但我会在关键路径上加约束解码做兜底,防止模型偶尔抽风。或者对于一些高频但简单的分类,我会用微调好的小模型,只有复杂情况才调大模型。

这里有个坑,就是Function Calling的枚举值如果太长,模型可能会出错。比如你有几百个标签,放在enum里,模型可能生成不存在的值或者干脆不输出。所以我会做分层,先粗分类再细分类,或者用检索增强的方式,让模型只从候选子集里选。

另外,约束解码虽然好,但跟KV Cache的兼容性是个问题。因为动态限制token选择,会破坏缓存,导致推理速度下降明显,这个在线上部署时是需要特别关注的。

所以整体上,我更倾向于把Function Calling作为默认方案,然后根据业务场景的延迟和准确率要求,决定要不要加约束解码或者微调。没有银弹,就是权衡。

关键一句:约束解码与KV Cache的兼容性问题会导致推理速度下降

面试官还可能这样问

  1. 问法 1 · 场景切入

    假设你做一个电商客服的意图识别,用户说“我想退换货”,你希望模型只输出“退货”、“换货”、“咨询”这几个标签之一。你一般怎么确保模型不会乱说一个不在列表里的词?

  2. 问法 2 · 层层追问

    用大模型做分类任务,你通常是怎么让模型输出固定标签的?……如果模型输出了不在列表里的内容怎么办?……那如果业务要求零错误,比如风控场景,你怎么保证输出绝对合规?

  3. 问法 3 · 直球架构

    给定一个预定义的标签集合,要求LLM输出严格限定在其中。请列出几种实现方案,并对比它们在可控性、延迟、开发成本上的优劣。你会怎么选型?

同模块相关题目