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

**expand 决定一次 Parse 任务往回返回什么。**默认情况下 API 只返回任务本身(状态、ID、错误信息),不含任何解析内容。你通过增加 expand 取值来按需取用,并且之后可以针对同一个任务换一组取值再取,无需重新解析。

本页说明 expand 的用法:全部取值、多数调用方常用的模式与限制。每个返回字段里有什么,见响应形态。

速查

内联内容

这些取值会把解析出的数据直接放在响应体里,不需要再下载。

取值你能拿到什么备注
markdown逐页的 Markdown
markdown_full整份文档作为一个 markdown 字符串
text逐页的纯文本
text_full整份文档作为一个纯文本字符串
items逐页的结构化 items:表格、标题、图形、列表
metadata逐页元数据:置信度、方向、水印、演讲者备注
forms逐页的表单树(beta)仅设了 processing_options.forms: "enrich" 的任务;fast 上永无
job_metadata任务执行元数据:状态迁移与耗时
usage计费的 credit,位于 job.usage 之下见单个任务计费的 credit

下载地址

这些取值不会返回内容本身,而是在 result_content_metadata 下给出一个预签名下载地址。当结果很大、你想先看它的大小、把它流式存起来,或者要取的是 XLSX、PDF 这类文件格式时就用它们。条目形态与各自对应什么文件,见下载地址。

取值文件备注
markdown_content_metadata逐页 markdown,JSON
markdown_full_content_metadata整份文档一个 .md
text_content_metadata逐页文本,JSON
text_full_content_metadata整份文档一个 .txt
items_content_metadataitems 树,JSON
metadata_content_metadata页元数据,JSON
forms_content_metadata表单,JSON仅设了 processing_options.forms: "enrich" 的任务
images_content_metadata已保存的图片,每张各有自己的 URL有哪些图片取决于 output_options.images_to_save
xlsx_content_metadata表格作为一个工作簿仅设了 tables_as_spreadsheet.enable: true 的任务
output_pdf_content_metadata渲染出的 PDF仅设了 output_options.save_output_pdf: true 的任务
raw_words_content_metadata词级边界框,JSONL仅设了 output_options.additional_outputs: ["word_bbox"] 的任务
result_content_metadata.grounded_itemsgrounded items 边车文件,JSONL设了 granular_bboxes 时自动包含;expand 里无需添加任何东西

每个取值在所有档位上都可用,只有两点例外:forms 需要表单分析这一轮,而 fast 档不跑它;固定在 2026-06-15 之前版本的 fast 任务则完全没有 markdown 与 items。见限制。

常见模式

下面的 SDK 片段都基于这套 setup 建立的 client 与已上传的 file;安装步骤见快速上手。逐页结果里可能存在失败的页("success": false)且没有内容字段,因此循环里会先检查 success 再读取;见页数组。

先下载一份样例 PDF —— 财政服务局的 FY2024 执行摘要,存为 doc.pdf:

终端窗口

curl -fL -o doc.pdf https://fiscal.treasury.gov/system/files/files/reports-statements/financial-report/2024/executive-summary-2024.pdf
  • Python
  • TypeScript
  • Go
  • Java
  • CLI
from llama_cloud import LlamaCloud

client = LlamaCloud()  # reads LLAMA_CLOUD_API_KEY from the environment
file = client.files.create(file="doc.pdf", purpose="parse")
import LlamaCloud from "@llamaindex/llama-cloud";
import fs from "fs";

const client = new LlamaCloud(); // reads LLAMA_CLOUD_API_KEY from the environment
const file = await client.files.create({
  file: fs.createReadStream("doc.pdf"),
  purpose: "parse",
});
package main

import (
  "context"
  "fmt"
  "log"
  "os"
  "strings"
  "time"

  llamacloud "github.com/run-llama/llama-parse-go"
)

func main() {
  ctx := context.Background()
  client := llamacloud.NewClient() // reads LLAMA_CLOUD_API_KEY from the environment

  f, err := os.Open("doc.pdf")
  if err != nil {
    log.Fatal(err)
  }
  defer f.Close()

  file, err := client.Files.New(ctx, llamacloud.FileNewParams{
    File:    f,
    Purpose: "parse",
  })
  if err != nil {
    log.Fatal(err)
  }

  // ... a snippet below goes here, using ctx, client, and file ...
  // Go rejects unused imports: drop "strings" if your snippet doesn't call it.
  _ = file
}
import ai.llamaindex.llamacloud.client.LlamaCloudClient;
import ai.llamaindex.llamacloud.client.okhttp.LlamaCloudOkHttpClient;
import ai.llamaindex.llamacloud.models.files.FileCreateParams;
import ai.llamaindex.llamacloud.models.files.FileCreateResponse;
import ai.llamaindex.llamacloud.models.parsing.ParsingCreateParams;
import ai.llamaindex.llamacloud.models.parsing.ParsingCreateResponse;
import ai.llamaindex.llamacloud.models.parsing.ParsingGetParams;
import ai.llamaindex.llamacloud.models.parsing.ParsingGetResponse;
import java.nio.file.Paths;
import java.util.stream.Collectors;

LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();
FileCreateResponse file = client.files().create(FileCreateParams.builder()
        .file(Paths.get("doc.pdf"))
        .purpose("parse")
        .build());

终端窗口

# llp reads LLAMA_CLOUD_API_KEY from the environment
FILE_ID=$(llp files create --file doc.pdf --purpose parse | jq -r '.id')

只要 markdown

最简单的模式。多数 LLM 流水线只需要这个。

  • Python
  • TypeScript
  • Go
  • Java
  • CLI
result = client.parsing.parse(
    file_id=file.id,
    tier="agentic",
    version="latest",
    expand=["markdown"],
)

for page in result.markdown.pages:
    if page.success:
        print(page.markdown)
const result = await client.parsing.parse({
  file_id: file.id,
  tier: "agentic",
  version: "latest",
  expand: ["markdown"],
});

for (const page of result.markdown?.pages ?? []) {
  if (page.success) {
    console.log(page.markdown);
  }
}
// expand is a GET parameter in Go, so create the job, poll, then request markdown
job, err := client.Parsing.New(ctx, llamacloud.ParsingNewParams{
  FileID:  llamacloud.String(file.ID),
  Tier:    llamacloud.ParsingNewParamsTierAgentic,
  Version: llamacloud.ParsingNewParamsVersionLatest,
})
if err != nil {
  log.Fatal(err)
}

getParams := llamacloud.ParsingGetParams{Expand: []string{"markdown"}}
result, err := client.Parsing.Get(ctx, job.ID, getParams)
if err != nil {
  log.Fatal(err)
}
for result.Job.Status != "COMPLETED" && result.Job.Status != "FAILED" && result.Job.Status != "CANCELLED" {
  time.Sleep(2 * time.Second)
  result, err = client.Parsing.Get(ctx, job.ID, getParams)
  if err != nil {
    log.Fatal(err)
  }
}
if result.Job.Status != "COMPLETED" {
  log.Fatalf("parse ended as %s", result.Job.Status)
}

for _, page := range result.Markdown.Pages {
  if page.Success {
    fmt.Println(page.Markdown)
  }
}
// expand is a query parameter in Java, so create the job, poll, then request markdown
ParsingCreateResponse job = client.parsing().create(ParsingCreateParams.builder()
        .fileId(file.id())
        .tier(ParsingCreateParams.Tier.AGENTIC)
        .version(ParsingCreateParams.Version.LATEST)
        .build());

ParsingGetParams getParams = ParsingGetParams.builder()
        .jobId(job.id())
        .addExpand("markdown")
        .build();

ParsingGetResponse result = client.parsing().get(getParams);
while (!result.job().status().equals(ParsingGetResponse.Job.Status.COMPLETED)
        && !result.job().status().equals(ParsingGetResponse.Job.Status.FAILED)
        && !result.job().status().equals(ParsingGetResponse.Job.Status.CANCELLED)) {
    Thread.sleep(2000);
    result = client.parsing().get(getParams);
}
if (!result.job().status().equals(ParsingGetResponse.Job.Status.COMPLETED)) {
    throw new RuntimeException("parse ended as " + result.job().status());
}

for (ParsingGetResponse.Markdown.Page page : result.markdown().get().pages()) {
    if (page.isMarkdownResult()) {
        System.out.println(page.asMarkdownResult().markdown());
    }
}

终端窗口

JOB_ID=$(llp parsing create \
  --file-id "$FILE_ID" \
  --tier agentic \
  --version latest \
  | jq -r '.id')

# Poll until the job reaches a terminal status
while true; do
  STATUS=$(llp parsing get --job-id "$JOB_ID" | jq -er '.job.status') || break
  case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac
  sleep 2
done

# expand is a query parameter — request markdown when you fetch the result
llp parsing get --job-id "$JOB_ID" --expand markdown \
  | jq -r 'if .job.status == "COMPLETED" then .markdown.pages[] | select(.success) | .markdown
    else "Parse job failed: \(.job.error_message // .)" end'

不需要逐页的 markdown?

如果你只想要整份文档的一个字符串,改用 expand=["markdown_full"]:它直接返回 result.markdown_full,省掉逐页循环。

markdown 加结构化 items 树

适合需要在程序里访问表格、标题与图形的流水线。items 里每个元素本就带一个 md 字段,所以只靠 items 也能拼出 LLM 的输入;但同时请求 markdown 能让你直接拿到现成的逐页 markdown 字符串,不必自己重组。

  • Python
  • TypeScript
  • Go
  • Java
  • CLI
result = client.parsing.parse(
    file_id=file.id,
    tier="agentic",
    version="latest",
    expand=["markdown", "items"],
)

# Per-page markdown for the LLM (or use markdown_full for a single string)
llm_input = "\n\n".join(p.markdown for p in result.markdown.pages if p.success)

# Walk the items tree for tables
for page in result.items.pages:
    if not page.success:
        continue
    for item in page.items:
        if item.type == "table":
            print(f"Table on page {page.page_number}: {len(item.rows)} rows")
const result = await client.parsing.parse({
  file_id: file.id,
  tier: "agentic",
  version: "latest",
  expand: ["markdown", "items"],
});

// Per-page markdown for the LLM (or use markdown_full for a single string)
const llmInput = (result.markdown?.pages ?? [])
  .filter((p) => p.success)
  .map((p) => p.markdown)
  .join("\n\n");

// Walk the items tree for tables
for (const page of result.items?.pages ?? []) {
  if (!page.success) continue;
  for (const item of page.items) {
    if (item.type === "table") {
      console.log(`Table on page ${page.page_number}: ${item.rows.length} rows`);
    }
  }
}
job, err := client.Parsing.New(ctx, llamacloud.ParsingNewParams{
  FileID:  llamacloud.String(file.ID),
  Tier:    llamacloud.ParsingNewParamsTierAgentic,
  Version: llamacloud.ParsingNewParamsVersionLatest,
})
if err != nil {
  log.Fatal(err)
}

// expand is a GET parameter — request markdown and items when you fetch the result
getParams := llamacloud.ParsingGetParams{Expand: []string{"markdown", "items"}}
result, err := client.Parsing.Get(ctx, job.ID, getParams)
if err != nil {
  log.Fatal(err)
}
for result.Job.Status != "COMPLETED" && result.Job.Status != "FAILED" && result.Job.Status != "CANCELLED" {
  time.Sleep(2 * time.Second)
  result, err = client.Parsing.Get(ctx, job.ID, getParams)
  if err != nil {
    log.Fatal(err)
  }
}
if result.Job.Status != "COMPLETED" {
  log.Fatalf("parse ended as %s", result.Job.Status)
}

// Per-page markdown for the LLM (or use markdown_full for a single string)
var pages []string
for _, page := range result.Markdown.Pages {
  if page.Success {
    pages = append(pages, page.Markdown)
  }
}
llmInput := strings.Join(pages, "\n\n")
_ = llmInput // feed to your LLM

// Walk the items tree for tables
for _, page := range result.Items.Pages {
  if !page.Success {
    continue
  }
  for _, item := range page.Items {
    if item.Type == "table" {
      fmt.Printf("Table on page %d: %d rows\n", page.PageNumber, len(item.Rows))
    }
  }
}
ParsingCreateResponse job = client.parsing().create(ParsingCreateParams.builder()
        .fileId(file.id())
        .tier(ParsingCreateParams.Tier.AGENTIC)
        .version(ParsingCreateParams.Version.LATEST)
        .build());

// expand is a query parameter — request markdown and items when you fetch the result
ParsingGetParams getParams = ParsingGetParams.builder()
        .jobId(job.id())
        .addExpand("markdown")
        .addExpand("items")
        .build();

ParsingGetResponse result = client.parsing().get(getParams);
while (!result.job().status().equals(ParsingGetResponse.Job.Status.COMPLETED)
        && !result.job().status().equals(ParsingGetResponse.Job.Status.FAILED)
        && !result.job().status().equals(ParsingGetResponse.Job.Status.CANCELLED)) {
    Thread.sleep(2000);
    result = client.parsing().get(getParams);
}
if (!result.job().status().equals(ParsingGetResponse.Job.Status.COMPLETED)) {
    throw new RuntimeException("parse ended as " + result.job().status());
}

// Per-page markdown for the LLM (or use markdown_full for a single string)
StringBuilder llmInput = new StringBuilder();
for (ParsingGetResponse.Markdown.Page page : result.markdown().get().pages()) {
    if (!page.isMarkdownResult()) {
        continue;
    }
    if (llmInput.length() > 0) {
        llmInput.append("\n\n");
    }
    llmInput.append(page.asMarkdownResult().markdown());
}

// Walk the items tree for tables
for (ParsingGetResponse.Items.Page page : result.items().get().pages()) {
    if (!page.isStructuredResult()) {
        continue;
    }
    ParsingGetResponse.Items.Page.StructuredResultPage structured = page.asStructuredResult();
    for (ParsingGetResponse.Items.Page.StructuredResultPage.Item item : structured.items()) {
        if (item.isTable()) {
            System.out.printf("Table on page %d: %d rows%n",
                    structured.pageNumber(), item.asTable().rows().size());
        }
    }
}

终端窗口

JOB_ID=$(llp parsing create \
  --file-id "$FILE_ID" \
  --tier agentic \
  --version latest \
  | jq -r '.id')

# Poll until the job reaches a terminal status
while true; do
  STATUS=$(llp parsing get --job-id "$JOB_ID" | jq -er '.job.status') || break
  case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac
  sleep 2
done

# expand is a query parameter — request markdown and items when you fetch the result
RESULT=$(llp parsing get --job-id "$JOB_ID" --expand markdown --expand items)

if printf '%s\n' "$RESULT" | jq -e '.job.status == "COMPLETED"' >/dev/null; then
  # Per-page markdown for the LLM (or use markdown_full for a single string)
  printf '%s\n' "$RESULT" | jq -r '[.markdown.pages[] | select(.success) | .markdown] | join("\n\n")'

  # Walk the items tree for tables
  printf '%s\n' "$RESULT" | jq -r '
    .items.pages[]
    | select(.success)
    | .page_number as $page
    | .items[]
    | select(.type == "table")
    | "Table on page \($page): \(.rows | length) rows"'
else
  printf '%s\n' "$RESULT" | jq -r '"Parse job failed: \(.job.error_message // .)"' >&2
fi

完整 markdown 加预签名图片地址

适合多模态流水线 —— 要一整块 markdown,同时把各页截图作为可单独下载的图像。

  • Python
  • TypeScript
  • Go
  • Java
  • CLI
result = client.parsing.parse(
    file_id=file.id,
    tier="agentic_plus",
    version="latest",
    output_options={"images_to_save": ["screenshot"]},
    expand=["markdown_full", "images_content_metadata"],
)

# One big markdown blob for the LLM
print(result.markdown_full)

# Each page screenshot as a downloadable URL
for image in result.images_content_metadata.images:
    print(f"{image.filename}: {image.presigned_url}")
const result = await client.parsing.parse({
  file_id: file.id,
  tier: "agentic_plus",
  version: "latest",
  output_options: { images_to_save: ["screenshot"] },
  expand: ["markdown_full", "images_content_metadata"],
});

console.log(result.markdown_full);

for (const image of result.images_content_metadata?.images ?? []) {
  console.log(`${image.filename}: ${image.presigned_url}`);
}
job, err := client.Parsing.New(ctx, llamacloud.ParsingNewParams{
  FileID:  llamacloud.String(file.ID),
  Tier:    llamacloud.ParsingNewParamsTierAgenticPlus,
  Version: llamacloud.ParsingNewParamsVersionLatest,
  OutputOptions: llamacloud.ParsingNewParamsOutputOptions{
    ImagesToSave: []string{"screenshot"},
  },
})
if err != nil {
  log.Fatal(err)
}

// Request the full markdown blob and the per-image download URLs on the result
getParams := llamacloud.ParsingGetParams{Expand: []string{"markdown_full", "images_content_metadata"}}
result, err := client.Parsing.Get(ctx, job.ID, getParams)
if err != nil {
  log.Fatal(err)
}
for result.Job.Status != "COMPLETED" && result.Job.Status != "FAILED" && result.Job.Status != "CANCELLED" {
  time.Sleep(2 * time.Second)
  result, err = client.Parsing.Get(ctx, job.ID, getParams)
  if err != nil {
    log.Fatal(err)
  }
}

// One big markdown blob for the LLM
fmt.Println(result.MarkdownFull)

// Each page screenshot as a downloadable URL
for _, image := range result.ImagesContentMetadata.Images {
  fmt.Printf("%s: %s\n", image.Filename, image.PresignedURL)
}
ParsingCreateResponse job = client.parsing().create(ParsingCreateParams.builder()
        .fileId(file.id())
        .tier(ParsingCreateParams.Tier.AGENTIC_PLUS)
        .version(ParsingCreateParams.Version.LATEST)
        .outputOptions(ParsingCreateParams.OutputOptions.builder()
                .addImagesToSave(ParsingCreateParams.OutputOptions.ImagesToSave.SCREENSHOT)
                .build())
        .build());

// Request the full markdown blob and the per-image download URLs on the result
ParsingGetParams getParams = ParsingGetParams.builder()
        .jobId(job.id())
        .addExpand("markdown_full")
        .addExpand("images_content_metadata")
        .build();

ParsingGetResponse result = client.parsing().get(getParams);
while (!result.job().status().equals(ParsingGetResponse.Job.Status.COMPLETED)
        && !result.job().status().equals(ParsingGetResponse.Job.Status.FAILED)
        && !result.job().status().equals(ParsingGetResponse.Job.Status.CANCELLED)) {
    Thread.sleep(2000);
    result = client.parsing().get(getParams);
}

// One big markdown blob for the LLM
System.out.println(result.markdownFull().orElse(""));

// Each page screenshot as a downloadable URL
for (ParsingGetResponse.ImagesContentMetadata.Image image : result.imagesContentMetadata().get().images()) {
    System.out.println(image.filename() + ": " + image.presignedUrl().orElse(""));
}

终端窗口

JOB_ID=$(llp parsing create \
  --file-id "$FILE_ID" \
  --tier agentic_plus \
  --version latest \
  --output-options.images-to-save '[screenshot]' \
  | jq -r '.id')

# Poll until the job reaches a terminal status
while true; do
  STATUS=$(llp parsing get --job-id "$JOB_ID" | jq -er '.job.status') || break
  case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac
  sleep 2
done

RESULT=$(llp parsing get --job-id "$JOB_ID" \
  --expand markdown_full \
  --expand images_content_metadata)

if printf '%s\n' "$RESULT" | jq -e '.job.status == "COMPLETED"' >/dev/null; then
  # One big markdown blob for the LLM
  printf '%s\n' "$RESULT" | jq -r '.markdown_full'

  # Each page screenshot as a downloadable URL
  printf '%s\n' "$RESULT" | jq -r '.images_content_metadata.images[] | "\(.filename): \(.presigned_url)"'
else
  printf '%s\n' "$RESULT" | jq -r '"Parse job failed: \(.job.error_message // .)"' >&2
fi

按页把多种表示拼起来

每一种逐页表示都带 page_number,于是你可以把同一页的 markdown、items 与 metadata 对齐。请按页号建查找表,而不是把数组按下标 zip —— 因为失败的页仍会出现在每个数组里,只是没有内容。

  • Python
  • TypeScript
result = client.parsing.parse(
    file_id=file.id,
    tier="agentic",
    version="latest",
    expand=["markdown", "items", "metadata"],
)

confidence = {m.page_number: m.confidence for m in result.metadata.pages}
items_by_page = {p.page_number: p.items for p in result.items.pages if p.success}

for page in result.markdown.pages:
    if not page.success:
        print(f"page {page.page_number} failed: {page.error}")
        continue
    n_items = len(items_by_page.get(page.page_number, []))
    print(page.page_number, confidence.get(page.page_number), n_items, "items")
const result = await client.parsing.parse({
  file_id: file.id,
  tier: "agentic",
  version: "latest",
  expand: ["markdown", "items", "metadata"],
});

const confidence = new Map(
  (result.metadata?.pages ?? []).map((m) => [m.page_number, m.confidence]),
);
const itemsByPage = new Map(
  (result.items?.pages ?? []).flatMap((p) => (p.success ? [[p.page_number, p.items] as const] : [])),
);

for (const page of result.markdown?.pages ?? []) {
  if (!page.success) {
    console.log(`page ${page.page_number} failed: ${page.error}`);
    continue;
  }
  const nItems = itemsByPage.get(page.page_number)?.length ?? 0;
  console.log(page.page_number, confidence.get(page.page_number), nItems, "items");
}

任务跑完之后再取结果

你不必在解析时就把自己可能需要的一切都要过来。可以先用一组 expand 取值跑任务,之后再用另一组取值调 get,无需重跑任务。

这正是下列场景该用的模式:

  • **你还不确定要什么。**先用 expand=["markdown"] 跑,后来发现还要 items 树,就针对同一个任务 ID 再用 expand=["items"] 取。这比重新解析便宜。
  • **你在处理大文件。**先用 expand=["markdown_content_metadata"] 看 size_bytes,再决定要不要下载。
  • **你要在早前解析过的任务上继续工作。**传入旧的任务 ID 与一份 expand 列表,就能取回该任务产出的任何一种表示。

本节每个片段都会自己建 client 并上传 doc.pdf,因此不使用上面的 setup。若你跳过了 setup,请先下载这份样例 PDF:

终端窗口

curl -fL -o doc.pdf https://fiscal.treasury.gov/system/files/files/reports-statements/financial-report/2024/executive-summary-2024.pdf
  • Python
  • TypeScript
  • Go
  • Java
  • CLI
from llama_cloud import LlamaCloud

client = LlamaCloud()  # reads LLAMA_CLOUD_API_KEY from the environment

# Step 1: run a Parse job with a minimal expand
result = client.parsing.parse(
    upload_file="doc.pdf",
    tier="cost_effective",
    version="latest",
    expand=["markdown_full"],
)
print(result.job.status)
print(result.markdown_full)

# Step 2: later, retrieve the text representation of the same job
text_result = client.parsing.get(
    job_id=result.job.id,
    expand=["text_full"],
)
print(text_result.text_full)
import fs from "fs";
import { LlamaCloud } from "@llamaindex/llama-cloud";

const client = new LlamaCloud(); // reads LLAMA_CLOUD_API_KEY from the environment

// Step 1: run a Parse job with a minimal expand
const result = await client.parsing.parse({
  upload_file: fs.createReadStream("doc.pdf"),
  tier: "cost_effective",
  version: "latest",
  expand: ["markdown_full"],
});
console.log(result.job.status);
console.log(result.markdown_full);

// Step 2: later, retrieve the text representation of the same job
const textResult = await client.parsing.get(result.job.id, { expand: ["text_full"] });
console.log(textResult.text_full);
package main

import (
  "context"
  "fmt"
  "log"
  "os"
  "time"

  llamacloud "github.com/run-llama/llama-parse-go"
)

func main() {
  ctx := context.Background()
  client := llamacloud.NewClient() // reads LLAMA_CLOUD_API_KEY from the environment

  // Step 1: upload the file and run a Parse job with a minimal expand
  f, err := os.Open("doc.pdf")
  if err != nil {
    log.Fatal(err)
  }
  defer f.Close()

  file, err := client.Files.New(ctx, llamacloud.FileNewParams{File: f, Purpose: "parse"})
  if err != nil {
    log.Fatal(err)
  }

  job, err := client.Parsing.New(ctx, llamacloud.ParsingNewParams{
    FileID:  llamacloud.String(file.ID),
    Tier:    llamacloud.ParsingNewParamsTierCostEffective,
    Version: llamacloud.ParsingNewParamsVersionLatest,
  })
  if err != nil {
    log.Fatal(err)
  }

  // expand is a GET parameter — request markdown_full when you poll for the result
  getParams := llamacloud.ParsingGetParams{Expand: []string{"markdown_full"}}
  result, err := client.Parsing.Get(ctx, job.ID, getParams)
  if err != nil {
    log.Fatal(err)
  }
  for result.Job.Status != "COMPLETED" && result.Job.Status != "FAILED" && result.Job.Status != "CANCELLED" {
    time.Sleep(2 * time.Second)
    result, err = client.Parsing.Get(ctx, job.ID, getParams)
    if err != nil {
      log.Fatal(err)
    }
  }
  fmt.Println(result.Job.Status)
  fmt.Println(result.MarkdownFull)

  // Step 2: later, retrieve the text representation of the same job
  textResult, err := client.Parsing.Get(ctx, job.ID, llamacloud.ParsingGetParams{
    Expand: []string{"text_full"},
  })
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(textResult.TextFull)
}
import ai.llamaindex.llamacloud.client.LlamaCloudClient;
import ai.llamaindex.llamacloud.client.okhttp.LlamaCloudOkHttpClient;
import ai.llamaindex.llamacloud.models.files.FileCreateParams;
import ai.llamaindex.llamacloud.models.files.FileCreateResponse;
import ai.llamaindex.llamacloud.models.parsing.ParsingCreateParams;
import ai.llamaindex.llamacloud.models.parsing.ParsingCreateResponse;
import ai.llamaindex.llamacloud.models.parsing.ParsingGetParams;
import ai.llamaindex.llamacloud.models.parsing.ParsingGetResponse;
import java.nio.file.Paths;

LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();

// Step 1: upload the file and run a Parse job with a minimal expand
FileCreateResponse file = client.files().create(FileCreateParams.builder()
        .file(Paths.get("doc.pdf"))
        .purpose("parse")
        .build());

ParsingCreateResponse job = client.parsing().create(ParsingCreateParams.builder()
        .fileId(file.id())
        .tier(ParsingCreateParams.Tier.COST_EFFECTIVE)
        .version(ParsingCreateParams.Version.LATEST)
        .build());

// expand is a query parameter — request markdown_full when you poll for the result
ParsingGetParams markdownParams = ParsingGetParams.builder()
        .jobId(job.id())
        .addExpand("markdown_full")
        .build();

ParsingGetResponse result = client.parsing().get(markdownParams);
while (!result.job().status().equals(ParsingGetResponse.Job.Status.COMPLETED)
        && !result.job().status().equals(ParsingGetResponse.Job.Status.FAILED)
        && !result.job().status().equals(ParsingGetResponse.Job.Status.CANCELLED)) {
    Thread.sleep(2000);
    result = client.parsing().get(markdownParams);
}
System.out.println(result.job().status());
System.out.println(result.markdownFull().orElse(""));

// Step 2: later, retrieve the text representation of the same job
ParsingGetResponse textResult = client.parsing().get(ParsingGetParams.builder()
        .jobId(job.id())
        .addExpand("text_full")
        .build());
System.out.println(textResult.textFull().orElse(""));

终端窗口

# Step 1: upload the file and run a Parse job with a minimal expand
FILE_ID=$(llp files create --file doc.pdf --purpose parse | jq -r '.id')

JOB_ID=$(llp parsing create \
  --file-id "$FILE_ID" \
  --tier cost_effective \
  --version latest \
  | jq -r '.id')

# Poll until the job reaches a terminal status
while true; do
  STATUS=$(llp parsing get --job-id "$JOB_ID" | jq -er '.job.status') || break
  case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac
  sleep 2
done

# expand is a query parameter — request markdown_full when you fetch the result
llp parsing get --job-id "$JOB_ID" --expand markdown_full | jq -r 'if .job.status == "COMPLETED" then .markdown_full
  else "Parse job failed: \(.job.error_message // .)" end'

# Step 2: later, retrieve the text representation of the same job
llp parsing get --job-id "$JOB_ID" --expand text_full | jq -r 'if .job.status == "COMPLETED" then .text_full
  else "Parse job failed: \(.job.error_message // .)" end'

取特定图片

images_content_metadata 会返回全部已保存的图片。只想取其中一部分时,把文件名放进 image_filenames 传入;这些名字来自先前的一次完整列举,或来自 items 树里的 image 条目。REST 侧的参数是一个逗号分隔的字符串。

下面的片段会为 setup 里那个 file 保存逐页截图、列出所有已保存的图片,然后按名字取回前两张。

  • Python
  • TypeScript
  • Go
  • Java
  • CLI
full = client.parsing.parse(
    file_id=file.id,
    tier="agentic",
    version="latest",
    output_options={"images_to_save": ["screenshot"]},
    expand=["images_content_metadata"],
)
names = [image.filename for image in full.images_content_metadata.images]

result = client.parsing.get(
    job_id=full.job.id,
    expand=["images_content_metadata"],
    image_filenames=",".join(names[:2]),
)
for image in result.images_content_metadata.images:
    print(f"{image.filename}: {image.presigned_url}")
const full = await client.parsing.parse({
  file_id: file.id,
  tier: "agentic",
  version: "latest",
  output_options: { images_to_save: ["screenshot"] },
  expand: ["images_content_metadata"],
});
const names = (full.images_content_metadata?.images ?? []).map((image) => image.filename);

const result = await client.parsing.get(full.job.id, {
  expand: ["images_content_metadata"],
  image_filenames: names.slice(0, 2).join(","),
});
for (const image of result.images_content_metadata?.images ?? []) {
  console.log(`${image.filename}: ${image.presigned_url}`);
}
job, err := client.Parsing.New(ctx, llamacloud.ParsingNewParams{
  FileID:  llamacloud.String(file.ID),
  Tier:    llamacloud.ParsingNewParamsTierAgentic,
  Version: llamacloud.ParsingNewParamsVersionLatest,
  OutputOptions: llamacloud.ParsingNewParamsOutputOptions{
    ImagesToSave: []string{"screenshot"},
  },
})
if err != nil {
  log.Fatal(err)
}

// Poll with the full image listing, then collect the file names
listParams := llamacloud.ParsingGetParams{Expand: []string{"images_content_metadata"}}
full, err := client.Parsing.Get(ctx, job.ID, listParams)
if err != nil {
  log.Fatal(err)
}
for full.Job.Status != "COMPLETED" && full.Job.Status != "FAILED" && full.Job.Status != "CANCELLED" {
  time.Sleep(2 * time.Second)
  full, err = client.Parsing.Get(ctx, job.ID, listParams)
  if err != nil {
    log.Fatal(err)
  }
}
if full.Job.Status != "COMPLETED" {
  log.Fatalf("parse ended as %s", full.Job.Status)
}
var names []string
for _, image := range full.ImagesContentMetadata.Images {
  names = append(names, image.Filename)
}

result, err := client.Parsing.Get(ctx, job.ID, llamacloud.ParsingGetParams{
  Expand:         []string{"images_content_metadata"},
  ImageFilenames: llamacloud.String(strings.Join(names[:min(2, len(names))], ",")),
})
if err != nil {
  log.Fatal(err)
}
for _, image := range result.ImagesContentMetadata.Images {
  fmt.Printf("%s: %s\n", image.Filename, image.PresignedURL)
}
ParsingCreateResponse job = client.parsing().create(ParsingCreateParams.builder()
        .fileId(file.id())
        .tier(ParsingCreateParams.Tier.AGENTIC)
        .version(ParsingCreateParams.Version.LATEST)
        .outputOptions(ParsingCreateParams.OutputOptions.builder()
                .addImagesToSave(ParsingCreateParams.OutputOptions.ImagesToSave.SCREENSHOT)
                .build())
        .build());

// Poll with the full image listing, then join the first two file names
ParsingGetParams listParams = ParsingGetParams.builder()
        .jobId(job.id())
        .addExpand("images_content_metadata")
        .build();

ParsingGetResponse full = client.parsing().get(listParams);
while (!full.job().status().equals(ParsingGetResponse.Job.Status.COMPLETED)
        && !full.job().status().equals(ParsingGetResponse.Job.Status.FAILED)
        && !full.job().status().equals(ParsingGetResponse.Job.Status.CANCELLED)) {
    Thread.sleep(2000);
    full = client.parsing().get(listParams);
}
if (!full.job().status().equals(ParsingGetResponse.Job.Status.COMPLETED)) {
    throw new RuntimeException("parse ended as " + full.job().status());
}
String names = full.imagesContentMetadata().get().images().stream()
        .limit(2)
        .map(ParsingGetResponse.ImagesContentMetadata.Image::filename)
        .collect(Collectors.joining(","));

ParsingGetResponse result = client.parsing().get(ParsingGetParams.builder()
        .jobId(job.id())
        .addExpand("images_content_metadata")
        .imageFilenames(names)
        .build());

for (ParsingGetResponse.ImagesContentMetadata.Image image : result.imagesContentMetadata().get().images()) {
    System.out.println(image.filename() + ": " + image.presignedUrl().orElse(""));
}

终端窗口

JOB_ID=$(llp parsing create \
  --file-id "$FILE_ID" \
  --tier agentic \
  --version latest \
  --output-options.images-to-save '[screenshot]' \
  | jq -r '.id')

# Poll until the job reaches a terminal status; stop if the lookup itself fails
while true; do
  STATUS=$(llp parsing get --job-id "$JOB_ID" | jq -er '.job.status') || break
  case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac
  sleep 2
done

if [ "$STATUS" = COMPLETED ]; then
  # List every saved image and keep the first two file names
  NAMES=$(llp parsing get --job-id "$JOB_ID" --expand images_content_metadata \
    | jq -r '[.images_content_metadata.images[:2][].filename] | join(",")')

  llp parsing get --job-id "$JOB_ID" \
    --expand images_content_metadata \
    --image-filenames "$NAMES" \
    | jq -r '.images_content_metadata.images[] | "\(.filename): \(.presigned_url)"'
else
  llp parsing get --job-id "$JOB_ID" | jq -r '"Parse job failed: \(.job.error_message // .)"' >&2
fi

单个任务计费的额度

expand=usage 返回某个 Parse 任务计费的 credit,位置在 job.usage 而不是顶层。它可以和内容类取值组合:expand=markdown,usage 两者都返回。

下面的片段会在 setup 的那个 file 上跑一个任务,然后取回它的 credit。

  • Python
  • TypeScript
  • CLI
import time

result = client.parsing.parse(
    file_id=file.id,
    tier="agentic",
    version="latest",
    expand=["usage"],
)

# Billing can trail completion, so fetch again until credits are recorded
for _ in range(10):
    if result.job.usage and result.job.usage.credits is not None:
        break
    time.sleep(3)
    result = client.parsing.get(job_id=result.job.id, expand=["usage"])

print(result.job.usage.credits if result.job.usage else None)
let result = await client.parsing.parse({
  file_id: file.id,
  tier: "agentic",
  version: "latest",
  expand: ["usage"],
});

// Billing can trail completion, so fetch again until credits are recorded
for (let attempt = 0; attempt < 10 && result.job.usage?.credits == null; attempt++) {
  await new Promise((resolve) => setTimeout(resolve, 3000));
  result = await client.parsing.get(result.job.id, { expand: ["usage"] });
}

console.log(result.job.usage?.credits);

终端窗口

JOB_ID=$(llp parsing create \
  --file-id "$FILE_ID" \
  --tier agentic \
  --version latest \
  | jq -r '.id')

# Poll until the job reaches a terminal status; stop if the lookup itself fails
while true; do
  STATUS=$(llp parsing get --job-id "$JOB_ID" | jq -er '.job.status') || break
  case "$STATUS" in COMPLETED|FAILED|CANCELLED) break ;; esac
  sleep 2
done

if [ "$STATUS" = COMPLETED ]; then
  # Billing can trail completion, so fetch again until credits are recorded
  for _ in 1 2 3 4 5 6 7 8 9 10; do
    CREDITS=$(llp parsing get --job-id "$JOB_ID" --expand usage | jq -e '.job.usage.credits') && break
    sleep 3
  done
  echo "$CREDITS"
else
  llp parsing get --job-id "$JOB_ID" | jq -r '"Parse job failed: \(.job.error_message // .)"' >&2
fi
{
  "job": {
    "id": "JOB_ID",
    "status": "COMPLETED",
    "usage": {
      "credits": 30.0
    }
  }
}

注意

计费可能滞后于任务完成一小段时间。credits: null 表示还没记录下来,此时请再次拉取,而不是把它当作零。

限制

Fast 档

当前的 fast 版本和其他档位一样会返回 markdown 与 items。只有固定在 2026-06-15 之前版本的 fast 任务是纯文本的:对那种任务 expand=markdown 会被拒绝并返回 400,提示信息形如 "Markdown expansion is not available for FAST tier jobs on version ...",而 items 会返回 null。把 version: "latest" 或当前的 fast 版本固定下来即可避免。

fast 档不跑表单分析。在 fast 档任务上请求 processing_options.forms: "enrich" 会返回校验错误,因此 forms 与 forms_content_metadata 只存在于 cost_effective 及以上档位的任务里。各档产出什么的完整清单见档位。

预签名地址的有效期

预签名 URL 会在有限时间后失效。请在取到后尽快下载,或者用同样的 expand 再调一次 get 以换取新地址。

另请参阅

  • 响应形态 —— 每个 expand 取值返回的字段、条目类型与边界框约定
  • 档位 —— 各档产出什么
  • 配置 Parse —— expand 是顶层键,不嵌在 output_options 里
  • 输出选项 —— 你能让 Parse 生成什么,之后即可通过 expand 取回:图片资源、表格转电子表格、印刷页号
  • 计费与用量 —— 套餐 credit 与整个组织的用量,与 expand=usage 返回的逐任务 credit 并列

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