Jev API 渠道怎么选:官方 API vs OpenRouter

更新于 适用版本 Jev 1.13

Jev 到你手上有两扇门:官方 TypeSafe AI 渠道和 OpenRouter——模型的主演示渠道。两者都说 OpenAI 兼容的请求/响应”方言”,所以选哪个都不会被锁死;但在接入速度、计费方式和看到新版本的早晚上有实质差异。这篇先做对比,再往下讲真正耗时间的部分:“OpenAI 兼容”到底保证了什么、哪些请求字段只属于市场侧、怎么用一个适配层同时覆盖两条路,以及一份照着做就不会重写的迁移清单。

TL;DR: 先用 OpenRouter:路径最短,按 token 计费(第三方列表约 $0.0462 / 1M input tokens——以模型页为准)。当你需要企业条款、直连支持或版本保障时再考虑官方渠道;其端点以 typesafe.ai 文档为准。把所有 Jev 调用收敛到一个 client 函数后面,日后切换只是一个下午的事,不是一次重写。

两个渠道对比

维度OpenRouter(演示渠道)官方 TypeSafe AI API
接入速度几分钟:注册、充值、拿 Key较慢:按官方文档走开通流程
请求格式OpenAI 兼容 chat completions以 typesafe.ai 文档为准
定价按 token 计费;列表价约 $0.0462 / 1M input tokens(第三方数据,以模型页为准)按官方条款;查 typesafe.ai
计费方式OpenRouter 预充值,可按 Key 设消费上限以官方计费安排为准
版本可用性模型页列出;slug 可能领先或滞后官方文档第一手;以官方发布说明为准
上游路由同一 slug 背后多家上游,可按价格、延迟或吞吐排序由官方渠道决定
请求侧扩展模型兜底数组、单次调用成本回传、数据采集过滤不保证;逐字段以官方文档为准
花费可观测性Key 级用量与剩余额度查询以官方工具为准
支持市场级别直连,按官方渠道
适合原型、中小规模生产、快速实验企业负载、合规需求、量级承诺

两个诚实的提醒。第一,模型 id 在两个渠道可能不同——typesafe/jev-1.13 是写作本文时 OpenRouter 的列表值,slug 会随版本变化,以模型页为准。第二,本文刻意不编造官方端点 URL;官方渠道提供什么,typesafe.ai 的文档是唯一事实来源,介绍 System One 模型与 Jev 的发布公告也是。

“OpenAI 兼容”到底保证了什么

兼容是个光谱。搞清楚你的代码依赖光谱的哪一半,就知道换渠道会疼到什么程度。

层次跨渠道可迁移?为什么重要
鉴权头形式(Authorization: Bearer …)通常可以HTTP 客户端和密钥注入方式原样保留
请求体结构(model、messages[])可以你已经写好的请求依然合法
响应信封(choices[0].message.content)可以解析入口不变
模型 slug不可以换渠道后 404 的头号原因
额外请求字段不可以市场侧能力不属于这套方言
错误响应体结构不保证错误处理要针对状态码写,别匹配文案
用量/token 统计字段不保证自己记 token,别赌字段名
限流响应头与语义不保证退避策略得按渠道重新调

实用规则:只依赖上表标”可以”的三层,其余全部当成渠道专属配置。读解析后 answer、confidence 的代码可以平移;拿正则去 HTTP 原始响应里找 “billing” 的代码不行。

值得知道的 OpenRouter 请求字段

这些是让演示渠道不止是”透传”的市场侧能力,也正是你切到不声明支持这些字段的渠道时必须剥掉的部分——未知字段要么被 400 拒掉,要么更糟:被静默忽略。而静默忽略,就是”我们设了数据采集过滤”这句话最后被证明是假的原因。

模型兜底数组。 传 models: ["typesafe/jev-1.13", "<备用 slug>"],主模型出错时路由会试第二个。版本过渡期有用,但用在判断任务上要小心:备用模型有自己的标定,它返回的 0.94 和你阈值假设的那个 0.94 不是一回事。用了兜底就必须记录”这次到底是谁回答的”。

上游路由。 provider 对象可以收窄或排序同一 slug 背后的上游:order 指定优先上游,allow_fallbacks: false 拒绝替补,sort 按 "price"、"latency" 或 "throughput" 排序,data_collection: "deny" 排除会留存或拿输入做训练的上游。对延迟敏感的内容审核流水线,按延迟排序值得实测;对处理个人信息、要写进合规文档的流水线,数据采集过滤值得记录——同时记住它是市场侧控制项,不是合同。

单次调用成本回传。 加 usage: {"include": true},响应里会带上 token 数与成本,可以按流水线直接归因花费,不用再去对账单导出。这是 OpenRouter 专属能力,下面的适配层会保证它不会发给别的渠道。

归因头。 HTTP-Referer 和 X-Title 让你的应用在 marketplace 面板里可辨识。设置成本极低,而且是多个项目共用一个账号时唯一的分账依据。

同时用上其中三项的请求:

# Confirm the exact model slug on the OpenRouter model page
curl https://openrouter.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -H "HTTP-Referer: https://your-app.example" \
  -H "X-Title: inbox-router" \
  -d '{
    "model": "typesafe/jev-1.13",
    "provider": {"sort": "latency", "data_collection": "deny"},
    "usage": {"include": true},
    "messages": [{"role": "user", "content": "Choice question: route this email to sales, billing or support? Email: \"...\""}]
  }'

OpenRouter 实际用起来什么样

一次调用、一个 Key、你熟悉的端点:

# Confirm the exact model slug on the OpenRouter model page
curl https://openrouter.ai/api/v1/chat/completions \
  -H "Authorization: Bearer $OPENROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "typesafe/jev-1.13",
    "messages": [{"role": "user", "content": "Choice question: route this email to sales, billing or support? Email: \"...\""}]
  }'

标准 chat completions 请求——分流语义由问题的措辞承载。

解析后的答案——示例数据(example fixture),正式字段名以官方文档为准:

{
  "answer": "billing",
  "confidence": 0.94,
  "rationale": "The email disputes a subscription charge, which maps to the billing queue."
}

这正是推荐先用 OpenRouter 的原因:你现有的 OpenAI 客户端库、重试逻辑和观测手段全都原样可用。

一个适配层,两份配置

整个”迁移成本低”的论证,其实就落在这一个文件上。把所有渠道差异放进数据,而不是散落在代码各处的分支里:

import json, os, requests
from dataclasses import dataclass, field

@dataclass(frozen=True)
class Channel:
    name: str
    base_url: str
    api_key_env: str
    model: str
    extra_headers: dict = field(default_factory=dict)
    extra_body: dict = field(default_factory=dict)

CHANNELS = {
    "openrouter": Channel(
        name="openrouter",
        base_url="https://openrouter.ai/api/v1/chat/completions",
        api_key_env="OPENROUTER_API_KEY",
        model=os.environ.get("JEV_MODEL_SLUG", "typesafe/jev-1.13"),
        extra_headers={
            "HTTP-Referer": "https://your-app.example",
            "X-Title": "inbox-router",
        },
        extra_body={"usage": {"include": True}},
    ),
    # 官方 TypeSafe AI 渠道:这两个值按官方文档填写。
    "official": Channel(
        name="official",
        base_url=os.environ.get("TYPESAFE_BASE_URL", ""),
        api_key_env="TYPESAFE_API_KEY",
        model=os.environ.get("TYPESAFE_MODEL", ""),
    ),
}

def ask(question: str, channel: str = "openrouter", timeout: int = 30) -> dict:
    ch = CHANNELS[channel]
    if not ch.base_url:
        raise RuntimeError(f"{ch.name}: base URL not configured")
    resp = requests.post(
        ch.base_url,
        headers={
            "Authorization": f"Bearer {os.environ[ch.api_key_env]}",
            "Content-Type": "application/json",
            **ch.extra_headers,
        },
        json={
            "model": ch.model,
            "messages": [{"role": "user", "content": question}],
            **ch.extra_body,
        },
        timeout=timeout,
    )
    resp.raise_for_status()
    envelope = resp.json()
    return json.loads(envelope["choices"][0]["message"]["content"])

三个性质值得注意。渠道是运行时参数,所以灰度分流 5% 的流量不需要发版。市场侧字段只活在 extra_headers 和 extra_body 里,对没声明支持的渠道会自动消失。解析结果就是上面那个示例数据形态——把它当成待核对的 example fixture,而不是规格说明。

迁移成本:架构对了就很低

切换成本大多是自找的,也就大多可以避免:

  1. 一个 client 函数。 所有 Jev 调用走同一个封装:进一个问题,出解析后的答案。
  2. base URL、Key、模型 id 全部走配置。 用环境变量,不写字面量。
  3. 容错解析。 防御式解析 message content;多出来的未知字段当可忽略,不要当致命错误。

有了这个结构,从 OpenRouter 迁到官方渠道就是改三个配置值、再对照官方文档核对一遍字段名——上面那个响应形态是示例数据(example fixture),官方渠道的确切字段名以其文档为准。

迁移清单

光改配置并不能回答”新渠道的行为和老渠道一样吗”。按顺序走这六步,每步都有放行条件,永远知道自己该不该继续。

步骤动作放行条件
1. 冻结 golden set导出 50–200 条真实输入,附人工标注每条都有期望答案
2. 各渠道固定 slug模型 id 进配置,不进代码两个值都能解析;slug 写错在启动时就报错
3. 离线回放golden set 同时灌两条渠道,不接线上流量有标注样本上的答案一致率 ≥ 95%
4. 比分布比 confidence 与延迟,不只看答案confidence 中位差 ≤ 0.05;p95 延迟增幅 ≤ 30%
5. 灰度5% 线上流量走新渠道,两边都记日志一周内回退率没有越过阈值
6. 切换并观察改默认值,老渠道保持可用回滚只需改一个环境变量,实测 5 分钟内完成

第 4 步是最常被跳过、也最能捞出真问题的一步。两条渠道可以在 96% 的答案上一致,却在”什么时候该不确定”上不一致——如果新渠道系统性给出更高的 confidence,你的回退阈值会悄悄不再触发,错分开始流到客户面前。这个阈值本身怎么定,《置信度与回退》有完整讲法。

回放脚本短到写一次就能长期复用:

GOLDEN = [
    ("Judgment question: does the string 'abc' contain the letter 'z'?", "no"),
    ("Choice question: which word is a colour? Options: red, seven, run. Word: 'seven'", "seven"),
    ("Scoring question (1-10): rate the similarity of 'cat' and 'cat'.", 10),
]

def compare(channel_a: str, channel_b: str) -> dict:
    agree, deltas = 0, []
    for question, expected in GOLDEN:
        a = ask(question, channel=channel_a)
        b = ask(question, channel=channel_b)
        agree += int(str(a["answer"]) == str(b["answer"]) == str(expected))
        deltas.append(abs(a["confidence"] - b["confidence"]))
    return {"agreement": agree / len(GOLDEN), "median_conf_delta": sorted(deltas)[len(deltas) // 2]}

两个结果里的答案都是示例数据形态;接进 CI 之前,先把官方渠道的字段名核对清楚。

分渠道的可观测性

比不了的渠道就选不了。两条渠道都会给你状态码和延迟,OpenRouter 另外提供了一组端点,正好回答你运维时真正会问的问题。

问题OpenRouter 的能力面用途
这个 Key 花了多少、还剩多少?Key 信息查询(用量、上限、剩余)按项目做每日预算护栏
账号余额要见底了吗?额度查询(总额度、总用量)批量任务前先报警
这一次调用花了多少?按请求 id 查单次生成把成本和自己的日志关联
配置的 slug 还在列表里吗?模型列表(含定价)每日 slug 漂移检查

最后一条值得第一天就自动化。slug 会随版本变化,而一旦 slug 消失,所有调用会在同一秒变成 404。一个每天拉一次模型列表、断言配置 slug 仍在、不在就报警的定时任务,把一次生产事故降级成一张工单。真漏过去了怎么办,故障排查那篇有完整的”报错—原因—修法”对照表。

限流不同,并发要分渠道调

限流是最像”可移植”、其实最不可移植的一项。市场侧通常按 Key 计量,天花板跟你的充值档位挂钩;官方渠道的配额写在它自己的协议里。于是同一份 max_workers=10 的线程池,在一条渠道上很舒服,在另一条上就是 429 制造机。

对迁移清单有两个推论。第一,把并发数当成和 base URL 同级的渠道配置,切换后重新实测,不要把旧值直接搬过去。先按 10 并发起,盯十分钟重试率,429 超过请求量的约 1% 就往下调。第二,记住灰度流量不是公平的压测:5% 的线上流量打在一个全新 Key、全新配额上,只能验证正确性,不能告诉你这条渠道在你真实量级下的表现。把每条渠道的重试率单独当指标看,上涨在变成积压之前就能被发现。

按阶段给建议

阶段渠道理由
评估 / 原型OpenRouter最快跑通
早期生产OpenRouterOpenAI 兼容生态,可按 Key 限消费
规模化 / 企业官方 API(评估后)支持、条款、版本保障——去 typesafe.ai 核实
混合任一保留适配层,按负载路由

三团队邮件分流的 case 展示了 OpenRouter 路径撑起生产负载的样子。钱的层面怎么算,《Jev 成本与延迟》把 token 经济学摆给你看。

会推翻偏好的四个硬约束

有四类需求会直接替你决定渠道,和上面的建议表无关。

会白花一周的反模式

把每条渠道的花费关进笼子

预充值把一种失败模式变得极好防:一个重试循环或一次失控的批量任务,把余额在月中抽干。两个习惯就够了。给每个 Key 设消费上限,泄露的凭据就掏不空账号;任何批量任务启动前先查剩余额度,预计花费超过余额就中止。预计值要用日志里实测的 prompt token 算,不要估——prompt 长度几乎就是全部成本模型,《Jev 成本与延迟》把它算给你看过。

混合架构下,两条渠道的 Key 分开放进不同的 secrets,各设各的上限。这样一条渠道的定价意外或故障只影响它自己,而你的备用路径仍然是付得起钱的。

本文适用版本 Jev 1.13。

常见问题

+ 刚开始用 Jev 选哪个渠道?

OpenRouter。它是主演示渠道,提供 OpenAI 兼容端点,几分钟就能接上,适合原型和中小规模生产。

+ 官方 TypeSafe AI 渠道多了什么?

直连支持、企业条款和第一手的版本信息。端点细节以 typesafe.ai 官方文档为准,迁移前先去确认。

+ 以后换渠道成本高吗?

把调用收敛在一个 client 函数里就不高。两条路都是 OpenAI 兼容的请求/响应,换 URL、Key 和模型 slug 就是主要工作量。

+ 两个渠道能同时跑吗?

能,而且这就是常规迁移路径:先用 OpenRouter 当默认渠道,把带人工标注的 golden set 和小比例灰度流量灌进官方渠道对比,再改配置切换默认值。

+ OpenRouter 独有的请求字段在官方渠道能用吗?

不要假设能用。上游路由、模型兜底数组、响应里带成本这些都属于市场侧能力;适配层应该把它们只发给声明支持的渠道。

继续阅读