主题
本例用 LlamaClassify 按类型给若干合同分类。给它一个文件,它会把它判为 co_branding 合同或 affiliate_agreement。
我们使用 CUAD 数据集,其中包含多种合同类型:加盟协议、联合品牌合同、特许经营合同等。
同样的流程也能在 LlamaCloud UI 里完成 —— 在那里你可以用可视化的方式而不是写代码来创建分类规则。
安装
- 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下载合同
下面的示例会在来自 CUAD 数据集(CC BY 4.0)的合同上运行 Classify;Hugging Face 也提供这批数据,但一次只给一个文件。先下载它们用到的那份加盟协议:
终端窗口
curl -fL -o "CybergyHoldingsInc_Affliate Agreement.pdf" "https://huggingface.co/datasets/theatticusproject/cuad/resolve/main/CUAD_v1/full_contract_pdf/Part_I/Affiliate_Agreements/CybergyHoldingsInc_20140520_10-Q_EX-10.27_8605784_EX-10.27_Affiliate%20Agreement.pdf"想多试几份合同,可以从数据集的 CUAD_v1/full_contract_pdf/Part_I/Affiliate_Agreements/ 与 CUAD_v1/full_contract_pdf/Part_I/Co_Branding/ 目录里下载其他文件。
连接 LlamaCloud
确认你已有一个 LlamaCloud API key。把它设成环境变量,或直接传给 SDK。
初始化客户端
- Python
- TypeScript
- Go
- Java
- CLI
import os
from llama_cloud import LlamaCloud
client = LlamaCloud(api_key=os.environ["LLAMA_CLOUD_API_KEY"])import LlamaCloud from "@llamaindex/llama-cloud";
const client = new LlamaCloud({
apiKey: process.env.LLAMA_CLOUD_API_KEY,
});import llamacloud "github.com/run-llama/llama-parse-go"
ctx := context.Background()
client := llamacloud.NewClient() // reads LLAMA_CLOUD_API_KEY from the environmentimport ai.llamaindex.llamacloud.client.LlamaCloudClient;
import ai.llamaindex.llamacloud.client.okhttp.LlamaCloudOkHttpClient;
// Reads LLAMA_CLOUD_API_KEY from the environment
LlamaCloudClient client = LlamaCloudOkHttpClient.fromEnv();终端窗口
# The llp CLI reads LLAMA_CLOUD_API_KEY from the environment
export LLAMA_CLOUD_API_KEY="llx-..."定义分类规则
本例在 co_branding 与 affiliate_agreements 之间做分类:
- Python
- TypeScript
- Go
- Java
- CLI
rules = [
{
"type": "affiliate_agreements",
"description": "This is a contract that outlines an affiliate agreement",
},
{
"type": "co_branding",
"description": "This is a contract that outlines a co-branding deal/agreement",
},
]const rules = [
{
type: 'affiliate_agreements',
description: 'This is a contract that outlines an affiliate agreement',
},
{
type: 'co_branding',
description: 'This is a contract that outlines a co-branding deal/agreement',
},
];rules := []llamacloud.ClassifyConfigurationRuleParam{
{
Type: "affiliate_agreements",
Description: "This is a contract that outlines an affiliate agreement",
},
{
Type: "co_branding",
Description: "This is a contract that outlines a co-branding deal/agreement",
},
}List<ClassifyConfiguration.Rule> rules = Arrays.asList(
ClassifyConfiguration.Rule.builder()
.type("affiliate_agreements")
.description("This is a contract that outlines an affiliate agreement")
.build(),
ClassifyConfiguration.Rule.builder()
.type("co_branding")
.description("This is a contract that outlines a co-branding deal/agreement")
.build());终端窗口
RULES='[
{type: affiliate_agreements, description: "This is a contract that outlines an affiliate agreement"},
{type: co_branding, description: "This is a contract that outlines a co-branding deal/agreement"}
]'分类文件
上传一个文件并分类:
- Python
- TypeScript
- Go
- Java
- CLI
import time
file_obj = client.files.create(
file="CybergyHoldingsInc_Affliate Agreement.pdf",
purpose="classify",
)
# Create a classify job
job = client.classify.create(
file_input=file_obj.id,
configuration={"rules": rules, "mode": "FAST"},
)
# Poll until complete
status = client.classify.get(job.id)
while status.status in ("PENDING", "RUNNING"):
time.sleep(2)
status = client.classify.get(job.id)
if status.result:
print(f"Classification Result: {status.result.type}")
print(f"Classification Reason: {status.result.reasoning}")import fs from 'fs';
const fileObj = await client.files.create({
file: fs.createReadStream('CybergyHoldingsInc_Affliate Agreement.pdf'),
purpose: "classify",
});
// Create a classify job
let job = await client.classify.create({
file_input: fileObj.id,
configuration: { rules, mode: 'FAST' },
});
// Poll until complete
while (job.status === 'PENDING' || job.status === 'RUNNING') {
await new Promise((r) => setTimeout(r, 2000));
job = await client.classify.get(job.id);
}
if (job.result) {
console.log("Classification Result: " + job.result.type);
console.log("Classification Reason: " + job.result.reasoning);
}// Upload a file
f, err := os.Open("CybergyHoldingsInc_Affliate Agreement.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: rules,
Mode: llamacloud.ClassifyConfigurationModeFast,
},
},
})
if err != nil {
log.Fatal(err)
}
// Poll until complete
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() {
fmt.Println("Classification Result: " + result.Result.Type)
fmt.Println("Classification Reason: " + result.Result.Reasoning)
}// Upload a file
FileCreateResponse fileObj = client.files().create(
FileCreateParams.builder()
.file(Paths.get("CybergyHoldingsInc_Affliate Agreement.pdf"))
.purpose("classify")
.build());
// Create a classify job
ClassifyCreateResponse job = client.classify().create(
ClassifyCreateRequest.builder()
.fileInput(fileObj.id())
.configuration(ClassifyConfiguration.builder()
.rules(rules)
.mode(ClassifyConfiguration.Mode.FAST)
.build())
.build());
// Poll until complete
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 Result: " + result.result().get().type().orElse(""));
System.out.println("Classification Reason: " + result.result().get().reasoning());
}终端窗口
# Upload a file
FILE_ID=$(llp files create --file "CybergyHoldingsInc_Affliate Agreement.pdf" --purpose classify | jq -r '.id')
# Create a classify job
JOB_ID=$(llp classify create \
--file-input "$FILE_ID" \
--configuration "{rules: $RULES, mode: FAST}" \
| jq -r '.id')
# Poll until complete
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 "Classification Result: \(.result.type)", "Classification Reason: \(.result.reasoning)"
else "Classification failed: \(.error_message // .)" end'分类完成后,结果里会给出预测的合同类型与模型的推理过程。例如:
Classification Result: affiliate_agreements
Classification Reason: The document is titled 'MARKETING AFFILIATE AGREEMENT' and repeatedly refers to one party as the 'Marketing Affiliate.' The agreement outlines the rights and obligations of the 'Marketing Affiliate' (MA) to market, sell, and support certain technology products, and details the relationship between the company and the affiliate. There is no mention of joint branding, shared trademarks, or collaborative marketing under both parties' brands, which would be indicative of a co-branding agreement. The content is entirely consistent with an affiliate agreement, where one party (the affiliate) is authorized to market and sell the products of another company, rather than a co-branding arrangement. Therefore, the best match is 'affiliate_agreements' with very high confidence.