feat(logging): name the request texts a failure's error quotes

This commit is contained in:
yucheng 2026-11-04 19:17:15 -08:00
parent 424dd5fc68
commit 1c67f492c3
2 changed files with 29 additions and 0 deletions

View file

@ -514,6 +514,16 @@ def scrub_request_text(text: str, texts: Collection[str]) -> str:
return REDACTED_BY_LITELLM if scrubbed is None else scrubbed
def quoted_request_texts(text: str, texts: Collection[str]) -> frozenset[str]:
"""
The request ``texts`` that ``scrub_request_text`` acts on in ``text``: those it quotes, or all of them when
``text`` holds a pydantic ``input_value`` or is too large to search one text at a time.
"""
if len(text) * len(texts) > _MAX_SCRUB_COMPARISONS:
return frozenset(texts)
return frozenset(each for each in texts if scrub_request_text(text, (each,)) != text)
def _with_echoes_replaced(text: str, echoes: Collection[str]) -> str | None:
"""
``text`` with each quote of ``echoes`` replaced by ``REDACTED_BY_LITELLM`` in one left-to-right pass, the

View file

@ -32,6 +32,7 @@ from litellm.litellm_core_utils.redact_messages import (
_redact_responses_api_output,
_redacted_responses_api_response,
perform_redaction,
quoted_request_texts,
redacted_model_call_details_for_custom_logger,
redacted_response_obj_for_custom_logger,
redacted_standard_logging_payload,
@ -2493,6 +2494,24 @@ def test_scrub_request_text_replaces_the_whole_text_when_the_prompt_repeats_past
assert scrub_request_text("bad: secret " * echoes, request_texts("secret")) == scrubbed
@pytest.mark.parametrize(
("error", "quoted"),
[
("Invalid content: 'secret one' and \"tab\\tafter\"", {"secret one", "tab\tafter"}),
("litellm.RateLimitError: Rate limit reached", set()),
("1 validation error\n Input should be a valid string [input_value='cut...', input_type=str]", None),
("x" * 5_000, None),
],
ids=["quoted_verbatim_or_escaped", "quoted_only_inside_a_word", "pydantic_input_value", "too_large_to_search"],
)
def test_quoted_request_texts_names_the_texts_a_scrub_of_the_error_acts_on(error: str, quoted: set[str] | None) -> None:
texts: Final = request_texts(
"secret one", "tab\tafter", "Error", [f"message number {index}" for index in range(2_000)]
)
assert quoted_request_texts(error, texts) == (texts if quoted is None else quoted)
def test_scrub_request_text_keeps_no_copy_of_the_prompt_after_it_returns() -> None:
prompt: Final = "".join(f"secret {index} " for index in range(20_000))
error: Final = f"Invalid content: '{prompt}'"