End-to-end RAG engine for scientific PDF documents. Orchestrates the full pipeline: 1. **PDF parsing** via a GROBID server (structured text + coordinates). 2. **Chunking** — paragraphs kept as-is or merged with :class:`TextMerger`. 3. **Embedding and storage** chunks are embedded
| 252 | |
| 253 | |
| 254 | class DocumentQAEngine: |
| 255 | """End-to-end RAG engine for scientific PDF documents. |
| 256 | |
| 257 | Orchestrates the full pipeline: |
| 258 | |
| 259 | 1. **PDF parsing** via a GROBID server (structured text + coordinates). |
| 260 | 2. **Chunking** — paragraphs kept as-is or merged with :class:`TextMerger`. |
| 261 | 3. **Embedding and storage** chunks are embedded and stored. |
| 262 | 4. **Retrieval + LLM** — relevant chunks are retrieved and fed to an LLM |
| 263 | to produce an answer. |
| 264 | |
| 265 | Args: |
| 266 | llm: A LangChain chat model (e.g. ``ChatOpenAI``). |
| 267 | data_storage: A `DataStorage` instance for managing embeddings. |
| 268 | grobid_url: URL of the GROBID server. |
| 269 | memory: Optional ``ConversationBufferMemory`` for multi-turn context. |
| 270 | |
| 271 | """ |
| 272 | |
| 273 | llm = None |
| 274 | qa_chain_type = None |
| 275 | |
| 276 | default_prompts = { |
| 277 | "stuff": stuff_prompt, |
| 278 | "refine": refine_prompts, |
| 279 | "map_reduce": map_reduce_prompt, |
| 280 | "map_rerank": map_rerank_prompt, |
| 281 | } |
| 282 | |
| 283 | def __init__(self, llm, data_storage: DataStorage, grobid_url=None, memory=None, ping_grobid_server: bool = True): |
| 284 | |
| 285 | self.llm = llm |
| 286 | self.memory = memory |
| 287 | self.chain = create_stuff_documents_chain(llm, self.default_prompts["stuff"].PROMPT) |
| 288 | self.text_merger = TextMerger() |
| 289 | self.data_storage = data_storage |
| 290 | |
| 291 | if grobid_url: |
| 292 | self.grobid_processor = GrobidProcessor(grobid_url, ping_server=ping_grobid_server) |
| 293 | |
| 294 | def query_document( |
| 295 | self, query: str, doc_id, output_parser=None, context_size=4, extraction_schema=None, verbose=False |
| 296 | ) -> tuple[Any, str, list]: |
| 297 | """Ask a question and get an LLM-generated answer. |
| 298 | |
| 299 | Retrieves the most relevant chunks from the vector store, feeds |
| 300 | them as context to the LLM, and returns the response. |
| 301 | |
| 302 | Args: |
| 303 | query: The natural-language question. |
| 304 | doc_id: Document identifier returned by create_memory_embeddings`. |
| 305 | output_parser: Optional LangChain output parser. If provided the |
| 306 | raw LLM response is re-processed into structured output. |
| 307 | context_size: Number of chunks to retrieve as context (default 4). |
| 308 | extraction_schema: Optional extraction schema. |
| 309 | verbose: Print debug information. |
| 310 | |
| 311 | Returns: |