โ˜… Final Challenge

โ€บ Ask Your Documents

50 pts

Your app is complete: it loads and chunks your files, embeds them, indexes them in a real vector database, retrieves by meaning, and answers with citations โ€” or refuses. The final challenge is that app's query path as one pure function. Everything you built is in it: cosine scoring, top-k selection, the score gate, prompt assembly. The two impure edges โ€” the embedding model and the LLM โ€” arrive as injected callables, exactly as embed_texts and llm_client do in rag.py; the tests stub them the same way the CLI chatbot course stubbed its client.

Implement retrieve_and_answer(question, entries, embed, client, k=3, min_score=0.25):

  • entries is a list of (chunk_id, text, vector) tuples โ€” your indexed corpus.
  • Call embed(question) exactly once to get the query vector.
  • Score every entry with cosine similarity (a working cosine_similarity is in the starter), and select up to k best entries โ€” highest score first, ties keeping input order, exactly like your top_k.
  • Drop selected entries scoring below min_score. If nothing survives (or entries is empty), return None without calling client โ€” that's the refusal gate.
  • Otherwise build the prompt with your build_prompt format from the previous lesson, using the surviving (chunk_id, text) pairs in score order, call client(prompt) exactly once, and return its reply.

Log in to submit a solution and earn points.