| from pathlib import Path | |
| from langchain_core.documents import Document | |
| SUPPORTED_EXTENSIONS = {".txt", ".md", ".pdf", ".docx", ".html", ".htm"} | |
| def load_documents(data_dir: str) -> list[Document]: | |
| root = Path(data_dir) | |
| root.mkdir(parents=True, exist_ok=True) | |
| documents: list[Document] = [] | |
| for path in sorted(root.rglob("*")): | |
| if not path.is_file() or path.suffix.lower() not in SUPPORTED_EXTENSIONS: | |
| continue | |
| documents.extend(load_document(path)) | |
| return documents | |
| def load_document(path: Path) -> list[Document]: | |
| suffix = path.suffix.lower() | |
| if suffix in {".txt", ".md"}: | |
| return [_text_document(path)] | |
| if suffix == ".pdf": | |
| return _pdf_documents(path) | |
| if suffix == ".docx": | |
| return [_docx_document(path)] | |
| if suffix in {".html", ".htm"}: | |
| return [_html_document(path)] | |
| return [] | |
| def _base_metadata(path: Path) -> dict: | |
| return { | |
| "source": path.name, | |
| "source_path": str(path), | |
| "file_type": path.suffix.lower().lstrip("."), | |
| } | |
| def _text_document(path: Path) -> Document: | |
| return Document(page_content=path.read_text(encoding="utf-8", errors="ignore"), metadata=_base_metadata(path)) | |
| def _pdf_documents(path: Path) -> list[Document]: | |
| try: | |
| from pypdf import PdfReader | |
| except ImportError as exc: | |
| raise RuntimeError("Install pypdf to ingest PDF files.") from exc | |
| reader = PdfReader(str(path)) | |
| documents: list[Document] = [] | |
| for index, page in enumerate(reader.pages, start=1): | |
| metadata = _base_metadata(path) | |
| metadata["page"] = index | |
| documents.append(Document(page_content=page.extract_text() or "", metadata=metadata)) | |
| return documents | |
| def _docx_document(path: Path) -> Document: | |
| try: | |
| from docx import Document as DocxDocument | |
| except ImportError as exc: | |
| raise RuntimeError("Install python-docx to ingest DOCX files.") from exc | |
| doc = DocxDocument(str(path)) | |
| text = "\n".join(paragraph.text for paragraph in doc.paragraphs if paragraph.text.strip()) | |
| return Document(page_content=text, metadata=_base_metadata(path)) | |
| def _html_document(path: Path) -> Document: | |
| try: | |
| from bs4 import BeautifulSoup | |
| except ImportError as exc: | |
| raise RuntimeError("Install beautifulsoup4 to ingest HTML files.") from exc | |
| soup = BeautifulSoup(path.read_text(encoding="utf-8", errors="ignore"), "html.parser") | |
| for tag in soup(["script", "style"]): | |
| tag.decompose() | |
| return Document(page_content=soup.get_text("\n", strip=True), metadata=_base_metadata(path)) | |