ek.base#
Foundational data structures and strategy protocols for ek.
This module is the single source of truth (SSOT) for ek’s two-layer data
model and for the small set of typing.Protocol strategy interfaces that every
swappable behaviour in the framework implements. It contains **data structures
and contracts only** – no business logic, no heavy imports. Importing it is
cheap and pulls in nothing beyond the standard library.
The two layers#
Evaluating an information-extraction (IE) output splits into two halves – scoring against a gold reference (offline) and estimating quality with no reference (online) – and both operate on the same object:
Layer A – the schema (
GraphGrammarand friends): a frozen description of the typed graph you extract, carrying both the types and the importance/cost weights per field/node/edge. It is the SSOT consulted by cost-sensitive metrics, by validators, and (eventually) by constrained decoders.Layer B – the extraction metadata (
AnnotatedExtractionand friends): per-extraction runtime metadata – provenance, raw signals, (calibrated) confidence, validator findings, and the accept/flag/block decision – keyed by aNodePathinto the Layer-A schema, riding alongside the grammar without ever mutating it.
The strategy protocols#
Metric, Validator, Calibrator, DecisionPolicy
and Signal are structural (duck-typed) contracts. Concrete
implementations are resolved from ek.registry by name and injected as
keyword-only arguments with smart defaults, so the simple path Just Works while
every layer stays replaceable (open-closed).
Example
>>> g = GraphGrammar(
... node_types={"donation": NodeType(
... "donation",
... fields={
... "amount": FieldSpec("amount", "number", importance=10.0),
... "city": FieldSpec("city", "string", importance=1.0),
... },
... )},
... )
>>> g.field_cost("donation", "amount")
10.0
>>> g.field_cost("donation", "city")
1.0
Module Attributes
Canonicalize a string before comparison (lowercase, fold, normalize, ...). |
|
Read named raw signals off a |
|
Cost of an edit on a typed element; defaults to reading |
|
Anything that turns an image (path/bytes/array) into an |
Functions
|
The default |
Classes
|
Layer B: the verification metadata, referencing a frozen Layer-A grammar. |
|
Maps a raw scalar signal to a probability after being |
|
Terminal action a selective-prediction gate emits for an extracted value. |
|
Turns a (calibrated) confidence into an accept/flag/block |
|
A directed relation kind between two |
|
One extracted value plus all of its reference-free verification metadata. |
|
A leaf attribute of a node: its type, validation domain and cost weight. |
|
One validator observation about a value: a flag, optionally a correction. |
|
The frozen schema SSOT: typed nodes/edges plus their importance weights. |
|
Compares one prediction to one gold reference, returning a |
|
Addresses a node (or one of its fields) in an extracted graph; keys Layer B. |
|
A node kind in the typed graph (e.g. an "invoice" or a "line item"). |
|
Where an extracted value came from, for audit and click-to-source review. |
|
The result of a reference-free quality estimate for one extraction. |
|
Aggregate of many |
|
The result of comparing one prediction against one reference. |
|
Whether a |
|
A reference-free quality signal: extractor output -> raw scalar score. |
|
A reference into the schema, so an injected cost function can read weights. |
|
Reference-free check on a value, yielding zero or more |
- class ek.base.AnnotatedExtraction(grammar, estimates=<factory>)[source]#
Bases:
objectLayer B: the verification metadata, referencing a frozen Layer-A grammar.
The grammar is held by reference and never mutated;
estimatesmaps aNodePathto theFieldEstimatefor that node/field.
- class ek.base.Calibrator(*args, **kwargs)[source]#
Bases:
ProtocolMaps a raw scalar signal to a probability after being
fiton labels.
- ek.base.ConfidenceSource#
Read named raw signals off a
FieldEstimate(e.g. for calibration).alias of
Callable[[FieldEstimate],Mapping[str,float]]
- ek.base.CostWeight#
Cost of an edit on a typed element; defaults to reading
*.importance.alias of
Callable[[GraphGrammar,TypeRef],float]
- class ek.base.Decision(*values)[source]#
-
Terminal action a selective-prediction gate emits for an extracted value.
- class ek.base.DecisionPolicy(*args, **kwargs)[source]#
Bases:
ProtocolTurns a (calibrated) confidence into an accept/flag/block
Decision.
- class ek.base.EdgeType(name, src, dst, importance=1.0)[source]#
Bases:
objectA directed relation kind between two
NodeTypenames.
- class ek.base.FieldEstimate(value, raw_signals=<factory>, confidence=None, findings=(), provenance=None, decision=None)[source]#
Bases:
objectOne extracted value plus all of its reference-free verification metadata.
- class ek.base.FieldSpec(name, type='string', importance=1.0, domain=(), normalizer=None)[source]#
Bases:
objectA leaf attribute of a node: its type, validation domain and cost weight.
- Parameters:
name (
str) – Attribute name.type (
str) – A free-form type tag (e.g."string","number","date");ekdoes not impose a type system – the tag drives metric/validator dispatch and is yours to define.importance (
float) – Per-field cost weight; the lever that makes “two extra digits on a donation amount” outweigh “a misspelled city”. Defaults to1.0.domain (
tuple) – Optional allowed values: an enum tuple, a(lo, hi)range, or a regex string – consumed by validators, never by metrics.normalizer (
Optional[str]) – Optional key naming a canonicalizer (resolved from the registry) to apply to this field before comparison.
- class ek.base.Finding(field, layer, severity=Severity.FLAG, message='', suggestion=None)[source]#
Bases:
objectOne validator observation about a value: a flag, optionally a correction.
A
suggestionis present iff the producing layer can correct (only the deterministic canonicalizer and the gated LLM corrector freely do so). The original value is always retained elsewhere; a Finding never mutates.
- class ek.base.GraphGrammar(node_types=<factory>, edge_types=<factory>)[source]#
Bases:
objectThe frozen schema SSOT: typed nodes/edges plus their importance weights.
Methods return the cost weight for a referenced type, defaulting to
1.0for anything not declared, so a partial grammar is always usable.
- class ek.base.Metric(*args, **kwargs)[source]#
Bases:
ProtocolCompares one prediction to one gold reference, returning a
Score.
- class ek.base.NodePath(node_id, node_type, field=None)[source]#
Bases:
objectAddresses a node (or one of its fields) in an extracted graph; keys Layer B.
- class ek.base.NodeType(name, fields=<factory>, importance=1.0)[source]#
Bases:
objectA node kind in the typed graph (e.g. an “invoice” or a “line item”).
- ek.base.Normalizer#
Canonicalize a string before comparison (lowercase, fold, normalize, …).
- ek.base.OcrBackend#
Anything that turns an image (path/bytes/array) into an
OcrResult-shaped object (with.textand.blocks). Typed loosely soekcore never imports an OCR package.
- class ek.base.Provenance(engine='', source_span=None, bbox=None, raw_transcripts=())[source]#
Bases:
objectWhere an extracted value came from, for audit and click-to-source review.
bboxis intentionally typedAnysoekcore need not import any OCR package; the OCR instance stores normalized[0, 1]top-left-origin geometry.
- class ek.base.QualityReport(calibrated_confidence=None, decision=None, findings=(), raw_signals=<factory>, provenance=<factory>, per_field=None)[source]#
Bases:
objectThe result of a reference-free quality estimate for one extraction.
For a single value the scalar fields carry the verdict. For a whole
AnnotatedExtraction,per_fieldmaps eachNodePathto its updatedFieldEstimate(confidence/findings/decision filled in), and the scalar fields summarize:calibrated_confidenceis the weakest field, anddecisionthe most severe (block>flag>accept).
- class ek.base.Report(metric='', aggregate=None, n=0, scores=<factory>, per_slice=<factory>, detail=<factory>)[source]#
Bases:
objectAggregate of many
Scores over a corpus, with optional per-slice cuts.aggregateis the corpus-level headline (computed by the metric’s own aggregator – e.g. globally accumulated WER – not a naive mean of per-item values).per_slicemaps a slice label to its own aggregate.
- class ek.base.Score(value, precision=None, recall=None, f1=None, metric='', detail=<factory>)[source]#
Bases:
objectThe result of comparing one prediction against one reference.
valueis the headline number (higher is better unless a metric documents otherwise). The optional decomposition fields let structured metrics carry precision/recall/F1, an alignment, and raw counts (e.g. edit operations) so that corpus aggregation can be done correctly (e.g. global WER accumulation) rather than by averaging per-item scores.float(score)returnsvalue.
- class ek.base.Severity(*values)[source]#
-
Whether a
Findingmerely flags or can also correct a value.
- class ek.base.Signal(*args, **kwargs)[source]#
Bases:
ProtocolA reference-free quality signal: extractor output -> raw scalar score.
The
cost_tierattribute (lower is cheaper) lets an escalation policy run cheap signals first and pay for expensive ones only on residual uncertainty.
- class ek.base.TypeRef(kind, name, field=None)[source]#
Bases:
objectA reference into the schema, so an injected cost function can read weights.
kindis one of"node","edge"or"field"; for a field,nameis the node-type name andfieldthe field name.
- class ek.base.Validator(*args, **kwargs)[source]#
Bases:
ProtocolReference-free check on a value, yielding zero or more
Findings.
- ek.base.default_cost_weight(grammar, ref)[source]#
The default
CostWeight: read the importance weight off the schema.- Return type: