高级 API 用法
上下文压缩
当对话超过几千个 token 时,每次后续调用都会重新发送所有之前的消息,并为所有这些消息支付输入 token 的费用。上下文压缩允许您将这些消息压缩成一个不透明的项目,它保留了重要状态——系统提示、附加文件、先前推理以及压缩后的对话记录——同时省略了冗长的工具输出和来回对话。
然后,您将这个压缩项目原样传递回下一个请求中,模型会继续对话,就好像完整的历史记录仍然存在一样。
- 更低的输入成本 — 下一次调用只需为压缩后的上下文付费,而不是原始消息。
- 更低的延迟 — 更小的有效载荷意味着更快的首 token 时间。
- 更清晰的响应 — 更紧凑的上下文使模型专注于当前任务,而不是被过时的工具输出和旧对话分散注意力。
- 更长的对话 — 保持多小时的代理循环远低于模型的上下文窗口限制。
NOTE
将 encrypted_content 视为不透明 — 不要解析或修改它。您可以将这个 blob 存储在自己的数据库中,并在后续请求中原样传回;只有当它被发送回 xAI 的 API 时才有意义。
何时进行压缩
当所有以下条件都为真时进行压缩:
- 对话已经增长到足以使每次调用中的
input_tokens影响成本或延迟。 - 您仍然希望模型记住之前的对话(否则只需开始新对话)。
- 当前窗口仍适合模型的上下文限制(压缩会缩小对话 — 它无法拯救已经超出限制的请求)。
一个典型的模式是在代理循环中每 N 轮调用一次压缩 API,或者每当您的记账显示渲染后的上下文超过您为工作负载选择的阈值时调用一次。
压缩 API
发送您想要压缩的对话。响应包含一个代表整个先前对话的压缩项目 — 您可以安全地从客户端状态中删除原始消息,使用压缩项目作为下一个请求的头部,并在其后追加新的用户对话。
# Step 1 — compact the long conversation
curl -s https://api.x.ai/v1/responses/compact \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $XAI_API_KEY" \
-d '{
"model": "grok-4.5",
"input": [
{"role": "system", "content": "You are a concise and knowledgeable science tutor."},
{"role": "user", "content": "What is the Higgs boson and why is it important?"},
{"role": "assistant", "content": "The Higgs boson is an elementary particle..."},
{"role": "user", "content": "How does the Higgs mechanism actually work?"},
{"role": "assistant", "content": "The Higgs mechanism works through spontaneous symmetry breaking..."}
]
}'
# Step 2 — continue the conversation using the compacted output
curl -s https://api.x.ai/v1/responses \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $XAI_API_KEY" \
-d '{
"model": "grok-4.5",
"input": [
{
"type": "compaction",
"id": "cmp_abc123",
"encrypted_content": "<paste encrypted_content from step 1>"
},
{"role": "user", "content": "Based on our earlier conversation, what gives particles their mass?"}
]
}'import os
from xai_sdk import Client
from xai_sdk.chat import system, user
client = Client(api_key=os.environ["XAI_API_KEY"])
# Build up a chat normally — system prompt plus a few user/assistant turns.
# use_encrypted_content=True is recommended for reasoning models so the model's
# reasoning content from prior turns is preserved through the compaction.
chat = client.chat.create(model="grok-4.5", use_encrypted_content=True)
chat.append(system("You are a concise and knowledgeable science tutor."))
chat.append(user("What is the Higgs boson and why is it important?"))
chat.append(chat.sample())
chat.append(user("How does the Higgs mechanism actually work?"))
chat.append(chat.sample())
# ... many more turns ...
# Step 1 — compact the conversation. Pass the chat's accumulated messages
# straight into compact_context.
compact = client.chat.compact_context(
model="grok-4.5",
messages=chat.messages,
)
print(f"Compaction ID: {compact.id}")
print(f"Dropped messages: {compact.dropped_message_count}")
print(f"Tokens used: {compact.usage.total_tokens}")
# Step 2 — continue the conversation. chat.append(compact) clears the
# in-memory message list on the chat object and seeds it with just the
# compaction blob, so subsequent chat.sample() calls run on top of the
# compacted context instead of replaying the full prior history.
chat.append(compact)
chat.append(user("Based on our earlier conversation, what gives particles their mass?"))
print(chat.sample().content)import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["XAI_API_KEY"],
base_url="https://api.x.ai/v1",
)
# Step 1 — compact the long conversation
compacted = client.responses.compact(
model="grok-4.5",
input=[
{"role": "system", "content": "You are a concise and knowledgeable science tutor."},
{"role": "user", "content": "What is the Higgs boson and why is it important?"},
{"role": "assistant", "content": "The Higgs boson is an elementary particle..."},
{"role": "user", "content": "How does the Higgs mechanism actually work?"},
{"role": "assistant", "content": "The Higgs mechanism works through spontaneous symmetry breaking..."},
],
)
print(f"Compaction ID: {compacted.id}")
print(f"Dropped messages: {compacted.usage.dropped_message_count}")
print(f"Output tokens: {compacted.usage.output_tokens}")
# Step 2 — continue the conversation. Spread compacted.output into the next input.
followup = client.responses.create(
model="grok-4.5",
input=[
*compacted.output, # use the compaction item verbatim — do not modify
{"role": "user", "content": "Based on our earlier conversation, what gives particles their mass?"},
],
)
print(followup.output_text)import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.XAI_API_KEY,
baseURL: "https://api.x.ai/v1",
});
// Step 1 — compact the long conversation
const compacted = await client.responses.compact({
model: "grok-4.5",
input: [
{ role: "system", content: "You are a concise and knowledgeable science tutor." },
{ role: "user", content: "What is the Higgs boson and why is it important?" },
{ role: "assistant", content: "The Higgs boson is an elementary particle..." },
{ role: "user", content: "How does the Higgs mechanism actually work?" },
{ role: "assistant", content: "The Higgs mechanism works through spontaneous symmetry breaking..." },
],
});
console.log(`Compaction ID: ${compacted.id}`);
console.log(`Dropped messages: ${compacted.usage.dropped_message_count}`);
console.log(`Output tokens: ${compacted.usage.output_tokens}`);
// Step 2 — continue the conversation. Spread compacted.output into the next input.
const followup = await client.responses.create({
model: "grok-4.5",
input: [
...compacted.output, // use the compaction item verbatim — do not modify
{ role: "user", content: "Based on our earlier conversation, what gives particles their mass?" },
],
});
console.log(followup.output_text);xAI SDK 还暴露了一个 AsyncClient,在 asyncio 下具有 await client.chat.compact_context(...) 和 await chat.sample() 方法用于相同流程。
响应结构
REST 端点 (POST /v1/responses/compact) 返回一个与 OpenAI 兼容的压缩对象:
{
"id": "cmp_01HZ9P0V8M2YQK3F7C4G6N5R2A",
"object": "response.compaction",
"created_at": 1748895600,
"model": "grok-4.5",
"output": [
{
"type": "compaction",
"id": "cmp_01HZ9P0V8M2YQK3F7C4G6N5R2A",
"encrypted_content": "<opaque blob>"
}
],
"usage": {
"input_tokens": 12000,
"input_tokens_details": { "cached_tokens": 0 },
"output_tokens": 800,
"output_tokens_details": { "reasoning_tokens": 240 },
"total_tokens": 12800,
"dropped_message_count": 45
}
}| 字段 | 描述 |
|---|---|
id | 此压缩的稳定 ID (cmp_<uuid>)。也在内部压缩项目上回显。 |
object | 始终为 "response.compaction"。 |
output | 包含单个压缩项目的数组。将其原样传递到您的下一个请求中。 |
output[].type | 始终为 "compaction"。 |
output[].encrypted_content | 包含压缩对话的不透明 blob。 |
usage.input_tokens | 压缩前的对话中的 token 数。 |
usage.output_tokens | 为压缩记录生成的 token。模型在下次调用时重新生成的内容大约是您保留的系统提示加上这些 token。 |
usage.dropped_message_count | 合并到压缩中的输入消息数量。 |
WARNING
不要修剪压缩输出。 将返回的压缩项目视为对话的新"开始" — 在其后追加新的用户对话,绝不要在前。删除或重新排序压缩输出内部的项目会破坏链式结构。
xAI SDK 中的原地压缩
对于长时间运行的代理循环,xAI SDK 在活动的 Chat 对象上提供了一个便捷方法:chat.compact() 针对聊天当前的消息运行压缩,并原地替换它们为压缩项目。之后您可以像以前一样继续调用 chat.sample() — 服务器会在下一个请求中重新生成压缩的前缀。
import os
from xai_sdk import Client
from xai_sdk.chat import system, user
client = Client(api_key=os.environ["XAI_API_KEY"])
# use_encrypted_content=True preserves the model's reasoning content across
# turns, recommended when using reasoning models.
chat = client.chat.create(model="grok-4.5", use_encrypted_content=True)
chat.append(system("You are a helpful assistant. Keep answers brief."))
compact_every = 5
for turn in range(1, 100):
chat.append(user(input("You: ")))
response = chat.sample()
print(f"Grok: {response.content}")
chat.append(response)
if turn % compact_every == 0:
before = len(chat.messages)
compact = chat.compact()
print(
f"[compacted {before} → {len(chat.messages)} messages | "
f"dropped {compact.dropped_message_count} | "
f"tokens used: {compact.usage.total_tokens}]"
)AsyncClient 上也有相同的方法,作为 await chat.compact()。
限制和注意事项
- 您压缩的对话必须已经适合上下文。 压缩会缩小对话;它无法拯救超出限制的请求。如果您的对话已经超过了
context_length_exceeded,您需要在调用压缩之前进行修剪或拆分。 - 每次调用最多一个压缩。 每个请求只进行一次压缩。
encrypted_content是不透明的。 不要解析、编辑或手动合并多个 blob。始终完整地传回output数组(或CompactContextResponse)。- 重新压缩是可以的。 您可以稍后再次压缩已经压缩的对话 — 例如,当对话在先前的压缩之后变长时。
- 压缩调用的 token 使用量。 压缩本身会使用 token(在
usage.input_tokens/usage.output_tokens中可见)。如果您经常进行压缩,请选择更小/更快的模型。
相关
- 生成文本 — Responses API — 压缩所馈入的主要端点。
- 提示缓存 — 用于未更改提示前缀的互补成本降低工具。
- Chat API 参考 — 压缩 API 的完整请求/响应架构。