Take a moment to think about this
This lesson is a practice set that combines the RAG, embeddings, vector database, and AI agent concepts from the Advanced chapter for deeper hands-on practice. The tasks are no longer single-concept quizzes — they operate at the level of an entire end-to-end flow, from chunking a document, to comparing embeddings, to building a RAG pipeline, all the way to writing tool-decision logic for an agent. It's a step up in difficulty from Lesson 1, and it's designed to have you write the core logic yourself rather than leaning on a built-in library (e.g. LangChain), so you truly understand how it works.
Exercises
Task 1: Write a function that splits a 3-paragraph document into fixed-size chunks (around 200 characters) with 20% overlap. Task 2: Implement a cosine similarity function yourself (no built-in libraries allowed), then write code that takes 3 vectors and finds which one is closest to a given query vector. Task 3: Write a minimal RAG pipeline (in pseudo-function form) that, given a user query, retrieves the top-3 relevant chunks from a vector database, inserts those chunks into the system prompt as context, and then calls the LLM. Task 4: Design a simple agent router with decision logic that uses the get_weather tool for weather questions, the calculator tool for calculation questions, and replies with plain text when no extra tool is needed.
Code Example
# Task 2 — implement cosine similarity yourself (no numpy/sklearn shortcuts allowed)
import math
def cosine_similarity(vec_a, vec_b):
dot_product = sum(a * b for a, b in zip(vec_a, vec_b))
magnitude_a = math.sqrt(sum(a * a for a in vec_a))
magnitude_b = math.sqrt(sum(b * b for b in vec_b))
if magnitude_a == 0 or magnitude_b == 0:
return 0.0
return dot_product / (magnitude_a * magnitude_b)
def find_most_similar(query_vector, candidate_vectors):
# candidate_vectors: list of (id, vector) tuples
best_id, best_score = None, -1.0
for cand_id, cand_vector in candidate_vectors:
score = cosine_similarity(query_vector, cand_vector)
if score > best_score:
best_id, best_score = cand_id, score
return best_id, best_score
# Task 3 — minimal RAG pipeline skeleton (fill in the TODOs)
def rag_answer(user_query, vector_store, llm_client):
# TODO 1: embed the user_query
# TODO 2: retrieve top-3 chunks from vector_store using find_most_similar
# TODO 3: build a prompt that injects the retrieved chunks as context
# TODO 4: call llm_client with that prompt and return the answer
pass
# Task 4 — simple agent router
def route_to_tool(user_query):
if "weather" in user_query.lower():
return "get_weather"
if any(op in user_query for op in ["+", "-", "*", "/", "calculate"]):
return "calculator"
return "plain_text_response"Given a query vector, the function should correctly return the nearest chunk ID; and running the RAG pipeline on a document set should produce a context-grounded answer that includes the retrieved context.Try it in 5 minutes
Within 5 minutes, split 2 paragraphs into chunks, run your cosine_similarity function against a sample query vector, and check for yourself which chunk comes out closest.
A quick heads-up
Calling the cosine similarity function with two vectors of different embedding dimensions can throw an error — in production, always check for dimension mismatches first.