mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-13 08:52:02 +00:00
fix(google_genai): keep skipped results after answers split by empty or text turns
A skipped result now goes after the last answer before the next model turn. An empty or text-only user turn between split answers used to end the search early, so GPT read the later answer as the skipped call's result
This commit is contained in:
parent
f039b97fa6
commit
2e3eda2d27
2 changed files with 30 additions and 4 deletions
|
|
@ -424,7 +424,10 @@ def _genai_turn_messages(
|
||||||
|
|
||||||
|
|
||||||
def _last_answering_turn(turns: Sequence[_GenAITurn], index: int) -> int:
|
def _last_answering_turn(turns: Sequence[_GenAITurn], index: int) -> int:
|
||||||
return next((later for later in range(index + 1, len(turns)) if not turns[later].responses), len(turns)) - 1
|
next_model_turn: Final = next(
|
||||||
|
(later for later in range(index + 1, len(turns)) if turns[later].role == "model"), len(turns)
|
||||||
|
)
|
||||||
|
return max((later for later in range(index + 1, next_model_turn) if turns[later].responses), default=index)
|
||||||
|
|
||||||
|
|
||||||
def _genai_contents_messages(contents: Sequence[object]) -> tuple[AllMessageValues, ...]:
|
def _genai_contents_messages(contents: Sequence[object]) -> tuple[AllMessageValues, ...]:
|
||||||
|
|
|
||||||
|
|
@ -660,9 +660,11 @@ def _call_tags(messages: list[dict[str, object]]) -> dict[str, str]:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _ids_answered_right_after(messages: list[dict[str, object]], index: int) -> list[str]:
|
def _ids_answered_before_the_next_model_turn(messages: list[dict[str, object]], index: int) -> list[str]:
|
||||||
return [
|
return [
|
||||||
answer["tool_call_id"] for answer in takewhile(lambda message: message["role"] == "tool", messages[index + 1 :])
|
message["tool_call_id"]
|
||||||
|
for message in takewhile(lambda message: message["role"] != "assistant", messages[index + 1 :])
|
||||||
|
if message["role"] == "tool"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -716,6 +718,25 @@ def _ids_answered_right_after(messages: list[dict[str, object]], index: int) ->
|
||||||
frozenset({"paris", "rome"}),
|
frozenset({"paris", "rome"}),
|
||||||
id="answers_split_across_user_turns",
|
id="answers_split_across_user_turns",
|
||||||
),
|
),
|
||||||
|
pytest.param(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"role": "model",
|
||||||
|
"parts": [
|
||||||
|
_tagged_call("get_weather", "paris"),
|
||||||
|
_tagged_call("get_weather", "rome"),
|
||||||
|
_tagged_call("get_weather", "oslo"),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{"role": "user", "parts": [_tagged_response("get_weather", "paris")]},
|
||||||
|
{"role": "user", "parts": []},
|
||||||
|
{"role": "user", "parts": [{"text": "Rome took longer"}]},
|
||||||
|
{"role": "user", "parts": [_tagged_response("get_weather", "rome")]},
|
||||||
|
{"role": "model", "parts": [{"text": "Oslo did not answer"}]},
|
||||||
|
],
|
||||||
|
frozenset({"paris", "rome"}),
|
||||||
|
id="answers_split_by_empty_and_text_turns",
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
def test_a_call_a_later_turn_left_unanswered_gets_one_skipped_result_and_the_others_keep_their_answers(
|
def test_a_call_a_later_turn_left_unanswered_gets_one_skipped_result_and_the_others_keep_their_answers(
|
||||||
|
|
@ -732,7 +753,9 @@ def test_a_call_a_later_turn_left_unanswered_gets_one_skipped_result_and_the_oth
|
||||||
if message.get("tool_calls")
|
if message.get("tool_calls")
|
||||||
}
|
}
|
||||||
answers: Final = [message for message in messages if message["role"] == "tool"]
|
answers: Final = [message for message in messages if message["role"] == "tool"]
|
||||||
assert {index: _ids_answered_right_after(messages, index) for index in call_ids_per_turn} == call_ids_per_turn
|
assert {
|
||||||
|
index: _ids_answered_before_the_next_model_turn(messages, index) for index in call_ids_per_turn
|
||||||
|
} == call_ids_per_turn
|
||||||
assert {
|
assert {
|
||||||
tag_by_call_id[answer["tool_call_id"]]: json.loads(answer["content"])["tag"]
|
tag_by_call_id[answer["tool_call_id"]]: json.loads(answer["content"])["tag"]
|
||||||
for answer in answers
|
for answer in answers
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue