MCPcopy Index your code
hub / github.com/MarchLiu/hypatia

github.com/MarchLiu/hypatia @main

Chat with this repo
repository ↗ · DeepWiki ↗ · + Follow
470 symbols 1,248 edges 40 files 106 documented · 23%
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

Hypatia

"We can wander through the stacks of the Library of Alexandria, imagining the scrolls and the knowledge they contain. Its destruction is a warning: all we have is transient."——Alberto Manguel

AI-oriented memory management system. Stores structured knowledge as a graph of Knowledge entries (nodes) and Statement triples (edges), queried via a custom JSON Search Expression (JSE) language. Built on SQLite FTS5 + DuckDB, with configurable embedding models (local ONNX or remote API) for semantic vector search.

Features

  • Knowledge Graph -- Knowledge entries (named info points with tags) and Statement triples (subject-predicate-object with temporal ranges)
  • JSE Query Engine -- JSON-based query language compiling to parameterized SQL + FTS5, supporting $and, $or, $not, $eq, $ne, $gt, $lt, $contains, $like, $content, $search, $quote, $triple, $k-hop
  • Dual-Database Storage -- DuckDB for structured queries + vector search, SQLite FTS5 (Porter stemmer + multi-column BM25) for full-text search, auto-synchronized
  • Configurable Vector Search -- Local ONNX models (BGE-M3 default) or remote API (OpenAI-compatible) for semantic similarity search via DuckDB cosine distance
  • Synonyms -- Per-entry synonym lists for knowledge, per-position (subject/predicate/object) synonyms for statements, indexed in FTS
  • Shelf System -- Named, connectable, exportable data directories for isolation
  • CLI + REPL -- Full command-line interface with interactive mode (rustyline)
  • Agent Integration -- Claude Code skill for natural-language-to-CLI translation
  • Cross-Platform -- Build for 18+ targets (Linux, macOS, Windows, FreeBSD, NetBSD, illumos, Android)

Quick Start

# Build
cargo build --release

# Download embedding model (BGE-M3, recommended)
mkdir -p ~/.hypatia/default
hf download BAAI/bge-m3 --local-dir /tmp/bge-m3
cp /tmp/bge-m3/onnx/model.onnx ~/.hypatia/default/embedding_model.onnx
cp /tmp/bge-m3/onnx/model.onnx_data ~/.hypatia/default/model.onnx_data
cp /tmp/bge-m3/onnx/tokenizer.json ~/.hypatia/default/tokenizer.json

# Create knowledge
hypatia knowledge-create "Rust" -d "systems programming language" -t "language,compiled"

# Create a relationship
hypatia statement-create "Rust" "is_a" "systems language"

# Full-text search
hypatia search "programming language"

# Vector similarity search (requires embedding model)
hypatia backfill    # generate embeddings for existing entries
hypatia similar "programming language"  # semantic search

# Structured query (JSE)
hypatia query '["$knowledge", ["$eq", "name", "Rust"]]'
hypatia query '["$statement", ["$triple", "Rust", "$*", "$*"]]'
hypatia query '["$knowledge", ["$search", "database migration"]]'

# Interactive REPL
hypatia repl

Embedding Models

Hypatia supports multiple embedding backends, configured via shelf.toml in the shelf directory (e.g., ~/.hypatia/default/shelf.toml).

Default: BAAI/bge-m3 (Local ONNX)

No configuration needed — place model files in the shelf directory and Hypatia auto-detects them.

# Download from HuggingFace
hf download BAAI/bge-m3 --local-dir /tmp/bge-m3
cp /tmp/bge-m3/onnx/model.onnx ~/.hypatia/default/embedding_model.onnx
cp /tmp/bge-m3/onnx/model.onnx_data ~/.hypatia/default/model.onnx_data
cp /tmp/bge-m3/onnx/tokenizer.json ~/.hypatia/default/tokenizer.json
  • Dimensions: 1024
  • Max sequence length: 8192
  • Multilingual (100+ languages including Chinese and English)

Switching to Other Local Models

Create or edit ~/.hypatia/default/shelf.toml:

[embedding]
provider = "local"
dimensions = 1536
max_seq_length = 8192

Alibaba-NLP/gte-Qwen2-1.5B-instruct

hf download Alibaba-NLP/gte-Qwen2-1.5B-instruct --local-dir /tmp/gte-qwen2
# Export ONNX first (requires optimum-cli or transformers)
# Then place files in shelf directory
  • Dimensions: 1536
  • Max sequence length: 8192
  • Strong multilingual performance

google/embedding-gemma-300M (EmbeddingGemma)

hf download google/embedding-gemma-300M --local-dir /tmp/embedding-gemma
# Export ONNX and place files
  • Dimensions: 768
  • Max sequence length: 8192
  • Lightweight, fast inference

jinaai/jina-embeddings-v5-text-small

hf download jinaai/jina-embeddings-v5-text-small-text-matching \
  onnx/model.onnx onnx/model.onnx_data tokenizer.json \
  --local-dir /tmp/jina-v5-small
cp /tmp/jina-v5-small/onnx/model.onnx ~/.hypatia/default/embedding_model.onnx
cp /tmp/jina-v5-small/onnx/model.onnx_data ~/.hypatia/default/model.onnx_data
cp /tmp/jina-v5-small/tokenizer.json ~/.hypatia/default/tokenizer.json

shelf.toml:

[embedding]
provider = "local"
dimensions = 1024
max_seq_length = 32768
pooling = "last_token"
  • Dimensions: 1024
  • Max sequence length: 32768
  • 677M params, last-token pooling

jinaai/jina-embeddings-v5-text-nano

hf download jinaai/jina-embeddings-v5-text-nano-text-matching \
  onnx/model.onnx onnx/model.onnx_data tokenizer.json \
  --local-dir /tmp/jina-v5-nano
cp /tmp/jina-v5-nano/onnx/model.onnx ~/.hypatia/default/embedding_model.onnx
cp /tmp/jina-v5-nano/onnx/model.onnx_data ~/.hypatia/default/model.onnx_data
cp /tmp/jina-v5-nano/tokenizer.json ~/.hypatia/default/tokenizer.json

shelf.toml:

[embedding]
provider = "local"
dimensions = 768
max_seq_length = 8192
pooling = "last_token"
  • Dimensions: 768
  • Max sequence length: 8192
  • 239M params, last-token pooling, fastest inference

Remote API (OpenAI-Compatible)

For cloud-based embeddings without local model files:

[embedding]
provider = "remote"
api_url = "https://api.openai.com/v1/embeddings"
api_key_env = "OPENAI_API_KEY"
api_model = "text-embedding-3-small"
dimensions = 1536

Works with any OpenAI-compatible API: - OpenAI (text-embedding-3-small, text-embedding-3-large) - Azure OpenAI - Local servers (Ollama, LM Studio, vLLM) - Other providers (Voyage AI, Cohere, Jina, Gitee AI)

Ollama Example

[embedding]
provider = "remote"
api_url = "http://localhost:11434/v1/embeddings"
api_key_env = "OLLAMA_API_KEY"
api_model = "qwen3-embedding:8b"
dimensions = 1024
# Set a dummy key (Ollama doesn't require auth)
export OLLAMA_API_KEY="ollama"

Set the API key as an environment variable:

export OPENAI_API_KEY="sk-..."

Configuration Reference

Field Default Description
provider "local" "local" for ONNX, "remote" for HTTP API
dimensions 1024 Embedding vector dimensions
max_seq_length 8192 Max tokenizer sequence length (local only)
pooling "mean" Pooling strategy: "mean", "cls", or "last_token" (local only)
model_path embedding_model.onnx ONNX model path, relative to shelf dir (local only)
tokenizer_path tokenizer.json Tokenizer path, relative to shelf dir (local only)
api_url OpenAI URL API endpoint URL (remote only)
api_key_env OPENAI_API_KEY Environment variable name for API key (remote only)
api_model text-embedding-3-small Model name sent to API (remote only)

CLI Reference

Command Description
hypatia connect <path> [-n <name>] Connect to a shelf directory
hypatia disconnect <name> Disconnect from a shelf
hypatia list List connected shelves
hypatia knowledge-create <name> [-d <data>] [-t <tags>] [--synonyms <csv>] [--figures <refs>] Create a knowledge entry
hypatia knowledge-get <name> Get a knowledge entry
hypatia knowledge-delete <name> Delete a knowledge entry
hypatia statement-create <subj> <pred> <obj> [-d <data>] [--synonyms <json>] Create a triple
hypatia statement-delete <subj> <pred> <obj> Delete a triple
hypatia search <query> [-c <catalog>] [--limit N] Full-text search
hypatia similar <query> [--limit N] Vector similarity search
hypatia backfill Generate embeddings for all entries
hypatia archive-store <file> [-n <name>] [-s <shelf>] Store a file in archives with auto-metadata
hypatia archive-get <name> [-o <output>] [-s <shelf>] Get an archive file path or copy it
hypatia archive-list [-s <shelf>] List all archive files
hypatia query '<jse-json>' Execute a JSE query
hypatia export <name> <dest> Export a shelf
hypatia repl Interactive REPL

JSE Query Language

JSE (JSON Search Expression) enables precise queries against knowledge or statement tables.

Syntax

["$knowledge", condition1, condition2, ...]
["$statement", condition1, condition2, ...]

Operators

Operator Purpose Example
$eq Equals ["$eq", "name", "Rust"]
$ne Not equals ["$ne", "name", "Rust"]
$gt / $lt / $gte / $lte Comparison ["$gt", "created_at", "2025-01-01"]
$contains Substring in JSON field ["$contains", "tags", "backend"]
$like SQL LIKE pattern match ["$like", "name", "Rust%"]
$content Match content JSON key-values ["$content", {"format": "markdown"}]
$search Full-text search ["$search", "database migration"]
$and Logical AND ["$and", cond1, cond2]
$or Logical OR ["$or", cond1, cond2]
$not Logical NOT ["$not", cond]
$quote Prevent evaluation ["$quote", ["$eq", "x", "y"]]
$triple Triple position match ["$triple", "Alice", "$*", "Bob"]
$k-hop K-hop graph traversal ["$k-hop", "Alice", "$*", 2]

Examples

# All knowledge entries
hypatia query '["$knowledge"]'

# Knowledge named "Rust" with tag "systems"
hypatia query '["$knowledge", ["$and", ["$eq", "name", "Rust"], ["$contains", "tags", "systems"]]]'

# Statements containing "Alice" in triple
hypatia query '["$statement", ["$contains", "triple", "Alice"]]'

# Triple matching: all relationships where Alice is the subject
hypatia query '["$statement", ["$triple", "Alice", "$*", "$*"]]'

# Triple matching: all "manages" relationships
hypatia query '["$statement", ["$triple", "$*", "manages", "$*"]]'

# Triple matching: exact triple (uses PK index)
hypatia query '["$statement", ["$triple", "Alice", "knows", "Bob"]]'

# Pattern matching: names starting with "Al"
hypatia query '["$knowledge", ["$like", "name", "Al%"]]'

# Content filtering: all markdown entries
hypatia query '["$knowledge", ["$content", {"format": "markdown"}]]'

# FTS search within knowledge
hypatia query '["$knowledge", ["$search", "query optimization"]]'

# Statements where triple contains Alice or Bob
hypatia query '["$statement", ["$or", ["$contains", "triple", "Alice"], ["$contains", "triple", "Bob"]]]'

# K-hop: all entities reachable from Alice in 2 hops
hypatia query '["$statement", ["$k-hop", "Alice", "$*", 2]]'

# K-hop: follow "knows" edges from Alice, 3 hops deep
hypatia query '["$statement", ["$k-hop", "Alice", "knows", 3]]'

Architecture

src/
├── cli/            # CLI commands + REPL (clap + rustyline)
├── embedding/      # Embedding providers (ONNX local + remote API)
├── engine/         # JSE parser, AST, evaluator, SQL builder
├── model/          # Knowledge, Statement, Content, Query types
├── service/        # Business logic (dual-write to DuckDB + SQLite)
├── storage/        # DuckDB store, SQLite FTS5 store, shelf manager
├── lab.rs          # Top-level API facade
├── error.rs        # Error types
├── lib.rs          # Module declarations
└── main.rs         # Entry point

Each shelf is a directory containing data.duckdb (structured data), index.sqlite (FTS5 index), optional shelf.toml (embedding config), embedding model files, and an archives/ directory for attachments. The service layer keeps both databases in sync via dual-write.

Archive Files

Hypatia supports storing archive files (images, PDFs, data, etc.) alongside knowledge entries. Files are stored in the shelf's archives/ directory and referenced via the archive:// convention in knowledge content.

~/.hypatia/default/
├── data.duckdb
├── index.sqlite
├── shelf.toml
└── archives/
    └── euclid/
        ├── fig_1_1.png
        └── fig_1_2.svg

Commands

# Store a file (auto-creates knowledge with metadata)
hypatia archive-store figure.png -n euclid/fig_1_1.png

# Get the path to a stored archive file
hypatia archive-get euclid/fig_1_1.png

# Copy an archive file to a local path
hypatia archive-get euclid/fig_1_1.png -o /tmp/fig.png

# List all archive files
hypatia archive-list

# Reference an archive when creating knowledge
hypatia knowledge-create "Euclid Prop 1" \
  -d "Construction of equilateral triangle" \
  --figures "archive://euclid/fig_1_1.png"

Auto-Created Metadata

archive-store automatically creates:

  1. Knowledge entry with name = archive path, containing filename, size, and MIME type
  2. Statement: <path> is_a archive (graph connectivity)

This enables JSE queries on archive metadata:

hypatia query '["$knowledge", ["$contains", "tags", "archive"]]'
hypatia query '["$knowledge", ["$content", {"mime_type": "image/png"}]]'
hypatia query '["$statement", ["$triple", "$*", "is_a", "archive"]]'

Convention

  • Storage: Files go in <shelf>/archives/<path> on the filesystem
  • Reference: Use archive://<path> in knowledge content's figures field
  • Resolution: archive://euclid/fig.png resolves to <shelf>/archives/euclid/fig.png
  • Export: hypatia export copies the archives/ directory along with databases
  • No cascade delete: Deleting a knowledge entry does not remove the archive file

Benchmark

LoCoMo Academic Benchmark

Tested on the LoCoMo long-term conversational memory benchmark (ACL 2024, 10 conversations, 1,540 non-adversarial QA pairs, 6,426 entries). Measures whether the correct evidence passage is found in top-K

Extension points exported contracts — how you extend this code

EmbeddingProvider (Interface)
Trait for embedding providers (local ONNX or remote API). [3 implementers]
src/embedding/provider.rs
Storage (Interface)
Abstract storage interface for testability. OpenShelf implements this trait by delegating to DuckDB/SQLite stores. Note: [2 …
src/storage/mod.rs
TextSegmenter (Interface)
Trait for text segmentation/tokenization. Future implementations could use LLM-based tokenizers. [1 implementers]
src/text.rs

Core symbols most depended-on inside this repo

get
called by 86
src/service/knowledge.rs
get
called by 51
src/storage/shelf_manager.rs
setup
called by 18
src/storage/duckdb_store.rs
contains
called by 18
src/storage/shelf_registry.rs
insert_statement
called by 16
src/storage/duckdb_store.rs
upsert_doc
called by 15
src/storage/sqlite_store.rs
connect
called by 13
src/storage/shelf_manager.rs
get_mut
called by 13
src/storage/shelf_manager.rs

Shape

Function 233
Method 164
Class 57
Enum 13
Interface 3

Languages

Rust96%
Python4%

Modules by API surface

src/storage/duckdb_store.rs48 symbols
src/embedding/config.rs41 symbols
src/engine/evaluator.rs36 symbols
src/storage/shelf_manager.rs31 symbols
src/model/content.rs27 symbols
tests/bench_data.rs24 symbols
src/lab.rs22 symbols
src/storage/sqlite_store.rs21 symbols
src/embedding/provider.rs21 symbols
tests/longmemeval.rs18 symbols
src/engine/operators.rs18 symbols
src/storage/shelf_registry.rs16 symbols

For agents

$ claude mcp add hypatia \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact