从写代码,到创作下一幕

探索 字节跳动 - 火山方舟 的 AI 编程与视频创作活动。

火山方舟 Agent Plan 与 Coding Plan 活动,价格 ¥9.9 起

Agent Plan & Coding Plan

一站体验多款热门模型,为 AI 编程与智能体开发提供更多选择。新用户可联系(微信: goo_lvyouyou)免费体验 9.9 agent plan。

查看套餐优惠
Seedance 2.5 视频创作活动:30 秒视频、多模态参考、局部编辑

Seedance 2.5

让创意,跃然成片。探索 30 秒视频、多模态参考与局部编辑,把脑海中的画面变成下一支作品。

探索视频创作

高级 API 用法

Batch API

查看 Markdown

Batch API 让你能以更低的价格和更高的速率限制异步处理大量请求。价格详情请参阅 Batch API 价格。如果实时请求需要更低延迟,请参阅Priority Processing。

什么是 Batch API?

发起标准 Grok API 调用时,你会发送请求并等待即时响应。这种方式非常适合聊天机器人、实时助手等交互式应用,以及任何用户正在等待响应的场景。

Batch API 采用不同的方式:请求不会立即处理,而是提交到队列并在后台执行。你不会立刻收到响应,而是在稍后获取结果。

与实时 API 请求的主要区别:

实时 APIBatch API
响应时间即时(秒级)通常在 24 小时内*
成本标准定价折扣定价(查看详情)
速率限制受每分钟限制请求不计入速率限制
使用场景交互式、实时后台处理、批量任务

* 处理时间: 大多数 batch 请求会在 24 小时内完成,但处理时间可能因系统负载和 batch 大小而异。完成时间为尽力而为,不作保证。


何时使用 Batch API

如果无需立即获得结果,Batch API 可帮你降低 API 成本:

  • 运行评测和基准测试 - 使用数千个 prompt 测试模型表现

  • 处理大型数据集 - 分析客户反馈、分类支持工单、提取实体

  • 大规模内容审核 - 审核积压的用户生成内容

  • 文档摘要 - 批量处理报告、研究论文或法律文档

  • 数据增强管道 - 为数据库记录添加 AI 生成的洞察

  • 计划的夜间任务 - 生成日报或为仪表板准备数据


工作原理

Batch API 工作流程包含四个主要步骤:

  1. 创建 batch - batch 是将相关请求归为一组的容器

  2. 添加请求 - 将推理请求提交到 batch 队列

  3. 监控进度 - 轮询 Batch 状态以追踪完成情况

  4. 获取结果 - 获取所有已处理请求的响应

下面逐步介绍。


步骤 1:创建 Batch

batch 是请求的容器,可将其理解为归集相关工作的文件夹。你可以针对不同数据集、实验或任务类型分别创建 batch。

创建 batch 后会收到 batch_id,用于添加请求和获取结果。

curl -X POST https://api.x.ai/v1/batches \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
    "name": "customer_feedback_analysis"
  }'

步骤 2:向 batch 添加请求

创建 batch 后即可向其中添加请求。每个请求都会异步处理。

使用 xAI SDK 时,先根据各个请求的类型调用相应方法构建请求,再将它们组成列表传入:

请求类型SDK 方法
文本chat.create()
图像image.prepare()
视频video.prepare()
视频扩展video.prepare_extension()

你也可以上传 JSONL 文件。

重要: 为每个请求分配唯一的 batch_request_id。

  • 使用此 ID 可以将结果与原始请求对应起来,在处理数百或数千条数据时尤为重要。

  • 如果未提供 ID,系统会为你生成 UUID。

  • 自定义 ID 有助于实现幂等性,确保请求只被处理一次。

  • 你还可以用它将批处理请求关联到自己系统中的记录。

curl -X POST https://api.x.ai/v1/batches/{batch_id}/requests \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
    "batch_requests": [
      {
        "batch_request_id": "feedback_001",
        "batch_request": {
          "responses": {
            "input": [
              {"role": "system", "content": "Classify the sentiment as positive, negative, or neutral."},
              {"role": "user", "content": "The product exceeded my expectations!"}
            ],
            "model": "grok-4.3"
          }
        }
      },
      {
        "batch_request_id": "feedback_002",
        "batch_request": {
          "responses": {
            "input": [
              {"role": "system", "content": "Classify the sentiment as positive, negative, or neutral."},
              {"role": "user", "content": "Shipping took way too long."}
            ],
            "model": "grok-4.3"
          }
        }
      }
    ]
  }'

步骤 3:监控 batch 进度

添加请求后,它们会开始在后台处理。由于 batch 处理是异步的,需要轮询 batch 状态才能知道结果何时就绪。

batch 状态包含待处理、成功和失败请求的计数器。请定期轮询,直到 num_pending 变为 0,表示所有请求均已处理完成(成功或出错)。

# Check batch status
curl https://api.x.ai/v1/batches/{batch_id} \\
  -H "Authorization: Bearer $XAI_API_KEY"

# Response includes state with request counts:
# {
#   "state": {
#     "num_requests": 100,
#     "num_pending": 25,
#     "num_success": 70,
#     "num_error": 5
#   }
# }

理解 batch 状态

Batch API 在两个层级追踪状态:batch 层级和单个请求层级。

batch 层级状态汇总了批次中所有请求的进度,记录在 batch.state 对象中。要获取该对象,请调用 client.batch.get() 方法:

计数器说明
num_requests添加到 Batch 的请求总数
num_pending等待处理的请求
num_success成功完成的请求
num_error因错误失败的请求
num_cancelled已取消的请求

当 num_pending 变为 0 时,所有请求都已处理完毕(成功、出错或取消)。

单个请求状态说明各请求所处的生命周期阶段,记录在 batch_request_metadata 对象中。要获取该对象,请调用 client.batch.list_batch_requests() 方法:

状态说明
pending请求已加入队列,等待处理
succeeded请求成功完成,结果可用
failed请求在处理过程中遇到错误
cancelled请求已取消(例如 Batch 在该请求处理前被取消)

batch 生命周期: batch 也可以被取消或过期。如果取消 batch,待处理请求将不再处理,但已完成的结果仍然可用。batch 设有过期时间,过期后结果将无法访问;获取 batch 详情时请检查 expires_at 字段。


步骤 4:获取结果

可以随时获取结果,即使整个 batch 尚未完成。单个请求完成处理后结果即可使用,因此可以在其他请求仍在处理时开始使用已完成的结果。

每个结果都通过先前分配的 batch_request_id 关联到原始请求。请根据请求类型,从相应的属性中读取响应:

请求类型属性字段
聊天补全result.response.content、.usage、.finish_reason等
图像result.image_response.url、.base64、.usage、.model
视频result.video_response.url、.duration、.usage、.model

这些响应类型与常规的 client.image.sample() 和 client.video.generate() 方法返回的类型相同。

SDK 提供方便的 .succeeded 和 .failed 属性,用于区分成功响应和错误。

分页: 结果按页返回。使用 limit 参数控制页面大小,并使用 pagination_token 获取后续页面。当 pagination_token 为 None 时,表示已经到达末尾。

# Fetch first page
curl "https://api.x.ai/v1/batches/{batch_id}/results?limit=100" \\
  -H "Authorization: Bearer $XAI_API_KEY"

# Use pagination_token from response to fetch next page
curl "https://api.x.ai/v1/batches/{batch_id}/results?limit=100&pagination_token={token}" \\
  -H "Authorization: Bearer $XAI_API_KEY"

其他操作

除核心 workflow 外,Batch API 还提供管理 batch 的其他操作。

取消 Batch

可以在所有请求完成前取消 batch。已处理请求的结果仍然可用,但待处理请求不会继续处理。无法向已取消的 batch 添加更多请求。

curl -X POST https://api.x.ai/v1/batches/{batch_id}:cancel \\
  -H "Authorization: Bearer $XAI_API_KEY"

列出所有 Batch

查看团队的所有 batch。batch 会保留到过期为止(请检查 expires_at 字段)。该 endpoint 支持相同的 limit 和 pagination_token 参数,可对大型列表分页。

curl "https://api.x.ai/v1/batches?limit=20" \\
  -H "Authorization: Bearer $XAI_API_KEY"

检查单个请求状态

如需详细追踪,可以检查 batch 中每个请求的元数据,其中显示单个请求的状态、计时和其他详情。该 endpoint 支持相同的 limit 和 pagination_token 参数,可对大型 batch 分页。

curl "https://api.x.ai/v1/batches/{batch_id}/requests?limit=50" \\
  -H "Authorization: Bearer $XAI_API_KEY"

追踪成本

每个 batch 都会追踪总处理成本。处理完成后可查看成本明细以了解支出。价格详情请参阅 价格页面中的 Batch API 价格。

# Get batch with cost information
curl -s "https://api.x.ai/v1/batches/{batch_id}/results?limit=100" \\
  -H "Authorization: Bearer $XAI_API_KEY"

# Cost per result can be found on response.results[].batch_result.response.chat_get_completion.usage.cost_in_usd_ticks
# Cost is returned in ticks (1e-10 USD) for precision

完整示例

此端到端示例演示了真实的 batch workflow:大规模分析客户反馈。它会创建 batch、提交反馈项目进行情感分析、等待处理并输出结果。为简化示例,这里不对结果分页;处理更大的 batch 时,请参阅 步骤 4了解分页。

JavaScript

const BASE_URL = "https://api.x.ai/v1";
const headers = { "Content-Type": "application/json", Authorization: \`Bearer \${process.env.XAI_API_KEY}\` };

// Sample dataset: customer feedback to analyze
const feedbackData = [
  { id: "fb_001", text: "Absolutely love this product! Best purchase ever." },
  { id: "fb_002", text: "Delivery was late and the packaging was damaged." },
  { id: "fb_003", text: "Works fine, nothing special to report." },
  { id: "fb_004", text: "Customer support was incredibly helpful!" },
  { id: "fb_005", text: "The app keeps crashing on my phone." },
];

// Step 1: Create a batch
console.log("Creating batch...");
const batchRes = await fetch(\`\${BASE_URL}/batches\`, {
  method: "POST",
  headers,
  body: JSON.stringify({ name: "feedback_sentiment_analysis" }),
});
const batch = await batchRes.json();
const batchId = batch.batch_id;
console.log(\`Batch created: \${batchId}\`);

// Step 2: Build and add requests
console.log("\\nAdding requests...");
const response = await fetch(\`\${BASE_URL}/batches/\${batchId}/requests\`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    batch_requests: feedbackData.map((item) => ({
      batch_request_id: item.id,
      batch_request: {
        chat_get_completion: {
          model: "grok-4.3",
          messages: [
            {
              role: "system",
              content: "Analyze the sentiment of the customer feedback. Respond with exactly one word: positive, negative, or neutral.",
            },
            { role: "user", content: item.text },
          ],
        },
      },
    })),
  }),
});
if (!response.ok) throw new Error(\`Failed to add requests: \${await response.text()}\`);
console.log(\`Added \${feedbackData.length} requests\`);

// Step 3: Wait for completion
console.log("\\nProcessing...");
const interval = setInterval(async () => {
  const statusRes = await fetch(\`\${BASE_URL}/batches/\${batchId}\`, { headers });
  const status = await statusRes.json();
  const { num_pending, num_success, num_error, num_requests } = status.state;
  console.log(\`  \${num_success + num_error}/\${num_requests} complete\`);

  if (num_requests > 0 && num_pending === 0) {
    clearInterval(interval);

    // Step 4: Retrieve and display results
    console.log("\\n--- Results ---");
    const resultsRes = await fetch(\`\${BASE_URL}/batches/\${batchId}/results?limit=100\`, { headers });
    const { results } = await resultsRes.json();

    // Create a lookup for original feedback text
    const feedbackLookup = Object.fromEntries(feedbackData.map((item) => [item.id, item.text]));

    const succeeded = results.filter((r) => r.batch_result?.response?.chat_get_completion);
    const failed = results.filter((r) => !r.batch_result?.response?.chat_get_completion);

    for (const result of succeeded) {
      const originalText = feedbackLookup[result.batch_request_id] ?? "";
      const sentiment = result.batch_result.response.chat_get_completion.choices[0].message.content.trim().toLowerCase();
      console.log(\`[\${sentiment.toUpperCase()}] \${originalText.slice(0, 50)}...\`);
    }

    // Report any failures
    if (failed.length > 0) {
      console.log("\\n--- Errors ---");
      for (const result of failed) {
        console.log(\`[\${result.batch_request_id}] \${result.error_message}\`);
      }
    }

    // Display cost
    let totalTicks = 0;
    for (const r of results) {
      totalTicks += r.batch_result?.response?.chat_get_completion?.usage?.cost_in_usd_ticks ?? 0;
    }
    console.log(\`\\nTotal cost: $\${(totalTicks / 1e10).toFixed(4)}\`);
  }
}, 2000);

Python

import time
from xai_sdk import Client
from xai_sdk.chat import system, user

client = Client()

# Sample dataset: customer feedback to analyze
feedback_data = [
    {"id": "fb_001", "text": "Absolutely love this product! Best purchase ever."},
    {"id": "fb_002", "text": "Delivery was late and the packaging was damaged."},
    {"id": "fb_003", "text": "Works fine, nothing special to report."},
    {"id": "fb_004", "text": "Customer support was incredibly helpful!"},
    {"id": "fb_005", "text": "The app keeps crashing on my phone."},
]

# Step 1: Create a batch
print("Creating batch...")
batch = client.batch.create(batch_name="feedback_sentiment_analysis")
print(f"Batch created: {batch.batch_id}")

# Step 2: Build and add requests
print("\\nAdding requests...")
batch_requests = []
for item in feedback_data:
    chat = client.chat.create(
        model="grok-4.3",
        batch_request_id=item["id"],
    )
    chat.append(system(
        "Analyze the sentiment of the customer feedback. "
        "Respond with exactly one word: positive, negative, or neutral."
    ))
    chat.append(user(item["text"]))
    batch_requests.append(chat)

client.batch.add(batch_id=batch.batch_id, batch_requests=batch_requests)
print(f"Added {len(batch_requests)} requests")

# Step 3: Wait for completion
print("\\nProcessing...")
while True:
    batch = client.batch.get(batch_id=batch.batch_id)
    pending = batch.state.num_pending
    completed = batch.state.num_success + batch.state.num_error
    
    print(f"  {completed}/{batch.state.num_requests} complete")
    
    if pending == 0:
        break
    time.sleep(2)

# Step 4: Retrieve and display results
print("\\n--- Results ---")
results = client.batch.list_batch_results(batch_id=batch.batch_id)

# Create a lookup for original feedback text
feedback_lookup = {item["id"]: item["text"] for item in feedback_data}

for result in results.succeeded:
    original_text = feedback_lookup.get(result.batch_request_id, "")
    sentiment = result.response.content.strip().lower()
    print(f"[{sentiment.upper()}] {original_text[:50]}...")

# Report any failures
if results.failed:
    print("\\n--- Errors ---")
    for result in results.failed:
        print(f"[{result.batch_request_id}] {result.error_message}")

# Display cost
cost_usd = batch.cost_breakdown.total_cost_usd_ticks / 1e10
print("\\nTotal cost: $%.4f" % cost_usd)

上传 JSONL 文件

除了通过 SDK 添加请求,还可以上传 JSONL 文件来创建 batch。通过脚本、管道或外部工具生成请求时,这种方式很实用。

文件的每一行都是一个 JSON 对象,包含四个字段:

字段说明
custom_id唯一标识符,对应 batch_request_id。
method始终为 "POST"。
urlAPI 端点路径。
bodyJSON 请求体,格式遵循REST API 参考中对应端点的定义。

JSON

{"custom_id": "chat-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "grok-4.3", "messages": [{"role": "user", "content": "Classify this as positive, negative, or neutral: The product exceeded my expectations!"}]}}
{"custom_id": "search-1", "method": "POST", "url": "/v1/responses", "body": {"model": "grok-4.3", "tools": [{"type": "web_search"}, {"type": "x_search"}], "input": [{"role": "user", "content": "What are the latest SpaceX launches?"}]}}
{"custom_id": "mcp-1", "method": "POST", "url": "/v1/responses", "body": {"model": "grok-4.3", "tools": [{"type": "mcp", "server_label": "deepwiki", "server_url": "https://mcp.deepwiki.com/mcp"}], "input": [{"role": "user", "content": "What does the xai-sdk-python repo do?"}]}}
{"custom_id": "img-1", "method": "POST", "url": "/v1/images/generations", "body": {"model": "grok-imagine-image-2.0", "prompt": "A futuristic city skyline at sunset"}}
{"custom_id": "img-edit-1", "method": "POST", "url": "/v1/images/edits", "body": {"model": "grok-imagine-image-2.0", "prompt": "Add a rainbow", "image": {"url": "https://picsum.photos/800"}}}
{"custom_id": "vid-1", "method": "POST", "url": "/v1/videos/generations", "body": {"model": "grok-imagine-video-1.5", "prompt": "A rocket launching from Mars", "duration": 8}}
{"custom_id": "vid-edit-1", "method": "POST", "url": "/v1/videos/edits", "body": {"model": "grok-imagine-video", "prompt": "Make it slow motion", "video": {"url": "https://lorem.video/cat_360p_3s"}}}
{"custom_id": "vid-ext-1", "method": "POST", "url": "/v1/videos/extensions", "body": {"model": "grok-imagine-video", "prompt": "The camera slowly pans to reveal a sunset", "video": {"url": "https://lorem.video/cat_360p_3s"}, "duration": 6}}

同一文件中可以混用不同 endpoint。每个请求都会独立路由。

支持的 url 值:

URL说明
/v1/chat/completions聊天补全
/v1/responses模型响应
/v1/images/generations图像生成
/v1/images/edits图像编辑
/v1/videos/generations 或 /v1/videos视频生成
/v1/videos/edits视频编辑
/v1/videos/extensions视频扩展

仅接受启用了 batch 的模型。最新信息请参阅对应的模型页面。不支持批处理的模型会被拒绝,错误信息为 not supported for batch processing。

通过 Files API上传文件,然后创建引用该文件的 batch:

# Upload the JSONL file
curl -X POST https://api.x.ai/v1/files \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -F file="@batch_requests.jsonl"

# Create a batch with the file ID
curl -X POST https://api.x.ai/v1/batches \\
  -H "Content-Type: application/json" \\
  -H "Authorization: Bearer $XAI_API_KEY" \\
  -d '{
    "name": "sentiment_analysis",
    "input_file_id": "file-abc123"
  }'

文件会在后台异步处理。若任意一行无效,batch 将被取消并返回错误消息。监控进度和获取结果的方式与内联 batch 相同。

使用文件创建批次时有以下限制:

  • 批次创建后即封存,无法再通过以下方法添加请求:AddBatchRequests。

  • 文件大小上限为 200 MB。

  • 每个文件最多容纳 50,000 个请求。

  • 文件中的每个custom_id 必须唯一。


限制

Batch

  • 一个团队可以拥有 不限数量 个 batch。

  • batch 创建速率上限:每个团队每秒创建 2 个 batch。

Batch Request

  • 理论上,一个 batch 可以包含 不限数量 个请求,但超大型 batch(超过 100,000 个请求)可能会为保障处理稳定性而受到限流。

  • 可添加到 batch 的每个单独请求最大负载大小为 25 MB。

  • 一个团队最多可以发送 1000 次 AddBatchRequests API 调用;限额周期为 30 秒(这是团队中所有 batch 共享的滚动限制)。

  • 图像和视频结果包含签名 URL,该 URL 会在 1 小时后过期。获取结果后请及时下载媒体。


Tool 使用

batch 请求同时支持服务端 tool和客户端 function tool。

  • 服务端 tool(web search、code execution、MCP 等)的工作方式与实时 API 相同:在处理过程中执行,并返回最终响应。

  • 客户端 function tool也受支持:模型会在响应中返回 tool_calls,供你离线处理。多轮 tool calling 需要提交新的 batch 请求,并在对话中包含 tool 结果消息。



最后更新:2026 年 10 月 20 日