Spaces:
Sleeping
Sleeping
| """ | |
| Document Loader — ingests PDF/TXT documents from the data/papers directory. | |
| Chunks documents with overlap for better retrieval context. | |
| """ | |
| from __future__ import annotations | |
| import re | |
| from pathlib import Path | |
| def _chunk_text( | |
| text: str, | |
| chunk_size: int = 400, | |
| overlap: int = 80, | |
| ) -> list[str]: | |
| """Split text into overlapping chunks by word count.""" | |
| words = text.split() | |
| chunks = [] | |
| start = 0 | |
| while start < len(words): | |
| end = min(start + chunk_size, len(words)) | |
| chunk = " ".join(words[start:end]) | |
| if len(chunk.strip()) > 50: # skip trivially short chunks | |
| chunks.append(chunk) | |
| start += chunk_size - overlap | |
| return chunks | |
| def _clean_text(text: str) -> str: | |
| """Basic text cleanup — remove excessive whitespace and encoding artefacts.""" | |
| text = re.sub(r'\s+', ' ', text) | |
| text = re.sub(r'[^\x00-\x7F]+', ' ', text) | |
| return text.strip() | |
| def load_pdf(path: Path) -> list[dict]: | |
| """Load a PDF and return chunked text with metadata.""" | |
| try: | |
| import fitz # PyMuPDF | |
| doc = fitz.open(str(path)) | |
| full_text = " ".join(page.get_text() for page in doc) | |
| full_text = _clean_text(full_text) | |
| chunks = _chunk_text(full_text) | |
| meta = { | |
| "source": path.name, | |
| "title": path.stem.replace("_", " ").replace("-", " "), | |
| "authors": "Rahman MA et al.", | |
| "year": "2024", | |
| "domain": "research_paper", | |
| } | |
| return [{"text": c, "metadata": meta} for c in chunks] | |
| except ImportError: | |
| print("PyMuPDF not installed — skipping PDF loading. Run: pip install pymupdf") | |
| return [] | |
| except Exception as e: | |
| print(f"Error loading {path}: {e}") | |
| return [] | |
| def load_txt(path: Path) -> list[dict]: | |
| """Load a plain text file and return chunked content.""" | |
| try: | |
| text = _clean_text(path.read_text(encoding="utf-8", errors="ignore")) | |
| chunks = _chunk_text(text) | |
| meta = { | |
| "source": path.name, | |
| "title": path.stem.replace("_", " "), | |
| "authors": "", | |
| "year": "", | |
| "domain": "document", | |
| } | |
| return [{"text": c, "metadata": meta} for c in chunks] | |
| except Exception as e: | |
| print(f"Error loading {path}: {e}") | |
| return [] | |
| def load_all_documents(docs_dir: Path) -> list: | |
| """Load all supported documents from a directory.""" | |
| from src.retrieval.rag_pipeline import DocumentChunk | |
| docs_dir = Path(docs_dir) | |
| if not docs_dir.exists(): | |
| return [] | |
| all_chunks = [] | |
| loaders = {".pdf": load_pdf, ".txt": load_txt} | |
| for ext, loader in loaders.items(): | |
| for fpath in docs_dir.glob(f"*{ext}"): | |
| print(f"Loading: {fpath.name}") | |
| raw = loader(fpath) | |
| for item in raw: | |
| all_chunks.append( | |
| DocumentChunk(text=item["text"], metadata=item["metadata"]) | |
| ) | |
| print(f"Loaded {len(all_chunks)} chunks from {docs_dir}") | |
| return all_chunks | |