Spaces:
Running
Running
| """Orchestrate one RAG turn: retrieve -> generate -> answer + source pages.""" | |
| from __future__ import annotations | |
| from dataclasses import dataclass, field | |
| from ..config import RAGConfig | |
| from ..config import rag as default_rag | |
| from .index import RagIndex | |
| from .llm import generate_answer | |
| class Answer: | |
| question: str | |
| answer: str | |
| source_pages: list[int] = field(default_factory=list) | |
| persona: str | None = None # e.g. "cook" -> shown with an IN CHARACTER tag | |
| # retrieved evidence, for transparency / debugging | |
| contexts: list[dict] = field(default_factory=list) | |
| def to_dict(self) -> dict: | |
| return { | |
| "question": self.question, | |
| "answer": self.answer, | |
| "source_pages": self.source_pages, | |
| "persona": self.persona, | |
| "in_character": bool(self.persona), | |
| "contexts": self.contexts, | |
| } | |
| def answer_question( | |
| doc_id: int, | |
| question: str, | |
| index: RagIndex, | |
| cfg: RAGConfig = default_rag, | |
| top_k: int | None = None, | |
| persona: str | None = None, | |
| ) -> Answer: | |
| retrieved = index.query(doc_id, question, top_k=top_k) | |
| if not retrieved: | |
| return Answer(question, "No transcribed text is available for this document yet.", | |
| persona=persona) | |
| contexts = [(r.page_number, r.text) for r in retrieved] | |
| text = generate_answer(question, contexts, cfg, persona=persona) | |
| # Distinct source pages in retrieval order -> the design's "Sources" chips. | |
| seen: set[int] = set() | |
| source_pages: list[int] = [] | |
| for r in retrieved: | |
| if r.page_number not in seen: | |
| seen.add(r.page_number) | |
| source_pages.append(r.page_number) | |
| return Answer( | |
| question=question, | |
| answer=text, | |
| source_pages=source_pages, | |
| persona=persona, | |
| contexts=[{"page_number": r.page_number, "score": round(r.score, 4), | |
| "text": r.text} for r in retrieved], | |
| ) | |