aifollow.news
Back Hugging Face 官方博客
Hugging Face 官方博客· · Original publication time AI score40

Hugging Face adds a shared interface for decision modelsMachine translation

Hugging Face 为决策模型加入统一接口支持

AI-assisted summary

Hugging Face says Transformers now supports decision model classes and the /v1/systemone endpoint, while llama.cpp supports the same API and the Hub has a dedicated tag for finding compatible models. The interface can answer choice, scoring and yes/no questions about the same input and return probabilities; routing customer support requests is an example in the post.

Article · AI translation

大型语言模型(LLM)非常擅长生成文本。我们用它们回答问题、编写代码、推理问题,以及做更多事情。但并非每个问题都需要生成文本。

设想一个客户支持系统收到以下消息:

“我的订阅被扣了两次款。我今天需要退款。”

系统需要确定应由哪个团队处理该请求、该请求有多紧急,以及客户是否在要求退款。

我们可以让大型语言模型返回一个包含这些答案的 JSON 对象。

但如果模型无需生成任何文本,就能直接评估可选项并返回它们的概率分布呢?

这就是决策模型背后的核心思想。

什么是决策模型?

决策模型接收一些输入上下文(状态),针对一个具有一组预定义可能答案(原语)的问题进行评估,并返回结构化决策及相应概率。我们并非让模型逐个词元生成答案,而是让它为应用程序已经能够理解的答案分配概率。

TypeSafe AI 推出了 Jev,并将其描述为一种“系统一”模型。这个名称的灵感来自快速、直觉式思考(系统 1)与较慢、审慎式思考(系统 2)之间的区别。

社区逐渐统一使用“决策模型”这一术语,因为它描述的是模型的计算作用,而不是援引某种特定的认知理论。在本文余下部分,我们将这些模型称为“决策模型”,而不是“系统一模型”。(一项关于我们应该如何称呼此类模型的 Twitter 投票)

社区逐渐统一使用“决策模型”这一术语,因为它描述的是模型的计算作用,而不是援引某种特定的认知理论。在本文余下部分,我们将这些模型称为“决策模型”,而不是“系统一模型”。(一项关于我们应该如何称呼此类模型的 Twitter 投票)

对于决策模型,其基本接口是:

为什么不把大型语言模型用于所有任务?

我们完全可以直接提示大型语言模型返回一个包含决策结果的 JSON 对象。事实上,许多应用程序已经以这种方式使用语言模型执行分类、路由和其他结构化任务。

然而,这种方法存在几个问题。

大型语言模型不能保证遵循要求的模式:即使给出明确指令,模型仍可能生成无效的 JSON、引入意料之外的键,或返回不在允许选项之内的答案。

受约束解码有所帮助,但无法消除计算开销:Outlines 和 XGrammar 等库可以通过限制模型在每一步能够生成的词元,强制输出遵循语法规则或 JSON 模式。这能确保输出符合所支持的结构约束,但也会带来额外的工作量。

为什么要生成完整的回答:大型语言模型是为开放式生成而设计的,但当应用程序只需从预定义答案中做出选择时,自回归解码可能是不必要的工作。

决策模型与分类模型有何不同?

在理解决策模型的接口之前,先回顾两种密切相关的方法会有所帮助,即传统分类和零样本分类。

传统分类

假设我们训练一个分类器,将客户支持请求分配给 3 个部门:

账单部门

技术支持部门

销售部门

传统分类模型学习将输入映射到一组预定义标签。在训练过程中,模型从示例中学习预测这些标签。分类头通常为每个类别生成一个 logit,softmax 则将这些 logit 转换为概率分布。

这里的局限在于,输出类别被固定在模型的分类头中。

如果我们引入第 4 个部门,例如法务部,现有分类器不会自动获得相应的输出类别。我们可能需要修改输出层、收集训练数据,并重新训练或调整模型。

零样本分类

零样本分类解决了这一局限的一个重要方面。我们不必要求分类器针对每个输出类别专门训练,而是在推理时提供候选标签。

例如:

与传统的固定标签分类器不同,类别可以随请求而变化。让我们再添加一个部门,例如“法务部”,看看模型的输出。

一种常见实现方式使用针对自然语言推断(NLI)训练的模型。每个候选标签都会转换为一个假设,模型会衡量输入在多大程度上蕴含该假设。

这听起来已经与决策模型很相似了。在很多方面,确实如此。

决策模型的不同之处

决策模型将这一思路扩展到单纯将输入归入某个类别之外。决策模型可以接收多个关于同一状态的具名问题,而这些问题可以有不同的答案类型。这些类型可以是从备选项中选择(choice)、在有序量表上评分(score),或估计某个陈述为真的概率(noul)。

更重要的是,它的接口围绕可能决策的概率分布而设计。

请看以下 3 种方法:

属性

分类

零样本分类

决策模型

各选项的概率

是

是

是

在推理时定义标签

否

是

是

多个具有类型的问题

否

否

是

有序评分和是/否决策

取决于具体任务

经过调整可以实现

原生基本类型

决策模型的优势并不在于它们发明了运行时定义标签或概率分类,而在于它们将这些能力组织成一致的接口,并且可能由专门针对决策优化的架构和训练流程提供支持。

决策模型接口

决策模型请求包含以下 2 个组成部分:

state

questions

状态

状态是模型应评估的信息。它可以是字符串、结构化的 JSON 对象,或者对于支持全模态的模型,可以是其他模态。

例如:

问题及其基本类型

问题描述了我们想了解状态的哪些方面。在决策模型接口中,3 种基本类型代表不同形式的决策:

选择(Choice):从几个可能的答案中选出 1 个。

评分(Score):在有序量表上评估某个事物。

Noul:以概率形式回答是/否问题。

让我们逐一了解它们。

选择是最直观的基本类型,也最接近传统分类。

假设我们提出以下问题:

哪个部门应该处理这项客户请求?

哪个部门应该处理这项客户请求?

可选项为账单部、技术支持部和销售部。

模型为每个选项分配一个 logit。对于 logits($z_1,\ldots,z_K$),(其中有 K 个类别),我们可以使用 softmax 得到概率:

p i = exp ⁡ ( z i / T ) ∑ j = 1 K exp ⁡ ( z j )

p_i=\frac{\exp(z_i/T)}{\sum_{j=1}^{K}\exp(z_j)}

这里,(K)是选项的数量。

请看以下示例性概率分布:

选项

概率

账单部

0.998

技术支持部

0.001

销售部

0.001

这些概率之和为 1:

∑ i = 1 K p i = 1.

\sum_{i=1}^{K}p_i=1.

模型选择概率最大的选项:

y ^ = arg ⁡ max ⁡ i p i

\hat y=\arg\max_i p_i

在这个例子中,选中的是账单部,概率为 0.998,但其余概率也有用。它们表明模型如何在各备选项之间分配其确信程度。

当存在几个不同的备选项时,可以使用选择。但如果我们想在有序量表上衡量某个事物呢?

请看这个问题:

这项客户请求有多紧急?

这项客户请求有多紧急?

我们定义 3 个级别:

0:紧急程度低

1:紧急程度中等

2:紧急程度高

模型同样会生成一个概率分布:

级别

概率

0 — 低

0.10

1 — 中

0.26

2 — 高

0.72

Score 原语并非只返回最可能的等级,而是计算等级索引的期望值。

对于表示等级的随机变量 (X),其期望值为:

E [ X ] = ∑ i = 0 K − 1 i p i

\mathbb{E}[X]=\sum_{i=0}^{K-1}ip_i

在我们的示例中:

E [ X ] = 0 ( 0.10 ) + 1 ( 0.26 ) + 2 ( 0.72 ) = 1.7

\mathbb{E}[X] = 0(0.10)+1(0.26)+2(0.72)=1.7

因此,报告的分数是 1.7。

这并不意味着模型选择了一个介于中和高之间的虚构等级,而是意味着其概率分布的期望值为 1.7。

第 3 种原语是 Noul,它表示一个二元问题。

例如:

客户是否在申请退款?

客户是否在申请退款?

我们不定义选项列表,而是让模型返回答案为真的概率。可以用伯努利分布来理解这一点(noul 一词源自 Bernoulli)。

设 (Y) 表示一个二元结果:

Y ∼ Bernoulli ⁡ ( p )

Y\sim\operatorname{Bernoulli}(p)

其中

P ( Y = 1 ) = p , P ( Y = 0 ) = 1 − p .

P(Y=1)=p,\qquad P(Y=0)=1-p.

如果模型返回:

它为“是”赋予 0.92 的概率,为“否”赋予 0.08 的概率。

模型在这里并未随机抽样得出二元答案。它返回的是概率参数本身,由应用程序决定如何据此采取行动。

到目前为止,我们已经从模型获得了概率分布。但决策模型接口还会为 Choice 和 Score 返回一个名为 confidence 的字段。

完整的分布可能包含多个可能的答案,因此概括模型的判断有多集中很有用。confidence 正是用于此目的。

对于有 (K) 个选项的 Choice,置信度为:

p max ⁡ − 1 K 1 − 1 K

\frac{p_{\max}-\frac{1}{K}}{1-\frac{1}{K}}

其中 ($p_{\max}$) 是最大的预测概率。

直观地说:

均匀分布的置信度为 0。($p_{\max} = \frac{1}{K}$)这意味着模型估计所有选项出现的可能性相同。

概率完全集中在一个选项上的分布,其置信度为 1。($p_{\max} = 1$)

胜出选项的概率相对于均匀分布越高,置信度就越高。

在前面有 3 个选项的示例中,Billing 的概率为 0.80:

C = 3 ( 0.99 ) − 1 2 = 0.98

C=\frac{3(0.99)-1}{2}=0.98

请注意,胜出选项的概率是 0.99,但报告的置信度是 0.98。置信度会根据可用选项的数量对最大概率进行归一化。相比之下,有序 Score 示例的置信度仅为 0.558。

Hugging Face 生态系统中的决策模型

决策模型是一个新兴且发展迅速的领域。各个模型在内部采用不同的决策方式(对整个模式联合评分的模型头、基于大语言模型骨干网络的独立输出层、适用于边缘设备的版本和多模态版本等)。这种多样性是好事,但也有代价。如果每个模型都提供自己的接口,围绕它构建的每个工具都需要针对具体模型进行适配。

我们在 Hugging Face 的目标是就通用接口达成共识,同时不强制采用统一的实现方式。只要决策模型接收相同的状态和问题,并返回相同类型的决策,它就应该能够自由选择内部的工作方式。一旦有了这样的约定,生态系统的其他部分就可以在此基础上统一构建:

llama.cpp 等推理引擎可以通过同一个 API 提供任何决策模型的服务

Hub 可以以一致的方式打包和展示这些模型

训练工具可以面向共享原语,而不是针对单个架构

本节其余部分将逐一介绍这些方面。

1. 使用 Transformers 提供服务

Transformers 现在支持 DecisionPipeline、AutoModelForDecision 和 DecisionConfig 类。它们沿用 transformers 中流水线和模型类的整体结构,但专为决策模型设计。

也可以像这样查看配置和模型:

Transformers 还支持 /v1/systemone 端点。

我们可以使用提供服务所需的依赖项启动本地服务器:

使用兼容版本的 Transformers,接下来我们可以发送一个决策请求:

响应包含 3 个具名答案,以及相应的类型化结果和概率。

一个有趣的细节是,上述 API 也适用于兼容的自回归语言模型。Transformers 会构造决策提示,在批量前向传播中计算答案标签的 logits,并应用 softmax,而不生成响应文本。这意味着我们不一定要训练新模型,就可以试验决策接口。

一个有趣的细节是,上述 API 也适用于兼容的自回归语言模型。Transformers 会构造决策提示,在批量前向传播中计算答案标签的 logits,并应用 softmax,而不生成响应文本。这意味着我们不一定要训练新模型,就可以试验决策接口。

2. 使用 llama.cpp 提供服务

llama.cpp 也通过同一个 /v1/systemone API 支持决策模型。

例如,我们可以从 Hub 启动一个 GGUF 决策模型:

默认服务器运行在端口 9931。

然后,我们可以使用 http://localhost:9931/v1/systemone 发送包含相同状态和问题的请求。由于模型已由服务器选定,我们可以在请求中省略 model 字段。

其实用之处在于接口兼容性。

3. 在 Hugging Face Hub 上发现模型

Hugging Face 引入了专门的 decision-model 标签,用于发现兼容模型。这很有用,因为决策模型不必共用同一种骨干模型或架构。

例如,该生态系统既有基于 ModernBERT 等编码器架构的模型,也有从更大的生成式语言模型骨干模型衍生而来的模型。

4. 使用 Hugging Face 工具训练决策模型

了解推理之后,下一个问题是我们能否调整决策模型。由于决策模型已集成到 transformers 中,我们可以使用 Trainer API 对其进行微调。

下面是一个使用 JEV-9B 进行微调以分流支持请求的玩具示例。它刻意保持简短,但展示了关键部分:

每个样本都是一个决策请求(一个状态加上若干问题),并配有正确答案。

model.decision_config.prepare_inputs 会将请求转换为模型输入,方式与推理时相同。

模型会为每个选项返回一个 logit,因此选择题使用针对各选项的普通交叉熵损失进行训练。

TRL 也即将提供对训练决策模型的一等支持(huggingface/trl#8040),这样我们就不必手动编写这些配套代码。撰写本文时,该 PR 仍未关闭。

如果我们想更进一步,将生成式大语言模型转变为决策模型,Unsloth 提供了一个方案,使用 LoRA 和决策评分头对 Qwen 等模型进行微调。

最后的思考

决策模型之所以有趣,并不是因为分类是新事物,而是因为它们将决策和概率作为软件中的一等输出。

传统分类器已经能输出概率,零样本分类器也已经允许在运行时定义类别。决策模型将这些理念纳入一个类型化接口,提供多种问题原语、非生成式评分,以及通过专门训练实现可靠且经过校准的决策的可能性。

Found an error? Send a correction

Contents