airflow.providers.common.ai.batch.base¶
Provider-agnostic types and the adapter contract for @task.llm_batch.
This module must never import a provider SDK (openai, anthropic, …):
batch/dispatch.py and the provider-yaml validation check import every
registered module, so a top-level SDK import here would make them fail in any
environment without that SDK installed.
Attributes¶
Classes¶
One input item for |
|
Returned by |
|
The current status of a provider-native batch, as returned by |
|
One provider-native per-request result, before output extraction or validation. |
|
The provider-agnostic shape adapters translate their native response into. |
|
Adapter contract between the common.ai batch surface and one provider's batch API. |
Functions¶
|
Reduce a per-status count breakdown to a single terminal reason. |
Module Contents¶
- class airflow.providers.common.ai.batch.base.BatchRequest[source]¶
Bases:
TypedDictOne input item for
@task.llm_batch.A bare string
"foo"is shorthand for{"prompt": "foo"}; the operator normalizes to this shape before anything else sees the input.
- class airflow.providers.common.ai.batch.base.SubmitResult[source]¶
Returned by
BatchAdapter.submit()once the provider has accepted the batch.
- class airflow.providers.common.ai.batch.base.BatchState[source]¶
The current status of a provider-native batch, as returned by
BatchAdapter.get_batch().
- class airflow.providers.common.ai.batch.base.RawResultItem[source]¶
One provider-native per-request result, before output extraction or validation.
iter_resultsyields these keyed by position (index), parsed back out of thecustom_ideach adapter wrote at submit time (f"{key16}-{index}").rawis opaque here; only the adapter’s ownBatchAdapter.extract_output()knows how to read it.provider_statuskeeps"expired"and"cancelled"distinct from"errored": both providers report per-item expiry (Anthropic as a result type, OpenAI as an error-file line with codebatch_expired), and folding it into"errored"would make an SLA lapse indistinguishable from a rate limit or a bad request.- error: collections.abc.Mapping[str, Any] | None[source]¶
- class airflow.providers.common.ai.batch.base.ExtractedOutput[source]¶
The provider-agnostic shape adapters translate their native response into.
extract_outputpicks exactly onekind:"text": plain-text output (output_type is str);textset."json_text": a JSON document as a string that still needs parsing (e.g. OpenAI’sresponse_formatcontent);textset."json_value": an already-parsed JSON-native value (e.g. Anthropic’s tool-useinput, which arrives as a dict);valueset."absent": the model did not produce structured output at all (e.g. notool_useblock came back even though one was requested);textmay still carry leftover plain-text content for diagnostics.
- class airflow.providers.common.ai.batch.base.BatchAdapter(*, api_key=None, base_url=None, client=None)[source]¶
Bases:
abc.ABCAdapter contract between the common.ai batch surface and one provider’s batch API.
batch/dispatch.pyselects a concrete subclass by themodel_idprefix (request shape) and checks the connection type againstconn_types(auth). Operator, trigger, and the state/results layers depend on this interface only, so another package can register its own adapter (seeregister_adapter()) without touching them.- abstract validate_requests(requests, *, model, output_spec, idempotency_key, **kwargs)[source]¶
Reject an over-limit or otherwise invalid batch before any network call.
Must check
len(requests)againstmax_requestsand the serialized request size (including the per-request output directive built fromoutput_spec, which a large schema repeats in every request) againstmax_payload_bytes, and callcheck_custom_id_length(). Raise a subclass ofLLMBatchInputErrornaming the limit, the actual count/size, and the.expand()remedy.**kwargscarries the same batch-level request-building context assubmit()(system_prompt,max_tokens,request_params) so the serialized-size estimate matches whatsubmitsends.
- abstract submit(requests, *, model, idempotency_key, input_fingerprint, output_spec, **kwargs)[source]¶
Upload/submit the batch and return the provider’s batch id.
Where the provider offers batch-level metadata (OpenAI), record both
idempotency_keyandinput_fingerprintthere sofind_orphaned_batch()can read them back. The key alone identifies the task instance, not this submission of it: it is stable across acleareven when the prompts changed.
- abstract get_batch(batch_id)[source]¶
Return the current status of a submitted batch. Synchronous; the trigger wraps it in
to_thread.
- abstract iter_results(batch_id)[source]¶
Return (not
yield) a streaming iterator of per-request results.Returning a plain iterator rather than using
yieldin this method makes an invalidbatch_id(or any other call-time failure) raise immediately, instead of only once the caller starts iterating.
- abstract build_output_directive(spec)[source]¶
Translate
spec.json_schemainto this provider’s structured-output request fields.Returns
{}whenspec.is_structuredisFalse. The result is merged into every request’s body/params by the adapter itself.
- abstract extract_output(raw, spec)[source]¶
Pull the model’s output out of a provider-native result, in the shape
ExtractedOutputdescribes.
- abstract find_orphaned_batch(idempotency_key, input_fingerprint, not_before)[source]¶
Best-effort recovery of a batch whose submit response was never recorded.
Return the provider’s batch id if a batch exists whose recorded
idempotency_keyandinput_fingerprintboth match and which was created at or afternot_before(an ISO 8601 timestamp, the intent record’s own write time); prefer the most recently created candidate. All three conditions are needed: the key is stable across aclearwith different prompts, and an unordered listing could otherwise return an older submission of identical content.Return
Noneif nothing matches. An adapter with no way to correlate an orphan back to a batch must returnNoneunconditionally and say so in its docstring. Raise if the lookup itself failed (network, auth); the operator treats that as “unknown”, never as “absent”.
- close()[source]¶
Release the underlying SDK client’s connection pool.
The default closes
self._clientif the adapter set one and it has aclose()method, which both the OpenAI and Anthropic clients do. Callers wrap adapter use intry/finallyso the pool is freed deterministically rather than by garbage collection.
- resolve_request_model(request_model, *, default_bare_model, request_index)[source]¶
Resolve a per-request
modeloverride to this adapter’s bare model name.request_modelmust beNone(inherit the batch-level default, already bare) or a"<provider>:<model>"string whose prefix equalsname. A request naming a different provider is rejected before any network call rather than sent to the wrong provider’s model namespace.
- check_custom_id_length(idempotency_key, request_count, *, max_length=64)[source]¶
Reject a batch whose worst-case
custom_idwould exceedmax_length.Anthropic documents
custom_idas^[a-zA-Z0-9_-]{1,64}$. A 16-character key plus a separator plus a 5-digit index is at most 22 characters, so this is not reachable today; it exists so a future change to the key length ormax_requestsfails clearly before submit instead of producing an invalidcustom_id.
- airflow.providers.common.ai.batch.base.evaluate_batch_counts(counts)[source]¶
Reduce a per-status count breakdown to a single terminal reason.
Shared by the trigger (provider-reported counts) and the results layer’s manifest assembly (the full breakdown, including
invalid_outputandmissing) so both describe “some requests did not produce a usable result” the same way.