Skip to main content

EdgeVDB — On-device vector database with HNSW, hybrid retrieval, knowledge graph, and CRDT sync

Project description

EdgeVDB Python SDK

Python wrapper for EdgeVDB on-device vector database with ctypes FFI binding.

The EdgeVDB Python SDK provides a Pythonic interface to the EdgeVDB C++ core library using ctypes. It enables Python applications to use EdgeVDB's vector database capabilities on desktop and Raspberry Pi platforms.

Features

  • ctypes FFI Binding — Direct calls to C API with no Python dependencies
  • Context Manager Support — Automatic resource cleanup with with statements
  • Type Hints — Full type annotations for IDE support
  • Zero Python Dependencies — Only standard library and ctypes
  • Cross-Platform — Linux, macOS, Windows, Raspberry Pi
  • Flexible Embedding — Use any embedding provider or built-in ONNX embedder

Installation

From Source

# Build the C++ core first
cd ..
cmake --preset desktop-release
cmake --build build/desktop-release

# Copy shared library to Python package (platform-specific)
# Linux:
cp build/desktop-release/core/libedgevdb_shared.so python/edgevdb/lib/linux/
# macOS:
# cp build/desktop-release/core/libedgevdb_shared.dylib python/edgevdb/lib/darwin/
# Windows:
# copy build\desktop-release\core\edgevdb_shared.dll python\edgevdb\lib\windows\

# Install in development mode
cd python
pip install -e .

From PyPI (after publishing)

pip install edgevdb

Quick Start

Without ONNX (Recommended)

Use embeddings from any provider (OpenAI, Cohere, sentence-transformers, etc.):

from edgevdb import EdgeVDB

# Open database
db = EdgeVDB("./my_database")

# Get embeddings from your preferred provider
# Example with sentence-transformers:
from sentence_transformers import SentenceTransformer
model = SentenceTransformer('all-MiniLM-L6-v2')
embedding = model.encode("Machine learning finds patterns in data")

# Insert with pre-computed embedding
chunk_id = db.insert_chunk(
    text="Machine learning finds patterns in data",
    embedding=embedding,
    doc_id=1,
    page_number=0
)

# Query
query_emb = model.encode("what is ML?")
results = db.query_vector(query_emb, query_text="what is ML?", top_k=5)

for r in results:
    print(f"score={r.score:.3f} text={r.text}")

# Object store
doc_id = db.put_object("Document", {"title": "ML Intro", "author": "Alice"})
db.add_relation("has_chunk", doc_id, chunk_id)

db.save()
db.close()

With Built-in Embedder

from edgevdb import EdgeVDB, Embedder

# Create embedder
embedder = Embedder(
    model_path="models/model.onnx",
    vocab_path="models/vocab.txt",
    threads=2
)

# Use with context manager
with EdgeVDB("./my_database") as db:
    # Auto-embed on insert
    chunk_id = db.insert_text(
        embedder, 
        "Deep learning uses neural networks",
        doc_id=1,
        page_number=0
    )

    # Auto-embed on query
    results = db.query_text(embedder, "neural network architecture", top_k=5)
    print(results.context_string)

API Reference

EdgeVDB

Main database class.

Constructor

EdgeVDB(storage_dir: str, **kwargs)

Parameters:

  • storage_dir (str): Directory for database files
  • hnsw_M (int): HNSW M parameter (default: 16)
  • hnsw_ef_construction (int): HNSW ef_construction (default: 200)
  • hnsw_ef_search (int): HNSW ef_search (default: 64)
  • ranker_alpha (float): Cosine weight (default: 0.70)
  • ranker_beta (float): Page proximity weight (default: 0.20)
  • ranker_gamma (float): Keyword weight (default: 0.10)
  • token_budget (int): Max tokens in context (default: 3200)
  • embedding_threads (int): ONNX thread count (default: 2)
  • enable_knowledge_graph (bool): Enable KG (default: True)
  • enable_sync (bool): Enable sync (default: False)
  • device_id (str): Device ID for sync (default: auto-generated)

Methods

Vector Store

insert_chunk(text, embedding, doc_id=0, page_number=0) -> int

  • Insert text with pre-computed embedding
  • Returns chunk ID
chunk_id = db.insert_chunk(
    text="Your text here",
    embedding=[0.1, 0.2, ...],  # 384-dim float array
    doc_id=1,
    page_number=0
)

insert_text(embedder, text, doc_id=0, page_number=0) -> int

  • Insert text with auto-embedding via embedder
  • Returns chunk ID
chunk_id = db.insert_text(
    embedder,
    "Your text here",
    doc_id=1,
    page_number=0
)

remove_chunk(chunk_id)

  • Remove chunk by ID
db.remove_chunk(chunk_id)

query_vector(embedding, query_text="", top_k=5) -> QueryResults

  • Query with pre-computed embedding
  • Returns QueryResults object
results = db.query_vector(
    embedding=[0.1, 0.2, ...],
    query_text="search query",
    top_k=5
)

query_text(embedder, query, top_k=5, use_kg_expansion=False) -> QueryResults

  • Query with auto-embedding via embedder
  • Returns QueryResults object
results = db.query_text(
    embedder,
    "search query",
    top_k=5,
    use_kg_expansion=False
)
Object Store

put_object(type_name, properties) -> int

  • Store JSON object
  • Returns object ID
doc_id = db.put_object(
    "Document",
    {"title": "My Doc", "author": "Alice"}
)

get_object(object_id) -> Optional[Dict]

  • Retrieve object by ID
  • Returns dict or None if not found
obj = db.get_object(doc_id)
if obj:
    print(obj["title"])

remove_object(object_id)

  • Soft delete object
db.remove_object(doc_id)
Relations

add_relation(name, from_id, to_id)

  • Add typed edge between objects
db.add_relation("has_chunk", doc_id, chunk_id)
Lifecycle

save()

  • Flush all data to disk
db.save()

close()

  • Release native resources
db.close()

Context Manager

with EdgeVDB("./data") as db:
    # Auto-save and close on exit
    db.insert_chunk("text", embedding, doc_id=1)

Embedder

ONNX embedding model wrapper.

Constructor

Embedder(model_path: str, vocab_path: str, threads: int = 2)

Parameters:

  • model_path (str): Path to ONNX model file
  • vocab_path (str): Path to vocabulary file
  • threads (int): Number of inference threads (default: 2)

Methods

embed(text: str) -> List[float]

  • Embed text to 384-dim vector
  • Returns list of floats
embedding = embedder.embed("Hello world")

destroy()

  • Release native resources
embedder.destroy()

QueryResults

Query result container with lazy access.

Properties

count (int): Number of results

print(f"Found {results.count} results")

context_string (str): Pre-assembled RAG context

print(results.context_string)

Methods

getitem(index) -> ChunkResult

  • Access individual result by index
result = results[0]
print(result.text)

iter()

  • Iterate over results
for r in results:
    print(f"{r.score}: {r.text}")

to_list() -> List[ChunkResult]

  • Convert to list
results_list = results.to_list()

free()

  • Free native query handle (called automatically by del)
results.free()

ChunkResult

Single query result.

Attributes

  • chunk_id (int): Unique chunk identifier
  • text (str): Chunk text content
  • score (float): Hybrid similarity score [0.0, 1.0]
  • page_number (int): Page number in document
  • doc_id (int): Document identifier
for r in results:
    print(f"ID: {r.chunk_id}")
    print(f"Text: {r.text}")
    print(f"Score: {r.score:.3f}")
    print(f"Page: {r.page_number}")

Examples

RAG Pipeline

from edgevdb import EdgeVDB
from sentence_transformers import SentenceTransformer

# Initialize
model = SentenceTransformer('all-MiniLM-L6-v2')
db = EdgeVDB("./rag_database")

# Index documents
documents = [
    {"id": 1, "text": "Python is a high-level programming language."},
    {"id": 2, "text": "Machine learning is a subset of AI."},
    {"id": 3, "text": "Vector databases enable semantic search."},
]

for doc in documents:
    embedding = model.encode(doc["text"])
    db.insert_chunk(doc["text"], embedding, doc_id=doc["id"])

# Query
query = "What is semantic search?"
query_emb = model.encode(query)
results = db.query_vector(query_emb, query_text=query, top_k=2)

# Assemble context
context = results.context_string
print(f"Context: {context}")

db.save()
db.close()

Object Store + Relations

from edgevdb import EdgeVDB

db = EdgeVDB("./my_database")

# Store documents
doc1_id = db.put_object("Document", {
    "title": "Introduction to ML",
    "author": "Alice",
    "year": 2024
})

doc2_id = db.put_object("Document", {
    "title": "Advanced Topics",
    "author": "Bob",
    "year": 2024
})

# Store chunks with embeddings
chunk1_id = db.insert_chunk("ML is fascinating", emb, doc_id=doc1_id)
chunk2_id = db.insert_chunk("Deep learning is powerful", emb, doc_id=doc2_id)

# Link chunks to documents
db.add_relation("has_chunk", doc1_id, chunk1_id)
db.add_relation("has_chunk", doc2_id, chunk2_id)

db.save()
db.close()

Error Handling

from edgevdb import EdgeVDB, set_log_level

# Enable debug logging
set_log_level(3)

try:
    db = EdgeVDB("./my_database")
    
    # Operations
    chunk_id = db.insert_chunk("text", embedding, doc_id=1)
    
    # Object not found returns None (doesn't throw)
    obj = db.get_object(999)
    if obj is None:
        print("Object not found")
    
    db.save()
    db.close()
    
except RuntimeError as e:
    print(f"EdgeVDB error: {e}")

Library Discovery

The Python SDK automatically searches for the EdgeVDB shared library in the following locations:

  1. Platform-specific directory (edgevdb/lib/<platform>/) — preferred
  2. Package lib directory (edgevdb/lib/)
  3. Package directory (edgevdb/)
  4. Current working directory
  5. build/desktop-release/core/
  6. build/desktop-debug/core/

Library Layout:

python/edgevdb/lib/
  linux/    → libedgevdb_shared.so
  darwin/   → libedgevdb_shared.dylib
  windows/  → edgevdb_shared.dll, libedgevdb_shared.dll

Performance Considerations

Embedding Provider Choice

Provider Speed Quality Offline Cost
sentence-transformers Fast Good Free
OpenAI API Slow Excellent Paid
Cohere API Medium Good Paid
Built-in ONNX Medium Good Free

Batch Operations

For large-scale operations, consider batching:

# Batch insert
embeddings = model.encode(texts)
for text, emb in zip(texts, embeddings):
    db.insert_chunk(text, emb, doc_id=doc_id)

db.save()  # Save once after all inserts

Memory Management

  • Query results hold native handles; call results.free() or use context manager
  • Embedders hold native resources; call embedder.destroy() when done
  • Database handles are released by close() or context manager

Platform-Specific Notes

Linux

# Build
cmake --preset desktop-release
cmake --build build/desktop-release

# Install
cp build/desktop-release/core/libedgevdb_shared.so python/edgevdb/lib/linux/
pip install -e python/

macOS

# Build
cmake --preset desktop-release
cmake --build build/desktop-release

# Install
cp build/desktop-release/core/libedgevdb_shared.dylib python/edgevdb/lib/darwin/
pip install -e python/

Windows

# Build
cmake --preset desktop-release
cmake --build build/desktop-release

# Install
copy build\desktop-release\core\edgevdb_shared.dll python\edgevdb\lib\windows\
pip install -e python\

Raspberry Pi

# Build with NEON support
cmake --preset desktop-release
cmake --build build/desktop-release

# Install
cp build/desktop-release/core/libedgevdb_shared.so python/edgevdb/lib/linux/
pip install -e python/

Testing

cd python

# Run tests
python -m unittest tests.test_edgevdb -v

# Or with pytest
pytest tests/ -v

Troubleshooting

Library Not Found

Error: FileNotFoundError: Could not find EdgeVDB library

Solution:

  1. Build the C++ core: cmake --preset desktop-release && cmake --build build/desktop-release
  2. Copy the shared library to python/edgevdb/lib/<platform>/
  3. Verify the library name matches your platform

Import Errors

Error: ImportError: dynamic module does not define init function

Solution:

  • Ensure the shared library was built for your platform
  • Check Python architecture matches library (32-bit vs 64-bit)
  • Rebuild the C++ core for your platform

Segmentation Faults

Error: Python crashes with segmentation fault

Solution:

  • Ensure you're using the correct library version
  • Check that you're not accessing freed handles
  • Verify embedding dimensions are exactly 384
  • Enable debug logging: set_log_level(3)

Contributing

Development Setup

# Build C++ core in debug mode
cmake --preset desktop-debug
cmake --build build/desktop-debug

# Copy debug library
cp build/desktop-debug/core/libedgevdb_shared.so python/edgevdb/

# Install in development mode
cd python
pip install -e .

Running Tests

cd python
python -m unittest tests.test_edgevdb -v

Code Style

  • Follow PEP 8
  • Use type hints
  • Add docstrings for public APIs
  • Run black and flake8

See Also

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

edgevdb-1.0.0.tar.gz (535.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

edgevdb-1.0.0-py3-none-any.whl (532.3 kB view details)

Uploaded Python 3

File details

Details for the file edgevdb-1.0.0.tar.gz.

File metadata

  • Download URL: edgevdb-1.0.0.tar.gz
  • Upload date:
  • Size: 535.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for edgevdb-1.0.0.tar.gz
Algorithm Hash digest
SHA256 60088a35a0f6335fa4f5fa0aa5f51f5537db823a6c9b6684c13e35339a5e09f8
MD5 4acc16c59a21f63a47cc6dacf714dbbc
BLAKE2b-256 ec27dd7622a53bc6541772530906ab742aace66f27cc5addb8bd01e925ed79c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for edgevdb-1.0.0.tar.gz:

Publisher: publish-pypi.yml on XformAI/EDGEVDB

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file edgevdb-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: edgevdb-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 532.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for edgevdb-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f09e82dd0217d35ca16d40df2df8766d3393cc3156cddec9edd7e43dc48d2480
MD5 ff7b808275e3a4d88967109be7d42bc9
BLAKE2b-256 58de687878330a88141a47d54f0bc35fdf5da15f826674277387712d5b0f75c3

See more details on using hashes here.

Provenance

The following attestation bundles were made for edgevdb-1.0.0-py3-none-any.whl:

Publisher: publish-pypi.yml on XformAI/EDGEVDB

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page