跳到主要内容

ai-proxy

ai-proxy 插件将 LLM 和嵌入请求转发到 OpenAI、DeepSeek、Anthropic、Gemini、Vertex AI 以及其他兼容的模型服务提供方。统一的插件配置会应用各模型服务提供方所需的身份验证、端点和请求格式。

转发请求前,插件会根据请求 URI 和请求体识别客户端协议。当客户端使用 Anthropic Messages,而所选模型服务提供方支持 OpenAI Chat Completions 而非原生 Anthropic Messages 时,插件会执行协议转换:将客户端请求转换为 OpenAI 格式,并将后端响应转换为 Anthropic 格式。该转换只支持 Anthropic Messages 的一部分功能。有关检测规则、字段映射、版本边界和限制,请参阅协议参考。

该插件还可以在访问日志而非错误日志中记录 LLM 请求信息,包括 Token 用量、模型和首字节响应时间。日志插件可以采集这些条目。

示例​

以下示例展示如何针对常见的模型服务提供方和协议场景配置 ai-proxy。

代理到 OpenAI​

本示例在向 OpenAI 发送聊天请求的路由上配置 ai-proxy。

获取 OpenAI API 密钥,并可选择将其保存到环境变量中:

export OPENAI_API_KEY="<OPENAI_API_KEY>"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options":{
"model": "gpt-4.1-mini"
}
}
}
}
EOF

❶ 指定提供商为 openai。

❷ 在 Authorization 请求头中附带 OpenAI API Key。

❸ 指定模型名称。

ADC 和 Gateway API 标签页包含一个常规后端。当插件自行处理请求时,不会访问该后端。请验证下文中插件特有的结果;仅收到后端响应并不能证明插件已运行。

发送一个 POST 请求到该路由,请求体中包含系统提示词和一个示例用户问题:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

你应该会收到类似以下的响应:

{
...,
"model": "gpt-4.1-mini-2025-04-14",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}

如果 LLM 上游返回 429 或 5xx 响应,客户端会收到上游的状态码、响应体和 Content-Type,从而保留模型服务提供方返回的错误详情。

代理到 DeepSeek​

本示例配置 ai-proxy 向 DeepSeek 发送聊天请求。

获取 DeepSeek API Key,并可选择将其保存到环境变量中:

export DEEPSEEK_API_KEY="<DEEPSEEK_API_KEY>"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "deepseek",
"auth": {
"header": {
"Authorization": "Bearer $DEEPSEEK_API_KEY"
}
},
"options": {
"model": "deepseek-chat"
}
}
}
}
EOF

❶ 指定提供商为 deepseek,插件会将请求代理到 https://api.deepseek.com/chat/completions。

❷ 在 Authorization 请求头中附带 DeepSeek API Key。

❸ 指定模型名称。

向该路由发送一个 POST 请求,请求体中包含输入字符串:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "system",
"content": "You are an AI assistant that helps people find information."
},
{
"role": "user",
"content": "Write me a 50-word introduction for Apache APISIX."
}
]
}'

你应该会收到类似以下的响应:

{
...
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Apache APISIX is a dynamic, real-time, high-performance API gateway and cloud-native platform. It provides rich traffic management features like load balancing, dynamic upstream, canary release, circuit breaking, authentication, observability, and more. Designed for microservices and serverless architectures, APISIX ensures scalability, security, and seamless integration with modern DevOps workflows."
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}

代理到 Azure OpenAI​

本示例通过 Azure OpenAI 部署的 v1 API 发送 Chat Completions 请求。

获取 Azure OpenAI API Key,并可选择将其保存到环境变量中:

export AZ_OPENAI_API_KEY="<AZURE_OPENAI_API_KEY>"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai-compatible",
"auth": {
"header": {
"api-key": "$AZ_OPENAI_API_KEY"
}
},
"options":{
"model": "<AZURE_OPENAI_DEPLOYMENT>"
},
"override": {
"endpoint": "https://<AZURE_OPENAI_RESOURCE>.openai.azure.com/openai/v1/chat/completions"
}
}
}
}
EOF

❶ 将模型服务提供方设置为 openai-compatible,以便部署名称保留在 v1 请求体中。

❷ 在 api-key 请求头中附加 Azure OpenAI API Key。

❸ 指定 Azure OpenAI 部署名称。

❹ 指定 Azure OpenAI v1 Chat Completions 端点。

向该路由发送一个 POST 请求,请求体中包含输入字符串:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "system",
"content": "You are an AI assistant that helps people find information."
},
{
"role": "user",
"content": "Write me a 50-word introduction for Apache APISIX."
}
],
"max_tokens": 800,
"temperature": 0.7,
"frequency_penalty": 0,
"presence_penalty": 0,
"top_p": 0.95,
"stop": null
}'

你应该会收到类似以下的响应:

{
"choices": [
{
...,
"message": {
"content": "Apache APISIX is a modern, cloud-native API gateway built to handle high-performance and low-latency use cases. It offers a wide range of features, including load balancing, rate limiting, authentication, and dynamic routing, making it an ideal choice for microservices and cloud-native architectures.",
"role": "assistant"
}
}
],
...
}

代理到 Gemini​

本示例向 Gemini API 发送聊天请求。API7 企业版 3.9.2 和 APISIX 3.15.0 开始支持 Gemini。

获取 Gemini API Key,并可选择将其保存到环境变量中:

export GEMINI_API_KEY="<GEMINI_API_KEY>"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-gemini-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "gemini",
"auth": {
"header": {
"Authorization": "Bearer $GEMINI_API_KEY"
}
},
"options": {
"model": "gemini-3.5-flash"
}
}
}
}
EOF

❶ 将提供商指定为 gemini。

❷ 在 Authorization 请求头中替换为你的 Gemini API Key。

❸ 指定 Gemini 模型名称。

关于模型端点

上述配置会将请求代理到位于 https://generativelanguage.googleapis.com/v1beta/openai/chat/completions 的聊天补全端点。若要将请求代理到向量嵌入模型,请在 override 字段中显式配置该模型的端点。

发送一个 POST 请求到该路由,请求体中包含系统提示词和一个示例用户问题:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a helpful AI assistant" },
{ "role": "user", "content": "What is the capital of France?" }
]
}'

你应该会收到类似以下的响应:

{
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "The capital of France is **Paris**.",
"role": "assistant"
}
}
],
"model": "gemini-3.5-flash",
"object": "chat.completion",
"usage": {
"completion_tokens": 8,
"prompt_tokens": 15,
"total_tokens": 41
},
...
}

代理到 Vertex AI 聊天补全​

本示例使用 Google Cloud 服务账号向 Vertex AI 发送聊天请求。API7 企业版 3.9.2 和 APISIX 3.15.0 开始支持 Vertex AI。

在继续之前:

凭证文件应类似如下:

credentials.json
{
"type": "service_account",
"project_id": "<GCP_PROJECT_ID>",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "<SERVICE_ACCOUNT_EMAIL>",
"client_id": "....",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/<URL_ENCODED_SERVICE_ACCOUNT_EMAIL>",
"universe_domain": "googleapis.com"
}

分别保存供 ADC 示例使用的原始 JSON,以及供 Admin API 示例使用的 JSON 编码字符串:

export GCP_SA_JSON="$(cat credentials.json)"
export GCP_SA_JSON_STRING="$(jq -Rs . < credentials.json)"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-vertex-ai-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "vertex-ai",
"auth": {
"gcp": {
"service_account_json": $GCP_SA_JSON_STRING
}
},
"provider_conf": {
"project_id": "<GCP_PROJECT_ID>",
"region": "northamerica-northeast1"
},
"options": {
"model": "google/gemini-3.5-flash"
}
}
}
}
EOF

❶ 将模型服务提供方指定为 vertex-ai。

❷ 以 JSON 字符串形式提供服务账号凭据。

❸ 替换为你的 Vertex AI 项目 ID 和区域。

❹ 以 <publisher>/<model> 格式指定通过 Vertex AI 使用的 Gemini 模型名称。

发送一个 POST 请求到该路由,请求体中包含系统提示词和一个示例用户问题:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

你应该会收到类似以下的响应:

{
"choices": [
{
"message": {
"role": "assistant",
"content": "1 + 1 = 2\n"
},
"index": 0,
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"completion_tokens": 8,
"extra_properties": {
"google": {
"traffic_type": "ON_DEMAND"
}
},
"total_tokens": 19,
"prompt_tokens": 11
},
"object": "chat.completion",
"model": "google/gemini-3.5-flash",
...
}

代理到 Vertex AI 向量嵌入模型​

本示例使用 Google Cloud 服务账号向 Vertex AI 发送嵌入请求。API7 企业版 3.9.2 和 APISIX 3.15.0 开始支持 Vertex AI。

在继续之前:

凭证文件应类似如下:

credentials.json
{
"type": "service_account",
"project_id": "<GCP_PROJECT_ID>",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "<SERVICE_ACCOUNT_EMAIL>",
"client_id": "....",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/<URL_ENCODED_SERVICE_ACCOUNT_EMAIL>",
"universe_domain": "googleapis.com"
}

分别保存供 ADC 示例使用的原始 JSON,以及供 Admin API 示例使用的 JSON 编码字符串:

export GCP_SA_JSON="$(cat credentials.json)"
export GCP_SA_JSON_STRING="$(jq -Rs . < credentials.json)"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-vertex-ai-embeddings-route",
"uri": "/embeddings",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "vertex-ai",
"auth": {
"gcp": {
"service_account_json": $GCP_SA_JSON_STRING
}
},
"provider_conf": {
"project_id": "<GCP_PROJECT_ID>",
"region": "us-central1"
},
"options": {
"model": "gemini-embedding-001"
}
}
}
}
EOF

❶ 将模型服务提供方指定为 vertex-ai。

❷ 以 JSON 字符串形式提供服务账号凭据。

❸ 替换为你的 Vertex AI 项目 ID 和区域。

❹ 指定 Vertex AI Gemini 向量嵌入模型的名称。

向该路由发送一个包含输入字符串的 POST 请求:

curl "http://127.0.0.1:9080/embeddings" -X POST \
-H "Content-Type: application/json" \
-d '{
"input": "hello world"
}'

你应该会收到类似以下的响应:

{
"model": "gemini-embedding-001",
"usage": {
"total_tokens": 2,
"prompt_tokens": 2
},
"object": "list",
"data": [
{
"index": 0,
"object": "embedding",
"embedding": [
-0.0241838414222,
0.0098769934847951,
0.0074856607243419,
-0.067302219569683,
...
]
}
]
}

代理到 OpenAI 向量嵌入模型​

本示例配置 ai-proxy 向 OpenAI 发送嵌入请求。

获取 OpenAI API 密钥,并可选择将其保存到环境变量中:

export OPENAI_API_KEY="<OPENAI_API_KEY>"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-route",
"uri": "/embeddings",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options": {
"model": "text-embedding-3-small",
"encoding_format": "float"
}
}
}
}
EOF

❶ 选择 openai 提供方。请求体包含 input 时,插件会检测到 Embeddings 请求,并将其发送到 https://api.openai.com/v1/embeddings。

❷ 在 Authorization 请求头中附带 OpenAI API Key。

❸ 指定嵌入模型的名称。

❹ 添加 encoding_format 参数,将返回的向量嵌入配置为浮点数列表。

向该路由发送一个包含输入字符串的 POST 请求:

curl "http://127.0.0.1:9080/embeddings" -X POST \
-H "Content-Type: application/json" \
-d '{
"input": "hello world"
}'

你应该会收到类似以下的响应:

{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [
-0.0067144386,
-0.039197803,
0.034177095,
0.028763203,
-0.024785956,
-0.04201061,
...
],
}
],
"model": "text-embedding-3-small",
"usage": {
"prompt_tokens": 2,
"total_tokens": 2
}
}

代理到 Anthropic​

本示例配置 ai-proxy,通过 Anthropic API 将兼容 OpenAI Chat Completions 格式的请求发送到 Claude。

获取 Anthropic API Key,并可选择将其保存到环境变量中:

export ANTHROPIC_API_KEY="<ANTHROPIC_API_KEY>"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-anthropic-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "anthropic",
"auth": {
"header": {
"x-api-key": "$ANTHROPIC_API_KEY"
}
},
"options": {
"model": "claude-sonnet-5-5"
}
}
}
}
EOF

❶ 将模型服务提供方指定为 anthropic。

❷ 在 x-api-key 请求头中附加 Anthropic API Key。

❸ 指定 Anthropic 模型的名称。

发送一个 POST 请求到该路由,请求体中包含系统提示词和一个示例用户问题:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

你应该会收到类似以下的响应:

{
"id": "chatcmpl-...",
"object": "chat.completion",
"model": "claude-sonnet-5-5",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 19,
"completion_tokens": 11,
"total_tokens": 30
}
}

将 Anthropic 请求转换后发送到兼容 OpenAI 的后端​

本示例配置 ai-proxy 插件接收 Anthropic Messages 请求,将其转换为 OpenAI Chat Completions,再转发到兼容 OpenAI 的后端。当客户端应用发送 Anthropic 格式的请求,而后端使用兼容 OpenAI 的 API 时,请使用此配置。

将路由 URI 设置为 /v1/messages 会触发协议转换。插件会把 Anthropic 格式的请求转换为 OpenAI Chat Completions,并将响应转换回 Anthropic 格式。

获取所选兼容 OpenAI 后端服务的 API Key,并将其保存到环境变量中。本示例使用 OpenAI:

export BACKEND_API_KEY="<BACKEND_API_KEY>"

创建配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-anthropic-convert-route",
"uri": "/v1/messages",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $BACKEND_API_KEY"
}
},
"options": {
"model": "gpt-4.1-mini"
}
}
}
}
EOF

❶ 使用以 /v1/messages 结尾的 URI,将请求识别为 Anthropic Messages。

❷ 配置支持 OpenAI Chat Completions 的模型服务提供方。插件会在转发前转换 Anthropic 请求。

❸ 指定后端模型服务提供方的模型名称。

向该路由发送 Anthropic Messages API 格式的 POST 请求:

curl "http://127.0.0.1:9080/v1/messages" -X POST \
-H "Content-Type: application/json" \
-H "x-api-key: ${BACKEND_API_KEY}" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "gpt-4.1-mini",
"max_tokens": 1024,
"messages": [
{ "role": "user", "content": "What is 1+1?" }
]
}'

虽然请求以 Anthropic 格式发送,但它会自动转换为 OpenAI 格式并转发到后端。响应会转换回 Anthropic 格式:

{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "1+1 equals 2."
}
],
"model": "gpt-4.1-mini",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 12,
"output_tokens": 8
}
}

该转换覆盖常见 Anthropic Messages 工作流,包括文本消息、系统提示词、流式传输(SSE)和自定义函数工具,并将响应转换回 Anthropic 格式。

这种转换只支持 Anthropic Messages API 的一部分,并非等效实现。部分字段会近似转换,插件还可能在不返回错误的情况下丢弃不支持的字段。字段级映射、版本边界和已知限制请参阅协议参考。

如果客户端和后端都原生支持 Anthropic Messages API,请改用原生 Anthropic Messages API 透传。该模式会跳过转换并保留 Anthropic 专用字段。

原生 Anthropic Messages API 透传​

API7 企业版 3.9.8 和 APISIX 3.17.0 开始支持原生透传 Anthropic Messages。

本示例将 Anthropic Messages 请求直接传递到 Anthropic 后端,不进行协议转换。当客户端和后端都使用原生 Anthropic 格式时,请使用这种方式。

转换示例会将 Anthropic 客户端请求转换为 OpenAI 格式,并将后端响应转换为 Anthropic 格式。原生透传不执行任何一种协议转换,因此会保留所有 Anthropic 特有字段,包括缓存 Token 用量(cache_creation_input_tokens、cache_read_input_tokens)。

获取 Anthropic API Key,并将其保存到环境变量中:

export ANTHROPIC_API_KEY="<ANTHROPIC_API_KEY>"

创建一个配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-anthropic-native",
"uri": "/v1/messages",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "anthropic",
"auth": {
"header": {
"x-api-key": "$ANTHROPIC_API_KEY"
}
},
"options": {
"model": "claude-sonnet-5-5"
}
}
}
}
EOF

使用 Anthropic Messages API 格式发送请求:

curl -i "http://127.0.0.1:9080/v1/messages" -X POST \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-sonnet-5-5",
"messages": [
{"role": "user", "content": "Hello, Claude!"}
],
"max_tokens": 1024
}'

请求会直接转发到 Anthropic API,不进行格式转换。响应以原生 Anthropic 格式返回,并保留所有服务提供方特有字段。

代理 OpenAI Responses API​

API7 企业版 3.9.8 和 APISIX 3.17.0 开始支持 OpenAI Responses API。

本示例配置 ai-proxy 处理 OpenAI Responses API 请求(POST /v1/responses)。该 API 支持网页搜索、文件搜索和计算机使用等内置工具。

获取 OpenAI API Key,并将其保存到环境变量中:

export OPENAI_API_KEY="<OPENAI_API_KEY>"

Responses 和 Embeddings 请求都包含 input。请保留 /v1/responses URI 后缀,使插件将该请求识别为 Responses,而不是 Embeddings。请参阅请求协议检测。

创建一个配置了 ai-proxy 插件的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-responses-api",
"uri": "/v1/responses",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options": {
"model": "gpt-4.1"
}
}
}
}
EOF

使用 OpenAI Responses API 格式发送请求:

curl -i "http://127.0.0.1:9080/v1/responses" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4.1",
"input": "Explain API gateways in one sentence."
}'

发送流式请求:

curl "http://127.0.0.1:9080/v1/responses" -X POST \
--no-buffer \
-H "Content-Type: application/json" \
-d '{
"stream": true,
"input": "Count from one to five."
}'

❶ 禁用 cURL 输出缓冲,使其在每个服务器发送事件到达时立即显示。

❷ 请求 OpenAI 返回流式响应。

该流包含 response.output_text.delta 等类型化事件,并以 response.completed 事件结束。

有关空流和流中断行为,请参阅失败响应。

可以在同一路由上使用明确支持 Responses 请求结构的插件,包括 ai-prompt-decorator、ai-prompt-guard、ai-rag 和 ai-aliyun-content-moderation。

各插件对 instructions 和 input 的处理方式不同。将插件添加到 Responses 路由前,请先查看对应插件页面;仅为 Chat Completions 设计的插件不会自动支持 Responses 格式。

代理到 AWS Bedrock​

bedrock 模型服务提供方会对请求进行签名,并将其转发到 Amazon Bedrock 的 Converse API。该模型服务提供方使用 AWS Signature Version 4,因此插件需要 IAM 凭据,而不是 API 密钥请求头。API7 企业版 3.9.12 和 APISIX 3.17.0 开始支持 Bedrock Converse 和 ConverseStream。

获取 AWS IAM 凭证,并将其保存到环境变量中:

export AWS_ACCESS_KEY_ID="<AWS_ACCESS_KEY_ID>"
export AWS_SECRET_ACCESS_KEY="<AWS_SECRET_ACCESS_KEY>"

创建一个路由,并为 Bedrock 配置 ai-proxy 插件:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-bedrock",
"uri": "/bedrock/converse",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "bedrock",
"auth": {
"aws": {
"access_key_id": "$AWS_ACCESS_KEY_ID",
"secret_access_key": "$AWS_SECRET_ACCESS_KEY"
}
},
"provider_conf": {
"region": "us-east-1"
},
"options": {
"model": "global.anthropic.claude-haiku-5-5"
}
}
}
}
EOF

插件使用已配置的 AWS 凭证对请求进行 SigV4 签名。

向该路由发送 Bedrock Converse 格式的 POST 请求。请求 URI 必须以 /converse 结尾:

curl "http://127.0.0.1:9080/bedrock/converse" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": [
{ "text": "Explain API gateways in one sentence." }
]
}
],
"inferenceConfig": {
"maxTokens": 256
}
}'

插件将请求转发到已配置的 Bedrock 模型,并自动应用 SigV4 签名。

若要使用流式传输,请在请求体中添加 "stream": true:

curl "http://127.0.0.1:9080/bedrock/converse" -X POST \
-H "Content-Type: application/json" \
-d '{
"stream": true,
"messages": [
{
"role": "user",
"content": [
{ "text": "Hello" }
]
}
]
}'

流式请求会被路由到 /converse-stream 端点,二进制 AWS EventStream 响应经解析后转发给客户端。

根据请求体参数代理到指定模型​

本示例根据请求体中的 model 字段,将同一 URI 上的请求路由到 OpenAI 或 DeepSeek。路由使用 post_arg.* 变量读取该字段。

该示例将使用 OpenAI 和 DeepSeek 作为示例 LLM 服务。获取 OpenAI 和 DeepSeek API Key 并将其保存到环境变量中:

# 替换为你的 API 密钥
export OPENAI_API_KEY="<OPENAI_API_KEY>"
export DEEPSEEK_API_KEY="<DEEPSEEK_API_KEY>"

创建一个使用 ai-proxy 插件通往 OpenAI API 的路由:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-openai-route",
"uri": "/anything",
"methods": ["POST"],
"vars": [[ "post_arg.model", "==", "openai" ]],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options": {
"model": "gpt-4.1-mini"
}
}
}
}
EOF

❶ 将路由 URI 设置为 /anything。

❷ 将路由匹配到 model 请求体参数设置为 openai 的请求。

创建另一个通往 DeepSeek API 的路由 /anything 并配置 ai-proxy 插件:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-deepseek-route",
"uri": "/anything",
"methods": ["POST"],
"vars": [[ "post_arg.model", "==", "deepseek" ]],
"plugins": {
"ai-proxy": {
"provider": "deepseek",
"auth": {
"header": {
"Authorization": "Bearer $DEEPSEEK_API_KEY"
}
},
"options": {
"model": "deepseek-chat"
}
}
}
}
EOF

❶ 将路由 URI 设置为 /anything,与上一条路由相同。

❷ 匹配请求体参数 model 设置为 deepseek 的请求。

向该路由发送一个 POST 请求,将 model 设置为 openai:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": "openai",
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

你应该会收到类似以下的响应:

{
...,
"model": "gpt-4.1-mini-2025-04-14",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}

向该路由发送一个 POST 请求,将 model 设置为 deepseek:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek",
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

你应该会收到类似以下的响应:

{
...,
"model": "deepseek-chat",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The sum of 1 and 1 is 2. This is a basic arithmetic operation where you combine two units to get a total of two units."
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}

你还可以配置 post_arg.* 来获取嵌套的请求体参数。例如,如果请求格式为:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": {
"name": "openai"
},
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

你可以将路由上的 vars 配置为 [[ "post_arg.model.name", "==", "openai" ]]。

有关表达式的更多信息,请参阅 APISIX 表达式。

在访问日志中包含 LLM 信息​

本示例将 LLM 请求信息添加到网关访问日志,以便进行分析和审计。除 NGINX 变量外,还可以使用以下变量:

  • apisix_upstream_response_time:网关向上游服务发送请求并接收完整响应所用的时间,单位为毫秒。LLM 上游返回错误响应时,也会以毫秒为单位记录。自 API7 企业版 3.8.8 起可用。
  • request_type:请求类型,取值可以是 traditional_http、ai_chat 或 ai_stream。
  • llm_time_to_first_token:从发送请求到收到 LLM 服务第一个 Token 的时间,单位为毫秒。上游返回错误响应时,该值表示收到错误响应前的时间;如果网关无法连接上游,则该值保持为 0。
  • llm_model:转发到上游 LLM 服务的 LLM 模型名称。
  • request_llm_model:请求中指定的 LLM 模型名称。
  • llm_prompt_tokens:提示词中的 Token 数量。
  • llm_completion_tokens:响应中的补全 Token 数量。
  • llm_content_risk_level:AI 内容审核插件报告的内容风险等级。该变量在 APISIX 3.14.0 中引入。

对于通过 Lua socket transport 发送的请求,网关还会填充标准上游变量 upstream_addr、upstream_status、apisix_upstream_response_time、upstream_scheme、upstream_host、upstream_uri 和 upstream_response_length。这适用于 API7 企业版 3.10.0 及更高版本和 APISIX 3.17.0 及更高版本中的流式与非流式 AI 响应。

这些变量适用于 API7 企业版 3.9.11 及更高版本和 APISIX 3.17.0 及更高版本中的流式与非流式 AI 响应。对于通过 FFI 客户端发送的 APISIX 请求,这些变量也会被填充。

以下其他变量在 API7 企业版 3.9.14 和 APISIX 3.18.0 中引入:

  • llm_total_tokens:使用的 Token 总数,包括提示词和补全 Token。
  • llm_stream:请求是否为流式请求,值为 true 或 false。
  • llm_has_tool_calls:LLM 响应是否包含工具调用,值为 true 或 false。
  • llm_tool_count:请求中提供的工具数量。
  • llm_end_user_id:从请求体提取的终端用户标识符,例如 user、safety_identifier 或 metadata.user_id。
  • llm_cache_read_input_tokens:从服务提供方提示词缓存中读取的提示词 Token 数量。
  • llm_cache_creation_input_tokens:写入服务提供方提示词缓存的提示词 Token 数量。
  • llm_reasoning_tokens:推理模型使用的推理 Token 数量。
提示

访问日志示例使用这些变量,日志插件也可以使用它们。在 API7 企业版 3.9.18 和 3.10.5 以及 APISIX 3.18.0 中,启用 logging.summaries 会将这些变量添加到 llm_summary 对象,并移除 llm_ 前缀。请求中未产生的值会被省略。

若要在访问日志中记录这些值,请将 LLM 变量添加到网关访问日志格式中:

在网关配置文件中添加或更新以下配置:

config.yaml
nginx_config:
http:
access_log_format: "$remote_addr - $remote_user [$time_local] $http_host \"$request_line\" $status $body_bytes_sent $request_time \"$http_referer\" \"$http_user_agent\" $upstream_addr $upstream_status $apisix_upstream_response_time \"$upstream_scheme://$upstream_host$upstream_uri\" \"$apisix_request_id\" \"$request_type\" \"$llm_time_to_first_token\" \"$llm_model\" \"$request_llm_model\" \"$llm_prompt_tokens\" \"$llm_completion_tokens\" \"$llm_total_tokens\" \"$llm_stream\" \"$llm_has_tool_calls\" \"$llm_tool_count\" \"$llm_end_user_id\" \"$llm_cache_read_input_tokens\" \"$llm_cache_creation_input_tokens\" \"$llm_reasoning_tokens\""

重新加载网关,使配置更改生效。

按照代理到 OpenAI创建路由,然后发送请求:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

插件会将请求中的模型替换为配置的 gpt-4.1-mini 模型。你将收到类似以下内容的响应:

{
...,
"model": "gpt-4.1-mini-2025-04-14",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null,
"annotations": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 23,
"completion_tokens": 8,
"total_tokens": 31,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
...
},
"service_tier": "default",
"system_fingerprint": null
}

在网关的访问日志中,你应该会看到类似于以下的日志条目:

192.168.215.1 - - [<TIMESTAMP>] 127.0.0.1:9080 "POST /anything HTTP/1.1" 200 808 2.670 "-" "curl/8.6.0" - - 2670 "http://127.0.0.1:9080" "<REQUEST_ID>" "ai_chat" "2670" "gpt-4.1-mini" "gpt-4o-mini" "23" "8" "31" "false" "false" "0" "" "0" "0" "0"

访问日志条目显示,上游响应时间和首个 Token 的响应时间均为 2670 毫秒。请求类型为 ai_chat,请求的模型是 gpt-4o-mini,并被转发到 gpt-4.1-mini。请求使用了 23 个提示词 Token、8 个补全 Token,共计 31 个 Token。

其余值表示这是一个非流式请求,且不包含工具调用、提供的工具、最终用户标识符、提示缓存 Token 或推理 Token。

将 AI 请求日志发送到 Kafka​

以下示例将 AI 请求和响应详情(包括模型、Token 用量和负载)发送到 Kafka。请先按照 kafka-logger 指南完成 broker 和 apisix-logs 主题配置。

创建一条通往 LLM 服务的路由并启用 Kafka 日志记录:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d @- <<EOF
{
"id": "ai-proxy-openai-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options": {
"model": "gpt-4.1-mini"
},
"logging": {
"summaries": true,
"payloads": true
}
},
"kafka-logger": {
"brokers": [
{
"host": "kafka-server",
"port": 9092
}
],
"kafka_topic": "apisix-logs",
"key": "key1",
"batch_max_size": 1
}
}
}
EOF

❶ 记录请求的 LLM 模型、持续时间、请求和响应 Token 数。

❷ 记录请求和响应负载。

❸ 更新为你的 Kafka 地址。

❹ 更新为你的 Kafka 主题。

❺ 更新为你的 Kafka 密钥。

❻ 设置为 1 以立即发送日志条目。

向该路由发送一个 POST 请求:

curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

你应该会收到类似以下的响应:

{
...,
"model": "gpt-4.1-mini-2025-04-14",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}

在 Kafka 主题中,你还应该看到与该请求对应的日志条目,其中包含 LLM 摘要以及请求和响应负载:

{
"llm_summary": {
"model": "gpt-4.1-mini",
"prompt_tokens": 23,
"completion_tokens": 8,
"total_tokens": 31
},
"llm_request": {
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
],
"stream": false
},
"llm_response_text": {
"content": "1+1 equals 2."
}
}