Skip to content
LlamaParse 文档版本 跟随上游 源快照 619b8f3c 更新于 2026-10-16

LlamaExtract 提供若干高级能力,在抽取数据之外返回额外的元数据与洞见。它们把 schema 级的元数据放在响应的 extract_metadata 字段里返回。API 默认把 cite_sources 与 confidence_scores 设为 false。在 Extract playground 里,Cite sources 与 Confidence scores 是 Build 标签下 General 组的两个开关、默认开启,而 Advanced citations 位于 Advanced settings → Output。推理元数据没有对应的 playground 开关。

引用

引用会为每个抽取字段给出来源信息,让你能精确回溯每条数据出自原文的哪里。

工作机制:对 schema 里每一个叶子层字段,引用会返回:

  • 该信息出现在第几页
  • 用于得出该字段取值的原文逐字文本
  • 指出被引文字在页面上确切位置的边界框坐标(x、y、w、h)
  • 页面尺寸(width、height),帮你把边界框准确地绘制出来

引用出现在 API 响应的 extract_metadata.field_metadata.document_metadata 下,也会出现在 LlamaCloud 界面里。字段参考见 Extract 响应形态。

API 响应结构示例(标量字段):

"extract_metadata": {
  "field_metadata": {
    "document_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
            }
          }
        ]
      }
    }
  }
}

数组字段: 引用挂在叶子子字段这一层,而不是数组元素那一层。field_metadata 这棵树与你抽出的数据结构一一镜像,只是每个叶子取值被替换成了它的引用元数据。

对于像 key_facts: list[KeyFact] 这样、KeyFact 含一个 fact: str 字段的 schema,元数据结构是:

"extract_metadata": {
  "field_metadata": {
    "document_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 }
              }
            ]
          }
        }
      ]
    }
  }
}

注意:引用的路径是 field_metadata.document_metadata.key_facts[i].fact.citation,不是 field_metadata.document_metadata.key_facts[i].citation。元数据里的每个数组元素都按位置对应到抽出数据里的同一元素。

用法:在配置里设 cite_sources: true 以开启该能力。

适用场景:

  • 合规与审计要求
  • 事实核查与验证流程
  • 理解抽取的质量与准确度
  • 用边界框坐标自建高亮/批注功能

高级引用

高级引用能把引用的边界框放得更准。对 Agentic 2.5 及更高版本以及 Agentic Plus,它默认开启。设 advanced_citations: false 可以换取更快的抽取与略粗的边界框 —— 你仍然会拿到引用。

{
  "cite_sources": true,
  "advanced_citations": false
}

置信度得分

confidence 是某个字段取值的总体得分,取值 0 到 1,分数越高表示该取值越可信。每个字段各有自己的得分,因此你可以只把没把握的取值送人工复核,其余照收。高分仍然是一个估计,不是正确性的保证。

开启与读取得分

在配置里设 confidence_scores: true,得分就会进入 extract_metadata.field_metadata。取回任务时请请求 expand=extract_metadata 才能把这层元数据带进响应。见 Extract 响应形态。

元数据遵循与你 schema 相同的嵌套结构。例如一份含 total 字段与 items 数组的文档可能返回:

{
  "extract_metadata": {
    "field_metadata": {
      "document_metadata": {
        "total": {"confidence": 0.97},
        "items": [
          {"amount": {"confidence": 0.62}}
        ]
      }
    }
  }
}

第一个 item 的 amount 的得分位于 extract_metadata.field_metadata.document_metadata.items[0].amount.confidence。若复核阈值定为 0.8,你的应用就会把这个 amount 送复核、而接受那个 total。阈值由你的应用决定。

选择复核阈值

请用一批你已知正确取值的自有文档来选复核阈值。先定一个候选阈值,然后同时检查被送复核的字段与被自动接受的字段:数一数该阈值拦下了多少错误、放过了多少错误取值、又制造了多少复核量。要复核更多字段就调高阈值,要减少复核量就调低。

对取值错了代价很高的字段,请使用更严的阈值。较长的自由文本字段(例如摘要与描述)得分往往低于短小的事实型字段;应当分别评估,而不是假定一个阈值适用于所有字段类型。

怎么理解这个得分

校准度描述的是得分与观测到的正确率有多吻合。校准度随档位与版本而变,因此 0.8 分并不总等于 80% 的正确概率。请在你实际使用的档位与版本上验证你的 cutoff,并在更换版本或开始处理另一类文档时重新验证。

推理元数据

推理元数据在 2026-03-31 及更早的 Extract 版本上可用。更新的版本不再返回逐字段的推理字符串。

如果你的应用依赖 extract_metadata.field_metadata 里的推理字符串,请把 configuration.version 固定在 2026-03-31。用更新版本时,需要出处或复核信号请改用引用与置信度得分。

性能考量

⚠️ 重要:引用与置信度得分会显著拖慢抽取的处理时长。只有当额外的元数据对你的场景确有必要时才开启它们。

配置与用法

关于如何用 Python SDK 与 REST API 配置并使用这些扩展的完整示例,见 配置 Extract 页。

那一节包含:

  • 带扩展设置的完整 Python SDK 示例
  • REST API 的 curl 命令示例
  • 涵盖所有可用选项的配置参考表

扩展能力速查:

先下载一份样例简历存为 document.pdf:

终端窗口

curl -fL -o document.pdf https://raw.githubusercontent.com/run-llama/llama_cloud_services/main/examples/extract/data/resumes/software_architect.pdf
  • Python
  • TypeScript
  • Go
  • Java
  • CLI
import time
from llama_cloud import LlamaCloud

client = LlamaCloud()  # reads LLAMA_CLOUD_API_KEY from the environment

file_obj = client.files.create(file="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 completion
while 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(); // reads LLAMA_CLOUD_API_KEY from the environment

const fileObj = await client.files.create({
  file: fs.createReadStream('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 completion
while (!['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("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 schema
ExtractConfiguration.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("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 completion
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());
}

终端窗口

# Your extraction schema
DATA_SCHEMA='{"type": "object", "properties": {}}'

FILE_ID=$(llp files create --file 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 completion
while true; do
  STATUS=$(llp extract get --job-id "$JOB_ID" | jq -er '.status') || break
  case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac
  sleep 2
done

BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。