@dzhulgakov: Jev 炙手可热:人们没有意识到许多分类任务并不需要前沿的 LLM。您可能还没有…
摘要
这篇文章描述了一种实用方法,通过使用令牌概率来微调大语言模型,将其作为校准分类器,从而以最小的计算资源实现具有成本效益的分类任务。
查看缓存全文
缓存时间: 2026/09/21 17:42
Jev 近来风头正劲:许多人并未意识到,许多分类任务根本无需使用前沿大语言模型
你可能还未意识到:仅需几分钟和 2 美元,就能为你自己的任务构建一个专用 Jev
https://t.co/niyYCJbzHx
如何用 2 美元将你的 LLM 变成一个校准分类器
来源:https://fireworks.ai/blog/Finetuning-LLMs-as-Classifiers 大语言模型并不仅限于开放式生成。一个非常常见的生产用例是分类,即模型必须从少量类别中做出选择——并且关键在于,为每个类别返回概率(置信度)。
在本文中,我们介绍一种调整和部署用于分类任务的 LLM 的实用方法。该方法建立在现有的模型训练和推理基础设施之上,并基于对训练过程中类别概率如何自然产生的理论分析。这些概率随后可用于下游应用——例如排序和事件预测——或直接用作置信度估计。
在许多实际场景中,训练所需的预算出人意料地低——通常仅需几美元的计算成本。
为何使用 LLM 进行分类?
大语言模型经过训练以预测下一个词元——但许多实际应用根本不需要自由形式的文本。相反,它们归结为做出离散决策:从多个选项中选择一个标签、一个意图或一条路径。
例如:
- •安全与审核:允许 vs. 禁止的内容。
- •路由与分诊:决定将消息发送给团队 A、B 还是 C。
- •意图分类:识别用户是需要账单帮助还是想取消订阅。
- •领域特定标记:分配医疗代码、法律类别或文档类型。
在这些场景中,关键输出不仅是类别本身——而是每个类别的概率。这些概率驱动着阈值设定、排序和下游决策。
这之所以特别有趣,是因为 LLM 本身已经对词元建模了概率。挑战在于,如何重新解释或调整这些词元概率,使其成为校准良好的类别概率,同时不放弃模型的通用性。
为分类调整 LLM
有多种方法可以将生成模型转变为分类器。它们在模型修改程度、训练栈或推理接口上有所不同。
添加分类头
一种传统方法是将语言模型头替换为一个小型分类器——一个在汇集的隐藏表示上训练的线性或 MLP 层。这会产生一个干净的、在标签空间上的 softmax,并与经典的深度学习设置自然集成。然而,它改变了模型架构,这意味着需要重新训练、新的导出,并且常常与标准推理栈或托管 API 不兼容。
使用词元作为类别
一种更优雅的路径是保持架构完全不变。每个类别被映射到一个或多个词元(例如,“yes” / “no”、“positive” / “negative”、“0” / “1”)。通过精心设计的简短提示,使模型用这些词元之一作为响应,下一个词元的分布就变成了类别概率分布。
这种方法有几个优点:
- •无需更改架构——与标准微调和推理 API 无缝协作。
- •经济高效且稳健——尤其适用于中小规模标签集。
- •可解释性强——词元选择通常与人类语义一致,使调试更容易。
当然,词元化细节很重要:前导空格、大小写或多词元类别可能会轻微扭曲映射。当多个词元代表一个类别时,需要聚合它们的概率。但在实践中,这些问题都是可管理的——而且其收益远超复杂性。
对于大多数生产环境设置,这种方法提供了在现有 LLM 基础设施上部署分类模型的最简洁路径:无需新的分类头,无需自定义服务代码,只需仔细的提示设计和校准。此外,这种方法与标准的微调方法(如监督微调 SFT 和强化学习 RL)完全兼容,允许无缝使用现有的后训练平台。
标签概率与校准
让我们聚焦于不修改模型架构、而是利用词表来表示类别的方法。一旦我们将每个类别映射到一个词元,模型的下一个词元概率就有效地成为了类别概率。但要使这些概率有用——用于排序、阈值设定或下游决策逻辑——它们需要被校准,即应反映真实的似然性。
校准
首先,让我们形式化校准的含义。对于类别 c,定义聚合校准为:
calibration,其中 p_{i,c} 是模型对样本 i 上类别 c 的预测概率,y_{i,c} ∈ {0,1} 是 one-hot 标签,N 是评估数据集中的样本总数。
- •Calib(c) ≈ 1:预测概率质量与真实频率匹配(良好的校准)。
- •Calib(c) > 1:模型对于类别 c 过于自信。
- •Calib(c) < 1:模型不够自信。
(你也可以监控标准指标,如 ECE 或 Brier 分数,但这个聚合比率在迭代过程中是一个简单、可操作的信号。)
获取类别概率
假设每个类别 c 由一个单独的词元 t_c 表示。当模型被提示使其下一个词元应为类别词元时,它会为词表中的每个词元 t 产生一个 log 概率 log P(t | context)。
原则上,我们只关心类别词元的概率——让我们将这些词元记作 C。挑战在于 softmax 的归一化跨越整个词表——因此分配给无关词元的概率质量可能会扭曲类别概率。为了生成校准的类别概率——我们将其记作 \hat{p}_c,我们需要对它们进行重新归一化:
然而在实践中,一旦模型针对分类任务进行了微调,这种重新归一化就变得不必要了。如附录所示,微调目标隐式地重新平衡了词元概率,使得 \hat{p}_c ≈ p_c。也就是说,即使类别数量相对于词表大小非常小,原始的下一个词元概率也已经表现得像校准后的类别概率。
实用技巧
- •提示至关重要:如果模型未经微调,请通过精心设计的提示(例如,“只用‘yes’或‘no’回答”)约束其只输出单个词元,并使用 logit 偏置或解码约束来抑制非标签词元。
- •微调有帮助:一旦微调完成,模型自然会将概率质量集中在标签词元上——无需特殊的推理逻辑。
- •注意词元化:一些分词器包含前导空格(例如,“ yes”而不是“yes”)。在训练或评估之前,务必检查哪些词元 ID 对应你的标签。
实验验证
为了从经验上验证这些想法,我们训练了一个分类模型,并在整个训练过程中跟踪了其准确率和校准度。
我们使用了 AG News (http://groups.di.unipi.it/~gulli/AG_corpus_of_news_articles.html) 数据集,该数据集包含被标记为四类之一的短新闻摘要:世界、体育、商业和科技。对于基础模型,我们使用 LoRA 微调了 Qwen3-4B,实现了高效的监督适应,而无需修改模型的架构或推理栈。在 Fireworks 平台上,使用该数据集训练的总成本约为 2 美元。
在训练过程中,每个批次都在预留样本上进行评估:我们在每次权重更新前计算标签准确率和聚合校准度。这确保了校准是在未见过的数据上测量的,而不是在当前小批次上。
结果证实了先前的假设:即使我们保持模型的语言建模头不变——即不重新归一化类别词元概率——校准度也自然收敛到 1.0。换句话说,标准的微调设置足以直接从模型的原生词元分布产生校准良好的类别概率。
图 1:每个训练批次的校准度和准确率。准确率定义为当前批次中被正确分类的样本比例。
代码示例
当类别映射到单个词元时,你可以使用标准的推理 API 直接获取它们的概率——无需修改架构。
虽然大多数闭源模型提供商不暴露词元级别的概率,但像 Fireworks 这样的开源和面向开发者的平台完全提供了这一功能。这允许你按照上述方式精确计算校准的类别概率。
下面是一个最小化的示例,展示了如何查询托管在 Fireworks 上的模型并提取分配给每个类别词元的概率:
import math
import os
from openai import OpenAI
client = OpenAI(
api_key=os.getenv("FIREWORKS_API_KEY"),
base_url="https://api.fireworks.ai/inference/v1",
)
model = "accounts/fireworks/models/deepseek-v3p1-terminus"
categories = ["yes", "no"]
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "Is the sky high? Answer yes or no."},
]
# 获取带有 logprobs 的响应
response = client.chat.completions.create(model=model, messages=messages, logprobs=True)
# 提取匹配的词元
matches = []
for choice in response.choices:
if choice.logprobs and choice.logprobs.content:
for idx, token_info in enumerate(choice.logprobs.content):
if token_info.token.lower() in categories:
matches.append(
{
"position": idx,
"token": token_info.token,
"logprob": token_info.logprob,
}
)
assert len(matches) == 1, f"Expected 1 category, got {len(matches)}"
# 打印结果
for match in matches:
prob = 100 * math.exp(match["logprob"])
print(f"Category '{match['token']}' probability: {prob:.1f}%")
"""
示例输出:
Category 'Yes' probability: 97.4%
"""
未进行微调?使用嵌入 API
如果你无法(或不想)微调模型,你仍然可以使用 Fireworks 的 /v1/embeddings (https://docs.fireworks.ai/guides/querying-embeddings-models#using-the-%2Fembeddings-endpoint) 端点从任何基础模型获取归一化的类别概率。
无需拉取完整词表的 logprobs 并在客户端重新归一化,你可以:
- •提供输入文本和一小批标签词元 ID。
- •调用嵌入端点,设置 return_logits=true 和 normalize=true。
服务器仅计算这些标签词元的 logits,并在该子集上应用 softmax,返回在你的类别上总和为 1 的概率分布。这让你可以重用本文中的“词元作为标签”的想法,而无需任何微调或自定义推理逻辑——只需一次嵌入 API 调用。
附录:为什么在微调时不需要重新归一化
设 V 为词表,C 为类别词元。对于具有目标标签词元 c ∈ C 的特定输入 x,模型输出 z ∈ R^{|V|} 和概率 p = softmax(z)。
我们分析在学习率 η 下使用梯度下降时,目标类别 c 与任何非类别词元 j ∉ C 之间的 logit 间隔 Δ_j^t = z_j^t - z_c^t 的动态变化。交叉熵损失的梯度暗示了以下更新:
z_c^{t+1} = z_c^t + η(1 - p_c^t), z_j^{t+1} = z_j^t - η p_j^t.
我们定义间隔 Δ_j^t = z_j^t - z_c^t。该间隔的更新规则为:
Δ_j^{t+1} = Δ_j^t - η(1 + p_j^t - p_c^t).
注意,1 - p_c^t = Σ_{k ≠ c} p_k^t。由于 j 是这些非目标词元之一,我们知道 1 - p_c^t ≥ p_j^t。
因此:
1 + p_j^t - p_c^t ≥ 2 p_j^t.
这意味着在模型为词元 j 分配非零概率的每一步,间隔 Δ_j^t 至少减少(变得更负)2η p_j^t。
p_j^t = e^{z_j^t} / Σ_k e^{z_k^t} < e^{z_j^t} / e^{z_c^t} = e^{Δ_j^t}.
随着 Δ_j → -∞,概率 p_j 被迫趋于 0。因此,概率质量完全集中在类别词元 C 上,使得 Σ_{c ∈ C} p_c → 1。因此,在微调后,显式的重新归一化变得不必要。
快速入门
准备好开始训练了吗?我们的监督微调和强化微调文档将一步步引导你如何在自己的数据上调整基础 LLM。更喜欢视频?查看我们的快速入门演练,观看完整的训练流程演示。
相似文章
Jev 不是 LLM 杀手,也不仅仅是一个分类器。我们将其部署于生产环境并与真实用户一起使用。以下是我们学到的经验。
文章分享了使用 Jev(一个语义决策引擎)的生产见解,它通过与 LLMs 并行高效处理常规决策来增强 AI 代理系统,而不替代生成模型。
热门观点:Jev有趣之处不在于它是一个分类器,而在于我们一直将LLM用作极其昂贵的if/else语句
作者认为,Jev及其类似的分类器之所以有趣,并非因为其新颖性,而是因为它们突显了LLM常被用于简单的决策任务,建议采用更高效的架构,使用较小的模型进行路由和评估。
@cjzafir: 垂直语言模型(VLMs)正在击败顶级大语言模型。这些参数量7B到15B的小型专精模型在各自的细分领域击败了SoTA模型……
作者演示了,通过使用开源模型和Codex编排进行高性价比微调,小型垂直语言模型(6B-15B)能够在细分基准上超越顶级大语言模型,仅用价值300美元的数据集就取得了成果。
探索小型语言模型作为分类器与Jev竞争(分享我的发现)
作者通过分析高温度下的对数概率和校准,探索使用如Gemma 4等小型语言模型作为分类器,并在GitHub上分享代码与发现。
@pallavishekhar_: https://x.com/pallavishekhar_/status/2058460434035060758
解释大型语言模型实际所做的工作(下一个Token预测),以及为什么即使出错时它们听起来也很有信心。提供了一种心智模型和验证检查清单,用于安全使用LLM。