从版本 0.35 开始,Ollama 支持基于 TypeSafe 的 Jev API 构建的决策模型。这些不是通常意义上的聊天模型:它们不编写文本,而是回答一组有关转移状态的键入问题。对于分类、路由、审核和分类,这比要求常规 LLM 返回 JSON 然后解析其响应更快、更可靠。
在这篇文章中,我将介绍什么是决策模型、它们如何在 HTTP 级别工作、哪些模型已经可用,以及如何将它们构建到现有代码中,以便常规生成模型继续工作。
决策模型与常规模型有何不同
常规的 LLM 会收到提示并逐个生成文本标记。即使你让她用一个词来回答,生成仍然发生在里面,而答案的格式必须由图表、说明和后续验证来控制。决策模型的工作方式有所不同:您通过类型传递状态和问题,模型返回概率和选定的选项。没有自由文本,没有从响应中解析 JSON。
新端点称为 /v1/systemone。在一个请求中,您可以同时提出多个问题,模型将回答所有问题。这对于需要做出多个相关决策的任务非常方便:例如,确定团队、是否需要返回以及票证的紧急程度。
有哪些型号可供选择
现在您可以通过 Ollama 运行三个决策模型:
- nimble 是来自 Bespoke Labs 的开放模型,拥有 90 亿个参数。它是现有的最大且最准确的。
- tev1 是来自 Together AI 的一个实验模型,拥有 40 亿个参数。
- tev1:0.8b 是来自 Together AI 的具有 8 亿个参数的实验模型。最快、最简单。
它们都在本地工作,不需要付款,也不将数据发送到外部服务。支持 Ollama 0.35 及更高版本。
安装
首先查看Ollama版本:
ollama --version
然后下载所需的模型。对于最简单的一个:
ollama pull tev1:0.8b
对于 tev1 的完整版本:
ollama pull tev1
对于敏捷:
ollama pull nimble
nimble 模型占用约 9.5 GB 的磁盘空间,因此最好在下载之前清理一些空间。 tev1:0.8b 占用不到 1 GB。
通过curl发出的第一个请求
最简单的例子是判断一段文字是否是招聘广告:
curl http://localhost:11434/v1/systemone -d '{
"model": "tev1:0.8b",
"state": {
"message": "Senior Swift developer, Berlin, remote friendly"
},
"questions": {
"isJob": {
"type": "noul",
"instructions": "Does the message advertise a job posting that someone can apply to?"
}
}
}'
答案看起来像这样:
{
"model": "tev1:0.8b",
"answers": {
"isJob": {
"type": "noul",
"noul": 0.921
}
},
"usage": {
"input_tokens": 42,
"output_tokens": 0
}
}
noul字段是从0到1的概率。通过与阈值(通常为0.5)比较来做出决定。与生成模型不同,不需要请求 JSON 格式的响应,然后检查模型是否没有破坏它。
问题类型
决策模型支持三种类型的问题。
noul 是一个二元问题。返回语句为真的概率:
{
"questions": {
"refund": {
"type": "noul",
"instructions": "Does the customer explicitly ask for a refund?"
}
}
}
选择 – 从给定的集合中选择一个选项。返回所选选项、所有选项的概率和置信度:
{
"questions": {
"team": {
"type": "choice",
"instructions": "Which team should handle this ticket?",
"criteria": {
"billing": "Payments and refunds",
"technical": "Bugs and integrations",
"other": "None of the above"
}
}
}
}
分数 – 等级评分。返回每个比例点的数字、图例和概率:
{
"questions": {
"urgency": {
"type": "score",
"instructions": "How urgent is this ticket?",
"criteria": ["Routine", "Soon", "Urgent"]
}
}
}
一个请求可以同时包含多个不同类型的问题。这就是决策模型便于分类的原因:一种操作,一种状态,几个独立的决策。
无需额外库的 Python
对于请求来说,标准的urllib就足够了;不需要单独的 SDK:
import json
from urllib.request import Request, urlopen
OLLAMA_DECISION_URL = "http://localhost:11434/v1/systemone"
def ask_decision(state, questions, model="tev1:0.8b"):
payload = {
"model": model,
"state": state,
"questions": questions,
}
request = Request(
OLLAMA_DECISION_URL,
data=json.dumps(payload).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
with urlopen(request, timeout=3600) as response:
return json.loads(response.read().decode())["answers"]
用法:
answers = ask_decision(
{"message": "Senior Swift developer, Berlin, remote friendly"},
{
"isJob": {
"type": "noul",
"instructions": "Does the message advertise a job posting that someone can apply to?"
}
},
)
probability = answers["isJob"]["noul"]
is_job = probability >= 0.5
如果您需要官方的Python SDK,它称为typesafe-sdk。对于本地主机,可以使用环境变量 TYPESAFE_BASE_URL、TYPESAFE_API_KEY 和 TYPESAFE_DEFAULT_MODEL 将其定向到 Ollama。但对于简单的任务,直接 HTTP 请求就足够了。
如何理解模型支持决策
决策模型无法通过 /api/generate 或 /api/chat 进行响应。如果您发送此类请求,Ollama 将返回 400 错误,其中包含如下文本:
"tev1:0.8b" does not support generate
如果您已经拥有通过 /api/generate 处理常规模型的代码,这一点很重要:如果您将模型更改为决策模型,它将停止工作。最好通过 /api/show 提前了解模型的能力,并选择合适的调用方式:
import json
from urllib.request import Request, urlopen
OLLAMA_SHOW_URL = "http://localhost:11434/api/show"
def supports_decision(model):
request = Request(
OLLAMA_SHOW_URL,
data=json.dumps({"model": model}).encode(),
headers={"Content-Type": "application/json"},
method="POST",
)
try:
with urlopen(request, timeout=30) as response:
capabilities = json.loads(response.read().decode()).get("capabilities", [])
except (OSError, TypeError, ValueError):
return False
return "decision" in capabilities
决策模型只能根据其能力做出决策。常规模型将有完成、工具或其他功能。如果 Ollama 不可用,则可以合理地认为模型正常并使用生成路径。
如何嵌入现有代码
最简单的方法不是重写分类器,而是将其分为两种策略。生成策略的工作方式与以前一样:它收集提示,将其发送到 /api/generate 并解析 JSON。决策策略将状态和键入的问题发送到 /v1/systemone 并将概率与阈值进行比较。
创建分类器时,策略的选择发生在一个地方:
def create_classifier(model):
if supports_decision(model):
return DecisionClassifier(model)
return GenerativeClassifier(model)
这种方法有几个优点。生成模型继续运行不变。可以通过更改一个环境变量来启用决策模型。这两种方法之间的全部差异集中在两个小类中,并且没有分散到整个应用程序中。
对于二元分类,决策策略如下所示:
async def classify(text):
answers = await ask_decision(
{"message": text},
{
"isJob": {
"type": "noul",
"instructions": instructions,
}
},
model,
)
probability = answers["isJob"]["noul"]
return probability >= 0.5, probability
请注意,决策模型不会返回解释。如果您的结果格式具有原因字段,您可以根据概率构建它:例如,存储概率本身或类似“模型将 0.935 的消息评为空缺”的字符串。这比发明模型没有给出的原因更诚实。
说明应该是一个问题
这是最重要的实际结论。决策模型无法理解“你对消息进行分类,如果……则回答 true,否则回答 false”这样的长提示。他们想要一个简短、直接的问题。
在同一条关于职位空缺的消息中,我收到了以下概率:
- 直接提问“此消息是招聘信息吗?” — 0.921。
- 详细说明什么被视为空缺 – 0.026。
- 最后有问题的长说明 – 0.391。
相差了近三十倍。该模型在分类上并没有错误,只是当问题隐藏在段落中时,它不明白他们想要从中得到什么。因此,对于决策模型,值得保留单独的简短指令,并为生成模型留下长提示。
创建单独的环境变量很方便:
OLLAMA_JOB_CLASSIFIER_DECISION_INSTRUCTIONS=Does the message advertise a job posting that someone can apply to?
并仅对生成路径使用常规提示。
阈值和概率
阈值 0.5 适合作为默认值,但将其包含在配置中会很有用。对于不同的任务,误报和误报响应的成本是不同的。对于节制来说,提高门槛比较安全;寻找职位空缺时,将其降低比较安全,以免错过有用的消息。
记录概率本身也很有用,而不仅仅是结果布尔值。当分类器出错时,日志会显示它是一个自信的答案还是一个边界决策。对于选择问题,值得保存概率和置信度:它们显示模型在选项之间的波动程度。
性能和内存
速度很大程度上取决于模型的大小和硬件。在我的测试中,我在 CPU 上得到了以下数字:
- tev1:0.8b – 只需几秒钟即可解决,轻松装入内存。
- tev1 – 4B,明显较慢,但仍然适合交互式任务。
- nimble – Q8_0 中为 9B,内存约为 10 GB。第一个请求(包括加载模型)花费了大约 137 秒,后续解决方案在 CPU 上花费了 12 到 32 秒。
Nimble 需要大量 RAM。在具有 16 GB 和限制约为 8 GB 的 Docker/WSL 的计算机上,该模型不适合:系统开始交换,容器停止响应。通过 .wslconfig 文件将 WSL 限制增加到 12 GB 有助于:
[wsl2]
memory=12GB
swap=8GB
更改后,需要 wsl –shutdown 并重新启动 Docker Desktop。但即使有 12 GB,预留空间仍然很小:该模型大约占用 10 GB,留给系统的空间所剩无几。
默认情况下,Ollama 在五分钟不活动后卸载模型,释放内存。这很方便:nimble 不会始终保持 10 GB 繁忙,但暂停后每次新启动都会再次开始加载模型。
何时使用决策模型
决策模型非常适合需要快速、廉价地回答明确提出的问题的任务:
- 消息、票证和请求的分类。
- 通过命令或执行器进行路由。
- 内容审核和安全检查。
- 游戏或交互式应用程序中的快速二元和多元解决方案。
它们不太适合需要详细文本的任务:解释、字段提取、摘要、答案生成。为此,保留了通常的生成模型。组合时可以获得最佳结果:决策模型做出决策,生成模型解释决策或提取数据。
总计
与常规法学硕士相比,Ollama 的决策模型是一个独立的、范围更窄的工具。它们不会取代生成模型,但会取消工作的常规部分:键入的响应、概率而不是文本解析以及可预测的格式。如果您已经有了分类管道,则转换归结为检查模型的功能、单独的调用策略和简短的指导问题。
来源
https://ollama.com/blog/ollama-now-supports-jev-style-decision-models
https://ollama.com/library/nimble
https://ollama.com/library/tev1
https://typesafe.ai
Leave a Reply