引言
"决策不需要生成一段话来解释自己,它只需要一个概率分布。"
这是"一天一个开源项目"系列的第 225 篇。今天的项目是 NanoJev。
大多数用 LLM 做决策的方案都绕不开一个尴尬的效率问题:让模型自回归地生成一段文本(比如"我认为应该选择选项 B,因为……"),再从文本里解析出最终决策。这个过程需要逐 Token 解码,慢、贵,而且模型给出的"置信度"往往只是文本里顺嘴一提的形容词,不是真正校准过的概率。
如果一个任务的本质就是"给定状态和一组候选项,告诉我每个候选的概率",为什么还要让模型先生成一堆文字再解析?NanoJev 的答案是:不生成,直接输出分布。它是"Jev"这套并行决策模型系统的轻量复刻版,基于 Qwen3-0.6B 骨干网络加上专门的决策头,输入状态和问题,一次前向传播直接吐出完整的概率分布——零输出 Token 解码。
954 Stars,MIT 协议,用迷宫导航和 Snake 游戏基准验证了这套思路的实际效果。
你将学到什么
- NanoJev 如何用"状态+问题+候选集"三元组结构化一个决策
- 三种决策头类型:动态选择(Choice)、布尔判断(Boolean)、有序评分(Score)
- 为什么"零输出 Token 解码"比自回归生成更适合决策场景
- 完整的训练流程:构建查询 → 数据整理 → 训练 → 评估 → 服务
- NanoJev 与原版 Jev、未微调 Qwen3-0.6B 在游戏基准上的实测对比
前置知识
- 了解 LLM 的基本推理机制(自回归生成 vs 单次前向传播)
- 熟悉基础的概率与分类/回归任务概念
- 可选:了解强化学习中的奖励建模概念
项目背景
项目简介
NanoJev 的官方定义是:"一个 0.6B 参数的并行决策模型。状态和问题输入,完整的概率分布输出——零输出 Token 解码"(A 0.6B parallel decision model. States and questions in, complete probability distributions out—with zero output-token decoding)。
需要澄清的是,这不是图像生成或编辑工具,而是一个结构化决策模型/推理框架——本质上是把 LLM 的语言理解能力保留下来,但把输出端从"生成文本"改造成"输出校准过的概率分布",适用于游戏智能体决策、概率校准研究等场景。
团队与项目信息
- 作者:TianyuCodings
- 协议:MIT License
- 基础模型:Qwen3-0.6B
- 相关资源:模型仓库 C-Tianyu/NanoJev、数据集 C-Tianyu/NanoJev-Data(均在 HuggingFace)
项目数据
- ⭐ GitHub Stars:954
- 🍴 Forks:127
- 👀 Watchers:8
- 📄 协议:MIT
- 📊 提交次数:13 Commits
主要功能
解决什么问题
传统 LLM 决策方案:
状态+问题 → 自回归生成文本("我认为应该选B,因为……")
↓ 解析文本得出最终决策
↑ 逐 Token 解码慢且贵
↑ "置信度"只是文本里的形容词,没有真正校准
NanoJev 的做法:
状态+问题+候选集 → 单次前向传播 → 直接输出完整概率分布
↑ 零输出 Token 解码,速度快
↑ 分布经过训练校准,可直接用于排序/贪心选择/概率采样
↑ 单次前向可批量处理多个独立状态和问题
(官方示例:"6 states · 18 questions · 44 candidate paths · 1 backbone forward")
使用场景
-
游戏智能体决策
- 迷宫导航(8×8 到 50×50 多种规模)、Snake 贪吃蛇游戏的实时决策
-
局部安全判断
- 碰撞规避等需要快速布尔判断的场景,结合代码规划一起使用
-
概率校准研究
- 用 CE(交叉熵)/Brier 损失和成对正确奖励学习做概率校准实验
-
需要批量决策的场景
- 一次前向传播评估多个候选路径,适合需要高吞吐决策的应用
快速开始
最简单的方式:本地跑交互式演示(不需要模型权重)
git clone https://github.com/TianyuCodings/NanoJev.git
cd NanoJev
python3 -m http.server 8080 --bind 127.0.0.1 --directory web
访问 http://127.0.0.1:8080/side-by-side.html 查看三面板对比演示,或 arcade.html(竞技场演示)、comparison.html(早期基准查看器)。
完整运行:下载模型权重并启动服务
# 安装依赖
python -m pip install -r requirements-toy.txt
# 下载模型检查点和数据集
python -c "
from huggingface_hub import snapshot_download
snapshot_download(
repo_id='C-Tianyu/NanoJev', local_dir='checkpoints/NanoJev',
allow_patterns=['best.safetensors', 'config.json', 'tokenizer/*', 'backbone_config/*'],
)
snapshot_download(
repo_id='C-Tianyu/NanoJev-Data', repo_type='dataset', local_dir='data/NanoJev',
)
"
# 启动持久化服务
python scripts/serve_decisions.py \
--checkpoint-dir checkpoints/NanoJev \
--web-root web --port 8765
服务启动后加载模型一次,通过 POST /api/evaluate 接受重复的批量决策请求。
核心特性
1. 三种决策头类型
| 类型 | 支持范围 | 机制 |
|---|---|---|
| 动态选择(Choice) | 2–255 个候选项 | 共享标量头 + 集合注意力机制,输出每个候选的概率 |
| 布尔判断(Boolean) | 单一命题 | 单路径 sigmoid,输出命题为真的概率 |
| 有序评分(Score) | 2–10 档评分 | 计算等级分布的概率加权期望值 |
2. 三元组结构化决策
每个决策由状态(state)、问题(question)、**候选集(candidate set)**三部分定义。共享的决策头处理输入并针对候选集返回相应类型的分布输出。
3. 五步训练流程
构建查询(Build queries)
↓ 生成状态、问题、候选描述及目标分布
数据整理(Organize data)
↓ 相关地图、规则及变体保持在同一数据划分中
训练(Train)
↓ Qwen3-0.6B 初始化 + 决策头预热 + complete-question distribution losses
评估(Evaluate)
↓ 衡量概率质量 + 游戏控制器记录实际动作
服务与可视化(Serve and visualize)
↓ 复用持久化模型端点,浏览器回放完整轨迹
4. 多种预训练检查点变体
| 变体名称 | 用途 |
|---|---|
variants/local_atomic_seed17 | 50×50 迷宫演示 |
variants/games_gold_seed17 | Snake 演示 |
variants/games_api_seed17 | 完整地图对比基准 |
variants/events_ce_seed17 / events_brier_seed17 / events_paired_seed17 | 校准决策实验(不同损失函数) |
深入剖析
"零输出 Token 解码"的性能意义
NanoJev 最核心的架构决策是彻底放弃自回归生成,把 LLM 的输出端改造成结构化的决策头。这个改造带来的性能差异,官方给出了一个很直观的数字:
"6 states · 18 questions · 44 candidate paths · 1 backbone forward"
意味着:
6 个独立状态 + 18 个问题 + 44 条候选路径
↓ 全部塞进一次骨干网络前向传播
↓ 而不是 44 次自回归生成
自回归生成的开销是逐 Token 累积的——生成一段解释性文字可能需要几十到上百次前向传播(每个 Token 一次)。NanoJev 把 44 条候选路径的评估压缩进"1 次骨干网络前向",本质上是把"用文本表达置信度"这件事换成了"用模型内部的数值直接表达概率",绕开了整个自回归解码的开销链条。
Choice / Boolean / Score 三种头的设计取舍
为什么不用一个通用头处理所有决策类型?三种头对应的其实是三类本质不同的统计问题:
Choice(动态选择):
候选数量可变(2-255个)→ 需要"集合注意力"机制
↑ 模型要理解"这些候选是互斥的一组选项",而不是独立判断
Boolean(布尔判断):
单一命题,是/否二元问题 → 单路径 sigmoid 就够了
↑ 不需要感知其他候选的存在
Score(有序评分):
等级之间有顺序关系(1星到5星)→ 不能简单当分类问题处理
↑ 用概率加权期望值,让"3.5星"这种非整数期望自然产生
这个设计体现了一个朴素但容易被忽视的原则:决策的统计结构不同,损失函数和输出头也应该不同。把"选哪个选项""是否为真""打几分"强行塞进同一个 softmax,会丢失每种问题类型本身的结构信息。
训练效果的实测对比:小模型 vs 微调
NanoJev 在三个游戏基准上和原版 Jev、未微调的 Qwen3-0.6B 做了对比,结果颇有说服力:
| 基准 | NanoJev | Jev(原版) | 未微调 Qwen3-0.6B |
|---|---|---|---|
| 50×50 迷宫(尝试次数/碰撞次数) | 244 次 / 36 次碰撞,到达目标 | 2,738 次 / 1,044 次碰撞,到达目标 | — |
| 12×12 Snake(食物数/存活) | 27 个食物,存活到终点 | 30 个食物,存活到终点 | 25 个食物,被困 |
| 40 地图导航基准(测试集/OOD) | 95% / 90% | 100% / 95% | 35% / 15% |
几个值得注意的点:
- 未微调的 Qwen3-0.6B 表现明显落后(35%/15% vs NanoJev 的 95%/90%),说明专门训练的决策头确实带来了实质性提升,不是"换个模型名字"的营销包装
- NanoJev 在 50×50 迷宫上尝试次数远少于原版 Jev(244 次 vs 2,738 次),说明轻量复刻版在特定任务上反而更高效,这可能得益于任务范围更聚焦的训练数据
- NanoJev 整体精度略低于原版 Jev(比如导航基准 95% vs 100%),符合预期——用更小的资源投入复刻一个系统,性能上有所取舍是合理的权衡
定位:研究性复刻,不是商业产品
NanoJev 明确把自己定位为"轻量级、可复现"的研究性替代方案。这个定位很清晰:它不追求超越原版 Jev 的性能,而是用更小的训练成本和更简单的部署方式,让更多研究者能够验证和扩展"并行决策模型"这个思路。路线图里提到的扩大数据规模、RLCD(对比蒸馏强化学习)扩展等方向,都指向"继续探索这套架构的边界"而不是"打磨成产品"。
项目地址与资源
官方资源
- 🌟 GitHub:github.com/TianyuCodin…
- 🤗 模型:C-Tianyu/NanoJev(HuggingFace)
- 🤗 数据集:C-Tianyu/NanoJev-Data(HuggingFace)
- 📄 协议:MIT License
- 🐛 Issues:GitHub Issues
相关资源
- Qwen3 — NanoJev 使用的 0.6B 骨干网络
- Brier Score — NanoJev 训练中用于概率校准的评分方式之一
总结与展望
核心要点回顾
- 零输出 Token 解码:抛弃自回归生成,用决策头直接输出概率分布,规避逐 Token 解码的性能开销
- 三元组结构化决策:状态+问题+候选集,清晰界定每一次决策查询的边界
- 三种决策头各司其职:Choice/Boolean/Score 对应不同的统计问题结构,而非强行统一到单一 softmax
- 实测验证有效:在迷宫导航和 Snake 游戏基准上,相较未微调 Qwen3-0.6B 有显著提升,相较原版 Jev 有合理的性能权衡
- 研究性定位:明确是轻量复刻而非商业产品,服务于"并行决策模型"这一方向的进一步探索
适合谁
- 游戏 AI / 智能体决策研究者:需要一个轻量、可复现的并行决策模型基线
- 关注 LLM 效率的研究者:对"跳过自回归生成,直接输出结构化分布"这类架构改造感兴趣
- 概率校准方向的研究者:想研究 CE/Brier 损失和成对奖励学习在决策场景下的实际效果
- 教学/复现型学习场景:想理解"决策头+骨干网络"架构而不想从零训练大规模系统
一句话评价
NanoJev 提出一个值得深思的问题:如果任务的本质是输出一个概率分布,为什么还要绕道生成一段文字?
欢迎访问 PrimeSkills —— 一个精心策划的 AI Agent 与技能市场,所有内容均经过真实企业级工作流验证。没有噱头,只有真正有效的东西。
更多实用知识和有趣产品,欢迎访问我的个人主页