Overview
Relationship attributes extend edges with structured properties (similar to entity attributes on nodes). They are defined in the ontology per relationship triple (source entity type, relationship type, target entity type), configured per content type, extracted by the LLM as JSON on each edge, filtered to allowed keys, and written to the graph as relationship properties where applicable.Data model
- Ontology defines relationships between entity types and optional relationship attributes (name, type, extraction defaults, enum options).
- Content types persist selections and overrides under
DocumentType.metadata["relations"]. - Extraction JSON uses instance names on edges:
{ "source": "<name>", "type": "<REL_TYPE>", "target": "<name>", "attributes": { ... } }. That differs from schema lines in prompts, which show entity type labels for source/target.
Available entities API
GET /api/ingestion/content_types/available_entities/ returns the default ontology via
extract_schema_structure(), which normalizes relationship attributes the same way as node attributes
(stable extraction_instructions, enum options, optional semantic_intent).
Prompt construction
DocumentTypeConfig.get_document_type_config() builds prompt_config["relationships"] with
attributes as attribute name → extraction instruction text.
build_prompt() / build_completion_prompt() (and paginated prompts) append those instructions per
triple so the model knows which keys may appear under relationships[].attributes.
Filtering extracted attributes
filter_relationship_attributes_by_config() restricts keys to those allowed on the document type.
Schema triples use entity type names for source/target; extracted edges use instance names.
relationship_key_for_schema_lookup() resolves instance names to entity types using the extracted
entities list before lookup. If a triple cannot be aligned to the schema map, extracted attributes are
not blindly cleared (avoids dropping valid LLM output when matching is imperfect).
Graph and LLM schema context
Relationship properties are reflected in graph introspection and LLM-facing schema strings on both Neo4j and FalkorDB. Helpers live inexperio.neo4j_graph.schema_helpers (shared formatting and
ontology filtering).
Fan-out statistics — For each relationship triple in the schema, Experio computes
fan_out_risk, max distinct targets per source, and max distinct sources per target from live graph
data. A single portable batch Cypher query runs on whichever provider is active (no Neo4j 5.23+
scoped subquery required). Stats are cached with the schema (24h TTL); refresh after deploy or
provider switch.
Related code
See also
- Content Types (admin workflow)
server/experio/ingestion/README.md(developer notes)