Skip to content

fix(ai-aws-content-moderation): respect Comprehend's segment limits and reuse the client - #13767

Open
shreemaan-abhishek wants to merge 2 commits into
apache:masterfrom
shreemaan-abhishek:fix/aws-comprehend-segment-limits
Open

fix(ai-aws-content-moderation): respect Comprehend's segment limits and reuse the client#13767
shreemaan-abhishek wants to merge 2 commits into
apache:masterfrom
shreemaan-abhishek:fix/aws-comprehend-segment-limits

Conversation

@shreemaan-abhishek

Copy link
Copy Markdown
Contributor

Description

AWS Comprehend's DetectToxicContent takes at most 10 text segments per call, each at most 1 KB, with the list capped at 10 KB. Over that it answers TextSizeLimitExceededException (400). ai-aws-content-moderation sent the whole prompt, or the whole completion, as a single segment.

Consequences on content longer than ~1 KB, which is most real traffic:

  • Request side: Comprehend returns 400, the plugin turns that into a 500, so long prompts are unusable.
  • Response side: the error is logged and the content passes through, so check_response silently does nothing.
  • On that error path the verdict is never computed, yet final_packet still annotates the SSE stream with risk_level, reporting the request-side (or stale) verdict as if the response had been scored.
  • realtime mostly stays under the cap with the default batch size, but an interval-triggered batch, or a single large upstream SSE event, pushes one batch over 1 KB and that batch leaks.

Changes:

  • Content is split on UTF-8 character boundaries into segments bounded by the new request_check_length_limit / response_check_length_limit (default 1000 bytes, capped at Comprehend's 1 KB), and the segments are batched up to the per-call limits, so a long body costs as few round trips as possible.
  • On a Comprehend failure the stream is left without a risk_level instead of carrying a verdict that was never computed.
  • The credentials and the Comprehend client were rebuilt on every call — in realtime that is a fresh client per batch. They are now built once per request, and timeout / keepalive / keepalive_timeout are exposed so the connection is reused instead of a new TLS handshake per batch.

The Comprehend mock in the tests now enforces the same input limits as the real service and answers with one result per segment, so content that is sent unsplit fails the tests.

Which issue(s) this PR fixes:

N/A

Checklist

  • I have explained the need for this PR and the problem it solves
  • I have explained the changes or the new features added to this PR
  • I have added tests corresponding to this change
  • I have updated the documentation to reflect this change
  • I have verified that this change is backward compatible

…nd reuse the client

DetectToxicContent takes at most 10 text segments per call, each at most 1 KB.
The plugin sent the whole prompt or the whole completion as a single segment,
so any content over 1 KB came back as a 400: the request side failed closed
with a 500, and the response side logged the error and let the content
through, which silently disabled check_response on normal-length responses.
On that path the verdict was never computed either, yet final_packet still
annotated the stream with risk_level, reporting the request-side (or stale)
verdict as if the response had been scored.

Content is now split on UTF-8 character boundaries into segments bounded by
the new request_check_length_limit / response_check_length_limit (default
1000 bytes, capped at Comprehend's 1 KB), and those segments are batched up
to the per-call limits so a long body costs as few round trips as possible.
When Comprehend fails, the stream is left without a risk_level rather than
carrying a verdict that was never computed.

The Comprehend client is also built once per request instead of once per
batch, and timeout / keepalive / keepalive_timeout are exposed so the
connection is reused across calls instead of a fresh TLS handshake each time.
@dosubot dosubot Bot added the size:XL This PR changes 500-999 lines, ignoring generated files. label Jul 31, 2026
- pass ssl_verify and the endpoint through the Comprehend service config
  instead of mutating the shared aws instance
- require at least 4 bytes per segment, the width of the widest UTF-8
  character, so a segment can always hold one whole character
- have the Comprehend mock reject segments that are not valid UTF-8, and
  cover a multibyte body that spans several segments

@membphis membphis left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants