Coverage for .venv/lib/python3.13/site-packages/litellm/proxy/guardrails/guardrail_hooks/custom_code/response_rejection_code.py: 100%
4 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-10 12:01 +0000
1"""
2Custom code for a response guardrail that blocks when the model response
3indicates it is rejecting the user request (e.g. "That's not something I can help with").
5Use this with the Custom Code Guardrail (custom_code) by setting litellm_params.custom_code
6to RESPONSE_REJECTION_GUARDRAIL_CODE. The guardrail runs only on input_type "response"
7and raises a block error if any response text matches known rejection phrases.
8"""
10from typing import Final
12# Default phrases that indicate the model is refusing the user request (lowercase for case-insensitive match).
13# Custom code guardrails can override by defining rejection_phrases in the code.
14DEFAULT_REJECTION_PHRASES: Final = [
15 "that's not something i can help with",
16 "that is not something i can help with",
17 "i can't help with that",
18 "i cannot help with that",
19 "i'm not able to help",
20 "i am not able to help",
21 "i'm unable to help",
22 "i cannot assist",
23 "i can't assist",
24 "i'm not allowed to",
25 "i'm not permitted to",
26 "i won't be able to help",
27 "i'm sorry, i can't",
28 "i'm sorry, i cannot",
29 "as an ai, i can't",
30 "as an ai, i cannot",
31]
33# Custom code string for the Custom Code Guardrail. Only runs on input_type "response".
34# Uses primitives: allow(), block(), lower(), contains()
35RESPONSE_REJECTION_GUARDRAIL_CODE: Final = '''
36def apply_guardrail(inputs, request_data, input_type):
37 """Block responses that indicate the model rejected the user request."""
38 if input_type != "response":
39 return allow()
41 texts = inputs.get("texts") or []
42 # All lowercase for case-insensitive matching (text is lowercased before check)
43 rejection_phrases = [
44 "that's not something i can help with",
45 "that is not something i can help with",
46 "i can't help with that",
47 "i cannot help with that",
48 "i'm not able to help",
49 "i am not able to help",
50 "i'm unable to help",
51 "i cannot assist",
52 "i can't assist",
53 "i'm not allowed to",
54 "i'm not permitted to",
55 "i won't be able to help",
56 "i'm sorry, i can't",
57 "i'm sorry, i cannot",
58 "as an ai, i can't",
59 "as an ai, i cannot",
60 ]
62 for text in texts:
63 if not text:
64 continue
65 text_lower = lower(text)
66 for phrase in rejection_phrases:
67 if contains(text_lower, phrase):
68 return block(
69 "Response indicates the model rejected the user request.",
70 detection_info={"matched_phrase": phrase, "input_type": "response"},
71 )
72 return allow()
73'''
75__all__ = [
76 "DEFAULT_REJECTION_PHRASES",
77 "RESPONSE_REJECTION_GUARDRAIL_CODE",
78]