Prediction output
model.predict(...) returns a pyarrow.Table. Before application postprocessing, each row represents one processed observation. Named fields form Arrow structs; repeated records form list<struct<...>> collections. For the transaction tutorial, read the transaction dispute predictions under predictions.trxns[i].disputed. Read predictions walks through one record; this page is the complete contract.
Continue with the trained transaction-history model. The request keeps the transaction inputs and omits disputed from every record:
payment_id: payment-42
trxns:
- booked_at: "2026-05-21T10:00:00"
amount: 32.00
merchant: Station Cafe
- booked_at: "2026-05-27T18:15:00"
amount: 56.20
merchant: North Market
- booked_at: "2026-05-28T14:30:00"
amount: 84.50
merchant: North Marketimport relflow as rf
# The model is trained; the application supplies the request file.
requests = rf.ArrowDataModule(
predict="payments/requests.parquet",
retain=("payment_id",),
)
result = model.predict(datamodule=requests, batch_size=256, devices=1)devices=1 collects the result on one device. For large outputs, use a Writer to persist batches as they complete.
Read a field
Use ordinary child names in the output tree. Slash-prefixed schema addresses remain identifiers for model configuration and metrics; they are not literal prediction field names.
Inspect one nonempty result row to read its transaction probabilities:
observation = result.slice(0, 1).to_pylist()[0]
transactions = observation["predictions"]["trxns"]
probabilities = [
transaction["disputed"]["content"]["probability"]
for transaction in transactions
]One output record has this shape. Earlier leaf payloads are abbreviated to their inferred flags; angle-bracket values are placeholders:
inputs:
payment_id: payment-42
predictions:
trxns:
- disputed:
inferred: true
- disputed:
inferred: true
- disputed:
state:
valued: <probability>
"null": <probability>
padded: <probability>
masked: <probability>
other: <probability>
content:
probability: <probability of true>
inferred: truestate gives probabilities for the five value states. Each datatype owns its content. inferred marks requested reconstruction, not confidence. Boolean returns a probability; choosing a Boolean decision threshold belongs to the application.
Every retained transaction has a requested dispute prediction, marked inferred: true. The training labels were hidden by mask=True; prediction requests can omit those labels entirely.
What appears in output
Only selected output columns appear:
| Column | Present when |
|---|---|
inputs |
retain selects processed source columns. |
predictions |
At least one selected field has a decoded public payload. |
representations |
At least one node has embed=True. |
An embeddings-only model returns representations without an empty predictions struct. A model with no decoded public output and no requested embeddings raises an error when planning prediction. Visible input fields are not automatically echoed.
Rich leaf payloads keep their datatype-specific structure:
| Field type | Decoded output |
|---|---|
Boolean |
content.probability: probability of True |
Number |
content: floating-point reconstruction |
Quantile |
content: reconstruction in source units; null before learning a distribution |
Vector |
content: fixed-width float list |
Category, Enum |
content.value, content.probability, content.topk |
Set |
content: list of value/probability candidates |
Cluster |
cluster.value, cluster.probability, plus content value/probability |
Text, Hash, DateParts |
No decoded public value; embeddings can be requested |
Number and Quantile use the units supplied after preprocessing. Quantile clips its inverse transformation to its learned range. Vector writes zeros where the most likely state is not valued. Reverse application-specific unit transforms in a postprocessor.
Category, Enum, and Set labels are Arrow large_string values. Top-k and Set candidates are lists of structs pairing each value with its probability. Category and Enum retain topk even when empty. A Set threshold can change candidate counts without changing the schema.
Repeated coordinates
All repeated record collections use variable Arrow lists, including Branch(length=1) and other finite limits. length caps retained input; it does not pad public output to the cap. The root is a struct with no singleton observation list.
A sequence can also contain a structural hole. This abbreviated illustration preserves that position while predicting every valid transaction:
predictions:
trxns:
- disputed:
content: {probability: 0.12}
inferred: true
- null
- disputed:
content: {probability: 0.04}
inferred: trueThis illustration omits state; each nonnull leaf still includes it. Sibling predictions share one transaction record and one set of list offsets. A missing leaf does not remove its record.
| Canonical collection | Output collection |
|---|---|
null |
null |
[] |
[] |
[null] |
[null] |
| A valid record with missing fields | A valid result record at the same position |
Record validity follows branch geometry, not predicted value-state probabilities. Positions follow preprocessing, structural queries, and configured overflow. They can differ from untouched source indices retained under inputs. Preserve application item identifiers when joining them back. Types, lengths, and structural validity remain stable across execution batch widths. Fixed-width vectors retain their feature-width axis.
Representations
embed=True writes L2-normalized float32 vectors in a separate representations list. Each representation record has:
| Field | Meaning |
|---|---|
path |
Field-name segments; [] identifies the anonymous root. |
parents |
Item ordinals for repeated ancestors, outermost first. |
output_index |
The representation’s intrinsic output index at that site. |
embedding |
A fixed-size float32 list of model width. |
A history summary uses path=[trxns], parents=[]. A leaf embedding on its third transaction uses path=[trxns, merchant], parents=[2]. Branch summaries have their own output counts; they are not repeated once for each child record. Pass-through reductions preserve their routed output stream, including defined zero slots, rather than inventing source-token identities. Their output_index numbers tokens item-major: each item owns one contiguous block holding its leaf tokens and then its child-branch tokens in field order. See Reusable representations for extraction and nested examples.
Retain source columns
retain selects processed top-level columns copied into an inputs struct:
| Argument | Retained inputs |
|---|---|
retain=() |
No inputs column |
retain=("payment_id",) |
That column only |
retain="*" |
All processed source columns |
Retention changes output selection, not model inputs. Missing retained columns raise an error. Retain a business key to identify rows across distributed shards; RelFlow does not invent an application identity or promise global shard order.
Batch direct requests
The direct API accepts Arrow tables and record batches, plus a nonempty sequence of mappings for small interactive requests. Use a typed Arrow object for empty input: the planned output schema is preserved without a forward pass. Put file paths on a data module’s predict split.
A positive direct batch_size preprocesses the full input once, chunks processed Arrow rows before encoding, combines output tables, and postprocesses once. It also updates the model’s current batch size. Omitting the override, or using None, preserves whole-input direct execution. File-backed data modules and Batch inference provide streaming input/output.
Files and HTTP
Direct prediction, batch writing, and successful HTTP results use the same selected columns. JSON renders their records; Arrow HTTP writes their schema through IPC. Postprocessors can deliberately define an application-specific response at the table boundary.
Arrow schema metadata records the model’s recorded package version under relflow.model_version, and HTTP mirrors it in a header. This value does not uniquely identify a checkpoint. See Serving for error responses and request-order requirements.
rf.Writer requires an exact stable schema and metadata across batches. Its Parquet guard rejects fixed-size lists beneath null containers: PyArrow 24 cannot restore these reliably. This includes Vector output beneath a null record, or retained source vectors with null parents. Use Arrow IPC for those tables; the writer does not silently erase structural nulls or change vectors to variable lists. Ordinary nullable vector components inside a nonnull vector remain supported. See Batch inference.