Vector Stores & Index Operations: overview
- Source
- From the RAG & Agents Engineering course
- By
- Sourav Banerjee
- Last updated
- 8 Nov 2026
A vector store is a database. Each entry holds a vector, the text it came from and that text's metadata, and you add, read, filter, delete and persist entries the way you would rows. The hard part is keeping the store in step with source files that keep changing. The T5.5 notebooks build on four ideas: approximate nearest-neighbour (ANN) search, collections and namespaces, metadata filters, and idempotent re-indexing.
The running example is the Larkspur Cloud handbook kept as a folder of Markdown files: billing.md, refunds.md, outages.md, servers.md and data.md, ten chunks in all, with the same chunk texts as the T5.1 lab. A sixth file, support.md, arrives later. The event that drives the module is a policy change: the refund window for annual plans drops from 30 days to 14. The golden question is How long do I have to get a full refund on an annual plan?, and after the change the index must return the 14-day rule and nothing else.
In short
- A vector store can add, search, filter and delete. It cannot update text in place: new text means a new vector, so an update is a delete followed by an insert, and both need an ID that stays the same from one run to the next.
- Scores mean different things on different backends. Chroma and FAISS return a distance from
similarity_search_with_score(lower is closer), and Pinecone's cosine index returns a similarity (higher is closer). A threshold tuned on one is meaningless on another. - Large indexes use ANN structures such as HNSW and IVF, which trade a little recall for a lot of speed. LangChain's
FAISS.from_documentsbuilds an exactIndexFlatL2; Chroma builds HNSW. - A metadata filter applied before ranking returns up to
kmatches. One applied after ranking can return fewer, or none. LangChain's FAISS wrapper filters after fetching 20 candidates; PGVector filters in SQL before it ranks. - The Indexing API hashes every chunk and records the hash. In the lab, editing one refund chunk costs one embedding instead of ten, and
cleanup="incremental"deletes the old 30-day chunk. Withcleanup=Noneboth rules stay in the store.
Mental model
- The loader returns the handbook folder as 10 chunks. refunds.md now says 14 days where it said 30.
- Each chunk gets an ID from a hash of its text and its source. Same text, same ID.
- The record manager already holds 9 of the 10 hashes. Those 9 are skipped and never re-embedded.
- One hash is new: the 14-day refund rule. Only that chunk is embedded and added to the collection.
- All 10 keys are stamped with this run’s time, the skipped ones included.
- Incremental cleanup lists keys from refunds.md older than the run. The 30-day chunk is one, so it is deleted.
- A question with a metadata filter searches the collection, and ANN search returns the top k chunks.
The store is the system of record for what retrieval can return, so every change in the source folder has to reach it. The record manager is what makes that cheap: it remembers each chunk's hash, so a run embeds only the chunks whose text or source changed, and its cleanup step deletes the chunks the folder no longer contains. A stale chunk left in the collection is as retrievable as a current one.
Interactive lab
The record manager and cleanup modes: open the file in a browser. Run index() once to embed all 10 chunks. Set refunds.md to 14 days and run with cleanup None: 1 chunk is added, none is deleted, and the store now holds the 30-day rule and the 14-day rule side by side. Switch to incremental and run again to delete the stale one. Then mark outages.md Deleted and run under incremental (nothing is deleted) and under full (its 2 chunks go).
How it connects
- Before: T5.2 sets the
sourcemetadata the record manager groups by and the flat metadata types the stores accept; T5.3 decides what a chunk is, and so what gets hashed; T5.4 picks the embedding model, which has to match the index for as long as the index lives. - Next: T5.6 indexes more than one representation per document (parent documents, summaries), which needs the stable IDs from lesson 1 of T5.5; T6.1 builds retrieval strategies (MMR, thresholds, hybrid search) on top of
as_retriever().
Key Takeaways
- Give every chunk an ID derived from the document: its source and position, or a hash of its content. Without one you cannot update, delete or de-duplicate.
- Read what a score means on your backend before you set a threshold, and log how many results a filtered search returned.
- Filter before the search when the filter is selective; after-search filtering silently returns fewer than
k. - Sync with the Indexing API and
cleanup="incremental"keyed onsource. Usefullonly when the loader returns the whole corpus, and never on a batch that might be empty.