diff --git a/src/google/adk/evaluation/simulation/per_turn_user_simulator_quality_v1.py b/src/google/adk/evaluation/simulation/per_turn_user_simulator_quality_v1.py index 239fa31a71..8d2a88dda4 100644 --- a/src/google/adk/evaluation/simulation/per_turn_user_simulator_quality_v1.py +++ b/src/google/adk/evaluation/simulation/per_turn_user_simulator_quality_v1.py @@ -302,9 +302,15 @@ def _evaluate_first_turn( eval_status=EvalStatus.NOT_EVALUATED, ) + user_text = get_text_from_content(first_invocation.user_content) + if user_text is None: + return PerInvocationResult( + actual_invocation=first_invocation, + eval_status=EvalStatus.NOT_EVALUATED, + ) + score = int( - get_text_from_content(first_invocation.user_content).strip() - == conversation_scenario.starting_prompt.strip() + user_text.strip() == conversation_scenario.starting_prompt.strip() ) return PerInvocationResult( actual_invocation=first_invocation, diff --git a/tests/unittests/evaluation/simulation/test_per_turn_user_simulation_quality_v1.py b/tests/unittests/evaluation/simulation/test_per_turn_user_simulation_quality_v1.py index be0a0394c5..296b9935c6 100644 --- a/tests/unittests/evaluation/simulation/test_per_turn_user_simulation_quality_v1.py +++ b/tests/unittests/evaluation/simulation/test_per_turn_user_simulation_quality_v1.py @@ -514,6 +514,32 @@ def test_evaluate_first_turn_failure(): assert result.eval_status == EvalStatus.FAILED +@pytest.mark.parametrize( + "user_content", + [ + types.Content(role="user", parts=[]), + types.Content(), + ], +) +def test_evaluate_first_turn_not_evaluated_when_user_content_has_no_text( + user_content, +): + """First turn with empty/None parts is not evaluated instead of crashing.""" + evaluator = _create_test_evaluator( + threshold=1.0, stop_signal="test stop signal" + ) + conversation_scenario = _create_test_conversation_scenario( + conversation_plan="plan", + starting_prompt="test starting prompt", + ) + invocation = Invocation(invocation_id="1", user_content=user_content) + + result = evaluator._evaluate_first_turn(invocation, conversation_scenario) + + assert result.score is None + assert result.eval_status == EvalStatus.NOT_EVALUATED + + def test_aggregate_conversation_results_all_pass_produces_pass(): evaluator = _create_test_evaluator() results = [