bespokelabsai/nimble · 上手攻略
- 仓库:bespokelabsai/nimble
- 链接:https://github.com/bespokelabsai/nimble
- 分类:AI 模型 · 决策模型
- 作者:Jay
- 更新:2026-09-23
这是什么
Nimble 是一个本地运行的决策模型,基于 Qwen3.5-9B 微调而来,主打「给一段文字 + 一个 schema,立刻返回一个带概率的typed decision」——不做推理过程、不生成文本,直接从 logits 读出各候选答案的概率,返回确定类型的结构化结果。
核心灵感来自 TypeSafe 的商业产品 Jev(System One 决策路径),但 Nimble 并非蒸馏 Jev,而是独立实现了:① 对比数据策展(contrastive data curation)训练方法,② 本地推理代码(MLX / CUDA),③ 完整的 Benchmark 评估流程,全部开源。
2026-09-18 公开基准测试套件,2026-09-20 发布训练数据集(2,676 条训练 + 324 条 hold-out),2026-09-22 为 Bespoke-Nimble-9B 拟合了概率温度参数(温度=2.179),让输出的概率更接近实际正确率。
解决什么问题
通用 LLM 生成文本再解析 JSON 的 pipeline 有三个固有缺陷:① 速度慢(要生成完整文本再解析),② 输出不稳定(JSON 结构可能出错),③ 概率不准(生成模型对分类任务不校准)。Nimble 的做法是:直接对候选答案的 token logits 做 softmax,从 logits 读概率,完全绕过文本生成环节。
典型场景: - 请求路由:用户输入 → 选目的地(enum,多个选项) - 条件检查:一段文本 → True/False + 概率 - 策略执行:文本 + 规则 → 结构化决策 - 结果评级:文本 + 有序评分标准 → 评级 + 各档概率
快速安装
环境要求
| 平台 | 要求 |
|---|---|
| macOS | Apple Silicon(M 系列芯片),Python 直接跑在 macOS 上以使用 Metal |
| Linux | NVIDIA GPU,支持 BF16,PyTorch + CUDA |
步骤
① 克隆仓库
git clone https://github.com/bespokelabsai/nimble.git nimble
cd nimble
② 创建 Python 环境(Python 3.12)
python3.12 -m venv .cache/venvs/nimble
source .cache/venvs/nimble/bin/activate
pip install torch==2.8.0 -r requirements/training.txt
③ 下载并合并模型权重
# 将以下内容保存为脚本运行,或直接粘贴到 Python 交互环境
import hashlib, json
from pathlib import Path
from huggingface_hub import snapshot_download
repo = "bespokelabs/Bespoke-Nimble-9B" # 或 "bespokelabs/Bespoke-Nimble-9B-v2"
snapshot = Path(snapshot_download(repo, cache_dir=".cache/huggingface/hub"))
model_path = snapshot
if (snapshot / "adapter_config.json").exists():
import torch
from peft import PeftModel
from transformers import AutoTokenizer, Qwen3_5ForConditionalGeneration
contract = json.loads((snapshot / "schema_config.json").read_text())
base = Qwen3_5ForConditionalGeneration.from_pretrained(
contract["model"], revision=contract["revision"],
dtype=torch.bfloat16, device_map="cpu")
adapter = PeftModel.from_pretrained(base, snapshot)
merged = adapter.merge_and_unload(safe_merge=True)
model_path = Path(".cache/models") / ("nimble-9b-" + snapshot.name)
merged.save_pretrained(model_path)
AutoTokenizer.from_pretrained(snapshot).save_pretrained(model_path)
(model_path / "READY.json").write_text(json.dumps({
"model": repo, "revision": snapshot.name,
"adapter_sha256": hashlib.sha256(
(snapshot / "adapter_model.safetensors").read_bytes()
).hexdigest()}, indent=2))
config = {
"model_path": str(model_path.resolve()),
"model_id": repo,
"revision": snapshot.name,
"max_input_tokens": contract.get("max_length", 2048),
}
Path(".cache/nimble-model.json").write_text(json.dumps(config, indent=2))
print("Ready:", model_path)
④ 选择推理后端
macOS(MLX):
deactivate
python3.12 -m venv .venv-mlx
source .venv-mlx/bin/activate
pip install -r requirements/mlx.txt
Linux(CUDA):
# 先验证 GPU 支持
python -c "import torch; assert torch.cuda.is_available() and torch.cuda.is_bf16_supported()"
核心用法
加载 Scorer
macOS(MLX):
import json
from pathlib import Path
from nimble.scoring.parallel_scorer import ParallelScorer
config = json.loads(Path(".cache/nimble-model.json").read_text())
scorer = ParallelScorer(**config)
⚠️
ParallelScorer()不传参数会加载 Qwen3.5-4B 基线模型,不是 Nimble。MLX 不能直接加载 LoRA adapter,必须用上面合并后的权重目录。
Linux(CUDA):
import json
from pathlib import Path
from nimble.scoring.cuda_scorer import CudaCandidateScorer
config = json.loads(Path(".cache/nimble-model.json").read_text())
scorer = CudaCandidateScorer(**config)
定义 Schema 并打分
schema = {
"priority": {
"type": "enum",
"choices": ["HIGH", "LOW"],
"description": "Urgency based on current business impact.",
"choice_descriptions": {
"HIGH": "A critical business operation is currently blocked.",
"LOW": "An optional enhancement with no current business impact.",
},
},
"requires_review": {
"type": "boolean",
"description": "Whether customers are unable to complete a purchase.",
},
}
result = scorer.score(
"The payment service is down for all customers.",
schema
)
print(result["output"])
# {"priority": "HIGH", "requires_review": True}
print(result["fields"]["priority"]["scores"])
# 各候选概率
温度参数说明
- Bespoke-Nimble-9B(原始版本):默认温度 2.179(已拟合)
- Bespoke-Nimble-9B-v2:自动使用 2.179078721266035
- 其他模型:默认温度 1.0
⚠️ 如果你在阈值判断中使用概率,换了温度或模型版本后必须重新测试阈值。官方 2026-09-22 的温度更新后答案不变,但概率值变了。
典型适用场景
| 场景 | Nimble 能做什么 |
|---|---|
| AI Agent 请求路由 | 用户 query → 选插件/工具/意图 |
| 内容审核 | 评论 → 通过/待审/违规 + 置信度 |
| 客服工单分类 | 工单描述 → 优先级 + 部门路由 |
| 保险理赔判断 | 报案描述 → 赔付类型 + 材料缺失项 |
| 合同合规检查 | 条款文本 → 风险等级(enum)+ 是否需法务 |
坑与注意
① 9B 模型显存要求高
无量化权重约 18 GB(BF16),运行期间还需要额外显存。合并步骤在 CPU 上跑,需要额外 RAM 和磁盘空间。macOS 建议 64 GB 内存机器。
② 只接受文本输入
即使底层 Qwen3.5-9B 含视觉多模态部分,Nimble 也只处理纯文本,不支持图片输入。
③ 不生成文本、不支持嵌套结构
Schema 必须是 flat(无嵌套字段);enum 最多 26 个选项,boolean 只有 true/false。无法输出解释文本或从上下文中截取的原文。
④ 概率不等于正确率
0.9 的概率不代表「90% 的时候答案正确」。温度拟合后概率更接近实际正确率,但仍需在你的数据上测试阈值,不要直接用概率值做业务决策而不校验。
⑤ prompt 最多 2,048 token
包含 schema + 字段描述 + 上下文。超出直接拒绝,不会截断。
⑥ 领域泛化有限
训练数据 2,676 条来自策展的若干特定领域。对未见过的领域仍有改进空间(比基座 Qwen3.5-9B 强,但不如 Jev 的 93.21% 准确率,Nimble 90.12%)。
⑦ 无许可证文件(截至 2026-09-20)
GitHub 仓库根目录无 LICENSE 文件。模型权重在 Hugging Face 为 Apache 2.0,但代码暂未声明许可证,使用前请先联系作者。
与同类对比
| 方案 | 类型 | 本地运行 | 速度 | 输出稳定性 | 概率校准 |
|---|---|---|---|---|---|
| Bespoke-Nimble-9B | 决策模型(logits→softmax) | ✅ MLX/CUDA | 快(一步决策) | 高 | 温度拟合后较好 |
| Jev(TypeSafe,商业) | 决策模型 | 需 API | 快 | 高 | 93.21% 准确率 |
| 通用 LLM + JSON解析 | 生成式 | ✅ 可本地 | 慢 | 中等(可能解析失败) | 不校准 |
| LLM + Function Calling | 生成式 | ✅ | 中等 | 较高 | 不校准 |
| Qwen3.5-9B 基座 | 生成式 | ✅ | 慢 | 低 | 不校准 |
Nimble 的核心优势是速度和输出稳定性(不走生成,直接读 logits),以及本地运行(不需要任何 API Key)。对比通用 LLM 做分类,它更像一个专用的小模型,但比蒸馏版 Jev 在代码和数据上都更透明。
一句话推荐
如果你在 AI Agent 或软件系统里需要高频做「给定文本 + 选项列表 → 直接返回最优选项 + 概率」这类 typed decision,且希望完全本地运行、不依赖任何 API——Nimble(Bespoke-Nimble-9B)是目前开源生态里代码、数据、训练 recipe 全部公开可查的决策模型方案;相比直接用通用 LLM 生成再解析 JSON,它更快、更稳、概率更可信。