feat(guardrails): azure_content_safety_text_moderation — config + schema + dispatcher (P2 of #379) - #461
Conversation
…+ schema + dispatcher (P2 of #379) DP runtime for P2 text moderation — PR2, increment 1 of 2: - New GuardrailKind::AzureContentSafetyTextModeration variant + AzureContentSafetyTextModerationConfig (aisix-core). Reuses the P1 connection block (endpoint + api_key + timeout_ms) and adds the text:analyze moderation params (output_type, categories, severity_threshold[_by_category], blocklist_names, halt_on_blocklist_hit, text_source) + streaming controls (stream_processing_mode, window_size, window_overlap_size, max_buffer_bytes, on_buffer_exceeded, output_fail_open). serde defaults match the cp-api validator so a minimal projected row still moderates correctly. - schema::validate_guardrail: add the kind to the top-level enum + a per-kind oneOf branch (closes the schema gate, #459). - text_moderation.rs (TextModerationGuardrail): text:analyze dispatch, per-category severity resolution (override -> general -> default 2), blocklist match, 10k-char chunking, text_source-aware input collection, and OUTPUT-direction fail-closed by default (an Azure outage can't release unscanned model output). Forks the P1 transport (chunk_text / AcsFailure / fail-open mapping); shared-module extraction tracked as a follow-up so this slice doesn't touch the shipped P1 dispatcher. - build.rs wires the new kind through build_one (input + non-streaming output), feature-gated under azure-content-safety like P1. Deferred to increment 2: the build_sse_stream window/buffer_full streaming restructure in aisix-proxy. Tests: aisix-core 186 + aisix-guardrails 87 pass; clippy clean under default features (incl. the bedrock arm). Depends on the cp-api projection in api7/AISIX-Cloud#602.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Free Run ID: 📒 Files selected for processing (10)
📝 WalkthroughWalkthroughThis PR introduces Azure Content Safety text moderation for streaming chat completions. It adds a new ChangesAzure Content Safety Text Moderation with Streaming
Estimated code review effort🎯 4 (Complex) | ⏱️ ~75 minutes Note 🎁 Summarized by CodeRabbit FreeYour organization has reached its limit of developer seats under the Pro Plan. For new users, CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please add seats to your subscription by visiting https://app.coderabbit.ai/login.If you believe this is a mistake and have available seats, please assign one to the pull request author through the subscription management page using the link above. Comment |
PR2 (DP) — independent §7 auditIndependent cold review of the DP slice (commit Verified (not just claimed):
Merge gate: no HIGH/MEDIUM; the LOWs are pre-existing / benign / deferred. Streaming ( |
…hold-back policy (P2 of #379) Adds the plumbing the SSE builder will consume to actually hold streamed output back until it scans clean: - StreamOutputPolicy enum (EndOfStreamCheck | Window | BufferFull) + Guardrail::stream_output_policy() (default EndOfStreamCheck = today's live-forward, no behavior change for keyword/prompt_shield). - GuardrailChain folds members to the STRICTEST policy (any hold-back member → the whole stream holds back, full chain re-checks the held content). - TextModerationGuardrail returns Window/BufferFull from its config. Plumbing only; build_sse_stream consumes it in the next commit.
f1045ba to
08d23e4
Compare
…aming hold-back (P2 of #379) Wires the per-guardrail streamed-output policy into the SSE builder so azure_content_safety_text_moderation actually holds streamed content back until it scans clean: - EndOfStreamCheck (keyword / prompt_shield / no guardrail) path preserved byte-for-byte — content forwarded live, checked at end. The pre-existing leak for those kinds is tracked at #466. - Window: buffer content, scan per window_size (carrying overlap_chars), release a window only after it scans clean; on Block emit only the content_filter frame. - BufferFull: hold the whole response, scan once; max_buffer_bytes cap -> on_buffer_exceeded (fail-closed default blocks; fail-open releases held + forwards the rest live). - On block (or upstream error), held unscanned content is dropped — the offending content never reaches the wire. Tests: HTTP/SSE wire-level — blocked stream leaks nothing + content_filter + no [DONE]; clean stream releases content + [DONE]. Full aisix-proxy suite (352) green incl. the unchanged EndOfStreamCheck guardrail test; clippy clean.
…erlap (PR2 self-audit H1/M1) - H1: add streaming hold-back tests for the previously-untested novel paths — mid-stream Window block (no leak), multi-window clean release (overlap retention), and both BufferFull cap branches (fail-closed blocks; fail-open releases held + forwards rest live). - M1: clamp the retained window overlap to cc-1 so a misconfigured overlap >= window can't keep the whole buffer and re-scan every subsequent token (cost/latency guard).
#379) Fixes the 'schema drift (resources)' CI check — the new AzureContentSafetyTextModerationConfig was missing from the committed canonical schema. Generated by 'cargo run -p aisix-core --bin dump-schema'.
Status: draft. DP runtime for P2 text moderation (api7/AISIX-Cloud#379). Pairs with the CP slice in api7/AISIX-Cloud#602.
What this adds
Config + schema + dispatcher (input + non-streaming output):
GuardrailKind::AzureContentSafetyTextModeration+AzureContentSafetyTextModerationConfig(aisix-core). Reuses the P1 connection block (endpoint + api_key + timeout_ms) and adds thetext:analyzemoderation params + streaming controls; serde defaults match the cp-api validator.schema::validate_guardrail: kind enum + per-kindoneOfbranch (closes guardrails DP: accept kind=azure_content_safety_text_moderation (PR2 of #379) #459).text_moderation.rs(TextModerationGuardrail):text:analyzedispatch, per-category severity (override → general → default 2), blocklist, 10k chunking,text_source-aware input collection, OUTPUT-direction fail-closed.build.rswires the kind (feature-gatedazure-content-safety).Streaming hold-back (
build_sse_stream):Guardrail::stream_output_policy()→EndOfStreamCheck(default) |Window { size_chars, overlap_chars }|BufferFull { max_buffer_bytes, on_exceeded_fail_open }.GuardrailChainfolds members to the strictest.azure_content_safety_text_moderationreturns Window/BufferFull from config.build_sse_streamconsumes it: hold-back policies buffer content and release a window (or the whole response) only after a clean scan; on Block emit only thecontent_filterframe; held unscanned content (Block or upstream error) never reaches the wire. TheEndOfStreamCheckpath (keyword / prompt_shield / no guardrail) is preserved byte-for-byte.Scope / dependencies
keyword/prompt_shieldkeepEndOfStreamCheck; their pre-existing streaming-output leak is out of scope here and tracked at guardrails: streaming output moderation forwards content live before check_output (pre-P2 leak) #466.chunk_text/AcsFailure/ fail-open mapping); shared-module extraction is a follow-up (doesn't touch the shipped P1 dispatcher).content_blocksisn't scanned (pre-existing across the codebase, guardrails: text in content_blocks bypasses moderation (only flat content is scanned) #465).Independent self-audit (cold) — merge gate
Core guarantee independently verified: blocked / errored hold-back streams leak no content;
EndOfStreamCheckunchanged; borrow/async-safe; clippy clean.cc-1.ttft_msrecords first-upstream not first-delivered under hold-back) → deferred + tracked at build_sse_stream: ttft_ms misreports under streaming hold-back (first-upstream, not first-delivered) #467 (observability, not correctness/security).overlap_chars) → inherent windowing limitation; operators wanting zero boundary-evasion risk usebuffer_full.Tests
aisix-core+aisix-guardrailsunit suites;aisix-proxy356 incl. wire-level streaming hold-back (block leaks nothing +content_filter+ no[DONE]; clean releases +[DONE]; mid-stream Window; BufferFull cap fail-open/closed).clippy --all-targetsclean under default features (AWS SDK + bedrock arm). Real-Azure / dashboard e2e land in later slices.Summary by CodeRabbit
New Features
Tests