DEV Community

Cover image for Cách sử dụng OpenAI Batch API
Sebastian Petrus
Sebastian Petrus

Posted on • Originally published at apidog.com

Cách sử dụng OpenAI Batch API

Khi hoàn thành hướng dẫn này, bạn sẽ biết cách gọi Batch API của OpenAI để chạy hàng nghìn yêu cầu mô hình dưới dạng một tác vụ bất đồng bộ, nhận kết quả trong một tệp đầu ra và tiết kiệm 50% chi phí token. Quy trình gồm: tạo tệp JSONL, tải tệp lên, tạo batch, thăm dò trạng thái, tải kết quả và kiểm tra từng bước trong Apidog trước khi đưa vào production. Nếu use case của bạn cần phản hồi tức thì, hãy dùng API đồng bộ và tham khảo cách kiểm tra ChatGPT API bằng Apidog.

Dùng thử Apidog ngay hôm nay

Batch API là gì và khi nào nên dùng?

Batch API là endpoint bất đồng bộ cho các workload lớn nhưng không yêu cầu phản hồi ngay. Thay vì gửi từng HTTP request cho từng prompt, bạn gom nhiều request vào một tệp JSONL, upload tệp đó, tạo một batch job và thăm dò cho đến khi job hoàn tất.

Batch API phù hợp khi bạn có dữ liệu lớn cần xử lý offline:

  • Phân loại hoặc gắn thẻ dữ liệu tồn đọng
  • Tạo embeddings cho toàn bộ dataset
  • Tạo nội dung hàng loạt như mô tả sản phẩm, tóm tắt, bản dịch
  • Chạy bộ đánh giá hoặc so sánh model trên nhiều mẫu
  • Backfill dữ liệu bằng LLM

Đổi lại, bạn phải chấp nhận độ trễ. OpenAI cam kết batch hoàn thành trong vòng 24 giờ. Nhiều job có thể xong sớm hơn, nhưng hệ thống của bạn nên thiết kế theo giới hạn 24 giờ.

Không dùng Batch API cho các luồng mà người dùng đang chờ phản hồi, ví dụ:

  • Chat UI
  • Autocomplete
  • Agent tương tác trực tiếp
  • API request nằm trên critical path của sản phẩm

Nếu bạn đang tạo nhiều cấu hình model hoặc agent cùng lúc, batch là lựa chọn phù hợp. Bạn có thể xem thêm hướng dẫn tạo hơn 100 cấu hình tác nhân bằng xử lý hàng loạt.

Tổng quan quy trình

Batch API thường đi qua 4 bước chính với hai nhóm endpoint: /v1/files/v1/batches.

Bước Endpoint Mục đích
1. Upload POST /v1/files Upload tệp .jsonl với purpose: "batch" và nhận file_id
2. Tạo batch POST /v1/batches Tạo batch job từ input_file_id
3. Thăm dò GET /v1/batches/{id} Kiểm tra status cho đến khi completed
4. Tải kết quả GET /v1/files/{id}/content Tải output bằng output_file_id

Bạn cần chuẩn bị:

  • OpenAI API key, export dưới biến môi trường OPENAI_API_KEY
  • Một tệp JSONL chứa các request
  • Công cụ để gửi request và kiểm tra response, ví dụ Apidog hoặc curl

Bước 1: Tạo tệp JSONL cho batch

Đầu vào của Batch API là tệp JSONL. Mỗi dòng là một request độc lập.

Mỗi dòng cần có 4 trường:

  • custom_id: ID do bạn tự đặt để map kết quả về input gốc
  • method: thường là POST
  • url: endpoint đích, ví dụ /v1/chat/completions
  • body: payload thực tế gửi đến model

Ví dụ requests.jsonl:

{"custom_id": "req-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "Classify the sentiment of: 'shipping was slow but the product is great'"}]}}
{"custom_id": "req-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "gpt-4.1-mini", "messages": [{"role": "user", "content": "Classify the sentiment of: 'returned it the same day'"}]}}
Enter fullscreen mode Exit fullscreen mode

custom_id phải là duy nhất trong tệp. Output không đảm bảo giữ nguyên thứ tự dòng input, nên bạn phải dùng custom_id để ghép kết quả về bản ghi ban đầu.

Một batch có thể chứa tối đa 50.000 request và tệp input có thể lên tới 200 MB.

Kiểm tra nhanh JSONL trước khi upload

Trước khi gửi lên OpenAI, nên validate từng dòng để tránh batch fail ở bước xác thực.

Ví dụ kiểm tra JSONL bằng Node.js:

import fs from "node:fs";
import readline from "node:readline";

const file = readline.createInterface({
  input: fs.createReadStream("requests.jsonl"),
  crlfDelay: Infinity,
});

const ids = new Set();
let lineNumber = 0;

for await (const line of file) {
  lineNumber++;

  let item;
  try {
    item = JSON.parse(line);
  } catch {
    throw new Error(`Dòng ${lineNumber} không phải JSON hợp lệ`);
  }

  for (const field of ["custom_id", "method", "url", "body"]) {
    if (!item[field]) {
      throw new Error(`Dòng ${lineNumber} thiếu trường ${field}`);
    }
  }

  if (ids.has(item.custom_id)) {
    throw new Error(`custom_id bị trùng: ${item.custom_id}`);
  }

  ids.add(item.custom_id);

  if (item.method !== "POST") {
    throw new Error(`Dòng ${lineNumber}: method phải là POST`);
  }
}

console.log(`JSONL hợp lệ. Tổng số dòng: ${lineNumber}`);
Enter fullscreen mode Exit fullscreen mode

Bước 2: Upload tệp JSONL

Upload tệp qua Files API với purpose="batch":

curl https://api.openai.com/v1/files \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -F purpose="batch" \
  -F file="@requests.jsonl"
Enter fullscreen mode Exit fullscreen mode

Response sẽ có dạng:

{
  "id": "file-abc123",
  "object": "file",
  "purpose": "batch",
  "filename": "requests.jsonl"
}
Enter fullscreen mode Exit fullscreen mode

Lưu lại id. Đây là input_file_id dùng để tạo batch ở bước tiếp theo.

Bước 3: Tạo batch job

Gửi input_file_id, endpoint đích và completion_window.

Hiện tại completion_window nhận giá trị "24h".

curl https://api.openai.com/v1/batches \
  -H "Authorization: Bearer $OPENAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "input_file_id": "file-abc123",
    "endpoint": "/v1/chat/completions",
    "completion_window": "24h",
    "metadata": {
      "job": "sentiment-backfill"
    }
  }'
Enter fullscreen mode Exit fullscreen mode

Lưu ý: endpoint trong request tạo batch phải khớp với trường url trong từng dòng JSONL.

Các endpoint được hỗ trợ gồm:

  • /v1/chat/completions
  • /v1/responses
  • /v1/embeddings
  • /v1/completions
  • /v1/moderations
  • Và các endpoint khác được OpenAI hỗ trợ theo thời gian

Response trả về một batch object:

{
  "id": "batch_abc123",
  "object": "batch",
  "endpoint": "/v1/chat/completions",
  "input_file_id": "file-abc123",
  "completion_window": "24h",
  "status": "validating",
  "output_file_id": null,
  "error_file_id": null,
  "request_counts": {
    "total": 0,
    "completed": 0,
    "failed": 0
  },
  "created_at": 1733452800,
  "metadata": {
    "job": "sentiment-backfill"
  }
}
Enter fullscreen mode Exit fullscreen mode

Các trường quan trọng cần lưu:

  • id: batch ID để thăm dò
  • status: trạng thái hiện tại
  • output_file_id: file kết quả khi batch hoàn tất
  • error_file_id: file lỗi nếu có request thất bại
  • request_counts: tiến độ xử lý

Bước 4: Thăm dò trạng thái batch

Gọi endpoint sau để kiểm tra trạng thái:

curl https://api.openai.com/v1/batches/batch_abc123 \
  -H "Authorization: Bearer $OPENAI_API_KEY"
Enter fullscreen mode Exit fullscreen mode

Các trạng thái phổ biến:

Trạng thái Ý nghĩa
validating File input đang được kiểm tra
in_progress Các request đang được xử lý
finalizing Batch đã chạy xong, output file đang được chuẩn bị
completed Hoàn tất, có thể tải kết quả
failed Xác thực thất bại, không request nào được chạy
expired Quá 24 giờ trước khi hoàn tất toàn bộ
cancelling / cancelled Batch đang được hủy hoặc đã hủy

Không có webhook cho luồng này, vì vậy bạn cần polling. Không nên polling mỗi giây. Với workload batch, khoảng vài phút/lần thường hợp lý hơn.

Ví dụ script polling đơn giản bằng Bash:

BATCH_ID="batch_abc123"

while true; do
  RESPONSE=$(curl -s https://api.openai.com/v1/batches/$BATCH_ID \
    -H "Authorization: Bearer $OPENAI_API_KEY")

  STATUS=$(echo "$RESPONSE" | jq -r '.status')
  echo "Batch status: $STATUS"

  if [ "$STATUS" = "completed" ]; then
    echo "$RESPONSE" | jq .
    break
  fi

  if [ "$STATUS" = "failed" ] || [ "$STATUS" = "expired" ] || [ "$STATUS" = "cancelled" ]; then
    echo "$RESPONSE" | jq .
    exit 1
  fi

  sleep 180
done
Enter fullscreen mode Exit fullscreen mode

Nếu gửi nhầm batch, bạn có thể hủy:

curl -X POST https://api.openai.com/v1/batches/batch_abc123/cancel \
  -H "Authorization: Bearer $OPENAI_API_KEY"
Enter fullscreen mode Exit fullscreen mode

Bước 5: Tải output file

Khi statuscompleted, batch object sẽ có output_file_id.

Ví dụ:

{
  "status": "completed",
  "output_file_id": "file-output456",
  "error_file_id": "file-error789"
}
Enter fullscreen mode Exit fullscreen mode

Tải output:

curl https://api.openai.com/v1/files/file-output456/content \
  -H "Authorization: Bearer $OPENAI_API_KEY" > results.jsonl
Enter fullscreen mode Exit fullscreen mode

Output cũng là JSONL, mỗi dòng tương ứng với một request đã xử lý. Mỗi dòng chứa custom_idresponse.

Ví dụ:

{"custom_id":"req-1","response":{"status_code":200,"body":{"choices":[{"message":{"content":"mixed positive"}}]}}}
{"custom_id":"req-2","response":{"status_code":200,"body":{"choices":[{"message":{"content":"negative"}}]}}}
Enter fullscreen mode Exit fullscreen mode

Nếu có error_file_id, hãy tải cả file lỗi:

curl https://api.openai.com/v1/files/file-error789/content \
  -H "Authorization: Bearer $OPENAI_API_KEY" > errors.jsonl
Enter fullscreen mode Exit fullscreen mode

Luôn ghép kết quả bằng custom_id, không dựa vào thứ tự dòng.

Ví dụ parse kết quả bằng Node.js

Sau khi tải results.jsonl, bạn có thể parse và map kết quả về input ban đầu:

import fs from "node:fs";
import readline from "node:readline";

const results = new Map();

const file = readline.createInterface({
  input: fs.createReadStream("results.jsonl"),
  crlfDelay: Infinity,
});

for await (const line of file) {
  const item = JSON.parse(line);

  results.set(item.custom_id, {
    statusCode: item.response?.status_code,
    body: item.response?.body,
  });
}

console.log(results.get("req-1"));
Enter fullscreen mode Exit fullscreen mode

Nếu bạn cần merge với dữ liệu input gốc, hãy lưu custom_id cùng ID bản ghi trong database trước khi tạo JSONL.

Ví dụ:

{
  "custom_id": "product-9832",
  "record_id": 9832
}
Enter fullscreen mode Exit fullscreen mode

Sau khi có output, dùng custom_id để update đúng bản ghi.

Lưu ý về chi phí và thời gian xử lý

Batch API có đánh đổi rõ ràng:

  • Bạn tiết kiệm 50% chi phí token đầu vào và đầu ra.
  • Bạn chấp nhận thời gian xử lý tối đa 24 giờ.
  • Batch dùng nhóm giới hạn tốc độ riêng, không cạnh tranh trực tiếp với traffic đồng bộ.
  • Nếu batch expired, các request đã hoàn thành vẫn được trả về và tính phí; phần còn lại thì không.

Vì vậy, Batch API phù hợp cho:

  • Job chạy ban đêm
  • Backfill dữ liệu
  • Xử lý dataset định kỳ
  • Tác vụ không cần phản hồi real-time

Không phù hợp cho:

  • API request đang chờ trả response cho user
  • Tính năng tương tác trong UI
  • Luồng cần retry hoặc điều phối tức thì

Nếu bạn đang gặp giới hạn tốc độ với API đồng bộ, xem thêm hướng dẫn về giới hạn tốc độ GPT API và cách kiểm tra chúng.

Để phân bổ chi phí theo feature hoặc job, hãy dùng metadata khi tạo batch:

{
  "metadata": {
    "feature": "product-description",
    "env": "production",
    "run": "2025-01-nightly"
  }
}
Enter fullscreen mode Exit fullscreen mode

Bạn cũng có thể tham khảo hướng dẫn phân bổ chi phí cho chi tiêu OpenAI.

Cách kiểm tra Batch API trong Apidog

Batch API dễ lỗi hơn một request chat đơn lẻ vì lỗi có thể nằm ở nhiều lớp:

  • JSONL sai format
  • Thiếu trường trong từng dòng
  • endpoint không khớp với url
  • File upload sai purpose
  • Batch fail ở bước validating
  • Output đến sau nên logic tải kết quả khó kiểm tra ngay

Bạn nên kiểm tra thủ công toàn bộ lifecycle trước khi tự động hóa.

1. Tạo request upload file

Trong Apidog, tạo request:

POST https://api.openai.com/v1/files
Enter fullscreen mode Exit fullscreen mode

Headers:

Authorization: Bearer {{OPENAI_API_KEY}}
Enter fullscreen mode Exit fullscreen mode

Body dạng multipart/form-data:

Key Value
purpose batch
file requests.jsonl

Sau khi gửi, lưu id trả về vào environment variable, ví dụ:

INPUT_FILE_ID=file-abc123
Enter fullscreen mode Exit fullscreen mode

2. Tạo request tạo batch

Tạo request:

POST https://api.openai.com/v1/batches
Enter fullscreen mode Exit fullscreen mode

Headers:

Authorization: Bearer {{OPENAI_API_KEY}}
Content-Type: application/json
Enter fullscreen mode Exit fullscreen mode

Body:

{
  "input_file_id": "{{INPUT_FILE_ID}}",
  "endpoint": "/v1/chat/completions",
  "completion_window": "24h",
  "metadata": {
    "job": "sentiment-backfill"
  }
}
Enter fullscreen mode Exit fullscreen mode

Kiểm tra response:

  • status phải là validating
  • endpoint phải khớp /v1/chat/completions
  • input_file_id phải đúng file vừa upload

Lưu id của batch vào biến:

BATCH_ID=batch_abc123
Enter fullscreen mode Exit fullscreen mode

3. Tạo request thăm dò batch

Tạo request:

GET https://api.openai.com/v1/batches/{{BATCH_ID}}
Enter fullscreen mode Exit fullscreen mode

Theo dõi các trường:

  • status
  • request_counts.total
  • request_counts.completed
  • request_counts.failed
  • output_file_id
  • error_file_id

Khi statuscompleted, lưu output_file_id.

4. Tải output file

Tạo request:

GET https://api.openai.com/v1/files/{{OUTPUT_FILE_ID}}/content
Enter fullscreen mode Exit fullscreen mode

Response là JSONL. Tải về và parse theo custom_id.

5. Kiểm tra đường lỗi và hủy batch

Đừng chỉ test happy path. Nên tạo một file JSONL cố tình sai, ví dụ thiếu body, để xác nhận batch trả về failed.

Bạn cũng nên test endpoint hủy:

POST https://api.openai.com/v1/batches/{{BATCH_ID}}/cancel
Enter fullscreen mode Exit fullscreen mode

Việc này giúp code xử lý lỗi của bạn dựa trên response thật, không phải giả định.

Vì output có thể đến sau nhiều giờ, bạn có thể dựng API giả trả về một batch object mẫu ở trạng thái completed và một file kết quả dựng sẵn. Cách này giúp bạn kiểm tra logic tải và parse output mà không cần chờ job thật hoặc tốn token trong giai đoạn phát triển.

Nếu nhóm của bạn làm việc theo hướng specification-first, bạn cũng có thể tạo bộ sưu tập kiểm tra trực tiếp từ đặc tả OpenAPI để đưa các endpoint batch vào CI.

FAQ

Một batch mất bao lâu?

OpenAI cam kết hoàn thành trong vòng 24 giờ. Nhiều batch có thể xong sớm hơn, nhưng hệ thống của bạn nên xử lý theo giới hạn 24 giờ. Nếu quá thời gian, batch chuyển sang expired; các request đã hoàn thành vẫn được trả về và tính phí.

Batch API giảm giá bao nhiêu?

Batch API giảm 50% so với endpoint đồng bộ cho cả input token và output token. Nếu cần phân bổ chi phí theo feature hoặc job, hãy dùng metadata và tham khảo hướng dẫn phân bổ chi phí.

Có thể chạy endpoint nào trong batch?

Bạn đặt endpoint trong cả url của từng dòng JSONL và trường endpoint khi tạo batch. Hai giá trị này phải khớp nhau.

Các endpoint được hỗ trợ gồm /v1/chat/completions, /v1/responses, /v1/embeddings, /v1/completions, /v1/moderations, cùng các endpoint hình ảnh và video được OpenAI hỗ trợ. Hãy kiểm tra tài liệu OpenAI hiện tại để có danh sách đầy đủ.

Vì sao output không theo thứ tự input?

Output JSONL không đảm bảo giữ thứ tự dòng như input. Đây là lý do mỗi request cần một custom_id duy nhất. Khi xử lý kết quả, luôn join bằng custom_id, không join bằng số dòng.

Kết luận

Batch API phù hợp cho các workload OpenAI lớn, offline và có thể chờ tới 24 giờ. Quy trình triển khai gồm: tạo JSONL, upload file, tạo batch, polling trạng thái, tải output và xử lý kết quả theo custom_id.

Trước khi tự động hóa, hãy chạy thủ công toàn bộ lifecycle để bắt lỗi sớm ở JSONL, upload, tạo batch, polling, hủy và tải output. Tải xuống Apidog để kiểm tra các endpoint này, xác nhận response object và tránh mất một vòng chờ 24 giờ chỉ vì một dòng JSONL sai định dạng.

Top comments (0)