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,它更快、更稳、概率更可信。