多 多宝库

Jeff

GitHub 开源 Python WindowsmacOSLinux ★ 1279 MIT
Jeff

Millisecond decisions, any domain: a 0.8B open "System 1" model that picks between your options with calibrated probabilities. One base, swappable LoRA adapters, on your own hardware.

作者
firelex
版本
v1.2
源码
查看仓库 ↗
主页
打开主页 ↗

DOWNLOAD下载地址

  • 站内直链 Jeff · 完整源码包 4.9 MB
  • 站内直链 Jeff · 一键安装工具包(含 Windows 脚本) 10 KB windows,macos,linux
  • GitHub 发布 GitHub 仓库(查看源码 / 提交反馈)

站内直链无需提取码,点击即可下载。

INTRO项目介绍

这是什么

Jeff 是一个只有 0.8B 参数的「系统 1」决策模型:你把情况和若干个选项用大白话写给它,它在一次前向传播里给每个选项返回一个校准过的概率。不生成文字,不需要解析输出,有独显时 22 毫秒就能给出一次决策。

它不跟你聊天,也不是用来写文章或做多步推理的。它的位置在大模型前面——让 Qwen3.8-27B 这类大模型去写作和规划,让 Jeff 先把那些高频、简单、要快的判断做掉:Jeff 先答,只有当它没有把握时,请求才继续交给后面的大模型。

它解决什么问题

小模型做判断有两个老毛病:不准、而且「不知道自己不准」(概率不可信)。Jeff 用两条办法压住:

  • 校准概率:每个选项给一个概率值,并且这个值经过温度拟合,说 90% 就是真的 90% 左右——所以你可以放心用「置信度低于阈值就转交大模型」这个策略。
  • LoRA 适配器:每个适配器约 41 MB,针对一个具体任务微调。官方提供了 9 个,也可以自己训。

官方给出的对比(同一个 27B 模型,加不加 Jeff 的差别):

  • 准确率:8 个适配器平均 86.6% → 95.3%
  • 每次决策耗时:8.1 秒 → 0.25 秒(快 38 倍)
  • 错误率:13.4% → 4.7%(错误少 2.8 倍)
  • 显存:27B 占 28.6 GB,Jeff 九个适配器全加载只多 1.96 GB

九个官方适配器

每个适配器管一件事,用哪个加载哪个(不指定适配器就走未经微调的基座零样本模式):

  • guard — 提示注入与越狱拦截,98.4%
  • spam — 短信与邮件垃圾/钓鱼识别,98.4%
  • tools — Agent 该调用哪个工具,97.9%
  • nav — 语音指令对应屏幕上哪个元素,97.0%
  • ground — 答案有没有被原文支持(重排 + 接地),97.0%
  • support-intents — 客户到底想要什么,96.8%
  • triage — 工单紧急度与情绪,91.8%
  • legal-clauses — 合同条款类型,85.7%
  • emotion — 短评论里 27 种情绪里最强的一种,60.6%(这题人类标注都不一致,27B 只有 35.6%)

资源占用与硬件

  • 权重体积:0.8B 模型 16 位约 1.7 GB
  • NVIDIA RTX PRO 6000:每次决策约 22 毫秒;加载全部九个适配器、每次请求都切换适配器,中位数 30 毫秒、显存 1.96 GB
  • Apple M4 Max(MLX 后端):约 28 毫秒
  • 纯 CPU(32 线程):463 毫秒——能跑,但慢一个量级

也就是说:有独显最好,Mac 的 Apple 芯片也可以,纯 CPU 也能用,只是别指望毫秒级。

怎么用

它对外是一个本地 HTTP 服务(默认 127.0.0.1:8000,可用 PORT 改),三个接口:

  • GET /health — 健康检查
  • GET /v1/models — 当前可用的模型与适配器列表
  • POST /v1/systemone — 发一次决策请求

官方提供了 Python 客户端和 TypeScript 客户端,Python 侧用法大致是这样(先起服务,再调用):

from jeff import Client
from jeff.client import choice_question, yes_no_question

jeff = Client("http://localhost:8765", model="jeff-latest")
answers = jeff.ask("包裹到的时候已经压坏了,我要退款。", {
    "team": choice_question({"refunds": "退款与支付", "parcels": "包裹破损或丢失",
                             "login": "账号与登录问题"}, "这单该谁来处理?"),
    "angry": yes_no_question("客户生气了吗?"),
})
answers.choice("team").key   # "parcels",同时带概率

三类问题:choice(最多 254 个选项)、yes_no、score(打分)。两条必须遵守的规矩:选项的 key 永远不要用纯数字;请求里不变的部分放前面、变化的部分放最后。

用之前要知道的

  • 适配器绑定基座版本:v1.2 的适配器只能用在 Jeff-Qwen3.5-0.8B v1.2 上,换成别的基座服务端会直接拒绝。换基座版本需要重训适配器,但数据集可以沿用。
  • 小模型不会推理:它是在你给的选项之间做快速校准的选择,不是用来做多步推理的。
  • 只支持英文文本,选项上限 254 个(另一个 Gemma 版基座只支持 26 个)。
  • 它是个分类器,不是规划器:把「每个选项意味着什么」在代码里想清楚,不要让它去预测。

授权的坑(重要)

这个项目的代码是 MIT、模型权重是 Apache 2.0,可以商用。但注意仓库首页的「Licence」一节写得很清楚:他们只公开权重和代码,不公开训练数据;训练数据里有一部分来源是 CC BY-SA 等分享相同的协议。

谁适合用

  • 想给本地大模型加一层快速前置判断、省掉大量「杀鸡用牛刀」的调用
  • 做 Agent、客服、内容审核、语音交互,需要毫秒级且概率可信的分类
  • 想学 LoRA 微调:仓库自带 adapter kit(训练前查数据有没有「捷径特征」)和完整的训练脚本,40 分钟到 4 小时能训出一个适配器
  • 只想在自己的机器上跑、不想把数据发给任何云服务

GUIDE安装与使用教程

这篇教程带你在一台普通电脑上把 Jeff 装起来并跑通。全文步骤都在真实环境里跑过一遍,截图是真实终端输出,不是照着 README 抄的。

开始之前

系统要求:

  • Windows 10/11、macOS、或 Linux 都行
  • Python 3.12 或更高(这是硬要求,比多数项目严格)
  • 硬盘留 8 GB 以上(Python 依赖约 3 GB,模型权重 1.7 GB)
  • 装适配器训练才需要 NVIDIA 显卡;只做推理,纯 CPU 也能跑

硬件建议: 有 NVIDIA 独显最快(每次决策约 22 毫秒);Apple 芯片的 Mac 用 MLX 后端约 28 毫秒;纯 CPU 大概 463 毫秒一次,能用但慢一个量级。

第 1 步 · 确认 Python 版本

第 1 步 · 确认 Python 环境
第 1 步 · 确认 Python 环境

打开终端(Windows 用 PowerShell 或 CMD),敲:

python --version
pip --version

看到 3.12 以上才能继续。如果提示找不到 python,说明装 Python 时没勾「Add python.exe to PATH」,重装一遍并勾上,然后重开一个终端。

第 2 步 · 千万不要 `pip install jeff`

第 2 步 · 同名包陷阱
第 2 步 · 同名包陷阱

这一步是本文最想提醒你的地方。PyPI 上确实有一个叫 jeff 的包,但它跟本文的 Jeff 毫无关系 —— 那是另一个人写的、用来生成授权文件的小工具(0.3.1 版,作者 Oskar Cieslik)。

如果你手快敲了 pip install jeff,不会报错,只会装上一个完全没用的东西,然后奇怪为什么 jeff-serve 命令不存在。

正确做法只有一个:从源码安装,往下看。

第 3 步 · 建一个独立环境

不动系统里的 Python,单独开一个环境给 Jeff:

python -m venv jeff-env

Windows 激活:

jeff-env\Scripts\activate

macOS / Linux 激活:

source jeff-env/bin/activate

激活成功后命令行前面会出现 (jeff-env)。

第 4 步 · 装依赖(版本号别改)

第 4 步 · 安装依赖
第 4 步 · 安装依赖

Jeff 的依赖表把版本号全部写死了,照着装就行:

pip install torch==2.14.0 torchvision==0.29.0 transformers==5.17.0 pillow==12.3.0 fastapi==0.141.1 uvicorn==0.52.4 safetensors==0.8.0 numpy==2.5.3 huggingface-hub==1.31.0 peft==0.21.1

为什么要锁版本: transformers 5.x 的接口和 4.x 是两回事,放宽版本限制极可能装上一个对不上的版本,然后在莫名其妙的地方报错。

国内网络慢的话加个镜像(实测阿里云可用):

pip install -i https://mirrors.aliyun.com/pypi/simple/ torch==2.14.0 ...(后面同上)

一共约 3 GB,耐心等它下载完。

第 5 步 · 装上 Jeff 本体

第 5 步 · 安装本体
第 5 步 · 安装本体

依赖装完只是装了「零件」,还得把项目本身装上。进到源码目录(解压出来那个 jeff-main),执行:

pip install .

这一步才生成那 **20 个 jeff-* 命令**。常用的四个:

  • jeff-serve —— 启动决策服务(核心)
  • jeff-kit —— 训练数据质量检查工具
  • jeff-train —— 训练基座或 LoRA 适配器
  • jeff-evaluate —— 在测试集上评测

验证一下装没装上:

python -c "import jeff, jeff.server, jeff.kit.cli; print('OK')"

第 6 步 · 用 jeff-kit 检查你的训练数据

这一步不需要模型权重,装上就能用,也是这个项目里最实用的工具。

Jeff 的适配器好不好,几乎全看训练数据。而数据里最坑的问题是捷径特征:某个表面特征(比如文本长度)恰好能区分标签,模型学会它之后,在你自建的测试集上分数很高,一到真实输入就崩。官方说他们做九个适配器,每一个都至少栽过一次。

jeff-kit 就是用来提前把这些问题查出来的。它自带一份 60 行的样例数据,可以拿它先熟悉流程。

① 检查每一行是否合法:

第 6 步 · 检查数据
第 6 步 · 检查数据

jeff-kit check-rows examples/adapter-kit/sample/rows.jsonl

输出 60 rows, 8 families: all rows valid 就是全部合规。它会挑出的毛病包括:字段缺失、标签不在选项里、选项 key 用了纯数字(JavaScript 会静默重排)、同一个 id 出现两次、模板占位符 ${...} 忘了替换。

② 按「组」切分数据:

第 7 步 · 切分数据
第 7 步 · 切分数据

jeff-kit split examples/adapter-kit/sample/rows.jsonl --out runs/split --test 0.25 --development 0.125 --calibration 0.125 --seed 1

关键在于 family(组):同一家公司、同一个文档的样本算一组,切分时整组一起走,绝不把同一家的样本拆到训练集和测试集两边。这样测出来的分数才是真实水平。

切出来四份,各有用处:train 训练用、development 选检查点、calibration 专门用来拟合温度、让概率可信、test 测试用。

③ 查数据泄漏:

第 8 步 · 查泄漏
第 8 步 · 查泄漏

jeff-kit leak-check --train runs/split/train.jsonl --against runs/split/test.jsonl runs/split/development.jsonl runs/split/calibration.jsonl

训练集里哪怕混进一条测试样本(或它的近似复制),评测分数就白测了。

④ 查捷径特征:

第 9 步 · 查捷径特征
第 9 步 · 查捷径特征

jeff-kit shortcut-report --train runs/split/train.jsonl --test runs/split/test.jsonl --out runs/shortcuts.md

拿它自带的样例数据跑,工具报出 3 个问题。最典型的一条:只看正文长度就能 100% 区分 refund 标签(随机水平只有 50%)。这种数据拿去训练,模型学的就是「字数」而不是「意思」。

看到这类警告,回头改数据,别硬训。

第 7 步 · 跑一遍官方测试(可选)

第 10 步 · 测试套件
第 10 步 · 测试套件

python -m pytest -m "not slow" -q --continue-on-collection-errors

本机实测:156 个通过。剩下的失败和报错都不是项目的问题,见下面「兼容性说明」。

第 8 步 · 下载模型权重

第 11 步 · 下载权重
第 11 步 · 下载权重

服务要跑起来,必须有模型权重(1.7 GB)。国内直连 HuggingFace 基本不通,用国内镜像:

Windows:

set HF_ENDPOINT=https://hf-mirror.com
set HF_HUB_DISABLE_XET=1
hf download mstrasser/Jeff-Qwen3.5-0.8B --revision v1.2 --local-dir Jeff-Qwen3.5-0.8B-v1.2

macOS / Linux:

export HF_ENDPOINT=https://hf-mirror.com
export HF_HUB_DISABLE_XET=1
hf download mstrasser/Jeff-Qwen3.5-0.8B --revision v1.2 --local-dir Jeff-Qwen3.5-0.8B-v1.2

两个环境变量缺一不可:

  • HF_ENDPOINT 把下载指向国内镜像(不设就是连 huggingface.co,大概率超时)
  • HF_HUB_DISABLE_XET=1 关掉新版 Xet 传输通道。不关会直接报 401 Unauthorized(错误信息指向 cas-server.xethub.hf.co,看起来像权限问题,其实是通道不通,极容易误判)

镜像偶尔抽风连接超时,客户端会自己重试,看到 Retrying in 1s [Retry 1/5] 属正常,别急着按 Ctrl+C。

想连适配器一起下(每个约 41 MB,按需选):

hf download mstrasser/Jeff-Qwen3.5-0.8B-guard --local-dir adapters/guard

可选的适配器名有:guard triage support-intents tools ground nav emotion spam legal-clauses。

第 9 步 · 启动决策服务

第 12 步 · 启动服务
第 12 步 · 启动服务

Windows:

set JEFF_CHECKPOINT=Jeff-Qwen3.5-0.8B-v1.2
set JEFF_ADAPTERS=adapters
set PORT=8765
jeff-serve

macOS / Linux 把 set 换成 export,Apple 芯片再加一句 set JEFF_BACKEND=mlx。

服务跑起来后,浏览器打开 http://127.0.0.1:8765/health 能看状态。

如果报错说找不到 checkpoints/selected/decision_config.json,说明权重没准备好 —— 这是新人最容易卡住的一步,jeff-serve 启动时必须能读到模型目录,没有就立刻退出。

可用的接口:

  • GET /health —— 健康检查
  • GET /v1/models —— 看当前挂载了哪些适配器
  • POST /v1/systemone —— 发一次决策请求
  • POST /v1/adapters/reload —— 不重启加载新适配器

第 10 步 · 写第一个调用

Python 客户端(pip install . 时已经装上了):

from jeff import Client
from jeff.client import choice_question, yes_no_question

jeff = Client("http://localhost:8765", model="jeff-latest")
answers = jeff.ask("The parcel arrived crushed and I want my money back.", {
    "team": choice_question({
        "refunds": "Refunds and payments",
        "parcels": "Damaged or lost parcels",
        "login": "Account and login problems",
    }, "Which team should handle this ticket?"),
    "angry": yes_no_question("Is the customer angry?"),
})
print(answers.choice("team").key)

想用适配器,就把 model="jeff-latest" 换成 jeff.with_model("guard") 这样。

两条必须遵守的规矩:

1. 选项的 key 永远不要用纯数字。 用 "refunds" 这种描述性短词。纯数字会被前端 JSON 处理悄悄重排。

2. 请求里不变的部分放前面,变化的部分放最后。 这样模型缓存能命中,速度更快。

兼容性说明:Windows 上哪些能用,哪些不能

实测结论(本机 Windows + Python 3.13):

能用的:

  • jeff-serve 决策服务
  • Python 客户端 / TypeScript 客户端
  • jeff-kit 数据检查全套
  • jeff-evaluate、jeff-decoder、jeff-encoder 等推理相关模块

不能用的:

  • jeff-train 训练、jeff-data 数据构建这条链路

原因是源码里的 src/jeff/events.py 第 3 行直接 import fcntl,而 fcntl 是 Unix 专有模块,Windows 上不存在。实测 import jeff.train 会直接报:

ModuleNotFoundError: No module named 'fcntl'

想在 Windows 上训适配器,用 WSL(Windows 里的 Linux 子系统)就行。

常见问题

Q:为什么会有 ModuleNotFoundError: No module named 'pyarrow'?

pyarrow 属于「训练/评测」那组可选依赖(datasets 的依赖),只装推理依赖时不会有。用到 jeff-grounded、jeff-evaluate 这类命令时补装即可。

Q:跑测试时一堆用例报错,是装坏了吗?

大概率不是。实测 156 个通过,剩下的分三类:① 需要 NVIDIA 显卡的用例(test_cuda_available 之类);② 需要联网下载第三方 tokenizer 的用例(比如 google/gemma-3-270m-it);③ 用了 fcntl 的 Unix 专用用例。都不是安装问题。

Q:CPU 上能跑吗?

能。官方数据是 32 线程 CPU 约 463 毫秒一次决策。做批处理、离线任务没问题;要实时响应还是得有独显。

Q:一定要下载 1.7 GB 权重吗?

是的,jeff-serve 启动时必须能读到模型目录,没有权重它直接退出。这是硬性的。

一句话总结

装 Jeff 的坑总共三个:别装 PyPI 上的同名包、权重下载要设那两个环境变量、启动前先备好模型目录。绕开这三个,剩下的都是等下载。