mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-09 03:18:44 +00:00
fix(caching): keep structured function_call_output text in semantic prompts
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
8b08e07f18
commit
8bf443997b
4 changed files with 39 additions and 4 deletions
11
litellm-rust/crates/cache/src/semantic.rs
vendored
11
litellm-rust/crates/cache/src/semantic.rs
vendored
|
|
@ -199,10 +199,13 @@ fn collect_input_text(value: &Value, parts: &mut Vec<String>) {
|
|||
return;
|
||||
}
|
||||
for key in ["text", "output", "input_text", "output_text"] {
|
||||
if let Some(Value::String(text)) = map.get(key)
|
||||
&& push_trimmed(text, parts)
|
||||
{
|
||||
return;
|
||||
match map.get(key) {
|
||||
Some(nested @ Value::Array(_)) => {
|
||||
collect_input_text(nested, parts);
|
||||
return;
|
||||
}
|
||||
Some(Value::String(text)) if push_trimmed(text, parts) => return,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
8
litellm-rust/crates/cache/tests/semantic.rs
vendored
8
litellm-rust/crates/cache/tests/semantic.rs
vendored
|
|
@ -240,6 +240,14 @@ fn prompt_from_messages_reads_messages_only(
|
|||
])),
|
||||
Some("update the config\n{\"name\":\"write_file\",\"arguments\":\"{\\\"path\\\":\\\"a.yaml\\\"}\"}\nok"),
|
||||
)]
|
||||
#[case::responses_structured_function_call_output(
|
||||
None,
|
||||
Some(json!([
|
||||
{"type": "function_call", "call_id": "c1", "name": "write_file", "arguments": "{}"},
|
||||
{"type": "function_call_output", "call_id": "c1", "output": [{"type": "input_text", "text": "denied"}]},
|
||||
])),
|
||||
Some("{\"name\":\"write_file\",\"arguments\":\"{}\"}\ndenied"),
|
||||
)]
|
||||
fn prompt_from_context_matches_python(
|
||||
#[case] messages: Option<Value>,
|
||||
#[case] input: Option<Value>,
|
||||
|
|
|
|||
|
|
@ -299,6 +299,9 @@ class RedisSemanticCache(BaseCache):
|
|||
|
||||
for text_key in ("text", "output", "input_text", "output_text"):
|
||||
text_value = value.get(text_key)
|
||||
if isinstance(text_value, (list, tuple)):
|
||||
cls._collect_responses_input_text(text_value, prompt_parts)
|
||||
return
|
||||
if isinstance(text_value, str):
|
||||
stripped_text = text_value.strip()
|
||||
if stripped_text:
|
||||
|
|
|
|||
|
|
@ -614,6 +614,27 @@ def test_redis_semantic_cache_prompt_extraction_keeps_responses_function_calls()
|
|||
assert prompt == 'update the config\n{"name":"write_file","arguments":"{\\"path\\":\\"a.yaml\\"}"}\nok'
|
||||
|
||||
|
||||
def test_redis_semantic_cache_prompt_extraction_keeps_structured_function_call_outputs():
|
||||
from litellm.caching.redis_semantic_cache import RedisSemanticCache
|
||||
|
||||
def prompt_for(output_text: str) -> str | None:
|
||||
return RedisSemanticCache._get_prompt_from_kwargs(
|
||||
input=[
|
||||
{"type": "message", "role": "user", "content": [{"type": "input_text", "text": "write hello"}]},
|
||||
{"type": "function_call", "call_id": "c1", "name": "write_file", "arguments": '{"path":"a.txt"}'},
|
||||
{
|
||||
"type": "function_call_output",
|
||||
"call_id": "c1",
|
||||
"output": [{"type": "input_text", "text": output_text}],
|
||||
},
|
||||
]
|
||||
)
|
||||
|
||||
expected_call = '{"name":"write_file","arguments":"{\\"path\\":\\"a.txt\\"}"}'
|
||||
assert prompt_for("wrote 5 bytes") == f"write hello\n{expected_call}\nwrote 5 bytes"
|
||||
assert prompt_for("wrote 5 bytes") != prompt_for("PermissionError")
|
||||
|
||||
|
||||
def test_redis_semantic_cache_prompt_extraction_handles_model_objects():
|
||||
from litellm.caching.redis_semantic_cache import RedisSemanticCache
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue