关于 OpenZiti / LLM-Gateway
NetFoundry LLM Gateway 是 OpenZiti 项目中的 OpenAI 兼容 API 代理,可把请求路由到 OpenAI、Anthropic 及任意 OpenAI 兼容后端。它通过 zrok 与 OpenZiti 覆盖网络连接位于 NAT 之后的推理服务器,适合需要零信任访问多个 LLM 后端的团队。
主要功能
- 01OpenAI 兼容 API,并转换 Anthropic 格式
- 02按模型名前缀路由到不同提供方
- 03三层语义路由:启发式、嵌入与分类器
- 04多端点加权轮询与健康检查故障转移
- 05基于 zrok 的零信任后端连接
- 06Prometheus 指标与 API 密钥认证
适用场景
- 01把 Ollama、vLLM 等本地推理服务接入统一网关
- 02通过 zrok 在无需开放端口的情况下暴露网关
MCP 相关
该项目的 README 未说明与 MCP 的关系,因此此处留空。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
llm-gateway
兼容 OpenAI 的 API 代理,可将请求路由到 OpenAI、Anthropic 以及任何兼容 OpenAI 的后端(Ollama、vLLM、llama-server、SGLang 等)。还可选择通过 zrok 暴露网关,实现零信任访问。
为什么还需要一个 LLM 网关?
大多数 LLM 代理解决的是 API 转换问题。这个网关还解决了网络问题:如何将网关连接到位于 NAT 后的 GPU 服务器,在不开放端口的情况下将其提供给客户端,并将请求路由到正确的模型——所有这些都无需额外搭建 VPN、服务网格或路由数据库?
- 借助 zrok(基于 OpenZiti)实现零信任网络 — 网关和后端通过 zrok 在 OpenZiti 覆盖网络上通信。无需防火墙规则或端口转发,即可暴露网关,或跨越 NAT、隔离网络和云边界访问后端。两个方向的操作方式相同。
- 语义路由 — 三层级联(关键词启发式规则、嵌入相似度、LLM 分类器)会在客户端省略
model字段时自动选择最佳模型。无需手动维护路由表。 - 多端点负载均衡 — 在推理服务器池中实现加权轮询、带被动故障转移的健康检查,以及 VM 休眠检测。适用于 Ollama、llama-server、vLLM、SGLang,或任何提供
/v1/chat/completions的服务。专为在实际硬件上分配推理任务而构建。 - 单个二进制文件,无需基础设施 — 一个 Go 二进制文件,一个 YAML 文件。无需数据库、消息队列或 Sidecar。
功能
- 兼容 OpenAI 的 API:可直接替换 OpenAI 客户端库
- 多提供商路由:根据模型名称自动路由请求
- 语义路由:可选的三层级联(启发式规则、嵌入、LLM 分类器),在省略
model时自动选择最佳模型 - Anthropic 格式转换:透明地将 OpenAI 格式与 Anthropic 的 Messages API 相互转换
- 流式传输支持:所有提供商均支持服务器发送事件(SSE)流式传输
- 多端点负载均衡:在多个推理后端之间分配负载,并自动故障转移
- OpenTelemetry 指标:导出 Prometheus 指标,涵盖请求、延迟、令牌和端点健康状况
- zrok 集成:通过 zrok 私有或公共共享暴露网关
- 零信任后端:通过 zrok 共享连接到任意提供商(无需开放端口)
初次使用? 请参阅入门指南,按照分步说明从零开始搭建可运行的网关。
安装
可在 Releases 页面下载适用于 Linux、macOS 和 Windows 的预编译二进制文件。
也可使用 Go 安装:
go install github.com/openziti/llm-gateway/cmd/llm-gateway@latest
或从源代码构建:
git clone https://github.com/openziti/llm-gateway.git
cd llm-gateway
go install ./...
快速开始
- 创建配置文件:
# config.yaml
listen: ":8080"
providers:
open_ai:
api_key: "${OPENAI_API_KEY}"
anthropic:
api_key: "${ANTHROPIC_API_KEY}"
local: # works with any OpenAI-compatible backend
base_url: "http://localhost:11434"
- 运行网关:
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
llm-gateway run config.yaml
- 使用任意兼容 OpenAI 的客户端发送请求:
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o",
"messages": [{"role": "user", "content": "Hello!"}]
}'
提供商路由
请求根据模型名称前缀进行路由:
| 模型前缀 | 提供商 |
|---|---|
gpt-* | OpenAI |
o1-* | OpenAI |
o3-* | OpenAI |
claude-* | Anthropic |
| 其他所有模型 | 本地 / 可自托管 |
任何前缀不匹配 OpenAI 或 Anthropic 的模型都会路由到本地提供商。它适用于任何兼容 OpenAI 的后端,例如 Ollama、vLLM、llama-server、SGLang 等。
多端点负载均衡
将请求分发到多个推理后端,实现负载均衡和弹性。当存在 endpoints 时,网关会采用轮询选择,并在故障时自动切换:
providers:
local:
endpoints:
- name: gpu-box-1
base_url: "http://10.0.0.1:11434"
weight: 3
- name: gpu-box-2
base_url: "http://10.0.0.2:11434"
- name: remote
zrok_share_token: "abc123"
health_check:
interval_seconds: 30 # default: 30
timeout_seconds: 5 # default: 5
每个端点都可以使用直接 HTTP 或 zrok 共享。可选的 weight(默认值:1)用于控制端点接收的流量比例——权重为 3 的端点接收的请求约为权重为 1 的端点的 3 倍。后台 goroutine 会按配置的间隔 ping 每个端点,并将不健康的端点标记为自动跳过。请求期间发生的网络错误也会立即触发被动故障切换。所有使用本地提供方的网关功能(聊天补全、嵌入、分类器)都会将请求分发到端点组。
这些端点不必运行相同的软件。你可以在同一个池中混用 Ollama、vLLM、llama-server 或任何其他兼容 OpenAI 的服务——负载均衡层不关心 URL 后面运行的是什么。
API 端点
POST /v1/chat/completions
兼容 OpenAI 的聊天补全端点。支持流式(stream: true)和非流式请求。启用语义路由后,model 字段为可选项。
GET /v1/models
返回所有已配置提供方的可用模型。启用语义路由后,还会包含一个用于触发自动模型选择的 auto 虚拟模型。在多端点模式下,返回所有健康端点上的模型并去重。
GET /health
返回 {"status":"ok"},HTTP 状态码为 200。可用于存活检查。
GET /metrics
Prometheus 指标端点(当 metrics.enabled: true 时)。提供请求计数、持续时间直方图、令牌计数器、路由决策、提供方错误、进行中的请求数以及端点健康状态。
配置
完整配置示例
listen: ":8080"
zrok:
share:
enabled: false
mode: private # public or private
token: "" # use existing persistent share (private only)
providers:
open_ai:
api_key: "${OPENAI_API_KEY}"
base_url: "" # optional: override for Azure or compatible APIs
zrok_share_token: "" # optional: connect via zrok share
anthropic:
api_key: "${ANTHROPIC_API_KEY}"
base_url: "" # optional: override base URL
zrok_share_token: "" # optional: connect via zrok share
local:
base_url: "http://localhost:11434"
zrok_share_token: "" # optional: connect via zrok share
# or use multi-endpoint mode for round-robin + failover:
# endpoints:
# - name: gpu-box-1
# base_url: "http://10.0.0.1:11434"
# - name: gpu-box-2
# base_url: "http://10.0.0.2:11434"
# - name: remote
# zrok_share_token: "abc123"
# health_check:
# interval_seconds: 30
# timeout_seconds: 5
metrics:
enabled: false
环境变量
API 密钥支持使用 ${VAR} 语法展开环境变量。
API 密钥
网关支持使用虚拟 API 密钥对客户端进行身份验证。生成密钥并将其添加到配置中:
llm-gateway genkey
# sk-gw-a1b2c3d4e5f6...
api_keys:
enabled: true
keys:
- name: alice
key: "sk-gw-a1b2c3d4e5f6..."
客户端通过 Authorization: Bearer <key> 标头发送密钥。/health 和 /metrics 端点无需身份验证。可以使用 glob 模式将密钥限制为特定模型。有关面向客户端的约定,请参阅 docs/current/api-keys.md;有关可重新加载的 YAML 和 HTTP 来源,请参阅 docs/current/key-sources.md。
语义路由
配置后,网关可以根据请求内容自动选择最合适的模型。model 字段变为可选项——如果省略,请求会经过以下三层级联:
- 启发式规则 — 通过关键词/模式快速匹配(例如,“翻译” -> 快速模型,工具使用 -> 支持工具的模型)
- 嵌入 — 使用 Ollama 或 OpenAI 嵌入,在用户提示词和路由示例之间计算余弦相似度
- LLM 分类器 — 当嵌入结果不明确时,请求 LLM 对请求进行分类
每一层都可以单独启用或禁用——例如,可以在不使用嵌入的情况下使用分类器。如果所有层都被跳过或无法得出结论,则使用配置的默认路由。禁用语义路由或未配置语义路由时,行为保持不变。
语义路由配置
routing:
allow_explicit_model: true # clients can still specify a model directly
default_route: general # fallback when no layer matches
heuristics:
enabled: true
rules:
- match:
keywords: ["translate", "translation"]
route: fast
- match:
has_tools: true
route: tools
- match:
system_prompt_contains: "you are a code assistant"
route: coding
- match:
max_tokens_lt: 100
message_length_lt: 200
route: fast
semantic:
enabled: true
provider: local # local or openai
model: nomic-embed-text
threshold: 0.82 # confident match
ambiguous_threshold: 0.65 # escalate to classifier
comparison: centroid # centroid, max, or average
classifier:
enabled: true
provider: local
model: llama3
timeout_ms: 5000
confidence_threshold: 0.7
routes:
- name: coding
model: claude-sonnet-4-20250514
description: "code generation, debugging, and technical tasks"
examples:
- "write a python function to sort a list"
- "debug this segfault in my C code"
- name: creative
model: claude-sonnet-4-20250514
description: "creative writing, storytelling, and artistic content"
examples:
- "write a poem about the ocean"
- "tell me a story about a dragon"
- name: fast
model: llama3
description: "simple tasks, translations, and short responses"
examples:
- "translate hello to French"
- "what is 2+2"
- name: tools
model: gpt-4
description: "tasks requiring tool use and function calling"
examples:
- "search the web for recent news"
- "call the weather API for New York"
- name: general
model: llama3
description: "general conversation and miscellaneous tasks"
examples:
- "what is the capital of France"
- "explain quantum computing"
启发式匹配条件
每条启发式规则都有一个包含一个或多个条件的 match 块。单条规则中指定多个条件时,必须全部匹配(AND 逻辑)。在 keywords 中,任意关键词匹配都会触发规则(OR 逻辑)。可用条件:
| 条件 | 描述 |
|---|---|
keywords | 对用户消息内容进行不区分大小写的单词边界匹配 |
has_tools | 如果请求包含或不包含工具定义,则匹配 |
system_prompt_contains | 对系统消息进行子字符串匹配 |
max_tokens_lt | 如果 max_tokens 低于阈值,则匹配 |
message_length_lt | 如果消息总字符长度低于阈值,则匹配 |
exclude | 短语列表;如果这些短语出现在用户消息中,则阻止关键词匹配 |
不指定模型发送请求
启用语义路由后,可以省略 model 字段:
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"messages": [{"role": "user", "content": "Write a Python function to sort a list"}]
}'
与聊天客户端搭配使用(Open WebUI 等)
Open WebUI 等聊天客户端要求从模型列表中选择模型,因此始终会发送 model 字段。启用语义路由后,网关会公开一个虚拟 auto 模型,用于触发自动路由:
curl http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"messages": [{"role": "user", "content": "Write a Python function to sort a list"}]
}'
将客户端指向 http://localhost:8080/v1,并从模型列表中选择 auto。网关会通过语义路由级联为每个请求进行路由。
网关会记录每次路由决策所用的方法、置信度分数、延迟和级联跟踪信息。
指标
通过 Prometheus 导出器启用 OpenTelemetry 指标:
metrics:
enabled: true
启用后,网关会在同一监听地址上通过 GET /metrics 提供 Prometheus 指标。可用指标:
| 指标 | 类型 | 描述 |
|---|---|---|
llm_gateway.requests | Counter | 请求总数(按提供商、模型、流式传输统计) |
llm_gateway.request.duration | Histogram | 请求耗时(秒)(按提供商、模型统计) |
llm_gateway.tokens.prompt | Counter | 提示词 token 总数(按提供商、模型统计) |
llm_gateway.tokens.completion | Counter | 补全 token 总数(按提供商、模型统计) |
llm_gateway.routing.decisions | Counter | 语义路由决策数(按方法统计) |
llm_gateway.provider.errors | Counter | 提供商错误数(按 error_type 统计) |
llm_gateway.requests.inflight | Gauge | 当前正在处理的请求数 |
llm_gateway.endpoint.healthy | Gauge | 端点健康状态 |
跟踪
启用请求正文日志记录,以调试路由决策:
tracing:
enabled: true
max_content_length: 200 # max characters per message in log output
每个聊天补全请求都会记录模型、消息数量、流式传输标志、工具数量,以及每条消息的角色和截断后的内容。详情请参阅 docs/current/configuration.md。
CLI 参考
llm-gateway run <configPath>
Flags:
--address string listen address (overrides config)
--zrok enable zrok sharing (overrides config)
--zrok-mode string zrok share mode: public, private (overrides config)
zrok 集成
暴露网关
启用 zrok 共享,无需开放防火墙端口即可暴露网关:
zrok:
share:
enabled: true
mode: private
也可以通过 CLI 启用:
llm-gateway run config.yaml --zrok --zrok-mode private
网关启动时会记录共享令牌。客户端通过 zrok 访问进行连接。
使用持久共享
如需在重启后保持共享令牌不变,请使用 zrok CLI 创建持久共享并引用它:
zrok:
share:
enabled: true
token: "abc123xyz" # your persistent share token
通过 zrok 连接后端
任何提供商都可以通过 zrok 共享访问,而不是使用直接 URL:
providers:
open_ai:
api_key: "${OPENAI_API_KEY}"
zrok_share_token: "openai-proxy-share-token"
anthropic:
api_key: "${ANTHROPIC_API_KEY}"
zrok_share_token: "anthropic-proxy-share-token"
local:
zrok_share_token: "ollama-share-token"
示例
与 Python OpenAI 客户端搭配使用
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8080/v1",
api_key="not-needed" # gateway handles auth
)
# routes to OpenAI
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}]
)
# routes to Anthropic (translated automatically)
response = client.chat.completions.create(
model="claude-sonnet-4-20250514",
messages=[{"role": "user", "content": "Hello!"}]
)
# routes to local backend (Ollama, vLLM, etc.)
response = client.chat.completions.create(
model="llama3.2",
messages=[{"role": "user", "content": "Hello!"}]
)
流式传输
stream = client.chat.completions.create(
model="claude-sonnet-4-20250514",
messages=[{"role": "user", "content": "Write a haiku"}],
stream=True
)
for chunk in stream:
if chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="")
文档
- 快速入门 -- 分步设置指南
- 配置 -- 完整的配置参考和 CLI 标志
- 提供商 -- 提供商详情、流式传输和错误处理
- 语义路由 -- 阈值调优、比较模式和缓存
- API 密钥 -- 每个密钥的模型和路由限制
- 密钥来源 -- 可重新加载的密钥记录、YAML 和 HTTP 契约、过期状态及可观测性
- 多端点负载均衡 -- 加权负载均衡和故障转移
- 指标 -- Prometheus 指标和示例查询
- 流式传输 -- SSE 流式传输详情
- zrok -- 用于共享和访问的覆盖网络
- Agora -- 用于提供服务和拨号的 Agora 覆盖网络(与 zrok 的对等传输)
- 虚拟模型 -- 用于测试和演示的 OpenAI 兼容虚拟后端
- 虚拟密钥 -- 提供 HTTP 密钥来源契约的参考密钥 API,支持故障注入
许可证
Apache 2.0
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。