---
url: /anyjev/introduction.md
description: >-
  AnyJev 是诺基亚应用研究院于 2026 年 9 月 23 日发布的开源 Python
  库（Apache-2.0，v0.1.0），不用微调、不用标注，就能把你已在跑的开源大模型变成"带概率的决策模型"。默认 L0 用循环移位 +
  先验校正干掉位置偏置与标签偏置，Qwen3-8B 在 BANKING77 20 分类上把选项倒序时的翻答案率从 0.230 压到 0.073、准确率
  0.747 升到 0.803；加 100~500 条标注的 L1 把校准误差 ECE 从 0.240 降到 0.095，"可自动决策流量"从 7.7% 涨到
  52.0%。新加的 L2 用闭式解头部（shrunk LDA / ridge）在 2/3 深度截断前向，成本只有一次普通前向的 0.68
  倍，Qwen3-4B 的 0.786 打平微调过的 Laya。
---

# 认识 AnyJev：把选项换个顺序模型就改口，诺基亚用零标注把这个概率从 23% 压到 7.3%

先说一个让我很不舒服的数字。

你让 Qwen3-8B 做一个 20 选 1 的分类题（BANKING77，银行客服意图识别），它答对了。

然后你**什么都不改，只把 20 个选项的顺序倒过来**，再问一遍同样的题——

**它有 23% 的概率给出另一个答案。**

不是模型变笨了，也不是温度没设好。就是"选项排在第 3 位还是第 17 位"这件事，改变了它的答案。

我第一次看到这个数字的反应是：那我过去半年写的那些"让 LLM 输出 A/B/C 然后取 logits"的代码，全都是在赌运气？

答案是：**对，而且比你想的还普遍。**

2026 年 9 月 23 日，诺基亚应用研究院（Nokia Applied Research）把一个叫 **AnyJev** 的 Python 库推上了 PyPI 和 GitHub，Apache-2.0 协议，版本号 **v0.1.0**。它干的事非常窄，也非常狠：

**不微调、不训练、不要标注，把你已经在跑的开源大模型，变成一个"输出带真实概率的决策模型"。**

顺带一提，作者四个人里有一位来自**腾讯混元**。这个组合本身就挺有意思——诺基亚出工程，中国团队出模型侧的经验。

## 什么是 AnyJev

**AnyJev 是诺基亚应用研究院开源的 Python 库（Apache-2.0，v0.1.0，2026 年 9 月 23 日发布）。它把任意一个开源大模型包装成"类型化决策模型"：你给它一个带固定选项的问题，它不生成文字，而是从模型 next-token 分布里直接读出每个选项的概率，返回一个可以设阈值的决策。核心修的是直接读 logits 的两个老毛病——选项换顺序答案就变（位置偏置）、以及概率根本不可信（先验偏置 / 未校准）。**

先把"它不干什么"说清楚，这个比"它干什么"更重要：

* 它**不是**一个新模型，也不动你模型的任何权重；
* 它**不生成**文字，一次 prefill 就读完，没有解析、没有 JSON 修复、没有"请只输出 A 或 B"的咒语；
* 它**不是** Jev 的复刻。Jev 是 TypeSafe AI 在 2026 年 9 月发布的决策模型（System One），AnyJev 借的是它的**接口风格**（typed question），底层是一层跑在你已有模型上的适配器。

它支持**三种问题类型**，基本覆盖了生产里 90% 的"分类"需求：

| 类型 | 干什么 | 例子 |
|---|---|---|
| `choice` | K 个选项选一个 | "这个工单该转给哪个团队？" billing / technical / sales / other |
| `noul` | 是或否 | "这次工具调用是破坏性或不可逆的吗？" |
| `score` | 有序分档 | "这个任务完成度多少？" 5 档 |

然后是它的核心设计——**四个等级，每个决策都自带 level 标签**，下游代码可以明确拒绝用错等级的结果：

| 等级 | 需要什么 | 做什么 | 不做什么 |
|---|---|---|---|
| `raw` | 无 | 直接在选项 token 上受限 softmax（大多数开源项目的做法） | 不处理任何偏置与校准 |
| `L0` | **零标注** | K 次循环移位平均掉位置偏置 + 除掉无标注估计的标签先验 | 不让模型的不确定性变得可信 |
| `L1` | 每个问题 100~500 条标注 | 在 L0 之上加温度缩放（temperature scaling） | 不改变答案排序 |
| `L2` | 每个问题 100~300 条标注 + 本地模型 | 在 **~2/3 深度的隐藏状态**上解一个闭式解头部（shrunk LDA / ridge），一次前向、提前截断 | 不能迁移到别的问题或别的模型 |

> "每个决策都带着自己的等级"这件事，是我认为这个库最工程化的地方。
> 因为它承认了一个现实：**零标注的校准和几百条标注的校准，不是一回事，混着用会出事。**
> 大多数库会帮你悄悄选一个，AnyJev 逼你把等级写在脸上。

## 它有什么特点

* **L0 是零标注的，而且效果是真的。** 两个机制都不复杂，但都想明白了：

  **循环移位（cyclic shifts）**：K 个选项就展示 K 次，每次轮转一格，保证每个选项都在每个位置上出现过一次，最后在对数空间取几何平均。**如果位置偏置在 logit 空间是可加的，这个轮转能精确消掉它。**

  **先验校正（batch calibration）**：在真实输入上维护一个预测分布的滑动均值，以 0.75 的强度除掉它，从第 8 条开始生效。这一刀砍的是"模型天生更爱说 Yes、更爱选 A"这类标签偏好。

  代价是 K 次 prefill：H100 上 batch 32、K=20 的情况下约 **0.25 秒一次决策**。不是免费的，但共享前缀可以批处理掉大部分。

* **最有说服力的那一行不是准确率，是"可自动决策流量"。** 官方主表（Qwen3-8B，BANKING77 20 分类，300 条测试）：

  | 指标 | raw logits | AnyJev L0 | AnyJev L1 |
  |---|---|---|---|
  | 需要的标注 | 无 | **无** | 100~500 |
  | 选项倒序时翻答案率 | 0.230 | **0.073** | 0.077 |
  | 准确率 | 0.747 | **0.803** | 0.807 |
  | 校准误差（ECE） | 0.240 | 0.184 | **0.095** |
  | **误差 ≤5% 可自动决策的比例** | **7.7%** | **46.3%** | **52.0%** |

  准确率只涨了 6 个点，但**能安全交给机器的流量从 7.7% 涨到 52.0%，差 6.8 倍。**

  这才是真正值钱的那一行。准确率高 6% 只是"报表好看"，而"可自动决策比例"决定的是**你要养多少人工审核**。

  > raw logits 给的那个"0.9"，是不能拿去干活的。
  > 一旦概率说的是真话，你才敢设阈值——\*\*阈值之上自动过，阈值之下转人工。\*\*这才是从"AI 演示"走到"AI 上线"的分界线。

* **9/9：所有被测的模型 × 任务组合，L0 都降低了翻答案率。** 3 个模型 × 3 个任务，全中，而且是在零标注的前提下。消融表覆盖了 Qwen、OLMo、Granite、Phi、Mistral——**不是只在 Qwen 上成立。**

* **L2 是这次新落地的东西，也是最骚的一层。** 它不是训练，是**一次闭式解**：CPU 上几秒，没有梯度，模型权重动都不动。头部是「一个 `[hidden, K]` 矩阵 + 偏置 + 标准化向量 + 温度」，约 **100 KB**，Qwen3 1.7B–8B 上 2~8 秒解完。

  更狠的是**成本比一次普通前向还低**——因为它在固定 block 处就把前向停了（Qwen3-8B 停在 36 层中的第 24 层），实测 **0.68×**。

  在 LocalLLaMA/typed-decisions（20 个问题，每个 300 条标注，2000 条留出决策）上的 Jev mode 成绩：

  | 模型 | L0（零标注） | **L2** | 截断位置 | 相对一次前向的成本 |
  |---|---|---|---|---|
  | Qwen3-1.7B | 0.494 | **0.730** | 18 / 28 | 0.70× |
  | Qwen3-4B | 0.564 | **0.786** | 24 / 36 | 0.69× |
  | Qwen3-8B | 0.647 | **0.771** | 24 / 36 | 0.68× |
  | Qwen3-30B-A3B | 0.630 | **0.799** | 40 / 48 | 未测 |
  | Qwen3-32B | 0.700 | **0.798** | 52 / 64 | 0.84× |

  对照组：Jev 官方公布 **0.727**，微调过的 Laya（421M）**0.768**。

  \*\*一个 1.7B 的模型在 64% 深度处，打到了 Jev 公布的数字；一个 4B 打平了专门微调过的 Laya。\*\*而 L2 的池化 ECE 只有 **0.03~0.05**。

  另外，**100 条标注就能把 8B 的头部推到 0.740**（20 条是 0.654，300 条是 0.772）。这个"标注量—收益"曲线对资源紧张的小团队极其友好。

* **头部会自己维护自己。** 这点我最喜欢。你改了问题的措辞，头部会掉（Qwen3-8B 从 0.77 掉到 0.65~0.70），但**喂 30 条无标注的新措辞请求**，它就自己重新居中回 **0.74~0.75**——完全重新标注再拟合是 0.77。

  **30 条无标注 ≈ 300 条全标注的 96% 效果。** 选项顺序变了？按选项文本重新映射就行。只有"换了一个新问题"或"换了一个基础模型"，才需要回到标注这一步。

  `d.observe(route, state, label)` 还能让标注边来边攒，攒到 30 条自己解一次头部，60、120 条再重解。

* **官方直接把丑话写在 README 里。** 这在今天的开源项目里属于稀有品质：

  * **typed-decisions 上的"准确率"，本质是"和教师模型的一致性"**——金标是一个教师模型三次采样的均值，而该教师重新采样一次，和自己的一致性只有 **0.735**。也就是说 0.80 已经接近这个金标能测出的天花板了。
  * **L2 是按问题、按模型的**，别的问题上拟合的头部对新问题没用，且目前**只发了 Qwen3 的头部**。它需要隐藏状态，所以**只有 transformers 后端能跑 L2**。
  * **校准救不了答不对的模型。** 在迷宫和扫雷这类任务上，没有任何读取方式能赢过平凡基线。
  * **L0 不总是白赚。** 当某个标签压倒性占多数时，batch 先验反而会损失准确率（官方专门写了 `docs/when_l0_helps.md`）。
  * 字母读取法**最多 26 个选项**；5% 风险下的覆盖率是 n=300 的高方差估计；主表全是 Qwen；所有决策都是孤立打分的，**没有放进真实 agent 循环里测过**。

  > 我特别想夸这一条：**一个刚发 v0.1.0 的项目，愿意写"我们在扫雷任务上打不过平凡基线"。**
  > 现在太多开源 README 是把最好看的一张图放最上面，剩下的靠你自己踩。
  > AnyJev 的 README 里连"研究日志（含负面结果）"都单独放了一个文档。

## 用在哪儿

**工单 / 意图路由。** 这是最直白的场景，也是 README 里的首个例子：来一条会话，判断转 billing / technical / sales / other。BANKING77 这个基准本身就是银行客服意图 77 分类，诺基亚团队说他们在一个**内部的路由问题**上试过，结果"promising"。

**Agent 的工具调用风控。** 这个我认为是 AnyJev 最有价值的用法。`Question.noul("Is this tool call destructive or irreversible?")`——在 Agent 真正执行 `rm -rf`、发邮件、下订单之前，用一个**带阈值的概率**决定要不要拦下来问人类。

> 注意这里的关键差别：**生成式模型会"解释"为什么安全，而决策模型给你一个可以设阈值的数字。**
> Agent 安全这件事上，一个可信的 0.12 比一段"我认为这个操作是安全的因为……"有用一万倍。

**审核与分流。** 内容是否违规（noul）、严重程度分档（score）、是否需要人工复核（noul + 阈值）。你要的不是"模型写一段审核意见"，你要的是"这批里有百分之多少能自动过"。

**任务完成度 / 质量打分。** `Question.score(..., bins=5)` 给 Agent 的产出打分，替代"让模型自己给自己打 8 分"这种自我吹嘘式评测。

**RAG 的"要不要检索"判定。** 判断这个问题是否真的需要查库，避免每次都无脑检索一遍——成本敏感的场景里，这一类"小决策"才是大头。

**不适合的地方也说清楚**：需要模型真正动脑推理的开放任务（它压根不生成）、选项超过 26 个的分类（当前字母读取法上限）、以及**模型本身就答不对的任务**（校准不能凭空创造准确性，迷宫和扫雷就是铁证）。

## 初体验

**先跑零下载的 demo，30 秒建立体感：**

```bash
pip install "anyjev[hf]"

# 用一个合成模型跑完整流程，不到 1 秒，不下载任何权重
python -m demo.jev_mode --backend fake

# 看完整部署生命周期：day 0 在 L0，标注一条条进来，30 条时头部自己解出来
python -m demo.jev_mode --backend fake --lifecycle
```

**然后是自己上手，L0 默认开启，零标注：**

```python
from anyjev import Decider, Question
from anyjev.backends.hf import HFBackend

d = Decider(HFBackend("Qwen/Qwen3-8B"))

route = Question.choice("Which team should handle this?", ["billing", "technical", "sales", "other"], name="route")
risky = Question.noul("Is this tool call destructive or irreversible?", name="risky")
done  = Question.score("How complete is the task?", bins=5, name="done")

r = d.decide({"conversation": [...], "tool_call": {...}}, [route, risky, done])
r["route"].distribution    # {"billing": 0.81, "technical": 0.07, ...}
r["risky"].p_true          # 0.12
r["done"].value            # 0.35
r.level                    # "L0"
```

**有标注之后升级到 L1 / L2：**

```python
d.calibrate(risky, states, labels)          # 100~500 条 → L1（一个温度）
d.fit_head(route, states, labels)           # 100~300 条 → L2，一次前向 + 闭式解，几秒
d.save_artifacts("qwen3-8b.json")           # 下次 d.load_artifacts(...)；每个头部约 100 KB

r = d.decide(state, [route], level="auto")  # 有头部的走 L2，否则 L1，再否则 L0
r["route"].level                            # "L2"
```

**懒人路线**：`anyjev-heads/<model>.json` 里已经为 **Qwen3-1.7B / 4B / 8B / 30B-A3B / 32B** 各发了 **23 个现成头部**（20 个 typed-decisions 问题 + 3 个基准任务），而且是用和你跑的同一条 `fit_head → decide_batch` 路径构建并验证的。

**四个坑，提前说：**

**第一，也是最容易踩的——vLLM 后端现在不支持。** 好几家媒体稿写"支持 transformers 和 vLLM 双后端、vLLM 走 prefix caching"，那是**照着早期 README 抄的**。官方 0.1.0 的 README 和 docs 已经明确改口：\*\*transformers 后端（`anyjev.backends.hf`）今天能跑全部四个等级，vLLM / SGLang 的服务化在 roadmap 上，不在这个版本里。\*\*L2 需要隐藏状态，这也是它暂时只能跑 transformers 的原因。

**第二，L0 要 K 次 prefill。** 20 个选项就是 20 次，成本不是 1 次前向。真上量请走 `d.decide_batch(states, question)`，并且认真算一下你的 QPS 扛不扛得住。

**第三，别拿"准确率"当圣旨。** typed-decisions 的金标本身只有 0.735 的自身一致性，0.80 已经贴着天花板了。**在自己的标注集上测，别信我的表，也别信官方的表。**

**第四，别把它当分类器训练用。** L2 的头部**按问题、按模型**绑定，换问题要重新标注，换基础模型要把所有头部重新解一遍。它省掉的是"训练"，不是"标注流程"。

## 进阶

如果这篇文章你只记住一件事，我希望是这个判断：

**2026 年开源大模型真正缺的，可能不是更强的模型，而是"让已有模型的输出变得可以设阈值"的那一层。**

我们花了两年把 LLM 塞进生产系统，然后发现最痛的地方不是它不够聪明，而是**它说"我 90% 确定"的时候，你根本不知道这个 90% 是真是假**。没有可信概率，你就不能设阈值；不能设阈值，就只能全量人工复核——于是所有 Agent 项目都卡在"演示很惊艳、上线不敢开"这一步。

AnyJev 的赌注很特别：\*\*它不做新的模型家族，它做一层任何人都能拧到自己已有模型上的校准层。\*\*你不用换模型、不用微调、不用等下一个版本。

冷水照例要泼，而且这次要泼在两点上：

**第一，7.7% → 52.0% 是 n=300 的点估计，官方自己说了区间很宽。**6.8 倍这个数字很炸，但它是**一个任务、一个模型、300 条测试**上的结果。别拿它去做预算，拿你自己的标注集跑一遍再说。

**第二，vLLM 不支持这件事，现在会卡住很多人。**生产环境跑大模型，大部分人用的是 vLLM / SGLang，不是原生 transformers。在 L2 能跑在服务化引擎上之前（roadmap 里排第一项），AnyJev 更适合**离线批处理**和**内部工具**，而不是高并发在线链路。

我的建议很具体：\*\*挑一个你现在正在用 prompt 硬凑的分类任务（工单路由、是否要拦、是否要检索，都行），先用 `--backend fake` 跑通流程，再用 transformers 后端在你的标注集上跑一遍 L0，重点只看两个数——翻答案率和 5% 阈值下的覆盖率。\*\*这两个数决定它对你有没有用，比任何准确率都准。

再往深一层，我建议你去读它的 `docs/method_v3.md` 和那份**包含负面结果的研究日志**。看清楚两件事：**为什么"循环移位 + 对数空间几何平均"能精确消掉可加的位置偏置**，以及**为什么 L0 在标签极度不平衡时反而会掉点**。这两个结论，对所有"从 logits 读分类"的代码都成立——不管你用不用 AnyJev。

至于"决策模型"会不会变成大模型的一个独立品类（Jev、Laya、AnyJev 三方在同一个月里扎堆出现，本身就说明有人押注），我的看法是：\*\*现在下结论都太早。\*\*但至少这一次，诺基亚给的不是一份 PPT，是一个 `pip install` 就能跑、把失败案例也写进 README 的东西。

更多开源技术干货和学习资料，关注公众号「遇码」，领取专属福利。
