主题
当前版本的每个档位上的 Parse 任务都能返回一棵 items 树:每页一个按顺序排列的带类型元素列表(标题、正文、表格、图片、页眉),每项都带自己的 markdown 与条目级边界框。若要为引用做高亮与落地,output_options.granular_bboxes 可再按词、按行、按表格单元格给出边界框,以 JSONL 边车文件交付。页 markdown 也会把页眉页脚从正文里分开,而 crop_box 会在解析前裁掉页面的装订区。
什么时候用它
- 在 PDF 查看器里高亮引用确切指向的那段文字。
- 把抽取出的答案落到某个词、某一行或某个单元格上,而不是整段。
- 并排预览:让 markdown 文字与源页上的区域同步。
- 去掉重复的页眉页脚,或让它们与正文分开保存。
- 为下游切块重建阅读顺序与元素类型。
固定在 2026-06-15 之前版本的 fast 任务只产出文本,因此那里没有 markdown、items 与细粒度边界框。
选项
| 选项 | 类型 | 默认值 | 作用 |
|---|---|---|---|
output_options.granular_bboxes | "word"、"line"、"cell" 的数组 | [] | 按所选层级计算边界框。写入一个 grounded_items JSONL 边车文件,其下载地址会自动出现在结果上,expand 里无需再加什么。 |
output_options.images_to_save | array | 当输出链接到裁剪图片时保存 layout | 加上 "screenshot" 可获得用于绘制边界框的整页渲染图。用 expand=["images_content_metadata"] 取回。 |
output_options.extract_printed_page_number | boolean | 未设 | 返回页面上印着的页号(v、A-3),放在 metadata.pages[].printed_page_number,供引用使用。 |
crop_box(顶层) | 含 top、bottom、left、right 的比例对象,取值 0 到 1 | 未设 | 解析前对每一页做的几何裁剪;去掉固定位置的页眉、页脚与页边装订区的常用手段。 |
output_options.spatial_text | object | 未设 | 保留空白的文本。do_not_unroll_columns 让多栏排版并列保留;另有 preserve_layout_alignment_across_pages 与 preserve_very_small_text 两个开关。 |
output_options.additional_outputs | array | [] | "word_bbox" 会把原始的逐词边界框存成 JSONL(每个词一个对象,含页号与 x/y/w/h),通过 expand=["raw_words_content_metadata"] 取回。 |
要版面树就请求 expand=["items"],要带 header 与 footer 字段的逐页 markdown 就用 expand=["markdown"],要 original_orientation_angle 与 printed_page_number 就用 expand=["metadata"]。
示例
从快速上手 下载那份报告:
终端窗口
curl -fL -o executive-summary-2024.pdf https://fiscal.treasury.gov/system/files/files/reports-statements/financial-report/2024/executive-summary-2024.pdf上传它、跑一个开启词/行/单元格落地的 Parse 任务,然后取回边车文件并打印第 1 页每个词的边界框:
import json
import httpx
from llama_cloud import LlamaCloud
client = LlamaCloud() # reads LLAMA_CLOUD_API_KEY from the environment
file = client.files.create(file="./executive-summary-2024.pdf", purpose="parse")
result = client.parsing.parse(
file_id=file.id,
tier="agentic",
version="latest",
output_options={"granular_bboxes": ["word", "line", "cell"]},
expand=["items"],
)
sidecar = (result.result_content_metadata or {}).get("grounded_items")
rows = [json.loads(line) for line in httpx.get(sidecar.presigned_url).text.splitlines() if line.strip()]
page = next(p for p in rows if p["success"] and p["page_number"] == 1)
for item in page["items"]:
grounding = item.get("grounding")
if not grounding or "lines" not in grounding:
continue
md_bytes = item["md"].encode("utf-8") # spans are UTF-8 byte offsets
for line in grounding["lines"]:
for word in line.get("words") or []:
start, end = word["span"]
print(md_bytes[start:end].decode("utf-8"), word["bbox"])你会拿到什么
条目按文档顺序逐页返回,每个都带 type、它的 md,以及以页面点为单位的 bbox 列表。常见的类型有 header、heading、text、table 与 image:
{
"page_number": 1, "page_width": 612.0, "page_height": 792.0,
"items": [
{ "type": "heading", "level": 1, "md": "# NATION BY THE NUMBERS", "bbox": [{ "x": 72.0, "y": 100.0, "w": 200.0, "h": 12.0 }] },
{ "type": "table", "rows": [["Gross Costs", "$ (7,772.2)"]], "csv": "...", "html": "...", "md": "..." }
],
"success": true
}边车里的每一行是同样的条目再加一个 grounding 块。对文本条目,它含 lines[],每行有自己的 bbox 和一个指向该条目 md 的 [start, end) 区间(UTF-8 字节偏移,不是字符偏移),每行内还有 words[]。对表格,它含 rows[row][col] 各单元格及其边界框与区间,另有 row_bboxes 与 column_bboxes:
{ "span": [0, 11], "bbox": { "x": 72.0, "y": 100.0, "w": 200.0, "h": 12.0 },
"words": [ { "span": [0, 5], "bbox": { "x": 72.0, "y": 100.0, "w": 35.0, "h": 12.0 } } ] }坐标约定
- 边界框是
x、y、w、h,以页面点为单位,坐标框架由该页的page_width与page_height给出。这个框架是方向校正之前的原始视口;PDF 的/Rotate已经算在里面。 r若存在,表示绕该框中心的顺时针旋转角度,用于视觉上被旋转过的文字。只应用r。不要把metadata.pages[].original_orientation_angle加到它上面;那个角度描述的是这一页被转成可阅读姿态的情况,无需旋转时为0。- 元数据与页的对应关系请按
page_number匹配,而不是按数组下标,尤其在使用了page_ranges选择时。 - 要在截图上绘制,先把每个框的角点在页面单位下旋转,再缩放到图像像素。先缩放再旋转会在横纵缩放比例不同时让框变形。
页 markdown 会把装订区与正文分开:markdown.pages[].header 与 footer 存放检测到的页眉页脚文字,header 条目也会出现在树里。对于位置固定的装订区,更合适的做法是用 crop_box 在解析前就裁掉。
另请参阅
- 细粒度边界框示例:边车 schema、表格单元格的落地,以及一个完整的截图渲染辅助函数
- 响应形态:grounded items 边车、items 页 与 边界框
- 配置 Parse:细粒度边界框、crop box 与 空间文本
- 表单与复选框:表单页上逐字段的边界框