主题
本指南演示如何用 SDK 给文档分类。你将:
- 创建分类规则
- 上传文件
- 提交一个 classify 任务
- 读取预测结果(类型、置信度、推理过程)
SDK 见于 llama-parse-py、llama-parse-ts、llama-parse-go 与 llama-parse-java,另有命令行工具 llama-parse-cli。
设置
首先获取一个 API key并妥善保存。
你可以把它设成环境变量 LLAMA_CLOUD_API_KEY,也可以在运行时直接传给 SDK。
然后安装依赖:
- Python
- TypeScript
- Go
- Java
- CLI
终端窗口
pip install "llama-cloud>=2.8"终端窗口
npm install @llamaindex/llama-cloud终端窗口
go get github.com/run-llama/llama-parse-gobuild.gradle.kts
implementation("ai.llamaindex:llama-cloud:1.3.0")终端窗口
go install github.com/run-llama/llama-parse-cli/cmd/llp@latest快速开始
使用 classify API 主要分几步:
- 上传文件并取得它的 ID
- 用你的规则创建一个 classify 任务,把该 ID 作为
file_input传入 - 等待任务结束
- 读取结果
file_input 也接受一个 parse 任务 ID,所以已经解析过的文档无需再次上传或解析就能分类。
下载示例所用到的那份发票:
终端窗口
curl -fL -o doc1.pdf https://media.githubusercontent.com/media/run-llama/llama-datasets/main/llama_agents/invoice-contracts/invoice-2-1.pdfSDK 提供了一个便捷方法,一次调用就完成上述全部步骤:
- Python
- TypeScript
- Go
- Java
- CLI
import os
from llama_cloud import LlamaCloud, AsyncLlamaCloud
# For async usage, use `AsyncLlamaCloud()`
client = LlamaCloud(api_key=os.environ["LLAMA_CLOUD_API_KEY"])
# Upload a file
file_obj = client.files.create(file="doc1.pdf", purpose="classify")
# Classify and wait for completion
job = client.classify.run(
file_input=file_obj.id,
configuration={
"rules": [
{
"type": "invoice",
"description": "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.",
},
{
"type": "receipt",
"description": "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.",
},
],
"parsing_configuration": {
"lang": "en",
"max_pages": 5, # optional, parse at most 5 pages
# "target_pages": "1,3", # optional, parse only specific pages (1-based)
},
},
)
# `run` raises PollingError if the job fails, so reaching here means it succeeded
print(f"Classified type: {job.result.type}")
print(f"Confidence: {job.result.confidence}")
print(f"Reasoning: {job.result.reasoning}")import LlamaCloud from '@llamaindex/llama-cloud';
import fs from 'fs';
const client = new LlamaCloud({ apiKey: process.env.LLAMA_CLOUD_API_KEY });
// Upload a file
const fileObj = await client.files.create({
file: fs.createReadStream('doc1.pdf'),
purpose: "classify",
});
// Classify and wait for completion
const job = await client.classify.run({
file_input: fileObj.id,
configuration: {
rules: [
{
type: 'invoice',
description: 'Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.',
},
{
type: 'receipt',
description: 'Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.',
},
],
parsing_configuration: {
lang: 'en',
max_pages: 5,
// target_pages: "1,3", // Optional: specific pages (1-based)
},
},
});
// `run` throws if the job fails, so reaching here means it succeeded
console.log(`Classified type: ${job.result!.type}`);
console.log(`Confidence: ${job.result!.confidence}`);
console.log(`Reasoning: ${job.result!.reasoning}`);package main
import (
"context"
"fmt"
"log"
"os"
"time"
llamacloud "github.com/run-llama/llama-parse-go"
)
func main() {
ctx := context.Background()
client := llamacloud.NewClient()
// Upload a file
f, err := os.Open("doc1.pdf")
if err != nil {
log.Fatal(err)
}
defer f.Close()
fileObj, err := client.Files.New(ctx, llamacloud.FileNewParams{
File: f,
Purpose: "classify",
})
if err != nil {
log.Fatal(err)
}
// Create a classify job
job, err := client.Classify.New(ctx, llamacloud.ClassifyNewParams{
ClassifyCreateRequest: llamacloud.ClassifyCreateRequestParam{
FileInput: llamacloud.String(fileObj.ID),
Configuration: llamacloud.ClassifyConfigurationParam{
Rules: []llamacloud.ClassifyConfigurationRuleParam{
{
Type: "invoice",
Description: "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.",
},
{
Type: "receipt",
Description: "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.",
},
},
ParsingConfiguration: llamacloud.ClassifyConfigurationParsingConfigurationParam{
Lang: llamacloud.String("en"),
MaxPages: llamacloud.Int(5), // optional, parse at most 5 pages
// TargetPages: llamacloud.String("1,3"), // optional, parse only specific pages (1-based)
},
},
},
})
if err != nil {
log.Fatal(err)
}
// Poll until the job reaches a terminal state
result, err := client.Classify.Get(ctx, job.ID, llamacloud.ClassifyGetParams{})
if err != nil {
log.Fatal(err)
}
for result.Status == llamacloud.ClassifyGetResponseStatusPending ||
result.Status == llamacloud.ClassifyGetResponseStatusRunning {
time.Sleep(2 * time.Second)
result, err = client.Classify.Get(ctx, job.ID, llamacloud.ClassifyGetParams{})
if err != nil {
log.Fatal(err)
}
}
if !result.JSON.Result.Valid() {
log.Fatalf("Classification failed: %s", result.ErrorMessage)
}
fmt.Printf("Classified type: %s\n", result.Result.Type)
fmt.Printf("Confidence: %v\n", result.Result.Confidence)
fmt.Printf("Reasoning: %s\n", result.Result.Reasoning)
}import ai.llamaindex.llamacloud.client.LlamaCloudClient;
import ai.llamaindex.llamacloud.client.okhttp.LlamaCloudOkHttpClient;
import ai.llamaindex.llamacloud.models.classify.ClassifyConfiguration;
import ai.llamaindex.llamacloud.models.classify.ClassifyCreateRequest;
import ai.llamaindex.llamacloud.models.classify.ClassifyCreateResponse;
import ai.llamaindex.llamacloud.models.classify.ClassifyGetResponse;
import ai.llamaindex.llamacloud.models.files.FileCreateParams;
import ai.llamaindex.llamacloud.models.files.FileCreateResponse;
import java.nio.file.Paths;
import java.util.Arrays;
public class ClassifyQuickStart {
public static void main(String[] args) throws Exception {
LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();
// Upload a file
FileCreateResponse fileObj = client.files().create(
FileCreateParams.builder()
.file(Paths.get("doc1.pdf"))
.purpose("classify")
.build());
// Create a classify job
ClassifyCreateResponse job = client.classify().create(
ClassifyCreateRequest.builder()
.fileInput(fileObj.id())
.configuration(ClassifyConfiguration.builder()
.rules(Arrays.asList(
ClassifyConfiguration.Rule.builder()
.type("invoice")
.description("Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.")
.build(),
ClassifyConfiguration.Rule.builder()
.type("receipt")
.description("Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.")
.build()))
.parsingConfiguration(ClassifyConfiguration.ParsingConfiguration.builder()
.lang("en")
.maxPages(5L) // optional, parse at most 5 pages
// .targetPages("1,3") // optional, parse only specific pages (1-based)
.build())
.build())
.build());
// Poll until the job reaches a terminal state
ClassifyGetResponse result = client.classify().get(job.id());
while (result.status().equals(ClassifyGetResponse.Status.PENDING)
|| result.status().equals(ClassifyGetResponse.Status.RUNNING)) {
Thread.sleep(2000);
result = client.classify().get(job.id());
}
if (!result.result().isPresent()) {
System.out.println("Classification failed: " + result.errorMessage().orElse(""));
} else {
System.out.println("Classified type: " + result.result().get().type().orElse(""));
System.out.println("Confidence: " + result.result().get().confidence());
System.out.println("Reasoning: " + result.result().get().reasoning());
}
}
}终端窗口
# llp reads LLAMA_CLOUD_API_KEY from the environment.
# Upload a file
FILE_ID=$(llp files create --file doc1.pdf --purpose classify | jq -r '.id')
# Create a classify job
JOB_ID=$(llp classify create \
--file-input "$FILE_ID" \
--configuration '{rules: [{type: invoice, description: "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals."}, {type: receipt, description: "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page."}], parsing_configuration: {lang: en, max_pages: 5}}' \
| jq -r '.id')
# Poll until the job reaches a terminal state
while true; do
RESULT=$(llp classify get "$JOB_ID") || break
STATUS=$(printf '%s\n' "$RESULT" | jq -r '.status')
[ "$STATUS" = "PENDING" ] || [ "$STATUS" = "RUNNING" ] || break
sleep 2
done
printf '%s\n' "$RESULT" | jq -r 'if .status == "COMPLETED" then .result.type, .result.confidence, .result.reasoning
else "Classification failed: \(.error_message // .)" end'分步执行(手工轮询)
需要更多控制时,也可以逐个步骤自己执行:
- Python
- TypeScript
- Go
- Java
- CLI
import os
import time
from llama_cloud import LlamaCloud
client = LlamaCloud(api_key=os.environ["LLAMA_CLOUD_API_KEY"])
# Upload a file
file_obj = client.files.create(file="doc1.pdf", purpose="classify")
# Create a classify job
job = client.classify.create(
file_input=file_obj.id,
configuration={
"rules": [
{
"type": "invoice",
"description": "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.",
},
{
"type": "receipt",
"description": "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.",
},
],
},
)
# Poll until the job reaches a terminal state
result = client.classify.get(job.id)
while result.status in ("PENDING", "RUNNING"):
time.sleep(2)
result = client.classify.get(job.id)
# `get` returns the result inline once the job is COMPLETED
if result.result is None:
print(f"Classification failed: {result.error_message}")
else:
print(f"Classified type: {result.result.type}")
print(f"Confidence: {result.result.confidence}")
print(f"Reasoning: {result.result.reasoning}")import LlamaCloud from '@llamaindex/llama-cloud';
import fs from 'fs';
const client = new LlamaCloud({ apiKey: process.env.LLAMA_CLOUD_API_KEY });
// Upload a file
const fileObj = await client.files.create({
file: fs.createReadStream('doc1.pdf'),
purpose: "classify",
});
// Create a classify job
const job = await client.classify.create({
file_input: fileObj.id,
configuration: {
rules: [
{
type: 'invoice',
description: 'Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.',
},
{
type: 'receipt',
description: 'Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.',
},
],
},
});
// Poll until the job reaches a terminal state
let result = await client.classify.get(job.id);
while (result.status === 'PENDING' || result.status === 'RUNNING') {
await new Promise((r) => setTimeout(r, 2000));
result = await client.classify.get(job.id);
}
// `get` returns the result inline once the job is COMPLETED
if (!result.result) {
console.log(`Classification failed: ${result.error_message}`);
} else {
console.log(`Classified type: ${result.result.type}`);
console.log(`Confidence: ${result.result.confidence}`);
console.log(`Reasoning: ${result.result.reasoning}`);
}package main
import (
"context"
"fmt"
"log"
"os"
"time"
llamacloud "github.com/run-llama/llama-parse-go"
)
func main() {
ctx := context.Background()
client := llamacloud.NewClient()
// Upload a file
f, err := os.Open("doc1.pdf")
if err != nil {
log.Fatal(err)
}
defer f.Close()
fileObj, err := client.Files.New(ctx, llamacloud.FileNewParams{
File: f,
Purpose: "classify",
})
if err != nil {
log.Fatal(err)
}
// Create a classify job
job, err := client.Classify.New(ctx, llamacloud.ClassifyNewParams{
ClassifyCreateRequest: llamacloud.ClassifyCreateRequestParam{
FileInput: llamacloud.String(fileObj.ID),
Configuration: llamacloud.ClassifyConfigurationParam{
Rules: []llamacloud.ClassifyConfigurationRuleParam{
{
Type: "invoice",
Description: "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.",
},
{
Type: "receipt",
Description: "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.",
},
},
},
},
})
if err != nil {
log.Fatal(err)
}
// Poll until the job reaches a terminal state
result, err := client.Classify.Get(ctx, job.ID, llamacloud.ClassifyGetParams{})
if err != nil {
log.Fatal(err)
}
for result.Status == llamacloud.ClassifyGetResponseStatusPending ||
result.Status == llamacloud.ClassifyGetResponseStatusRunning {
time.Sleep(2 * time.Second)
result, err = client.Classify.Get(ctx, job.ID, llamacloud.ClassifyGetParams{})
if err != nil {
log.Fatal(err)
}
}
// `Get` returns the result inline once the job is COMPLETED
if !result.JSON.Result.Valid() {
fmt.Printf("Classification failed: %s\n", result.ErrorMessage)
} else {
fmt.Printf("Classified type: %s\n", result.Result.Type)
fmt.Printf("Confidence: %v\n", result.Result.Confidence)
fmt.Printf("Reasoning: %s\n", result.Result.Reasoning)
}
}import ai.llamaindex.llamacloud.client.LlamaCloudClient;
import ai.llamaindex.llamacloud.client.okhttp.LlamaCloudOkHttpClient;
import ai.llamaindex.llamacloud.models.classify.ClassifyConfiguration;
import ai.llamaindex.llamacloud.models.classify.ClassifyCreateRequest;
import ai.llamaindex.llamacloud.models.classify.ClassifyCreateResponse;
import ai.llamaindex.llamacloud.models.classify.ClassifyGetResponse;
import ai.llamaindex.llamacloud.models.files.FileCreateParams;
import ai.llamaindex.llamacloud.models.files.FileCreateResponse;
import java.nio.file.Paths;
import java.util.Arrays;
public class ClassifyStepByStep {
public static void main(String[] args) throws Exception {
LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();
// Upload a file
FileCreateResponse fileObj = client.files().create(
FileCreateParams.builder()
.file(Paths.get("doc1.pdf"))
.purpose("classify")
.build());
// Create a classify job
ClassifyCreateResponse job = client.classify().create(
ClassifyCreateRequest.builder()
.fileInput(fileObj.id())
.configuration(ClassifyConfiguration.builder()
.rules(Arrays.asList(
ClassifyConfiguration.Rule.builder()
.type("invoice")
.description("Documents that contain an invoice number, invoice date, bill-to section, and line items with totals.")
.build(),
ClassifyConfiguration.Rule.builder()
.type("receipt")
.description("Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page.")
.build()))
.build())
.build());
// Poll until the job reaches a terminal state
ClassifyGetResponse result = client.classify().get(job.id());
while (result.status().equals(ClassifyGetResponse.Status.PENDING)
|| result.status().equals(ClassifyGetResponse.Status.RUNNING)) {
Thread.sleep(2000);
result = client.classify().get(job.id());
}
// `get` returns the result inline once the job is COMPLETED
if (!result.result().isPresent()) {
System.out.println("Classification failed: " + result.errorMessage().orElse(""));
} else {
System.out.println("Classified type: " + result.result().get().type().orElse(""));
System.out.println("Confidence: " + result.result().get().confidence());
System.out.println("Reasoning: " + result.result().get().reasoning());
}
}
}终端窗口
# llp reads LLAMA_CLOUD_API_KEY from the environment.
# Upload a file
FILE_ID=$(llp files create --file doc1.pdf --purpose classify | jq -r '.id')
# Create a classify job
JOB_ID=$(llp classify create \
--file-input "$FILE_ID" \
--configuration.rules '[{type: invoice, description: "Documents that contain an invoice number, invoice date, bill-to section, and line items with totals."}, {type: receipt, description: "Short purchase receipts, typically from POS systems, with merchant, items and total, often a single page."}]' \
| jq -r '.id')
# Poll until the job reaches a terminal state
while true; do
RESULT=$(llp classify get "$JOB_ID") || break
STATUS=$(printf '%s\n' "$RESULT" | jq -r '.status')
[ "$STATUS" = "PENDING" ] || [ "$STATUS" = "RUNNING" ] || break
sleep 2
done
# `get` returns the result inline once the job is COMPLETED
printf '%s\n' "$RESULT" | jq -r 'if .status == "COMPLETED" then .result.type, .result.confidence, .result.reasoning
else "Classification failed: \(.error_message // .)" end'说明
- 每条规则都需要
type(要打的标签)与description(用自然语言描述什么内容算命中)。同一个配置里规则类型必须唯一。 parsing_configuration可选。用lang、max_pages或target_pages控制文档在分类前如何解析。target_pages是以逗号分隔的、从 1 开始的页号或页范围字符串(例如"1,3,5-7")。- 每个任务只分类一份文档。要分类多个文件,就一个文件提交一个任务。
- 失败或被取消的任务没有
result—— 读取前先检查status,失败原因在error_message里。 - 任务状态:
PENDING、RUNNING、COMPLETED、FAILED、CANCELLED。 - 除了内联传
configuration,你也可以传configuration_id来复用已保存的配置。
怎样写出好规则
- 具体描述能区分该类型的内容特征。
- 写上文档通常包含的关键字段(例如发票号、合计金额)。
- 需要覆盖不同形态时就多写几条规则。
- 先从简单开始,在小样本上试跑,再逐步打磨。