Advanced Topics
Extending BackendConfig
BackendConfig is a Pydantic BaseModel and can be subclassed to add domain- or capability-specific fields to
an Inference Backend. The example below extends BackendConfig and sets the subclass as the
backend_config_model class attribute on a custom backend:
1from typing import Any, List
2
3from packflow import BackendConfig, InferenceBackend
4
5
6class CustomConfigModel(BackendConfig):
7 # New domain-specific fields with defaults
8 model_path: str = "./resources/model.joblib"
9
10 # Set fields without defaults so the backend cannot start without this provided
11 output_class_names: list[str]
12
13
14class CustomBackend(InferenceBackend):
15 backend_config_model = CustomConfigModel
16
17 def initialize(self):
18 self.logger.info(f"Loading model from {self.config.model_path}")
19 self.model = lambda x: x # Mocking loading of a model
20
21 def execute(self, inputs: Any) -> Any:
22 return self.model(inputs)
23
24 def transform_outputs(self, outputs: Any) -> List[dict]:
25 cleaned = []
26 for row in outputs:
27 cleaned.append(dict(zip(self.config.output_class_names, row)))
28 return cleaned
Config fields are accessed via the self.config instance attribute.
Note
BackendConfig subclasses are validated according to Pydantic’s validation rules. In the example above,
output_class_names has no default, so Pydantic treats it as required. Any instance of CustomBackend
must supply it — either as a keyword argument at instantiation time or via the backend_config: section of
packflow.yaml when loading through InferenceBackendLoader.from_project():
# Direct instantiation
backend = CustomBackend(output_class_names=["doubled"])
# Via packflow.yaml backend_config: + from_project()
# packflow.yaml:
# backend_config:
# output_class_names: [doubled]
backend = InferenceBackendLoader.from_project(".")
Configuration Sources
The InferenceBackend in Packflow loads and validates configurations in the following priority order (lowest to highest):
- Base Config defaults
Default values defined in
BackendConfigor a custom subclass.
backend_config:values frompackflow.yamlApplied only when a project is loaded via
InferenceBackendLoader.from_project(). Standalone loaders (LocalLoader,ModuleLoader) do not readpackflow.yamland skip this level entirely.
- Explicit keyword arguments passed at load time
Accepted by all loader methods (
.load(),from_project()). These always override both defaults and anybackend_config:values.
All configurations are validated through Pydantic at load time.
Configuring the Backend via packflow.yaml
Project-level backend configuration is specified in the backend_config: section of packflow.yaml.
These values are applied automatically when a project is loaded via InferenceBackendLoader.from_project(),
making them well-suited for deployment-time configuration that should not be hardcoded into the backend itself —
such as environment-specific field names, feature lists, or preprocessor settings.
For example, if the input field names differ between the training environment and production, the mapping can be
declared in packflow.yaml without modifying the Inference Backend code:
# === BACKEND CONFIG ===
backend_config:
feature_names:
- input_0
- input_1
from packflow.loaders import InferenceBackendLoader
backend = InferenceBackendLoader.from_project(".")
backend({"input_0": 1.0, "input_1": 2.0})
This approach also works with custom BackendConfig subclasses — any field defined on the subclass can be
supplied via backend_config: in the same way.
Creating Reusable Backends
An Inference Backend packaged as an installable Python module can be shared and loaded across multiple
projects using ModuleLoader or by setting loader: module in packflow.yaml. The backend_config:
section in each project’s packflow.yaml can then supply different configuration values to the same backend
without modifying its code. See the Packflow Loaders section for details.
Logging Configuration
Packflow uses the loguru library for logging and defaults to the INFO log level to minimize noise in production environments. The log level can be controlled via the PACKFLOW_LOG_LEVEL environment variable.
Setting the Log Level
To change the log level, set the PACKFLOW_LOG_LEVEL environment variable to one of the following values:
DEBUG: Detailed diagnostic information useful for troubleshootingINFO: General informational messages (default)WARNING: Warning messages for potentially problematic situationsERROR: Error messages for serious problemsCRITICAL: Critical messages for very serious errors
Example:
# Enable debug logging for detailed diagnostics
export PACKFLOW_LOG_LEVEL=DEBUG
python inference.py
# Use warning level to see only warnings and errors
export PACKFLOW_LOG_LEVEL=WARNING
python inference.py
Note
The verbose field in the BackendConfig controls whether execution metrics are logged during inference. This is separate from the overall log level and defaults to False. Set verbose=True to enable metrics logging.