mirror of
https://github.com/basicmachines-co/basic-memory
synced 2026-06-21 13:47:35 +00:00
203 lines
6.1 KiB
Python
203 lines
6.1 KiB
Python
"""Core pydantic models for basic-memory entities, observations, and relations.
|
|
|
|
This module defines the foundational data structures for the knowledge graph system.
|
|
The graph consists of entities (nodes) connected by relations (edges), where each
|
|
entity can have multiple observations (facts) attached to it.
|
|
|
|
Key Concepts:
|
|
1. Entities are nodes with a type and name, storing factual observations
|
|
2. Relations are directed edges between entities using active voice verbs
|
|
3. Observations are atomic facts/notes about an entity
|
|
4. Everything is stored in both SQLite and markdown files
|
|
5. Entity IDs are auto-generated as '{type}/{normalized_name}'
|
|
|
|
Common Entity Types:
|
|
- 'person': People (contributors, users, etc.)
|
|
- 'project': Major initiatives or repositories
|
|
- 'component': Software components/modules
|
|
- 'concept': Ideas or abstract concepts
|
|
- 'conversation': Chat discussions
|
|
- 'document': Documentation or specifications
|
|
- 'implementation': Specific code implementations
|
|
- 'test': Test suites or test cases
|
|
|
|
Common Relation Types:
|
|
- 'created': Attribution of creation
|
|
- 'depends_on': Technical dependency
|
|
- 'implements': Implementation of concept/design
|
|
- 'documents': Documentation relationship
|
|
- 'related_to': General relation
|
|
- 'part_of': Compositional relationship
|
|
- 'extends': Inheritance/extension
|
|
- 'tested_by': Test coverage
|
|
"""
|
|
|
|
from typing import List, Optional, Annotated
|
|
|
|
from annotated_types import MinLen, MaxLen
|
|
from pydantic import BaseModel, BeforeValidator
|
|
|
|
|
|
# Strip whitespace
|
|
def strip_whitespace(obs: str) -> str:
|
|
return obs.strip()
|
|
|
|
|
|
def lower_strip_whitespace(val: str) -> str:
|
|
return strip_whitespace(val.lower())
|
|
|
|
|
|
Observation = Annotated[str, BeforeValidator(strip_whitespace), MinLen(1), MaxLen(1000)]
|
|
"""A single piece of information about an entity. Must be non-empty and under 1000 characters.
|
|
|
|
Best Practices:
|
|
- Keep observations atomic (one fact per observation)
|
|
- Use clear, complete sentences
|
|
- Include context when relevant
|
|
- Avoid duplicating information
|
|
|
|
Examples:
|
|
- "Implements SQLite storage for persistence"
|
|
- "Created on December 10, 2024"
|
|
- "Depends on SQLAlchemy for database operations"
|
|
"""
|
|
|
|
EntityType = Annotated[str, BeforeValidator(strip_whitespace), MinLen(1), MaxLen(200)]
|
|
"""Classification of entity (e.g., 'person', 'project', 'concept').
|
|
|
|
The type serves multiple purposes:
|
|
1. Organizes entities in the filesystem
|
|
2. Enables filtering and querying
|
|
3. Provides context for relations
|
|
4. Helps generate meaningful IDs
|
|
|
|
Common types are listed in the module docstring.
|
|
"""
|
|
|
|
RelationType = Annotated[str, BeforeValidator(strip_whitespace), MinLen(1), MaxLen(200)]
|
|
"""Type of relationship between entities. Always use active voice present tense.
|
|
|
|
Guidelines:
|
|
1. Use verbs that clearly describe the relationship
|
|
2. Keep it concise but unambiguous
|
|
3. Consider bidirectional meaning
|
|
4. Use established types when possible
|
|
|
|
Common types are listed in the module docstring.
|
|
"""
|
|
|
|
|
|
class Relation(BaseModel):
|
|
"""Represents a directed edge between entities in the knowledge graph.
|
|
|
|
Relations are directed connections stored in active voice (e.g., "created", "depends_on").
|
|
The from_id represents the source or actor entity, while to_id represents the target
|
|
or recipient entity.
|
|
|
|
Example Relations:
|
|
1. Person creates Project:
|
|
{
|
|
"from_id": "person/alice",
|
|
"to_id": "project/basic_memory",
|
|
"relation_type": "created"
|
|
}
|
|
|
|
2. Component depends on another:
|
|
{
|
|
"from_id": "component/memory_service",
|
|
"to_id": "component/database_service",
|
|
"relation_type": "depends_on"
|
|
}
|
|
|
|
3. Test validates Implementation:
|
|
{
|
|
"from_id": "test/memory_service_test",
|
|
"to_id": "implementation/memory_service",
|
|
"relation_type": "validates"
|
|
}
|
|
|
|
4. Document describes Component:
|
|
{
|
|
"from_id": "document/architecture_spec",
|
|
"to_id": "component/memory_service",
|
|
"relation_type": "describes"
|
|
}
|
|
"""
|
|
|
|
from_id: int
|
|
to_id: int
|
|
relation_type: RelationType
|
|
context: Optional[str] = None
|
|
|
|
|
|
class Entity(BaseModel):
|
|
"""Represents a node in our knowledge graph - could be a person, project, concept, etc.
|
|
|
|
Each entity has:
|
|
- A unique name (used to generate its ID)
|
|
- An entity type (for classification)
|
|
- A list of observations (facts/notes about the entity)
|
|
- Optional relations to other entities
|
|
- Optional description for high-level overview
|
|
|
|
Example Entities:
|
|
|
|
1. Project Entity:
|
|
{
|
|
"name": "Basic_Memory",
|
|
"entity_type": "project",
|
|
"description": "Knowledge graph system for AI-human collaboration",
|
|
"observations": [
|
|
"Uses SQLite for local-first storage",
|
|
"Implements MCP protocol for AI interaction",
|
|
"Provides markdown file sync"
|
|
]
|
|
}
|
|
|
|
2. Component Entity:
|
|
{
|
|
"name": "MemoryService",
|
|
"entity_type": "component",
|
|
"description": "Core service managing knowledge persistence",
|
|
"observations": [
|
|
"Handles both file and database operations",
|
|
"Implements entity lifecycle management",
|
|
"Uses SQLAlchemy for database access"
|
|
]
|
|
}
|
|
|
|
3. Person Entity:
|
|
{
|
|
"name": "Alice_Smith",
|
|
"entity_type": "person",
|
|
"description": "Lead developer on Basic Memory project",
|
|
"observations": [
|
|
"Focuses on knowledge graph implementation",
|
|
"Created initial SQLite integration"
|
|
]
|
|
}
|
|
|
|
4. Concept Entity:
|
|
{
|
|
"name": "Semantic_Search",
|
|
"entity_type": "concept",
|
|
"description": "Advanced search capabilities in knowledge graphs",
|
|
"observations": [
|
|
"Uses embeddings for semantic matching",
|
|
"Enables natural language queries",
|
|
"Planned for future implementation"
|
|
]
|
|
}
|
|
"""
|
|
|
|
id: Optional[int] = None
|
|
name: str
|
|
entity_type: EntityType
|
|
description: Optional[str] = None
|
|
observations: List[Observation] = []
|
|
|
|
@property
|
|
def file_path(self) -> str:
|
|
"""The relative file path for this entity."""
|
|
return f"{id}.md"
|