ScienceBeam Parser

repository·main·Indexed 43 days ago

https://github.com/elifepathways/sciencebeam-parser

A Python-based tool for parsing scientific documents, designed as a partial variation of GROBID. It extracts semantic data (headers, full text, references) from PDFs and Word documents into TEI XML, JATS XML, and JSON formats. It features a multi-stage pipeline involving PDF parsing via pdfalto, semantic extraction, and TEI conversion, with support for Computer Vision (CV) and OCR models.

Tokens
17.3K
Snippets
41
Records
64
Agent score
55%

What's inside ScienceBeam Parser

  1. LLM Engine Data Integrity and Guarantees

    main

    The LLM engine enforces strict data integrity to ensure no hallucinated text is introduced into the document.

    • Text Integrity: No text reaches a document unless it existed in the source. Under values mode, every value is validated against the original token sequence. Under lines mode, only line numbers are returned.
    • Parsing Failures: If the engine receives bad JSON or a malformed entry, it retries up to max_malformed_response_retries (default 1).
    • Claim Validation: If a model claims a value that is not in the reference or is already claimed by a previous field, the value is dropped and logged to sciencebeam.dropped_fields. This prevents the model from 'adding' data that wasn't there.
    • Strict Mode: Using *_raises settings (e.g., unanswered_reference_raises) turns these warnings into fatal errors.
    • Zero Data Retention (ZDR): Every request enforces zero data retention via settings like data_collection: deny and allow_fallbacks: false to ensure privacy and security.
  2. Understand the predictions store and scoring

    main

    Scoring Logic

    Extraction quality is measured by comparing predictions (TEI or JATS) against Gold JATS. The sciencebeam-judge tool determines field mapping based on the root element. Fields and scoring methods are configured in eval.yml.

    The Predictions Store

    Predictions are stored in a private repository (sciencebeam-eval-predictions) using the key structure: <tool>/<version>/<profile>/.

    • Versioning: The version in the path prevents a tool update from incorrectly scoring against a predecessor's predictions.
    • Manifest: A manifest.jsonl file records document outcomes, and for served models, it records API calls and timings.
    • Security: The store must remain private as it contains predictions from PLOS manuscripts which are close to full-text documents.
  3. Configure LLM reasoning behavior

    main

    The reasoning_enabled setting controls whether the model uses its internal reasoning capabilities.

    • Behavior:
      • false: Sends {'enabled': false}. This is safe for all models. If a model doesn't support reasoning, the engine retries once without the parameter.
      • true: Sends {'enabled': true}.
      • Omitted: The engine sends nothing, letting the model use its default behavior.
    • Important Constraints:
      • Budget: Reasoning tokens count against max_output_tokens. If a model thinks by default, it may exhaust the budget before providing an answer.
      • Syntax: Must be an unquoted boolean in YAML (e.g., reasoning_enabled: false). Quoted values are rejected.
      • Provider-specific settings: Use extra_body for settings like effort. Do not use both reasoning_enabled and extra_body for reasoning settings, as reasoning_enabled will overwrite the extra_body value.
    extra_body:
      reasoning:
        effort: 'low'
  4. Understand the document abstraction hierarchy

    main

    ScienceBeam Parser uses three distinct document abstractions to represent data at different stages of processing:

    1. Layout Document

    Represents the parsed input document without layout information.

    • Immutability: Layout Document and its associated classes should be treated as immutable.
    • Views: You can create a 'view' by constructing a layout document with a subset of tokens (e.g., passing only header tokens to a header model).

    2. Semantic Document

    Represents the intermediate semantically extracted document. This is the core of the semantic analysis.

    • Mutability: This document is mutable and can be changed during processing.
    • Semantic Labels: The type class serves as the main semantic label (e.g., SemanticTitle for titles, SemanticPageRange for page ranges).
    • Hierarchy: Content can be hierarchical (e.g., a SemanticTitle inside a SemanticFront is a manuscript title, while a SemanticTitle inside a SemanticReference is a reference title).
    • Preservation: All text should be preserved. Content without a known semantic meaning should use SemanticNote. The document aims to maintain the original order and formatting.
    • Partial Parsing: Some types, like SemanticRawAuthors, represent partially parsed content intended for further processing by downstream models.

    3. TEI Document

    Used for the final TEI XML output.

    • Mapping: It maps the Semantic Document to XML elements.
    • Output: By default, it aims to output all content from the semantic document (often as a note) and includes page coordinates and preserved formatting.
  5. Understand the ScienceBeam Parser processing pipeline

    main

    The ScienceBeam Parser follows a multi-stage pipeline to convert PDF files into structured TEI XML. The workflow is as follows:

    1. PDF Parsing: The input PDF is parsed using pdfalto to generate XML.
    2. Layout Document Creation: The pdfalto XML is parsed into a Layout Document (sciencebeam_parser/document/layout_document.py).
    3. Re-tokenization: The layout document is re-tokenized.
    4. Semantic Extraction: The FullText Processor (sciencebeam_parser/processors/fulltext.py) uses various models to transform the Layout Document into a Semantic Document (sciencebeam_parser/document/semantic_document.py).
    5. TEI Conversion: The Semantic Document is finally converted into TEI XML (sciencebeam_parser/document/tei_document.py).
  6. Understand the `tei` generation quality record

    main

    Every run of generate_data writes a quality.jsonl file per model. This file contains one JSON line per source document, tracking the status and cardinality of labels at various stages. This allows for comparing a corpus against its aligned JATS source without post-processing counts.

    File Location:

    • If --use-directory-structure is used: <model>/quality.jsonl inside the output directory.
    • Otherwise: <model>.quality.jsonl in the output path.

    Key JSON Fields:

    • document_id: The ID of the document.
    • status: ok, missing (no JATS matched), unparsable, unreadable, timeout, or error.
    • jats.status: The status of the JATS alignment.
    • jats.reference_count: Total references declared in the JATS.
    • aligned_reference_count: Number of references successfully placed by the aligner.
    • entity_element_count: Number of entities written (e.g., bibl for citation models). Absent for region-marking models.
    • written: Boolean indicating if the model wrote a file.
    • label_counts: Per-label counts. jats counts references carrying a sub-field for that label; marked counts references actually marked in the training data.
    {
      "document_id": "PPR459453",
      "source_filename": "PPR459453.pdf",
      "status": "ok",
      "model": "citation",
      "jats": {"status": "ok", "reference_count": 45, "aligned_reference_count": 2},
      "written": true,
      "entity_element_count": 2,
      "label_counts": {"<title>": {"jats": 44, "marked": 2}}
    }
  7. Understand Reference Segmenter response shapes

    main

    The response_shape configuration determines how the reference_segmenter returns data. The choice depends on the model and task.

    • lines (Default): Returns only the line number per reference. This is efficient and uses fewer tokens.
    • evidence: Returns the line number and the first words on that line. This is more robust for verification but costs approximately four times the output tokens.

    Verification Note: A quote is considered valid if it matches the named line or the line immediately below it (as models often name the line containing the reference number but quote the text underneath). Mismatches are logged to sciencebeam.evidence_mismatches unless evidence_mismatch_raises is enabled.

  8. Configure Citation batching and concurrency

    main

    The citation model processes references in batches to improve throughput.

    Key Parameters:

    • max_references_per_request: The number of references sent in a single call. Larger batches are more efficient (roughly 2x improvement) but can trigger provider timeouts if the generation becomes too long. Smaller batches are generally preferred for stability.
    • max_concurrent_requests: The number of calls in flight at once. Increasing this provides roughly 2x throughput improvement up to 4 calls, after which provider limits usually become the bottleneck.

    Error Handling in Batches:

    • If a reference is skipped or numbered incorrectly, it is counted in sciencebeam.unanswered_references. The engine will retry skipped references in a new batch (up to max_missing_reference_retries, default 1).
    • If a response hits max_output_tokens, the batch is halved and retried until individual references are processed.
    • If unanswered_reference_raises is set, any unrecovered reference makes the entire process fatal.
    max_references_per_request: 10   # references per call
    max_concurrent_requests: 4       # calls in flight at once
  9. How models are structured in ScienceBeam Parser

    main

    Models in this project follow a specific internal structure to ensure consistency. A model typically consists of three components:

    • Data Generator (data.py): Responsible for creating the layout features required by the model.
    • Semantic Extractor (extract.py): Responsible for translating the raw model output into Semantic Content elements.
    • Model Wrapper (model.py): Provides a model-specific implementation using a common interface, usually by providing constructors for the data generator and semantic extractor.

    Note: Models do not interact with each other directly. All interactions between models are managed by the FullText Processor (sciencebeam_parser/processors/fulltext).

  10. Choose an LLM provider for the engine

    main

    When selecting an LLM provider for the ScienceBeam Parser, note that the same model ID can behave differently across providers due to quantization and performance variations. For example, qwen/qwen3.5-9b on Venice is significantly faster than on SiliconFlow for similar token accuracy.

    To find available providers, their quantization, pricing, and uptime, use the following API endpoint:

    GET /api/v1/models/{author}/{slug}/endpoints

    Note: Latency and throughput are typically returned as None in this endpoint, so you should measure performance manually for your specific use case. Additionally, ensure the provider supports the zero-retention pin if required.

    GET /api/v1/models/{author}/{slug}/endpoints
  11. Workflow for training ScienceBeam Parser sequence models

    main

    To improve performance for a specific domain, you can train custom machine learning models (such as delft) using domain-specific documents. The general workflow for training sequence models follows these steps:

    1. Generate training data: Create the initial dataset from your documents.
    2. Annotate training data: Label the generated data to provide ground truth.
    3. Train model: Use the sciencebeam-trainer-delft tool to train the model.
    4. Use and evaluate the model:
      • Configure the new model within sciencebeam-parser.
      • Convert documents using the new model.
      • Evaluate the quality of the converted documents using sciencebeam-judge.
  12. Install CPU-only PyTorch for ScienceBeam Parser

    main

    On Linux, the default PyTorch wheel includes CUDA and NVIDIA packages that are unnecessary for CPU-only deployments. To avoid these, install the CPU-specific version of torch from the PyTorch index before installing the parser.

    Using pip:

    pip install torch --index-url https://download.pytorch.org/whl/cpu
    pip install sciencebeam-parser[delft,cpu]

    Using uv: When using uv, declare torch as a direct dependency in your pyproject.toml and point it to the CPU index to ensure the source is applied correctly.

    [project]
    dependencies = [
        "sciencebeam-parser[delft,cpu]",
        "torch",
    ]
    
    [tool.uv.sources]
    torch = [{ index = "torch-cpu" }]
    
    [[tool.uv.index]]
    name = "torch-cpu"
    url = "https://download.pytorch.org/whl/cpu"
    explicit = true