☰
semantic-router Router API 参考:ExtProc 协议、OpenAI 兼容端点与 Prometheus 指标体系全解
2026/10/14 16:23:46 网站建设 项目流程
  • 后端
  • API网关
  • 模型推理服务
  • AI Agent

【免费下载链接】semantic-router

An open, programmable decision layer for models and compute.

项目地址:https://gitcode.com/gh_mirrors/sem/semantic-router
点击查看免费下载

本文基于 semantic-router 仓库的 Router API 参考文档(router.md),系统讲解该项目的 API 体系:包括基于 gRPC 的 Envoy ExtProc 集成协议、OpenAI 兼容的/v1/models与/v1/chat/completions端点、路由 Header 约定,以及/health、/metrics等运维监控接口。读完本篇,你可以完成与 Router 的端到端集成,并建立一套覆盖分类、缓存、安全、成本与 TTFT/TPOT 延迟的可观测性监控方案。

1. API 概览:Router 作为 ExtProc 服务器

Semantic Router 提供了一个基于 gRPC 的 API,可与 Envoy 的外部处理(ExtProc)协议无缝集成。Router 作为一个 ExtProc 服务器运行,通过 Envoy 代理处理 HTTP 请求。它不直接公开 REST endpoint 处理推理流量,而是处理通过 Envoy 路由的 OpenAI 兼容 API 请求。

注意:除了 ExtProc 路径外,该项目还在8080 端口启动了一个轻量级的 HTTP Classification API,用于健康/信息和分类工具。OpenAI 兼容的/v1/models端点由该 HTTP API(8080)提供,并可以通过路由规则在 Envoy(8801)上有选择地公开。

1.1 端口和端点映射

端口协议用途
8801HTTPEnvoy 公共入口。典型的客户端入口,用于 OpenAI 兼容请求,如POST /v1/chat/completions。如果添加了 Envoy 路由,可以将GET /v1/models代理到 Router 8080;否则 8801 的/v1/models可能返回 "no healthy upstream"
8080HTTPClassification API:GET /v1/models(OpenAI 兼容模型列表,含合成的MoM)、GET /health、GET /info/models(已加载的分类器模型 + 系统信息)、GET /info/classifier(分类器配置详情)、POST /api/v1/classify/intent\|pii\|security\|batch(直接分类工具)
50051gRPCEnvoy 外部处理(ExtProc),用于/v1/chat/completions的路径内分类/路由。注意:这不是 HTTP 端口,无法直接通过 curl 访问
9190HTTPPrometheus 指标:GET /metrics(全局进程指标抓取端点)

这些端口在源码中得到了印证。启动引导代码 中定义了运行参数的默认值:

port = flag.Int("port", 50051, "Port to listen on for gRPC ExtProc") apiPort = flag.Int("api-port", 0, "Port to listen on for the router apiserver (default from config: 8080)") metricsPort = flag.Int("metrics-port", 9190, "Port for Prometheus metrics")

即 gRPC ExtProc 默认监听50051、Prometheus 指标默认监听9190,而 Classification API 的8080端口默认取自配置文件。

1.2 请求流程

一次完整的聊天补全请求在客户端、Envoy、Router 和后端模型之间的流转如下:

关键设计点:Router 在请求阶段做"分类与路由"决策,并以路由 Header 的形式返回给 Envoy,由 Envoy 根据这些 Header 完成流量调度;在响应阶段 Router 再次介入,对响应做增强(追加元数据 Header、安全标记等),客户端最终拿到的是"增强后的响应"。

2. OpenAI API 兼容性

路由处理标准的 OpenAI API 请求,主要包括两个端点:模型列表与聊天补全。

2.1 模型端点(GET /v1/models)

列出可用模型,并包含一个合成的"MoM"(Mixture of Models)模型,该模型使用 Router 的 intent classification 为每个请求选择最佳的基础模型。

响应示例:

{ "object": "list", "data": [ { "id": "MoM", "object": "model", "created": 1726890000, "owned_by": "semantic-router" }, { "id": "gpt-4o-mini", "object": "model", "created": 1726890000, "owned_by": "upstream-endpoint" }, { "id": "llama-3.1-8b-instruct", "object": "model", "created": 1726890000, "owned_by": "upstream-endpoint" } ] }

注意事项:

  • 具体的模型列表来源于config.yaml中配置的 vLLM 端点(见vllm_endpoints[].models);
  • 特殊的MoM(Mixture of Models)模型始终存在,并指示 Router 自动分类并路由到最佳后端模型。为了向后兼容,模型名称auto也被接受为别名。

源码印证:/v1/models的处理入口在 handleOpenAIModels,它根据当前生效的配置生成模型列表,并通过ListBackendModels配置项(默认false)控制是否在列表中额外包含具体后端模型——默认情况下客户端看到的"入口模型"更少更干净,配置开启后才能直接看到所有可指定的后端模型名。

2.2 聊天补全端点(POST /v1/chat/completions)

请求格式
{ "model": "gpt-3.5-turbo", "messages": [ { "role": "user", "content": "x^2 的导数是多少?" } ], "max_tokens": 150, "temperature": 0.7, "tools": [ { "type": "function", "function": { "name": "calculator", "description": "执行数学计算" } } ] }
响应格式

响应在标准 OpenAI 结构之外附带了routing_metadata字段,用于暴露 Router 的决策信息:

{ "id": "chatcmpl-abc123", "object": "chat.completion", "created": 1677858242, "model": "gpt-3.5-turbo", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "x^2 的导数是 2x。" }, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 12, "completion_tokens": 8, "total_tokens": 20 }, "routing_metadata": { "selected_model": "mathematics", "confidence": 0.96, "processing_time_ms": 15, "cache_hit": false, "security_checks": { "pii_detected": false, "jailbreak_detected": false } } }

routing_metadata使客户端无需解析 Header 也能获知:请求被路由到了哪个类别/模型、分类置信度、处理耗时、是否命中缓存,以及 PII / 越狱(jailbreak)安全检查的结果。

3. 路由 Header

路由在请求和响应中都会添加元数据 Header,这是 Router 与 Envoy 之间传递路由决策的主要机制。

3.1 请求 Header(由路由添加)

Header描述示例
x-vsr-destination-endpoint选定的后端端点endpoint1
x-selected-model确定的模型类别mathematics
x-routing-confidence分类置信度0.956
x-request-id唯一请求标识符req-abc123
x-cache-status缓存命中/未命中状态miss

3.2 响应 Header(由路由添加)

Header描述示例
x-processing-time总处理时间 (ms)45
x-classification-time分类时间 (ms)12
x-security-checks安全检查结果pii:false,jailbreak:false
x-tools-selected选定的工具数量2

3.3 从源码看:完整的x-vsr-*Header 契约

上表是文档层面的核心契约。当前源码中,Header 的完整定义集中在 headers.go,可以推断出实际部署中的 Header 面比早期文档更广,形成了一套带版本号的响应契约(v0.4)。几个值得关注的要点:

  • 决策追踪 Header:x-vsr-selected-category(分类器选定的 MMLU 类别)、x-vsr-selected-decision(DecisionEngine 最终选定的决策)、x-vsr-selected-confidence(0.0–1.0 的置信度)、x-vsr-selected-model(最终处理请求的模型名)、x-vsr-routing-latency-ms(路由耗时,微秒精度)。
  • 响应契约标记:x-vsr-schema-version标注 Header 契约修订版(当前为"2"),x-vsr-response-path标明响应产生路径,取值包括upstream、cache、fast_response、looper、image_generation、blocked、rate_limited、error、fallback等。这两个 Header 出现在每一次 VSR 处理的响应上,客户端可据此判断"这次响应到底是谁产生的"。
  • 信号追踪 Header:x-vsr-matched-keywords、x-vsr-matched-embeddings、x-vsr-matched-pii、x-vsr-matched-jailbreak等,暴露哪些信号规则被命中,便于调试决策过程。
  • 客户端控制 Header:x-vsr-debug(为单请求开启调试/回放模式 Header)、x-vsr-skip-processing(在global.router.skip_processing.enabled为 true 时让请求跳过所有路由处理)、x-session-id(客户端指定会话 ID)。
  • 缓存与成本 Header:x-vsr-cache-hit、x-vsr-cost与x-vsr-cost-currency(按所选模型配置的计价计算响应成本)。

从源码结构看,Header 是"调试/运维面"的主要载体:默认面保持精简,完整诊断信息(如幻觉检测 span、越狱类型与置信度)放在 Router Replay 记录中,可通过x-vsr-replay-id关联取回。

4. 健康检查 API

Router 提供用于监控的健康检查 endpoint:

端点:GET http://localhost:8080/health

{ "status": "healthy", "version": "1.0.0", "uptime": 3600, "models": { "category_classifier": "loaded", "pii_detector": "loaded", "jailbreak_guard": "loaded" }, "cache": { "status": "healthy", "entries": 1247, "hit_rate": 0.73 }, "endpoints": { "endpoint1": "healthy", "endpoint2": "healthy", "endpoint3": "degraded" } }

该健康检查聚合了四个维度:进程状态与版本、各分类模型(类别分类器、PII 检测器、越狱防护)的加载状态、响应缓存的健康度与命中率、以及各后端端点的健康状态(healthy/degraded)。从源码看,/health是 Classification API 中少数允许匿名访问的端点(参见 route_auth_test.go 中"匿名 /health 应成功"的断言),适合直接用于负载均衡器或编排系统的存活探针。此外还有/ready、/startup-status等就绪/启动状态端点可供使用。

与文档中/info/models、/info/classifier对应的库存信息接口,在当前源码中挂载于管理 API 命名空间下(见 routes_catalog.go):

  • GET /api/v1/inventory/models:已加载模型信息;
  • GET /api/v1/inventory/classifier:分类器信息与状态(无secret_view权限时密钥被脱敏);
  • GET /api/v1/inventory/embedding-models、GET /api/v1/inventory/model-runtime:嵌入模型与 model_runtime 部署的进程/就绪/重启/服务模型卡信息。

直接分类工具端点在当前源码中位于诊断命名空间,包括POST /api/v1/diagnostics/classify/intent、/api/v1/diagnostics/classify/pii、/api/v1/diagnostics/classify/security以及POST /api/v1/classify/batch等(见 api_paths.go 与 routes_catalog.go),可用于在不发真实补全请求的情况下验证分类模型行为。

5. 指标 API(Metrics API)

Router 提供 Prometheus 兼容指标,抓取端点为GET http://localhost:9190/metrics(由 main.go 中的独立 metrics HTTP server 提供,可用--metrics-port覆盖默认端口 9190)。

5.1 关键指标

# 请求指标 semantic_router_requests_total{endpoint="endpoint1",category="mathematics",status="success"} 1247 semantic_router_request_duration_seconds{endpoint="endpoint1"} 0.045 # 分类指标 semantic_router_classification_accuracy{category="mathematics"} 0.94 semantic_router_classification_duration_seconds 0.012 # 缓存指标 semantic_router_cache_hit_ratio 0.73 semantic_router_cache_size 1247 # 安全指标 semantic_router_pii_detections_total{action="block"} 23 semantic_router_jailbreak_attempts_total{action="block"} 5 # 错误指标 llm_request_errors_total{model="gpt-4",reason="timeout"} 12 llm_request_errors_total{model="claude-3",reason="upstream_5xx"} 3 llm_request_errors_total{model="phi4",reason="upstream_4xx"} 5 llm_request_errors_total{model="phi4",reason="pii_policy_denied"} 8

5.2 推理模式指标(Reasoning Mode Metrics)

Router 公开了专用的 Prometheus 计数器,用于监控跨模型家族的 reasoning mode 决策和 template 使用情况。这些指标由 Router 发送,可以由你的 Prometheus 服务器抓取。

  • llm_reasoning_decisions_total{category, model, enabled, effort}

    • 描述:按类别和所选模型记录的推理决策计数,包括是否启用推理以及应用的努力等级(effort level)。
    • 标签:
      • category:路由期间确定的类别名称
      • model:请求最终选择的模型
      • enabled:根据决策结果为"true"或"false"
      • effort:启用时的努力等级(例如low|medium|high)
  • llm_reasoning_template_usage_total{family, param}

    • 描述:特定模型家族模板参数应用于请求的次数统计。
    • 标签:
      • family:规范化的模型家族(例如qwen3, deepseek, gpt-oss, gpt)
      • param:应用的模板参数名称(例如enable_thinking, thinking, reasoning_effort)
  • llm_reasoning_effort_usage_total{family, effort}

    • 描述:为给定模型家族设置推理努力等级的次数统计。
    • 标签:
      • family:规范化的模型家族
      • effort:努力等级(例如low|medium|high)

这三个计数器在 reasoning_metrics.go 中定义,记录入口函数分别为RecordReasoningDecision、RecordReasoningTemplateUsage、RecordReasoningEffortUsage;从源码看,当family或param/effort为空时会归一化为unknown/none/unspecified,保证标签基数可控。

PromQL 示例:

# 按类别和模型划分的推理决策(最近 5 分钟) sum by (category, model, enabled, effort) ( rate(llm_reasoning_decisions_total[5m]) ) # 按模型家族和参数划分的模板使用情况(最近 5 分钟) sum by (family, param) ( rate(llm_reasoning_template_usage_total[5m]) ) # 按模型家族划分的努力等级分布(最近 5 分钟) sum by (family, effort) ( rate(llm_reasoning_effort_usage_total[5m]) )

5.3 成本和路由指标

Router 为成本核算和路由决策公开了额外的指标。

  • llm_model_cost_total{model, currency}

    • 描述:归属于每个模型的总累计成本(根据 token 使用情况和每 1M 定价计算),按货币标记。
    • 标签:model(用于请求的模型名称)、currency(货币代码,例如"USD")
  • llm_routing_reason_codes_total{reason_code, model}

    • 描述:按原因代码和所选模型划分的路由决策计数。
    • 标签:reason_code(发生路由决策的原因,例如auto_routing, model_specified, pii_policy_alternative_selected)、model(最终选择的模型)

两个计数器均在 metrics.go 中注册(ModelCost、RoutingReasonCodes)。PromQL 示例:

# 过去一小时内按模型和货币划分的成本 sum by (model, currency) (increase(llm_model_cost_total[1h])) # 或者,如果你只使用 USD,常见的查询是: sum by (model) (increase(llm_model_cost_total{currency="USD"}[1h])) # 过去 15 分钟内按原因代码划分的路由决策 sum by (reason_code) (increase(llm_routing_reason_codes_total[15m]))

5.4 请求错误指标

Router 按模型和原因跟踪请求级失败,因此你可以监控绝对错误吞吐量和失败请求的比例。

  • llm_request_errors_total{model, reason}
    • 描述:按失败原因分类的请求错误总数
    • 标签:
      • model:失败请求的目标模型名称
      • reason:错误类别(timeout, upstream_4xx, upstream_5xx, pii_policy_denied, jailbreak_block, parse_error, serialization_error, cancellation, classification_failed, unknown)

该计数器的 help 文本在 metrics.go 中明确列出了timeout, upstream_5xx, pii_policy_denied, jailbreak_block, parse_error, serialization_error, cancellation等原因;extproc 层的测试(extproc_test.go)验证了parse_error、upstream_5xx、upstream_4xx等标签值在相应故障路径下确实会递增。

PromQL 查询示例:

# 过去一小时内按原因划分的总错误数 sum by (reason) (increase(llm_request_errors_total[1h])) # 过去 15 分钟内按模型划分的错误吞吐量(错误数/秒)。 # 这对于事件响应很有帮助,因为它显示了有多少失败请求正在影响用户。 sum by (model) (rate(llm_request_errors_total[15m])) # 过去 15 分钟内按模型划分的错误率(失败请求的百分比)。 # 使用 increase() 使分子和分母在相同的回溯窗口内对齐。 100 * sum by (model) (increase(llm_request_errors_total[15m])) / sum by (model) (increase(llm_model_requests_total[15m])) # 过去 24 小时内 PII 策略拦截的数量 sum(increase(llm_request_errors_total{reason="pii_policy_denied"}[24h]))

5.5 TTFT 和 TPOT 指标

TTFT(Time To First Token,首 token 时间)和 TPOT(Time Per Output Token,每输出 token 时间)以 Prometheus histogram 的形式导出,可以使用histogram_quantile在 p95 处可视化:

  • llm_model_ttft_seconds{model}
    • 直方图:公开_bucket、_sum、_count
    • 描述:自 Router 开始处理请求以来的 Time To First Token
    • 按模型划分的 p95 示例(最近 5 分钟):
histogram_quantile(0.95, sum(rate(llm_model_ttft_seconds_bucket[5m])) by (le, model))
  • llm_model_tpot_seconds{model}
    • 直方图:公开_bucket、_sum、_count
    • 描述:每输出 token 的秒数(completion 延迟 / completion token 数)
    • 按模型划分的 p95 示例(最近 5 分钟):
histogram_quantile(0.95, sum(rate(llm_model_tpot_seconds_bucket[5m])) by (le, model))

这两个 TTFT/TPOT p95 面板已包含在仓库自带的 Grafana 仪表板中("TTFT (p95) by Model" 与 "TPOT (p95) by Model (sec/token)")。在当前仓库中,该仪表板以 ConfigMap 形式随部署清单一起提供,见 Kubernetes 部署的仪表板(第 2207 行与第 2296 行附近即对应的histogram_quantile(0.95, ...)查询)以及 OpenShift 部署的仪表板。

流式传输(SSE)注意事项
  • 对于服务器发送事件(SSE)响应,路由测量的是第一个流式正文块(即第一个 token)的 TTFT,而不是响应 Header;
  • 无需手动更改 Envoy 配置:ExtProc 处理程序会自动为 SSE 响应设置带有response_body_mode: STREAMED的ModeOverride,以便第一个块立即到达 ExtProc;
  • 前提条件:Envoy 的ext_proc过滤器必须具有allow_mode_override: true(仓库默认的本地/部署配置已经包含此项,例如 deploy/local/envoy.yaml 第 78 行,以及deploy/kubernetes/下多个 EnvoyFilter/网关清单),在静态处理模式中保持response_body_mode: BUFFERED是可以的——路由会在运行时为 SSE 将其翻转为 STREAMED。

5.6 定价配置

为你的模型提供每 1M token 的 pricing,以便 Router 可以计算请求成本并发出 metrics/log:

model_config: phi4: pricing: currency: USD prompt_per_1m: 0.07 completion_per_1m: 0.35 "mistral-small3.1": pricing: currency: USD prompt_per_1m: 0.1 completion_per_1m: 0.3 gemma3:27b: pricing: currency: USD prompt_per_1m: 0.067 completion_per_1m: 0.267

注意事项:

  • 定价是可选的;如果省略,成本视为 0,且仅发出 token 指标;
  • 成本计算公式为:(prompt_tokens * prompt_per_1m + completion_tokens * completion_per_1m) / 1,000,000(以配置的货币计算)。

从源码看,计价结构定义在 catalog/types.go 的Pricing中,除文档中的currency、prompt_per_1m、completion_per_1m外,还支持cached_input_per_1m(缓存输入 token 单价)和cache_write_per_1m(缓存写入单价)。成本计算实际发生在 extproc 的响应处理阶段(model_pricing.go),它会先用Normalize对 usage 做归一化再计价,因此响应体中的x-vsr-costHeader 与llm_model_cost_total指标使用同一套口径。

6. gRPC ExtProc API

用于与 Envoy 的 ExtProc 协议直接集成:

6.1 服务定义

syntax = "proto3"; package envoy.service.ext_proc.v3; service ExternalProcessor { rpc Process(stream ProcessingRequest) returns (stream ProcessingResponse); } message ProcessingRequest { oneof request { RequestHeaders request_headers = 1; RequestBody request_body = 2; ResponseHeaders response_headers = 3; ResponseBody response_body = 4; } } message ProcessingResponse { oneof response { RequestHeadersResponse request_headers = 1; RequestBodyResponse request_body = 2; ResponseHeadersResponse response_headers = 3; ResponseBodyResponse response_body = 4; } }

Process是双向流:Envoy 按"请求 Header → 请求体 → 响应 Header → 响应体"的顺序推送ProcessingRequest,Router 在每一阶段返回对应的ProcessingResponse(继续/改写/短路)。

6.2 处理方法

请求 Header 处理——提取请求元数据、设置请求上下文、返回 continue 响应:

func (r *Router) handleRequestHeaders(headers *ProcessingRequest_RequestHeaders) *ProcessingResponse { // 提取请求元数据 // 设置请求上下文 // 返回 continue 响应 }

请求正文处理——这是路由决策的核心阶段:

func (r *Router) handleRequestBody(body *ProcessingRequest_RequestBody) *ProcessingResponse { // 解析 OpenAI 请求 // 分类查询意图 // 运行安全检查 // 选择最优模型 // 返回路由 Header }

从源码结构看,当前实现将这四个阶段拆分在pkg/extproc包的一组处理程序中:processor_req_header.go(Header 阶段)、processor_req_body.go 与 processor_req_body_routing.go(请求体解析、路由决策)、processor_res_header.go 与 processor_res_body.go(响应阶段)。pkg/extproc/testdata/parity/下保存了大量"parity 语料"(如auto-essay-anthropic-backend.json、client-selected-model-overwritten.json、upstream-503.json等请求/响应记录),用于回归验证各阶段行为,是理解该协议实际报文形态的极好材料。

7. 错误处理

7.1 错误响应格式

{ "error": { "message": "在请求中检测到 PII", "type": "security_violation", "code": "pii_detected", "details": { "entities_found": ["EMAIL", "PERSON"], "action_taken": "block" } } }

7.2 HTTP 状态码

状态码描述
200成功
400Bad Request(格式错误的输入)
403Forbidden(违反安全规定)
429Too Many Requests(频率限制)
500Internal Server Error(内部服务器错误)
503Service Unavailable(后端掉线)

当请求因守卫规则被拒绝(如 PII 拦截、越狱拦截)时,客户端除了收到错误响应外,还可以从x-vsr-response-path: blocked响应 Header 中直接判断"该响应是被守卫拒绝的",这在自动化重试逻辑中非常有用。

8. 配置 API 与运行时更新

8.1 运行时配置更新(v0.2 契约)

端点:POST /admin/config/update

{ "classification": { "confidence_threshold": 0.8 }, "security": { "enable_pii_detection": true }, "cache": { "ttl_seconds": 7200 } }

该端点允许在不重启 Router 的情况下热更新分类置信度阈值、安全检测开关与缓存 TTL 等运行时参数。

从源码结构看,当前仓库的管理面 API 已演进到统一命名空间/api/v1下,配置生命周期围绕"部署→激活→回滚"展开,包括GET /api/v1/config、POST /api/v1/config/validate、POST /api/v1/config/plan、GET /api/v1/config/versions、POST /api/v1/config/rollback、GET /api/v1/config/hash等(见 api_paths.go),所有写操作还带审计记录(/api/v1/observability/audit)。如果你的部署基于较新主干,建议以这些端点为准;v0.2 文档中的/admin/config/update语义可视为其早期形态。

9. WebSocket API(可选)

用于实时流式响应:

端点:ws://localhost:8801/v1/chat/stream

const ws = new WebSocket('ws://localhost:8801/v1/chat/stream'); ws.send(JSON.stringify({ "model": "gpt-3.5-turbo", "messages": [{"role": "user", "content": "讲个故事"}], "stream": true })); ws.onmessage = function(event) { const chunk = JSON.parse(event.data); console.log(chunk.choices[0].delta.content); };

注意该端点标注为"可选":在标准部署中,流式补全通常通过POST /v1/chat/completions+"stream": true以 SSE 形式提供(配合 5.5 节所述的STREAMED模式覆写),WebSocket 端点用于需要双工连接的场景。

10. 客户端库示例

10.1 Python 客户端

import requests class SemanticRouterClient: def __init__(self, base_url="http://localhost:8801"): self.base_url = base_url def chat_completion(self, messages, model="gpt-3.5-turbo", **kwargs): response = requests.post( f"{self.base_url}/v1/chat/completions", json={ "model": model, "messages": messages, **kwargs } ) return response.json() def get_health(self): response = requests.get(f"{self.base_url}/health") return response.json() # 使用示例 client = SemanticRouterClient() result = client.chat_completion([ {"role": "user", "content": "2 + 2 等于多少?"} ])

10.2 JavaScript 客户端

class SemanticRouterClient { constructor(baseUrl = 'http://localhost:8801') { this.baseUrl = baseUrl; } async chatCompletion(messages, model = 'gpt-3.5-turbo', options = {}) { const response = await fetch(`${this.baseUrl}/v1/chat/completions`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model, messages, ...options }) }); return response.json(); } async getHealth() { const response = await fetch(`${this.baseUrl}/health`); return response.json(); } } // 使用示例 const client = new SemanticRouterClient(); const result = await client.chatCompletion([ { role: 'user', content: '求解 x^2 + 5x + 6 = 0' } ]);

由于 Router 严格保持 OpenAI 兼容的请求/响应形状,任何 OpenAI SDK(将base_url指向http://localhost:8801)也可以直接使用;只需把model字段设为MoM(或别名auto)即可触发自动分类路由。

11. 频率限制(Rate Limiting)

路由使用以下 Header 实施频率限制:

X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 999 X-RateLimit-Reset: 1640995200 X-RateLimit-Retry-After: 60

当触发限制时,响应体遵循统一的错误结构:

{ "error": { "message": "超出频率限制", "type": "rate_limit_error", "code": "too_many_requests", "details": { "limit": 1000, "window": "1h", "retry_after": 60 } } }

客户端应优先读取X-RateLimit-Remaining做主动限流,并在收到 429 时按X-RateLimit-Retry-After(或details.retry_after)退避重试。

12. 最佳实践

12.1 请求优化

在请求中提供充分的上下文(system prompt)和相关工具声明,有助于分类器更准确地判定意图:

# 包含相关的上下文 messages = [ { "role": "system", "content": "你是一位数学导师。" }, { "role": "user", "content": "用简单的术语解释导数" } ] # 使用合适的工具 tools = [ { "type": "function", "function": { "name": "calculator", "description": "用于数学计算" } } ]

12.2 错误处理

try: response = client.chat_completion(messages) if 'error' in response: handle_router_error(response['error']) else: process_response(response) except requests.exceptions.Timeout: handle_timeout_error() except requests.exceptions.ConnectionError: handle_connection_error()

12.3 监控集成

import time start_time = time.time() response = client.chat_completion(messages) duration = time.time() - start_time # 记录路由元数据 routing_info = response.get('routing_metadata', {}) logger.info(f"请求被路由到 {routing_info.get('selected_model')} " f"置信度为 {routing_info.get('confidence')} " f"耗时 {duration:.2f}s")

将routing_metadata落入应用日志,再与 9190 端口导出的llm_routing_reason_codes_total、llm_request_errors_total等指标对照,可以建立"单请求决策"与"集群级趋势"两级可观测性。

13. 进一步阅读

  • Classification API 参考:详细的分类端点说明
  • 快速入门指南:真实世界的集成示例
  • 配置指南:生产环境配置
  • 核心源码入口:extproc 处理包、Header 契约定义、指标注册、Classification API 路由目录
  • 端到端验证用例:e2e 测试目录 中的网关级集成测试可帮助确认各端点在真实 Envoy 栈下的行为

版本提示:本文以仓库中 v0.2 文档翻译版为主体,并对照当前源码补充了演进信息(如管理 API 迁移到/api/v1命名空间、x-vsr-*v0.4 Header 契约等)。不同版本间端点路径可能存在差异,实际接入时请以你所部署版本自带的 OpenAPI 规范端点/openapi.json输出为准。

  • 后端
  • API网关
  • 模型推理服务
  • AI Agent

【免费下载链接】semantic-router

An open, programmable decision layer for models and compute.

项目地址:https://gitcode.com/gh_mirrors/sem/semantic-router
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询