Skip to content

Commit 25e2e73

Browse files
refactor: ai-content-moderation to ai-aws-content-moderation (#12010)
1 parent 47008af commit 25e2e73

11 files changed

+110
-194
lines changed

Makefile

-3
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,6 @@ install: runtime
382382
$(ENV_INSTALL) -d $(ENV_INST_LUADIR)/apisix/plugins/ai-rag/vector-search
383383
$(ENV_INSTALL) apisix/plugins/ai-rag/vector-search/*.lua $(ENV_INST_LUADIR)/apisix/plugins/ai-rag/vector-search
384384

385-
# ai-content-moderation plugin
386-
$(ENV_INSTALL) -d $(ENV_INST_LUADIR)/apisix/plugins/ai
387-
$(ENV_INSTALL) apisix/plugins/ai/*.lua $(ENV_INST_LUADIR)/apisix/plugins/ai
388385

389386
$(ENV_INSTALL) bin/apisix $(ENV_INST_BINDIR)/apisix
390387

apisix/cli/config.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ local _M = {
217217
"ai-prompt-template",
218218
"ai-prompt-decorator",
219219
"ai-rag",
220-
"ai-content-moderation",
220+
"ai-aws-content-moderation",
221221
"proxy-mirror",
222222
"proxy-rewrite",
223223
"workflow",

apisix/plugins/ai-content-moderation.lua renamed to apisix/plugins/ai-aws-content-moderation.lua

+28-53
Original file line numberDiff line numberDiff line change
@@ -19,48 +19,34 @@ local aws_instance = require("resty.aws")()
1919
local http = require("resty.http")
2020
local fetch_secrets = require("apisix.secret").fetch_secrets
2121

22-
local next = next
2322
local pairs = pairs
2423
local unpack = unpack
2524
local type = type
2625
local ipairs = ipairs
27-
local require = require
2826
local HTTP_INTERNAL_SERVER_ERROR = ngx.HTTP_INTERNAL_SERVER_ERROR
2927
local HTTP_BAD_REQUEST = ngx.HTTP_BAD_REQUEST
3028

31-
32-
local aws_comprehend_schema = {
33-
type = "object",
34-
properties = {
35-
access_key_id = { type = "string" },
36-
secret_access_key = { type = "string" },
37-
region = { type = "string" },
38-
endpoint = {
39-
type = "string",
40-
pattern = [[^https?://]]
41-
},
42-
ssl_verify = {
43-
type = "boolean",
44-
default = true
45-
}
46-
},
47-
required = { "access_key_id", "secret_access_key", "region", }
48-
}
49-
5029
local moderation_categories_pattern = "^(PROFANITY|HATE_SPEECH|INSULT|"..
5130
"HARASSMENT_OR_ABUSE|SEXUAL|VIOLENCE_OR_THREAT)$"
5231
local schema = {
5332
type = "object",
5433
properties = {
55-
provider = {
34+
comprehend = {
5635
type = "object",
5736
properties = {
58-
aws_comprehend = aws_comprehend_schema
37+
access_key_id = { type = "string" },
38+
secret_access_key = { type = "string" },
39+
region = { type = "string" },
40+
endpoint = {
41+
type = "string",
42+
pattern = [[^https?://]]
43+
},
44+
ssl_verify = {
45+
type = "boolean",
46+
default = true
47+
}
5948
},
60-
maxProperties = 1,
61-
-- ensure only one provider can be configured while implementing support for
62-
-- other providers
63-
required = { "aws_comprehend" }
49+
required = { "access_key_id", "secret_access_key", "region", }
6450
},
6551
moderation_categories = {
6652
type = "object",
@@ -78,20 +64,16 @@ local schema = {
7864
minimum = 0,
7965
maximum = 1,
8066
default = 0.5
81-
},
82-
llm_provider = {
83-
type = "string",
84-
enum = { "openai" },
8567
}
8668
},
87-
required = { "provider", "llm_provider" },
69+
required = { "comprehend" },
8870
}
8971

9072

9173
local _M = {
9274
version = 0.1,
9375
priority = 1040, -- TODO: might change
94-
name = "ai-content-moderation",
76+
name = "ai-aws-content-moderation",
9577
schema = schema,
9678
}
9779

@@ -107,51 +89,44 @@ function _M.rewrite(conf, ctx)
10789
return HTTP_INTERNAL_SERVER_ERROR, "failed to retrieve secrets from conf"
10890
end
10991

110-
local body, err = core.request.get_json_request_body_table()
92+
local body, err = core.request.get_body()
11193
if not body then
11294
return HTTP_BAD_REQUEST, err
11395
end
11496

115-
local msgs = body.messages
116-
if type(msgs) ~= "table" or #msgs < 1 then
117-
return HTTP_BAD_REQUEST, "messages not found in request body"
118-
end
119-
120-
local provider = conf.provider[next(conf.provider)]
97+
local comprehend = conf.comprehend
12198

12299
local credentials = aws_instance:Credentials({
123-
accessKeyId = provider.access_key_id,
124-
secretAccessKey = provider.secret_access_key,
125-
sessionToken = provider.session_token,
100+
accessKeyId = comprehend.access_key_id,
101+
secretAccessKey = comprehend.secret_access_key,
102+
sessionToken = comprehend.session_token,
126103
})
127104

128-
local default_endpoint = "https://comprehend." .. provider.region .. ".amazonaws.com"
129-
local scheme, host, port = unpack(http:parse_uri(provider.endpoint or default_endpoint))
105+
local default_endpoint = "https://comprehend." .. comprehend.region .. ".amazonaws.com"
106+
local scheme, host, port = unpack(http:parse_uri(comprehend.endpoint or default_endpoint))
130107
local endpoint = scheme .. "://" .. host
131108
aws_instance.config.endpoint = endpoint
132-
aws_instance.config.ssl_verify = provider.ssl_verify
109+
aws_instance.config.ssl_verify = comprehend.ssl_verify
133110

134111
local comprehend = aws_instance:Comprehend({
135112
credentials = credentials,
136113
endpoint = endpoint,
137-
region = provider.region,
114+
region = comprehend.region,
138115
port = port,
139116
})
140117

141-
local ai_module = require("apisix.plugins.ai." .. conf.llm_provider)
142-
local create_request_text_segments = ai_module.create_request_text_segments
143-
144-
local text_segments = create_request_text_segments(msgs)
145118
local res, err = comprehend:detectToxicContent({
146119
LanguageCode = "en",
147-
TextSegments = text_segments,
120+
TextSegments = {{
121+
Text = body
122+
}},
148123
})
149124

150125
if not res then
151126
core.log.error("failed to send request to ", endpoint, ": ", err)
152127
return HTTP_INTERNAL_SERVER_ERROR, err
153128
end
154-
129+
core.log.warn("dibag: ", core.json.encode(res))
155130
local results = res.body and res.body.ResultList
156131
if type(results) ~= "table" or core.table.isempty(results) then
157132
return HTTP_INTERNAL_SERVER_ERROR, "failed to get moderation results from response"

apisix/plugins/ai/openai.lua

-33
This file was deleted.

conf/config.yaml.example

+1-1
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,7 @@ plugins: # plugin list (sorted by priority)
481481
- ai-prompt-template # priority: 1071
482482
- ai-prompt-decorator # priority: 1070
483483
- ai-rag # priority: 1060
484-
- ai-content-moderation # priority: 1040 TODO: compare priority with other ai plugins
484+
- ai-aws-content-moderation # priority: 1040 TODO: compare priority with other ai plugins
485485
- proxy-mirror # priority: 1010
486486
- proxy-rewrite # priority: 1008
487487
- workflow # priority: 1006

docs/en/latest/config.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
"plugins/ext-plugin-post-resp",
8383
"plugins/inspect",
8484
"plugins/ocsp-stapling",
85-
"plugins/ai-content-moderation"
85+
"plugins/ai-aws-content-moderation"
8686
]
8787
},
8888
{

docs/en/latest/plugins/ai-content-moderation.md renamed to docs/en/latest/plugins/ai-aws-content-moderation.md

+27-33
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
---
2-
title: ai-content-moderation
2+
title: ai-aws-content-moderation
33
keywords:
44
- Apache APISIX
55
- API Gateway
66
- Plugin
7-
- ai-content-moderation
8-
description: This document contains information about the Apache APISIX ai-content-moderation Plugin.
7+
- ai-aws-content-moderation
8+
description: This document contains information about the Apache APISIX ai-aws-content-moderation Plugin.
99
---
1010

1111
<!--
@@ -29,23 +29,23 @@ description: This document contains information about the Apache APISIX ai-conte
2929

3030
## Description
3131

32-
The `ai-content-moderation` plugin processes the request body to check for toxicity and rejects the request if it exceeds the configured threshold.
32+
The `ai-aws-content-moderation` plugin processes the request body to check for toxicity and rejects the request if it exceeds the configured threshold.
3333

3434
**_This plugin must be used in routes that proxy requests to LLMs only._**
3535

3636
**_As of now, the plugin only supports the integration with [AWS Comprehend](https://aws.amazon.com/comprehend/) for content moderation. PRs for introducing support for other service providers are welcomed._**
3737

3838
## Plugin Attributes
3939

40-
| **Field** | **Required** | **Type** | **Description** |
41-
| ----------------------------------------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42-
| provider.aws_comprehend.access_key_id | Yes | String | AWS access key ID |
43-
| provider.aws_comprehend.secret_access_key | Yes | String | AWS secret access key |
44-
| provider.aws_comprehend.region | Yes | String | AWS region |
45-
| provider.aws_comprehend.endpoint | No | String | AWS Comprehend service endpoint. Must match the pattern `^https?://` |
46-
| moderation_categories | No | Object | Key-value pairs of moderation category and their score. In each pair, the key should be one of the `PROFANITY`, `HATE_SPEECH`, `INSULT`, `HARASSMENT_OR_ABUSE`, `SEXUAL`, or `VIOLENCE_OR_THREAT`; and the value should be between 0 and 1 (inclusive). |
47-
| moderation_threshold | No | Number | The degree to which content is harmful, offensive, or inappropriate. A higher value indicates more toxic content allowed. Range: 0 - 1. Default: 0.5 |
48-
| llm_provider | Yes | String | Name of the LLM provider that this route will proxy requests to. |
40+
| **Field** | **Required** | **Type** | **Description** |
41+
| ---------------------------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
42+
| comprehend.access_key_id | Yes | String | AWS access key ID |
43+
| comprehend.secret_access_key | Yes | String | AWS secret access key |
44+
| comprehend.region | Yes | String | AWS region |
45+
| comprehend.endpoint | No | String | AWS Comprehend service endpoint. Must match the pattern `^https?://` |
46+
| comprehend.ssl_verify | No | String | Enables SSL certificate verification. |
47+
| moderation_categories | No | Object | Key-value pairs of moderation category and their score. In each pair, the key should be one of the `PROFANITY`, `HATE_SPEECH`, `INSULT`, `HARASSMENT_OR_ABUSE`, `SEXUAL`, or `VIOLENCE_OR_THREAT`; and the value should be between 0 and 1 (inclusive). |
48+
| moderation_threshold | No | Number | The degree to which content is harmful, offensive, or inappropriate. A higher value indicates more toxic content allowed. Range: 0 - 1. Default: 0.5 |
4949

5050
## Example usage
5151

@@ -58,26 +58,23 @@ SECRET_ACCESS_KEY=aws-comprehend-secret-access-key-here
5858
OPENAI_KEY=open-ai-key-here
5959
```
6060

61-
Create a route with the `ai-content-moderation` and `ai-proxy` plugin like so:
61+
Create a route with the `ai-aws-content-moderation` and `ai-proxy` plugin like so:
6262

6363
```shell
6464
curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT \
6565
-H "X-API-KEY: ${ADMIN_API_KEY}" \
6666
-d '{
6767
"uri": "/post",
6868
"plugins": {
69-
"ai-content-moderation": {
70-
"provider": {
71-
"aws_comprehend": {
72-
"access_key_id": "'"$ACCESS_KEY_ID"'",
73-
"secret_access_key": "'"$SECRET_ACCESS_KEY"'",
74-
"region": "us-east-1"
75-
}
69+
"ai-aws-content-moderation": {
70+
"comprehend": {
71+
"access_key_id": "'"$ACCESS_KEY_ID"'",
72+
"secret_access_key": "'"$SECRET_ACCESS_KEY"'",
73+
"region": "us-east-1"
7674
},
7775
"moderation_categories": {
7876
"PROFANITY": 0.5
79-
},
80-
"llm_provider": "openai"
77+
}
8178
},
8279
"ai-proxy": {
8380
"auth": {
@@ -167,15 +164,12 @@ curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT \
167164
-d '{
168165
"uri": "/post",
169166
"plugins": {
170-
"ai-content-moderation": {
171-
"provider": {
172-
"aws_comprehend": {
173-
"access_key_id": "'"$ACCESS_KEY_ID"'",
174-
"secret_access_key": "'"$SECRET_ACCESS_KEY"'",
175-
"region": "us-east-1"
176-
}
167+
"ai-aws-content-moderation": {
168+
"comprehend": {
169+
"access_key_id": "'"$ACCESS_KEY_ID"'",
170+
"secret_access_key": "'"$SECRET_ACCESS_KEY"'",
171+
"region": "us-east-1"
177172
},
178-
"llm_provider": "openai",
179173
"moderation_categories": {
180174
"PROFANITY": 0.5,
181175
"HARASSMENT_OR_ABUSE": 0.7,
@@ -216,9 +210,9 @@ curl "http://127.0.0.1:9180/apisix/admin/routes/1" -X PUT \
216210
-d '{
217211
"uri": "/post",
218212
"plugins": {
219-
"ai-content-moderation": {
213+
"ai-aws-content-moderation": {
220214
"provider": {
221-
"aws_comprehend": {
215+
"comprehend": {
222216
"access_key_id": "'"$ACCESS_KEY_ID"'",
223217
"secret_access_key": "'"$SECRET_ACCESS_KEY"'",
224218
"region": "us-east-1"

t/admin/plugins.t

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ body-transformer
9797
ai-prompt-template
9898
ai-prompt-decorator
9999
ai-rag
100-
ai-content-moderation
100+
ai-aws-content-moderation
101101
proxy-mirror
102102
proxy-rewrite
103103
workflow

t/plugin/ai-content-moderation-secrets.t renamed to t/plugin/ai-aws-content-moderation-secrets.t

+14-20
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,13 @@ Success! Data written to: kv/apisix/foo
114114
[[{
115115
"uri": "/echo",
116116
"plugins": {
117-
"ai-content-moderation": {
118-
"provider": {
119-
"aws_comprehend": {
120-
"access_key_id": "$secret://vault/test1/foo/access_key_id",
121-
"secret_access_key": "$secret://vault/test1/foo/secret_access_key",
122-
"region": "us-east-1",
123-
"endpoint": "http://localhost:2668"
124-
}
125-
},
126-
"llm_provider": "openai"
117+
"ai-aws-content-moderation": {
118+
"comprehend": {
119+
"access_key_id": "$secret://vault/test1/foo/access_key_id",
120+
"secret_access_key": "$secret://vault/test1/foo/secret_access_key",
121+
"region": "us-east-1",
122+
"endpoint": "http://localhost:2668"
123+
}
127124
}
128125
},
129126
"upstream": {
@@ -169,16 +166,13 @@ POST /echo
169166
[[{
170167
"uri": "/echo",
171168
"plugins": {
172-
"ai-content-moderation": {
173-
"provider": {
174-
"aws_comprehend": {
175-
"access_key_id": "$env://ACCESS_KEY_ID",
176-
"secret_access_key": "$env://SECRET_ACCESS_KEY",
177-
"region": "us-east-1",
178-
"endpoint": "http://localhost:2668"
179-
}
180-
},
181-
"llm_provider": "openai"
169+
"ai-aws-content-moderation": {
170+
"comprehend": {
171+
"access_key_id": "$env://ACCESS_KEY_ID",
172+
"secret_access_key": "$env://SECRET_ACCESS_KEY",
173+
"region": "us-east-1",
174+
"endpoint": "http://localhost:2668"
175+
}
182176
}
183177
},
184178
"upstream": {

0 commit comments

Comments
 (0)