Skip to content

Commit f2d73fd

Browse files
vertex-sdk-botcopybara-github
authored andcommitted
fix: Strip None fields from agent_data in GenerateLossClusters to prevent INVALID_ARGUMENT errors
PiperOrigin-RevId: 901053406
1 parent 657bb26 commit f2d73fd

3 files changed

Lines changed: 96 additions & 3 deletions

File tree

tests/unit/vertexai/genai/replays/test_generate_loss_clusters.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121

2222
def _make_eval_result():
23-
"""Creates an EvaluationResult with representative data for loss analysis."""
23+
"""Creates an EvaluationResult with rubric verdicts for loss analysis."""
2424
return types.EvaluationResult(
2525
eval_case_results=[
2626
types.EvalCaseResult(
@@ -32,6 +32,19 @@ def _make_eval_result():
3232
"multi_turn_task_success_v1": types.EvalCaseMetricResult(
3333
score=0.0,
3434
explanation="Failed tool invocation",
35+
rubric_verdicts=[
36+
types.evals.RubricVerdict(
37+
evaluated_rubric=types.evals.Rubric(
38+
rubric_id="tool_invocation",
39+
content=types.evals.RubricContent(
40+
property=types.evals.RubricContentProperty(
41+
description="The agent should invoke the find_flights tool with the correct parameters.",
42+
)
43+
),
44+
),
45+
verdict=False,
46+
)
47+
],
3548
)
3649
},
3750
)

tests/unit/vertexai/genai/test_evals.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,86 @@ def test_sanitize_agent_data_skips_error_payload(self):
441441
assert "error" not in sanitized
442442
assert sanitized == {}
443443

444+
def test_t_inline_results_strips_none_tool_fields(self):
445+
"""Tests that t_inline_results strips None tool fields like file_search."""
446+
eval_result = common_types.EvaluationResult(
447+
eval_case_results=[
448+
common_types.EvalCaseResult(
449+
eval_case_index=0,
450+
response_candidate_results=[
451+
common_types.ResponseCandidateResult(
452+
response_index=0,
453+
metric_results={
454+
"multi_turn_task_success_v1": common_types.EvalCaseMetricResult(
455+
score=0.0,
456+
explanation="Failed",
457+
)
458+
},
459+
)
460+
],
461+
)
462+
],
463+
evaluation_dataset=[
464+
common_types.EvaluationDataset(
465+
eval_cases=[
466+
common_types.EvalCase(
467+
agent_data=vertexai_genai_types.evals.AgentData(
468+
agents={
469+
"agent_0": vertexai_genai_types.evals.AgentConfig(
470+
agent_id="agent_0",
471+
agent_type="LlmAgent",
472+
instruction="You are a helper.",
473+
tools=[
474+
genai_types.Tool(
475+
function_declarations=[
476+
genai_types.FunctionDeclaration(
477+
name="search",
478+
description="Searches the web.",
479+
)
480+
]
481+
)
482+
],
483+
)
484+
},
485+
turns=[
486+
vertexai_genai_types.evals.ConversationTurn(
487+
turn_index=0,
488+
events=[
489+
vertexai_genai_types.evals.AgentEvent(
490+
author="user",
491+
content=genai_types.Content(
492+
parts=[genai_types.Part(text="Hi")],
493+
),
494+
),
495+
],
496+
)
497+
],
498+
)
499+
)
500+
]
501+
)
502+
],
503+
metadata=common_types.EvaluationRunMetadata(
504+
candidate_names=["candidate-1"]
505+
),
506+
)
507+
508+
payload = _transformers.t_inline_results([eval_result])
509+
assert len(payload) == 1
510+
511+
agent_data = payload[0]["request"]["prompt"]["agent_data"]
512+
agent_config = agent_data["agents"]["agent_0"]
513+
assert "tools" in agent_config
514+
tool = agent_config["tools"][0]
515+
# function_declarations should be preserved
516+
assert "function_declarations" in tool
517+
assert tool["function_declarations"][0]["name"] == "search"
518+
# Gemini-API-only fields must NOT be present (they would be None)
519+
assert "file_search" not in tool
520+
assert "mcp_servers" not in tool
521+
assert "google_search" not in tool
522+
assert "code_execution" not in tool
523+
444524
def test_t_inline_results_skips_error_agent_data_in_df(self):
445525
"""Tests that t_inline_results skips error agent_data from DataFrame."""
446526
error_json = json.dumps({"error": "Agent run failed"})

vertexai/_genai/_transformers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ def t_inline_results(
422422
if agent_data:
423423
if hasattr(agent_data, "model_dump"):
424424
prompt_payload["agent_data"] = _sanitize_agent_data(
425-
agent_data.model_dump()
425+
agent_data.model_dump(exclude_none=True)
426426
)
427427
elif isinstance(agent_data, dict):
428428
prompt_payload["agent_data"] = _sanitize_agent_data(agent_data)
@@ -442,7 +442,7 @@ def t_inline_results(
442442
if df_agent_data is not None:
443443
if hasattr(df_agent_data, "model_dump"):
444444
prompt_payload["agent_data"] = _sanitize_agent_data(
445-
df_agent_data.model_dump()
445+
df_agent_data.model_dump(exclude_none=True)
446446
)
447447
elif isinstance(df_agent_data, str):
448448
try:

0 commit comments

Comments
 (0)