File size: 2,631 Bytes
14c7fcf
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
from __future__ import annotations

import time
from functools import lru_cache
from pathlib import Path
from typing import Literal

from .models import PaperDocument
from .sections import split_markdown_sections

ParserMode = Literal["standard", "granite"]


@lru_cache(maxsize=1)
def _standard_converter():
    from docling.document_converter import DocumentConverter

    return DocumentConverter()


@lru_cache(maxsize=1)
def _granite_converter():
    from docling.datamodel import vlm_model_specs
    from docling.datamodel.base_models import InputFormat
    from docling.datamodel.pipeline_options import VlmPipelineOptions
    from docling.document_converter import DocumentConverter, PdfFormatOption
    from docling.pipeline.vlm_pipeline import VlmPipeline

    pipeline_options = VlmPipelineOptions(
        vlm_options=vlm_model_specs.GRANITEDOCLING_TRANSFORMERS,
    )
    return DocumentConverter(
        format_options={
            InputFormat.PDF: PdfFormatOption(
                pipeline_cls=VlmPipeline,
                pipeline_options=pipeline_options,
            )
        }
    )


def parse_document(
    source: str,
    parser_mode: ParserMode = "granite",
    page_limit: int = 3,
) -> PaperDocument:
    """Convert a PDF/URL into structured Markdown with Docling.

    Granite mode is the multimodal transformer path. Standard mode is a faster
    fallback and a useful baseline for later extraction-quality comparisons.
    """

    if parser_mode not in {"standard", "granite"}:
        raise ValueError(f"Unknown parser mode: {parser_mode}")
    if page_limit < 1:
        raise ValueError("page_limit must be at least 1")

    converter = _granite_converter() if parser_mode == "granite" else _standard_converter()

    started = time.perf_counter()
    result = converter.convert(
        source=source,
        page_range=(1, page_limit),
        raises_on_error=True,
    )
    elapsed = time.perf_counter() - started
    markdown = result.document.export_to_markdown()
    sections = split_markdown_sections(markdown)

    filename = Path(source).name if not source.startswith("http") else source
    metadata = {
        "display_name": filename,
        "pages_requested": page_limit,
        "conversion_seconds": round(elapsed, 2),
        "section_count": len(sections),
        "word_count": len(markdown.split()),
        "formula_markers": markdown.count("$$") + markdown.count("\\[") + markdown.count("\\("),
    }
    return PaperDocument(
        source=source,
        parser_mode=parser_mode,
        markdown=markdown,
        sections=sections,
        metadata=metadata,
    )