Metadata Extensions
Advanced extraction features including citations and confidence scores for enhanced data extraction workflows.
LlamaExtract offers several advanced features that provide additional metadata and insights alongside your extracted data. These extensions are available under Advanced Settings in the UI and return schema-level metadata in the extract_metadata field of the response.
Citations
Section titled “Citations”Citations provide the source information for every extracted field, allowing you to trace back exactly where each piece of data came from in the original document.
How it works: For every leaf-level field in your schema, citations return:
- The page number where the information was found
- The verbatim text that was used to extract the field value
- Bounding box coordinates (
x,y,w,h) indicating the exact location of the cited text on the page - Page dimensions (
width,height) to help you render the bounding boxes accurately
The citation information appears both in the API response (extract_metadata.field_metadata) and is visualized in the LlamaCloud UI.
Example API response structure (scalar fields):
"extract_metadata": { "field_metadata": { "phone": { "citation": [ { "page": 1, "matching_text": "(555) 123-4567", "bounding_boxes": [ { "x": 177, "y": 82, "w": 318, "h": 43 } ], "page_dimensions": { "width": 612, "height": 792 } } ] } }}Array fields: Citations attach at the leaf sub-field level, not the array item level. The field_metadata tree mirrors the structure of your extracted data, with each leaf value replaced by its citation metadata.
For a schema like key_facts: list[KeyFact] where KeyFact has a fact: str field, the metadata structure is:
"extract_metadata": { "field_metadata": { "key_facts": [ { "fact": { "citation": [ { "page": 3, "matching_text": "Revenue grew 114% year-over-year", "bounding_boxes": [{ "x": 50, "y": 200, "w": 400, "h": 20 }], "page_dimensions": { "width": 612, "height": 792 } } ] } }, { "fact": { "citation": [ { "page": 7, "matching_text": "Operating expenses increased to $3.2B", "bounding_boxes": [{ "x": 50, "y": 310, "w": 380, "h": 20 }], "page_dimensions": { "width": 612, "height": 792 } } ] } } ] }}Note: the citation path is field_metadata.key_facts[i].fact.citation, not field_metadata.key_facts[i].citation. Each array element in the metadata corresponds positionally to the same element in the extracted data.
Usage: Set cite_sources: true in the configuration to enable this feature.
Use cases:
- Compliance and audit requirements
- Fact-checking and verification workflows
- Understanding extraction quality and accuracy
- Building custom highlighting/annotation features using bounding box coordinates
Confidence Scores
Section titled “Confidence Scores”Confidence scores provide quantitative measures of how confident the system is in the extracted values, helping you identify potentially unreliable extractions.
How it works: This feature adds three confidence-related fields to the extraction metadata:
parsing_confidence: Confidence score indicating how well the relevant context was parsed from the source document.extraction_confidence: Confidence score indicating the relevance of the extraction based on the JSON schema field.confidence: Combined confidence score that incorporates both parsing and extraction confidence.
Usage: Set confidence_scores: true in the configuration to enable confidence scores.
Reading the scores. confidence is the value to threshold on; the other two explain where a low score came from.
- Calibrated on Cost Effective, Agentic, and Agentic Plus. On those tiers a score approximates a real probability of correctness, so you can set a threshold directly rather than only ranking fields against each other. At a 0.8 threshold roughly 75% of extraction errors fall below the line.
- Agentic Max and Turbo return scores from an earlier model. They are still useful for ranking fields, but the calibration above does not apply to them.
- Validate the threshold on your own documents. The right cutoff depends on your document mix and on how costly a missed error is. Start at 0.8, score a sample you have ground truth for, and move it until review volume and escape rate sit where you want them.
- Longer text fields score lower. Summaries and descriptions typically score below short factual fields, because there are many valid ways to word the same answer. That does not by itself indicate lower accuracy, so consider a separate threshold for free-text fields.
Limitations: enabling confidence scores adds processing time to a job.
Use cases:
- Routing low-confidence fields to human review while the rest pass straight through
- Ranking extraction reliability across fields within a document
- Flagging documents that need a second look before they enter a downstream system
Reasoning Metadata
Section titled “Reasoning Metadata”Reasoning metadata is available for Extract versions through 2026-03-31. Newer versions do not return per-field reasoning strings.
If your application depends on reasoning strings in extract_metadata.field_metadata, pin configuration.version to 2026-03-31. For newer versions, use citations and confidence scores when you need provenance or review signals.
Performance Considerations
Section titled “Performance Considerations”⚠️ Important: Citations and confidence scores will significantly slow down extraction processing time. Enable these features only when the additional metadata is essential for your use case.
Configuration and Usage
Section titled “Configuration and Usage”For complete examples of how to configure and use these extensions with both the Python SDK and REST API, see the Configuring Extract page.
The configuration section includes:
- Complete Python SDK examples with extension settings
- REST API curl command examples
- Configuration reference table with all available options
Quick reference for extensions:
import timefrom llama_cloud import LlamaCloud
client = LlamaCloud(api_key="your_api_key")
file_obj = client.files.create(file="path/to/your/document.pdf", purpose="extract")file_id = file_obj.id
job = client.extract.create( file_input=file_id, configuration={ "data_schema": {"type": "object", "properties": {}}, # your extraction schema "tier": "agentic", "cite_sources": True, "confidence_scores": True, },)
# Poll for completionwhile job.status not in ("COMPLETED", "FAILED", "CANCELLED"): time.sleep(2) job = client.extract.get(job.id)import fs from 'fs';import LlamaCloud from '@llamaindex/llama-cloud';
const client = new LlamaCloud({ apiKey: 'your_api_key',});
const fileObj = await client.files.create({ file: fs.createReadStream('path/to/your/document.pdf'), purpose: 'extract',});
let job = await client.extract.create({ file_input: fileObj.id, configuration: { data_schema: { /* your extraction schema */ }, tier: 'agentic', cite_sources: true, confidence_scores: true, },});
// Poll for completionwhile (!['COMPLETED', 'FAILED', 'CANCELLED'].includes(job.status)) { await new Promise((r) => setTimeout(r, 2000)); job = await client.extract.get(job.id);}package main
import ( "context" "log" "os" "time"
llamacloud "github.com/run-llama/llama-parse-go")
func main() { ctx := context.Background() client := llamacloud.NewClient()
// Your extraction schema dataSchema := map[string]*llamacloud.ExtractConfigurationDataSchemaUnionParam{ "type": {OfString: llamacloud.String("object")}, "properties": {OfAnyMap: map[string]any{}}, }
// Upload a file to extract from f, err := os.Open("path/to/your/document.pdf") if err != nil { log.Fatal(err) } defer f.Close()
fileObj, err := client.Files.New(ctx, llamacloud.FileNewParams{ File: f, Purpose: "extract", }) if err != nil { log.Fatal(err) }
job, err := client.Extract.New(ctx, llamacloud.ExtractNewParams{ ExtractV2JobCreate: llamacloud.ExtractV2JobCreateParam{ FileInput: fileObj.ID, Configuration: llamacloud.ExtractConfigurationParam{ DataSchema: dataSchema, Tier: llamacloud.ExtractConfigurationTierAgentic, CiteSources: llamacloud.Bool(true), ConfidenceScores: llamacloud.Bool(true), }, }, }) if err != nil { log.Fatal(err) }
// Poll for completion for job.Status != "COMPLETED" && job.Status != "FAILED" && job.Status != "CANCELLED" { time.Sleep(2 * time.Second) job, err = client.Extract.Get(ctx, job.ID, llamacloud.ExtractGetParams{}) if err != nil { log.Fatal(err) } }}import ai.llamaindex.llamacloud.client.LlamaCloudClient;import ai.llamaindex.llamacloud.client.okhttp.LlamaCloudOkHttpClient;import ai.llamaindex.llamacloud.core.JsonValue;import ai.llamaindex.llamacloud.models.extract.ExtractConfiguration;import ai.llamaindex.llamacloud.models.extract.ExtractCreateParams;import ai.llamaindex.llamacloud.models.extract.ExtractGetParams;import ai.llamaindex.llamacloud.models.extract.ExtractV2Job;import ai.llamaindex.llamacloud.models.extract.ExtractV2JobCreate;import ai.llamaindex.llamacloud.models.files.FileCreateParams;import ai.llamaindex.llamacloud.models.files.FileCreateResponse;import java.nio.file.Paths;import java.util.HashMap;
LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();
// Your extraction schemaExtractConfiguration.DataSchema dataSchema = ExtractConfiguration.DataSchema.builder() .putAdditionalProperty("type", JsonValue.from("object")) .putAdditionalProperty("properties", JsonValue.from(new HashMap<String, Object>())) .build();
FileCreateResponse fileObj = client.files().create( FileCreateParams.builder() .file(Paths.get("path/to/your/document.pdf")) .purpose("extract") .build());
ExtractV2Job job = client.extract().create( ExtractCreateParams.builder() .extractV2JobCreate( ExtractV2JobCreate.builder() .fileInput(fileObj.id()) .configuration( ExtractConfiguration.builder() .dataSchema(dataSchema) .tier(ExtractConfiguration.Tier.AGENTIC) .citeSources(true) .confidenceScores(true) .build()) .build()) .build());
// Poll for completionwhile (!job.status().equals("COMPLETED") && !job.status().equals("FAILED") && !job.status().equals("CANCELLED")) { Thread.sleep(2000); job = client.extract().get(ExtractGetParams.builder().jobId(job.id()).build());}# Your extraction schemaDATA_SCHEMA='{"type": "object", "properties": {}}'
FILE_ID=$(llp files create --file path/to/your/document.pdf --purpose extract | jq -r '.id')
JOB_ID=$(llp extract create \ --file-input "$FILE_ID" \ --configuration "{\"data_schema\": $DATA_SCHEMA, \"tier\": \"agentic\", \"cite_sources\": true, \"confidence_scores\": true}" \ | jq -r '.id')
# Poll for completionwhile true; do STATUS=$(llp extract get --job-id "$JOB_ID" | jq -r '.status') case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac sleep 2done