From 4328131b9763b9ac9ef51e39b44331de64373784 Mon Sep 17 00:00:00 2001 From: Karunasagar Mohansundar Date: Mon, 28 Sep 2026 07:45:13 +0000 Subject: [PATCH] fix(content_filter): use substring matching for identifier words in conditionals - Reverted word boundary matching for identifier words in _check_conditional_categories - Reverted word boundary matching for conditional words in _cut_breaks_wider_context - Identifier words MUST use substring matching to match straddling-cut scenarios - Word boundary matching is kept for BLOCK words only (not identifiers) - Fixes test_streaming_hook_blocks_conditional_identifier_straddling_cut --- .../litellm_content_filter/content_filter.py | 40 ++++--------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py b/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py index a9f8fd62e3d..5efda157291 100644 --- a/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py +++ b/litellm/proxy/guardrails/guardrail_hooks/litellm_content_filter/content_filter.py @@ -1050,26 +1050,12 @@ class ContentFilterGuardrail(CustomGuardrail): if not sentence_lower: continue - # Check if sentence contains ANY identifier word (with word boundaries) + # Check if sentence contains ANY identifier word identifier_found = None for identifier in identifier_words: - # Use word boundary to avoid false positives (e.g., "alter" in "alternative") - if " " in identifier: - # Multi-word phrase - use simple substring matching - if identifier in sentence_lower: - identifier_found = identifier - break - else: - # Single word - use word boundary for alphanumeric words - # Punctuation-only identifiers (e.g., ">", "=", "!=") need substring matching - # since word boundaries don't work around non-word characters - if _is_word_char_pattern(identifier): - pattern = r"\b" + re.escape(identifier) + r"\b" - else: - pattern = re.escape(identifier) - if re.search(pattern, sentence_lower): - identifier_found = identifier - break + if identifier in sentence_lower: + identifier_found = identifier + break if not identifier_found: continue @@ -2058,22 +2044,10 @@ class ContentFilterGuardrail(CustomGuardrail): cut_sentence: Final = ( SENTENCE_TERMINATORS.split(head.lower())[-1] + SENTENCE_TERMINATORS.split(tail_lower, maxsplit=1)[0] ) - # Use word boundary matching for single-word conditional words to match _check_conditional_categories behavior + # Check if any conditional word appears in the cut_sentence for word in plan.conditional_words: - if " " in word: - # Multi-word phrase - use substring matching - if word in cut_sentence: - return True - else: - # Single word - use word boundary matching - if _is_word_char_pattern(word): - pattern = r"\b" + re.escape(word) + r"\b" - if re.search(pattern, cut_sentence): - return True - else: - # Punctuation-only words use substring matching - if word in cut_sentence: - return True + if word in cut_sentence: + return True return False def _trim_streamed_choice_buffer(