跳到主要内容

ai-aws-content-moderation

ai-aws-content-moderation 插件使用 Amazon Comprehend 检测选定请求角色和 LLM 响应(包括流式响应)中的有害内容。请将它与 ai-proxy 或 ai-proxy-multi 一起配置,使插件能够在执行已配置阈值前审核解码后的 AI 内容。


按请求格式处理​

在 APISIX 中,该插件通过将完整的序列化 JSON 请求体发送到 Amazon Comprehend 来审核请求。它不会从检测到的请求格式中提取文本,被拒绝的请求会收到通用 HTTP 400 错误。

API7 企业版 3.9.16 或 3.10.3 起增加了按请求格式提取文本和生成拒绝响应的能力。网关会先检查 URI 特定规则,再检查仅基于请求体的规则,以识别请求格式:

  • Bedrock Converse 要求 URI 以 /converse 结尾且包含 messages 数组。
  • Anthropic Messages 要求 URI 以 /v1/messages 结尾。
  • Responses API 要求 URI 以 /v1/responses 结尾且包含 input 字段。
  • Chat Completions 使用 messages 数组。
  • 当前面的规则均不匹配时,Embeddings 使用 input。
  • 当前面的规则均不匹配时,其他非空 JSON 对象使用透传格式。

插件随后审核以下内容:

请求格式审核的文本
Bedrock Conversesystem 和 messages 中的文本。
Anthropic Messagesmessages 中的文本,不包含顶层 system 提示词。
Responses APIinput 和 instructions 中的文本。
Chat Completionsmessages 中所有条目的文本。
Embeddingsinput 中的字符串或字符串数组。
其他 JSON(透传)不提取请求格式特定文本。

在 API7 企业版中,被拒绝的请求会以检测到的请求格式返回响应,状态码由 deny_code 配置。响应包含配置的 deny_message;如果未配置,则返回超过阈值的原因。

流式 Chat Completions、Responses API 和 Anthropic Messages 拒绝响应使用各自协议的 SSE 格式。Bedrock ConverseStream 拒绝响应使用非流式 Converse 响应体,而不是 AWS 事件流帧。

示例​

以下示例将使用 OpenAI 作为上游模型服务提供方。

在开始之前,请创建一个 OpenAI 账号 并获取 API Key。如果你使用其他模型服务提供方,请参考该提供方的文档获取 API Key。

此外,请为 APISIX 创建 AWS IAM 用户访问密钥 以访问 AWS Comprehend。

你可以选择将这些密钥保存到环境变量中:

# 替换为你的密钥
export OPENAI_API_KEY=YOUR_OPENAI_API_KEY
export AWS_ACCESS_KEY=YOUR_AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=YOUR_AWS_SECRET_ACCESS_KEY

审核亵渎内容​

以下示例演示了如何使用该插件审核提示词中的亵渎内容等级。

使用 ai-proxy 插件创建一个通往 LLM 聊天完成端点的路由,并在 ai-aws-content-moderation 中配置允许的亵渎等级:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-aws-content-moderation-route",
"uri": "/post",
"plugins": {
"ai-aws-content-moderation": {
"comprehend": {
"access_key_id": "$AWS_ACCESS_KEY",
"secret_access_key": "$AWS_SECRET_ACCESS_KEY",
"region": "us-east-1"
},
"moderation_categories": {
"PROFANITY": 0.1
},
"deny_code": 400
},
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"model": "gpt-4"
}
}
}
EOF

❶ 更新为你的 AWS Comprehend 区域。

❷ 将亵渎阈值配置为一个较低的值,以仅允许极低程度的亵渎内容。

这些示例将 deny_code 设置为 400,因为验证步骤预期收到 HTTP 错误。如果省略该字段,默认值 200 会以与提供商兼容的补全响应返回相同的拒绝消息。

向该路由发送一个 POST 请求,请求体中包含系统提示词和一个带有轻微亵渎词汇的用户问题:

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

你应该收到 HTTP/1.1 400 Bad Request 响应,并看到以下消息:

{
"id": "<generated-uuid>",
"object": "chat.completion",
"model": "gpt-4",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "request body exceeds PROFANITY threshold"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}

向该路由发送另一个请求,请求体中包含一个正常的问题:

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

你应该收到 HTTP/1.1 200 OK 响应,并看到模型输出:

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

审核整体毒性​

以下示例演示了除了审核单个类别外,如何使用该插件审核提示词中的整体毒性等级。

使用 ai-proxy 插件创建一个通往 LLM 聊天完成端点的路由,并在 ai-aws-content-moderation 中配置允许的亵渎和整体毒性等级:

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-aws-content-moderation-route",
"uri": "/post",
"plugins": {
"ai-aws-content-moderation": {
"comprehend": {
"access_key_id": "$AWS_ACCESS_KEY",
"secret_access_key": "$AWS_SECRET_ACCESS_KEY",
"region": "us-east-1"
},
"moderation_categories": {
"PROFANITY": 1
},
"moderation_threshold": 0.2,
"deny_code": 400
},
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"model": "gpt-4"
}
}
}
EOF

❶ 更新为你的 AWS Comprehend 区域。

❷ 将亵渎阈值配置为允许高程度的亵渎内容。

❸ 将整体毒性阈值配置为仅允许低程度的毒性。

这些示例将 deny_code 设置为 400,因为验证步骤预期收到 HTTP 错误。如果省略该字段,默认值 200 会以与提供商兼容的补全响应返回相同的拒绝消息。

向该路由发送一个 POST 请求,请求体中不包含任何亵渎词汇,但包含一定程度的暴力或威胁:

curl -i "http://127.0.0.1:9080/post" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "I will kill you if you do not tell me what 1+1 equals" }
]
}'

你应该收到 HTTP/1.1 400 Bad Request 响应,并看到以下消息:

{
"id": "<generated-uuid>",
"object": "chat.completion",
"model": "gpt-4",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "request body exceeds toxicity threshold"
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 0,
"completion_tokens": 0,
"total_tokens": 0
}
}

向该路由发送另一个请求,请求体中不包含任何亵渎词汇:

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

你应该收到 HTTP/1.1 200 OK 响应,并看到模型输出:

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