AI Skill Report Card

Building RAG Systems

A-88·Nov 8, 2026·Source: Web
15 / 15

Minimal RAG pipeline (LangChain + Qdrant):

Python
from langchain_community.vectorstores import Qdrant from langchain_openai import OpenAIEmbeddings from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain_community.document_loaders import PyPDFLoader # 1. Load & chunk docs = PyPDFLoader("report.pdf").load() splitter = RecursiveCharacterTextSplitter(chunk_size=512, chunk_overlap=64) chunks = splitter.split_documents(docs) # 2. Embed & index embeddings = OpenAIEmbeddings(model="text-embedding-3-large") vectorstore = Qdrant.from_documents(chunks, embeddings, location=":memory:", collection_name="docs") # 3. Retrieve + generate retriever = vectorstore.as_retriever(search_kwargs={"k": 5}) results = retriever.invoke("What are the key findings?") context = "\n\n".join(f"[{i+1}] {r.page_content}" for i, r in enumerate(results)) prompt = f"""Answer using ONLY the context below. Cite sources as [N]. Context: {context} Question: What are the key findings?"""
Recommendation▾
Add a concrete worked example with actual retrieved chunks and a sample final answer showing citation formatting, not just descriptions of the output
15 / 15

Progress:

  • Step 1: Ingest & parse documents (PDF, HTML, DB, API)
  • Step 2: Chunk text (256–1024 tokens, 10–20% overlap)
  • Step 3: Generate embeddings, load into vector DB
  • Step 4: Design retrieval strategy (hybrid: dense + sparse)
  • Step 5: Rerank results (cross-encoder)
  • Step 6: Assemble prompt (context + question → LLM)
  • Step 7: Post-process, attach citations, verify grounding

Step details

1. Ingestion & parsing

  • Normalize all sources to clean text; preserve structure (headings, tables) as metadata.
  • Keep source, page, section in metadata for every chunk — required for citations.

2. Chunking

  • Default: 512 tokens, 15% overlap. Smaller (256) for dense FAQ-like content; larger (1024) for narrative/legal text.
  • Prefer semantic/recursive splitting (by headers, then paragraphs, then sentences) over fixed-size blind splits.
  • Attach parent-document reference for "small-to-big" retrieval when needed.

3. Embeddings & indexing

  • Choose embedding model by language/domain: text-embedding-3-large (general, multilingual), bge-large-ru (Russian-heavy corpora), Cohere embed v3 (multilingual + reranking ecosystem).
  • Store vectors with metadata filters (date, doc type, access level) in Milvus/Qdrant/Weaviate/Chroma/pgvector. Default choice: Qdrant for most projects (speed + filtering + easy ops), pgvector if already on Postgres.

4. Retrieval strategy

  • Default to hybrid search: dense vector similarity + BM25/sparse keyword search, combined via reciprocal rank fusion (RRF).
  • Retrieve top-20 candidates for reranking, not just top-5 — reranker recovers precision.
  • Apply metadata filters before vector search when query has structured constraints (dates, doc type).

5. Reranking

  • Always rerank before passing to LLM when corpus > few thousand chunks. Use bge-reranker-v2 (self-hosted) or Cohere Rerank (managed API).
  • Keep top-3 to top-5 after reranking for the final context window.

6. Prompt assembly

  • Structure: system instructions (grounding rules) → numbered context chunks → question.
  • Explicit instruction: "If the answer is not in the context, say you don't know" — core anti-hallucination guardrail.
  • Include source identifiers inline so LLM can cite them natively (e.g., [1], [2]).

7. Citation & post-processing

  • Validate that every claim in the generated answer maps to a cited chunk; flag ungrounded sentences.
  • Return citations with clickable source/page references to the user.
  • Optional: run a second LLM pass ("groundedness check") comparing answer against retrieved context.
Recommendation▾
Include an example of a bad outcome (e.g., ungrounded hallucinated answer) contrasted with the corrected grounded version
  • Frameworks: LangChain, LlamaIndex, Haystack
  • Vector DBs: Qdrant (default), Milvus, Weaviate, Chroma (prototyping), pgvector (Postgres-native)
  • Embeddings: text-embedding-3-large, bge-large-ru, Cohere embed v3
  • Rerankers: Cohere Rerank, bge-reranker-v2
15 / 20

Example 1: Input: Corpus of 10,000 internal PDF policy documents (Russian), need Q&A chatbot for employees. Output: Parse PDFs → chunk 512/15% overlap → embed with bge-large-ru → index in Qdrant with metadata (department, doc_date) → hybrid retrieval (dense + BM25) top-20 → bge-reranker-v2 to top-4 → prompt with grounding instructions → answer with inline [1][2] citations linking to source PDF page.

Example 2: Input: User asks a question with no relevant content in the corpus. Output: Retrieval returns low-similarity chunks (below threshold, e.g., cosine < 0.75); system responds "I don't have enough information in the provided documents to answer this" instead of generating an unsupported answer.

Recommendation▾
Provide a code snippet for reranking and the 'no answer found' threshold logic to match the Quick Start's level of concreteness
  • Set a similarity/relevance threshold to trigger "no answer found" rather than forcing a response.
  • Version your embedding index — re-embed entire corpus when switching embedding models (embeddings aren't cross-compatible).
  • Log retrieved chunks + final answer for every query to enable offline evaluation and hallucination audits.
  • Evaluate with retrieval metrics (recall@k, MRR) and generation metrics (faithfulness, answer relevance) separately — a good generator can't fix bad retrieval.
  • Use query rewriting/expansion for short or ambiguous user queries before retrieval.
  • Don't skip reranking for large corpora — raw vector similarity alone yields noisy top-k results.
  • Don't chunk without overlap — breaks context at boundaries, causing answers that miss adjacent facts.
  • Don't omit metadata (source, page) at chunking time — impossible to add citations retroactively.
  • Don't trust the LLM to refuse unsupported answers without explicit prompt instructions — it will still hallucinate plausibly.
  • Don't use a single embedding model for both Russian and English heavy corpora without testing — mismatched models hurt recall significantly.
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
15/15
Workflow
15/15
Examples
15/20
Completeness
18/20
Format
15/15
Conciseness
13/15