Reference

Vector Stores

Six backends, one interface. VectorRetriever, GraphLLM, and MonitoredGraph only ever talk to BaseVectorStore — swapping backends never touches any other file.

The contract

class BaseVectorStore(ABC):
    @abstractmethod
    def add(self, chunks: list[Chunk]) -> None: ...

    @abstractmethod
    def search(self, query_embedding: list[float], k: int = 4) -> list[ScoredChunk]: ...

    @abstractmethod
    def __len__(self) -> int: ...

    def clear(self) -> None: ...   # optional override

Implement these four methods to add your own backend — Pinecone, Weaviate, Milvus. Nothing else in the library changes.

Compare

ClassInstallInfraScalePersists
InMemoryVectorStorenumpy (always)None~100k chunksNo
SQLiteVectorStorestdlib onlySingle .db file~100k chunksYes
ChromaVectorStorepip install chromadbNone / DockerMillionsYes
FAISSVectorStorepip install faiss-cpuTwo local filesBillions (exact: ~1M)Yes
PGVectorStorepip install psycopg2-binary pgvectorPostgreSQL serverHundreds of millionsYes
QdrantVectorStorepip install qdrant-clientNone / Docker / CloudBillionsYes

Backends

InMemoryVectorStoreDefault — zero setup
store = InMemoryVectorStore()

numpy L2-normalised vectors in a single (N × D) matrix. search() is one matrix–vector multiply — no Python loops. Vectors are lost when the process exits.

SQLiteVectorStorePersistent, zero new deps
store = SQLiteVectorStore(
    db_path    = "./knowledge_base.db",
    table_name = "vector_chunks",   # default
)

Embeddings stored as BLOB columns (serialized float32). Loads all rows into a numpy matrix on first search(), cached until the next add(). Same scale ceiling as in-memory — the win here is purely persistence.

ChromaVectorStoreBest DX at scale
# Embedded (local directory)
store = ChromaVectorStore(path="./chroma_db", collection="my_docs")

# HTTP server
store = ChromaVectorStore(url="http://localhost:8000", collection="my_docs")

Exactly one of path or url. HNSW approximate nearest-neighbor indexing — fast and memory-efficient at scale, no in-memory matrix loading.

FAISSVectorStoreExact search, two files
store = FAISSVectorStore(
    index_path = "./docs.faiss",
    meta_path  = "./docs_meta.pkl",
    dimension  = None,   # inferred from first add()
)

IndexFlatIP — exact inner-product search on L2-normalised vectors. FAISS holds only raw floats; a parallel pickle file carries chunk text/metadata in the same order. Both files auto-load on restart if present.

PGVectorStoreStage 2 production target
store = PGVectorStore(
    connection_string = "postgresql://user:pass@localhost:5432/mydb",
    table_name        = "vector_chunks",
    dimension         = 1536,   # must match your embedding model
)
store.close()   # closes the psycopg2 connection

Uses the <=> cosine-distance operator for server-side nearest-neighbour search. add() raises ValueError on any dimension mismatch. Live tests gated by PYWRAPAI_TEST_PG_URL.

QdrantVectorStoreMost deployment flexibility
store = QdrantVectorStore(collection="my_docs", location=":memory:", dimension=1536)
store = QdrantVectorStore(collection="my_docs", location="./qdrant_data")
store = QdrantVectorStore(collection="my_docs", url="http://localhost:6333")
store = QdrantVectorStore(collection="my_docs", url="https://xyz.qdrant.io", api_key="...")

Same constructor API for in-memory, local disk, Docker, and Cloud. Local disk mode holds an exclusive file lock — call store.close() before opening a second instance on the same path.

Optional dependencies

Everything beyond in-memory and SQLite is a pip extra — lazy-imported, so a missing package only raises when you actually instantiate that backend.

pip install pywrapai-graphInMemoryVectorStore + SQLiteVectorStore always available
pip install pywrapai-graph[chroma]adds ChromaVectorStore
pip install pywrapai-graph[faiss]adds FAISSVectorStore
pip install pywrapai-graph[pgvector]adds PGVectorStore
pip install pywrapai-graph[qdrant]adds QdrantVectorStore