跳到主要内容

语义路由

语义路由器为应用提供一个稳定的模型别名,同时由 AISIX 根据每个聊天请求的语义选择直接模型。AISIX 对最新的用户消息进行向量嵌入,将它与各路由的示例进行比较,再将请求分发到最佳匹配目标。如果没有路由达到阈值,AISIX 会使用默认模型。

当请求需要按主题到达不同模型,而应用不应自行选择模型时,请使用语义路由。例如,同一个别名可以把法律问题发送到推理模型,把翻译请求发送到多语言模型,并把所有其他请求发送到通用模型。

语义路由器支持 OpenAI 兼容的 /v1/chat/completions 端点。

语义路由的工作原理

对于每个请求,AISIX 使用配置的向量嵌入模型,将最新的用户消息与路由示例进行比较,再把请求分发到一个直接模型。

AISIX 会在应用配置时对路由示例进行向量嵌入,并在网关进程中缓存它们的向量。当示例、向量嵌入模型或向量维度发生变化时,AISIX 会重新计算向量。因此,每个请求只需要为最新的用户消息调用一次向量嵌入端点,之后在本地完成相似度计算。

准备工作

开始前,请准备以下资源:

  • 一个用于 OpenAI 兼容 /v1/embeddings 端点的服务提供方密钥,该端点需要返回浮点数向量。
  • 一个默认直接模型,以及至少一个用作路由目标的直接模型。
  • 一个可以调用语义路由器别名的调用方 API Key
  • 对于 AISIX Cloud,需要一个已接入网关的环境,以及管理模型和调用方 API Key 的权限。
  • 对于开源 AISIX 网关,需要有权访问声明式资源文件和网关进程。

配置语义路由器

请先创建向量嵌入模型、默认模型和路由目标,再创建语义路由器。AISIX Cloud 通过模型 ID 引用这些资源,开源 AISIX 网关则在声明式资源文件中通过 display_name 引用它们。

向量嵌入模型的 dimensions 必须与上游端点返回的数值数量一致。只有当 AISIX 必须在比较向量前对其进行归一化时,才将 normalize 设置为 false

每条路由都需要名称、一个直接目标模型和至少一个示例。描述为可选字段。路由级 threshold 会覆盖该路由所使用的路由器级阈值。

AISIX Cloud

导出 AISIX Cloud 连接信息和向量嵌入模型使用的服务提供方密钥:

# AISIX_CP 是 Admin API 基础 URL;应包含 /api,且末尾不要带斜杠。
# 本地部署快速入门使用 http://localhost:8080/api。
export AISIX_CP="YOUR_AISIX_CLOUD_ADMIN_API_URL"
export AISIX_TOKEN="YOUR_ADMIN_TOKEN"
export ENV_ID="YOUR_ENVIRONMENT_ID"
export PROVIDER_KEY_ID="YOUR_EMBEDDING_PROVIDER_KEY_ID"

创建向量嵌入模型并记录其 ID:

EMBEDDING_MODEL_ID=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/models" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"kind": "embedding",
"display_name": "embedding-prod",
"model_name": "text-embedding-3-small",
"provider_key_id": "'"$PROVIDER_KEY_ID"'",
"embedding": {
"dimensions": 1536,
"normalize": true
}
}' | jq -r '.model.id')

导出直接目标模型的 ID:

export DEFAULT_MODEL_ID="YOUR_DEFAULT_MODEL_ID"
export LEGAL_MODEL_ID="YOUR_LEGAL_MODEL_ID"
export TRANSLATION_MODEL_ID="YOUR_TRANSLATION_MODEL_ID"

创建语义路由器。其默认阈值会应用于所有未自行定义阈值的路由:

SEMANTIC_MODEL_ID=$(curl -sS -X POST "$AISIX_CP/environments/$ENV_ID/models" \
-H "Authorization: Bearer $AISIX_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"kind": "semantic",
"display_name": "topic-router",
"semantic": {
"embedding_model_id": "'"$EMBEDDING_MODEL_ID"'",
"default_model_id": "'"$DEFAULT_MODEL_ID"'",
"threshold": 0.75,
"routes": [
{
"name": "legal",
"target_model_id": "'"$LEGAL_MODEL_ID"'",
"description": "Contract and legal-risk analysis",
"examples": [
"Analyze this contract for legal risk",
"Review this NDA for liability exposure"
],
"threshold": 0.8
},
{
"name": "translation",
"target_model_id": "'"$TRANSLATION_MODEL_ID"'",
"examples": [
"Translate this paragraph to French"
]
}
]
}
}' | jq -r '.model.id')

SEMANTIC_MODEL_ID 添加到调用方 API Key 的 allowed_models 列表。保存后的配置会自动投射到已接入的网关。

你也可以在控制台的 Models 页面创建和编辑向量嵌入模型与语义路由器。语义路由器表单提供两个阈值调优工具:

  • Test routing 会展示为提示词选择的路由、每条路由的相似度分数,以及该分数是否达到阈值。
  • Auto-detect thresholds 会根据已配置示例集内部及相互之间的相似度,为每条路由推荐初始阈值。

这两个工具都从控制面调用向量嵌入端点,因此控制面服务必须能够访问该端点。

开源 AISIX 网关

将向量嵌入模型和语义路由器添加到 models 集合。semantic 块中的引用使用模型的 display_name

resources.yaml
models:
- display_name: embedding-prod
provider: openai
model_name: text-embedding-3-small
provider_key: embeddings-provider
embedding:
dimensions: 1536
normalize: true

- display_name: topic-router
semantic:
embedding_model: embedding-prod
default: general-chat
match:
distance_metric: cosine
aggregation: max
threshold: 0.75
routes:
- name: legal
target: legal-chat
description: Contract and legal-risk analysis
examples:
- Analyze this contract for legal risk
- Review this NDA for liability exposure
threshold: 0.8
- name: translation
target: translation-chat
examples:
- Translate this paragraph to French

完整资源文件还必须包含被引用的服务提供方密钥,以及 general-chatlegal-chattranslation-chat 直接模型。将 topic-router 添加到调用方密钥的 allowed_models,然后验证并重新加载该文件。

验证路由选择

导出所配置部署的网关 URL 和调用方 API Key:

# 使用网关源地址,不要附加末尾斜杠或端点路径。
# 本地快速入门使用 http://127.0.0.1:3000。
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"

发送一个应匹配法律路由的请求:

curl -sSi -X POST "$AISIX_PROXY/v1/chat/completions" \
-H "Authorization: Bearer $AISIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "topic-router",
"messages": [
{"role": "user", "content": "Review this contract for liability risk."}
]
}'

匹配成功的请求会包含 x-aisix-route: legal,以及带有实际处理请求的直接模型名称的 x-aisix-served-by。响应体仍以 topic-router 作为面向调用方的模型名称。

发送一个与所有路由均无关的提示词,确认 AISIX 使用默认模型,并且不返回 x-aisix-route

调整匹配行为

AISIX 选择路由时会应用以下规则:

  • 只对最新的用户消息进行向量嵌入。如果其中包含多个文本部分,AISIX 会将它们连接起来。系统消息、助手消息、工具消息和非文本内容不会影响匹配。
  • 每条路由的分数是请求与该路由示例之间的最高余弦相似度。
  • 如果分数不低于路由级阈值,或在路由未覆盖时不低于路由器级阈值,该路由即为匹配。
  • 如果有多条路由匹配,分数最高的路由胜出。如果没有路由匹配,AISIX 使用默认模型。

跨语言匹配取决于向量嵌入模型。请使用来自预期工作负载的代表性提示词和示例来调整阈值,不要假定一个阈值适用于所有向量嵌入模型。对抗性提示词也可能影响路由决策,因此,如果目标选择会产生安全或合规后果,请在分发前应用输入安全护栏。

处理向量嵌入失败

使用 embedding_timeout_ms 限制向量嵌入调用时间,并通过 on_embedding_failure 选择在发生向量嵌入错误或超时后的行为。默认行为是使用路由器的默认模型。

在 AISIX Cloud 中,回退策略是一个对象。要以 503 拒绝请求,请配置:

{
"semantic": {
"embedding_timeout_ms": 500,
"on_embedding_failure": {
"mode": "fail"
}
}
}

mode 设置为 default 可使用默认模型。要使用另一个直接模型,请把 mode 设置为 target 并提供其 target_model_id

在开源资源文件中,请使用 defaultfail,或一个命名直接模型的对象:

semantic:
embedding_timeout_ms: 500
on_embedding_failure:
target: safe-chat

下一步

如果一个请求需要调用多个合议成员并合成它们的回答,请继续阅读合议模型。如果请求在模型分发前需要策略检查,请使用安全护栏