Store, index, and search high-dimensional vector embeddings. Built for RAG systems, semantic search, and LLM applications.
▶ Watch the 18-second ToucanDB overview — with sound
An embedded, local-first vector database for semantic search, RAG, and application memory. ToucanDB combines atomic SQLite persistence with FAISS search and does not require a separate database server.
- Cosine, dot-product, and Euclidean similarity.
- Exact flat search and approximate HNSW or IVF indices.
- SQLite WAL storage with atomic batch writes and safe arbitrary vector IDs.
- Generation-checked FAISS snapshots with deterministic rebuild after a crash or a cross-architecture restore.
- Bounded, database-wide LRU cache budgets and automatic tombstone compaction.
- Optional authenticated encryption with a per-database salt and memory-hard key derivation.
- Async APIs that move storage, index, and local-model work off the event loop.
- Stable upserts that do not re-embed unchanged documents.
- A dependency-free RAG pipeline with chunking, namespace isolation, pruning, source attribution, bounded context, and an injected generator.
- Privacy-safe pipeline traces, reviewed retrieval evaluation, and optional bounded FAISS topic discovery.
- Lazy Sentence Transformers and OpenAI embedding adapters, plus a generic callable adapter.
- A tested SimpliXio semantic-signal integration.
ToucanDB is an embedded component, not a distributed service. One process owns a database directory at a time; a second owner fails fast instead of operating on a stale in-memory index.
ToucanDB 2 requires Python 3.10 or newer.
pip install toucandbInstall only the integration you use:
pip install 'toucandb[embeddings]' # local Sentence Transformers
pip install 'toucandb[openai]' # OpenAI embeddings
pip install 'toucandb[all]' # both adapters
pip install 'toucandb[dev]' # contributors and release checksThe RAG pipeline itself is in the core package and adds no model or framework
dependency. The old ml extra remains as an alias for embeddings during the
2.x transition. ToucanDB does not publish a gpu extra because the upstream
FAISS GPU wheel has been discontinued; custom FAISS GPU builds are an advanced
deployment choice.
import asyncio
from toucandb import SentenceTransformerEmbeddingProvider
from toucandb.integrations import RAGDocument, RAGStore
async def main() -> None:
rag = await RAGStore.create(
"./knowledge.tdb",
SentenceTransformerEmbeddingProvider("all-MiniLM-L6-v2"),
encryption_key="load-this-from-a-secret-store",
namespace="product-docs",
)
await rag.sync_documents(
[
RAGDocument(
id="architecture",
text="ToucanDB stores records in SQLite and rebuilds FAISS safely.",
source="architecture.md",
metadata={"project": "ToucanDB"},
),
RAGDocument(
id="deployment",
text="ToucanDB is embedded and needs one owning process.",
source="deployment.md",
metadata={"project": "ToucanDB"},
),
],
prune=True,
)
hits = await rag.retrieve("Does ToucanDB need a database server?", k=3)
for hit in hits:
print(hit.score, hit.source, hit.text)
# `answer()` accepts any async object with generate(prompt), or a callable.
async def generator(prompt: str) -> str:
return await your_llm(prompt)
answer = await rag.answer(
"Does ToucanDB need a database server?",
generator,
)
print(answer.answer)
await rag.close()
asyncio.run(main())See the RAG guide and
examples/rag_pipeline.py for a runnable example.
Production tracing, recall/MRR evaluation, postprocessing, and semantic
clustering are covered in the LLM pipeline guide.
import asyncio
from toucandb import SearchQuery, ToucanDB, create_schema
async def main() -> None:
async with await ToucanDB.create("./vectors.tdb") as db:
await db.create_collection(
create_schema("items", dimensions=3, index_type="hnsw")
)
result = await db.upsert_vectors(
"items",
[
{
"id": "toucan",
"vector": [0.9, 0.1, 0.2],
"metadata": {"kind": "bird"},
},
{
"id": "macaw",
"vector": [0.8, 0.2, 0.1],
"metadata": {"kind": "bird"},
},
],
)
if not result.success:
raise RuntimeError(result.error_message)
matches = await db.search_vectors(
"items",
SearchQuery(
vector=[1.0, 0.0, 0.0],
k=2,
metadata_filter={"kind": "bird"},
),
)
print(matches.data)
asyncio.run(main())application
│
├── vectors supplied directly, or lazy embedding provider
│
â–Ľ
ToucanDB collection
├── SQLite WAL: durable source of truth and atomic batches
├── FAISS: in-memory search accelerator
├── snapshot manifest: generation + schema verification
└── bounded LRU: vectors/metadata loaded by results
The design deliberately avoids a background server, a connection pool, an unbounded cache, and eager model loading. SQLite records are authoritative; FAISS can always be rebuilt. A clean close writes an index snapshot. A crash after a committed data write produces a generation mismatch, so the next open rebuilds instead of trusting stale search state.
| Index | Best fit | Trade-off |
|---|---|---|
flat |
Small collections or exact evaluation | Exact recall; linear search |
hnsw |
Default interactive retrieval | Fast approximate search; extra memory |
ivf |
Larger, batch-oriented corpora | Trained approximate index; tune nprobe |
Metadata filters use adaptive candidate expansion. Selective filters may require more index work; benchmark with the metadata distribution and recall requirements of the real corpus.
See architecture, performance guidance, and the 2.0 migration guide. FAISS topic discovery is a separate, non-persistent analysis operation; IVF's internal centroids are search partitions and should not be treated as product labels.
No backend is required when one Python application owns local data. This is the best fit for desktop tools, local agents, evaluation pipelines, private RAG, and an application service that embeds ToucanDB in its own process.
A service boundary does make sense when multiple processes or devices need the same live index, when API credentials must not ship in a client, or when access control and synchronization are server responsibilities. In that scenario, run one ToucanDB owner behind the application's API; do not let several workers write the same directory.
For iOS and macOS, the Python wheel is not embedded into the app. SimpliXio uses a native Swift runtime built from Apple Natural Language, SQLite WAL, Accelerate, and actor isolation. It synchronizes source records rather than model-specific vectors and needs no backend for an on-device-only experience. See Apple integration.
Pass an encryption key only from a keychain, secret manager, or environment owned by the host application—never hard-code it. Encryption covers vector and metadata payloads. Collection names, vector IDs, hashed record keys, SQLite structure, and index snapshots are not encrypted. If whole-index confidentiality matters, rely on full-disk/platform data protection as well. A lost encryption key cannot be recovered.
Retrieved RAG text is untrusted input. RAGStore.answer() tells the generator
to treat sources as data, but the host application must still apply its normal
prompt-injection, authorization, sensitivity, and output controls.
ToucanDB does not claim a universal latency, throughput, or corpus-size number. Results depend on hardware, dimensions, index type, vector count, filters, encryption, and recall targets. The repository includes a reproducible local benchmark command; publish the full configuration with any reported result.
python benchmarks/benchmark.py --vectors 10000 --dimensions 384 --index hnswSimplixioSignalMemory indexes stable SimpliXio signal IDs, skips unchanged
embeddings, filters by project, and prunes deleted records with a bulk
transaction. SimpliXio keeps deterministic product ranking and sensitivity
rules as the source of truth; ToucanDB supplies semantic candidates.
See the reviewed use case and
examples/simplixio_signal_memory.py.
ToucanDB 2 is a beta embedded engine. It is not a distributed vector database, does not provide HTTP/authentication/multi-tenancy by itself, and does not yet provide a transactional metadata secondary index. Equality metadata filters are supported. Validate recall and failure behavior with representative data before relying on it for a high-stakes production workflow.
ToucanDB was created and is maintained by Pierre-Henry Soria:
- Website: pierrehenry.dev
- GitHub: github.com/pH-7
- LinkedIn: linkedin.com/in/ph7enry
Additional acknowledgements and citation details are in CREDITS.md and CITATION.cff.
Toucans reflect the project’s aim: precise retrieval, adaptability across data sources, and a vivid local-first identity. Pierre-Henry’s family history in the Amazon and lifelong love of birds inspired the name.
See CONTRIBUTING.md for the development workflow. ToucanDB is released under the MIT License.
Built with ❤️ for the AI community