Spaces:
Sleeping
Sleeping
| """ | |
| Constructs the prompt sent to the LLM. | |
| This is where grounding happens — the system prompt explicitly instructs the | |
| model to only use the provided context. Understanding this module deeply is | |
| what separates RAG engineers from people who just call LangChain. | |
| Key concepts: | |
| - System prompt: Sets behaviour for the entire conversation. | |
| - Context block: The retrieved chunks, formatted clearly with source info. | |
| - User question: The original query. | |
| Interview question: "How do you prevent hallucination in RAG?" | |
| Answer lives here: the system prompt + the fallback behaviour when context is weak. | |
| """ | |
| SYSTEM_PROMPT = """You are a precise document assistant. Your job is to answer questions | |
| using ONLY the context passages provided below. | |
| Rules you must follow: | |
| 1. If the answer is clearly in the context, answer directly and cite the source. | |
| 2. If the context is partially relevant, use what is there and acknowledge limits. | |
| 3. If the context contains no relevant information, say exactly: | |
| "I could not find relevant information in the provided documents." | |
| Do NOT guess, infer beyond the text, or use prior knowledge. | |
| 4. Always mention which document and page your answer comes from. | |
| """ | |
| def build_prompt(query: str, chunks: list[dict]) -> str: | |
| """ | |
| Assemble the full prompt from retrieved chunks + user query. | |
| Args: | |
| query: The user's question. | |
| chunks: Retrieved chunks from Retriever.retrieve() | |
| Returns: | |
| A single formatted string ready to send to the LLM. | |
| """ | |
| if not chunks: | |
| context_block = "No relevant context was retrieved." | |
| else: | |
| context_parts = [] | |
| for i, chunk in enumerate(chunks, start=1): | |
| context_parts.append( | |
| f"[Source {i}: {chunk['source']}, Page {chunk['page']} | Similarity: {chunk['score']}]\n" | |
| f"{chunk['text']}" | |
| ) | |
| context_block = "\n\n---\n\n".join(context_parts) | |
| prompt = ( | |
| f"{SYSTEM_PROMPT}\n\n" | |
| f"=== CONTEXT ===\n{context_block}\n\n" | |
| f"=== QUESTION ===\n{query}\n\n" | |
| f"=== ANSWER ===" | |
| ) | |
| return prompt | |
| def build_messages(query: str, chunks: list[dict]) -> list[dict]: | |
| """ | |
| Build chat-style messages (system/user) for models that use message format. | |
| Used with HuggingFace chat-template models. | |
| """ | |
| context_block = _format_context(chunks) | |
| return [ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| { | |
| "role": "user", | |
| "content": f"Context:\n{context_block}\n\nQuestion: {query}", | |
| }, | |
| ] | |
| def _format_context(chunks: list[dict]) -> str: | |
| if not chunks: | |
| return "No relevant context was retrieved." | |
| parts = [] | |
| for i, chunk in enumerate(chunks, start=1): | |
| parts.append(f"[{chunk['source']} | p{chunk['page']}]\n{chunk['text']}") | |
| return "\n\n".join(parts) | |