This is an automated email from the ASF dual-hosted git repository. kaxil pushed a commit to branch commonai-classifier-stable in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 81e4beaca77db4e8e5412c392b55cb927dc4d1ec Author: Kaxil Naik <[email protected]> AuthorDate: Wed Oct 14 09:59:50 2026 +0100 Graduate ClassifierRetryPolicy to stable in Common AI Its fallback order (fallback_policy, then fallback_rules, then the task's own retry settings) shipped and has not changed since, so the stated reason for keeping it experimental no longer holds. Only the typesafe extra stays experimental, because typesafe-sdk is pre-1.0. Also drop the stale experimental labels the Why Common AI page still carried for features that are already stable. --- providers/common/ai/docs/decision_models.rst | 5 +++-- providers/common/ai/docs/retry_policies.rst | 5 ----- providers/common/ai/docs/stability.rst | 16 +++++++++++--- providers/common/ai/docs/why_common_ai.rst | 25 ++++++++++------------ .../airflow/providers/common/ai/policies/retry.py | 10 --------- 5 files changed, 27 insertions(+), 34 deletions(-) diff --git a/providers/common/ai/docs/decision_models.rst b/providers/common/ai/docs/decision_models.rst index 337b306d1a6..8320806ffb5 100644 --- a/providers/common/ai/docs/decision_models.rst +++ b/providers/common/ai/docs/decision_models.rst @@ -20,8 +20,9 @@ Decision models .. note:: - Experimental: this can change or be removed in a minor release of this provider. - See :ref:`howto/stability`. + Experimental: the ``typesafe`` extra can change or be removed in a minor release of this + provider, because the ``typesafe-sdk`` it installs is before its 1.0 release. See + :ref:`howto/stability`. Every other model in this provider writes text. A decision model does not: you give it some text and a typed question, and it answers with a value from a set you named in diff --git a/providers/common/ai/docs/retry_policies.rst b/providers/common/ai/docs/retry_policies.rst index 686eb5c7e0f..5b19a1f2966 100644 --- a/providers/common/ai/docs/retry_policies.rst +++ b/providers/common/ai/docs/retry_policies.rst @@ -162,11 +162,6 @@ an attempt is a separate mechanism on the connection; see ClassifierRetryPolicy --------------------- -.. note:: - - Experimental: this can change or be removed in a minor release of this provider. - See :ref:`howto/stability`. - ``ClassifierRetryPolicy`` takes the retry decision away from the model. Its ``categories`` maps a category name to an :class:`~airflow.providers.common.ai.policies.retry.ErrorCategory`: what diff --git a/providers/common/ai/docs/stability.rst b/providers/common/ai/docs/stability.rst index abf65413ff2..70ce591b8cb 100644 --- a/providers/common/ai/docs/stability.rst +++ b/providers/common/ai/docs/stability.rst @@ -173,6 +173,17 @@ Pydantic AI toolsets, but the Pydantic AI class they inherit from can change. ``redact_exception=False`` or a custom ``redactor`` replaces the masking. If the model call fails, it falls back to ``fallback_rules`` and then to the task's own retry settings; it never fails the task itself. + * - :class:`~airflow.providers.common.ai.policies.retry.ClassifierRetryPolicy` and + :class:`~airflow.providers.common.ai.policies.retry.ErrorCategory` + - The model can only answer with one of the names in ``categories``, and that name's + ``ErrorCategory`` decides whether the task retries and after what ``delay``. + Without ``categories`` the policy uses + :data:`~airflow.providers.common.ai.policies.retry.DEFAULT_CATEGORIES`, whose seven + names and their retry or fail split stay the same. When the model call fails, or + ``min_confidence`` is set and the answer is under it or carries no confidence, the + policy uses the RETRY or FAIL of ``fallback_policy``, then ``fallback_rules``, then + the task's own retry settings. Secrets are masked in the exception text as for + ``LLMRetryPolicy``. * - Output review: ``require_approval``, ``enable_hitl_review`` and the review plugin - With ``require_approval=True``, the task defers after generating output and returns it only once a person approves it on the Required Actions page. A rejection, or a @@ -191,9 +202,8 @@ Everything this provider ships that is not in the table above is experimental. * - Feature - Why it is experimental - * - :class:`~airflow.providers.common.ai.policies.retry.ClassifierRetryPolicy` - (:doc:`decision_models`) - - What it does when the classifier is unsure or unavailable is changing. + * - The ``typesafe`` extra (:doc:`decision_models`) + - It installs ``typesafe-sdk``, which is before its 1.0 release. * - :class:`~airflow.providers.common.ai.policies.decision.DecisionPolicy`, and ``min_confidence`` on :class:`~airflow.providers.common.ai.policies.decision.BranchOption` diff --git a/providers/common/ai/docs/why_common_ai.rst b/providers/common/ai/docs/why_common_ai.rst index 992b54945fd..cfd3e7fa9f8 100644 --- a/providers/common/ai/docs/why_common_ai.rst +++ b/providers/common/ai/docs/why_common_ai.rst @@ -85,10 +85,9 @@ and a bucket of report files. What differs: - **The tools.** The hand-written ``query`` runs any SQL the model writes, including ``DELETE``, on any table the connection can reach, and returns every row it gets. ``SQLToolset`` allows only the ``orders`` table, rejects statements that write, and caps - the rows and bytes it returns. ``ObjectStorageToolset`` (experimental) keeps reads under - the prefix you gave it. Both run Airflow's secrets masker over results, which hides - values Airflow knows are secret, such as connection passwords, not personal data in your - tables. + the rows and bytes it returns. ``ObjectStorageToolset`` keeps reads under the prefix you + gave it. Both run Airflow's secrets masker over results, which hides values Airflow knows + are secret, such as connection passwords, not personal data in your tables. - **The model.** The plain task names a vendor in code and reads its key from the environment. ``AgentOperator`` takes both from a connection, so moving to another vendor or adding a fallback is a connection change. See :doc:`model_providers`. @@ -137,7 +136,7 @@ What a plain task leaves to you * - A person has to approve a tool call before it runs, such as a refund or a write to a production table. - A tool marked with Pydantic AI's approval API pauses ``AgentOperator`` before the - call, without holding a worker slot. Airflow 3.3 and later. Experimental. Not with + call, without holding a worker slot. Airflow 3.3 and later. Not with ``durable=True`` or ``enable_hitl_review=True``; with either, a tool marked for approval fails the task. - :doc:`tool_approval` @@ -150,10 +149,10 @@ What a plain task leaves to you - :doc:`hitl_review` * - The agent needs your databases, object storage or an API you already have a hook for. - - ``SQLToolset``, ``HookToolset`` and ``ObjectStorageToolset`` (experimental) build - tools from an Airflow connection, with table allow-lists, read-only SQL and size - limits. Results pass through Airflow's secrets masker before the model sees - them. They work in an agent you run yourself too. + - ``SQLToolset``, ``HookToolset`` and ``ObjectStorageToolset`` build tools from an + Airflow connection, with table allow-lists, read-only SQL and size limits. Results + pass through Airflow's secrets masker before the model sees them. They work in an + agent you run yourself too. - :doc:`toolsets/index` * - A model vendor is down. - ``fallback_conn_ids`` fails over to other connections in order. @@ -162,11 +161,10 @@ What a plain task leaves to you - The batch operator sends them through the OpenAI or Anthropic batch API at roughly half the per-token cost. A retry re-attaches to the batch already submitted if the prompts, model, output schema and connection are unchanged. - With ``deferrable=True`` the wait does not hold a worker slot. Experimental. + With ``deferrable=True`` the wait does not hold a worker slot. - :doc:`operators/llm_batch` The provider runs on Airflow 2.11 and later; a row that needs a newer Airflow says so. -Experimental features can change in a minor release; see :doc:`stability`. Decide whether a failed task retries ------------------------------------ @@ -187,9 +185,8 @@ When the task fails, the model reads the exception and decides whether to retry long to wait, so it can decide to wait out a rate limit and to fail a revoked credential at once. The exception text goes through the secrets masker before the model sees it, and ``fallback_rules`` decide when the model cannot be reached. ``ClassifierRetryPolicy`` -(experimental) has a cheaper model pick from categories you define, and can hand the -cases it is unsure of to an ``LLMRetryPolicy``. Both need Airflow 3.3 or later. See -:doc:`retry_policies`. +has a cheaper model pick from categories you define, and can hand the cases it is unsure +of to an ``LLMRetryPolicy``. Both need Airflow 3.3 or later. See :doc:`retry_policies`. When a plain task is enough --------------------------- diff --git a/providers/common/ai/src/airflow/providers/common/ai/policies/retry.py b/providers/common/ai/src/airflow/providers/common/ai/policies/retry.py index cccdfbe4593..bb72791d0e6 100644 --- a/providers/common/ai/src/airflow/providers/common/ai/policies/retry.py +++ b/providers/common/ai/src/airflow/providers/common/ai/policies/retry.py @@ -129,11 +129,6 @@ class ErrorCategory: """ One kind of failure a :class:`ClassifierRetryPolicy` may name, and what it does when it does. - .. note:: - - Experimental: this can change or be removed in a minor release of this provider. - See :ref:`howto/stability`. - The value of the policy's ``categories`` mapping, keyed by the category name the model answers with. @@ -459,11 +454,6 @@ class ClassifierRetryPolicy(_ModelRetryPolicy): """ Retry policy where the model names the kind of failure and the author's table decides. - .. note:: - - Experimental: this can change or be removed in a minor release of this provider. - See :ref:`howto/stability`. - The model's only job is to pick one of ``categories``; it reads each one's description from the output schema. Whether that category is retried, after how long, and how sure the model has to be all come from the :class:`ErrorCategory` in the worker process.
