Skip to content

Commit baf7efb

Browse files
google-genai-botcopybara-github
authored andcommitted
feat: Added config option to include tool calls/responses in conversation history passed to user simulator
PiperOrigin-RevId: 917340645
1 parent 48f1b30 commit baf7efb

2 files changed

Lines changed: 35 additions & 2 deletions

File tree

src/google/adk/evaluation/simulation/llm_backed_user_simulator.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,12 @@ class LlmBackedUserSimulatorConfig(BaseUserSimulatorConfig):
8585
""",
8686
)
8787

88+
include_function_calls: bool = Field(
89+
default=False,
90+
description="""Whether to include function calls and responses in the
91+
conversation history prompt provided to the user simulator.""",
92+
)
93+
8894
@field_validator("custom_instructions")
8995
@classmethod
9096
def validate_custom_instructions(cls, value: str | None) -> str | None:
@@ -132,13 +138,15 @@ def __init__(
132138
def _summarize_conversation(
133139
cls,
134140
events: list[Event],
141+
include_function_calls: bool = False,
135142
) -> str:
136143
"""Summarize the conversation to add to the prompt.
137144
138-
Removes tool calls, responses, and thoughts.
145+
Removes responses, thoughts, optionally tool calls and tool responses.
139146
140147
Args:
141148
events: The conversation history to rewrite.
149+
include_function_calls: Whether to include function calls and responses.
142150
143151
Returns:
144152
The summarized conversation history as a string.
@@ -151,6 +159,16 @@ def _summarize_conversation(
151159
for part in e.content.parts:
152160
if part.text and not part.thought:
153161
rewritten_dialogue.append(f"{author}: {part.text}")
162+
elif include_function_calls and part.function_call:
163+
rewritten_dialogue.append(
164+
f"{author} called tool '{part.function_call.name}' with args:"
165+
f" {part.function_call.args}"
166+
)
167+
elif include_function_calls and part.function_response:
168+
rewritten_dialogue.append(
169+
f"Tool '{part.function_response.name}' returned:"
170+
f" {part.function_response.response}"
171+
)
154172

155173
return "\n\n".join(rewritten_dialogue)
156174

@@ -255,7 +273,9 @@ async def get_next_user_message(
255273
return NextUserMessage(status=Status.TURN_LIMIT_REACHED)
256274

257275
# rewrite events for the user simulator
258-
rewritten_dialogue = self._summarize_conversation(events)
276+
rewritten_dialogue = self._summarize_conversation(
277+
events, self._config.include_function_calls
278+
)
259279

260280
# query the LLM for the next user message
261281
response, error_reason = await self._get_llm_response(rewritten_dialogue)

tests/unittests/evaluation/simulation/test_llm_backed_user_simulator.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,19 @@ def test_convert_conversation_to_user_sim_pov(self):
119119
)
120120
assert rewritten_dialogue == _EXPECTED_REWRITTEN_DIALOGUE_LONG
121121

122+
def test_summarize_conversation_with_function_calls(self):
123+
"""Tests _summarize_conversation with include_function_calls=True."""
124+
rewritten_dialogue = LlmBackedUserSimulator._summarize_conversation(
125+
_INPUT_EVENTS, include_function_calls=True
126+
)
127+
expected = (
128+
"user: Can you help me?\n\n"
129+
"helpful_assistant called tool 'get_user_name' with args: None\n\n"
130+
"Tool 'get_user_name' returned: {'name': 'John Doe'}\n\n"
131+
"helpful_assistant: Hi John, what can I do for you?"
132+
)
133+
assert rewritten_dialogue == expected
134+
122135

123136
async def to_async_iter(items):
124137
for item in items:

0 commit comments

Comments
 (0)