Skip to main content
parsemedicalexams

parsemedicalexams

License Python OpenRouter

🏥 Extract and summarize medical exam reports from PDFs using Vision AI 📄

Features · Quick Start · Configuration · Output Format


Features

  • Vision-powered extraction — Uses Vision LLMs to read X-rays, MRIs, ultrasounds, endoscopies, and more directly from PDF scans
  • Self-consistency voting — Runs multiple extractions and votes on the best result for maximum reliability
  • Intelligent classification — Automatically categorizes exams (imaging, ultrasound, endoscopy, other) and standardizes naming
  • Clinical summarization — Preserves all findings, impressions, and recommendations while filtering noise
  • Markdown output with YAML frontmatter — Clean, structured files ready for Obsidian, static sites, or further processing
  • Smart caching — Persistent JSON caches avoid redundant API calls and allow manual overrides
  • Multi-era document handling — Frequency-based date voting correctly handles documents spanning multiple time periods

Quick Start

1. Install

pip install -e .

Requires Poppler for PDF processing:

  • macOS: brew install poppler
  • Ubuntu: apt-get install poppler-utils

2. Configure

cp .env.example .env

Edit .env with your settings:

OPENROUTER_API_KEY=your_api_key_here
INPUT_PATH=/path/to/your/exam/pdfs
OUTPUT_PATH=/path/to/output

3. Run

python main.py

How It Works

┌─────────────┐    ┌─────────────────┐    ┌────────────────┐    ┌──────────────┐    ┌────────────┐
│  PDF Input  │───▶│  Preprocessing  │───▶│ Vision LLM ×N  │───▶│ Standardize  │───▶│  Markdown  │
│             │    │  (grayscale,    │    │  + voting      │    │  + classify  │    │   Output   │
│             │    │   resize)       │    │                │    │              │    │            │
└─────────────┘    └─────────────────┘    └────────────────┘    └──────────────┘    └────────────┘
  1. PDF → Images — Converts each page to grayscale, resizes, and enhances contrast
  2. Document classification — Determines if the document is a medical exam before processing
  3. Vision LLM transcription — Transcribes each page verbatim using function calling (runs N times for reliability)
  4. Self-consistency voting — If transcriptions differ, LLM votes on the best result
  5. Standardization — Classifies exam type and standardizes the name via LLM with caching
  6. Summarization — Generates document-level clinical summaries preserving all findings

Configuration

Environment Variables

Variable Description Default
OPENROUTER_API_KEY Your OpenRouter API key (get one here) required
INPUT_PATH Directory containing exam PDFs required
OUTPUT_PATH Where to write output files required
EXTRACT_MODEL_ID Vision model for extraction google/gemini-2.5-flash
SUMMARIZE_MODEL_ID Model for summarization google/gemini-2.5-flash
SELF_CONSISTENCY_MODEL_ID Model for voting google/gemini-2.5-flash
N_EXTRACTIONS Number of extraction runs for voting 3
MAX_WORKERS Parallel workers for PDF processing 1
INPUT_FILE_REGEX Regex pattern for input files .*\.pdf

Using Profiles

Profiles let you save different input/output configurations for different use cases:

# Create a profile from template
cp profiles/_template.yaml profiles/myprofile.yaml

# Run with profile
python main.py --profile myprofile

# List available profiles
python main.py --list-profiles

Profile files (YAML or JSON) support path overrides and model configuration:

name: myprofile
input_path: /path/to/input
output_path: /path/to/output
input_file_regex: ".*\\.pdf"
model: google/gemini-2.5-flash  # Optional override
workers: 1                       # Optional override

CLI Options

Option Description
--profile, -p Profile name to use
--list-profiles List available profiles
--regenerate Regenerate markdown files from existing JSON data
--reprocess-all Force reprocess all documents
--document, -d Process only this document (filename or stem)
--page Process only this page number (requires --document)
--model, -m Override model ID
--workers, -w Override worker count
--pattern Override input file regex

Examples:

# Process all new PDFs
python main.py --profile tsilva

# Regenerate summaries from existing transcription files
python main.py --profile tsilva --regenerate

# Force reprocess all documents
python main.py --profile tsilva --reprocess-all

# Reprocess a specific document
python main.py -p tsilva -d exam_2024.pdf

# Reprocess a specific page within a document
python main.py -p tsilva -d exam_2024.pdf --page 2

Output Format

The parser generates structured markdown files with YAML frontmatter:

output/
├── {document}/
│   ├── {document}.pdf            # Source PDF copy
│   ├── {document}.001.jpg        # Page 1 image
│   ├── {document}.001.md         # Page 1 transcription + metadata
│   ├── {document}.002.jpg        # Page 2 image
│   ├── {document}.002.md         # Page 2 transcription + metadata
│   └── {document}.summary.md     # Document-level summary

Transcription File Structure

Each .md file contains YAML frontmatter with metadata followed by the verbatim transcription:

---
date: 2024-01-15
title: "Chest X-Ray PA and Lateral"
category: imaging
exam_name_raw: "RX TORAX PA Y LAT"
doctor: "Dr. Smith"
facility: "Hospital Central"
confidence: 0.95
page: 1
source: exam_2024.pdf
---

[Full verbatim transcription text here...]

Metadata Fields

Field Description
date Exam date (YYYY-MM-DD)
title Standardized exam name (English)
category Exam type: imaging, ultrasound, endoscopy, other
exam_name_raw Exam name exactly as written in document
doctor Physician name (if found)
facility Healthcare facility name
department Department within facility
confidence Self-consistency confidence score (0.0-1.0)
page Page number in source PDF
source Source PDF filename

Architecture

parsemedicalexams/
├── main.py              # Pipeline orchestration, CLI handling
├── extraction.py        # Pydantic models, Vision LLM extraction, voting
├── standardization.py   # Exam type classification with JSON cache
├── summarization.py     # Document-level clinical summarization
├── config.py            # ExtractionConfig (.env) + ProfileConfig (profiles/)
├── utils.py             # Image preprocessing, logging, JSON utilities
├── prompts/             # Externalized LLM prompts as markdown
├── profiles/            # User-specific path configurations
└── config/cache/        # Persistent LLM response caches (user-editable)

Key Design Patterns

  • Two-phase processing: Classify document first, then transcribe all pages
  • Two-column naming: *_raw (exact from document) + *_standardized (LLM-mapped)
  • Persistent caching: LLM standardization results cached in config/cache/*.json
  • Editable caches: Manually override cached values to fix misclassifications
  • Profile inheritance: Profiles can inherit from .env with overrides
  • Frequency-based date voting: Handles multi-era documents (e.g., 2024 cover letter + 1997 records)

Requirements

License

MIT

Metadata

Release files for parsemedicalexams 0.1.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for parsemedicalexams 0.1.3
File Size Uploaded Provenance Actions
parsemedicalexams-0.1.3.tar.gz 2.0 MB With provenance Details for parsemedicalexams-0.1.3.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for parsemedicalexams 0.1.3
File Interpreter ABI Platform Actions
parsemedicalexams-0.1.3-py3-none-any.whl Python 3 none any Details for parsemedicalexams-0.1.3-py3-none-any.whl

Total release size: 2.0 MB

Release files / parsemedicalexams-0.1.3.tar.gz

Download URL parsemedicalexams-0.1.3.tar.gz
Size 2.0 MB
Tags Source
SHA-256 checksum
How to use checksums
4db4224ddee16fd2c6b3d9a6946cd2b0b8b784fb52959047b4dc53b06eaed7f4
BLAKE2b-256 checksum
How to use checksums
8b8d575e7f5a4c78919c9e98c8e85d78fb695ab2de47135dcfd5063628939e5a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 28, 2026.

Transparency log

Release files / parsemedicalexams-0.1.3-py3-none-any.whl

Download URL parsemedicalexams-0.1.3-py3-none-any.whl
Size 29.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d373630ac05a311d6a799c3b5eccb35380e8ec636b25be7d386b86396e8858d8
BLAKE2b-256 checksum
How to use checksums
88e8054c8c444984587d95cb118b62ce90b18c14595053d46be4517f9e6f4c5a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 28, 2026.

Transparency log

Security for parsemedicalexams 0.1.3

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for parsemedicalexams-0.1.3.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 28, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.3 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page