跳到主要内容

ai-proxy

ai-proxy 插件通过将插件配置转换为指定的请求格式,简化对 LLM 和向量嵌入模型的访问。该插件支持集成 OpenAI、DeepSeek、Anthropic、Gemini、Vertex AI 以及其他兼容 OpenAI 的 API。

此外,该插件还支持将 LLM 请求信息记录到访问日志(而非错误日志)中,例如 Token 用量、模型、首字节响应时间等。日志插件也可以采集这些日志条目。

示例

以下示例演示了如何针对不同场景配置 ai-proxy

代理到 OpenAI

以下示例演示了如何在 ai-proxy 插件中配置 API Key、模型和其他参数,并在路由上配置该插件以将用户提示词代理到 OpenAI。

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

export OPENAI_API_KEY=YOUR_OPENAI_API_KEY   # 替换为你的 API Key

创建一个路由并按如下方式配置 ai-proxy 插件:

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

❶ 指定提供商为 openai

❷ 在 Authorization 请求头中附带 OpenAI 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 a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

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

{
...,
"model": "gpt-4-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}

代理到 DeepSeek

以下示例演示了如何配置 ai-proxy 插件将请求代理到 DeepSeek。

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

export DEEPSEEK_API_KEY=YOUR_DEEPSEEK_API_KEY   # 替换为你的 API Key

创建一个路由并按如下方式配置 ai-proxy 插件:

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

❶ 指定提供商为 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

以下示例演示了如何配置 ai-proxy 插件,将请求代理到 Azure OpenAI 等其他 LLM 服务。

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

export AZ_OPENAI_API_KEY=YOUR_AZURE_OPENAI_API_KEY   # 替换为你的 API Key

创建一个路由并按如下方式配置 ai-proxy 插件:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "ai-proxy-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "azure-openai",
"auth": {
"header": {
"api-key": "'"$AZ_OPENAI_API_KEY"'"
}
},
"options":{
"model": "gpt-4"
},
"override": {
"endpoint": "https://api7-azure-openai.openai.azure.com/openai/deployments/gpt-4/chat/completions?api-version=2024-02-15-preview"
}
}
}
}'

❶ 将提供商设置为 azure-openai

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

❸ 指定模型名称。

❹ 指定 Azure OpenAI 端点。

向该路由发送一个 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

以下示例演示了如何配置 ai-proxy 插件,将聊天补全请求代理到 Google 的 Gemini API。本示例仅适用于 API7 企业版 3.9.2 及更高版本,不适用于 Apache APISIX。

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

export GEMINI_API_KEY=YOUR_GEMINI_API_KEY   # 替换为你的 API Key

创建一个路由并按如下方式配置 ai-proxy 插件:

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

❶ 将提供商指定为 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-2.5-flash",
"object": "chat.completion",
"usage": {
"completion_tokens": 8,
"prompt_tokens": 15,
"total_tokens": 41
},
...
}

代理到 Vertex AI 聊天补全

以下示例演示了如何配置 ai-proxy 插件,使用 GCP 服务账号认证将请求代理到 Google Cloud Vertex AI 平台。本示例仅适用于 API7 企业版 3.9.2 及更高版本,不适用于 Apache APISIX。

在继续之前:

  • 启用 Vertex AI 并为 GCP 项目启用结算。
  • 按照服务账号凭证文档在 GCP 中创建服务账号,为该账号分配“Vertex AI User”角色,并获取 JSON 格式的账号凭证。

凭证文件应类似如下:

credentials.json
{
"type": "service_account",
"project_id": "api7-vertex",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "api7-docs@api7-vertex.iam.gserviceaccount.com",
"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/api7-docs%40api7-vertex.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

你可以选择将该 JSON 保存到环境变量中:

export GCP_SA_JSON="$(cat credentials.json)"

创建一个路由并按如下方式配置 ai-proxy 插件:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "ai-proxy-vertex-ai-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "vertex-ai",
"auth": {
"gcp": {
"service_account_json": "'"$GCP_SA_JSON"'"
}
},
"provider_conf": {
"project_id": "api7-vertex",
"region": "us-central1"
},
"options": {
"model": "google/gemini-2.5-flash"
}
}
}
}'

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

❷ 替换为你的 JSON 凭证。请确保该值为经过 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-2.5-flash",
...
}

代理到 Vertex AI 向量嵌入模型

以下示例演示了如何配置 ai-proxy 插件,使用 GCP 服务账号认证将请求代理到 Vertex AI 向量嵌入模型。本示例仅适用于 API7 企业版 3.9.2 及更高版本,不适用于 Apache APISIX。

在继续之前:

  • 启用 Vertex AI 并为 GCP 项目启用结算。
  • 按照服务账号凭证文档在 GCP 中创建服务账号,为该账号分配“Vertex AI User”角色,并获取 JSON 格式的账号凭证。

凭证文件应类似如下:

credentials.json
{
"type": "service_account",
"project_id": "api7-vertex",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "api7-docs@api7-vertex.iam.gserviceaccount.com",
"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/api7-docs%40api7-vertex.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

你可以选择将该 JSON 保存到环境变量中:

export GCP_SA_JSON="$(cat credentials.json)"

创建一个路由并按如下方式配置 ai-proxy 插件:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"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"'"
}
},
"provider_conf": {
"project_id": "api7-vertex",
"region": "us-central1"
},
"options": {
"model": "gemini-embedding-001"
}
}
}
}'

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

❷ 替换为你的 JSON 凭证。请确保该值为经过 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 Key,并可选择将其保存到环境变量中:

export OPENAI_API_KEY=YOUR_OPENAI_API_KEY   # 替换为你的 API Key

创建一个路由并按如下方式配置 ai-proxy 插件:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"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"
},
"override": {
"endpoint": "https://api.openai.com/v1/embeddings"
}
}
}
}'

❶ 将模型服务提供方指定为 openai,使插件将请求代理到 https://api.openai.com/v1/chat/completions

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

❸ 指定嵌入模型的名称。

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

❺ 使用向量嵌入 API 端点覆盖默认端点。

向该路由发送一个包含输入字符串的 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 Claude API。

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

export ANTHROPIC_API_KEY=sk-ant-api03-XXXXXXXXXXXXXXXX   # 替换为你的 API Key

创建一个路由并按如下方式配置 ai-proxy 插件:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"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-4-20250514"
}
}
}
}'

❶ 将模型服务提供方指定为 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": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "1+1 equals 2."
}
],
"model": "claude-sonnet-4-20250514",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 19,
"output_tokens": 11
}
}

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

以下示例演示了 ai-proxy 插件如何接收 Anthropic Messages API 格式的请求,自动将其转换为兼容 OpenAI 的格式,再转发到任意兼容 OpenAI 的后端(例如 OpenAI、DeepSeek 或其他兼容服务)。当客户端应用发送 Anthropic 格式的请求,而你希望使用其他 LLM 后端时,此功能非常有用。

当路由 URI 设置为 /v1/messages(Anthropic Messages API 端点)时,会自动触发协议转换。插件会将 Anthropic 格式的请求转换为兼容 OpenAI 的格式,并将响应转换回 Anthropic 格式。

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

export BACKEND_API_KEY=sk-xxx   # 替换为你的 API Key

创建一个路由并按如下方式配置 ai-proxy 插件:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"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"
}
}
}
}'

❶ 将 URI 设置为 /v1/messages,以触发 Anthropic 协议自动转换。

❷ 指定后端服务提供方。它可以是任意兼容 OpenAI 的服务提供方,例如 openaideepseek 等。

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

向该路由发送 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",
"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",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 12,
"output_tokens": 8
}
}

该插件支持 Anthropic Messages API 的所有功能,包括流式传输(SSE)、系统提示词和工具使用(函数调用)。协议转换会透明处理 Anthropic 与 OpenAI 格式之间的双向映射。

原生 Anthropic Messages API 透传

本示例适用于 API7 企业版 3.9.8 及更高版本,以及 Apache APISIX 3.17.0 及更高版本。

以下示例演示了如何使用 ai-proxy 插件,以原生 Anthropic Messages API 格式将请求直接透传到 Anthropic 后端,而不进行任何协议转换。当客户端和后端都原生使用 Anthropic SDK 时,此模式非常有用。

与会在 Anthropic 和 OpenAI 格式之间进行转换的将 Anthropic 请求转换后发送到兼容 OpenAI 的后端示例不同,此模式会保留所有 Anthropic 特有字段,包括缓存 Token 用量(cache_creation_input_tokenscache_read_input_tokens)。

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

export ANTHROPIC_API_KEY=sk-ant-your-api-key

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

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"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-4-20250514"
}
}
}
}'

使用 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-4-20250514",
"messages": [
{"role": "user", "content": "Hello, Claude!"}
],
"max_tokens": 1024
}'

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

代理 OpenAI Responses API

本示例适用于 API7 企业版 3.9.8 及更高版本,以及 Apache APISIX 3.17.0 及更高版本。

以下示例演示了如何使用 ai-proxy 插件代理 OpenAI Responses API 请求(POST /v1/responses)。Responses API 是 OpenAI 较新的 API 格式,支持内置工具、网页搜索、文件搜索和计算机使用。

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

export OPENAI_API_KEY=sk-your-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 '{
"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"
}
}
}
}'

使用 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."
}'

所有下游插件(RAG、内容审查、提示词装饰器、提示词防护和日志记录)均可正常处理 Responses API 格式。流式和非流式响应均受支持。

代理到 AWS Bedrock

本示例适用于 API7 企业版 3.9.12 及更高版本,以及 Apache APISIX 3.17.0 及更高版本。

以下示例演示了如何使用 ai-proxy 插件,通过 Converse API 将请求代理到 AWS Bedrock。Bedrock 使用 AWS SigV4 签名进行身份认证,因此需要提供 IAM 凭证,而不是 API Key 请求头。

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

export AWS_ACCESS_KEY_ID=<your-aws-access-key-id>
export AWS_SECRET_ACCESS_KEY=<your-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 '{
"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": "anthropic.claude-3-haiku-20240307-v1:0"
}
}
}
}'

插件使用已配置的 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 响应经解析后转发给客户端。

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

以下示例演示了如何根据用户在请求中指定的模型,通过同一 URI 将请求代理到不同模型。你将使用 post_arg.* 变量获取请求体参数的值。

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

# 替换为你的 API Key
export OPENAI_API_KEY=YOUR_OPENAI_API_KEY
export DEEPSEEK_API_KEY=YOUR_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 '{
"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"
}
}
}
}'

❶ 将路由 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 '{
"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"
}
}
}
}'

❶ 将路由 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-0613",
"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:APISIX 向上游服务发送请求并接收完整响应所花费的时间。从 API7 企业版 3.8.8 起可用。
  • request_type:请求类型,其值可以是 traditional_httpai_chatai_stream
  • llm_time_to_first_token:从请求发送到从 LLM 服务收到第一个令牌的持续时间,单位为毫秒。
  • llm_model:转发到上游 LLM 服务的 LLM 模型名称。
  • request_llm_model:请求中指定的 LLM 模型名称。
  • llm_prompt_tokens:提示词中的 Token 数量。
  • llm_completion_tokens:提示词中的聊天补全 Token 数。

从 API7 企业版 3.9.14 起,还可以使用以下变量:

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

这些变量在访问日志格式中演示,但也适用于日志记录插件。

若要在访问日志中记录这些值,请将 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-3.5",
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'

由于 ai-proxy 中的模型是 gpt-4,因此请求将被转发到 GPT-4 模型,你将收到类似以下的响应:

{
...,
"model": "gpt-4-0613",
"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 - - [29/Aug/2025:09:54:16 +0000] 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" "6526bf5c961b6e6bb8cfcb66486f02dc" "ai_chat" "2670" "gpt-4" "gpt-3.5" "23" "8" "31" "false" "false" "0" "" "0" "0" "0"

该访问日志条目显示:APISIX 上游响应时间为 2.670 秒,请求类型为 ai_chat,首 Token 时间为 2670 毫秒,请求转发到的 LLM 模型为 gpt-4,请求中的 LLM 模型为 gpt-3.5,提示词 Token 用量为 23,补全 Token 用量为 8,Token 总用量为 31;该请求为非流式请求,没有工具调用,请求中未提供工具,也没有终端用户标识符、提示词缓存 Token 或推理 Token。

将请求日志发送到日志记录器

以下示例演示了如何记录请求和请求信息(包括 LLM 模型、令牌和负载),并将它们推送到日志记录器。在继续之前,你应该先设置一个日志记录器,例如 Kafka。有关更多信息,请参阅 kafka-logger

创建一条通往 LLM 服务的路由,并按如下方式配置日志记录详情:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"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"
},
"logging": {
"summaries": true,
"payloads": true
}
},
"kafka-logger": {
"brokers": [
{
"host": "127.0.0.1",
"port": 9092
}
],
"kafka_topic": "test2",
"key": "key1",
"batch_max_size": 1
}
}
}
}'

❶ 记录请求的 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-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}

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