2626from .common import EvalBaseModel
2727from .eval_case import get_all_tool_calls_with_responses
2828from .eval_case import IntermediateDataType
29+ from .eval_case import Invocation
30+ from .eval_case import InvocationEvents
2931from .eval_metrics import RubricScore
3032from .evaluator import EvalStatus
3133
@@ -44,8 +46,38 @@ class Label(enum.Enum):
4446
4547
4648def get_text_from_content (
47- content : Optional [genai_types .Content ],
49+ content : Optional [Union [genai_types .Content , Invocation ]],
50+ * ,
51+ include_intermediate_responses_in_final : bool = False ,
4852) -> Optional [str ]:
53+ """Extracts text from a `Content` or an `Invocation`.
54+
55+ When `content` is a `Content`, returns the concatenated text of its parts.
56+
57+ When `content` is an `Invocation`, returns the text of the invocation's final
58+ response. If `include_intermediate_responses_in_final` is True, text from
59+ intermediate invocation events (e.g. natural language emitted before tool
60+ calls) is concatenated with the final response text.
61+ """
62+ if isinstance (content , Invocation ):
63+ if not include_intermediate_responses_in_final :
64+ # Flag off: revert to basic plain-Content behavior.
65+ return get_text_from_content (content .final_response )
66+
67+ parts : list [str ] = []
68+ if isinstance (content .intermediate_data , InvocationEvents ):
69+ # Walk intermediate events in order; collect text parts.
70+ for event in content .intermediate_data .invocation_events :
71+ text = get_text_from_content (event .content )
72+ if text :
73+ parts .append (text )
74+ # Then fetch the final response text and append it to the end.
75+ final_text = get_text_from_content (content .final_response )
76+ if final_text :
77+ parts .append (final_text )
78+
79+ return "\n " .join (parts ) if parts else None
80+
4981 if content and content .parts :
5082 return "\n " .join ([p .text for p in content .parts if p .text ])
5183
0 commit comments