Outcome Panel API

Sealed text-to-code decoding splits over the Census index entries (roadmap Stage 2).

Index-entry roles

Index-entry roles for the outcome panel (Req 3; roadmap D4).

Every entry of the Census NAICS index file holds exactly one role: examples-channel text, or a training, validation or test query. The assignment is made once, frozen in a committed table (conf/data/index_roles.csv), and consumed by hash afterwards; regeneration is never how the sealed splits are preserved.

  • Eligibility. Validation and test queries are drawn only from entries that no training text can leak: an entry is withheld from both held-out splits when it matches, exactly or as a near-duplicate (leakage), any title, description, exclusion text, fallback examples text or any other index entry. Checking against every other entry, not only those that end up as training text, makes the held-out splits leak-free whatever the assignment.
  • Quotas. Per code, role counts are largest-remainder quotas of the configured fractions, with remainder ties broken by a seeded draw. Every code keeps at least examples_floor examples-channel entries, and held-out quotas beyond the code's eligible entries move to training, one at a time from the larger of the two held-out quotas (test on a tie).
  • Seeds. Each code draws from its own generator, seeded by (seed, code), so a code's roles do not depend on any other code.

EligibilityReport dataclass

Which entries may be held out, and why the others are withheld.

The *_static and *_entry counts overlap; withheld_exact (any exact match) and withheld_near_duplicate (a near-duplicate and no exact match) partition withheld.

RoleFractions dataclass

Exact role fractions; non-negative and summing to one.

from_mapping(mapping) classmethod

Exact fractions from decimal config values (0.35 becomes 7/20, not a binary float).

allocate_role_counts(n_entries, n_eligible, fractions, tie_break, examples_floor=1)

Role counts for one code with n_entries entries, n_eligible of them held-out-eligible.

Parameters:

Name Type Description Default
n_entries int

The code's index entries.

required
n_eligible int

Entries that may become validation or test queries.

required
fractions RoleFractions

Target role fractions.

required
tie_break Sequence[float]

One draw per role, in ROLE_ORDER; the smaller draw wins a remainder tie.

required
examples_floor int

Minimum examples-role entries (capped at n_entries).

1

Returns:

Type Description
Dict[IndexRole, int]

Counts per role, summing to n_entries.

assign_index_roles(entries, eligible, fractions, seed, examples_floor=1)

Give every entry exactly one role, per code and stratified.

Parameters:

Name Type Description Default
entries DataFrame

Index entries (entry_id, code, ...), one row per entry.

required
eligible ndarray

Held-out eligibility, aligned with entries.

required
fractions RoleFractions

Target role fractions.

required
seed int

Base seed; each code draws from np.random.default_rng([seed, int(code)]).

required
examples_floor int

Minimum examples-role entries per code.

1

Returns:

Type Description
DataFrame

entry_id, code, role sorted by entry_id.

attach_role_text(roles, entries)

Join the frozen role table to the index entries it was built from.

Returns:

Type Description
DataFrame

entry_id, code, text, role sorted by entry_id.

Raises:

Type Description
ValueError

If the two list different entries, or give an entry different codes.

examples_channel_by_code(role_rows)

Each code's examples channel: its examples-role entries in index-file order, joined.

held_out_eligibility(entries, static_segments, min_jaccard=NEAR_DUPLICATE_MIN_JACCARD)

Flag the entries that no training text can leak.

Parameters:

Name Type Description Default
entries DataFrame

Index entries (entry_id, code, text).

required
static_segments Sequence[str]

Every code's title, description, exclusion and fallback examples segments (leakage.training_text_segments without index-derived examples).

required
min_jaccard Fraction

Near-duplicate threshold.

NEAR_DUPLICATE_MIN_JACCARD

read_role_table(path)

Read the frozen role table, keeping codes as strings.

role_table_fingerprint(roles)

SHA-256 of the role assignment's canonical CSV (entry_id, code, role).

It equals the committed table's file hash, so a split is identified by its assignment whichever file it was read from.

verify_examples_channel(descriptions, role_rows)

Require every code with index entries to carry exactly its examples-role entries.

Raises:

Type Description
ValueError

If a code's examples channel differs from its examples-role entries.

verify_role_leakage(descriptions, role_rows, min_jaccard=NEAR_DUPLICATE_MIN_JACCARD, *, extra_texts=())

Match every validation and test query against all training text; fail on any match.

Training text is every code's title, description, examples channel and exclusion text in descriptions, every training-role query, and extra_texts: the redirection table's activity phrases, which Stage 7 trains on as queries (Req 8).

Returns:

Type Description
Dict[str, Dict[str, int]]

Exact and near-duplicate match counts per held-out split (all zero on success).

write_role_table(roles, path)

Write the canonical CSV and return its sha256 (role_table_fingerprint).

Draw the frozen index-entry role table (roadmap Stage 2; Req 3; D4).

naics-embedder data roles runs this once. The table it writes (conf/data/index_roles.csv) is committed and data preprocess applies it from then on, so the sealed validation and test splits never move. Redrawing reassigns every entry and unseals both splits, so an existing table is replaced only with force.

generate_index_role_table(download_cfg, panel_cfg, *, force=False)

Draw every index entry's role, check the result, and write the table and its provenance.

Held-out (validation and test) queries are drawn only from entries that match no title, description, exclusion text, fallback examples text or other index entry, exactly or as a near-duplicate; the provenance counts the entries withheld for each reason.

Returns:

Type Description
Path

The role table's path (download_cfg.index_roles_csv).

Raises:

Type Description
FileExistsError

If the table exists and force is False.

ValueError

If the drawn roles fail a Req 3 check.

Leakage

Leakage between held-out index-entry queries and training text (Req 3, "Leakage").

Texts are compared after normalize_text: lowercase ASCII letters and digits, with every other run of characters collapsed to one space. A query leaks into a training segment in two ways:

  • exact: the query occurs in the segment as whole words (equality included);
  • near-duplicate: the character-trigram Jaccard similarity of query and segment reaches the threshold, 9/10 by default. Trigrams are taken inside word boundaries, as scikit-learn's char_wb analyzer builds them, so reordered words score as the same text.

Jaccard is compared in integers (denominator * shared >= numerator * union), so no pair sits on a floating-point boundary. The check compares whole queries with whole segments, so a query whose words appear reordered inside a longer segment is not caught.

LeakageMatches dataclass

Per-query leakage flags, one boolean per query in input order.

find_leakage(queries, corpus, *, min_jaccard=NEAR_DUPLICATE_MIN_JACCARD)

Flag each query that occurs in, or near-duplicates, any corpus text.

Raises:

Type Description
ValueError

If a query has no letters or digits, or the threshold is outside (0, 1].

find_leakage_within(texts, *, min_jaccard=NEAR_DUPLICATE_MIN_JACCARD)

Flag each text that occurs in, or near-duplicates, another text of the same list.

A text is never matched against itself, but two identical texts flag each other.

leaking_texts(segments, queries, *, min_jaccard=NEAR_DUPLICATE_MIN_JACCARD)

Flag each text that some query leaks into, under find_leakage's two rules.

Parameters:

Name Type Description Default
segments Sequence[Sequence[str]]

Each text's normalized segments, as text_segments returns them.

required
queries Sequence[str]

The queries, normalized here.

required
min_jaccard Fraction

The near-duplicate threshold.

NEAR_DUPLICATE_MIN_JACCARD

Returns:

Type Description
ndarray

One boolean per text: some query occurs in, or near-duplicates, one of its segments.

normalize_text(text)

Lowercase ASCII letters and digits, every other run of characters one space.

text_segments(text)

Normalized sentences of a description or exclusion text.

A cross-reference sentence ("Growing soybeans--are classified in Industry 111110") also yields its activity phrase, the part before --, which later stages train on as a query.

training_text_segments(descriptions, extra_texts=())

Sorted, de-duplicated normalized segments of every code's training text, plus extra texts.

Titles are one segment each, descriptions and exclusion texts are split into sentences, and the examples channel is split into its '; '-joined entries.

Decoding

Text-to-code decoding scores for the outcome panel (Req 3).

Each query decodes to the nearest candidate code under the arm's own distance. Ties are broken against the truth: the true code's rank counts every candidate at a distance no greater than its own, so an encoder that places every point alike ranks the truth last, never first. Distances are computed in float64 on the CPU whatever the device or dtype of the points.

Metrics per query: exact top-1 accuracy, reciprocal rank, Hit@k for k in HIT_KS, and the level of the lowest common ancestor of the top-1 code and the truth (6 for the same six-digit code, 2 for a shared sector, 1 for the virtual root above the sectors).

DecodingResult dataclass

Decoding scores at three grains.

Attributes:

Name Type Description
per_query DataFrame

One row per query: query_id, code, top1_code, rank, reciprocal_rank, hit_at_k per k and lca_level. Stage 4 resamples it by code.

per_code DataFrame

One row per true code: code, n_queries and each metric's mean.

summary Dict[str, Union[int, float, str]]

Query-weighted means of every metric, with n_queries, n_codes, n_candidates and the distance's name.

cosine_distances(queries, candidates)

One minus cosine similarity, (Q, C).

euclidean_distances(queries, candidates)

Euclidean distances, (Q, C), without the matrix-product shortcut that loses precision.

lca_level(code_a, code_b)

Level of the lowest common ancestor of two codes, counting the virtual root as level 1.

A shared sector is level 2 and the same six-digit code level 6; combined sectors (31-33, 44-45, 48-49) count as one sector.

lorentz_distances(queries, candidates)

Geodesic distances on the curvature -1 hyperboloid, (Q, C), for (time, space) rows.

The time coordinate is re-derived from the spatial ones, as metrics.core's lorentz_distance_matrix does, so a point rounded off the hyperboloid is read at its spatial position.

resolve_distance(distance)

A registered distance by name, or a callable with its __name__.

score_decoding(query_points, query_codes, candidate_points, candidate_codes, distance='cosine', query_ids=None)

Decode every query to its nearest candidate and score it against the query's true code.

Parameters:

Name Type Description Default
query_points Tensor

Query embeddings, (Q, D).

required
query_codes Sequence[str]

The true code of each query.

required
candidate_points Tensor

Candidate embeddings, (C, D), in the same space.

required
candidate_codes Sequence[str]

Distinct candidate codes, one per row of candidate_points.

required
distance Union[str, DistanceFn]

A name in DISTANCES or a callable taking float64 CPU (Q, D) and (C, D) tensors and returning (Q, C) distances.

'cosine'
query_ids Optional[Sequence[int]]

Identifiers carried into per_query (index entry ids); 0..Q-1 if omitted.

None

Raises:

Type Description
ValueError

On mismatched shapes, repeated candidates, a query code that is not a candidate, or a distance that is not finite.

Panel and selection log

The outcome panel (Req 3; Req 4): text-to-code decoding over sealed query splits.

Validation queries may be read at any time, and every read is logged. The test split is sealed: reading it needs a logged opening by the same panel object, and opening the same split (the same role assignment, by fingerprint) a second time needs a stated reason. Training queries are training data, not a selection, so reading them is not logged.

OutcomePanel

The index-entry query splits, the six-digit candidates, and the log every read goes to.

Parameters:

Name Type Description Default
role_rows DataFrame

Every index entry with its text and role (entry_id, code, text, role).

required
candidates Sequence[str]

The six-digit codes queries decode to, entry-less codes included.

required
log SelectionLog

The selection log.

required

entryless_candidates property

Candidates without index entries: decoded to, never queried (112130 and 541120).

data_fingerprint(split)

SHA-256 of what a read of the split scores: its queries (entry_id, code and text, in entry order) and the candidates.

fingerprint names the role assignment alone, which the log counts openings by, so two panels can share it and still score other text or decode to other candidates. This returns no rows, so it is not a read and logs nothing, even for the sealed test split.

from_bundle(bundle, log_path) classmethod

The panel from a validated supervision bundle's index_roles member and codebook.

Every loadable bundle carries the member, whose roles its build checked against its descriptions.

from_files(index_roles_parquet, descriptions_parquet, log_path) classmethod

The panel from data preprocess outputs: the index roles and the descriptions.

Raises:

Type Description
ValueError

If the descriptions' examples channel is not built from the examples-role entries only. A descriptions file from before the roles existed holds every entry, held-out queries included, in its examples channel.

open_test(purpose, *, reopen_reason=None)

Open the sealed test split for this panel object, logging the opening.

Raises:

Type Description
SplitAlreadyOpenedError

If the log already records an opening of this split and no reopen_reason is given.

score(encoder, split, purpose, distance='cosine', detail=None)

Decode one split's queries over every candidate with the encoder, logging the read.

detail joins the read's logged detail, so a caller can name the run it scores; it cannot replace the encoder or the distance the panel logs. score_logged also returns the record the read logged.

score_logged(encoder, split, purpose, distance='cosine', detail=None)

score, also returning the record the read appended to the selection log.

The record is appended before any query is encoded, so a read that fails while it scores is logged all the same. A caller that keeps its own copy of its reads, as the training monitor keeps monitor_reads.jsonl, keeps this record as it was logged.

Returns:

Type Description
Tuple[DecodingResult, Dict[str, Any]]

The decoding scores, and the read's record as the log appended it.

test_queries(purpose)

Test queries, logging the read.

Raises:

Type Description
SealedSplitError

If this panel object has not opened the test split.

training_queries()

Training queries (entry_id, code, text); training data, so not logged.

validation_queries(purpose)

Validation queries, logging the read.

QueryCodeEncoder

Bases: Protocol

What the panel needs from an arm: queries and codes embedded in one space.

SealedSplitError

Bases: RuntimeError

The test split was read before a logged opening.

SplitAlreadyOpenedError

Bases: RuntimeError

The test split was opened again without a stated reason.

The selection log (Req 4; Verification "Selection hygiene").

An append-only JSON-lines file with one record per event: every read of a panel's validation or test split, and every opening of a test split. It is the evidence that selections read validation splits only and that each test split was opened once, for the final configuration. A second opening needs a stated reason and is recorded as reopen.

SelectionEvent

Bases: str, Enum

What a selection-log record reports.

SelectionLog

Append-only JSON-lines log of panel reads and test-split openings.

append(event, *, panel, split, purpose, fingerprint, n_queries, detail=None)

Append one record and return it.

Raises:

Type Description
ValueError

If purpose is blank: every read and opening states why it happens.

openings(panel, fingerprint)

The recorded openings (open and reopen) of one test split, oldest first.

Parameters:

Name Type Description Default
panel Union[str, Collection[str]]

The name the split is opened under, or every such name: the regressor panel's two outcomes share each regime's outer set (Req 22).

required
fingerprint str

The split's fingerprint.

required

records()

Every record, oldest first; a log that does not exist yet has none.

merge_read_detail(logged, extra)

A read's logged detail joined with a caller's extra, which can name the run it scores.

Raises:

Type Description
ValueError

If extra would replace a key the panel logs itself.

Lexical baseline

A training-free lexical encoder for the outcome panel.

Texts are hashed character trigrams of their normalized form (leakage.normalize_text), L2-normalized, so cosine distance decodes a query to the code whose text shares most of its trigrams. It is the stub arm that exercises the panel end to end on the real validation split until a trained encoder can embed a query (roadmap Stage 6), and a floor for trained arms. It is never a candidate configuration.

LexicalTrigramEncoder

Hashed character-trigram vectors for codes (from their texts) and queries.

Parameters:

Name Type Description Default
code_texts Mapping[str, str]

The text each code is embedded from.

required
n_features int

Hash buckets per vector.

4096

code_texts_from_descriptions(descriptions)

Each code's title, description and examples channel, joined by spaces.

Exclusion text is left out: it names activities the code does not cover.