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.3.tar.gz (532.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.3-py3-none-any.whl (529.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: edgevdb-1.0.3.tar.gz
  • Upload date:
  • Size: 532.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.3.tar.gz
Algorithm Hash digest
SHA256 fba216c7fb998b3956e1e179c1d1fedcba8e1094c6552aece773393f2f8e2607
MD5 60315b60c13c9a91bb3a8535a34601f6
BLAKE2b-256 5f4277219e30b9edc5e5d3d6e1fb26cae46f81ba4239e99a51d77d5002ccca3e

See more details on using hashes here.

Provenance

The following attestation bundles were made for edgevdb-1.0.3.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.3-py3-none-any.whl.

File metadata

  • Download URL: edgevdb-1.0.3-py3-none-any.whl
  • Upload date:
  • Size: 529.0 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 f581f563bbeff9a4ffcd7529a2c62a4d458df2ac70cb7e7503aa6693bf5f2305
MD5 439e406bb40f9b0fa17f30a1494eb56e
BLAKE2b-256 18d5e0c0e401d9c6e61fc2897a01d7ac4175f6c82883e2f100b01102c7bfe4e5

See more details on using hashes here.

Provenance

The following attestation bundles were made for edgevdb-1.0.3-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