Ohhnews

分类导航

$ cd ..
foojay原文

dukehoff-decide:用小型语言模型实现类型化且校准的决策

#dukehoff-decide#java#小型语言模型#概率校准#开源工具

许多业务应用中的 LLM 调用,都是在问一个答案只有少数几个选项的问题。哪支团队负责处理这张工单?这条消息是垃圾信息吗?它有多紧急?通常的做法是把问题发给一个大模型,要求它返回 JSON,解析文本,然后指望答案落在允许的取值范围内。而当模型表示自己很确定时,你也无法判断这到底有没有意义。

dukehoff-decide 将这类问题转换为 Java 类型,并用一个本地运行的小模型来回答。你会得到该类型的一个有效值、每个选项的概率,以及一个门控——只有当这些概率可靠时,它才会自行做出决定。该项目基于 Apache License 2.0 开源,0.1.0 版本已发布在 Maven Central。

代码示例

@Question("Triage an incoming customer support ticket")
record Triage(
    @Question("How urgent is this ticket?") Priority priority,
    @Question("Which team should handle it?") Team team,
    @Question("Does the customer threaten to cancel?") boolean churnRisk) {}

Decision<Triage> d = triage.decide(State.of(ticketText));
d.value();                      // always a valid Triage
d.distribution("priority");     // Map<Priority, Double>

switch (triage.requireConfidence(0.9).decide(state)) {
    case Outcome.Confident<Triage>(var dec)          -> route(dec.value());
    case Outcome.Uncertain<Triage>(var dec, var why) -> sendToHuman(state, dec, why);
}

每个字段都会变成一个带有固定选项集合的问题:布尔值是“是”或“否”,枚举的每个常量对应一个选项,刻度上的每一档对应一个选项。模型用单个 token 回答每个问题,dukehoff-decide 从模型的对数概率中读取所有选项的概率。由于不需要解析文本,也就不存在无效答案。

为什么校准很重要

原始的模型概率通常过度自信,而小模型还常常偏好某些特定选项。因此,你需要在离线状态下用几百个已知答案的历史案例校准一次,例如工单以及最终处理它们的团队。dukehoff-decide 会为每个字段拟合一个校正,并生成报告:校准前后的准确率、每个阈值下的门控会自动决定多少案例、这些案例的准确率,以及哪些选项容易被混淆。

这份报告值得一读。像“选项 CONTACT 收到 30 个错误中的 16 个”这样的警告,指向的是描述匹配范围过宽的选项。在我们的测试中,重写一个这样的描述后,准确率从 76% 提升到 88%–90%,超过了规模大 4.7 倍的模型。

我们测了什么

来自公开数据集的客户消息,11 个类别,使用 llama.cpp 运行 Qwen2.5 1.5B(4-bit),300 个样本用于校准,另 300 个不同样本用于测试:

校准之前之后
类别正确87.7%93.7%
自动决定(阈值 0.9)50%71%
其中正确94.0%99.5%

如果总是猜最常见的类别,正确率只有 21.3%。

第二个测试同样重要。在一个支持工单数据集上,队列和优先级大多无法从文本中推断出来,而模型经常声称置信度超过 99%。原始分数会自动路由 42%–65% 的工单,其中完全正确的不到 10%。校准之后,没有任何工单被自动路由。这才是正确答案:门控知道模型什么时候并不知道。

详细信息、两个数据集以及如何重新运行它们,都在 README 中。

获取

你需要 Java 21,以及一个提供 OpenAI 兼容 API 并能返回对数概率的服务器。我们使用 Ollama 和 llama.cpp 进行了验证。

<dependency>
    <groupId>com.dukehoff.decide</groupId>
    <artifactId>dukehoff-decide-openai</artifactId>
    <version>0.1.0</version>
</dependency>

对于 Spring Boot,请改用 dukehoff-decide-spring-boot-starter。它会为每种类型创建一个 DecisionTask bean,并自带健康检查和 Micrometer 指标。入门指南、Spring Boot 配置以及限制说明都在 GitHub 上的 README 中。

如果你想用自己运行的小模型替换应用中对大模型的调用,或者在准备用于校准的带标签样本方面需要帮助,请联系我们。

本文最初发表于 dukehoff.com。