ontocast.onto.ontology_condense¶
Best-effort condensing of an ontology graph before it becomes prompt text.
Only the vector-retrieval mode ever bounded how much ontology reached the LLM.
selected_single_ontology (the default) and fixed_single_ontology serialize
the whole selected catalog ontology into every prompt, and the facts fan-out
serializes the union of every ontology artifact -- all with no cap, no sampling
and no truncation. On a large catalog that is the context blow-up; nothing else
in the pipeline notices.
This module trims a graph toward a triple budget by dropping the
least-load-bearing triples first, in the order established by
:data:~ontocast.onto.graph_prune.BFS_PREDICATE_PRIORITY. It is deliberately
best-effort: it will never drop labels, types, hierarchy or domain/range to
hit a number. A budget that cannot be met without cutting into those is reported
as a warning and the graph is passed through oversized, because silently
removing the schema the model needed produces a bad extraction that looks like a
bad model -- the most expensive failure mode this pipeline has.
Attributes¶
CLIP_MARKER = '…'
module-attribute
¶
CONTRACT_TEXT_PREDICATES = frozenset({SKOS.scopeNote, SKOS.definition})
module-attribute
¶
GLOSS_PREDICATES = BFS_PREDICATE_PRIORITY[-1]
module-attribute
¶
LOAD_BEARING_PREDICATES = frozenset().union(*BFS_PREDICATE_PRIORITY[:-1])
module-attribute
¶
NAMING_TEXT_PREDICATES = frozenset({RDFS.label, SKOS.prefLabel, SKOS.altLabel})
module-attribute
¶
PROSE_TEXT_PREDICATES = frozenset({RDFS.comment, SKOS.example, SKOS.note, SKOS.editorialNote, SKOS.historyNote})
module-attribute
¶
logger = logging.getLogger(__name__)
module-attribute
¶
Classes¶
CondenseReport
¶
Bases: BaseModel
What condensing did, for telemetry and for explaining a warning.
Source code in ontocast/onto/ontology_condense.py
Attributes¶
changed
property
¶
Whether anything was removed or shortened at all.
dropped_glosses = Field(default=0, description='Comments, definitions, scope notes, alt labels')
class-attribute
instance-attribute
¶
dropped_noise = Field(default=0, description='Header/list plumbing removed')
class-attribute
instance-attribute
¶
dropped_structural = Field(default=0, description='Generic types, stub restrictions, orphan bnodes')
class-attribute
instance-attribute
¶
literals_clipped = Field(default=0, description='Text literals shortened to a per-role cap')
class-attribute
instance-attribute
¶
max_triples = Field(default=None, description='Budget applied; None means no budget')
class-attribute
instance-attribute
¶
over_budget = Field(default=False, description='Still above budget after condensing; passed through oversized')
class-attribute
instance-attribute
¶
text_chars_after = Field(default=0, description='Summed length of capped text literals after capping')
class-attribute
instance-attribute
¶
text_chars_before = Field(default=0, description='Summed length of capped text literals on entry')
class-attribute
instance-attribute
¶
text_over_budget = Field(default=False, description='Still above the total text budget after every tightening stage')
class-attribute
instance-attribute
¶
triples_after = Field(description='Triple count after condensing')
class-attribute
instance-attribute
¶
triples_before = Field(description='Triple count on entry')
class-attribute
instance-attribute
¶
Methods:¶
as_metrics()
¶
Flat mapping for the retrieval-metrics payload.
Source code in ontocast/onto/ontology_condense.py
TextCaps
¶
Bases: BaseModel
Per-role character caps on the text literals reaching a prompt.
Nothing else in the pipeline bounds a single literal, so chapter size is otherwise proportional to how chatty a catalog's authors were rather than to how many terms it offers. These caps make it proportional to the term count, which the retrieval budget already controls. On a tersely authored catalog they are a no-op; that is the intended shape -- a bound, not a reduction.
Clipping rather than dropping is what keeps a usage contract available at a predictable price: the first sentence of a scope note is the part that says when a term applies. Where a cap fires, the cut is by content rather than by position -- the opening sentence and any clause stating when the term applies, then stop -- so a verbose catalog pays for its terms and not for its prose style. A cap left unset leaves every literal exactly as authored.
Source code in ontocast/onto/ontology_condense.py
Attributes¶
active
property
¶
Whether any cap is set at all.
contract = Field(default=None, ge=1, description='Cap on skos:scopeNote / skos:definition.')
class-attribute
instance-attribute
¶
naming = Field(default=None, ge=1, description='Cap on rdfs:label / skos:prefLabel / skos:altLabel.')
class-attribute
instance-attribute
¶
prose = Field(default=None, ge=1, description='Cap on rdfs:comment and other notes.')
class-attribute
instance-attribute
¶
total_budget = Field(default=None, ge=1, description='Ceiling on the summed length of all text literals in the chapter. Backstop for a catalog that defeats the per-role caps by holding very many short terms.')
class-attribute
instance-attribute
¶
Methods:¶
cap_for(predicate)
¶
The cap governing predicate, or None when it governs no role.
Source code in ontocast/onto/ontology_condense.py
Functions:¶
clip_text(text, cap)
¶
Clip text to cap characters, marking the cut.
The retained text is at most cap characters; :data:CLIP_MARKER is
appended on top of it, so a clipped literal reads as clipped. A cap of
None, or text already within it, is returned unchanged -- byte-identical, so
a disabled cap cannot perturb a prompt or its cache key.
Where the text has more than one sentence the cut is content-aware (see
:func:_contract_head) and may retain well under cap; a single
sentence longer than the cap falls back to a word boundary, which is the
only cut available inside it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
Literal text to bound. |
required |
cap
|
int | None
|
Maximum retained characters, or None to leave |
required |
Returns:
| Type | Description |
|---|---|
str
|
Either |
Source code in ontocast/onto/ontology_condense.py
condense_graph_for_prompt(graph, max_triples, text_caps=None)
¶
Trim graph toward max_triples, dropping the least useful triples first.
Passes are applied in increasing order of harm, stopping as soon as the graph fits: header/list noise, then structural scaffolding, then glosses. Structure that lets the model name and place a term is never dropped.
Text literals are bounded first and unconditionally: the triple budget is a
count and says nothing about how long a single rdfs:comment may be, so a
graph well under it can still carry an unbounded chapter. text_caps makes
chapter size a function of term count rather than of prose volume.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
graph
|
RDFGraph
|
Ontology graph destined for a prompt. Not mutated. |
required |
max_triples
|
int | None
|
Triple budget, or |
required |
text_caps
|
TextCaps | None
|
Per-role character caps on text literals, or |
None
|
Returns:
| Type | Description |
|---|---|
RDFGraph
|
The condensed graph (or |
CondenseReport
|
|
Source code in ontocast/onto/ontology_condense.py
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 | |
split_sentences(text)
¶
Split text into sentences, keeping each one's terminator.
Abbreviation-aware only to the extent that a period inside e.g. or a
single capital initial must not end a sentence; anything more would be
guessing at a catalog's writing style.