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 PyPI (Recommended)

pip install edgevdb

Pre-built wheels include native libraries for Linux (x86_64, glibc 2.28+), macOS (arm64/x86_64), and Windows (x86_64).

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 .

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

Uploaded Python 3

File details

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

File metadata

  • Download URL: edgevdb-1.0.4.tar.gz
  • Upload date:
  • Size: 532.1 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.4.tar.gz
Algorithm Hash digest
SHA256 a46c8cc4a0cea75ba7cd10d30d566bfaeeeead9e3eedfe6ecd8c9fca7bd14e07
MD5 1dcb7a84b75c1164f631724cf2309996
BLAKE2b-256 5ac200d832160e3270e961f2a2ef9bae018ba00574ecd0d0117ededb2b15f314

See more details on using hashes here.

Provenance

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

File metadata

  • Download URL: edgevdb-1.0.4-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.4-py3-none-any.whl
Algorithm Hash digest
SHA256 5f35435a42bead7c2ce6d98f4b4a0b429292a262cfae57eaf25d355c95fd24b5
MD5 99c5b3a6c5ec41270ca9fa51ee11ef9e
BLAKE2b-256 6d8698a799d01908fe6e30402416dde63fd48b7b3a18a03fb364640e859ea7a8

See more details on using hashes here.

Provenance

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