Build your own decision model
TL;DR · AI 摘要
Build your own decision model By Nish Tahir — 10 Oct 2026 "System one" decision models are models that infer and respond...
核心要点
- 主题聚焦:Build your own decision model
- 来源:Hacker News Best,建议结合原文判断细节。
- AI 分析暂不可用,本条为保底评分与摘要。
构建自己的决策模型
By
Nish Tahir
—
2026年10月10日
"系统一"决策模型是通过校准概率或所有允许的答案进行推断和响应的模型。
以日常使用的语言模型为例,若要从模型中获取结构化输出(如JSON格式),可以使用结构化输出功能来约束输出为保证有效的JSON格式。虽然模型可以在一次前向传递中填充输入,但仍需对每个token进行多次传递才能生成有效响应。
在此示例中,生成最终输出需要11次传递。(我们未考虑推测解码和其他推理优化技术。)
kg-card-begin: html
步骤
播放
重置
提示(预填充)
生成(预测)
正在预测
kg-card-end: html
像Jev这样的决策模型假设存在固定选项供我们选择,并且可以通过单次传递快速完成选择。在此示例中,我们将可能的输出集约束为选项A、B、C、D、E。通过屏蔽词汇表中的其他项,模型只能输出这些token。通过选择概率最高的输出,我们就能得到答案。
由于输出被约束在固定选项集中,模型无法选择集外内容。但这也无法保证输出的正确性。在此场景中,输出token的概率通常被当作置信度分数处理,但未经额外训练时,这些分数更可能反映模型对下一个token的预测置信度,而非响应正确性的实际概率。
构建自己的模型
我们可以通过使用LLM约束输出token来模拟这种行为。这里我使用Qwen/Qwen3-1.7B
import argparse
import json
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer
model_name = "Qwen/Qwen3-1.7B"
options = ["A", "B", "C", "D", "E"]
parser = argparse.ArgumentParser()
parser.add_argument("--input", default="question.json")
args = parser.parse_args()
# 加载分词器和模型
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype="auto",
device_map="auto"
)
# 每个选项作为第一个助手token时模型会生成的token ID
option_token_ids = [tokenizer.encode(opt, add_special_tokens=False)[0] for opt in options]
def format_prompt(item):
prompt = item["question"] + "\n"
for opt in options:
prompt += f"{opt}. {item[opt]}\n"
prompt += "Answer:"
messages = [
{"role": "user", "content": prompt}
]
return tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True,
enable_thinking=False
)
with open(args.input) as f:
item = json.load(f)
model_inputs = tokenizer(format_prompt(item), return_tensors="pt").to(model.device)
with torch.no_grad():
logits = model(**model_inputs).logits[0, -1]
# 约束解码:仅允许选项token
probs = torch.softmax(logits[option_token_ids].float(), dim=-1)
print(f"预测结果: {options[probs.argmax().item()]}")
for opt, prob in zip(options, probs.tolist()):
print(f"{opt}: {prob:.4f} {item[opt]}")使用简单问题进行测试时输出如下:
// 输入
{
"question": "天空是什么颜色?",
"A": "红色",
"B": "蓝色",
"C": "绿色",
"D": "紫色",
"E": "我不知道"
}
// 输出prediction: B A: 0.0000 红色 B: 0.9988 蓝色 C: 0.0000 绿色 D: 0.0000 紫色 E: 0.0012 我不知道
模型能够正确理解输入并做出与正确答案合理对应的预测。
我们可以通过在公开数据集上运行模型来测试其准确性。我将其应用于 CommonsenseQA 的随机样本测试集
precision recall f1 support A 0.5733 0.7197 0.6382 239 B 0.5506 0.7686 0.6416 255 C 0.5372 0.6598 0.5922 241 D 0.7206 0.3904 0.5065 251 E 0.7519 0.4255 0.5435 235 accuracy: 725/1221 = 0.5938 macro f1: 0.5844
对于一个17亿参数的模型来说表现不错,对数据集进行快速微调后性能略有提升
precision recall f1 support A 0.6475 0.6611 0.6542 239 B 0.6113 0.6784 0.6431 255 C 0.6234 0.5975 0.6102 241 D 0.6700 0.5418 0.5991 251 E 0.5808 0.6426 0.6101 235 accuracy: 762/1221 = 0.6241 macro f1: 0.6234
# 模型校准
对模型进行非常模糊问题的测试展示了有趣的特性。
// 输入 { "question": "你最可能在哪里发现蝙蝠?", "A": "洞穴", "B": "棒球比赛", "C": "阁楼", "D": "动物园", "E": "体育用品店" }
// 输出
prediction: A A: 0.9978 洞穴 B: 0.0004 棒球比赛 C: 0.0017 阁楼 D: 0.0000 动物园 E: 0.0001 体育用品店
这里应该没有明确答案,但将输出概率视为伪"置信度"分数时,可以看出模型对这个答案的过度自信。
如果将我之前运行的评估中的置信度范围进行分箱,可以发现模型的置信度与其准确性不匹配。这意味着模型未经过校准。
bin count confidence accuracy (0.00, 0.10] 0 0.0000 0.0000 (0.10, 0.20] 0 0.0000 0.0000 (0.20, 0.30] 3 0.2834 0.0000 (0.30, 0.40] 26 0.3761 0.2692 (0.40, 0.50] 41 0.4538 0.2683 (0.50, 0.60] 70 0.5490 0.3286 (0.60, 0.70] 74 0.6476 0.3649 (0.70, 0.80] 77 0.7495 0.4286 (0.80, 0.90] 121 0.8555 0.4711 (0.90, 1.00] 809 0.9855 0.7009
我们可以注意到模型在0.9-1.0分箱中表现出极端的过度自信,但正确率仅为70%。当它以0.8-0.9的置信度进行预测时,准确率仅为40%左右。这表明模型在预测中普遍过度自信。
由于我们的目标是让模型输出能反映其准确性的分数,我们可以使用温度缩放来校准模型。通过调整温度值,我们可以平滑其输出概率分布曲线并将其缩放以近似其准确性。
温度 T
曲线拟合将温度参数拟合到模型的准确性上,我找到3.797280788421631作为温度值。
bin count 置信度 准确率 (0.00, 0.10] 0 0.0000 0.0000 (0.10, 0.20] 0 0.0000 0.0000 (0.20, 0.30] 82 0.2712 0.2317 (0.30, 0.40] 217 0.3507 0.3917 (0.40, 0.50] 199 0.4472 0.5126 (0.50, 0.60] 166 0.5475 0.5482 (0.60, 0.70] 139 0.6562 0.5827 (0.70, 0.80] 140 0.7492 0.7714 (0.80, 0.90] 169 0.8507 0.7988 (0.90, 1.00] 109 0.9333 0.9541
这使我们获得了显著改善的校准效果。如果你想进一步探索,我在GitHub上创建了一个仓库,其中包含逐步引导你完成构建数据集、模型评估、微调和校准的完整脚本。我建议你克隆这个仓库,并尝试在其他更大的模型上进行验证。