ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Bespoke-Nimble-9B 实战指南:基于 Qwen3.5-9B LoRA 的上下文接地候选评分模型(choices / boolean / rubric)

Bespoke-Nimble-9B 实战指南:基于 Qwen3.5-9B LoRA 的上下文接地候选评分模型(choices / boolean / rubric)
  • 人工智能
  • 大模型
  • 微调
  • LoRA
  • 模型评测
  • NLP

【免费下载链接】Bespoke-Nimble-9B

项目地址:https://ai.gitcode.com/hf_mirrors/bespokelabs/Bespoke-Nimble-9B
点击查看免费下载

本文以 HuggingFace 镜像仓库hf_mirrors/bespokelabs/Bespoke-Nimble-9B中的 README.md 为主线,结合仓库内的 inference.py、schema_config.json、adapter_config.json 等源码与配置,系统讲解 Bespoke-Nimble-9B 的模型定位、安装加载、Schema 编写、候选评分原理与可靠性设计。读完本文,你将能够独立完成模型的下载安装、通过NimbleModel.score()完成布尔判断、选项分类与评分级(rubric)三类结构化预测,并理解其"直接对候选 token 打分、不做自由生成"的底层机制。

一、模型定位:不是生成式评分,而是候选 token 直接打分

Bespoke-Nimble-9B 是一个基于Qwen3.5-9B 基础模型的LoRA 适配器(adapter),专门用于"上下文接地"(context-grounded)的三种结构化输出任务:

  • choices(选项分类):从给定候选中选出与上下文事实最匹配的一项;
  • booleans(布尔判断):对某个命题给出 true / false;
  • rubric score levels(评分等级):按等级描述(如 0、1、2、3)对结果打分。

它的核心工作方式与常见 LLM 应用不同:它直接对"允许出现的答案 token"计算得分(scores the allowed answer tokens directly),推理工作流不生成推理过程(reasoning),也不产出自由文本答案。也就是说,模型不是"写"出答案,而是从你给出的候选集合里"选"出最合适的一个,并以概率形式给出置信度。这一点在 README.md 中有明确说明,也是本模型适用场景(结构化分类、自动化评估、规则化决策)的设计前提。

版本信息方面,README 记录了一个重要更新(2026 年 9 月 24 日):本仓库发布的是最新 9B 检查点,具备8,192 token 上下文上限与单字段最多 255 个选项的能力,官方评估使用T=1.0;更早的检查点可通过revision="original-2676"获取,而 Bespoke-Nimble-9B-v2 保持不变。本仓库不重复存放基础模型权重,使用时需要自行获取 Qwen3.5-9B 基础检查点。

二、仓库构成与关键文件

本仓库只包含适配器本身(约165 MiB)及配套运行资产,不包含完整基础权重,典型文件及其作用如下:

文件作用
adapter_model.safetensorsLoRA 适配器权重
adapter_config.jsonPEFT LoRA 配置(rank、alpha、target_modules 等)
tokenizer.json / tokenizer_config.jsonQwen3.5 分词器
chat_template.jinja聊天模板(prompt 渲染)
inference.py官方参考推理代码(NimbleModel)
serving_schema.py / candidate_schema.py / parallel_schema.py / extended_schema.py精确 prompt 构建与 schema 校验
schema_config.json训练契约:任务类型、上下文上限、候选编码、数据审计等
serving_config.json服务端候选编码(codebook)校验配置
temperature_config.json温度配置与适配器 SHA-256
provenance.json发布元数据(版本、基础模型、校验和)
requirements.txt固定依赖版本
SHA256SUMS文件校验和清单
LICENSEApache 2.0 许可证

从 adapter_config.json 可以看到本适配器的 LoRA 超参数:r=16、lora_alpha=32、lora_dropout=0.05、peft_type=LORA、task_type=CAUSAL_LM,目标模块覆盖了注意力(q_proj/k_proj/v_proj/o_proj)、线性注意力(in_proj_qkv/in_proj_z/in_proj_a/in_proj_b/out_proj)与 MLP(gate_proj/up_proj/down_proj)等投影层;基础模型固定为Qwen/Qwen3.5-9B,revision 为c202236235762e1c871ad0ccb60c8ee5ba337b9a。

三、环境要求与安装

3.1 硬件与软件前提

README 明确要求支持 BF16 的 CUDA GPU(官方原始运行环境为 PyTorch 2.8.0 + CUDA 12.8)。inference.py 在初始化时会强制检查torch.cuda.is_available()与torch.cuda.is_bf16_supported(),不满足条件直接抛出RuntimeError,因此在非 NVIDIA(或老架构不支持 BF16)的 GPU 上无法运行官方参考推理。

安装步骤分为两步:

hf download bespokelabs/Bespoke-Nimble-9B --local-dir nimble-model pip install -r nimble-model/requirements.txt
  • 第一条命令用huggingface_hub的hf download将仓库下载到本地nimble-model目录;
  • 第二条命令安装固定依赖;如果仓库被设置为私有,需要配置一个具备读取权限的 Hugging Face token;
  • 官方参考 helper 无需trust_remote_code=True,但 README 建议导入前先自行审阅 helper 代码。

3.2 依赖版本

requirements.txt 中固定了以下核心版本,安装时可直接照搬:

transformers==5.17.0 peft==0.21.0 accelerate==1.15.0 sentencepiece==0.2.2 pillow==12.3.0 huggingface_hub>=0.34

四、快速开始:加载模型并完成一次评分

将下载目录加入 Python 路径后导入NimbleModel(即 inference.py 中ParallelScorer的别名),传入模型目录即可完成加载。以下示例来自 README.md 并稍作展开:

import sys sys.path.insert(0, "nimble-model") from inference import NimbleModel model = NimbleModel("nimble-model") result = model.score( context="The store accepts returns within 30 days. This item was bought 12 days ago.", schema={ "eligible": { "type": "boolean", "description": "Is this item within the store return window?" } }, ) print(result["output"]) print(result["fields"]["eligible"]["probabilities"])

返回结果result的结构为:

  • result["output"]:字典,每个字段名映射到该字段的预测值(如{"eligible": True});
  • result["fields"][field_name]["probabilities"]:该字段各候选的概率分布;
  • result["fields"][field_name]["logits"]:各候选的原始 logits;
  • 顶层还包含temperature与temperature_fitted字段。

对布尔字段,结果中还会额外给出probability_true(见 inference.py 中kind == "noul"分支)。score()内部会逐字段独立处理,且完整保留训练时的 prompt 构造与概率计算方法,确保推理路径与评估路径一致。

五、Schema 字段类型详解

score(context, schema, score_fields=())中的schema是一个 JSON 对象:键为字段名,值为字段定义。支持两种字段类型:boolean与enum。

5.1 boolean 字段

如第四节示例,只需提供type与description。底层会把候选固定为[False, True](见 parallel_schema.py 的choices_for),无需手动指定 choices。

5.2 enum 字段(选项分类)

对于多选一场景,使用type="enum",并给出choices字符串列表、description,以及可选的choice_descriptions(用于给每个选项补充含义说明,辅助模型理解):

result = model.score( context="The report is 12 pages long and contains three charts.", schema={ "document_type": { "type": "enum", "description": "What kind of document is this?", "choices": ["report", "invoice", "email", "manual"], "choice_descriptions": { "report": "A structured summary of findings", "invoice": "A bill for goods or services", }, } }, )

5.3 rubric score 字段(评分等级)

评分字段本质上是取整数值的 enum:用字符串形式的整数作为choices(如["0", "1", "2", "3"]),并为每个等级写描述,然后把该字段名传入score_fields:

result = model.score( context="The answer covers all key points but lacks examples.", schema={ "quality": { "type": "enum", "description": "Rate answer quality.", "choices": ["0", "1", "2", "3"], "choice_descriptions": { "0": "No relevant content", "1": "Partial, many gaps", "2": "Good, minor omissions", "3": "Complete and precise", }, } }, score_fields=["quality"], )

此时返回值中除了prediction(选中等级对应的整数),还会给出expected_score(概率加权期望分数):sum(int(v) * p for v, p in zip(choices, probs))(见 inference.py)。从源码看,score_fields必须是 schema 中存在的字段,且要求为整数值 enum、各取值互不相同,否则会抛ValueError。

5.4 Schema 校验规则

无论是官方代码还是自定义调用,schema 都会经过 extended_schema.py(或 parallel_schema.py)中validate_schema的严格校验,核心规则包括:

  • schema 必须是非空对象,字段名必须是非空字符串;
  • 字段类型仅支持enum与boolean;
  • 每个字段必须提供非空description;
  • enum的 choices 必须是 1~255 个非空字符串,且不允许重复;
  • boolean的 choices 必须是[false, true]恰好各一次(默认即如此);
  • choice_descriptions的键必须对应真实存在的选项名;
  • 字段定义中不允许出现除type、choices、description、choice_descriptions之外的键。

这些校验保证了进入模型的 prompt 永远符合训练契约,避免格式漂移导致评分失真。

六、运行约束:255 个选项与 8,192 token 上限

本版本的两项关键上限在 schema_config.json 中固化:max_length: 8192、max_choices: 255。

  • 单字段最多 255 个选项:超出会直接报错。当选项数 ≤ 26 时使用单字母编码(A~Z);超过 26 个时,extended_schema.py 会从分词器词表中挑选满足条件的 2~3 位大写纯字母 token(如AA、AB…JT),并逐一验证其在"真实答案边界"上恰好编码为单个普通 token,这一编码方案在 schema_config.json 中登记为uppercase_single_token_v1。
  • 超长 prompt 直接拒绝而非截断:extended_schema.py 与 parallel_schema.py 在构建 prompt 时若检测到最长序列超过max_input_tokens,会抛出ValueError(错误信息明确写着 "Nothing was truncated"),保证上下文完整性。

此外,官方推理一次可以处理多个字段:prompt 构建使用__PARALLEL_FIELD_TARGET__标记,将共享的上下文与 schema 部分渲染一次,再为每个字段替换目标标记生成独立 prompt(见 extended_schema.py),score()内部逐字段执行前向并聚合结果。

七、底层原理:候选 token 直接评分

7.1 一次前向、只取最后位置

inference.py 的candidate_logits揭示了评分核心:模型前向时使用use_cache=False, logits_to_keep=1,只保留最后一个位置的 logits,然后通过gather取出各候选 token 对应的 logit,并用 mask 将不在候选项内的位置填充为-inf:

logits = model(input_ids=inputs["input_ids"], attention_mask=inputs["attention_mask"], use_cache=False, logits_to_keep=1).logits[:, -1, :].float() selected = logits.gather(1, inputs["candidate_ids"]) return selected.masked_fill(~inputs["candidate_mask"], -torch.inf)

也就是说,模型从未"生成"过任何 token,它只负责评估:在给定上下文中,哪个候选 token 最应该出现在答案位置。

7.2 概率与温度

inference.py 的decision_result中,概率计算只有一步:

probs = softmax(candidate_logits / temperature)
  • 默认temperature = 1.0(DEFAULT_TEMPERATURE);
  • 温度参数有严格校验:必须是正的有限数(bool 不被接受),否则抛ValueError(见 inference.py);
  • 预测值取原始 logits 的 argmax,概率则来自温度缩放后的 softmax;
  • 若在测试/评估场景提供labels,还会额外计算correct、nll与brier等指标。

7.3 温度校准的重要提醒

README 特别强调:本检查点没有单独拟合过温度(temperature_fitted: false),评估默认就是 T=1.0,不要沿用旧版本模型拟合的 2.179 校准值。这一点在 temperature_config.json 与 provenance.json 中一致登记:"temperature": 1.0、"temperature_fitted": false、"method": "softmax(candidate_logits / temperature)",且note字段明确"先前版本的校准不适用"。因此在使用本版本时,请直接使用默认温度;如需自定义,务必先做自己的校准实验。

八、供应链与契约校验:防止"错误适配器"被加载

仓库在可靠性上有非常细致的设计:加载模型时会做多层一致性校验,任何不匹配都会抛出ValueError:

  1. 训练契约校验:ParallelScorer.__init__读取 schema_config.json,校验task == "schema_candidate_classification_v2",并用 SHA-256 比对 parallel_schema.py、candidate_schema.py、extended_schema.py 等 prompt 源码哈希(对应prompt_source_sha256);
  2. 服务 codebook 校验:validate_serving_config读取 serving_config.json,比对max_choices、候选代码列表、候选 token id,以及各源文件的 SHA-256(见 inference.py);
  3. 编码契约校验:用真实分词器在真实答案边界上重建完整 codebook,确认与训练契约一致(见 candidate_schema.py)。

这些校验的意义在于:prompt 构建代码若被修改、候选编码若与分词器不匹配、或适配器与 base 模型 revision 不匹配,都会在加载阶段被拦截,而不是在推理时悄悄产生错误结果。此外 provenance.json 记录了发布元数据:release: v3-12026、adapter_sha256、基础模型与 revision,并声明weights_unchanged_from_evaluated_checkpoint: true,即发布权重与官方评估所用权重完全一致。

九、训练契约速览(辅助参考)

schema_config.json 中的data_audit与超参记录提供了该检查点的训练背景(仅供理解模型来源,非性能声明):

  • 数据规模:12,026 个训练行(8,468 个分组、5,370 个 family),324 个验证行;训练数据包含 13 个组件(如decision-skills-local、safety-local、public-banking77、public-boolq、public-multinli等公开数据集);
  • 任务构成:训练集中 choice(选项分类)8,080 行、noul(布尔)2,412 行、score(评分)1,534 行;
  • 超参数:learning_rate: 5e-05、batch_size: 2、gradient_accumulation: 4、warmup_steps: 451、max_steps: 4512、线性调度、seed: 17、训练 GPU 为 NVIDIA H100 80GB;
  • 推理精度:inference_precision: bf16_autocast,与官方推理路径一致。

十、常见问题与注意事项

  • 没有 NVIDIA GPU / 不支持 BF16:官方参考推理会直接报错;Mac/MLX 与 Linux 平台的加载器请参考 Nimble 项目官方 quickstart(README 中提供了入口,本文不展开外部链接)。
  • 想要旧检查点:加载时指定revision="original-2676"可获取先前版本,但请注意其上下文上限、候选数与温度校准与本版本不同,不要混用。
  • 温度参数:必须为正有限数;默认 T=1.0 是本版本的评估默认值,旧版 2.179 校准值不适用。
  • 私有仓库认证:若模型仓库为私有,需要配置可读权限的 HF token。
  • 超长输入:超过 8,192 token 的 prompt 会被拒绝而非截断,请在调用前自行控制上下文长度。

总的来说,Bespoke-Nimble-9B 提供了一条"结构化评分"的完整链路:从 README.md 给出的加载示例,到 inference.py 的候选 token 评分实现,再到 schema_config.json 与 serving_config.json 的契约校验,整个仓库都围绕"精确复现训练与评估路径"这一目标设计。对于需要稳定、可复现的布尔判断、选项分类与评分级结构化输出的工程场景,它是一个值得直接使用的参考实现。

  • 人工智能
  • 大模型
  • 微调
  • LoRA
  • 模型评测
  • NLP

【免费下载链接】Bespoke-Nimble-9B

项目地址:https://ai.gitcode.com/hf_mirrors/bespokelabs/Bespoke-Nimble-9B
点击查看免费下载

相关推荐

上一篇:OpenGame Template Skill原理:模板库如何从M0自动演化出游戏原型?
下一篇:Lap虚拟滚动实现解析:10万张照片库为何依然丝滑

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进