Lee-W commented on code in PR #71051:
URL: https://github.com/apache/airflow/pull/71051#discussion_r3757025366
##########
providers/common/ai/src/airflow/providers/common/ai/operators/llm_schema_compare.py:
##########
@@ -313,8 +324,32 @@ def execute(self, context: Context) -> dict[str, Any]:
self.log.info("Running LLM schema comparison...")
result = agent.run_sync(self.prompt, usage_limits=self.usage_limits)
log_run_summary(self.log, result)
+ output = result.output
- output_result = result.output.model_dump()
+ output_result = output.model_dump()
self.log.info("Schema comparison result: \n %s",
json.dumps(output_result, indent=2))
+ if self.require_approval:
+ severity_counts = Counter(mismatch.severity for mismatch in
output.mismatches)
+ summary = ", ".join(
+ f"{severity_counts[severity]} {severity}"
+ for severity in ("critical", "warning", "info")
+ if severity_counts[severity]
+ )
+ body = (
+ f"Compatible: {output.compatible}"
+ + (f" (mismatches: {summary})" if summary else "")
+ + f"\n\n```\nPrompt:
{self.prompt}\n\n{output.model_dump_json(indent=2)}\n```"
Review Comment:
```suggestion
+ (
"\n\n```\n"
f"Prompt: {self.prompt}\n\n"
f"{output.model_dump_json(indent=2)}\n'
"```"
)
```
easier to understand what this if
##########
providers/common/ai/tests/unit/common/ai/operators/test_llm_schema_compare.py:
##########
@@ -16,20 +16,36 @@
# under the License.
from __future__ import annotations
+import json
from unittest import mock
from unittest.mock import MagicMock
+from uuid import uuid4
import pytest
from airflow.providers.common.ai.operators.llm_schema_compare import (
LLMSchemaCompareOperator,
SchemaCompareResult,
+ SchemaMismatch,
)
-from airflow.providers.common.compat.sdk import
AirflowOptionalProviderFeatureException
+from airflow.providers.common.compat.sdk import
AirflowOptionalProviderFeatureException, TaskDeferred
from airflow.providers.common.sql.config import DataSourceConfig
from airflow.providers.common.sql.datafusion.engine import DataFusionEngine
from airflow.providers.common.sql.hooks.sql import DbApiHook
+from tests_common.test_utils.version_compat import AIRFLOW_V_3_1_PLUS,
AIRFLOW_V_3_3_PLUS
+
+if AIRFLOW_V_3_3_PLUS:
+ from airflow.sdk.exceptions import TaskAwaitingInput as ApprovalPauseSignal
Review Comment:
Why do we need alias here
##########
providers/common/ai/src/airflow/providers/common/ai/example_dags/example_llm_schema_compare.py:
##########
@@ -105,6 +105,27 @@ def check_migration_readiness(ds=None):
example_llm_schema_compare_decorator()
+# [START howto_operator_llm_schema_compare_approval]
+@dag(tags=["example"])
+def example_llm_schema_compare_approval():
+ from datetime import timedelta
Review Comment:
I think we can move it to the top
##########
providers/common/ai/src/airflow/providers/common/ai/operators/llm_schema_compare.py:
##########
@@ -313,8 +324,32 @@ def execute(self, context: Context) -> dict[str, Any]:
self.log.info("Running LLM schema comparison...")
result = agent.run_sync(self.prompt, usage_limits=self.usage_limits)
log_run_summary(self.log, result)
+ output = result.output
- output_result = result.output.model_dump()
+ output_result = output.model_dump()
self.log.info("Schema comparison result: \n %s",
json.dumps(output_result, indent=2))
+ if self.require_approval:
+ severity_counts = Counter(mismatch.severity for mismatch in
output.mismatches)
+ summary = ", ".join(
+ f"{severity_counts[severity]} {severity}"
+ for severity in ("critical", "warning", "info")
+ if severity_counts[severity]
+ )
+ body = (
+ f"Compatible: {output.compatible}"
+ + (f" (mismatches: {summary})" if summary else "")
+ + f"\n\n```\nPrompt:
{self.prompt}\n\n{output.model_dump_json(indent=2)}\n```"
+ )
+ self.defer_for_approval(context, output, body=body) # type:
ignore[misc]
+
return output_result
+
+ def execute_complete(self, context: Context, generated_output: str, event:
dict[str, Any]) -> Any:
+ output = super().execute_complete(context, generated_output, event)
+ if not isinstance(output, dict):
Review Comment:
we only check ths type here. how do we know whether it's a valid
SchemaCompareResult JSON or not?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]