Why this matters
- PolicyDesk's first demo was a notebook that embedded the query and printed cosine scores, with no answer. The product is the answer plus the source.
- Interviewers ask you to walk the code in order: load, split, embed, store, retrieve, generate.
- Library class names change between LangChain releases. If you memorize an import and miss the pipeline, you fail the question.
- Metadata added at ingest is the only metadata you can filter on at query time.
What you are assembling
You will build PolicyDesk's leave assistant with Python. The pieces are a PDF loader, a recursive splitter, an embedding model, a Qdrant collection, a chat model, and a prompt. Orchestration libraries (LangChain is the one these notes use) wire those pieces. You can wire them yourself with the OpenAI and Qdrant clients. The order of work does not change.
The stack
| Concern | A solid pick | Role |
|---|---|---|
| Language | Python | Loaders and ML clients are richest here |
| Orchestration | LangChain or LlamaIndex, or plain functions | Glue. Not the retrieval algorithm |
| Embeddings | text-embedding-3-small, or BGE if you must self-host | One vector per chunk and per query |
| Vector store | Qdrant | ANN search plus payload filters |
| Chat model | A current small or mid chat model | Writes the answer. Does not search |
| Splitter | Recursive character splitter with a token length function | Chunks on natural boundaries |
Language
A solid pickPythonRoleLoaders and ML clients are richest hereOrchestration
A solid pickLangChain or LlamaIndex, or plain functionsRoleGlue. Not the retrieval algorithmEmbeddings
A solid picktext-embedding-3-small, or BGE if you must self-hostRoleOne vector per chunk and per queryVector store
A solid pickQdrantRoleANN search plus payload filtersChat model
A solid pickA current small or mid chat modelRoleWrites the answer. Does not searchSplitter
A solid pickRecursive character splitter with a token length functionRoleChunks on natural boundaries
Pin versions. ChatOpenAI, OpenAIEmbeddings, and the Qdrant integration have moved packages (langchain-openai, langchain-qdrant) and method names. The code below is the shape to implement against the packages you install, not a promise that every import path is eternal.
The six implementation steps
Build order
- Load.
PyPDFLoader(or a better PDF parser if the handbook is multi-column) returns documents with page metadata. - Split. Recursive splitter. Start at a few hundred tokens with overlap, not a random character count you never inspect.
- Embed and store. Create the collection with the model's dimension and cosine distance. Upsert vectors with payload text and metadata.
- Embed the query with that same model.
- Retrieve top-k with a department filter.
- Generate from a prompt that contains only those chunks and forbids guessing.
The rest of this guide is part of Pro
Free covers every fresher guide in full. Pro unlocks Senior, Staff and Architect guides across every track.
Still to come · 5 sections
- Indexing code
- Query code
- Metadata on the chunk
- Ask different questions on purpose
- Make the script something you can operate
Test yourself
Answer these before moving on — recall is what makes it stick.