Wayfinder Router:在本地和托管的大语言模型之间进行确定性查询路由
Wayfinder Router:在本地和托管的大型语言模型(LLM)之间进行确定性查询路由
Wayfinder Router 通过分析提示词的结构(长度、标题、列表、代码)和措辞(证明、数学、硬约束),在微秒级完成路由决策,完全离线且无需调用其他模型。默认仅使用结构特征,词汇线索因盲测未泛化而默认为关闭。对比依赖模型调用的路由器(如 RouteLLM、NotDiamond),它避免了延迟、成本和随机性。用户可在自有数据上校准评分阈值。支持任何 OpenAI 兼容 API(含 Ollama、Anthropic、Groq、vLLM 等),可自托管。提供终端和网页演示(--dry-run 无需密钥),以及基准测试和 FAQ。
Wayfinder Router 把 prompt 路由变成了离线文本分析,无需额外模型调用,对希望节省成本同时保持私密的开发者很实用,比现有方案更轻量和确定,但纯语义难题仍是短板。

对每个提示词做一次快速、离线的难易判定——以确定性方式打分,不调用任何模型。把简单的路由到你的小型/本地模型,把困难的交给你的大型模型,或者在其后组合任意模型路由器。
快速开始 · 基准测试 · 对比情况 · 说明 · 更新日志
| 不调用模型 即可决定路由 | 确定性 且完全离线 |
| 校准 基于你自己的数据 | 自带密钥 自托管 |
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。
-
生成配置脚手架——
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会检测你已安装了其中哪些工具,并建议确切的配置行。 -
设置好你的密钥,然后运行网关。
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
-
把你现有的客户端指向它即可。无需改动代码:
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/v1macOS 是主要目标平台;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 可以自行发现它们。
- LibreChat —— 将
examples/librechat.yaml和examples/docker-compose.override.yml复制到你的代码检出中,运行docker compose up,然后选择 "Wayfinder" 端点。 - Open WebUI —— 添加一个指向该网关的 OpenAI 连接;它会自动发现这些路由选项。
两者都参见 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