Skip to content

babelfin

package babelfin

provisional (not yet in the spec) G-DATA-07 is in the gate registry but not yet in the specification’s gate catalogue, so it is not normative.

Babelfin: the analyst-facing Python API for UMP.

import babelfin as fin
roi = fin.estimand("roi", channels=["tv", "search"], weeks=104)
tv = fin.number(1.37, (1.26, 1.50), roi)
fin.compare(tv, test_number)

Everything here wraps ump_spec; each result exposes the underlying model as .spec.

Read the babelfin guide first for the main entry points.

class

class Alignment

The G-EST-02 ladder’s answer for two numbers or estimands. spec is the AlignmentResult.

Methods and properties (9)

init constructor

Alignment(self, spec: AlignmentResult, comparison: EstimandComparison) -> None

rung property

rung: str

match, converter, re_ask, assumed_alignment or side_by_side.

combinable property

combinable: bool

mismatched property

mismatched: list[str]

interval property

interval: Interval | None

fallback property

fallback: FallbackEntry | None

reason property

reason: str

to_frame method

def to_frame(self) -> pd.DataFrame

One row per field that differs.

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_numbers.py, line 124

class

class Allocation

Current and optimal spend per channel, each optimal spend with its interval across draws.

Fields

NameTypeDefaultDescription
rawrows
Methods and properties (2)

init constructor

Allocation(self, rows: list[dict[str, Any]]) -> None

to_frame method

def to_frame(self) -> pd.DataFrame

Source: packages/babelfin/src/babelfin/_apps.py, line 197

class

class AppModel

A model as the models app describes it: plain status, estimand in words, acceptance, use label.

Methods and properties (11)

init constructor

AppModel(self, app: Models, raw: dict[str, Any]) -> None

id property

id: str

title property

title: str

tier property

tier: str

acceptance property

acceptance: str

passed, untested, pilot or failed (untested is usable with reduced trust; failed is excluded).

use_label property

use_label: str

dependence property

dependence: str

estimand property

estimand: str

What the model’s headline number means, in words.

plain property

plain: str

client property

client: str | None

curves method

def curves(self, level: float = 0.9) -> Curves

Source: packages/babelfin/src/babelfin/_apps.py, line 118

class

class Artifact

A handle on one artifact in ump-core. Methods update the handle and return it, so calls chain.

Fields

NameTypeDefaultDescription
envelopeenvelope
approval_leafint | NoneNone
Methods and properties (14)

init constructor

Artifact(self, session: Session, envelope: dict[str, Any]) -> None

id property

id: str

kind property

kind: str

state property

state: str

client property

client: str | None

doc property

doc: dict[str, Any]

fallbacks property

fallbacks: Fallbacks

The fallbacks from the latest checks: what an approver must accept by name.

gates property

gates: GateReport

refresh method

def refresh(self) -> Artifact

submit method

def submit(self, reason: str | None = None) -> Artifact

Run the checks and, when nothing stops, move to awaiting approval.

approve method

def approve(
self,
accept: Iterable[FallbackEntry | str] | None = None,
comment: str | None = None,
) -> Artifact

Sign as this session’s principal. accept must name every fallback on the artifact (art.fallbacks, the FallbackEntry objects, or "gate:code" strings); otherwise fin.UnacknowledgedFallbacks is raised before anything is sent. G-INT-02 refuses an approver who owns, submitted or wrote the work.

reject method

def reject(self, comment: str) -> Artifact

Reject with a reason (core requires one); nothing is accepted.

proof method

def proof(self) -> LogProof

Fetch this artifact’s latest log leaf and the signed checkpoint, and check them here.

lineage method

def lineage(self, upstream: bool = True, depth: int | str = 'all') -> Lineage

Source: packages/babelfin/src/babelfin/_session.py, line 134

class

class ClientView

The console’s view of one client: returns per channel (with intervals), alerts, raw.

Fields

NameTypeDefaultDescription
rawraw
namestrstr(raw.get('client') or raw.get('client_id') or '')
alertslist[dict[str, Any]]list(raw.get('alerts') or [])
Methods and properties (2)

init constructor

ClientView(self, raw: dict[str, Any]) -> None

returns property

returns: pd.DataFrame

Source: packages/babelfin/src/babelfin/_apps.py, line 338

class

class Contract

A workflow’s input contract. .spec is the ump_spec InputContract.

Fields

NameTypeDefaultDescription
specspec
Methods and properties (8)

init constructor

Contract(self, spec: InputContract) -> None

from_frame classmethod

def from_frame(
cls,
df: pd.DataFrame,
*,
time: str | None,
target: str | None,
freq: str | None = None,
categories: dict[str, DimPolicy] | list[str] | None = None,
extra: Literal['allow', 'drop'] = 'drop',
min_rows: int | None = None,
) -> Contract

Infer a contract from a training frame: every non-time, non-target, non-category column is a required variable with the frame’s dtype (missing: forbid unless it already has nulls). categories maps a column to its policy (a list means fixed); when None, string columns are fixed categories. Fixed categories get their level set (hash and count). freq is inferred from the time column when not given.

load classmethod

def load(cls, path: str | Path) -> Contract

save method

def save(self, path: str | Path) -> Path

to_dict method

def to_dict(self) -> dict[str, Any]

key property

key: list[str]

profile method

def profile(self, df: pd.DataFrame) -> FrameProfile

What check_input reads about df: no row values, only dtypes, counts and hashes.

check method

def check(
self,
df: pd.DataFrame,
*,
mode: InputMode = 'score',
history_end: str | None = None,
trained_rows: int | None = None,
) -> InputCheck

Check df against the contract (ump_spec.rules.check_input). history_end (ISO date) checks a score follows on from the saved history; trained_rows notes growth on a refit.

Source: packages/babelfin/src/babelfin/_contract.py, line 107

class

class Curves

Response curves on a spend grid with their band. rung and origin say which fallback-ladder rung produced them; raw is the app’s JSON.

Fields

NameTypeDefaultDescription
channelslist[str]list(c['channels'])
drawsnp.asarray(c['draws'], dtype=float)
rungstrraw.get('ladder', {}).get('step', '')
originstrraw.get('source', {}).get('origin', '')
pseudo_drawsboolbool(raw.get('pseudo_draws'))
Methods and properties (5)

init constructor

Curves(self, raw: dict[str, Any], level: float = 0.9) -> None

n_draws property

n_draws: int

band property

band: str

How the band is drawn: quantiles at level with enough real draws, else min to max across draws.

to_frame method

def to_frame(self) -> pd.DataFrame

Long form: one row per channel and grid point with spend, lo, median, hi.

plot method

def plot(self, scale: float = 1000000.0, unit: str = '$M') -> Figure

One panel per channel: the band, the median and a dotted line at current spend (needs matplotlib).

Source: packages/babelfin/src/babelfin/_apps.py, line 59

class

class Error(Exception)

Base class: code is the UMP note or error code, gate the gate that raised it (if any).

Methods and properties (1)

init constructor

Error(self, code: str, detail: str, *, gate: str | None = None) -> None

Source: packages/babelfin/src/babelfin/_errors.py, line 16

class

class Estimand

What a number means: the seven UMP fields plus scope. spec is the ump_spec model.

Fields

NameTypeDefaultDescription
specspec
Methods and properties (5)

init constructor

Estimand(self, spec: SpecEstimand) -> None

words property

words: str

registry_id property

registry_id: str | None

to_dict method

def to_dict(self) -> dict[str, Any]

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_estimand.py, line 51

class

class Fallbacks(list[FallbackEntry])

The fallbacks a check applied: what was assumed and how the numbers moved. A list, plus to_frame.

Methods and properties (2)

to_frame method

def to_frame(self) -> pd.DataFrame

keys property

keys: list[str]

gate:code for each, the form an approver acknowledges.

Source: packages/babelfin/src/babelfin/_gates.py, line 39

class

class FittedWorkflow

A workflow fitted in this session. .model is what the module’s fit returned.

Methods and properties (9)

init constructor

FittedWorkflow(
self,
workflow: Workflow,
module: ModuleType,
model: Any,
*,
data: pd.DataFrame,
prepped: pd.DataFrame,
check: InputCheck,
) -> None

answers method

def answers(
self,
df: pd.DataFrame | None = None,
*,
inputs: dict[str, Any] | None = None,
) -> dict[str, Number]

{question: fin.Number} on the training data, or on df (checked against the contract, cleaned and prepped first) from this fitted model. inputs binds the prep recipe’s other inputs (df binds its first), as in fit and run.

answer method

def answer(self, name: str) -> Number

summary_model method

def summary_model(self) -> Model

The fit-time answers as a Tier D fin.Model (Model.from_table): the bundle’s summary.json and the fallback rung when its code cannot run. Questions without a summary number are left out.

check method

def check(
self,
*,
at: str = 'submit',
strict: bool | str | list[str] = False,
) -> GateReport

The gates on the answers’ model (the Tier D summary a bundle carries), as Model.check.

save method

def save(
self,
path: str | Path,
*,
include_data: bool = False,
version: str = '0.1.0',
author: str | None = None,
) -> Path

Write the workflow as a bundle folder at path (which must not exist): source, plain fitted state, contract, prep recipe, questions and the Tier D summary, every file hashed. The state must round-trip (from_state(to_state(model)) gives the same answers, else WORKFLOW_STATE_LOSSY) and be plain (STATE_NOT_PLAIN); on a refusal nothing is written. Training data is left out unless include_data=True (and never when the recipe marks an input transient_only). author is a principal id (user:maya.chen), recorded in workflow.json; a shared bundle’s author can never be its approver.

to_frame method

def to_frame(self) -> pd.DataFrame

to_dict method

def to_dict(self) -> dict[str, Any]

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_workflow.py, line 243

class

class Forbidden(Refused)

A 403: not allowed for this principal (G-INT-02 self approval, a missing role, client scope, agent tools).

Source: packages/babelfin/src/babelfin/_errors.py, line 51

class

class GateReport

Every gate’s outcome for one document at one point in its life. results are ump_spec results.

Fields

NameTypeDefaultDescription
resultsresults
summarygates.summarize(results)
Methods and properties (9)

init constructor

GateReport(self, results: list[GateResult]) -> None

ok property

ok: bool

False when anything stopped (a hard stop, or a strict stop when strict was asked).

next_state property

next_state: str

stops property

stops: list[GateResult]

warnings property

warnings: list[GateResult]

fallbacks property

fallbacks: Fallbacks

raise_for_stops method

def raise_for_stops(self) -> None

Raise fin.Stopped with the first stop’s code; do nothing when nothing stopped.

to_frame method

def to_frame(self, all: bool = False) -> pd.DataFrame

One row per gate that did something; all=True adds the passes.

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_gates.py, line 52

class

class InputCheck

The outcome of checking a frame against a workflow’s contract. .spec is the ump_spec InputReport.

Fields

NameTypeDefaultDescription
specreport
Methods and properties (10)

init constructor

InputCheck(self, report: InputReport) -> None

ok property

ok: bool

False when a note refuses the input (the step is not available).

route property

route: str

score, refit or not_available.

mode property

mode: str

notes property

notes: list[InputNote]

to_frame method

def to_frame(self) -> pd.DataFrame

to_dict method

def to_dict(self) -> dict[str, Any]

clean method

def clean(self, df: pd.DataFrame) -> pd.DataFrame

A new frame with the excluded rows removed (rows at a new category level, matched by level hash, and rows with no time or category value), drop_columns dropped and the coerce casts applied. The input is not changed. Missing values in variables are left for the caller’s stated policy.

gate method

def gate(self, *, strict: bool = False) -> GateReport

G-DATA-07 on this report, as core would run it on a score or refit (strict=True turns its Fall back outcomes into stops; warnings stay warnings).

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_contract.py, line 40

class

class InvalidDocument(Error)

A document failed the contract (SCHEMA_INVALID). issues lists each field with its pointer.

Fields

NameTypeDefaultDescription
issuesissues
Methods and properties (2)

init constructor

InvalidDocument(self, detail: str, issues: list[dict[str, Any]]) -> None

to_frame method

def to_frame(self) -> pd.DataFrame

Source: packages/babelfin/src/babelfin/_errors.py, line 24

class

class Lineage

Edges from inputs to outputs around one artifact (nodes, edges and raw as core returns them).

Fields

NameTypeDefaultDescription
rawraw
edgeslist[dict[str, Any]]list(raw.get('edges') or [])
nodeslist[dict[str, Any]]list(raw.get('nodes') or [])
Methods and properties (2)

init constructor

Lineage(self, raw: dict[str, Any]) -> None

to_frame method

def to_frame(self) -> pd.DataFrame

Source: packages/babelfin/src/babelfin/_session.py, line 114

class

class LoadedWorkflow

A saved workflow, opened. Inspecting it, its contract check and its summary need no trust; running its code does (.trust() or Workflow.load(..., trust_code=True)).

Fields

NameTypeDefaultDescription
bundlebundle
approvalapprovalFor a workflow fetched from core (s.workflows.get): what its approval vouches for, or the reason it vouches for nothing (WORKFLOW_SHARE_NOT_APPROVED, WORKFLOW_SELF_APPROVED, WORKFLOW_SHARE_MISMATCH).
model_idmodel_id
Methods and properties (16)

init constructor

LoadedWorkflow(
self,
bundle: OpenBundle,
*,
approval: ApprovalTrust | None = None,
model_id: str | None = None,
) -> None

name property

name: str

code property

code: str

The module’s source: read it before trusting it.

code_sha256 property

code_sha256: str

trusted property

trusted: bool

contract property

contract: Contract

trust method

def trust(self) -> LoadedWorkflow

Trust this code hash on this machine (persisted in finprint’s trust store). Read .code first. A prep recipe’s named-step code is not covered: read .step_code, then .trust_steps().

step_code property

step_code: dict[str, str]

{step_id: source} of the prep recipe’s named steps: code that runs on the input before the module.

trust_steps method

def trust_steps(self) -> LoadedWorkflow

Trust the prep recipe’s named-step code on this machine (finprint’s store). Read .step_code first.

inspect method

def inspect(self) -> dict[str, Any]

Manifest, contract, questions and env report (no trust needed, nothing runs); env_pin is the versions it was saved with.

check method

def check(self, df: pd.DataFrame, *, mode: Mode = 'score') -> InputCheck

The contract check on df (score follows on from the saved history); data only.

run method

def run(
self,
df: pd.DataFrame,
*,
mode: Mode = 'score',
allow_refit: bool = True,
inputs: dict[str, Any] | None = None,
) -> WorkflowRun

Answer the questions on df. Score (the default) reuses the saved state; input that breaks continuity (a gap, an overlap, irregular time, spend outside the training range, a major env drift) refits, labelled, unless allow_refit=False; anything unavailable, or untrusted code, gives the bundle’s Tier D summary, labelled.

score method

def score(self, df: pd.DataFrame, **kw: Any) -> WorkflowRun

refit method

def refit(self, df: pd.DataFrame, **kw: Any) -> WorkflowRun

to_dict method

def to_dict(self) -> dict[str, Any]

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_workflow.py, line 487

class

class Log

An append-only Merkle log (RFC 9162 style) held in memory. Records are hashed under a domain tag.

Fields

NameTypeDefaultDescription
tagtag
Methods and properties (6)

init constructor

Log(self, tag: str = 'ump.artifact.v1') -> None

size property

size: int

root property

root: str

add method

def add(self, record: Any) -> int

Append a record; returns its index.

proof method

def proof(self, index: int) -> Proof

appended_since method

def appended_since(self, size: int, root: str) -> bool

True when this log only appended to the earlier log of size with root (a consistency proof).

Source: packages/babelfin/src/babelfin/_log.py, line 39

class

class LogProof

An approval’s place in the sealed log, checked here with ump_spec.integrity in two steps (spec §18): the record against its log entry’s content hash, the leaf hash recomputed from the entry, the audit path to the root, the root against the signed checkpoint, the log’s signature and the timestamp token beside it.

Fields

NameTypeDefaultDescription
recorddict[str, Any]entry['record']
checksdict[str, bool]{'record matches its log entry': not any('content_hash' in p or 'no log entry...
Methods and properties (4)

init constructor

LogProof(self, entry: dict[str, Any], checkpoint: dict[str, Any]) -> None

ok property

ok: bool

verify method

def verify(self) -> bool

to_frame method

def to_frame(self) -> pd.DataFrame

Source: packages/babelfin/src/babelfin/_session.py, line 69

class

class Me

Who the session acts as: principal, roles, client_scope, permissions (raw has the rest).

Fields

NameTypeDefaultDescription
rawraw
principalstrraw['principal']
roleslist[str]list(raw.get('roles') or [])
client_scopelist[str] | strraw.get('client_scope') or []
permissionsdict[str, Any]dict(raw.get('permissions') or {})
Methods and properties (1)

init constructor

Me(self, raw: dict[str, Any]) -> None

Source: packages/babelfin/src/babelfin/_session.py, line 48

class

class Model

A model manifest you can check, save and (with a session) file. doc is the JSON, spec the model.

Fields

NameTypeDefaultDescription
specModelManifestspec
docdoc
Methods and properties (8)

init constructor

Model(self, doc: dict[str, Any]) -> None

from_table classmethod

def from_table(
cls,
table: pd.DataFrame | Mapping[str, Number],
*,
estimand: EstimandLike | Estimand,
name: str,
engine: str,
client: str | None = None,
metric: Literal['roi', 'mroi'] = 'roi',
dependence: DependenceKind | dict[str, Any] | None = None,
recipe: Any = None,
**fields: Any,
) -> Model

A Tier D model (summary numbers at current spend) from a results table with columns channel, value, lo, hi and optionally current_spend and level, or from a dict of channel to fin.Number. A model of more than one channel must declare dependence (G-DEP-01): how its channel estimates move together, e.g. "joint_draws" when they came from one fit’s draws. recipe links the transform recipe that made the input. Other manifest fields pass through as keywords.

load classmethod

def load(cls, path: str | Path) -> Model

check method

def check(
self,
*,
at: str = 'submit',
strict: bool | str | list[str] = False,
) -> GateReport

The gates core will run when this model is submitted (see fin.check).

save method

def save(self, path: str | Path) -> Path

to_dict method

def to_dict(self) -> dict[str, Any]

to_frame method

def to_frame(self) -> pd.DataFrame

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_model.py, line 52

class

class Number

A value with its interval, estimand, trust labels and fallbacks. spec is the ShownNumber.

Fields

NameTypeDefaultDescription
specspec
Methods and properties (11)

init constructor

Number(self, spec: ShownNumber) -> None

value property

value: float

lo property

lo: float

hi property

hi: float

level property

level: float

label property

label: str | None

fallbacks property

fallbacks: list[FallbackEntry]

estimand property

estimand: Estimand

words property

words: str

The value and its range in words, e.g. “1.37, likely between 1.26 and 1.50”.

to_dict method

def to_dict(self) -> dict[str, Any]

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_numbers.py, line 31

class

class Optimisation

A planner optimisation. uplift is a fin.Number with its reallocation estimand; nothing is saved unless it was asked for (scenario_id is then set).

Fields

NameTypeDefaultDescription
opdict[str, Any]raw['optimisation']
Methods and properties (9)

init constructor

Optimisation(
self,
planner: Planner,
request: dict[str, Any],
raw: dict[str, Any],
) -> None

uplift property

uplift: Number

allocation property

allocation: Allocation

p_beat_plan property

p_beat_plan: float | None

Share of joint draws in which the optimised plan beats the current one.

ladder_step property

ladder_step: str | None

dependence property

dependence: str | None

fallbacks property

fallbacks: list[dict[str, Any]]

scenario_id property

scenario_id: str | None

save method

def save(self, name: str) -> Optimisation

Run the same optimisation again (same model, settings and seed) with save=True, as the web app’s Save button does, and return the saved result.

Source: packages/babelfin/src/babelfin/_apps.py, line 211

class

class Priority

Which test to run next: candidates ranked by expected information gain and EVOI, with the rule used.

Fields

NameTypeDefaultDescription
rawraw
rulestrstr(rule.get('words') if isinstance(rule, dict) else rule or '')
keptstr | Noneraw.get('kept')
guarantee_notestrstr(raw.get('guarantee_note') or '')
Methods and properties (2)

init constructor

Priority(self, raw: dict[str, Any]) -> None

to_frame method

def to_frame(self) -> pd.DataFrame

Source: packages/babelfin/src/babelfin/_apps.py, line 294

class

class Proof

Proof that one record is in the log. spec is the InclusionProof.

Methods and properties (3)

init constructor

Proof(self, spec: InclusionProof, tag: str) -> None

root property

root: str

verify method

def verify(self, record: Any = None) -> bool

The audit path reaches the root; with record, also that this record is the proven leaf.

Source: packages/babelfin/src/babelfin/_log.py, line 13

class

class Refused(Error)

ump-core or an app said no (any 4xx): status, code, gate and the RFC 9457 problem.

Methods and properties (1)

init constructor

Refused(
self,
code: str,
detail: str,
*,
status: int,
gate: str | None = None,
problem: Any = None,
) -> None

Source: packages/babelfin/src/babelfin/_errors.py, line 43

class

class Session

One principal talking to ump-core. Use as a context manager; core is the underlying CoreClient.

Fields

NameTypeDefaultDescription
gate_mode'strict' if strict else None
coreCoreClient(url, principal=principal, transport=transport, on_gate_fail=self.g...
Methods and properties (16)

init constructor

Session(
self,
principal: str,
*,
url: str | None = None,
strict: bool = False,
transport: httpx.BaseTransport | None = None,
) -> None

close method

def close(self) -> None

models property

models: Models

The models app: list, get, then a model’s curves().

planner property

planner: Planner

The planner app: optimize (not saved unless asked).

experiments property

experiments: Experiments

The experiments app: prioritise.

console property

console: Console

The console app: client(id).

data property

data: Data

The data catalogue app: datasets, dataset.

workflows property

workflows: Workflows

Workflow bundles shared through core: publish, get, list.

engines method

def engines(self) -> pd.DataFrame

The engine adapters core knows, with metadata re-read from each adapter.

as_ method

def as_(self, who: str) -> Session

The same connection acting as another principal (for example the approver).

me property

me: Me

portfolio method

def portfolio(self) -> pd.DataFrame

One row per client in scope; ShownNumber columns flattened (iroas.value, iroas.range_words, …).

artifacts method

def artifacts(
self,
*,
kind: str | None = None,
client: str | None = None,
state: str | None = None,
) -> pd.DataFrame

artifact method

def artifact(self, artifact_id: str) -> Artifact

check method

def check(
self,
document: Document,
*,
strict: bool | str | list[str] = False,
) -> GateReport

Dry-run the gates on the server (core adds context from the client’s contract), on the doc as core will store it. Core raises on a stop, so a stop here raises fin.Stopped; otherwise the report comes back.

file method

def file(
self,
document: Document,
*,
client: str | None = None,
title: str | None = None,
parents: Mapping[str, str | None] | Iterable[str] | None = None,
) -> Artifact

Create a draft. client defaults to the doc’s client_id; title to its name. parents records lineage into the new artifact: ids, or a mapping of id to role ({"ds_...": "training_data"}).

Source: packages/babelfin/src/babelfin/_session.py, line 229

class

class Stopped(Error)

A strict or hard stop. report is the full gate report when the stop came from the gates.

Fields

NameTypeDefaultDescription
reportreport
Methods and properties (1)

init constructor

Stopped(
self,
code: str,
detail: str,
*,
gate: str | None = None,
report: GateReport | None = None,
) -> None

Source: packages/babelfin/src/babelfin/_errors.py, line 35

class

class Total

A sum of channel estimates under a dependence assumption. spec is the DependenceEnvelope.

Fields

NameTypeDefaultDescription
specspec
Methods and properties (9)

init constructor

Total(self, spec: DependenceEnvelope) -> None

value property

value: float

lo property

lo: float

hi property

hi: float

method property

method: str

fallbacks property

fallbacks: list[FallbackEntry]

envelope_kind property

envelope_kind: str | None

bound when the total is a G-DEP-01 union of couplings (spec §7: a sum is a bound); None when the draws were joint and nothing was assumed.

to_frame method

def to_frame(self) -> pd.DataFrame

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_numbers.py, line 203

class

class UnacknowledgedFallbacks(Error)

approve was called without naming every fallback on the artifact. missing lists gate:code.

Fields

NameTypeDefaultDescription
missingmissing
Methods and properties (1)

init constructor

UnacknowledgedFallbacks(self, missing: list[str]) -> None

Source: packages/babelfin/src/babelfin/_errors.py, line 63

class

class Unavailable(Error)

A service or engine is down or unreachable (502/503).

Fields

NameTypeDefaultDescription
statusstatus
Methods and properties (1)

init constructor

Unavailable(self, code: str, detail: str, *, status: int = 502) -> None

Source: packages/babelfin/src/babelfin/_errors.py, line 55

class

class Workflow

A workflow being built: a contract for its input, the module that holds the model, an optional prep recipe, and the questions it answers. fit(df) runs it; Workflow.load(path) opens a saved one.

Fields

NameTypeDefaultDescription
namename
contractcontract
code_pathPath(code)
sourceraw.decode('utf-8')
code_sha256_sha256(raw)
paramsdict[str, Any]dict(params or {})
seedint(seed)
entry{'fit': fit, 'to_state': to_state, 'from_state': from_state}
dependencedependence
questionslist[dict[str, Any]][]
Methods and properties (6)

init constructor

Workflow(
self,
name: str,
*,
contract: Contract,
code: str | Path,
prep: Any = None,
params: dict[str, Any] | None = None,
seed: int = 0,
fit: str = 'fit',
to_state: str = 'to_state',
from_state: str = 'from_state',
dependence: str | dict[str, Any] | None = None,
) -> None

code is the module file (its source is what a bundle saves). prep is a finprint recipe (path, recipe or save result) applied to the checked input before fit. fit, to_state and from_state name the module’s functions. dependence is how the summary’s channel numbers move together, required once the summary holds two or more channels (G-DEP-01).

question method

def question(
self,
name: str,
*,
ask: str,
estimand: Estimand | str | dict[str, Any],
fn: str | None = None,
weeks: Weeks | None = 'rows',
summary: tuple[str, str] | Literal[False] | None = None,
) -> Workflow

Register a question answered by the module function fn (default: name), which returns one value per draw. estimand is a fin.Estimand or a registry name; the interval level is the estimand’s. weeks="rows" (or "periods") recomputes a window horizon from the input on every run; None keeps the estimand’s horizon. summary=(metric, channel) names its Tier D number in the bundle’s summary (the fallback rung); by default a registered ROI or mROI on one channel gets one, False opts out. Returns the workflow, so calls chain. A mistake raises fin.Error with code WORKFLOW_QUESTION_INVALID and adds nothing.

fit method

def fit(
self,
df: pd.DataFrame,
*,
inputs: dict[str, Any] | None = None,
) -> FittedWorkflow

Check df against the contract (refit mode), apply the prep recipe, fit the module and answer every question. A refused input raises fin.Error with the contract’s code (e.g. a missing target).

load staticmethod

def load(
path: str | Path,
*,
trust_code: bool = False,
trust_steps: bool = False,
) -> LoadedWorkflow

Open a saved bundle: every file’s hash checked, data parsed, no code run. The code runs only once its hash is trusted on this machine (.trust(), finprint’s store) or trust_code=True is passed after reading .code; until then, answers come from the bundle’s Tier D summary, labelled. A prep recipe’s named-step code is separate: .trust_steps() or trust_steps=True after reading .step_code.

to_dict method

def to_dict(self) -> dict[str, Any]

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_workflow.py, line 105

class

class WorkflowRun

One rerun of a loaded workflow. route: score, refit or not_available; source: where the answers came from (score, refit or summary); notes: every label, in the input-note shape.

Methods and properties (11)

init constructor

WorkflowRun(self, result: RunResult, name: str) -> None

route property

route: str

source property

source: str

notes property

notes: list[dict[str, Any]]

rows property

rows: int

plain property

plain: bool

True when the saved state scored the input with nothing routed or substituted.

answers method

def answers(self) -> dict[str, Number]

{question: fin.Number}. Where the route or source is not a plain score, each warn, exclude or refuse note, and an asked-for refit’s WORKFLOW_REFIT, is on each number as a G-DATA-07 fallback; other info notes (such as a dropped extra column) stay plain notes. Summary answers carry trust level 1. A question the summary holds no number for is left out (named in the SUMMARY_FALLBACK note).

answer method

def answer(self, name: str) -> Number

to_frame method

def to_frame(self) -> pd.DataFrame

to_dict method

def to_dict(self) -> dict[str, Any]

explain method

def explain(self) -> str

Source: packages/babelfin/src/babelfin/_workflow.py, line 397

class

class Workflows

Workflow bundles shared through core: publish, get, list; answer calls a served bundle (ump-workflow serve).

Methods and properties (5)

init constructor

Workflows(self, session: Session) -> None

publish method

def publish(
self,
fitted_or_bundle_path: FittedWorkflow | str | Path,
*,
client: str,
title: str | None = None,
) -> Artifact

Upload every file of the bundle (POST /v1/blobs, idempotent) and file a draft Tier A model_manifest for client: summary numbers and estimands from summary.json, input_contract from contract.json, payload_refs pinning every file, and a note with the code and prep-step hashes. A FittedWorkflow is saved first (to a temporary folder) with this session’s principal as its author. Then art.submit(), and a second person art.approve(accept=...).

get method

def get(self, model_id: str, *, dest: str | Path | None = None) -> LoadedWorkflow

Download the bundle a workflow manifest names (its validated version while a revision is pending, as ump-workflow serve --artifact reads it), rebuild and verify it in dest (or this user’s private cache folder under the system temp dir, mode 0700; when that folder cannot be trusted, a fresh mkdtemp folder removed as soon as the bundle is open, so .bundle.data.root then names a folder that no longer exists) and open it trusting exactly the hashes a validated, second-person approval vouches for (.approval). A draft, an unapproved manifest or a self-approval loads untrusted: its runs answer from the labelled summary. A wrong or missing blob raises fin.Error BUNDLE_TAMPERED; a manifest of the wrong shape, or a ref that is not a sha256, WORKFLOW_SHARE_MISMATCH.

list method

def list(self, client: str | None = None) -> pd.DataFrame

Workflow manifests (engine ump-workflow) in scope, one row each.

answer method

def answer(
self,
base_url: str,
df: pd.DataFrame,
*,
mode: Literal['score', 'refit'] = 'score',
allow_refit: bool = True,
questions: Iterable[str] | None = None,
transport: httpx.BaseTransport | None = None,
) -> WorkflowRun

Ask a served workflow bundle (ump-workflow serve, at base_url) its questions on df: one POST /v1/answer as this session’s principal. The result is a WorkflowRun like lw.run(df): each answer keeps its estimand and interval, and anything but a plain score is labelled (the server’s code trust comes from an approval or its own trust store; untrusted code answers from the bundle’s summary). A refusal is fin.Refused (413 WORKFLOW_REQUEST_TOO_LARGE past the server’s body limit), an unreachable server fin.Unavailable. transport is for tests (an in-process app).

Source: packages/babelfin/src/babelfin/_share.py, line 88

function

def check(
kind: str,
doc: dict[str, Any],
*,
at: str = 'submit',
strict: bool | str | Iterable[str] = False,
context: dict[str, Any] | None = None,
operation: str | None = None,
) -> GateReport

Run the gate catalogue on doc exactly as core would, on the doc as core stores it. at is "submit" (default), "seal", or the lifecycle state being entered (any key of ump_spec’s TRANSITIONS). strict=True turns every fallback into a stop; a list of gate ids makes only those strict (a single id may be a plain string; an unknown id is refused). Hard stops stop in every mode.

Source: packages/babelfin/src/babelfin/_gates.py, line 113

function

def compare(
a: Number | EstimandLike,
b: Number | EstimandLike,
*,
strict: bool = False,
a_is_model: bool = False,
b_is_model: bool = False,
can_reask: bool = False,
) -> Alignment

Can these two be combined? Walks match, converter, re-ask, assumed alignment (interval widened), side by side. strict=True raises fin.Stopped where a fallback would be needed. can_reask is off by default because a notebook cannot re-ask a model unless it is connected to one.

Source: packages/babelfin/src/babelfin/_numbers.py, line 186

function

def connect(
as_: str,
*,
url: str | None = None,
strict: bool = False,
transport: httpx.BaseTransport | None = None,
) -> Session

A session on ump-core as as_ ("maya.chen" means user:maya.chen; the POC’s identity stub is the X-UMP-Principal header, IAP/OIDC in production). url defaults to UMP_CORE_URL or localhost:8000. strict=True sends X-UMP-On-Gate-Fail: strict on every call.

Source: packages/babelfin/src/babelfin/_session.py, line 360

function

def contract(
*,
time: str | None = None,
freq: str | None = None,
target: str | None = None,
target_dtype: str | None = None,
required: dict[str, str],
optional: dict[str, str] | None = None,
missing: dict[str, MissingPolicy] | None = None,
categories: dict[str, DimPolicy] | None = None,
key: list[str] | None = None,
extra: Literal['allow', 'drop'] = 'drop',
min_rows: int | None = None,
) -> Contract

A contract written by hand: required and optional map column to dtype; missing maps a column to forbid (default), allow or mask; categories maps a categorical column to its policy (no level sets: use Contract.from_frame to record them); key columns are required and never dropped as extra; target_dtype makes a refit check the target’s cast; min_rows is a proposed threshold.

Source: packages/babelfin/src/babelfin/_contract.py, line 174

function

def estimand(
name: str | dict[str, Any] | Estimand | SpecEstimand,
**overrides: Any,
) -> Estimand

A registered estimand ("roi", "mroi", "iroas", "lift" or any registry id), changed only where you say. channels, geos, client and scope_kpi set the scope and keep the registry id; any of the seven fields (weeks, kpi, interval, level, intervention, baseline, …) makes it a custom estimand, so registry_id is dropped. intervention and horizon also take a dict for the whole field. A full estimand dict or model is accepted as is.

Source: packages/babelfin/src/babelfin/_estimand.py, line 107

function

def imputed_number(
value: float,
estimand: EstimandLike,
*,
level: float | None = None,
label: str | None = None,
) -> Number

A number whose source gave no interval: the band is imputed (G-UNC-01, proposed width) and labelled.

Source: packages/babelfin/src/babelfin/_numbers.py, line 109

function

def ladder(available: Iterable[str], *, excluded: Iterable[str] = ()) -> LadderDecision

The fallback-ladder rung for what you have: full_model, curve_params, spend_table, summary (warned), benchmarks (warned) or not_available.

Source: packages/babelfin/src/babelfin/_numbers.py, line 304

function

def number(
value: float,
interval: tuple[float, float],
estimand: EstimandLike,
*,
level: float | None = None,
label: str | None = None,
**labels: Any,
) -> Number

A shown number. interval is (lo, hi) and is required: UMP never shows a bare point. level defaults to the estimand’s. Extra keywords (trust_level, audit_level, unit_label, artifact_id) pass through to ump_spec.rules.shown_number.

Source: packages/babelfin/src/babelfin/_numbers.py, line 95

function

def record(title: str, **kwargs: Any) -> Any

Start recording what you do to data (finprint.session). In a notebook, %load_ext finprint first so cells are recorded too.

Source: packages/babelfin/src/babelfin/_recipes.py, line 16

function

def total(
values: Mapping[str, Number | tuple[float, float, float] | float] | pd.DataFrame,
*,
dependence: DependenceKind | None = None,
level: float = DEFAULT_LEVEL,
strict: bool = False,
seed: int = 0,
) -> Total

Add channel estimates honestly. Give a dict of channel to Number, (value, lo, hi) or a bare value (its interval is imputed and labelled), and the total is the G-DEP-01 envelope with DEPENDENCE_ASSUMED, labelled envelope_kind: bound. Give a draws-by-channels DataFrame and the total uses the joint draws, with no assumption; with dependence="per_channel" (or "none") the columns are not aligned, so the total couples them two ways (a permutation seeded with seed, and sorted), its point is the median under the independent coupling and its interval the union, a bound (spec §7).

Source: packages/babelfin/src/babelfin/_numbers.py, line 266

function

def validate(kind: str, doc: dict[str, Any]) -> BaseModel

The typed ump_spec model for doc, or fin.InvalidDocument listing every issue with its pointer.

Source: packages/babelfin/src/babelfin/_gates.py, line 30

function

def verify_recipe(path: Any, **kwargs: Any) -> Any

Replay a saved recipe and say whether it reproduced (finprint.verify).

Source: packages/babelfin/src/babelfin/_recipes.py, line 22

NameTypeValueDescription
ATdict[str, tuple[str, str | None]]{'submit': ('checks_running', None), 'seal': ('validated', 'seal')}Points in an artifact’s life you can check at, as (transition, operation). submit is what core runs when a draft is submitted; seal is what runs when an approved record is written to the log.
DEFAULT_LEVELfloatInterval.model_fields['level'].defaultInterval level used when an estimand declares none (ump_spec’s Interval default).
ESTIMAND_ALIASESdict[str, str]{'roi': 'E-MMM-ROI', 'mroi': 'E-MMM-MROI', 'iroas': 'E-GEO-IROAS', 'lift': 'E...Short names for the registered estimands analysts use most. Any registry id works too.