跳到正文
北京时间
原文
Hacker News 热门(buzzing.cc 中文翻译)· handfuloflight·· 2026-06-29精选AI 评分75

Wayfinder Router:在本地和托管的大语言模型之间进行确定性查询路由

Wayfinder Router:在本地和托管的大型语言模型(LLM)之间进行确定性查询路由

AI 导读

Wayfinder Router 通过分析提示词的结构(长度、标题、列表、代码)和措辞(证明、数学、硬约束),在微秒级完成路由决策,完全离线且无需调用其他模型。默认仅使用结构特征,词汇线索因盲测未泛化而默认为关闭。对比依赖模型调用的路由器(如 RouteLLM、NotDiamond),它避免了延迟、成本和随机性。用户可在自有数据上校准评分阈值。支持任何 OpenAI 兼容 API(含 Ollama、Anthropic、Groq、vLLM 等),可自托管。提供终端和网页演示(--dry-run 无需密钥),以及基准测试和 FAQ。

推荐理由

Wayfinder Router 把 prompt 路由变成了离线文本分析,无需额外模型调用,对希望节省成本同时保持私密的开发者很实用,比现有方案更轻量和确定,但纯语义难题仍是短板。

正文 · AI 翻译

Wayfinder

对每个提示词做一次快速、离线的难易判定——以确定性方式打分,不调用任何模型。把简单的路由到你的小型/本地模型,把困难的交给你的大型模型,或者在其后组合任意模型路由器。

快速开始 · 基准测试 · 对比情况 · 说明 · 更新日志

不调用模型
即可决定路由
确定性
且完全离线
校准
基于你自己的数据
自带密钥
自托管

Wayfinder 会对提示词的结构(长度、标题、列表、代码)和措辞(证明、数学、硬性约束)进行评分,得出一个 0.0–1.0 的复杂度分数,然后把简单的路由到你的小型/本地模型,把困难的交给你的大型模型。这个决策本身就是产品:确定性、亚毫秒级、完全离线——无需 API key、无需网络、无需调用模型即可完成。你将其路由到什么是你说了算:两层、N 层阶梯,或者在其后组合一个模型路由器。

便宜的提示词留在本地,困难的才交给昂贵的模型,这样你就不必再为“总结一下这个”和“帮我改个错别字”支付顶级价格。

对比情况

大多数路由器靠调用模型来做决策:一个训练好的分类器、一个 LLM 评判器,或者一个托管 API。这恰恰在本该帮你省钱的环节上增加了延迟、成本和随机性。Wayfinder 则改为读取结构和措辞,因此决策是免费的,而且每次结果都一致。

路由器 决策方式 是否调用模型? 自托管 校准
Wayfinder 确定性的结构评分 否 是 是
RouteLLM 训练好的分类器(偏好数据) 是 是 重新训练
NotDiamond / Martian 学习型、托管式 是 否 通过平台
OpenRouter(自动) 托管式自动路由器 是 否 —
Bifrost / LiteLLM 提供商网关(非按复杂度路由) 否 是 不适用

最后两行中的网关(OpenRouter、Bifrost、LiteLLM)回答的是另一个问题:哪个提供商来服务一次调用,依据价格、可用性和故障转移。Wayfinder 回答的是一个提示词该配哪一档:便宜还是昂贵,依据难度,离线决定。两者可以组合。运行 Wayfinder 来做便宜与昂贵的判断,再在下面接一个网关来触达各个提供商。

Wayfinder 并不追求顶尖的准确率数字——它给你的是一个可以离线运行、并能在你自己的流量上微调的路由决策。默认情况下,它只对提示词的结构打分;它也能读取词汇线索(证明、数学、约束),但这些默认关闭,因为一项双盲测试表明这种提升无法泛化(它只捕捉到约 20% 的未见过的难题提示词,还输给了一个简单的词数基线)。如果一个提示词的难度纯粹是语义上的(一段微妙的代码片段、"第 100 个质数是多少?"),它就没有结构性线索,语义路由器在这方面会胜过它。基准测试(make benchmark)展示了它在与诚实的基线和完美 oracle 对比时在哪里赢、在哪里输;FAQ给出了直白的版本——包括它在 RouterBench 那些短而难的条目上并不比随机更好,以及为什么你仍然会运行它。

试试演示(无需密钥)

有两种方式让你亲眼看到路由决策——无需 API 密钥、无需模型、网络上什么都不用。

在你的终端中——一个以决策优先的聊天界面,采用 Wayfinder 配色方案。终端聊天功能随默认安装一起提供,因此无需额外添加任何东西——或者完全不安装,直接通过 uvx 运行:

uvx wayfinder-router chat --dry-run      # zero install, zero keys
# or:  pip install wayfinder-router && wayfinder-router chat

每一轮都会显示它路由到了哪里(● LOCAL / ◆ CLOUD)、结构分数以及原因(/why),还有相对于始终使用云端所累积的节省量。/init 让你无需离开聊天即可配置模型,/route · /local · /cloud 可强制某一轮的处理方式,对话还会跨会话持久保存(/threads)。

在你的浏览器中——带有实时阈值滑块的网页聊天界面:

pip install "wayfinder-router[gateway]"
wayfinder-router webchat --dry-run
# opens http://127.0.0.1:8088/demo

webchat 是 serve 之上的一层轻量启动器(即网关及其 /demo 页面;--no-open、--port、--host 0.0.0.0、--dry-run);serve 是无头命令。在没有配置的情况下,它仅做决策(--dry-run),因此你可以零配置地试用它;要获得真正的回复,请运行 wayfinder-router init 来生成 [gateway.models] 的脚手架(然后用 wayfinder-router doctor 确认你的密钥能够解析)——参见 快速入门。

兼容任何 OpenAI 兼容的 API

Wayfinder 会把每次调用转发到一个 OpenAI 风格的 /chat/completions 端点——所以只要你的服务商支持这种格式(大多数都支持),它就能直接运行。 一个层级就是一个 base_url、一个模型名称,以及在请求时从环境变量中读取的一个密钥;无需 SDK,无需针对每个服务商编写代码。你可以把一个免费的本地模型与一个托管模型配对,也可以运行两个云端层级。

……此外还有 Groq、Together、OpenRouter、Fireworks、DeepSeek,以及本地服务器(vLLM、LM Studio、llama.cpp)——+ 任何接受 Bearer 密钥的 OpenAI 兼容端点。

Wayfinder Desktop v0.1.0

首个原生桌面版本是一个仅支持 Apple Silicon的应用,适用于 macOS 14 或更高版本。它在嵌入式 arm64 Rust 网关上提供专注的 Chat 功能,并使用独立的 desktop-v0.1.0 标签;独立路由器则保留其 CalVer/PyPI 发布线。Intel 支持、通用二进制、DMG 打包以及自动更新属于后续的桌面工作。

在 Desktop Chat 中使用 ChatGPT Codex 账户(可选启用)

原生桌面应用可以通过一个符合条件的 ChatGPT Codex 账户来路由 Chat,而无需 OpenAI Platform API 密钥。这是一个独立的 codex-app-server 服务商——不是用于任意 OpenAI API 调用的 bearer token——并且它绝不会被启用为默认路由。Desktop v0.1.0 要求单独安装、签名正确的应用位于 /Applications/ChatGPT.app;Wayfinder 不会捆绑或再分发 Codex 可执行文件,也不声称该服务商是自包含的。

将路由添加到桌面网关配置,重启网关,然后使用 Settings → Accounts 登录:

[gateway.models.chatgpt-sol]
provider = "codex-app-server"
model = "gpt-5.6-sol"
context_window = 1050000

只有当该模型由隔离的 Codex 运行时对外声明时,账户路由才会出现在 Chat 中。登录不会改变 Automatic 或任何现有的路由阶梯。请求由托管方承载并离开 Mac;离线模式会禁用该提供商。Wayfinder 接收的是规范化后的账户状态和模型名称,绝不会接收账户 token,也不会扩大其凭据代理的范围。开发构建可以使用显式选择或同机部署的辅助程序。发布构建会忽略这些开发路径,仅在其位置、运行时兼容性和签名检查均通过后,接受固定的 ChatGPT 应用运行时。未来的自包含发布将需要一项单独经过审查的决策,涵盖许可、版本锁定、架构、嵌套签名、版本和摘要校验。完整边界参见 提供商设计。

快速开始

将 Wayfinder 置于你的模型之前。你的应用继续使用 OpenAI API 通信;你只需更改一个 base_url。

  1. 生成配置脚手架——init 会写入一个起始 wayfinder-router.toml(无需密钥的本地 Ollama → Anthropic 云端)以及一个 .env.example,然后检查你的密钥:

    pip install "wayfinder-router[gateway]"
    wayfinder-router init                 # starter config (hybrid preset)
    wayfinder-router init --preset openai # two OpenAI tiers (gpt-4o-mini → gpt-4o)
    wayfinder-router init --preset gemini # two Gemini tiers (gemini-2.5-flash → gemini-2.5-pro)
    wayfinder-router init --interactive   # pick providers/models step by step

    或者在 wayfinder-router.toml 中手动描述你的两个模型:

    [routing]
    threshold = 0.5            # below -> local, at/above -> cloud
    
    [gateway.models.local]
    base_url = "http://localhost:11434/v1"
    model = "llama3.2"
    
    [gateway.models.cloud]
    base_url = "https://api.openai.com/v1"
    model = "gpt-4o"
    api_key_env = "OPENAI_API_KEY"   # read from this env var, never stored
    # api_key_cmd = "op read op://Private/OpenAI/credential"  # optional: fill it from a vault

    Wayfinder 从不存储密钥:模型只需指定一个环境变量名(api_key_env),密钥会在请求时从你的环境中读取。无需“安装”任何东西——只需导出该变量即可。不想把原始密钥粘贴到 shell 里?添加一个可选的 api_key_cmd,Wayfinder 会在启动时从你的密钥存储中填充该变量——op read …(1Password)、security …(macOS 钥匙串)、secret-tool …(Linux)、pass/gopass、vault kv get …、aws secretsmanager get-secret-value …、bw、doppler、gcloud secrets …,或任何能打印出密钥的命令。密钥仅保存在内存中,依然绝不写入磁盘。wayfinder-router doctor 会检测你已安装了其中哪些工具,并建议确切的配置行。

  2. 设置好你的密钥,然后运行网关。doctor 会在你启动前重新检查配置以及每个模型的密钥是否能解析(✓ set / ✗ not set):

    export ANTHROPIC_API_KEY=sk-...     # or OPENAI_API_KEY, per your config
    wayfinder-router doctor             # ✓/✗ per model — is each key set?
    wayfinder-router serve --port 8088
  3. 把你现有的客户端指向它即可。无需改动代码:

    client = openai.OpenAI(base_url="http://localhost:8088/v1", api_key="unused")
    client.chat.completions.create(model="auto", messages=[{"role": "user", "content": "..."}])

简单的提示词走本地,困难的走云端,每个响应都带有 x-wayfinder-router-model 和 x-wayfinder-router-score,让你能看到它去了哪里。想为某一次请求强制指定层级?设置 model="local" 或 "cloud"(或 prefer-local / prefer-hosted),用 X-Wayfinder-Threshold 请求头为单次调用移动分界线,或在聊天消息开头加上 /local 或 /cloud(参见 引导单次请求)。

检查它是否正常工作:

curl -s localhost:8088/healthz
# {"status":"ok","models":["cloud","local"]}

curl -s -D - -o /dev/null http://localhost:8088/v1/chat/completions \
  -H "Content-Type: application/json" \
  -d '{"model":"auto","messages":[{"role":"user","content":"hi"}]}' \
  | grep -i x-wayfinder-router
# x-wayfinder-router-model: local
# x-wayfinder-router-score: 0.00

还没有后端?wayfinder-router serve --dry-run 会直接返回路由决策,而不是调用上游,因此你可以在接入真实模型之前,用 30 秒感受一下路由效果。

安装

命令 你将获得
pip install wayfinder-router 评分器、CLI、Python API、以及终端聊天(chat);评分器/库的导入保持轻依赖
pip install "wayfinder-router[gateway]" 增加了 OpenAI 兼容的路由网关,这是服务部署的常见场景
pip install "wayfinder-router[ui]" 增加了本地的校准 / 解释 / 配置 UI
pip install "wayfinder-router[all]" 在默认安装之上增加了网关和 UI

将其作为本地服务运行

让 Wayfinder 成为你机器上始终在线的 LLM 端点,这样每个兼容 OpenAI 的应用都能共享同一个本地 base_url,而你只需设置一次密钥。service install 会将它注册到操作系统服务管理器中,以便在登录时启动,并在退出时重启:

wayfinder-router service install     # macOS (launchd) or Linux (systemd user unit)
wayfinder-router service status      # is it running? endpoint + /healthz
wayfinder-router service uninstall

然后让你的应用指向它一次即可——大多数兼容 OpenAI 的工具都会读取 OPENAI_BASE_URL:

export OPENAI_BASE_URL=http://127.0.0.1:8088/v1

macOS 是主要目标平台;Linux 也可以使用。--print 会输出 unit 文件而不进行安装,如果不存在服务管理器,它会写入 unit 文件并打印出启动它的那一条命令。还是同一个网关,只是保持运行——路由决策不变。

工作原理

Wayfinder 位于你已经在使用的任何兼容 OpenAI 的客户端之后。你将该客户端的 base_url 指向网关一次,此后它就隐于无形。无论请求是路由到本地还是托管服务,同一个客户端都能处理。

  your client   (chat app, IDE, agent, or code)
       |
       v
  Wayfinder gateway   scores, picks a model
       |
       |-- low  -->  local    (Ollama, vLLM)
       |-- high -->  hosted   (OpenAI, any /v1)
       |
       v
  response returns via the same client,
  with x-wayfinder-router-* headers

由此可以得出几点:

  • 前面的界面由你决定。一个聊天 GUI(Open WebUI、LibreChat)、一个带自定义端点的 IDE 助手(Cursor、Continue)、一个智能体框架,或者你自己基于 OpenAI SDK 编写的代码。今天就想有个聊天窗口?把 Open WebUI 放在前面,让它指向网关即可。
  • 本地和托管都是后端,而不是应用。 本地模型只是一个服务器(Ollama、LM Studio、vLLM、llama.cpp),使用 OpenAI 的 /v1;托管的那一个形态相同。用户从不切换 UI,通常也根本不知道是哪个模型给出的回答。

密钥在请求时从环境变量中读取,从不接触配置文件或评分路径。

从 CLI 对提示词进行评分

echo "Summarise this paragraph in one sentence." | wayfinder-router route -
Recommended Model: local
Complexity Score: 0.00  (mode: tiered)

Tiers:
  >= 0.00  local <-
  >= 0.50  cloud

Contributing Features:
  Word Count: 6
  ...

为机器消费者添加 --json(智能体读取它并路由到自己的模型):

{
  "schema_version": "3",
  "score": 0.66,
  "recommendation": "cloud",
  "mode": "tiered",
  "features": { "word_count": 545, "heading_count": 12, "reasoning_term_count": 3, "...": 0 },
  "tiers": [{ "min_score": 0.0, "model": "local" }, { "min_score": 0.5, "model": "cloud" }]
}

配置路由

Wayfinder 读取它自己的 wayfinder-router.toml,通过从你运行它的位置向上查找来找到。共有三种模式,按优先级顺序(分类器 > 分层 > 阈值);标量分数 weights 适用于其中任何一种。

二值(默认)是单一分界:

[routing]
threshold = 0.6
weights = { word_count = 4.0, list_item_count = 2.5 }

--threshold N 为单次运行覆盖它;WAYFINDER_ROUTER_THRESHOLD 从环境变量覆盖它。

要开启词汇线索,请提高它们的 weights 并在膝盖处截断——这是在真实前沿流量上相对于结构性默认配置唯一保留的改进(技能 −0.038 → +0.057,在 RouterBench 上节省 61% 成本)。参见 docs/lexical-routing.md 以及可直接编辑的 examples/wayfinder-router.lexical.toml;根据你自己的流量重新校准阈值(约 20 条提示词的引导样本只是冒烟测试——参见 benchmarks/calibration-eval.md)。

分层将有序的分数区间路由到任意数量的模型:

[[routing.tiers]]
min_score = 0.0
model = "llama-3b"
[[routing.tiers]]
min_score = 0.3
model = "llama-70b"
[[routing.tiers]]
min_score = 0.6
model = "claude-cloud"

分类器是一个拟合的多项式逻辑回归模型,argmax基于每个模型的线性分数。你通常用 calibrate 生成它,而不是手写。

每个 [gateway.models.<name>] 块将一个路由名称映射到一个上游 base_url、一个 model,以及一个可选的 api_key_env(环境变量的名称,绝不是密钥本身)。网关是唯一接触密钥或网络的部分;评分器、配置和校准器保持纯粹且离线。

在你的数据上校准

截断值只是一个代理,因此要针对你自己的流量来调整它。wayfinder-router calibrate 读取一个带标签的 JSONL 数据集({"text": ..., "label": ...})并打印出一个配置片段。它离线运行,从不调用模型;标签就是你的真实基准。

wayfinder-router calibrate data.jsonl --mode threshold              # sweep the binary cut
wayfinder-router calibrate data.jsonl --mode tiers                  # ordinal multi-model
wayfinder-router calibrate data.jsonl --mode classifier --out wayfinder-router.toml

该片段可直接嵌入 wayfinder-router.toml;准确率和选定的断点会打印到 stderr。分类器通过确定性的 L2 正则化 Newton/IRLS 拟合,纯 Python 实现,几次迭代即可收敛。

若要从成本角度而非单纯的准确率来选择切分点,可使用成本感知目标。--objective knee 会自动选择成本感知的拐点(它最大化质量恢复 × 成本节省——无需猜测目标值,而且不会像纯准确率在标签偏斜时那样坍缩为总是路由到昂贵模型);--objective cost-quality --target-savings X 则保持一个具体的节省下限。添加 --weights 以使用——并输出——自定义特征权重进行评分,例如词法选项,从而使输出成为一份完整、可部署的配置(参见 docs/lexical-routing.md):

wayfinder-router calibrate data.jsonl --mode threshold --objective knee \
  --costs local=0.2,cloud=1.0 \
  --weights reasoning_term_count=5,math_symbol_count=3,constraint_term_count=1.5

成本仅为元数据——它影响校准后的切分点,并在 /metrics 端点上报告,但绝不参与逐请求决策,后者保持确定性且免费。

引导单个请求

部署的配置设定了默认边界,但客户端可以通过普通 OpenAI 传输方式覆盖单个请求的决策。覆盖仅改变请求的去向;提示词仍会被评分,且不会增加任何模型调用。

  • 该 model 字段是一条路由指令。 auto(或任何普通模型 id)让 Wayfinder 自行决定;配置好的端点名称(local、cloud)会把请求固定到那里;prefer-local / prefer-hosted 会固定到路由器的低端 / 高端(prefer-cloud 仍可作为 prefer-hosted 的别名使用)。
  • 一个 X-Wayfinder-Threshold 请求头会为该请求重新做出决策,0.0-1.0 中的一个数字会复用你的权重(仅限二值路由器)。
  • 消息内的 /directive(需主动启用:[gateway] slash_directives = true)让一个普通的聊天框也能引导路由——以 /local、/cloud、/prefer-hosted 或 /auto 开头的一条消息会固定该轮次(在模型看到之前会被剥离)。只有已知的指令才会被处理;任何其他以 / 开头的内容都会作为普通文本保留(WF-ADR-0036)。
  • 离线模式让你在无网络环境下继续工作。设置 [gateway] offline = true(或为单次请求发送 X-Wayfinder-Offline: true),Wayfinder 就会使用最便宜/本地的层级,绝不调用云端层级——因此请求不会在飞机上因超时而挂起。提示词仍会被评分和上报;只有投递方式发生变化(WF-ADR-0039)。
# Pin one call to cloud regardless of score:
client.chat.completions.create(model="cloud", messages=[...])
# Or move the cut for one call (keep model="auto"):
client.chat.completions.create(
    model="auto", messages=[...], extra_headers={"X-Wayfinder-Threshold": "0.8"}
)

每个响应都会添加x-wayfinder-router-mode (scored / pinned / threshold-override)紧邻-model和-score标头,这样你就能看到是哪个渠道决定了路由。

通过聊天界面驱动它(无需 fork)

因为 model 字段是一条路由指令,任何兼容 OpenAI 的聊天 UI 都能在无需改动代码的情况下驱动路由:应用原本的模型下拉菜单变成了按对话选择路由的选择器(auto / prefer-local / prefer-hosted / 一个固定端点)。网关会在 GET /v1/models 列出这些选项,因此 UI 可以自行发现它们。

两者都参见 examples/。原生 UI 唯一无法表达的是一个实时的按对话阈值滑块;这正是 wayfinder-chat 分支所添加的功能,而这条无需分支的路径先对它进行了验证。

查看请求流向何处

Wayfinder 的控制项分散在你已经在运行的各种工具中,因此很容易察觉不到它正在工作。有四个界面可以展示或操控路由:

界面 它展示什么 在哪里
模型下拉菜单 路由选择器(auto / prefer-local / prefer-hosted / 一个固定端点) 你的客户端,来自 GET /v1/models
响应头 每个请求去了哪里以及为什么(-model / -score / -mode / -request-id) 每一个响应
调试响应体字段 响应体内部的决策,需主动开启 请求头 X-Wayfinder-Debug: true
仪表盘 近期决策、按模型统计的数量、评分——仅元数据,绝不包含提示词文本 GET /router(JSON 位于 /router/recent)

该仪表盘与离线的 wayfinder-router ui 控制台相互独立,后者用于调优,而非生产流量。

从反馈中学习

不要猜测分界线,而是从你自己对本地与托管输出的判断中学习它。这个循环是:收集判断、校准、自动路由。

用 A/B 引导来启动它。对于每个示例提示词,wayfinder-router onboard 会同时运行两个分支,并询问哪个足够好;答案就是一个标签:

wayfinder-router onboard prompts.jsonl --arms local,cloud --calibrate > wayfinder-router.toml

比较结果输出到 stderr;--calibrate 将生成的配置打印到 stdout。每次判断都会向反馈日志追加一行 {"text", "label"},而该日志本身就是 calibrate 数据集,因此日志可以直接转化为配置。

要跳过人工评分,可以让 wayfinder-router judge 自动打标签。它会运行两个层级,并询问一个自动评判器 “更便宜的那个层级足够好吗?”——同一个充分性问题,无需人工介入:

wayfinder-router judge prompts.jsonl --arms local,cloud --gold gold.jsonl > wayfinder-router.toml

内置评判器是一个确定性的文本比较器,当它无法判断时会 弃权,而不是猜测。由于错误的标签会悄无声息地降低线上路由的质量,judge 只有在 通过信任门控 后才会输出配置——与你人工标注的 --gold 集一致(Cohen's κ ≥ 0.6)、在折外数据上优于多数基线,且两个分支都有代表。如果门控未通过,它会打印混淆矩阵并拒绝输出(标签仍会被记录)。传入 --save-comparisons out.jsonl 还可以保留原始响应(默认关闭——这是一个正文存储)。

一旦你开始自动路由,就通过记录实际哪个模型足够好来保持诚实:

curl localhost:8088/v1/feedback -d '{"text": "...", "label": "cloud"}'

然后按计划重新拟合,可以通过 cron、k8s CronJob 或 UI 中的点击来触发。重新校准只会重写 [routing] 部分,并保留你的 [gateway] 端点,运行中的网关会热重载结果,无需重启:

wayfinder-router recalibrate                  # log -> calibrate -> write config
wayfinder-router recalibrate --min-labels 50  # no-op until you have enough signal

评判过程会运行模型,因此它位于网关层(使用你的密钥);评分核心保持不变,日志中不携带任何机密。

部署与集成

CLI、引导流程和 UI 面向运维人员和初始化搭建。在生产环境中,提示词通过网关(透明)或库(进程内)流转,因此路由发生在提示词本就所在的位置。

将网关作为服务、sidecar 或独立进程运行:

docker build -t wayfinder-router . && docker run -p 8088:8088 -v "$PWD/data:/data" wayfinder-router
# or: docker compose up gateway   (see docker-compose.example.yml)

将你现有的客户端指向它,无需改动应用。任何兼容 OpenAI API 的东西只需一个 base_url 即可接入,包括智能体框架(LangChain、LlamaIndex)、支持自定义端点的 IDE 助手(Cursor、Continue),以及像 LiteLLM 这样的网关:

client = openai.OpenAI(base_url="http://localhost:8088/v1", api_key="unused")

参见 集成配方,获取可直接复制粘贴的配置,覆盖聊天 UI(Open WebUI、LibreChat、Jan)、编辑器(Continue、Cline、Zed、JetBrains)、智能体框架(LangChain、LlamaIndex、CrewAI、AutoGen、OpenAI Agents SDK、Vercel AI SDK)以及 CLI(aider、Copilot CLI)——外加经典的 OPENAI_BASE_URL / OPENAI_API_KEY 组合。

Claude Code 使用的是 Anthropic 的 Messages API 而非 OpenAI 的,因此网关提供了一个 POST /v1/messages 适配器(WF-DESIGN-0011),可在两个方向上进行 Anthropic ⇄ OpenAI 的转换——包括流式传输和工具调用。将其指向网关根地址,Claude Code 就会像其他客户端一样通过 Wayfinder 路由:

export ANTHROPIC_BASE_URL="http://localhost:8088"   # client appends /v1/messages
export ANTHROPIC_API_KEY="unused"                   # the gateway uses each upstream's own key
claude

从你的用户所在的任何地方接入反馈。你的应用、IDE 或聊天界面显示点赞或点踩并提交判断;下一次重新校准会从中学习:

fetch("http://localhost:8088/v1/feedback", {
  method: "POST",
  body: JSON.stringify({ text: prompt, label: wasGoodEnough ? "local" : "cloud" }),
});

网关异步转发并以流式方式传输:带有 stream: true 的请求会以 Server-Sent-Events 形式返回,因此聊天客户端可以在 token 到达时即时渲染。上游超时或连接失败会返回 OpenAI 格式的错误,而不是裸的 500,每个响应都带有请求 id 以便追踪,路由决策和重载失败都会被记录日志。

除此之外,它还具备你所期望的生产级控制项——按请求超时、有界重试,并配有按目标熔断器和故障转移、支出预算上限、精确匹配响应缓存, 速率限制,以及虚拟 API 密钥,支持按密钥设置预算和允许列表。这些默认全部关闭或设置得较为宽松;有关每项设置及其暴露的各个请求头,请参阅网关配置参考。

解释与调优

要了解某个提示词为何被路由到某个位置,可以请求按特征细分:每个特征的值、其归一化水平、其权重,以及它在得分中所占的份额。

wayfinder-router route prompt.md --explain

如需交互式调优,有一个本地 Web UI:

  • Explain — 粘贴一个提示词;查看分数、层级阶梯和贡献条,并拖动阈值滑块实时观察路由变化。
  • Calibrate — 粘贴一个带标签的数据集,运行某个模式,查看准确率、扫描曲线以及生成的配置片段。
  • Configure — 编辑 wayfinder-router.toml,带实时校验并保存。
  • Onboard — 在浏览器中对本地模型和托管模型进行 A/B 测试,逐一评判,并根据日志进行校准(模型调用需要 [gateway])。
pip install "wayfinder-router[ui]"
wayfinder-router ui --port 8099    # then open http://localhost:8099

该 UI 只是对同一组纯函数的轻量封装;它从不调用模型,其中也不会出现任何密钥。

Python API

from wayfinder_router import score_complexity, RoutingConfig, explain_score

result = score_complexity(prompt_text, config=RoutingConfig.binary(threshold=0.7))
print(result.recommendation, result.score, result.features)
for fc in explain_score(result.features, RoutingConfig().weights):
    print(fc.name, fc.contribution)

起源

Wayfinder 最初是一个更大需求工具内部的 route 实验,后来被拆分出来,因为路由是运行时关注点,而非知识关注点:提示词路由器不应该让你安装一个你并不需要的引擎。最终成果是一个小巧而专注的工具,其评分核心保持零依赖——你可以仅用标准库就 import wayfinder_router 并对提示词评分(WF-ADR-0001、WF-ADR-0029)。

仓库结构

wayfinder-router/
  wayfinder_router/   the package: scorer, tiers + classifier, config loader/writer,
                      offline calibration (Newton/IRLS), explain, the feedback log and
                      onboarding harness, recalibration, CLI, and the optional gateway
                      and local UI (the impure layers, behind their extras)
  tests/              scorer, config, calibration, explain, feedback, onboard,
                      recalibrate, CLI, gateway, and UI coverage
  decisions/          design notes behind the tool's own choices
  docs/               the FAQ and the lexical-routing guide
  Dockerfile, docker-compose.example.yml   deploy the gateway as a service

测试

pip install -e .[dev]   # or: pip install pytest
make test

来源:Hacker News 热门(buzzing.cc 中文翻译) · github.com