Temporal graph memory layer for large language models
Project description
Dagestan
Temporal Graph Memory Layer for LLMs
Dagestan stores LLM memory as a typed temporal knowledge graph instead of flat vector embeddings. It tracks entities, concepts, events, preferences, and goals — with time-aware confidence decay, contradiction detection, and relationship-based retrieval.
Why
Current LLM memory solutions (vector DBs) treat memory as a pile of embeddings retrieved by similarity. They don't understand:
- Time — old information and new information are treated the same
- Relationships — there's no structure between memories
- Contradictions — conflicting facts coexist silently
- Decay — nothing fades; nothing is curated
Dagestan addresses these gaps with a graph-based approach where memory has structure, relationships, and temporal awareness.
Status
v0.1 — Foundation release. Working memory layer with:
- Typed temporal graph (Entity, Concept, Event, Preference, Goal nodes)
- LLM-based knowledge extraction from conversations
- Contradiction detection between conflicting preferences/goals
- Exponential temporal decay on confidence scores
- Gap detection (incomplete entity profiles)
- Bridge node detection (cross-cluster connections)
- Centrality-based importance scoring
- Query-driven graph retrieval (keyword + structure, no embeddings)
- JSON persistence
- CLI for graph inspection
- 63 passing unit tests
Install
# Core (no LLM dependencies)
pip install -e .
# With OpenAI
pip install -e ".[openai]"
# With Anthropic
pip install -e ".[anthropic]"
# Development
pip install -e ".[dev]"
Quick Start
from dagestan import Dagestan
# Initialize with an LLM provider for extraction
mem = Dagestan(provider="openai", db_path="./memory.json")
# Ingest conversation text
mem.ingest("User mentioned they love Python and want to build a startup focused on graph databases.")
# Retrieve relevant context
context = mem.retrieve("What does the user care about?")
print(context)
# Run curation (applies decay, finds contradictions)
report = mem.curate()
print(f"Contradictions found: {report.contradictions_found}")
# Get structured context for next conversation
strategy = mem.strategy()
print(strategy)
Without an LLM (manual graph building)
from dagestan import Dagestan, Node, Edge, NodeType, EdgeType
mem = Dagestan(db_path="./memory.json", auto_save=True)
# Add nodes directly
user = mem.add_node(Node(type=NodeType.ENTITY, label="User"))
pref = mem.add_node(Node(type=NodeType.PREFERENCE, label="Prefers tea"))
goal = mem.add_node(Node(type=NodeType.GOAL, label="Build Dagestan"))
mem.add_edge(Edge(source_id=user.id, target_id=pref.id, type=EdgeType.HAS_PREFERENCE))
mem.add_edge(Edge(source_id=user.id, target_id=goal.id, type=EdgeType.WANTS))
# Query the graph
results = mem.retrieve("user preferences")
print(results)
CLI
# Show graph summary
dagestan info --db ./memory.json
# List all nodes
dagestan nodes --db ./memory.json
# Filter by type
dagestan nodes --type preference --db ./memory.json
# Query the graph
dagestan retrieve "user goals" --db ./memory.json
# Run curation
dagestan curate --db ./memory.json
# Export full graph
dagestan export --db ./memory.json
Architecture
Conversation → Extraction (LLM) → Temporal Graph → Operations → Retrieval
↓
Curation
(decay, contradictions,
gaps, bridges)
Node Types: Entity, Concept, Event, Preference, Goal
Edge Types: relates_to, caused, contradicts, happened_before, has_preference, wants
Temporal Metadata: Every node carries created_at, last_reinforced, confidence_score, and decay_rate. Confidence degrades exponentially unless reinforced by new conversation.
Graph Operations
These run on the graph structure — no LLM needed for computation.
| Operation | What it does |
|---|---|
| Contradiction Detection | Finds conflicting preferences/goals for the same entity |
| Temporal Decay | Reduces confidence based on time since last reinforcement |
| Gap Detection | Identifies entities with incomplete knowledge profiles |
| Bridge Detection | Finds nodes connecting otherwise disconnected clusters |
| Centrality Scoring | Ranks nodes by connection count + recency |
Project Structure
dagestan/
├── __init__.py # Main Dagestan class (public API)
├── cli.py # Command-line interface
├── graph/
│ ├── schema.py # Node, Edge, NodeType, EdgeType
│ ├── temporal_graph.py # Core graph with CRUD + snapshots
│ └── operations.py # Contradiction, decay, gap, bridge, centrality
├── extraction/
│ ├── extractor.py # Conversation → graph via LLM
│ └── prompts.py # Extraction prompt templates
├── curation/
│ ├── curator.py # Curation pipeline orchestrator
│ └── strategy.py # Context strategy generation
├── retrieval/
│ └── retriever.py # Query-driven graph traversal
├── storage/
│ └── store.py # JSON persistence (SQLite planned for v0.2)
├── integrations/ # Planned: drop-in OpenAI/Anthropic wrappers
viz/
├── __init__.py
├── __main__.py # Entry point (python -m viz)
├── server.py # Stdlib HTTP server + REST API + SSE
├── watcher.py # File-change polling (no deps)
├── export.py # LaTeX/TikZ, DOT, CSV export
├── generate_demo.py # Demo graph generator
└── static/
├── index.html # Main UI page
├── style.css # Dark-theme styling
└── app.js # vis-network graph rendering
Visualization
Dagestan ships with a zero-dependency interactive graph visualizer for debugging and exploring your knowledge graphs in the browser.
# Launch with auto-detected graph file
python -m viz.server
# Or point at a specific file and port
python -m viz.server --file demo_memory.json --port 8765
Then open http://localhost:8765.
Features
| Feature | Description |
|---|---|
| Live Graph Rendering | Interactive force-directed layout via vis-network |
| Auto-Refresh / SSE | File watcher detects changes and pushes updates via Server-Sent Events |
| Diff Highlighting | New nodes glow green with a ✦ marker; removed counts shown in dashboard |
| Node & Edge Inspector | Click any element to view full metadata, confidence, decay rate |
| Neighborhood Explorer | Double-click a node to zoom into its local neighborhood |
| Stats Dashboard | Node/edge counts, type distributions, confidence histograms |
| Temporal Decay View | Color-coded confidence levels (green → yellow → red) |
| Filter by Type | Toggle node types on/off |
| Search | Find nodes by label (keyboard shortcut: /) |
| LaTeX / DOT / CSV Export | Export graphs for research papers (TikZ, Graphviz DOT, CSV) |
| File Switcher | Browse and switch between graph JSON files in the project |
| Keyboard Shortcuts | R refresh, F fit view, / search, ? help, Esc clear |
Generate a Demo Graph
python -m viz.generate_demo --output viz_demo_graph.json --nodes 25
python -m viz.server --file viz_demo_graph.json
See viz/README.md for full details.
Roadmap
| Version | Focus | Status |
|---|---|---|
| v0.1 | Core graph, extraction, basic operations, JSON storage | Done |
| v0.2 | SQLite backend, all 5 operations fully tuned | Planned |
| v0.3 | Query-driven traversal improvements, context compression | Planned |
| v1.0 | Benchmarks, paper, honest evaluation vs baselines | Planned |
| v2.0 | Graph operations as reasoning substrate | Research |
Evaluation (LOCOMO Benchmarks)
Dagestan includes an evaluation harness for benchmarking against the LOCOMO benchmark.
Evaluation code/config lives under evals/:
evals/run_locomo_eval.py— main evaluation runner (QA, summarization, coherence)evals/run_ablations.py— ablation study runnerevals/configs/*.yaml— model/data settings (e.g.,smoke_test.yaml,locomo_gemini_flash.yaml)
Quick commands (from repo root):
# Install eval-only dependencies (dataset download / caching)
pip install datasets huggingface_hub pyyaml
# Download/cache the LOCOMO dataset locally
make download-locomo
# Smoke run (fast dry-run)
make smoke
# Full benchmark run
make locomo
# Single tasks
make qa
make summarization
make coherence
# Ablations
make ablations
make ablations-baselines
Notes:
- The runner writes outputs under
evals/results/<run_id>/. - The
make smoketarget uses theprovider: stubsetting fromevals/configs/smoke_test.yaml. If your current Dagestan backend does not supportprovider="stub"for extraction/ingestion, run with a real provider (e.g.,openai/anthropic) by editing the config.
Performance claims should be made only after you complete the benchmark runs.
Constraints
- Zero GPU required — runs on CPU only
- Minimal dependencies — core is stdlib only, LLM client is optional
- LLM-agnostic — works with any provider via simple callable interface
- Storage-agnostic — JSON now, SQLite/Neo4j planned
- Honest evaluation — we measure where it fails, not just where it wins
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dagestan-1.0.0.tar.gz.
File metadata
- Download URL: dagestan-1.0.0.tar.gz
- Upload date:
- Size: 48.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
967eba673eb619bd9f5dbd72e9dddf3bd52c3a9a38b77f52802846befab73e52
|
|
| MD5 |
21098a9c163d6c4c9f7708c9a5c3e8cf
|
|
| BLAKE2b-256 |
882c5a1e6d88d286027e7326390aff6520314930ccbeb7300f9601516bfbf86a
|
File details
Details for the file dagestan-1.0.0-py3-none-any.whl.
File metadata
- Download URL: dagestan-1.0.0-py3-none-any.whl
- Upload date:
- Size: 43.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b3cb99516ae3d7efc644be2a0e087df362120b383e49731ec4ec27afcb9c6c51
|
|
| MD5 |
75c86c1ff18a6a8dcb242dd63ef692f2
|
|
| BLAKE2b-256 |
ca0cc7749dd3c77205e99cf3038fbde4e9e75ad21686f4f6b2cf27cf835f0440
|