Jev Router 是什么:什么时候该路由,什么时候该死守 Jev 1.13
OpenRouter 上挂着两个都叫 Jev 的 TypeSafe 条目,而它们不是同一个东西。一个是本站一直在写的判断模型 typesafe/jev-1.13——你问类型化的问题,它回概率。另一个是 typesafe/jev-router,它根本不回答你的问题,它决定由谁来回答,然后把位置让开。
这个区别值得单独写一篇,因为两者的失败方式正好相反。钉住 jev-1.13,你拿到的是机器可判的类型化答案,代价是它天生不擅长写散文式长回答和开放式推理。调 jev-router,你拿到的是某个被选中模型写的普通文本,而”选谁”这一步由 Jev 来做。用错工具,你会花一周时间跟一个本来就不负责这件事的东西较劲。
下面所有内容都来自 OpenRouter 官方 Jev Router 文档和 OpenRouter models API,读取时间是 2026-11-03。文中出现数字的地方,就是当天 API 返回的数字。
TL;DR:
typesafe/jev-router是个可以直接填进model的 slug:不装插件也能用,Chat Completions、Responses、Messages 三种形状都通,响应的model字段告诉你这次是谁答的。只有要传cost_tier(low/medium/high)、包含偏好(models/allowed_models)或硬排除(excluded_models)时才加那个可选的jev-router插件。包含是软的——候选池空掉时会回退;排除是硬的。cost tier 只是路由偏好,不是固定模型,不保证分数,也不是单次请求的价格上限。需要能if判断的类型化结果,就去钉jev-1.13;路由器解决的是「一批普通生成请求,怎么控成本」。
两个产品,一个名字
先看各自返回什么,因为这决定了后面所有工程选择。
Jev 1.13(typesafe/jev-1.13) | Jev Router(typesafe/jev-router) | |
|---|---|---|
| 返回什么 | 类型化判断:选中的答案 + 概率 | 被选中模型写的普通文本 |
| 谁组织答案 | Jev 自己 | 路由器选出来的那个模型 |
| 你发什么 | 状态 + 按判断题/选择题/打分题措辞的问题 | 普通的 completions / responses / messages 请求 |
| 类型化输出 | 决策 JSON | 由服务模型自己决定 |
| 适合什么 | 分支逻辑、闸门、打分、代码内部的路由决策 | 一个端点接一堆模型,配成本策略和偏好 |
| 模型在哪确定 | 你自己在配置里钉死 | 由响应里的 model 字段告诉你,每次请求决定 |
目录数据也印证了这个分野。2026-11-03 我读 models API 时,typesafe/jev-1.13 条目报的输出模态是 decisions,端点信息里上下文 262,144 tokens、最大补全 235,929 tokens。typesafe/jev-router 条目报的是文本输出、上下文 1,000,000 tokens、最大补全 65,536 tokens,输入支持 text / image / file / audio / video——而 endpoints 数组是空的,因为它背后没有某一个固定 provider。
还有一条要多说一句:路由器的 pricing 里 prompt 和 completion 都是 -1。也就是说路由器本身没有公布按 token 计的固定费率——你付的是它选中的那些模型的钱。它不是一张独立价目表,而是包在别人模型外面的一套决策流程。做预算要对池子里的模型做,不要对着一个”路由器费率”做。
路由器到底在决定什么
OpenRouter 把机制拆成三步。
评估请求。 Jev 读对话,判断这个任务需要什么。这就是判断模型在做它本职的事:判断请求的形状和难度,而不是生产输出。
选模型和推理强度。 路由层按当前的 cost 策略、候选模型的能力,以及你设的模型/供应商限制来选。这里的 effort 指的是 reasoning effort,只对暴露这个参数的模型有意义。
跨轮次自适应。 在支持的 agentic 工作流里,路由器可以在任务推进过程中保留同一个模型、调整强度,或者换模型。策略允许时,还能拉一个 expert advisor 来协助干活的模型。
文档里有两句提醒,能挡掉大部分错误预期。第一句:可用的模型和路由策略会随时间变化。第二句更要紧:cost tier 是一种路由偏好,不是固定模型、不是保证的分数、也不是单次请求的价格上限。真要硬性控花费,靠路由器档位做不到——那需要用账户级的 spend limit,或者干脆钉一个固定模型。
两种请求写法
最省事的接法完全不用插件,把 slug 填上就发:
curl https://openrouter.ai/api/v1/responses \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe/jev-router",
"input": "Explain the difference between a mutex and a semaphore."
}'
响应里的 model 字段就是这次实际服务的模型。Chat Completions、Responses、Messages 都能用,流式和非流式都行,所以你现有的客户端不用换 SDK。
第二种写法是加插件,让路由配置跟着单次请求走:
curl https://openrouter.ai/api/v1/responses \
-H "Authorization: Bearer $OPENROUTER_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "typesafe/jev-router",
"plugins": [
{ "id": "jev-router", "cost_tier": "medium" }
],
"input": "Summarize this incident report."
}'
插件参数:
| 参数 | 类型 | 行为 |
|---|---|---|
id | string | 必填,必须正好是 "jev-router" |
cost_tier | string | "low"、"medium"、"high";不写则用 Jev 的默认路由策略 |
models | string 数组 | 带兜底的包含偏好,在动态池选择之前生效 |
allowed_models | string 数组 | models 的别名,同样的兜底行为;两个字段的条目会合并 |
excluded_models | string 数组 | 硬排除。匹配到的模型永不被选中,包含回退时也一样 |
除 id 外全部可选。未知字段和非法值一律返 400——文档举的例子是 allowed_model(少了 s)不被当作别名接受。这种拼写错误很贵,好在它是大声失败而不是默默降级。
cost tier 的实际含义
| 档位 | 意图 |
|---|---|
low | 优先压估成本 |
medium | 在估成本和能力之间平衡 |
high | 当预期收益值那份钱时,优先更强的模型 |
cost_tier 选的是路由策略,不是模型的 reasoning effort——这是两个独立的旋钮,文档写得很明确。你在模型和供应商上设的限制,仍然叠在档位之上生效。不写 cost_tier 等于接受默认策略;想明确用平衡策略就写 "medium"。写了个不认识的档位名,返 400。
有一个后果需要在设计阶段就吃掉:换档位可能在同一段对话里换掉模型。如果你的应用默认”风格和输出格式跨轮次保持稳定”,逐轮改档位就会打破这个假设。除非你确实想要这种切换,否则档位按工作流定,不要按单次调用定。
模型偏好:包含是软的,排除是硬的
真正容易搞错的语义都在这一节。
models 和 allowed_models 是带兜底的包含偏好,不是硬白名单。路由器先在合并后的包含集合里组一个可路由的池子;池子空了,它会不带包含列表重试一次。所以 models: ["anthropic/*"] 是「偏好 Anthropic」,但包含列表把候选筛空时会退到别的作者那里。文档原话是:不要用包含列表来强制实现作者限制。
excluded_models 正相反——硬限制,两次尝试里都保留。由此直接推出两种失败方式:
- 匹配不到任何目录模型时,包含列表不会放松。 如果
models或allowed_models里没有任何条目匹配目录中的公开文本模型——比如 slug 拼错,或者 slug 其实是个纯图像模型——请求直接 404 并点名是哪个字段,而不是悄悄退到全池。这是个好设计:拼错会报错,不会变成账单惊吓。 - 排除永远不被忽略。 如果
excluded_models把池子里的模型全排掉了,请求返 404,而不会去路由一个被你排除的模型。
对动态池来说,这些过滤在排序和池子上限之前生效。所以排掉一个排名靠前的模型,可能正好给另一个合格模型腾出位置。包含从不绕过程序的资格检查、端点策略、能力或 token 预算;显式指定的 operator pool 和内置池保持它们配置好的成员。
还有一个会坑到调成本的人:列表可能把能力档位压下来。当请求本身需要比列表允许的更强的模型时,路由器可以降低自己的能力要求,这一步在 stage 里报成 list_tier_cap。它和 low/medium/high 那个 cost tier 不是一回事,混淆两者会让你去调错的旋钮。如果池子里一个合格模型都不剩,请求 404,错误信息会点出你发的字段,并给出 widen allowed_models 或 remove excluded_models 这类提示。
通配语法和它的边界
偏好列表里的每个条目可以是四种东西之一:
- 精确 slug,比如
openai/gpt-6-luna,匹配这个 slug 的所有带日期版本。 - 带日期的具体版本,比如
openai/gpt-6-luna-20260922,只匹配那一版。 - 通配模式,比如
anthropic/*或*flash*。匹配区分大小写。 ~author/family-latest别名,比如~openai/gpt-luna-latest,匹配这个家族的所有版本。
尺寸限制文档也给了:每个列表最多 1,024 个模式,每个模式最多 1,024 个字符,每个列表总计 65,536 个字符。最容易踩的是大小写——*Flash* 和 *flash* 是两个不同的模式,只有一个小写 slug 会命中后者。
推理强度只是提示,不是设置
路由器正常自己决定 reasoning effort。你可以传标准的顶层 reasoning.effort 当提示,它和 cost_tier 相互独立:
{
"model": "typesafe/jev-router",
"plugins": [{ "id": "jev-router", "cost_tier": "medium" }],
"reasoning": { "effort": "high" },
"input": "Analyze the tradeoffs in this design."
}
Chat Completions 上还接受旧的顶层 reasoning_effort。但路由器可以改选别的强度,也可以跨轮次调整,所以提示不保证最终发给模型的设置就是它。另外两个字段直接被拒:reasoning.max_tokens 和 reasoning.mode: "pro" 都返 400。如果你的配置里设了这两个,指向路由器之前先删掉。
看清路由器做了什么
一个静默换模型的路由器是没法排障的,所以 OpenRouter 把决策暴露出来。响应的 model 字段是标题答案。带上 X-OpenRouter-Metadata: enabled 头,openrouter_metadata.pipeline 里那条 jev-router 记录会有这些:
| 字段 | 含义 |
|---|---|
resolved_models | 路由器选中的模型,按兜底顺序 |
candidates | 候选,含 model、effort、能力 tier、estimated_cost;估算是估算,不是最终账单 |
reason | 策略选择或保留这条路由的原因 |
pipeline | "default" 或 "agentic" |
advisor_model | 选出 advisor 时的那个 advisor |
models、excluded_models | 实际应用的列表;models 里含 allowed_models 的条目 |
list_fallback | 包含列表匹配到目录模型、但没匹配到池内模型时为 "models_ignored" |
list_tier_cap | 列表下调请求档位时,被压到的那个档 |
max_fallback | 本该有 advisor 的请求最终没有 advisor 时为 "deep" |
做账的人要注意那句:candidates 里是估算,估算不是最终计费成本。要对账请看实际的 usage 记录,别把路由器的估算加起来当账单。
实操建议:灰度期间把每次路由调用的 model 和 reason 都记下来。几周后有人问「为什么这请求变贵了」「为什么语气变了」,能回答的就是 reason 这个字段——而事后是重建不出来的。
可用性、报错,和那条区域限制
有三条限制比上面所有参数都更早生效。
只有 global 数据区。 Jev Router 只在 global 数据区可用,而且要工作区允许。用区域路由的请求属于文档列出的 400 情形之一。
路由器权限 + 被选模型的权限。 你既要能访问路由器,也要能访问被选中那些模型。池子里塞满你的工作区调不动的模型,表现出来是失败,不是优雅降级。
不要叠加路由器。 typesafe/jev-router 不能和另一个路由器模型放在同一个请求里,否则 400。实践意义就是:不要在一次调用里同时套 Jev Router 和 auto router 或作者路由。
| 状态码 | 文档给出的例子 |
|---|---|
| 400 | 未知 cost tier 或插件字段、不支持的 reasoning 设置、区域路由、叠加路由器模型 |
| 404 | 应用模型偏好和请求要求之后没有合格模型了,或者你没有路由器权限 |
| 503 | Jev Router 不可用 |
503 当瞬时故障处理——路由器自己挂了不是你请求体的问题。404 当配置问题处理,先查偏好列表和权限。400 当自己写的东西处理,改一版就能修。
作者路由器
还有第二种吃到 Jev 路由的方式:目录里有时会提供 openai/auto、anthropic/auto 这类 <author>/auto 模型,它们用该作者的模型跑 Jev,池发现、任务策略、推理强度和 cost tier 都和 Jev Router 一致。
两条性质要拎清。第一,作者范围是硬限制:调用方的 models / allowed_models 仍然是带兜底的包含偏好,excluded_models 仍是硬限制,三者都在该作者的池子内部运作。包含筛空时,Jev 在同一作者范围内不带包含重试,排除照旧执行;某个作者没有合格模型就返 404。第二,范围限定的是模型作者,不是 provider——一个 OpenAI 模型仍可能由 Azure 之类的 provider 提供。要限 provider 是另一个设置项。
openrouter/auto 是另一个路由器,不走这套作者别名逻辑。别名也是目录产物:一个别名需要目录里自己有对应行,私有的还需要你对那一行的访问权。API 不会按需创建别名,所以你不能靠提要求造一个自己的 yourauthor/auto。
什么情况下路由器是错的工具
有三种场景,钉 jev-1.13 才是对的答案,而且不是”保守”地对。
你要一个能 if 的类型化判断。 如果代码写的是 if answer.confidence > 0.8 then act,一个返回散文、还是随机模型写的散文的路由器毫无用处。判断模型存在的意义就是让文本不需要被解析。路由器不产出判断,它产出文本。
你需要跨批次可复现。 打分、审核、重排这类管线要比较不同时间的结果。路由器的公开行为——模型和策略会变、档位能在同一段对话里换模型——正好是评分卡和基准测试最怕的。钉死 slug、钉死问题措辞,任何变化都当作一次有意的迁移。
你需要单次请求的硬价格天花板。 档位只是偏好,文档自己这么说。预算控制该放在账户级(spend limit)或模型级(固定一个更便宜的 slug),不该放在一个路由偏好里。
反过来,路由器值回票价的时候是这样:你的负载很杂,又不想为每个任务手动选模型——一个端点、一个客户端、一套会随任务难度调整的策略,需要时再用偏好把某个工作流圈在某个家族里、或者隔开某个贵的家族。
一份安全的灰度清单
- 先确认 slug。 上线前在 OpenRouter 模型页读一遍
typesafe/jev-router。slug 和模型池都会变。 - 先只写模型。 不装插件、不加偏好。确认响应里的
model字段有值,并且你的下游解析能容忍这个值变来变去。 - 再加
cost_tier, 一次一个工作流,并记录每个工作流用的哪个档。别让两个工作流不小心共用一个档位常量。 - 开 metadata 日志(
X-OpenRouter-Metadata: enabled)至少一周,持久化model、reason、candidates[].tier、list_fallback。这是你唯一的现场记录。 - 偏好最后加,而且优先用排除而不是包含。 排除是硬的,包含会静默兜底。意图是「永远不用这个模型」就用
excluded_models;意图是「偏好这个家族」就用models并接受兜底。 - 偏好一改就盯 404。 404 基本都是列表已经留不出合格模型,或者某个 slug 不再匹配了。
- 别叠加路由器。 一个请求一个路由器。需要作者范围就用作者别名,不要叠。
这份清单想挡的失败方式都很贵:包含列表静默兜底、档位在对话中途被换、以及因为当初没记 metadata 而完全解释不清的账单。
接下来读什么
如果你还在判断 Jev 是不是你要的那类工具,从 Jev AI 是什么 开始。已经决定了、只想把第一次调用跑通,第一次 API 调用 和 获取 API Key 是最短的路径。路由之前想先把成本账算清,看 成本与延迟;在官方渠道和 OpenRouter 之间犹豫,看 API 渠道怎么选。如果路由请求开始返你没见过的错误码,排错手册 是按症状组织的。
最后交代一句范围:本页描述的是 OpenRouter 在 2026-11-03 文档里写的路由器行为,没有对 TypeSafe 自己的直连端点做任何断言。如果官方 API 也暴露了路由器,那它的权威行为归 typesafe.ai 的文档,不归一篇第三方文章。