lpgcast.select¶
Stage A selection: the slice of one schema a text is about.
Two mechanisms, kept apart. Seeds come from retrieval: lexical lanes over
the schema's element text, fused by rank. Structure comes from closure:
graflo's subschema() grows the seeds into a valid standalone schema under
a budget and never drops identity fields. A schema already under the budget
is passed whole.
Lanes:
exact— code-like names and synonyms (PLC,WorkOrder, an IRI) found verbatim, case-sensitively, in the text.lexical— names and synonyms found as phrases in the text after case-folding, camel/snake splitting and a light suffix stemmer, weighted by how few elements share the phrase; plus description words the text repeats.unit— a number followed by a token that is a property's declared unit (200 kV) seeds that property's owner.
A hit on a property seeds its owner — the vertex or edge — at half weight.
Attributes¶
DESCRIPTION_MIN_WORDS = 2
module-attribute
¶
DESCRIPTION_WEIGHT = 0.25
module-attribute
¶
LANES = ('exact', 'lexical', 'unit')
module-attribute
¶
Lane = Literal['exact', 'lexical', 'unit']
module-attribute
¶
MAX_PHRASE_WORDS = 8
module-attribute
¶
PROPERTY_HIT_WEIGHT = 0.5
module-attribute
¶
Seed = str | EdgeId
module-attribute
¶
Classes¶
RetrievalMetrics
¶
Bases: BaseModel
What retrieval found, before and after each cut.
fused == 0 means nothing matched; fused > 0 with no seeds would mean
the gate rejected everything — kept apart because they have different fixes.
Source code in lpgcast/select.py
Attributes¶
capped = Field(description='Seeds over max_seeds.')
class-attribute
instance-attribute
¶
fused = Field(description='Distinct seeds over all lanes.')
class-attribute
instance-attribute
¶
gated_out = Field(description='Seeds below the relevance gate.')
class-attribute
instance-attribute
¶
lane_hits = Field(description='Distinct seeds per lane.')
class-attribute
instance-attribute
¶
schema_tokens = Field(description='Estimated size of the whole schema.')
class-attribute
instance-attribute
¶
seeds = Field(description='Seeds passed on.')
class-attribute
instance-attribute
¶
SeedHit
¶
Bases: BaseModel
A seed and how it was found.
Source code in lpgcast/select.py
Attributes¶
edge_id = Field(default=None, description='Seed edge.')
class-attribute
instance-attribute
¶
ranks = Field(description='Rank within each lane that found it.')
class-attribute
instance-attribute
¶
score = Field(description='Fused score.')
class-attribute
instance-attribute
¶
seed
property
¶
vertex = Field(default=None, description='Seed vertex type.')
class-attribute
instance-attribute
¶
Selection
¶
Bases: BaseModel
The schema a cast runs against, and how it was chosen.
Source code in lpgcast/select.py
Attributes¶
elision = Field(default=None, description='What closure left out; None when whole.')
class-attribute
instance-attribute
¶
metrics
instance-attribute
¶
mode = Field(description='``whole``: the schema fit the budget and was passed as is.')
class-attribute
instance-attribute
¶
model_config = ConfigDict(arbitrary_types_allowed=True)
class-attribute
instance-attribute
¶
seeds = Field(description='Seeds, best first.')
class-attribute
instance-attribute
¶
slice = Field(description='A valid standalone schema.')
class-attribute
instance-attribute
¶
SelectionConfig
¶
Bases: BaseModel
Tuning for stage A selection.
Source code in lpgcast/select.py
Attributes¶
budget
property
¶
lane_depth = Field(default=20, ge=1, description='Hits kept per lane before fusion.')
class-attribute
instance-attribute
¶
lane_weights = Field(default_factory=lambda: dict.fromkeys(LANES, 1.0), description='Weight of each lane in fusion.')
class-attribute
instance-attribute
¶
max_elements = Field(default=60, ge=1, description='Vertex and edge budget of the slice.')
class-attribute
instance-attribute
¶
max_seeds = Field(default=12, ge=1, description='Seeds passed to closure.')
class-attribute
instance-attribute
¶
max_tokens = Field(default=4000, ge=1, description='Token budget of the slice.')
class-attribute
instance-attribute
¶
min_relative_score = Field(default=0.2, gt=0.0, le=1.0, description='A seed must reach this fraction of the score a rank-1 hit in one lane earns. Relative, so it means the same for any schema.')
class-attribute
instance-attribute
¶
model_config = ConfigDict(extra='forbid')
class-attribute
instance-attribute
¶
rank_constant = Field(default=0.0, ge=0.0, description='Added to each rank before the reciprocal. Raising it lets agreement across lanes outweigh position within one.')
class-attribute
instance-attribute
¶
SelectionError
¶
Bases: RuntimeError
No slice could be chosen.
Attributes:
| Name | Type | Description |
|---|---|---|
reason |
|
|
metrics |
Retrieval metrics, when retrieval ran. |
Source code in lpgcast/select.py
Functions:¶
number_adjacent_tokens(text)
¶
Tokens that directly follow a number: candidate unit mentions.
Source code in lpgcast/select.py
retrieve(schema, text, config=None)
¶
Rank the schema's elements against text; return gated, capped seeds.
Source code in lpgcast/select.py
select(schema, text, config=None)
¶
Choose the schema a cast of text runs against.
Raises:
| Type | Description |
|---|---|
SelectionError
|
the text is empty, or the schema is over budget and nothing in the text matched it. |
Source code in lpgcast/select.py
words(text)
¶
Case-folded, camel- and snake-split, stemmed words.