Vector stores¶
Eight connectors, one contract. Every one supports hybrid search (dense + lexical), metadata filtering, namespaces, and idempotent upsert/delete. Pick with one key:
# config.yaml
vector_store: sqlite # or pinecone | qdrant | pgvector | mongodb
# | milvus | opensearch | weaviate
All indexes, collections, and tables bootstrap on first use — no manual setup. In our retrieval evals, every connector scores identically (hit@3 = 1.00 reranked), so choose on operational grounds:
| Pick | When |
|---|---|
| SQLite | You want zero infrastructure: one local file, no server, no keys. Retrieves as well as the clouds in our evals — the right default for local and single-machine use |
| Pinecone | You want serverless cloud with a free tier and nothing to operate |
| Qdrant | You want an OSS vector DB — local docker or Qdrant Cloud |
| pgvector | You already run Postgres (RDS, Supabase, Neon, docker) |
| MongoDB | You already run MongoDB (Atlas any tier incl. free M0, or 8.2+ self-managed) |
| Milvus | You want a dedicated OSS vector database at scale — docker or Zilliz Cloud |
| OpenSearch | You are AWS-native — Amazon domains sign with your existing profile, no new key |
| Weaviate | You want native server-side hybrid in a single call — docker or Weaviate Cloud |
Using a connector directly¶
The services use the configured store automatically. To bring your own instance (different collection, several stores side by side):
from ingestlib.storage import SqliteStore, default_store
from ingestlib.services import ingest, retrieve
store = default_store() # whatever config.yaml selects
ingest("report.pdf", store=SqliteStore()) # or any connector instance
retrieve("question", store=store)
The contract every connector implements is the VectorStore ABC:
upsert_chunks, query (dense vector + optional query text for the
lexical half), delete_document — see
API reference → Storage.
Connector notes¶
What each needs and how its hybrid works. Config keys (index/collection names) are in the configuration reference; everything below defaults sensibly.
SQLite¶
- Needs: nothing.
sqlite.path(defaultingestlib.db, beside config.yaml). - Hybrid: sqlite-vec (
vec0) dense KNN + built-in FTS5 BM25 with porter stemming (breadcrumb weighted 2×), fused client-side with RRF. - Notes: writes are one transaction across all tables — dense and lexical can never drift. Namespaces are physical partitions.
Pinecone¶
- Needs:
PINECONE_API_KEY. - Hybrid: two serverless indexes — dense (cosine) + sparse, with
Pinecone-hosted sparse embeddings (
pinecone-sparse-english-v0, no corpus state to manage); merged client-side, reranker arbitrates.
Qdrant¶
- Needs:
QDRANT_URL(+QDRANT_API_KEYfor cloud). Local:docker run -p 6333:6333 qdrant/qdrant - Hybrid: one collection with named dense + BM25 sparse vectors (server computes IDF live); both branches fused server-side with RRF in a single query.
pgvector¶
- Needs:
PGVECTOR_URL(postgresql://user:pass@host:5432/db). Local:docker run -p 5432:5432 pgvector/pgvector:pg18 - Hybrid: HNSW cosine + a generated, weighted
tsvectorcolumn (lexical index physically cannot drift from the text), fused client-side with RRF. - Notes: the
vectorextension is enabled automatically when the role may; otherwise you get a clear message naming the fix. Writes are delete-then-insert in one transaction — re-ingests never leave orphaned chunks.
MongoDB¶
- Needs:
MONGODB_URL(Atlasmongodb+srv://…or self-managed 8.2+). - Hybrid:
$vectorSearch(cosine) +$search(true Lucene BM25, breadcrumb boosted), fused client-side with RRF. Both search indexes are created programmatically and polled until queryable. - Notes: Atlas search indexes lag writes by seconds (eventual consistency). The free M0 tier caps search indexes at 3 per cluster.
Milvus¶
- Needs:
MILVUS_URL(+MILVUS_TOKENfor Zilliz Cloud). - Hybrid: dense + a built-in BM25 function (the server computes
sparse vectors and IDF from raw text), fused server-side with an
RRF ranker in one
hybrid_searchcall.
OpenSearch¶
- Needs:
OPENSEARCH_URL. Amazon domains are SigV4-signed with youraws.profile— no new credential; local docker runs unsigned. - Hybrid: faiss HNSW k-NN + Lucene BM25, fused client-side with RRF.
Weaviate¶
- Needs:
WEAVIATE_URL(+WEAVIATE_API_KEYfor cloud). Local docker needs HTTP + gRPC ports (8080, 50051). - Hybrid: native — one
hybridcall fuses dense and BM25 server-side.
Migrating between stores¶
The vector store is a derived index; the artifact store is the source of truth. Switching stores is not a migration project:
- Change
vector_storein config.yaml. - Re-embed the stored chunks into the new store — no re-parsing, no
OCR server (the studio's Settings page does this as "Backfill", or
see the eval harness's
--backfillflag).
The previous store is left untouched, so two stores can stay populated side by side.