This is an automated email from the ASF dual-hosted git repository.

kaxil pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 24ff00e7d0b common-ai: Honour serialize_output=True on 
LLMFileAnalysisOperator (#67858)
24ff00e7d0b is described below

commit 24ff00e7d0b57abd03f3226f61e59217313973cb
Author: Kaxil Naik <[email protected]>
AuthorDate: Tue Jun 2 09:01:28 2026 +0100

    common-ai: Honour serialize_output=True on LLMFileAnalysisOperator (#67858)
---
 .../common/ai/operators/llm_file_analysis.py       |  9 +++++++
 .../common/ai/operators/test_llm_file_analysis.py  | 28 ++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git 
a/providers/common/ai/src/airflow/providers/common/ai/operators/llm_file_analysis.py
 
b/providers/common/ai/src/airflow/providers/common/ai/operators/llm_file_analysis.py
index 1b2bd9a912a..0c9d1df1bdd 100644
--- 
a/providers/common/ai/src/airflow/providers/common/ai/operators/llm_file_analysis.py
+++ 
b/providers/common/ai/src/airflow/providers/common/ai/operators/llm_file_analysis.py
@@ -21,6 +21,8 @@ from __future__ import annotations
 from collections.abc import Sequence
 from typing import TYPE_CHECKING, Any
 
+from pydantic import BaseModel
+
 from airflow.providers.common.ai.operators.llm import LLMOperator
 from airflow.providers.common.ai.utils.file_analysis import 
build_file_analysis_request
 from airflow.providers.common.ai.utils.logging import log_run_summary
@@ -139,6 +141,13 @@ class LLMFileAnalysisOperator(LLMOperator):
         if self.require_approval:
             self.defer_for_approval(context, output)  # type: ignore[misc]
 
+        if self._serialize_model_output and isinstance(output, BaseModel):
+            # Honour ``serialize_output=True`` and the older-Airflow fallback,
+            # matching ``LLMOperator.execute``. ``LLMFileAnalysisOperator``
+            # overrides ``execute`` rather than calling ``super().execute()``,
+            # so the dump step has to be repeated here.
+            output = output.model_dump()
+
         return output
 
     def _build_system_prompt(self) -> str:
diff --git 
a/providers/common/ai/tests/unit/common/ai/operators/test_llm_file_analysis.py 
b/providers/common/ai/tests/unit/common/ai/operators/test_llm_file_analysis.py
index bea72048a2a..7b32e27451d 100644
--- 
a/providers/common/ai/tests/unit/common/ai/operators/test_llm_file_analysis.py
+++ 
b/providers/common/ai/tests/unit/common/ai/operators/test_llm_file_analysis.py
@@ -146,6 +146,34 @@ class TestLLMFileAnalysisOperator:
         assert isinstance(result, Summary)
         assert result.findings == ["error spike"]
 
+    @patch("airflow.providers.common.ai.operators.llm.PydanticAIHook", 
autospec=True)
+    @patch(
+        
"airflow.providers.common.ai.operators.llm_file_analysis.build_file_analysis_request",
 autospec=True
+    )
+    def test_execute_serialize_output_returns_dict(self, mock_build_request, 
mock_hook_cls):
+        """serialize_output=True dumps the BaseModel to a dict on the wire."""
+        mock_build_request.return_value = FileAnalysisRequest(
+            user_content="prepared prompt",
+            resolved_paths=["/tmp/app.log"],
+            total_size_bytes=10,
+        )
+        mock_agent = MagicMock(spec=["run_sync"])
+        mock_agent.run_sync.return_value = 
_make_mock_run_result(Summary(findings=["error spike"]))
+        mock_hook_cls.get_hook.return_value.create_agent.return_value = 
mock_agent
+
+        op = LLMFileAnalysisOperator(
+            task_id="test",
+            prompt="Summarize the file",
+            llm_conn_id="my_llm",
+            file_path="/tmp/app.log",
+            output_type=Summary,
+            serialize_output=True,
+        )
+        result = op.execute(context={})
+
+        assert result == {"findings": ["error spike"]}
+        assert not isinstance(result, Summary)
+
     @patch(
         
"airflow.providers.common.ai.operators.llm_file_analysis.build_file_analysis_request",
 autospec=True
     )

Reply via email to