kshetrajna12/reflex · 上手攻略
- 仓库:kshetrajna12/reflex
- 链接:https://github.com/kshetrajna12/reflex
- 分类:AI 推理 / 决策模型 / 校准概率(calibrated probabilistic decisions)
- 作者:spark
- 更新:2026-09-21
是什么
reflex 是一个小型、可在自有 GPU 上跑的「决策模型」(decision model)。它把一段输入(工单、文档、照片、JSON 状态)和若干固定选项的问题一次给到基于 Qwen3.5-4B 的推理后端,同时输出每个选项的校准概率,并直接告诉你置信度(confidence)。它不输出自由文本,只输出数字,所以结果永远落在你给定的选项里——结构上不可能「幻觉」出列表之外的答案。
它是对 TypeSafe 于 2026 年 9 月发布的闭源模型 Jev(System One 模型)的开源复刻:同样的请求/响应格式、同样的题型(noul / choice / score),底层用 Qwen3.5-4B 作为「快思考」系统,搭配校准与可选 LoRA 微调,把分类/路由/打分这类「快速、结构化判断」从大聊天模型里拆出来。
解决什么问题
大聊天模型擅长推理,但当你只需要「这是哪一类?紧急程度?退款?」这种结构化判断时,它们:
- 慢且贵:每个判断都要重新生成一段自然语言;
- 结果不稳定:JSON 经常写出 schema 不符的格式;
- 置信度不可信:模型嘴上说「85%」,实测命中率往往远低于 85%,无法用阈值做自动路由。
reflex 把这类「System 1」任务从「System 2」聊天模型里剥离,给出带置信度且经过温度校准的数字输出,目标是让你能直接拿百分比做策略("team=payments 且 prob≥0.9 → 自动派单;否则转人工")。
典型适用场景:
- 客服工单三分类:路由团队、是否升级、紧急程度(0/1/2);
- 内容审核:是否违规、哪一类违规、置信度;
- 图像三元组判断:图是否匹配描述、属于哪个标签、严重度;
- RAG 检索质量门:passage 相关性、是否需要兜底答案。
快速安装
硬件:Linux + NVIDIA GPU(默认模型 8 GB 显存就够),Python 3.12,uv 包管理器。
git clone https://github.com/kshetrajna12/reflex
cd reflex
uv sync # 装 PyTorch(CUDA 13)、transformers 等
uv run python examples/support_ticket.py # 首次会下载 Qwen3.5-4B (~8 GB)
第一次调用约 20 秒等 GPU kernel 编译,之后单请求约 100 ms。
WebGPU 浏览器版(仅推理,模型换成 Qwen3.5-0.8B,约 650 MB,要求 Chrome/Edge/Safari 18+):访问 kshetrajna12.github.io/reflex/,选 preset → 加载模型 → 拖入图片 → Run。数据全部本地,无任何上传。
核心用法
三种题型(primitives)
| 类型 | 问的什么 | 返回 |
|---|---|---|
noul |
"这件事是不是真的?" | yes 概率(0~1) |
choice |
"选哪一个?" | 最佳选项 + 每个选项概率 + 置信度 |
score |
"在这个有序量表上是多少?" | 加权位置(0~N-1)+ 各 level 概率 + 图例 + 置信度 |
Python 示例:客服工单
from reflex import Engine, SystemOneRequest
engine = Engine.load("Qwen/Qwen3.5-4B")
resp = engine.answer(SystemOneRequest(
state={"email": "Hi, I was charged twice for my subscription this month, please fix."},
questions={
"team": {
"type": "choice",
"instructions": "Which team should handle this?",
"criteria": {
"billing": "charges, refunds, invoices",
"technical": "bugs, outages",
"sales": "pricing, upgrades",
},
},
"angry": {"type": "noul", "instructions": "Is the customer angry?"},
"urgency": {
"type": "score",
"instructions": "How urgent is this?",
"criteria": ["can wait a week", "should be handled today", "blocked right now"],
},
},
))
print(resp.answers["team"].choice, resp.answers["team"].probabilities)
print(resp.answers["angry"].noul) # probability of yes
print(resp.answers["urgency"].score) # 0.0 .. 2.0, weighted
state 可以是字符串或任意 JSON;想喂图片就在 state 里塞 {"type": "image", "source": "..."}。一次请求里的多个 question 并行独立回答。
HTTP 服务(与 Jev 客户端代码完全兼容)
uv run reflex-serve --model Qwen/Qwen3.5-4B --port 8008
curl -s localhost:8008/v1/systemone -H 'content-type: application/json' -d '{
"state": "The export button crashes in Safari but works in Chrome.",
"questions": {
"browser_specific": {"type": "noul", "instructions": "Is the bug browser-specific?"},
"severity": {
"type": "score",
"instructions": "How severe is this?",
"criteria": ["cosmetic", "degraded but there is a workaround", "blocking"]
}
}
}'
请求/响应 shape 与 TypeSafe 托管 API 一致,写给 Jev 的客户端可以直接把 baseURL 改成 http://localhost:8008。
校准(让置信度真的准)
原模型概率会偏自信。跑 1200 道 MMLU 题目测一次,再 fit 一个温度:
uv run reflex-eval-mmlu --n 1200 --fit-temperature runs/calibration.json
uv run reflex-serve --calibration runs/calibration.json
| 模型 | 准确率 | ECE(校准前) | ECE(校准后) |
|---|---|---|---|
| Qwen3.5-4B | 72% | 0.090 | 0.039 |
| Qwen3-8B | 71% | 0.264 | 0.061 |
Jev 报告 ECE = 0.031;reflex + 温度缩放在 4B 模型上做到 0.039,已经接近闭源水平。
用自有数据微调(LoRA)
数据格式:每行一个 JSON 对象,与请求同结构 + labels 字段。标签可以是硬标签("billing" / true / 2)也可以是软标签(0.67 / {"billing": 0.7, "sales": 0.3}),后者才匹配 proper scoring rule(log loss / Brier)想要的真概率。
reflex 内置 8 个公开数据集的转换脚本(路由意图、考试题、toxicity 含软标签、幻觉检测、passage 相关性、response 有用性、code-review chunk):
uv run reflex-data mix --out runs/mix_train.jsonl --eval-out runs/mix_eval.jsonl --per-source 800
uv run reflex-calibrate train --data runs/mix_train.jsonl --val runs/mix_eval.jsonl --out runs/lora-mix
uv run reflex-serve --adapter runs/lora-mix --calibration runs/lora-mix/calibration.json
Qwen3.5-4B 上 1 个 epoch(每个源 200 条 hold-out)的实测:
| 阶段 | 准确率 | ECE |
|---|---|---|
| 原始模型 | 62.7% | 0.120 |
| + LoRA | 76.8% | 0.051 |
| + LoRA + 温度 | 76.8% | 0.024 |
按任务:toxicity 50%→94%,幻觉检测 78%→99%,code-review "needs a comment" 50%→74%。
典型适用场景
- 客服 / 工单系统:自动路由 + 紧急度评分 + 是否升级 + 是否退款。约 100 ms / 单工单,4B 模型 8 GB 显存,单卡一天能跑几十万件。
- 内容审核流水线:toxicity / 违规分类 / 置信度门控,避免误杀。
- RAG 检索质量门:passage 与 query 相关性、是否幻觉、是否需要 fallback 到人工回答。
- 图像小模型判断:图–文匹配、视觉分类、UI 截图 bug 分级(state 里塞图片字段即可)。
- 离线 / 隐私敏感场景:纯本地推理,无任何外部 API 调用,WebGPU 版连浏览器都跑得了。
坑与注意
⚠️ GPU kernel 首次编译 ~20 秒:首次 engine.answer() 调用要等,之后才进入 ~100 ms/次 的稳态。线上做 P50 指标前先 warm up。
⚠️ 温度只能修置信度,不修准确率:原始模型答错的题,温度缩放后还是答错。要真正提准确率必须 LoRA 微调 + 真标签(建议软标签)。
⚠️ 校准数据要代表线上分布:reflex-eval-mmlu 跑出来 0.039 ECE,但只代表 MMLU 这一分布;你的业务工单要重新校准,否则 ECE 可能反弹。
⚠️ score 类型返回的是加权位置,不是离散 label:例 urgency.score = 1.9 表示分布在 "low 4% / medium 1% / high 95%" 加权后的位置,下游逻辑要按 score 而非 argmax 解释。
⚠️ 图片字段是 state 内的特殊 JSON:{"type": "image", "source": "..."} 必须放在 state 树里,不能作为顶层 question 的 input。
⚠️ WebGPU 版是 0.8B 模型,精度和校准都差一截:官方说「less calibrated」,演示用可以,生产别用。
⚠️ 模型是 Qwen3.5-4B + LoRA,不是 chat 模型:别拿它来生成自然语言回答,所有输出都是结构化数字/枚举值。
与同类对比
| 项目 | 形态 | 速度 | 输出形态 | 校准 | 与 Jev 兼容 |
|---|---|---|---|---|---|
| kshetrajna12/reflex | 开源、Qwen3.5-4B 本地 | ~100 ms | 数字 + 置信度 | 温度 + LoRA | ✅ 完全兼容 |
| TypeSafe Jev(闭源) | 托管 API | ~? | 同上 | ECE 0.031 报告值 | — |
| 大聊天模型 + JSON mode | 开源/闭源 | 1~5 s | 自由文本 + JSON | 不可信 | ❌ |
| Outlines / Guidance / lm-format-enforcer | 开源约束解码 | 看后端 | 强 schema | 无显式校准 | ❌ |
| 专用分类模型(如 SetFit) | 开源 | <10 ms | 标签 | 可校准 | ❌ |
reflex 的差异化是「校准概率 + Jev 协议兼容 + 可本地化」三件套:如果你的下游策略是按概率做阈值(比如自动派单 / 升级),reflex 是目前最直接的开源选项。
一句话推荐结论
如果你要做「按概率阈值自动派单/审核/分级」的 System 1 任务,又不想被闭源 Jev 绑定,reflex 是当下最省事的本地替代——协议兼容、ECE 接近闭源、100 ms 量级、单卡 8 GB 就能跑。⚠️ 注意:校准数据要用自己业务的,温度缩放只能修置信度不修准确率,原始模型答错的题需要 LoRA 喂真(软)标签才能救回来。
来源:reflex GitHub README(kshetrajna12/reflex · 抓取 2026-09-21);TypeSafe Jev 介绍博客(typesafe.ai/blog/introducing-system-one-models-and-jev)。
不确定处:⚠️ WebGPU 演示页是否仍在线(截至抓取时可达);⚠️ reflex 与 Jev 的 ECE 对比数字来自 reflex 自述,未与 TypeSafe 官方独立验证。