Skip to content

Commit 50dc51f

Browse files
committed
Trim ADK extraction casing fallbacks
Remove unreachable inner Role, Parts, and Text fallbacks from ADK request/response text extraction while preserving outer Contents/Content handling. Add focused coverage for outer PascalCase ADK payload objects with lower-case inner content fields. Validation: uv run pytest tests/test_extraction.py -k 'ExtractUserText or ExtractAgentResponse'; uv run pytest tests/test_extraction.py tests/test_converter.py
1 parent 603d845 commit 50dc51f

2 files changed

Lines changed: 26 additions & 10 deletions

File tree

src/agentevals/extraction.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,17 +71,17 @@ def extract_user_text_from_attrs(attrs: dict[str, Any]) -> str | None:
7171
if isinstance(llm_request, dict):
7272
contents = llm_request.get("contents", llm_request.get("Contents", []))
7373
for content_dict in reversed(contents):
74-
if content_dict.get("role", content_dict.get("Role")) != "user":
74+
if content_dict.get("role") != "user":
7575
continue
76-
parts = content_dict.get("parts", content_dict.get("Parts", []))
77-
text_parts = [p for p in parts if "text" in p or "Text" in p]
76+
parts = content_dict.get("parts", [])
77+
text_parts = [p for p in parts if "text" in p]
7878
if text_parts:
79-
return " ".join(p.get("text", p.get("Text", "")) for p in text_parts)
79+
return " ".join(p["text"] for p in text_parts)
8080
for content_dict in contents:
81-
if content_dict.get("role", content_dict.get("Role")) == "user":
82-
parts = content_dict.get("parts", content_dict.get("Parts", []))
81+
if content_dict.get("role") == "user":
82+
parts = content_dict.get("parts", [])
8383
if parts:
84-
return " ".join(p.get("text", p.get("Text", "")) for p in parts if "text" in p or "Text" in p)
84+
return " ".join(p.get("text", "") for p in parts if "text" in p)
8585

8686
messages_raw = attrs.get(OTEL_GENAI_INPUT_MESSAGES)
8787
if messages_raw:
@@ -104,10 +104,10 @@ def extract_agent_response_from_attrs(attrs: dict[str, Any]) -> str | None:
104104
if isinstance(llm_response, dict):
105105
content_dict = llm_response.get("content", llm_response.get("Content", {}))
106106
if content_dict:
107-
parts_dicts = content_dict.get("parts", content_dict.get("Parts", []))
108-
text_parts = [p for p in parts_dicts if "text" in p or "Text" in p]
107+
parts_dicts = content_dict.get("parts", [])
108+
text_parts = [p for p in parts_dicts if "text" in p]
109109
if text_parts:
110-
return " ".join(p.get("text", p.get("Text", "")) for p in text_parts)
110+
return " ".join(p["text"] for p in text_parts)
111111

112112
messages_raw = attrs.get(OTEL_GENAI_OUTPUT_MESSAGES)
113113
if messages_raw:

tests/test_extraction.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ def test_adk_llm_request_prefers_last_user(self):
107107
}
108108
assert extract_user_text_from_attrs(attrs) == "Second"
109109

110+
def test_adk_llm_request_outer_contents_pascalcase(self):
111+
attrs = {
112+
ADK_LLM_REQUEST: json.dumps(
113+
{
114+
"Contents": [
115+
{"role": "user", "parts": [{"text": "Outer PascalCase only"}]},
116+
]
117+
}
118+
)
119+
}
120+
assert extract_user_text_from_attrs(attrs) == "Outer PascalCase only"
121+
110122
def test_genai_content_based(self):
111123
attrs = {
112124
OTEL_GENAI_INPUT_MESSAGES: json.dumps(
@@ -170,6 +182,10 @@ def test_adk_llm_response(self):
170182
attrs = {ADK_LLM_RESPONSE: json.dumps({"content": {"parts": [{"text": "ADK response"}]}})}
171183
assert extract_agent_response_from_attrs(attrs) == "ADK response"
172184

185+
def test_adk_llm_response_outer_content_pascalcase(self):
186+
attrs = {ADK_LLM_RESPONSE: json.dumps({"Content": {"parts": [{"text": "Outer Content only"}]}})}
187+
assert extract_agent_response_from_attrs(attrs) == "Outer Content only"
188+
173189
def test_genai_content_based(self):
174190
attrs = {
175191
OTEL_GENAI_OUTPUT_MESSAGES: json.dumps(

0 commit comments

Comments
 (0)