shreemaan-abhishek opened a new pull request, #13735: URL: https://github.com/apache/apisix/pull/13735
### Description `ai-aws-content-moderation` only moderated requests, while its sibling `ai-aliyun-content-moderation` moderates both directions. AWS Comprehend `DetectToxicContent` scores response text just as well, so this was a plugin gap rather than an API limitation. It builds on #13647, which moved the plugin to the `access` phase with protocol-aware content extraction. **What changed** — a new `check_response` option plus a `lua_body_filter`: | Case | Behavior | |---|---| | non-streaming (`ai_chat`) | the assembled completion is moderated in one call; a hit returns `deny_code` with a provider-compatible refusal body | | streaming, `stream_check_mode: realtime` | batches are moderated as they arrive, bounded by `stream_check_cache_size` (chars) and `stream_check_interval` (seconds); a hit replaces the rest of the stream with the refusal | | streaming, `stream_check_mode: final_packet` (default) | the assembled response is moderated once and the last chunk's SSE data events are annotated with `risk_level` | New schema fields: `check_response` (default `false`), `stream_check_mode` (default `final_packet`), `stream_check_cache_size` (default `128`), `stream_check_interval` (default `3`). All default to the previous behavior, so existing configurations are unaffected. The verdict is published on `ctx.var.llm_content_risk_level` as `high` or `none`. Comprehend grades nothing, it only scores against the configured thresholds, so the verdict is binary; reusing the same ctx var the aliyun plugin sets keeps logging and downstream consumers uniform. Deny reasons now name the side that tripped (`request body exceeds ...` / `response body exceeds ...`). A Comprehend failure on the **response** side is logged and the content passes through: once bytes are on the wire there is no fail-closed option, and buffered responses behave the same way for consistency. This matches `ai-aliyun-content-moderation`. The request side is unchanged and still fails closed with a 500. **Tests** — `t/plugin/ai-aws-content-moderation.t` TEST 18-30 cover non-streaming deny and pass-through, the provider-compatible deny body with a custom `deny_message` at the default `deny_code`, `check_response` off leaving a toxic response untouched, `final_packet` annotation, `realtime` cutting the stream off mid-flight, the upstream-error skip, and schema validation of the new fields. New fixtures live under `t/fixtures/aws/`. The Comprehend mock gained a fallback for free-form response text, since response content is not a fixture key; exact-key lookup still runs first, so every existing test is unchanged. **Docs** — `docs/en/latest/plugins/ai-aws-content-moderation.md` updated with the new attributes and the response-moderation description. # Checklist - [x] I have explained the need for this PR and the problem it solves - [x] I have explained the changes or the new features added to this PR - [x] I have added tests corresponding to this change - [x] I have updated the documentation to reflect this change - [x] I have verified that this change is backward compatible (If not, please discuss on the [APISIX mailing list](https://github.com/apache/apisix/tree/master#community) first) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
