Schemas and prompts¶
Extraction is driven by schema + prompt pairs under extraction.schemas.
LitCurate ships worked examples you can copy and adapt.
Shipped examples¶
| Role | Path |
|---|---|
| Example schema (JSON Schema) | schemas/example/record.json |
| Example schema (declarative YAML) | schemas/example/record.yaml |
| Example prompt | prompts/example/prompt.md |
| Bibliographic source schema (JSON) | schemas/example/source.json |
| Bibliographic source schema (YAML) | schemas/example/source.yaml |
The default dry-run config wires the example record schema:
extraction:
schemas:
- name: record
path: schemas/example/record.json
prompt: prompts/example/prompt.md
version: "2.1"
empty_list_field: eos_entries
Why EOS fields?
The example schema is a concrete equation-of-state extraction shape (eos_entries
with V0 / K0 / Kp). Treat it as a template for list-shaped scientific records,
not a package dependency on mineral physics. See the
full configuration example for
how schemas and prompts are connected.
Example prompt¶
Extract STATIC equation-of-state (EOS) parameters for lower-mantle-relevant phases
into the flat schema. Priority fields: **V0, K0, and Kp (K′)**. Values and units
must be copied exactly as reported.
Target phases (keep these; skip unrelated crustal/transition-zone-only phases unless
explicitly framed as lower-mantle):
- bridgmanite / (Mg,Fe)SiO3 or MgSiO3 perovskite (Pv)
- ferropericlase / magnesiowüstite / periclase / (Mg,Fe)O / MgO
- post-perovskite (PPv)
- CaSiO3 perovskite (CaPv)
- closely related deep-mantle SiO2 or hydrous phases only when discussed with EOS numbers
For each distinct phase + composition + sample/table row + EOS model, return one entry.
Promote when present:
- `V0` (+ `V0_unit`, `V0_name`, `V0_basis`, `V0_determination`)
- `K0` (+ `K0_unit`, `K0_name`, `K0_type`, `K0_determination`)
- `Kp` for K′ / K0′ / K_T′ (+ `Kp_name`, `Kp_determination`)
Determination enums:
- `V0_determination`: `measured` | `fitted` | `assumed` | `unknown`
- `K0_determination`: `fitted` | `measured` | `assumed` | `unknown`
- `Kp_determination`: `fitted` | `fixed` | `assumed` | `unknown`
Ambient / Table zero-pressure unit-cell volumes used with an EOS fit → fill `V0`
with `V0_determination: measured` even if the text only quotes fitted K0 and fixed
K′. Do not park those volumes only in `extra_info`.
Also set: `eos_model`, `method`, `T_ref`/`P_ref` (+ units), `origin`
(`this_study` | `cited` | `unknown`).
INCLUDE literature-tabulated V0/K0/K′ when reported numerically (`origin: cited`).
Other parameters (γ0, θ0, q, α, …) → `extra_info` only.
`evidence` is one string. Do not invent values or convert units.
If no relevant static EOS parameters appear, return `{ "eos_entries": [] }`.
Return JSON matching the schema: `{ "eos_entries": [ ... ] }`.
Example schema¶
Choose either JSON Schema or declarative YAML — same extraction shape, different
file formats. Do not configure both in the same extraction.schemas list.
- name: record
path: schemas/example/record.json
prompt: prompts/example/prompt.md
version: "2.1"
empty_list_field: eos_entries
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"eos_entries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"phase": {
"type": "string"
},
"composition": {
"type": "string"
},
"structure": {
"type": "string"
},
"sample": {
"type": "string"
},
"eos_model": {
"type": "string"
},
"method": {
"type": "string"
},
"V0": {
"type": [
"string",
"number"
]
},
"V0_unit": {
"type": "string"
},
"V0_name": {
"type": "string"
},
"V0_basis": {
"type": "string",
"enum": [
"unit_cell",
"molar",
"unknown"
]
},
"V0_determination": {
"type": "string",
"enum": [
"measured",
"fitted",
"assumed",
"unknown"
]
},
"K0": {
"type": [
"string",
"number"
]
},
"K0_unit": {
"type": "string"
},
"K0_name": {
"type": "string"
},
"K0_type": {
"type": "string",
"enum": [
"isothermal",
"adiabatic",
"unknown"
]
},
"K0_determination": {
"type": "string",
"enum": [
"fitted",
"measured",
"assumed",
"unknown"
]
},
"Kp": {
"type": [
"string",
"number"
]
},
"Kp_unit": {
"type": "string"
},
"Kp_name": {
"type": "string"
},
"Kp_determination": {
"type": "string",
"enum": [
"fitted",
"fixed",
"assumed",
"unknown"
]
},
"T_ref": {
"type": [
"string",
"number"
]
},
"T_ref_unit": {
"type": "string"
},
"P_ref": {
"type": [
"string",
"number"
]
},
"P_ref_unit": {
"type": "string"
},
"origin": {
"type": "string",
"enum": [
"this_study",
"cited",
"unknown"
]
},
"evidence": {
"type": "string"
},
"confidence": {
"type": "number",
"minimum": 0,
"maximum": 1,
"optional": true
},
"extra_info": {
"type": "object",
"additionalProperties": true,
"optional": true
}
},
"required": [
"phase",
"eos_model",
"evidence"
],
"additionalProperties": false
}
}
},
"required": [
"eos_entries"
],
"additionalProperties": false,
"title": "RecordList",
"version": "2.1",
"$id": "litcurate://schemas/example/record/2.1",
"description": "Example extraction schema (equation-of-state parameters: V0, K0, Kp). Copy and adapt for your domain. Values and units are verbatim from the paper.\n"
}
- name: record
format: declarative_yaml
path: schemas/example/record.yaml
prompt: prompts/example/prompt.md
version: "2.1"
empty_list_field: eos_entries
title: RecordList
version: "2.1"
$id: litcurate://schemas/example/record/2.1
description: >
Example extraction schema for static V0, K0, and Kp (K') equation-of-state
parameters. Values and units are verbatim from the paper.
fields:
eos_entries:
array:
required: [phase, eos_model, evidence]
fields:
phase: string
composition: string?
structure: string?
sample: string?
eos_model: string
method: string?
V0: string|number?
V0_unit: string?
V0_name: string?
V0_basis: enum(unit_cell, molar, unknown)?
V0_determination: enum(measured, fitted, assumed, unknown)?
K0: string|number?
K0_unit: string?
K0_name: string?
K0_type: enum(isothermal, adiabatic, unknown)?
K0_determination: enum(fitted, measured, assumed, unknown)?
Kp: string|number?
Kp_unit: string?
Kp_name: string?
Kp_determination: enum(fitted, fixed, assumed, unknown)?
T_ref: string|number?
T_ref_unit: string?
P_ref: string|number?
P_ref_unit: string?
origin: enum(this_study, cited, unknown)?
evidence: string
confidence:
type: number
minimum: 0
maximum: 1
optional: true
extra_info:
type: object
additionalProperties: true
optional: true
Warning
Do not configure both record schemas in the same extraction list. They represent the same schema in two file formats; choose either JSON or YAML.
Valid payload shape¶
Top-level object with an eos_entries array. Each entry requires at least
phase, eos_model, and evidence:
{
"eos_entries": [
{
"phase": "ExamplePhase",
"composition": "ABO3",
"eos_model": "3rd-order Birch-Murnaghan",
"method": "XRD",
"V0": "46.23",
"V0_unit": "Å^3",
"V0_determination": "measured",
"K0": "106 (2)",
"K0_unit": "GPa",
"K0_determination": "fitted",
"Kp": "4",
"Kp_determination": "fixed",
"origin": "this_study",
"evidence": "Table 2 reports K0 = 106 (2) GPa with K′ fixed at 4."
}
]
}
If the paper has nothing extractable, return { "eos_entries": [] }.
Optional source schema¶
Bibliographic source metadata is filled from OpenAlex / parquet, not extracted by
an LLM. Set fill_from: papers_meta; do not provide a prompt:
extraction:
schemas:
- name: record
path: schemas/example/record.json
prompt: prompts/example/prompt.md
empty_list_field: eos_entries
- name: source
path: schemas/example/source.json
fill_from: papers_meta
skip_when_prior_empty: record
With fill_from set:
- LitCurate reads bibliographic fields from the best available paper metadata
(
papers_filtered.parquet, thenpapers_ranked.parquet). - It does not call an LLM and does not read a prompt.
- It validates the generated payload against the configured source schema.
- It writes the normal extraction envelope as
<paper_id>/source.json.
The schema is therefore required even though a prompt is not.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Source",
"type": "object",
"required": ["doi", "title", "year", "source_type"],
"properties": {
"doi": { "type": "string" },
"title": { "type": "string" },
"authors": { "type": "array", "items": { "type": "string" } },
"journal": { "type": "string" },
"year": { "type": "integer" },
"source_type": {
"type": "string",
"enum": ["journal", "database", "book", "thesis", "other"]
},
"evidence_text": { "type": "string" },
"confidence": { "type": "number", "minimum": 0, "maximum": 1 }
},
"additionalProperties": false
}
$schema: https://json-schema.org/draft/2020-12/schema
title: Source
type: object
required:
- doi
- title
- year
- source_type
properties:
doi:
type: string
title:
type: string
authors:
type: array
items:
type: string
journal:
type: string
year:
type: integer
source_type:
type: string
enum:
- journal
- database
- book
- thesis
- other
evidence_text:
type: string
confidence:
type: number
minimum: 0
maximum: 1
additionalProperties: false
Warning
Do not configure both source schemas in the same extraction list. They represent the same schema in two file formats; choose either JSON or YAML.
There is intentionally no source prompt because this workflow does not use an LLM for source metadata.
{
"doi": "10.1000/example",
"title": "Example paper",
"authors": ["A. Author", "B. Author"],
"journal": "Example Journal",
"year": 2026,
"source_type": "journal",
"evidence_text": "Bibliographic metadata supplied by the paper index.",
"confidence": 1.0
}
Schema entry fields¶
extraction:
schemas:
- name: record
path: schemas/example/record.json
prompt: prompts/example/prompt.md
version: "2.1"
empty_list_field: eos_entries
| Field | Meaning |
|---|---|
name |
Schema id; output filename stem |
path |
JSON Schema, declarative YAML, or related format |
prompt |
Instructions for the LLM (required unless fill_from is set) |
format |
json_schema (default), yaml_schema, declarative_yaml, or pydantic |
version |
Optional schema version recorded in envelopes |
fill_from |
e.g. papers_meta — fill from paper metadata instead of calling an LLM |
skip_when_prior_empty |
Skip if a prior schema’s empty_list_field is empty |
empty_list_field |
List field used for empty checks / export counts |
Declarative YAML format¶
format: declarative_yaml is a shorter authoring style (string, string?,
enum(...), nested fields / array). The example record schema above shows the
full file; configure it with:
- name: record
format: declarative_yaml
path: schemas/example/record.yaml
prompt: prompts/example/prompt.md
empty_list_field: eos_entries
Output location¶
Each file is an envelope (metadata + payload). See Export format.
Adapting for your domain¶
- Copy
schemas/example/record.json→schemas/my_domain/... - Copy
prompts/example/prompt.md→prompts/my_domain/... - Rename fields / instructions to match what you extract
- Point
extraction.schemasat the new paths - Keep
empty_list_fieldaligned with your top-level list property
See Custom domains.