v1
Model inference step v1.
Module
Submodules
- bitfount.steps.model_inference.v1.config - Config for the model inference step (v1).
- bitfount.steps.model_inference.v1.result - Result for the model inference step (v1).
- bitfount.steps.model_inference.v1.task - Prefect task for model inference (unified for fovea and GA models).
Functions
task_fn
async def task_fn( datasource: BaseSource, model_resource: ModelResourceProtocol, config: ModelInferenceConfig, schema: BitfountSchema, datastructure: DataStructure, cache: CacheProtocol, task_hash: str, project_id: str, run_id: str | None = None, lifecycle_notifier: LifecycleNotifier | None = None,) ‑> ModelInferenceResult:Run model inference on the datasource and persist results to cache.
RAW inference results are written directly to the model_inferences cache
table via bulk_insert_inference_results — no postprocessing is applied
here. Postprocessing is format-specific to each consumer, so it runs
just-in-time inside the downstream calc step (see bitfount.preprocessing)
rather than at cache time. Caching the raw output lets any task on the same
datasource share these rows regardless of how it later postprocesses them.
Downstream interactive steps access the rows through a CacheAccessor
(<step_name>.cache) rather than receiving an in-memory DataFrame.
Arguments
datasource: The datasource to run inference on.model_resource: Model resource used to load the model.config: Model inference configuration (model ref, version, batch size).schema: Datasource schema.datastructure: Datasource data structure.cache: Cache instance to persist inference results into.task_hash: Pipeline task hash identifying this run; used as the partition key in themodel_inferencestable.project_id: Provenance only — the project that triggered this run. NOT part of the cache key: rows are keyed by(task_hash, model_ref, model_version, file_id)so two projects on the same datasource share them.run_id: The run_id for this phase of execution.lifecycle_notifier: Optional notifier used to signal the batch count (NUMBER_OF_BATCHES) and per-batch ids (CURRENT_BATCH_ID) to the task initiator. EachCURRENT_BATCH_ID(n)is sent right before the n-th file chunk is inferred (mirroring the v8 worker batch loop), so the ids track actual progress. The phase-4 marker (PREPARING_DATA_BATCHES) and the batches-complete boundary are emitted once per DAG by the executor, not here.None(the default) disables signalling — e.g. background runs, which have no initiator mailbox.
Returns
ModelInferenceResult with the number of records stored.
Classes
Config
class Config(**data: Any):Config for model inference (fovea or GA).
batch_size is optional and defaults to DEFAULT_INFERENCE_BATCH_SIZE
(1) when unset — see resolved_batch_size. The remaining fields are
required and provided by the YAML template.
Note: this step caches RAW model output. Format-specific postprocessing is
applied just-in-time inside the consuming calc step (see
bitfount.preprocessing), so there is no postprocessors field here.
Create a new model by parsing and validating input data from keyword arguments.
Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be
validated to form a valid model.
self is explicitly positional-only to allow self as a field name.
Variables
- static
batch_size : int | None
- static
model_config
- static
model_ref : str
- static
model_username : str
- static
model_version : int
-
resolved_batch_size : int- Effective batch size, defaulting to 1 whenbatch_sizeis unset.1 is safe for every model; see
DEFAULT_INFERENCE_BATCH_SIZE.
Methods
get_model_ref
def get_model_ref(self) ‑> ModelInferenceConfig:Return self — the config already contains all model ref fields.
This method exists for backward compatibility with code that
previously used BitfountModelRef.
Result
class Result(**data: Any):Result of a model inference task.
records_stored reports how many inference rows were persisted to the
cache, except on the all-cached skip: with nothing left to infer the task
persists nothing and reports the number of selected files instead, every
one of which already has a row (see model_inference_task).
The predictions DataFrame itself is not returned directly — it must be
accessed via the records property (same-process only) or, in a DAG
pipeline across Prefect task boundaries, via the <step_name>.cache
accessor.
Create a new model by parsing and validating input data from keyword arguments.
Raises [ValidationError][pydantic_core.ValidationError] if the input data cannot be
validated to form a valid model.
self is explicitly positional-only to allow self as a field name.
Ancestors
Variables
- static
model_config
cache : CacheAccessor | None- Return theCacheAccessorfor reading this result in a DAG pipeline.
-
records : pandas.core.frame.DataFrame- Retrieve this result's rows as a DataFrame.The DataFrame is fetched from the cache on each access — it is not stored in the result object, allowing lazy access to large datasets without materialising them in memory until needed.
Returns: A
pandas.DataFramewith one row per cached record.Raises: RuntimeError: If no accessor is attached (e.g. the result was serialised across a Prefect task boundary). In a DAG pipeline use
<step_name>.cacheinstead.
Static methods
from_accessor
def from_accessor( accessor: CacheAccessor, *, records_stored: int | None = None,) ‑> Self:Inherited from:
CacheBackedResult.from_accessor :
Build a result carrying accessor, in one call rather than two.
_accessor is a PrivateAttr, so it cannot be passed to the
constructor and every producer would otherwise construct the result and
then reach in to attach the accessor. That two-step is the shape this
replaces.
Arguments
accessor: TheCacheAccessorbacking<step>.cache, scoped to the partition this result stands for.records_stored: Rows this result stands for. Defaults toaccessor.count()— the whole partition — which is what a step that persisted nothing this run reports. A step that wrote rows passes what it wrote; see the field's docstring for why the two are not interchangeable.
Returns An instance of the calling subclass, with the accessor attached.
Methods
model_post_init
def model_post_init(self: BaseModel, context: Any, /) ‑> None:Inherited from:
CacheBackedResult.model_post_init :
This function is meant to behave like a BaseModel method to initialise private attributes.
It takes context as an argument since that's what pydantic-core passes when calling it.
Arguments
self: The BaseModel instance.context: The context.