mcpField
O
OpenZiti / LLM-Gateway

OpenZiti / LLM-Gateway

已认证精选本地服务
netfoundry.ioAI 与智能体1032 周前更新

关于 OpenZiti / LLM-Gateway

NetFoundry LLM Gateway 是 OpenZiti 项目中的 OpenAI 兼容 API 代理,可把请求路由到 OpenAI、Anthropic 及任意 OpenAI 兼容后端。它通过 zrok 与 OpenZiti 覆盖网络连接位于 NAT 之后的推理服务器,适合需要零信任访问多个 LLM 后端的团队。

主要功能

  1. 01OpenAI 兼容 API,并转换 Anthropic 格式
  2. 02按模型名前缀路由到不同提供方
  3. 03三层语义路由:启发式、嵌入与分类器
  4. 04多端点加权轮询与健康检查故障转移
  5. 05基于 zrok 的零信任后端连接
  6. 06Prometheus 指标与 API 密钥认证

适用场景

  1. 01把 Ollama、vLLM 等本地推理服务接入统一网关
  2. 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 ./...

快速开始

  1. 创建配置文件:
# 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"
  1. 运行网关:
export OPENAI_API_KEY="sk-..."
export ANTHROPIC_API_KEY="sk-ant-..."
llm-gateway run config.yaml
  1. 使用任意兼容 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 字段变为可选项——如果省略,请求会经过以下三层级联:

  1. 启发式规则 — 通过关键词/模式快速匹配(例如,“翻译” -> 快速模型,工具使用 -> 支持工具的模型)
  2. 嵌入 — 使用 Ollama 或 OpenAI 嵌入,在用户提示词和路由示例之间计算余弦相似度
  3. 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.requestsCounter请求总数(按提供商、模型、流式传输统计)
llm_gateway.request.durationHistogram请求耗时(秒)(按提供商、模型统计)
llm_gateway.tokens.promptCounter提示词 token 总数(按提供商、模型统计)
llm_gateway.tokens.completionCounter补全 token 总数(按提供商、模型统计)
llm_gateway.routing.decisionsCounter语义路由决策数(按方法统计)
llm_gateway.provider.errorsCounter提供商错误数(按 error_type 统计)
llm_gateway.requests.inflightGauge当前正在处理的请求数
llm_gateway.endpoint.healthyGauge端点健康状态

跟踪

启用请求正文日志记录,以调试路由决策:

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

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。