跳到主要内容

ai-aliyun-content-moderation

ai-aliyun-content-moderation 插件支持集成 阿里云内容安全增强版,在代理 LLM 请求时检查请求体的风险等级(如涉黄、涉政、辱骂、暴力等),如果评估结果超过配置的阈值,则拒绝该请求。

请确保已在插件中正确配置 access_key_secret。如果配置错误,所有请求都会绕过插件并直接转发到 LLM 上游,同时你会在网关错误日志中看到插件输出的 Specified signature is not matched with our calculation

ai-aliyun-content-moderation 插件应与 ai-proxyai-proxy-multi 插件配合使用,用于代理 LLM 请求。

演示

以下演示展示了如何在 API7 企业版控制台中完成审查请求内容毒性示例:你可以审查请求内容是否含有毒性,并自定义拒绝状态码和消息。

按请求格式处理

该插件使用各协议的原生内容结构审核 Chat Completions、Responses API、Embeddings、Anthropic Messages 和 Bedrock Converse 请求。

网关会先检查 URI 特定规则,再检查仅基于请求体的规则,以识别请求格式:

  • Bedrock Converse 要求 URI 以 /converse 结尾且包含 messages 数组。
  • Anthropic Messages 要求 URI 以 /v1/messages 结尾。
  • Responses API 要求 URI 以 /v1/responses 结尾且包含 input 字段。
  • Chat Completions 使用 messages 数组。
  • 当前面的规则均不匹配时,Embeddings 使用 input
  • 当前面的规则均不匹配时,其他非空 JSON 对象使用透传格式。
请求格式可审核的内容
Bedrock Conversesystemmessages 中的文本。
Anthropic Messagesmessages 中的文本。
Responses APIinstructionsinput 中的文本。
Chat Completionsmessages 中的文本。
Embeddingsinput 中的字符串或字符串数组。
其他 JSON(透传)不提取请求格式特定文本。

APISIX 会审核表中列出的所有已提取内容。API7 企业版 3.9.16 或 3.10.3 起支持按角色选择内容,默认审核最近一轮用户消息。使用 request_check_roles 选择用户、工具或系统内容,使用 request_check_mode 选择最近一轮或所有匹配轮次。

按角色选择内容时,选择系统角色即可审核 Anthropic 顶层 system 提示词。当请求格式使用独立的工具角色或条目表示工具输出时,插件可以审核工具结果。Anthropic Messages 和 Bedrock Converse 将工具结果嵌套在用户消息中,因此仅选择工具角色时不会提取这些结果。

如果 Responses 内容被拒绝,插件会以 Responses API 格式返回配置的消息。流式请求会收到以 response.completed 结尾的类型化服务器发送事件。

Embeddings 没有对话角色或轮次。启用按角色选择后,其 input 由用户角色选中。被拒绝的请求会收到 OpenAI 风格的错误响应。

示例

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

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

此外,请创建一个 阿里云账号,开通内容安全增强版服务,并获取 endpoint、region ID、access key ID 和 access key secret。

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

# 替换为你的数据
export OPENAI_API_KEY=YOUR_OPENAI_API_KEY
export ALIYUN_ENDPOINT=https://green-cip.cn-shanghai.aliyuncs.com
export ALIYUN_REGION_ID=cn-shanghai
export ALIYUN_ACCESS_KEY_ID=YOUR_ALIYUN_ACCESS_KEY_ID
export ALIYUN_ACCESS_KEY_SECRET=YOUR_ALIYUN_ACCESS_KEY_SECRET

审核请求内容毒性

以下示例演示了如何使用该插件审查请求内容的毒性,并自定义拒绝状态码和消息。

使用 ai-proxy 插件创建一个通往 LLM 聊天完成端点的路由,并在 ai-aliyun-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-aliyun-content-moderation-route",
"uri": "/anything",
"plugins": {
"ai-aliyun-content-moderation": {
"endpoint": "$ALIYUN_ENDPOINT",
"region_id": "$ALIYUN_REGION_ID",
"access_key_id": "$ALIYUN_ACCESS_KEY_ID",
"access_key_secret": "$ALIYUN_ACCESS_KEY_SECRET",
"deny_code": 400,
"deny_message": "Request contains forbidden content, such as hate speech or violence."
},
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
}
}
}
}
EOF

❶ 配置拒绝 HTTP 状态码。

❷ 配置拒绝消息。

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

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

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

{
"object": "chat.completion",
"usage": {
"completion_tokens": 124,
"prompt_tokens": 31,
"total_tokens": 155
},
"choices": [
{
"message": {
"role": "assistant",
"content": "Request contains forbidden content, such as hate speech or violence."
},
"finish_reason": "stop",
"index": 0
}
],
"model": "gpt-4",
"id": "c9466bbf-e010-469d-949a-a10f25525964"
}

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

curl -i "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?" }
]
}'

你应该收到 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-aliyun-content-moderation 中的 risk_level_bar 配置为 high

curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-aliyun-content-moderation-route",
"uri": "/anything",
"plugins": {
"ai-aliyun-content-moderation": {
"endpoint": "$ALIYUN_ENDPOINT",
"region_id": "$ALIYUN_REGION_ID",
"access_key_id": "$ALIYUN_ACCESS_KEY_ID",
"access_key_secret": "$ALIYUN_ACCESS_KEY_SECRET",
"deny_code": 400,
"deny_message": "Request contains forbidden content, such as hate speech or violence.",
"risk_level_bar": "high"
},
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"model": "gpt-4"
}
}
}
EOF

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

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

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

{
"object": "chat.completion",
"usage": {
"completion_tokens": 124,
"prompt_tokens": 31,
"total_tokens": 155
},
"choices": [
{
"message": {
"role": "assistant",
"content": "Request contains forbidden content, such as hate speech or violence."
},
"finish_reason": "stop",
"index": 0
}
],
"model": "gpt-4",
"id": "c9466bbf-e010-469d-949a-a10f25525964"
}

将插件中的 risk_level_bar 更新为 max

curl "http://127.0.0.1:9180/apisix/admin/routes/ai-aliyun-content-moderation-route" -X PATCH \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"plugins": {
"ai-aliyun-content-moderation": {
"risk_level_bar": "max"
}
}
}'

向该路由发送相同的请求:

curl -i "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": "Stupid, 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"
}
],
...
}

这是因为单词 "stupid" 的风险等级为 high,低于已配置的 max 阈值。若要在网关错误日志中查看阿里云内容审查结果,请暂时将网关日志级别设置为 debug

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

config.yaml
nginx_config:
error_log_level: debug

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

例如,对于上面的请求,你应该看到类似以下的调试日志条目:

{
"RequestId": "29F7AD19-074B-54AC-B240-B297AD96883F",
"Message": "OK",
"Data": {
...,
"RiskLevel": "high",
"Result": [
{
"RiskWords": "are&you&stupid",
...
}
]
},
"Code": 200
}