Performance Tips
Best practices and optimization strategies for successful data extraction workflows
Overall Performance Best Practices
Section titled “Overall Performance Best Practices”For maximum extraction success:
-
Start with the agentic tier for debugging: When troubleshooting extraction issues, use the
agentictier which uses the most capable models. If extraction succeeds withagentic, you can trycost_effectiveto see if quality holds for your use case. If extraction fails even withagentic, the issue is likely in your schema design (e.g., ambiguous field descriptions).import timefrom llama_cloud import LlamaCloudclient = LlamaCloud(api_key="your_api_key")schema = {"type": "object","properties": {"company_name": {"type": "string", "description": "Name of the company"},"revenue": {"type": "number", "description": "Annual revenue in USD"},},}file_obj = client.files.create(file="path/to/your/document.pdf", purpose="extract")# Start debugging with agentic tierjob = client.extract.create(file_input=file_obj.id,configuration={"data_schema": schema,"extraction_target": "per_doc","tier": "agentic",},)# Poll for completionwhile job.status not in ("COMPLETED", "FAILED", "CANCELLED"):time.sleep(2)job = client.extract.get(job.id)print(job.extract_result)import fs from 'fs';import LlamaCloud from '@llamaindex/llama-cloud';const client = new LlamaCloud({ apiKey: 'your_api_key' });const schema = {type: 'object',properties: {company_name: { type: 'string', description: 'Name of the company' },revenue: { type: 'number', description: 'Annual revenue in USD' },},};const fileObj = await client.files.create({file: fs.createReadStream('path/to/your/document.pdf'),purpose: 'extract',});// Start debugging with agentic tierlet job = await client.extract.create({file_input: fileObj.id,configuration: {data_schema: schema,extraction_target: 'per_doc',tier: 'agentic',},});// Poll for completionwhile (!['COMPLETED', 'FAILED', 'CANCELLED'].includes(job.status)) {await new Promise((r) => setTimeout(r, 2000));job = await client.extract.get(job.id);}console.log(job.extract_result);package mainimport ("context""fmt""log""os""time"llamacloud "github.com/run-llama/llama-parse-go")func main() {ctx := context.Background()client := llamacloud.NewClient()schema := map[string]*llamacloud.ExtractConfigurationDataSchemaUnionParam{"type": {OfString: llamacloud.String("object")},"properties": {OfAnyMap: map[string]any{"company_name": map[string]any{"type": "string", "description": "Name of the company"},"revenue": map[string]any{"type": "number", "description": "Annual revenue in USD"},}},}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)}// Start debugging with agentic tierjob, err := client.Extract.New(ctx, llamacloud.ExtractNewParams{ExtractV2JobCreate: llamacloud.ExtractV2JobCreateParam{FileInput: fileObj.ID,Configuration: llamacloud.ExtractConfigurationParam{DataSchema: schema,ExtractionTarget: llamacloud.ExtractConfigurationExtractionTargetPerDoc,Tier: llamacloud.ExtractConfigurationTierAgentic,},},})if err != nil {log.Fatal(err)}// Poll for completionfor 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)}}fmt.Println(job.ExtractResult.RawJSON())}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;import java.util.Map;public class ExtractAgenticDebug {public static void main(String[] args) throws Exception {LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();Map<String, Object> companyNameField = new HashMap<>();companyNameField.put("type", "string");companyNameField.put("description", "Name of the company");Map<String, Object> revenueField = new HashMap<>();revenueField.put("type", "number");revenueField.put("description", "Annual revenue in USD");Map<String, Object> properties = new HashMap<>();properties.put("company_name", companyNameField);properties.put("revenue", revenueField);ExtractConfiguration.DataSchema schema = ExtractConfiguration.DataSchema.builder().putAdditionalProperty("type", JsonValue.from("object")).putAdditionalProperty("properties", JsonValue.from(properties)).build();FileCreateResponse fileObj = client.files().create(FileCreateParams.builder().file(Paths.get("path/to/your/document.pdf")).purpose("extract").build());// Start debugging with agentic tierExtractV2Job job = client.extract().create(ExtractCreateParams.builder().extractV2JobCreate(ExtractV2JobCreate.builder().fileInput(fileObj.id()).configuration(ExtractConfiguration.builder().dataSchema(schema).extractionTarget(ExtractConfiguration.ExtractionTarget.PER_DOC).tier(ExtractConfiguration.Tier.AGENTIC).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());}System.out.println(job.extractResult());}}Terminal window DATA_SCHEMA='{"type": "object","properties": {"company_name": {"type": "string", "description": "Name of the company"},"revenue": {"type": "number", "description": "Annual revenue in USD"}}}'FILE_ID=$(llp files create --file path/to/your/document.pdf --purpose extract | jq -r '.id')# Start debugging with agentic tierJOB_ID=$(llp extract create \--file-input "$FILE_ID" \--configuration "{\"data_schema\": $DATA_SCHEMA, \"extraction_target\": \"per_doc\", \"tier\": \"agentic\"}" \| jq -r '.id')# Poll for completionwhile true; doJOB=$(llp extract get --job-id "$JOB_ID")STATUS=$(echo "$JOB" | jq -r '.status')case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esacsleep 2doneecho "$JOB" | jq '.extract_result' -
Start small and iterate: Begin with a subset of your data or schema to validate your extraction approach and iterate on your schema description (e.g. adding examples, formatting instructions etc.) to get better accuracy before scaling.
-
Design clear, focused schemas: Prefer precise short descriptions over verbose fields that try to do too much. See the section on schema design and avoiding complex transformations.
-
Leverage document structure: Use page ranges, extraction targets, sections, and chunking strategies to optimize processing. See options.
-
Combine tools strategically: Extract excels at extracting information from documents. Focus on leveraging this strength while using complementary tools for computational tasks and validation (e.g., heavy calculations are better handled in a post-processing step).
Extracting from Tables and Ordered Lists
Section titled “Extracting from Tables and Ordered Lists”The situation: When working with documents containing tables, spreadsheets (CSV/Excel), or ordered lists of entities, you want to ensure comprehensive and accurate extraction of each row or item.
Use per_table_row extraction target: If you are only interested in extracting or transforming data from a table or ordered list of entities, use the per_table_row extraction target. This processes each row individually for comprehensive coverage and accurate results.
# Optimal: Use per_table_row for tabular data extractionextraction_config = { "extraction_target": "per_table_row",}// Optimal: Use per_table_row for tabular data extractionconst extractionConfig = { extraction_target: 'per_table_row',};// Optimal: Use per_table_row for tabular data extractionextractionConfig := llamacloud.ExtractConfigurationParam{ ExtractionTarget: llamacloud.ExtractConfigurationExtractionTargetPerTableRow,}// Optimal: Use per_table_row for tabular data extractionExtractConfiguration.Builder extractionConfig = ExtractConfiguration.builder() .extractionTarget(ExtractConfiguration.ExtractionTarget.PER_TABLE_ROW);# Optimal: Use per_table_row for tabular data extractionEXTRACTION_CONFIG='{"extraction_target": "per_table_row"}'When your schema has additional elements beyond the table: If your schema includes fields that need to be extracted from outside the table (e.g., document metadata, headers, or summary information), you can run separate extractions for tabular data (using per_table_row) and non-tabular elements.
import timefrom llama_cloud import LlamaCloud
client = LlamaCloud(api_key="your_api_key")
metadata_schema = { "type": "object", "properties": { "report_title": {"type": "string", "description": "Title of the report"}, },}
table_row_schema = { "type": "object", "properties": { "line_item": {"type": "string", "description": "Name of the line item"}, "amount": {"type": "number", "description": "Amount in USD"}, },}
file_obj = client.files.create(file="path/to/your/document.pdf", purpose="extract")file_id = file_obj.id
# First extraction: Get document-level metadatametadata_job = client.extract.create( file_input=file_id, configuration={ "data_schema": metadata_schema, "extraction_target": "per_doc", "tier": "agentic", },)
# Second extraction: Get table row datatable_job = client.extract.create( file_input=file_id, configuration={ "data_schema": table_row_schema, "extraction_target": "per_table_row", "target_pages": "5-10", "tier": "agentic", },)
# Wait for both jobs and print the resultsfor job in (metadata_job, table_job): while job.status not in ("COMPLETED", "FAILED", "CANCELLED"): time.sleep(2) job = client.extract.get(job.id) print(job.extract_result)import fs from 'fs';import LlamaCloud from '@llamaindex/llama-cloud';
const client = new LlamaCloud({ apiKey: 'your_api_key' });
const metadataSchema = { type: 'object', properties: { report_title: { type: 'string', description: 'Title of the report' }, },};
const tableRowSchema = { type: 'object', properties: { line_item: { type: 'string', description: 'Name of the line item' }, amount: { type: 'number', description: 'Amount in USD' }, },};
const fileObj = await client.files.create({ file: fs.createReadStream('path/to/your/document.pdf'), purpose: 'extract',});const fileId = fileObj.id;
// First extraction: Get document-level metadataconst metadataJob = await client.extract.create({ file_input: fileId, configuration: { data_schema: metadataSchema, extraction_target: 'per_doc', tier: 'agentic', },});
// Second extraction: Get table row dataconst tableJob = await client.extract.create({ file_input: fileId, configuration: { data_schema: tableRowSchema, extraction_target: 'per_table_row', target_pages: '5-10', tier: 'agentic', },});
// Wait for both jobs and print the resultsfor (let job of [metadataJob, tableJob]) { while (!['COMPLETED', 'FAILED', 'CANCELLED'].includes(job.status)) { await new Promise((r) => setTimeout(r, 2000)); job = await client.extract.get(job.id); } console.log(job.extract_result);}package main
import ( "context" "fmt" "log" "os" "time"
llamacloud "github.com/run-llama/llama-parse-go")
func main() { ctx := context.Background() client := llamacloud.NewClient()
metadataSchema := map[string]*llamacloud.ExtractConfigurationDataSchemaUnionParam{ "type": {OfString: llamacloud.String("object")}, "properties": {OfAnyMap: map[string]any{ "report_title": map[string]any{"type": "string", "description": "Title of the report"}, }}, }
tableRowSchema := map[string]*llamacloud.ExtractConfigurationDataSchemaUnionParam{ "type": {OfString: llamacloud.String("object")}, "properties": {OfAnyMap: map[string]any{ "line_item": map[string]any{"type": "string", "description": "Name of the line item"}, "amount": map[string]any{"type": "number", "description": "Amount in USD"}, }}, }
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) } fileID := fileObj.ID
// First extraction: Get document-level metadata metadataJob, err := client.Extract.New(ctx, llamacloud.ExtractNewParams{ ExtractV2JobCreate: llamacloud.ExtractV2JobCreateParam{ FileInput: fileID, Configuration: llamacloud.ExtractConfigurationParam{ DataSchema: metadataSchema, ExtractionTarget: llamacloud.ExtractConfigurationExtractionTargetPerDoc, Tier: llamacloud.ExtractConfigurationTierAgentic, }, }, }) if err != nil { log.Fatal(err) }
// Second extraction: Get table row data tableJob, err := client.Extract.New(ctx, llamacloud.ExtractNewParams{ ExtractV2JobCreate: llamacloud.ExtractV2JobCreateParam{ FileInput: fileID, Configuration: llamacloud.ExtractConfigurationParam{ DataSchema: tableRowSchema, ExtractionTarget: llamacloud.ExtractConfigurationExtractionTargetPerTableRow, TargetPages: llamacloud.String("5-10"), Tier: llamacloud.ExtractConfigurationTierAgentic, }, }, }) if err != nil { log.Fatal(err) }
// Wait for both jobs and print the results for _, job := range []*llamacloud.ExtractV2Job{metadataJob, tableJob} { 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) } } fmt.Println(job.ExtractResult.RawJSON()) }}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.Arrays;import java.util.HashMap;import java.util.Map;
public class ExtractTableAndMetadata { public static void main(String[] args) throws Exception { LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();
Map<String, Object> reportTitleField = new HashMap<>(); reportTitleField.put("type", "string"); reportTitleField.put("description", "Title of the report");
Map<String, Object> metadataProperties = new HashMap<>(); metadataProperties.put("report_title", reportTitleField);
ExtractConfiguration.DataSchema metadataSchema = ExtractConfiguration.DataSchema.builder() .putAdditionalProperty("type", JsonValue.from("object")) .putAdditionalProperty("properties", JsonValue.from(metadataProperties)) .build();
Map<String, Object> lineItemField = new HashMap<>(); lineItemField.put("type", "string"); lineItemField.put("description", "Name of the line item");
Map<String, Object> amountField = new HashMap<>(); amountField.put("type", "number"); amountField.put("description", "Amount in USD");
Map<String, Object> tableRowProperties = new HashMap<>(); tableRowProperties.put("line_item", lineItemField); tableRowProperties.put("amount", amountField);
ExtractConfiguration.DataSchema tableRowSchema = ExtractConfiguration.DataSchema.builder() .putAdditionalProperty("type", JsonValue.from("object")) .putAdditionalProperty("properties", JsonValue.from(tableRowProperties)) .build();
FileCreateResponse fileObj = client.files().create( FileCreateParams.builder() .file(Paths.get("path/to/your/document.pdf")) .purpose("extract") .build()); String fileId = fileObj.id();
// First extraction: Get document-level metadata ExtractV2Job metadataJob = client.extract().create( ExtractCreateParams.builder() .extractV2JobCreate(ExtractV2JobCreate.builder() .fileInput(fileId) .configuration(ExtractConfiguration.builder() .dataSchema(metadataSchema) .extractionTarget(ExtractConfiguration.ExtractionTarget.PER_DOC) .tier(ExtractConfiguration.Tier.AGENTIC) .build()) .build()) .build());
// Second extraction: Get table row data ExtractV2Job tableJob = client.extract().create( ExtractCreateParams.builder() .extractV2JobCreate(ExtractV2JobCreate.builder() .fileInput(fileId) .configuration(ExtractConfiguration.builder() .dataSchema(tableRowSchema) .extractionTarget(ExtractConfiguration.ExtractionTarget.PER_TABLE_ROW) .targetPages("5-10") .tier(ExtractConfiguration.Tier.AGENTIC) .build()) .build()) .build());
// Wait for both jobs and print the results for (ExtractV2Job job : Arrays.asList(metadataJob, tableJob)) { while (!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()); } System.out.println(job.extractResult()); } }}METADATA_SCHEMA='{ "type": "object", "properties": { "report_title": {"type": "string", "description": "Title of the report"} }}'
TABLE_ROW_SCHEMA='{ "type": "object", "properties": { "line_item": {"type": "string", "description": "Name of the line item"}, "amount": {"type": "number", "description": "Amount in USD"} }}'
FILE_ID=$(llp files create --file path/to/your/document.pdf --purpose extract | jq -r '.id')
# First extraction: Get document-level metadataMETADATA_JOB_ID=$(llp extract create \ --file-input "$FILE_ID" \ --configuration "{\"data_schema\": $METADATA_SCHEMA, \"extraction_target\": \"per_doc\", \"tier\": \"agentic\"}" \ | jq -r '.id')
# Second extraction: Get table row dataTABLE_JOB_ID=$(llp extract create \ --file-input "$FILE_ID" \ --configuration "{\"data_schema\": $TABLE_ROW_SCHEMA, \"extraction_target\": \"per_table_row\", \"target_pages\": \"5-10\", \"tier\": \"agentic\"}" \ | jq -r '.id')
# Wait for both jobs and print the resultsfor JOB_ID in "$METADATA_JOB_ID" "$TABLE_JOB_ID"; do while true; do JOB=$(llp extract get --job-id "$JOB_ID") STATUS=$(echo "$JOB" | jq -r '.status') case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac sleep 2 done echo "$JOB" | jq '.extract_result'done- Use
agentictier for mixed content: If you need to extract both tabular and non-tabular elements in a single pass, theagentictier uses more capable models that handle complex layouts better. Note that this approach uses more credits (15/page vs 5/page).
Avoid Complex Field Transformations
Section titled “Avoid Complex Field Transformations”Don’t embed business logic in field descriptions. Extract clean data first, then compute in your application code.
# ❌ Problematic: Too much logic in the field descriptionproblematic_field = { "calculated_score": { "type": "number", "description": "If revenue > 1M, multiply by 0.8, else if revenue < 500K multiply by 1.2, otherwise use the base score from table 3, but only if the date is after 2020 and the category is not 'exempt'" }}
# ✅ Better: Simple extraction, handle logic separatelybetter_schema = { "revenue": {"type": "number", "description": "Total revenue in dollars"}, "base_score": {"type": "number", "description": "Base score value from the scoring table"}, "date": {"type": "string", "description": "Date in YYYY-MM-DD format"}, "category": {"type": "string", "description": "Business category"}}
# Then handle calculations in your application code:def calculate_final_score(extracted_data): revenue = extracted_data["revenue"] if revenue > 1000000: return extracted_data["base_score"] * 0.8 elif revenue < 500000: return extracted_data["base_score"] * 1.2 return extracted_data["base_score"]