| """Retrieval utilities for SHBRAG.""" | |
| from __future__ import annotations | |
| import httpx | |
| from groq import Groq | |
| from qdrant_client import QdrantClient | |
| from src.config import ( | |
| COLLECTION_NAME, | |
| GROQ_API_KEY, | |
| GROQ_MODEL, | |
| QDRANT_API_KEY, | |
| QDRANT_URL, | |
| ) | |
| from src.ingest import get_hf_embedding | |
| if not QDRANT_URL: | |
| raise ValueError("QDRANT_URL is not set.") | |
| qdrant_client = QdrantClient(url=QDRANT_URL, api_key=QDRANT_API_KEY) | |
| groq_client = Groq(api_key=GROQ_API_KEY, http_client=httpx.Client()) | |
| def retrieve_context(query: str, top_k: int = 3) -> list[dict]: | |
| """Retrieve the most relevant text chunks from Qdrant Cloud.""" | |
| if top_k <= 0: | |
| return [] | |
| query_embedding = get_hf_embedding(query) | |
| results = qdrant_client.search( | |
| collection_name=COLLECTION_NAME, | |
| query_vector=query_embedding, | |
| limit=top_k, | |
| with_payload=True, | |
| ) | |
| context_chunks: list[dict] = [] | |
| for result in results: | |
| payload = result.payload or {} | |
| context_chunks.append( | |
| { | |
| "text": payload.get("text", ""), | |
| "score": float(result.score), | |
| } | |
| ) | |
| return context_chunks | |
| def generate_answer(query: str, context_chunks: list[dict]) -> str: | |
| """Generate a grounded answer from retrieved context chunks via Groq.""" | |
| system_prompt = ( | |
| "Act as an expert research assistant. " | |
| "Answer the user's question using ONLY the provided context. " | |
| "If the context does not contain the answer, explicitly state: " | |
| "'INSUFFICIENT_CONTEXT'." | |
| ) | |
| context_text = "\n\n".join( | |
| f"[Chunk {index + 1}] {chunk.get('text', '')}" for index, chunk in enumerate(context_chunks) | |
| ) | |
| response = groq_client.chat.completions.create( | |
| model=GROQ_MODEL, | |
| temperature=0.0, | |
| messages=[ | |
| {"role": "system", "content": system_prompt}, | |
| { | |
| "role": "user", | |
| "content": f"Context:\n{context_text}\n\nQuestion:\n{query}", | |
| }, | |
| ], | |
| ) | |
| return response.choices[0].message.content or "" | |