Spaces:
Sleeping
Sleeping
| """Folder-level extraction helpers for locally downloaded PDFs.""" | |
| from __future__ import annotations | |
| from pathlib import Path | |
| from typing import Dict, List, Optional | |
| from extractor import extract_pdf | |
| from perovskite import extract_perovskite_fields | |
| def _pdf_files(folder: Path, *, recursive: bool) -> List[Path]: | |
| pattern = "**/*.pdf" if recursive else "*.pdf" | |
| return sorted(p for p in folder.glob(pattern) if p.is_file()) | |
| def _lighten_extraction(ext: Dict, *, include_full_text: bool) -> Dict: | |
| item = dict(ext) | |
| if not include_full_text: | |
| item.pop("full_text", None) | |
| return item | |
| def extract_folder_pdfs( | |
| folder_path: str, | |
| query: str = "", | |
| *, | |
| recursive: bool = True, | |
| max_files: Optional[int] = None, | |
| use_llm_filter: Optional[bool] = None, | |
| include_full_text: bool = False, | |
| analyze_images: Optional[bool] = None, | |
| image_query: str = "", | |
| ) -> Dict: | |
| """Extract text/images/perovskite fields from PDFs under ``folder_path``. | |
| The response is intentionally lightweight by default: per-paper full text is | |
| omitted unless ``include_full_text`` is true, so MCP responses stay small. | |
| """ | |
| folder = Path(folder_path).expanduser() | |
| if not folder.exists() or not folder.is_dir(): | |
| return { | |
| "ok": False, | |
| "error": "folder_not_found", | |
| "folder_path": str(folder), | |
| "results": [], | |
| "summary": { | |
| "total_pdf_files": 0, | |
| "processed": 0, | |
| "succeeded": 0, | |
| "failed": 0, | |
| }, | |
| } | |
| pdfs = _pdf_files(folder, recursive=recursive) | |
| total_pdf_files = len(pdfs) | |
| if max_files is not None: | |
| limit = max(0, int(max_files)) | |
| pdfs = pdfs[:limit] | |
| results: List[Dict] = [] | |
| succeeded = 0 | |
| failed = 0 | |
| for pdf_path in pdfs: | |
| try: | |
| ext = extract_pdf( | |
| str(pdf_path), | |
| query=query, | |
| analyze_images=analyze_images, | |
| image_query=image_query, | |
| ) | |
| if not ext.get("ok"): | |
| failed += 1 | |
| item = { | |
| "ok": False, | |
| "pdf_path": str(pdf_path), | |
| "filename": pdf_path.name, | |
| "error": ext.get("error") or "extract_failed", | |
| } | |
| else: | |
| fields = extract_perovskite_fields( | |
| ext.get("full_text") or "", | |
| use_llm_filter=use_llm_filter, | |
| ) | |
| item = _lighten_extraction(ext, include_full_text=include_full_text) | |
| item["filename"] = pdf_path.name | |
| item["perovskite_fields"] = fields | |
| succeeded += 1 | |
| except Exception as exc: # noqa: BLE001 - keep batch processing going | |
| failed += 1 | |
| item = { | |
| "ok": False, | |
| "pdf_path": str(pdf_path), | |
| "filename": pdf_path.name, | |
| "error": f"extract_failed: {exc}", | |
| } | |
| results.append(item) | |
| return { | |
| "ok": failed == 0, | |
| "folder_path": str(folder), | |
| "recursive": recursive, | |
| "max_files": max_files, | |
| "results": results, | |
| "summary": { | |
| "total_pdf_files": total_pdf_files, | |
| "processed": len(pdfs), | |
| "succeeded": succeeded, | |
| "failed": failed, | |
| }, | |
| } | |