poster2json
Convert scientific posters (PDF/images) to structured JSON metadata using Large Language Models.
Documentation · Changelog · Report Bug · Request Feature
Description
poster2json extracts structured metadata from scientific conference posters (PDF or image format) into machine-actionable JSON conforming to the poster-json-schema.
The pipeline uses:
- Llama-3.1-8B-Instruct (a verbatim mirror of Meta's release; swap with any HuggingFace instruct model via
--model) for JSON structuring - Qwen2-VL-7B for vision-based OCR of image posters
- pdfplumber for layout-aware PDF text extraction
- lingua-language-detector for ISO 639-1 language detection on body text (overrides any value the model emits — body text beats metadata-fragment guessing)
- ROR (
https://api.ror.org) for affiliation canonicalisation; matched names get a ROR identifier attached
Quick Start
Installation
pip install poster2json
CLI Usage
# Extract metadata from a poster (default: Llama-3.1-8B-Instruct @ 4bit)
poster2json extract poster.pdf -o result.json
# Use a different instruct model (any HuggingFace repo id works)
poster2json extract poster.pdf --model google/gemma-2-9b-it --quantization 4bit
# Trade VRAM for quality
poster2json extract poster.pdf --quantization 8bit
poster2json extract poster.pdf --quantization fp16
# Validate extracted JSON
poster2json validate result.json
# Process multiple posters
poster2json batch ./posters/ -o ./output/
Python API
from poster2json import extract_poster, validate_poster
# Extract metadata
result = extract_poster("poster.pdf")
print(result["titles"][0]["title"])
# Validate the result
is_valid = validate_poster(result)
Output Format
Output conforms to the poster-json-schema (DataCite 4.7):
{
"$schema": "https://posters.science/schema/v0.2/poster_schema.json",
"creators": [
{
"name": "Garcia, Sofia",
"givenName": "Sofia",
"familyName": "Garcia",
"affiliation": [
{
"name": "Stanford University",
"affiliationIdentifier": "https://ror.org/00f54p054",
"affiliationIdentifierScheme": "ROR",
"schemeURI": "https://ror.org/"
}
]
}
],
"titles": [
{ "title": "Machine Learning Approaches to Diabetic Retinopathy Detection" }
],
"publicationYear": null,
"language": "en",
"researchField": "Health Sciences",
"subjects": [
{ "subject": "Machine Learning" },
{ "subject": "Diabetic Retinopathy" }
],
"descriptions": [
{ "description": "We present a deep learning model...", "descriptionType": "Other" }
],
"publisher": null,
"content": {
"sections": [
{ "sectionTitle": "Abstract", "sectionContent": "..." },
{ "sectionTitle": "Methods", "sectionContent": "..." },
{ "sectionTitle": "Results", "sectionContent": "..." }
]
},
"imageCaptions": [{ "id": "fig1", "caption": "Figure 1. ROC curves showing..." }],
"tableCaptions": [{ "id": "table1", "caption": "Table 1. Performance metrics" }],
"formats": ["application/pdf"]
}
Notes on the auto-populated fields:
languageis detected from the raw body text (lingua heuristic). Returns null when text is too short (<200 chars / <50 non-ASCII codepoints) or the detector is unsure.researchFieldmust be one of the four OpenAlex top-level domains:Health Sciences,Life Sciences,Physical Sciences,Social Sciences. Null when the model can't pick one confidently.affiliationgets ROR enrichment when the matcher returns a high-confidence chosen result. Strings without a confident match pass through unchanged. SetPOSTER2JSON_ROR=0to disable.publisherandpublicationYearare always emitted asnull. They are platform-owned and set when the poster is published, not by extraction.formatsis derived from the input file's extension, not the model.
System Requirements
| Requirement | Specification |
|---|---|
| GPU | NVIDIA CUDA-capable, ≥8GB VRAM (default 4bit); ≥16GB for --quantization fp16 or image/OCR posters |
| RAM | ≥32GB recommended |
| Python | 3.10+ |
| OS | Linux, macOS, Windows (via WSL2) |
Performance
Validated on 20 manually annotated scientific posters (19 PDF via pdfplumber, 1 image via vision OCR):
| Metric | Score | Threshold |
|---|---|---|
| Word Capture | 0.92 | ≥0.75 |
| ROUGE-L | 0.85 | ≥0.75 |
| Number Capture | 0.97 | ≥0.75 |
| Field Proportion | 0.88 | 0.50–1.50 |
Pass Rate: 19/20 (95%). The single failure is a dense table/flowchart poster whose reference annotation splits one visual region into many fine-grained sections.
Documentation
| Document | Description |
|---|---|
| Architecture | Technical details & methodology |
| Evaluation | Validation metrics & results |
Development Setup
# Clone the repository
git clone https://github.com/fairdataihub/poster2json.git
cd poster2json
# Create a virtual environment
python -m venv .venv
# Activate the virtual environment
source venv/bin/activate
.venv\Scripts\activate # On Windows
# Install poetry
pip install poetry
# Install dependencies
poetry install
# Run tests
poe test
# Format code
poe format
If you are on windows and have multiple python versions, you can use the following commands:
py -0p # list all python versions
py -3.12 -m venv .venv
License
MIT License - see LICENSE for details.
Citation
@software{poster2json2026,
title = {poster2json: Scientific Poster to JSON Metadata Extraction},
author = {O'Neill, James and Soundarajan, Sanjay and Portillo, Dorian and Patel, Bhavesh},
year = {2026},
version = {0.8.0},
url = {https://github.com/fairdataihub/poster2json},
doi = {10.5281/zenodo.18320010}
}
Funding
This project is funded by The Navigation Fund (10.71707/rk36-9x79).
Contributing
Contributions welcome! Please see CONTRIBUTING.md for guidelines.
Release files for poster2json 0.9.23
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| poster2json-0.9.23.tar.gz | 80.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| poster2json-0.9.23-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 165.4 kB
Release files / poster2json-0.9.23.tar.gz
| Download URL | poster2json-0.9.23.tar.gz |
|---|---|
| Size | 80.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9cb907a74c78cb4c53e026281b83753437b0ed3270df14ab7a40f07dc407dbbf
|
|
BLAKE2b-256 checksum How to use checksums |
d2e18b78ca772d64e006e0fc9b2b6df2625f15a0e2ea05f1abc083909ad40a1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.12.13 Linux/6.17.0-1018-azure
|
Release files / poster2json-0.9.23-py3-none-any.whl
| Download URL | poster2json-0.9.23-py3-none-any.whl |
|---|---|
| Size | 85.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c9a0032ae8d5031417a57ff28aeb642e2501d4b1ce61938c3c7e57bc0af42a5e
|
|
BLAKE2b-256 checksum How to use checksums |
289fc5233591b24e25b997f528ae2005b0e91c02a18b279a0fad81c302ea127d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.4.1 CPython/3.12.13 Linux/6.17.0-1018-azure
|