> For the complete documentation index, see [llms.txt](https://tinyhumans.gitbook.io/openhuman/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tinyhumans.gitbook.io/openhuman/zh/kai-fa/jev.md).

# Jev

Jev，这个小型决策模型：它回答什么、OpenHuman 在哪里使用它、它的成本以及如何配置它。

Jev 是一个决策模型，不是文本生成器。给它一个请求和一组带标签的选项，它会在大约 150 毫秒内为每个选项返回一个校准后的概率。OpenHuman 在需要从短列表中做出选择而不是撰写长文时，把它当作快速、低成本的裁判。这意味着在搜索过程中的工具选择，以及逐步的浏览器控制。

模型为 `jev-1.13` 和 `jev-latest`，由 TypeSafe AI 构建。OpenHuman 通过 TinyHumans System One 代理访问它们；或者在自带密钥的 OpenRouter 路由上直接访问。输入费用为每百万 token 0.042 美元，输出免费。一次典型的工具搜索会使用一到两千个 token。没有会话、没有思维链，也没有任何内容需要流式传输：一次请求，一组概率。

## 三种问题类型

Jev 回答三类问题。它们定义在 `tinyjevclient`:

* Choice：对一组命名选项的概率分布。调用方可以取最优项、前三项，或者丢弃所有低于置信下限的结果。
* Score：针对单个事物返回一个校准后的数值，而不是在多个选项中做选择。
* Noul：一个是/否概率。OpenHuman 用它来询问“这是否完全适用”，而不是“这些之中哪一个适用”。

工具搜索会在同一个请求中发送一个 Choice 和一个 Noul。Choice 从候选短名单中选出一个工具（外加一个 `none` 选项），而 Noul 则说明该请求是否根本需要工具。浏览器控制会在每一步调用一次 Jev 来决定下一步动作。

## 为什么先做检索

Jev 在一次 Choice 中最多接受 255 个选项，而且当列表里塞满与请求无关的条目时，它的准确率会下降。因此 OpenHuman 从不把整个工具目录直接交给 Jev。 `tinytools-jev` (`vendor/tinyagents/vendor/tinytools/crates/tinytools-jev/`）会先缩小范围，再做决定：

1. 检索器（默认使用 BM25，或者在配置了 embedding 排序器时使用 embedding 排序器）先筛出 `retrieval_k` 个候选，默认 20 个。当目录本来就能装进一个 Choice 时，这一步会跳过。
2. 向 Jev 发出一次请求：对短名单做一个 Choice，再加上 `none`，以及一个询问该请求是否需要工具的 Noul。
3. 命中项按概率排序返回。 `none` 会被移除，而任何低于 `min_probability` （默认 0.05）的项都会被丢弃。

`JevRankerConfig::with_strategy` 决定如何缩小目录范围：

* `RetrieveThenDecide` （默认）：先检索前 20 个，再做一次决定。召回率受限于检索器，因为漏掉的改写根本不会到达 Jev。
* `FamilyThenDecide`：一次评估先选出 family（一个工具包或一组包，其他任何内容都在 `core`中）。然后第二次评估会针对所选 family 的每个成员分别运行。 `max_families` 默认是 2，且这些评估并发执行。一个能装进一个 Choice 的 family 会跳过检索，因此一个改写会在两个阶段都按语义判断，而不是先被词面过滤掉。

## OpenHuman 如何使用它

### 工具搜索

tinyagents 框架拥有 `tool_search` / `tool_call` 桥接器，覆盖所有被注册为延迟加载的工具。 `openhuman-tinyhumans` 安装 `TinyHumansJevRanker` (`crates/openhuman-tinyhumans/src/jev/ranker.rs`）作为该桥接器的全局排序器（`crates/openhuman-core/src/agent/tinyagents/discovery/`）。产品默认使用 `RetrieveThenDecide` 并将进程的 embedding 提供器作为检索器，因此在 Jev 决策前，候选项是按语义而不是按共享词找到的。

排序器会在每次搜索时解析其 Jev 路由和凭证，而不是在安装时缓存它们，因为桌面端进程运行期间用户可能登录或退出。路由是 `agent.tool_search.jev_route` （见 [配置](#configuration)）：TinyHumans 代理、TypeSafe 自己的 API，或者 OpenRouter 的 System One API。构建出的 Jev 客户端会按路由、凭证和后端 URL 缓存，因此稳定会话不会在每次搜索时都重建 HTTP 客户端。

如果进程没有可用的 embedding 提供器， `TinyHumansJevRanker` 就会拒绝，框架会改用自己的 BM25 排序。对词法短名单再运行 Jev 只会白白增加一次网络往返，并无收益。

### 浏览器控制

`crates/openhuman-core/src/modules/browser_task.rs` 把浏览器任务交给 TinyComputer 的任务成员（`StartTask`，然后 `AwaitTask` ，直到任务暂停或完成）。任务会停留在浏览器界面和允许的网站上。

决策模型设置在 `[computer] decision_model`中：Jev（登录后通过托管代理，或使用你的 OpenRouter 密钥）、OpenJev 或 Sage。一步失败后会交给救援模型（`[computer] rescue_model`，最多 `max_rescues` 次）然后任务才会失败。一个不可逆步骤会暂停为 `needs_approval`。浏览器工具会用一次性 token 将其保留，只有 `confirm_pending`通过主机审批关卡，才会响应 `ContinueTask`.

TinyComputer 模块会通过主机的 `SiteMemoryHost` 接口保存已完成浏览器任务学到的内容，按站点分别保存（`crates/openhuman-core/src/modules/site_memory_host.rs` 将其存入 `<workspace>/state/computer/sites/`). `StartTask.site` 会让模块加载它，并把它交给同一站点上的任务：

* 一次运行完成时所采用的计划，会作为同一目标和事实下该任务的 flow 写入，因此不需要重新规划。
* 它找到的元素会作为 grounding 提示写入。记住一个元素只需一次是/否判断，而不需要搜索。

只有完成的运行（`done`，或其支付检查点）才会学习任何东西。只有当一次运行不需要救援，并且不包含其目标不具备的事实值时，计划才会被保留。一个被复用的计划如果失败或需要救援，就会被遗忘。包含事实值或页面文本的元素不会被保留。条目在 30 天未使用后过期，且其中任何内容都不会进入代理的记忆或提示词。 `[browser] learn_from_tasks` 会关闭这一功能，而 `modules.browser_forget_sites` 会遗忘单个站点或全部站点。

## 测量结果

这些数字来自 [`docs/plans/jev-tool-search-baseline.md`](https://github.com/tinyhumansai/openhuman/blob/main/docs/plans/jev-tool-search-baseline.md)。测试使用了 215 个核心工具、1,000 条记录的 Composio 动作，以及 160 条手写请求。其中 66 条映射到一个 Composio 动作，63 条映射到一个核心工具，31 条应该不使用任何工具。

| 排序器                            | Top-1         | Top-3         | 无谓调用（共 31 个） | p50 延迟 |
| ------------------------------ | ------------- | ------------- | ------------ | ------ |
| BM25                           | 22.5%         | 38.0%         | 26           | 28 毫秒  |
| Jev，BM25 先取前 20 再决定            | 57.4%         | 62.0%         | 1            | 1.5 秒  |
| Jev，embedding 先取前 20 再决定（产品默认） | 62.0%         | 66.7%         | 1            | 1.5 秒  |
| Jev，先按 family 再决定              | 62.0% 到 64.3% | 67.4% 到 69.0% | 1            | 1.3 秒  |

在仅限 Composio 的子集上， `FamilyThenDecide` 对过大的 family 使用 embedding 裁切后，可达到 80.3% 的 Top-1 和 87.9% 的 Top-3。BM25 仅达到 18.2% 和 36.4%。

差距主要来自检索，而不是决策。使用 `RetrieveThenDecide` 和 BM25 进行短名单筛选时，Jev 在 Composio 上的 Top-3（72.7%）等于 BM25 的 recall\@20。Jev 能从它看到的所有候选中正确选择，但像“ping alex”这种针对 `SLACK_SEND_MESSAGE` 的改写根本到不了它那里。让 Jev 先选择 family，会移除所有能装进一个 Choice 的工具包的短名单，并把 Composio 的 Top-3 提升到 80% 多。

在任何 Jev 配置下，无谓工具调用都会显著下降。BM25 会用错误工具回答 31 个无工具请求中的 26 个。Jev 的 `none` 选项和 `needs_tool` Noul 让它除了一个之外都能放弃回答。

## 配置

`ToolSearchConfig` (`crates/openhuman-core/src/config/schema/agent.rs`）是 `[agent.tool_search]` 配置块：

```toml
[agent.tool_search]
ranker = "jev"   # "jev"（默认）| "auto" | "bm25" | "compare"
jev_route = "auto"   # "auto"（默认）| "tinyhumans" | "typesafe" | "openrouter"
# jev_base_url = "http://127.0.0.1:18080"   # typesafe/openrouter 源站覆盖
top_k = 3
```

* `ranker = "jev"`：使用已安装的决策模型排序器。只有当 Jev 失败或进程没有 TinyHumans 凭证时，才回退到 BM25。
* `"auto"`：与 `"jev"`.
* `"bm25"`：仅使用内置词法排序器，不发起网络调用。
* `"compare"`：同时提供 Jev，并把 BM25 排名记录到 `tool.searched` 遥测中。你可以在不改变模型可见内容的情况下，对实时流量比较两者。
* `jev_route`：Jev 调用会走哪里。 `"auto"` 如果进程有 TinyHumans 凭证，就使用它；否则使用 `TYPESAFE_API_KEY` （直接连接 TypeSafe）；否则使用 OpenRouter 密钥（`OPENROUTER_API_KEY`，或者已存储的 `openrouter` 密钥）。 `"tinyhumans"`, `"typesafe"` 和 `"openrouter"` 锁定一个路由，不再回退到其他凭证。可在启动时通过 `OPENHUMAN_JEV_ROUTE`.
* `jev_base_url`：替换 `typesafe` 和 `openrouter` 路由的 API 源站，例如计量代理或镜像站。远程源站必须使用 HTTPS。只有字面上的回环 IP 才接受 HTTP。可在启动时通过 `OPENHUMAN_JEV_BASE_URL`.
* `top_k`：当模型没有请求数量时，一次搜索返回多少个匹配项。默认值是 3，足以用于选择，同时不会返回多到让 deferring schemas 失去意义。

如果没有 embedding 提供器，或者所选路由没有可用凭证，工具搜索会自动回退到 BM25。 `auto` 和 `jev` 因此在未设置凭证时不会产生额外成本。没有 TinyHumans 账户的配置需要一个不依赖它的 embedding 提供器（例如 `memory.embedding_provider = "custom:<OpenAI-compatible endpoint>"`）以及一个 TypeSafe 或 OpenRouter 密钥。

## 运行基准测试

`tool-search-bench` 位于 `profile/` crate 中的 [openhuman-benchmarks](https://github.com/tinyhumansai/openhuman-benchmarks)。在该仓库的一个检出版本中：

```bash
cargo run --manifest-path profile/Cargo.toml --bin tool-search-bench -- --ranker all --misses
cargo run --manifest-path profile/Cargo.toml --bin tool-search-bench -- --ranker jev --family --embedding
cargo run --manifest-path profile/Cargo.toml --bin tool-search-bench -- --dump-catalogue
```

`OPENHUMAN_BACKEND_API_KEY` （或 `TYPESAFE_API_KEY`）用于选择凭证。若没有凭证，基准测试会像产品一样，通过已登录的 TinyHumans 会话进行排序。

## 代码位置

* `vendor/tinyagents/vendor/tinytools/crates/tinytools-jev/`：与传输无关的 `ToolRanker` 实现、其检索策略，以及 `JevRankerConfig` / `JevRanking` 类型。
* `crates/openhuman-tinyhumans/src/jev/`：TinyHumans 评估器（`TinyJevEvaluator`，位于 `tinyjevclient`）以及进程内安装的排序器（`TinyHumansJevRanker`).
* `crates/openhuman-core/src/agent/tinyagents/discovery/`：保存已安装排序器的主机槽位，并将 `[agent.tool_search]` 转换为一次回合所使用的策略。
* `crates/openhuman-core/src/modules/browser_task.rs`：运行 `JevController`.
* [`docs/plans/jev-tool-search-baseline.md`](https://github.com/tinyhumansai/openhuman/blob/main/docs/plans/jev-tool-search-baseline.md)：完整的基准测试说明。

另见 [性能](/openhuman/zh/kai-fa/performance.md) ，了解更广泛的成本和密度情况， [可插拔引擎](/openhuman/zh/kai-fa/engines.md) ，了解其他可替换部件，以及 [Embedding OpenHuman](https://github.com/tinyhumansai/openhuman/tree/main/docs/gitbooks/en/developing/embedding.md) ，了解如何将代理作为库运行。
