Knowledge graph¶
extremis maintains a structured knowledge graph alongside the vector store. Where vectors answer "what's related to this topic?", the graph answers "who works for who?", "what does this entity own?", "how are these things connected?"
When to use it¶
| Question type | Tool |
|---|---|
| "What does the user prefer?" | recall() — semantic search |
| "Who is Alice's manager?" | kg_query() — graph traversal |
| "What timezone is Bob in?" | kg_query() — attribute lookup |
| "What projects is this team working on?" | kg_traverse() — BFS walk |
Entities¶
An entity is a named node with a type:
from extremis.types import EntityType
mem.kg_add_entity("Ashwani", EntityType.PERSON)
mem.kg_add_entity("PropertyFinder", EntityType.ORG)
mem.kg_add_entity("extremis", EntityType.PROJECT)
Available types: PERSON, ORG, PROJECT, GROUP, CONCEPT, OTHER
Relationships¶
A directed edge between two entities:
mem.kg_add_relationship(
"Ashwani", # from
"PropertyFinder", # to
"works_at", # relationship type (any string)
weight=1.0, # confidence 0.0–1.0
)
mem.kg_add_relationship("Ashwani", "extremis", "building")
Attributes¶
Key-value tags on an entity:
mem.kg_add_attribute("Ashwani", "timezone", "Asia/Dubai")
mem.kg_add_attribute("Ashwani", "language", "Python")
mem.kg_add_attribute("Ashwani", "phone", "+971...")
Querying¶
Single entity¶
result = mem.kg_query("Ashwani")
print(result.entity.name) # "Ashwani"
print(result.entity.type) # EntityType.PERSON
for rel in result.relationships:
print(f"{rel.from_entity} → [{rel.rel_type}] → {rel.to_entity}")
for attr in result.attributes:
print(f"{attr.key}: {attr.value}")
BFS traversal¶
Walk the graph up to N hops from an entity:
# Everything reachable in 2 hops from Ashwani
graph = mem.kg_traverse("Ashwani", depth=2)
for entity_result in graph:
print(f"[{entity_result.entity.type.value}] {entity_result.entity.name}")
for rel in entity_result.relationships:
print(f" → [{rel.rel_type}] {rel.to_entity}")
Find by attribute¶
entities = mem.get_kg().query_by_attribute("timezone", "Asia/Dubai")
for e in entities:
print(e.name) # → "Ashwani"
Upsert behaviour¶
All write operations are upserts — calling them multiple times is safe:
# Adding the same entity twice updates it
mem.kg_add_entity("Ashwani", EntityType.PERSON)
mem.kg_add_entity("Ashwani", EntityType.PERSON, metadata={"seniority": "senior"})
# Adding the same relationship updates weight/metadata
mem.kg_add_relationship("A", "B", "knows", weight=0.5)
mem.kg_add_relationship("A", "B", "knows", weight=0.9) # updates weight
Namespace isolation¶
The knowledge graph respects namespaces — entities and relationships are scoped per namespace: