CLI Reference

The lemat-synth command-line tool lets you extract structured synthesis procedures from materials science papers without writing any Python code.

lemat-synth extract <paper>   [key=value ...] # Extract from a single paper
lemat-synth batch   <folder>  [key=value ...] # Extract from a folder of papers

Both commands accept the same key=value overrides, which can be used to change models, prompts, output paths, and other settings. See Quick Reference: All Arguments below.

By default, extraction runs a single LLM pass over the whole paper. Pass domain=catalysis (or superconductors, electrochemistry) to filter figures down to domain-relevant plots, add with_performance=true to also extract and link plot data to materials (requires ANTHROPIC_API_KEY), and override any prompts.* key, e.g., prompts.synthesis_instructions="...", to customize the extraction instructions.

Quick Reference: All Arguments

All settings — models, prompts, domain, output path — live in examples/config/cli.yaml. You can override any of them directly on the command line using Hydra key=value syntax.

ArgumentTypeDefaultDescription
Models & API
synthesis_modelstringgemini/gemini-3.5-flash-liteMain extraction model (LiteLLM format)
material_modelstringgemini/gemini-3.5-flash-liteFast model for material-list extraction
judge_modelstring(mirrors synthesis_model)Quality evaluation model
linker_modelstringgemini/gemini-3.1-pro-previewLinks plots to materials (requires with_performance=true)
plot_modelstringclaude-sonnet-4.6Claude model for plot data extraction (requires with_performance=true)
api_basestringnullCustom API base URL, e.g. https://openrouter.ai/api/v1
synthesis_api_key_envstringnullEnv var name holding synthesis model API key
material_api_key_envstringnullEnv var name holding material model API key
judge_api_key_envstring(mirrors synthesis_api_key_env)Env var name for judge model
linker_api_key_envstringnullEnv var name for linker model
Pipeline Behavior
domainchoicegenericPlot filtering: generic, catalysis, superconductors, electrochemistry
with_performanceboolfalseExtract performance data and link to materials (requires Claude API key)
output_dirpathresultsOutput directory for results
pdf_extractorchoicedoclingPDF extraction backend: docling (local) or mistral (API-based)
figure_segmenterchoicedinoFigure segmentation: dino or florence
florence_repo_idstringamayuelas/plot-visualization-florence-2-lora-32HuggingFace LoRA adapter ID (when figure_segmenter=florence)
Batch Only
max_papersintnullMaximum papers to process (null = all)
skip_existingbooltrueSkip papers already in output directory
max_papers_parallelint4Concurrent papers to process
Prompts
prompts.synthesis_systemstring(see below)System message for synthesis extraction
prompts.synthesis_instructionsstring(see below)Task instructions for synthesis extractor
prompts.material_instructionsstring(see below)Task instructions for material extractor
Other prompt keysstring(see below)See Customising prompts

Examples

Basic usage

# Uses all defaults from examples/config/cli.yaml
lemat-synth extract paper.txt

# Custom output folder
lemat-synth extract paper.txt output_dir=my_results/

Common customizations

# Use a different synthesis model
lemat-synth extract paper.txt synthesis_model=anthropic/claude-sonnet-4-6

# Domain-specific plot filtering (catalysis, superconductors, or electrochemistry)
lemat-synth extract paper.txt domain=catalysis

# Extract performance data and link plots to materials (requires ANTHROPIC_API_KEY)
lemat-synth extract paper.txt with_performance=true

# Use Mistral OCR for better PDF extraction (requires MISTRAL_API_KEY)
lemat-synth extract paper.pdf pdf_extractor=mistral

# Override the synthesis extraction prompt (inner 'single quotes' are required
# here because the value contains a comma — see "Customizing Prompts" below)
lemat-synth extract paper.txt \
    "prompts.synthesis_instructions='Extract only the primary synthesis route, ignoring alternative procedures.'"

Advanced: OpenRouter with multiple API keys

# All models through OpenRouter (Gemini Flash for synthesis, Claude for performance)
lemat-synth extract data/cipollone_2022.pdf \
    api_base="https://openrouter.ai/api/v1" \
    pdf_extractor=mistral \
    material_model="openrouter/google/gemini-3.1-pro-preview" \
    material_api_key_env=GEMINI_API_KEY \
    synthesis_model="openrouter/google/gemini-3-flash-preview" \
    synthesis_api_key_env=GEMINI_API_KEY \
    linker_model="openrouter/google/gemini-3.1-pro-preview" \
    linker_api_key_env=GEMINI_API_KEY \
    output_dir="results/"
Caution
The _api_key_env arguments must not contain the actual API key: they must be the name of an environment variable that holds the key. For example, material_api_key_env=GEMINI_API_KEY means that the material model set to Gemini will use the API key stored in the environment variable GEMINI_API_KEY. See API key environment variables for more details.

Advanced: Extract with performance linking (OpenRouter)

Extract synthesis procedures and link extracted plot data to synthesized materials:

# Same as above, plus performance extraction using Claude via OpenRouter
lemat-synth extract data/cipollone_2022.pdf \
    api_base="https://openrouter.ai/api/v1" \
    material_model="openrouter/google/gemini-3.1-pro-preview" \
    material_api_key_env=GEMINI_API_KEY \
    synthesis_model="openrouter/google/gemini-3-flash-preview" \
    synthesis_api_key_env=GEMINI_API_KEY \
    linker_model="openrouter/google/gemini-3.1-pro-preview" \
    linker_api_key_env=GEMINI_API_KEY \
    plot_model="openrouter/anthropic/claude-sonnet-4.6" \
    output_dir="results/" \
    with_performance=true
Caution
The _api_key_env arguments must not contain the actual API key: they must be the name of an environment variable that holds the key. For example, material_api_key_env=GEMINI_API_KEY means that the material model set to Gemini will use the API key stored in the environment variable GEMINI_API_KEY. See API key environment variables for more details.

Batch Processing

# Basic — processes all papers in folder
lemat-synth batch papers/

# Quick test run (first 5 papers only)
lemat-synth batch papers/ max_papers=5

# Custom output folder and domain filtering
lemat-synth batch papers/ \
    output_dir=results/catalysis/ \
    domain=catalysis

# Re-process everything (skip_existing=false)
lemat-synth batch papers/ skip_existing=false

# Reduce parallelism to avoid rate limits
lemat-synth batch papers/ max_papers_parallel=2

# Use Mistral OCR for all PDFs
lemat-synth batch papers/ pdf_extractor=mistral

# Powerful models, catalysis domain, resume if interrupted
lemat-synth batch papers/ \
    synthesis_model=gemini/gemini-2.5-pro \
    material_model=anthropic/claude-opus-4-7 \
    domain=catalysis \
    skip_existing=true \
    max_papers_parallel=2 \
    output_dir="results/catalysis/"

# Different models through OpenRouter
lemat-synth batch papers/ \
    synthesis_model=openrouter/google/gemini-3-flash-preview \
    material_model=openrouter/google/gemini-3.1-pro-preview \
    judge_model=openrouter/anthropic/claude-sonnet-4.6 \
    api_base=https://openrouter.ai/api/v1

Configuration Details

All arguments in the Quick Reference table above can be overridden from the command line. Defaults are read from examples/config/cli.yaml.

Model strings

Model strings follow the LiteLLM convention: {provider}/{model-name}. Common providers and models:

gemini/gemini-3.5-flash-lite                      # Google Gemini
gemini/gemini-3.1-pro-preview
gemini/gemini-2.5-pro
anthropic/claude-sonnet-4-6                      # Anthropic Claude
anthropic/claude-opus-4-7
openai/gpt-4o                                    # OpenAI
openai/gpt-4o-mini
mistral/mistral-large                            # Mistral
openrouter/google/gemini-3-flash-preview          # OpenRouter (requires api_base + key)
openrouter/google/gemini-3.1-pro-preview
openrouter/anthropic/claude-sonnet-4.6
openrouter/deepseek/deepseek-v3.2
openrouter/qwen/qwen3.5-35b-a3b
openrouter/moonshotai/kimi-k2.5

When using OpenRouter models, always set api_base=https://openrouter.ai/api/v1.

API key environment variables

By default LiteLLM auto-detects API keys from standard environment variables:

  • gemini/*GEMINI_API_KEY
  • anthropic/*ANTHROPIC_API_KEY
  • openai/*OPENAI_API_KEY
  • etc.

Use the *_api_key_env arguments to override this — useful for OpenRouter key slots or when multiple keys exist for the same provider.

# Example: different OpenRouter keys for different models
lemat-synth batch papers/ \
    synthesis_model=openrouter/qwen/qwen3.5-35b-a3b \
    synthesis_api_key_env=OPENROUTER_QWEN_API_KEY \
    linker_model=openrouter/moonshotai/kimi-k2.5 \
    linker_api_key_env=OPENROUTER_KIMI_API_KEY \
    api_base=https://openrouter.ai/api/v1
Caution
The _api_key_env arguments must not contain the actual API key: they must be the name of an environment variable that holds the key. For example, material_api_key_env=OPENROUTER_QWEN_API_KEY means that the material model set to QWEN will use the API key stored in the environment variable OPENROUTER_QWEN_API_KEY.

Allowed Environment Variables

Add these to your .env file (automatically loaded at runtime):

VariableWhen requiredExample use
GEMINI_API_KEYUsing gemini/* modelsDefault synthesis/material models
ANTHROPIC_API_KEYUsing Claude models or with_performance=truesynthesis_model=anthropic/claude-sonnet-4-6
OPENAI_API_KEYUsing openai/gpt-* modelsplot_model=openai/gpt-4o
MISTRAL_API_KEYUsing Mistral models or pdf_extractor=mistralpdf_extractor=mistral for better OCR
OPENROUTER_QWEN_API_KEYUsing Qwen via OpenRoutersynthesis_model=openrouter/qwen/qwen3.5-35b-a3b
OPENROUTER_KIMI_API_KEYUsing Kimi via OpenRouterlinker_model=openrouter/moonshotai/kimi-k2.5
OPENROUTER_DEEPSEEK_API_KEYUsing DeepSeek via OpenRoutersynthesis_model=openrouter/deepseek/deepseek-v3.2

PDF and figure processing

ArgumentOptionsWhen to use
pdf_extractordocling (default)Local, no API key required
mistralBetter for scanned/low-quality PDFs (requires MISTRAL_API_KEY)
figure_segmenterdino (default)Fast, 28-class detection
florenceMore accurate, binary quantitative/qualitative classification
florence_repo_idHuggingFace repo IDLoRA adapter for Florence (only when figure_segmenter=florence)

Domain filtering (when with_performance=true)

DomainFigures keptUse case
genericAll figures (no filtering)Default for multi-domain papers
catalysisConversion/selectivity vs temperature curvesCatalysis materials
superconductorsResistivity ρ(T) and resistance R(T) plotsSuperconductor data
electrochemistryCurrent/capacitance vs voltage curvesBattery/electrochemistry materials

Batch processing options

ArgumentDefaultPurpose
max_papersnullStop after N papers (useful for test runs)
skip_existingtrueResume from last run; set to false to reprocess all
max_papers_parallel4Concurrent papers; lower if hitting rate limits

Customizing Prompts

Every prompt used during extraction can be customized. The full set of prompt keys is in examples/config/cli.yaml under the prompts: block:

PromptPurpose
prompts.synthesis_systemSystem message for synthesis extraction
prompts.synthesis_instructionsTask instructions for synthesis extraction
prompts.paper_text_descriptionDescription of the input paper text
prompts.material_name_descriptionDescription of the target material
prompts.synthesis_output_descriptionDescription of the output structure
prompts.material_instructionsTask instructions for material extraction
prompts.material_input_descriptionDescription of material input
prompts.material_output_descriptionDescription of material output

To override a prompt from the command line, wrap the whole key=value in double quotes so the shell preserves spaces. If the value itself contains a comma, add a second, inner layer of single quotes too — otherwise Hydra reads the comma as a list separator and refuses to guess which you meant:

# Focus on specific synthesis methods (no comma — plain quoting is enough)
lemat-synth extract paper.txt \
    "prompts.synthesis_instructions=Extract only sol-gel synthesis procedures. \
    Ignore characterization and testing sections."

# Customize material name handling — the value has a comma, so it needs the
# inner 'single quotes' too, or Hydra rejects it as an ambiguous list
lemat-synth extract paper.txt \
    "prompts.material_name_description='The specific compound formula to extract, \
    including all dopants and promoters.'"
Tip
Any override value with a comma needs this inner-quote treatment — "key='value, with a comma'" — not just prompt overrides. Without it, Hydra fails fast with ConfigCompositionException: Ambiguous value for argument '...'.

Managing Concurrency & Rate Limits

Two independent settings control parallel API calls:

SettingDefaultTo reduce rate limits
Papers processed in parallel (batch mode)4max_papers_parallel=2
LLM calls per paper (async operations)env-drivenLLM_SYNTHESIS_MAX_CONCURRENT_LLM_CALLS=4 in .env

If you hit rate-limit errors, reduce one or both values:

# Reduce papers processed concurrently
lemat-synth batch papers/ max_papers_parallel=2

# Reduce concurrent API calls per paper
# Add to .env: LLM_SYNTHESIS_MAX_CONCURRENT_LLM_CALLS=4

Output structure

Results are written to output_dir/<paper-name>/. Each folder contains one JSON file per extracted material, plus optional performance files.

See the Output Format page for a full description of the JSON schema.