Data model¶
The Pydantic contracts that flow through the pipeline. Every store, layer, and renderer reads and writes these — they are the stable interface between stages.
Corpus¶
A Chunk is the atom of the corpus; Mention and EntityLink are the annotation
output that rides on it. See Corpus input for the file
format these are loaded from, and Annotation for how the
mentions and links are produced.
.. py:pydantic_model:: Chunk
- module:
foodscholar.io.chunk
Bases: :py:class:
~pydantic.main.BaseModel- Fields:
- py:
obj:
chunk_id (str) <foodscholar.io.chunk.Chunk.chunk_id>
- py:
obj:
created_at (datetime.datetime) <foodscholar.io.chunk.Chunk.created_at>
- py:
obj:
embedding (list[float] | None) <foodscholar.io.chunk.Chunk.embedding>
- py:
obj:
embedding_model (str | None) <foodscholar.io.chunk.Chunk.embedding_model>
- py:
obj:
enrichment_version (str) <foodscholar.io.chunk.Chunk.enrichment_version>
- py:
obj:
entity_links (list[foodscholar.io.chunk.EntityLink]) <foodscholar.io.chunk.Chunk.entity_links>
- py:
obj:
foodon_ids (list[str]) <foodscholar.io.chunk.Chunk.foodon_ids>
- py:
obj:
mentions (list[foodscholar.io.chunk.Mention]) <foodscholar.io.chunk.Chunk.mentions>
- py:
obj:
section_type (Literal['abstract', 'results', 'discussion', 'methods', 'introduction', 'conclusion', 'guideline', 'textbook', 'other']) <foodscholar.io.chunk.Chunk.section_type>
- py:
obj:
shelf_ids (list[str]) <foodscholar.io.chunk.Chunk.shelf_ids>
- py:
obj:
source_doc_id (str) <foodscholar.io.chunk.Chunk.source_doc_id>
- py:
obj:
source_metadata (dict[str, object]) <foodscholar.io.chunk.Chunk.source_metadata>
- py:
obj:
source_type (Literal['abstract', 'textbook', 'guide']) <foodscholar.io.chunk.Chunk.source_type>
- py:
obj:
text (str) <foodscholar.io.chunk.Chunk.text>
- py:
obj:
theme_ids (list[str]) <foodscholar.io.chunk.Chunk.theme_ids>
- py:
obj:
year (int | None) <foodscholar.io.chunk.Chunk.year>
.. py:pydantic_model:: Mention
- module:
foodscholar.io.chunk
Bases: :py:class:
~pydantic.main.BaseModel- Fields:
- py:
obj:
end (int) <foodscholar.io.chunk.Mention.end>
- py:
obj:
entity_type (Literal['food', 'nutrient', 'micronutrient', 'macronutrient', 'food component', 'dietary supplement', 'dietary pattern', 'medical condition', 'biomarker', 'Country', 'Measurement', 'Population', 'Time expression', 'other']) <foodscholar.io.chunk.Mention.entity_type>
- py:
obj:
ner_model_version (str) <foodscholar.io.chunk.Mention.ner_model_version>
- py:
obj:
score (float) <foodscholar.io.chunk.Mention.score>
- py:
obj:
start (int) <foodscholar.io.chunk.Mention.start>
- py:
obj:
text (str) <foodscholar.io.chunk.Mention.text>
.. py:pydantic_model:: EntityLink
- module:
foodscholar.io.chunk
Bases: :py:class:
~pydantic.main.BaseModel- Fields:
- py:
obj:
confidence (float) <foodscholar.io.chunk.EntityLink.confidence>
- py:
obj:
linker_version (str) <foodscholar.io.chunk.EntityLink.linker_version>
- py:
obj:
mention (foodscholar.io.chunk.Mention) <foodscholar.io.chunk.EntityLink.mention>
- py:
obj:
method (Literal['lexical_exact', 'lexical_fuzzy', 'dense', 'llm']) <foodscholar.io.chunk.EntityLink.method>
- py:
obj:
ontology_id (str) <foodscholar.io.chunk.EntityLink.ontology_id>
Graph¶
The nodes of the knowledge graph. A Shelf is a Layer A backbone node, a Theme is a
Layer B community, and a Card is a Layer C write-up. See the layer concept pages
(A, B,
C).
.. py:pydantic_model:: Shelf
- module:
foodscholar.io.graph
Bases: :py:class:
~pydantic.main.BaseModel- Fields:
- py:
obj:
chunk_count (int) <foodscholar.io.graph.Shelf.chunk_count>
- py:
obj:
depth (int) <foodscholar.io.graph.Shelf.depth>
- py:
obj:
display_label (str | None) <foodscholar.io.graph.Shelf.display_label>
- py:
obj:
facet (Literal['foods', 'health', 'sustainability', 'dietary_patterns', 'allergies', 'nutrients']) <foodscholar.io.graph.Shelf.facet>
- py:
obj:
foodon_id (str | None) <foodscholar.io.graph.Shelf.foodon_id>
- py:
obj:
label (str) <foodscholar.io.graph.Shelf.label>
- py:
obj:
parent_shelf_id (str | None) <foodscholar.io.graph.Shelf.parent_shelf_id>
- py:
obj:
see_also (list[str]) <foodscholar.io.graph.Shelf.see_also>
- py:
obj:
shelf_id (str) <foodscholar.io.graph.Shelf.shelf_id>
- py:
obj:
status (Literal['active', 'folded', 'absent']) <foodscholar.io.graph.Shelf.status>
- py:
obj:
support_direct (int) <foodscholar.io.graph.Shelf.support_direct>
- py:
obj:
support_lifted (int) <foodscholar.io.graph.Shelf.support_lifted>
.. py:pydantic_model:: Theme
- module:
foodscholar.io.graph
Bases: :py:class:
~pydantic.main.BaseModel- Fields:
- py:
obj:
chunk_count (int) <foodscholar.io.graph.Theme.chunk_count>
- py:
obj:
config_hash (str) <foodscholar.io.graph.Theme.config_hash>
- py:
obj:
discovered_by (Literal['leiden', 'hdbscan', 'bertopic']) <foodscholar.io.graph.Theme.discovered_by>
- py:
obj:
discovery_pass (Literal['relatedness', 'merged', 'global_similarity']) <foodscholar.io.graph.Theme.discovery_pass>
- py:
obj:
discovery_version (str) <foodscholar.io.graph.Theme.discovery_version>
- py:
obj:
facet (Literal['foods', 'health', 'sustainability', 'dietary_patterns', 'allergies', 'nutrients']) <foodscholar.io.graph.Theme.facet>
- py:
obj:
foodon_id_signature (list[str]) <foodscholar.io.graph.Theme.foodon_id_signature>
- py:
obj:
keyword_terms (list[str]) <foodscholar.io.graph.Theme.keyword_terms>
- py:
obj:
label (str) <foodscholar.io.graph.Theme.label>
- py:
obj:
parent_theme_id (str | None) <foodscholar.io.graph.Theme.parent_theme_id>
- py:
obj:
shelf_ids (list[str]) <foodscholar.io.graph.Theme.shelf_ids>
- py:
obj:
theme_id (str) <foodscholar.io.graph.Theme.theme_id>
- py:
obj:
version (str) <foodscholar.io.graph.Theme.version>
.. py:pydantic_model:: Card
- module:
foodscholar.io.graph
Bases: :py:class:
~pydantic.main.BaseModel- Fields:
- py:
obj:
card_id (str) <foodscholar.io.graph.Card.card_id>
- py:
obj:
cited_chunk_ids (list[str]) <foodscholar.io.graph.Card.cited_chunk_ids>
- py:
obj:
confidence_note (str | None) <foodscholar.io.graph.Card.confidence_note>
- py:
obj:
controversy_note (str | None) <foodscholar.io.graph.Card.controversy_note>
- py:
obj:
embedding (list[float] | None) <foodscholar.io.graph.Card.embedding>
- py:
obj:
embedding_model (str | None) <foodscholar.io.graph.Card.embedding_model>
- py:
obj:
evidence_quality (Literal['high', 'medium', 'low', 'debated', 'unclear']) <foodscholar.io.graph.Card.evidence_quality>
- py:
obj:
evidence_sentences (list[str]) <foodscholar.io.graph.Card.evidence_sentences>
- py:
obj:
generated_at (datetime.datetime) <foodscholar.io.graph.Card.generated_at>
- py:
obj:
llm_model (str) <foodscholar.io.graph.Card.llm_model>
- py:
obj:
prompt_version (str) <foodscholar.io.graph.Card.prompt_version>
- py:
obj:
safety_flagged (bool) <foodscholar.io.graph.Card.safety_flagged>
- py:
obj:
summary (str) <foodscholar.io.graph.Card.summary>
- py:
obj:
target_id (str) <foodscholar.io.graph.Card.target_id>
- py:
obj:
target_type (Literal['shelf', 'theme']) <foodscholar.io.graph.Card.target_type>
- py:
obj:
tip (str | None) <foodscholar.io.graph.Card.tip>
- py:
obj:
title (str) <foodscholar.io.graph.Card.title>
Entities & ontology terms¶
Entity is a deduplicated, corpus-aggregated view of a linked ontology id (produced by
build_entities); OntologyTerm is a single FoodOn class as loaded from the ontology.
.. py:pydantic_model:: Entity
- module:
foodscholar.io.entity
Bases: :py:class:
~pydantic.main.BaseModelA first-class entity discovered in the corpus.
ontology_idis the canonicalPREFIX:LOCALID(e.g.FOODON:03309927,CHEBI:16526). Theprefixfield is the OBO source ontology — callers filter on it to scope to FoodOn-only or any other vocabulary subset.- Fields:
- py:
obj:
ancestor_ids (tuple[str, ...]) <foodscholar.io.entity.Entity.ancestor_ids>
- py:
obj:
chunk_count (int) <foodscholar.io.entity.Entity.chunk_count>
- py:
obj:
chunk_ids (tuple[str, ...]) <foodscholar.io.entity.Entity.chunk_ids>
- py:
obj:
facet_hint (Literal['foods', 'health', 'sustainability', 'dietary_patterns', 'allergies', 'nutrients'] | None) <foodscholar.io.entity.Entity.facet_hint>
- py:
obj:
label (str) <foodscholar.io.entity.Entity.label>
- py:
obj:
last_seen (datetime.datetime) <foodscholar.io.entity.Entity.last_seen>
- py:
obj:
mention_count (int) <foodscholar.io.entity.Entity.mention_count>
- py:
obj:
ontology_id (str) <foodscholar.io.entity.Entity.ontology_id>
- py:
obj:
prefix (str) <foodscholar.io.entity.Entity.prefix>
- py:
obj:
synonyms (tuple[str, ...]) <foodscholar.io.entity.Entity.synonyms>
.. py:pydantic_field:: Entity.prefix
- module:
foodscholar.io.entity
- type:
str
- required:
.. py:pydantic_field:: Entity.label :module: foodscholar.io.entity :type: str :required:
.. py:pydantic_field:: Entity.ancestor_ids :module: foodscholar.io.entity :type: tuple[OntologyId, …] :optional:
.. py:pydantic_field:: Entity.facet_hint :module: foodscholar.io.entity :type: Facet | None :value: None
.. py:pydantic_field:: Entity.mention_count :module: foodscholar.io.entity :type: int :value: 0
.. py:pydantic_field:: Entity.chunk_count :module: foodscholar.io.entity :type: int :value: 0
.. py:pydantic_field:: Entity.chunk_ids :module: foodscholar.io.entity :type: tuple[str, …] :optional:
.. py:pydantic_model:: OntologyTerm
- module:
foodscholar.io.ontology
Bases: :py:class:
~pydantic.main.BaseModelA flattened, query-ready ontology term.
ancestor_idsis the closed transitive set of ancestors so downstream phases (layer_a propagation, the linker’s semantic-type gate) don’t have to re-walk the tree.parent_idsis the direct-parent set, kept separate for tree walks.- Fields:
- py:
obj:
ancestor_ids (tuple[str, ...]) <foodscholar.io.ontology.OntologyTerm.ancestor_ids>
- py:
obj:
id (str) <foodscholar.io.ontology.OntologyTerm.id>
- py:
obj:
label (str) <foodscholar.io.ontology.OntologyTerm.label>
- py:
obj:
obsolete (bool) <foodscholar.io.ontology.OntologyTerm.obsolete>
- py:
obj:
parent_ids (tuple[str, ...]) <foodscholar.io.ontology.OntologyTerm.parent_ids>
- py:
obj:
related_synonyms (tuple[str, ...]) <foodscholar.io.ontology.OntologyTerm.related_synonyms>
- py:
obj:
synonyms (tuple[str, ...]) <foodscholar.io.ontology.OntologyTerm.synonyms>
Run metadata¶
.. py:pydantic_model:: ArtifactMeta
- module:
foodscholar.io.artifacts
Bases: :py:class:
~pydantic.main.BaseModel- Fields:
- py:
obj:
artifact_id (str) <foodscholar.io.artifacts.ArtifactMeta.artifact_id>
- py:
obj:
config_hash (str) <foodscholar.io.artifacts.ArtifactMeta.config_hash>
- py:
obj:
created_at (datetime.datetime) <foodscholar.io.artifacts.ArtifactMeta.created_at>
- py:
obj:
phase (str) <foodscholar.io.artifacts.ArtifactMeta.phase>
- py:
obj:
record_count (int) <foodscholar.io.artifacts.ArtifactMeta.record_count>
- py:
obj:
schema_version (str) <foodscholar.io.artifacts.ArtifactMeta.schema_version>
- py:
obj:
upstream_artifact_ids (list[str]) <foodscholar.io.artifacts.ArtifactMeta.upstream_artifact_ids>