deep-research-back-hf / pdf_parser.py
chandra-prakash-94
feat: add first hf backend version
eb39750
Raw
History Blame Contribute Delete
2.79 kB
"""
pdf_parser.py
─────────────
Utility called by fastapi_main.py before invoking the LangGraph pipeline.
Accepts a list of (filename, raw_bytes) tuples, parses each PDF with LiteParse,
and returns a list of {"filename": str, "content": str} dicts ready to be stored
in the LangGraph state as `pdf_context`.
Each file's extracted text is truncated to MAX_SOURCE_CHARS (same cap used for
web-scraped content) so the synthesis token budget is not blown.
"""
import tempfile
import os
from liteparse import LiteParse
from config import MAX_SOURCE_CHARS
def parse_pdfs(file_bytes_list: list[tuple[str, bytes]]) -> list[dict] | None:
"""
Parse a list of PDF files and return their text content.
Args:
file_bytes_list: List of (filename, raw_bytes) tuples.
Returns:
List of {"filename": str, "content": str} dicts, or None if input is empty.
Files that fail to parse are skipped with a warning printed to stdout.
"""
if not file_bytes_list:
return None
parser = LiteParse()
results = []
for filename, raw_bytes in file_bytes_list:
# Write to a temp file because LiteParse expects a file path
suffix = os.path.splitext(filename)[-1] or ".pdf"
tmp = None
try:
with tempfile.NamedTemporaryFile(suffix=suffix, delete=False) as tmp:
tmp.write(raw_bytes)
tmp_path = tmp.name
print(f" [PDF] Parsing: {filename} ({len(raw_bytes) / 1024:.1f} KB)")
parsed = parser.parse(tmp_path)
# Concatenate all page texts
full_text = "\n\n".join(
page.text for page in parsed.pages if page.text and page.text.strip()
)
if not full_text.strip():
print(f" ⚠️ [PDF] No text extracted from: {filename} (may be image-only)")
continue
# Truncate to the same per-source cap used for web content
if len(full_text) > MAX_SOURCE_CHARS:
marker = "\n\n[PDF content truncated to fit the source budget.]"
full_text = full_text[: MAX_SOURCE_CHARS - len(marker)].rsplit(" ", 1)[0] + marker
results.append({"filename": filename, "content": full_text})
print(f" βœ… [PDF] Parsed: {filename} ({len(full_text):,} chars extracted)")
except Exception as exc:
print(f" ⚠️ [PDF] Failed to parse '{filename}': {type(exc).__name__}: {exc}")
finally:
# Always clean up the temp file
if tmp is not None and os.path.exists(tmp.name):
try:
os.unlink(tmp.name)
except OSError:
pass
return results if results else None