@apicity/xai (英语)
X.AI / Grok 提供商进行聊天和搜索.
运行时间依赖性 :
ws@^8.21.0——认证服务器 WebSocket 运出自@apicity/xai/realtimezod@^4.6.6- 请求在每一个 POST 端点上附加计划.schema
安装
npm install @apicity/xai
# or
pnpm add @apicity/xai
快速启动
import { createXai } from "@apicity/xai";
const xai = createXai({ apiKey: process.env.XAI_API_KEY! });
现实世界的例子:与Grok-4进行结构化的远景分析
手Grok -4 一张肖像, 系统提示 钉下输出计划,
财务报告和审定财务报表 text.format.type: "json_object" - 准备复制
JSON描述带有决定性的射击/有词汇. 以下流量
逐字记录
tests/integration/xai-vision-json.test.ts
并重玩对
tests/recordings/xai_3613880225/vision-analysis-json_243984103/recording.har, (中文(简体) ),
因此反应形状符合xAI实际返回的内容.
import { readFile } from "node:fs/promises";
import { createXai } from "@apicity/xai";
const xai = createXai({ apiKey: process.env.XAI_API_KEY! });
// 1. Load the image and inline it as a data URL. xAI also accepts
// https:// URLs, but inlining keeps the call self-contained and
// works against private hosts.
const image = await readFile("./portrait.jpg");
const base64 = image.toString("base64");
// 2. The system prompt enumerates the legal vocabulary for `shot` and
// constrains `pose` to body geometry only. Combined with
// `text.format.type: "json_object"` this gives Grok no room to drift
// off-schema — temperature 0 keeps the result reproducible.
const SYSTEM_PROMPT = [
"You are an expert image-to-prompt analyst.",
"Return only a JSON object with keys prompt, shot, and pose.",
"prompt: a single-paragraph reproduction-ready image prompt, 1900 characters or fewer, with no line breaks.",
'shot: exactly "<size>, <angle>" where size is one of extreme close-up, close-up, medium close-up, medium shot, medium long shot, long shot, or extreme long shot, and angle is one of eye-level, low-angle, high-angle, overhead, or dutch.',
"pose: only body geometry for human figures, with no clothing, hair, background, or lighting details.",
].join(" ");
// 3. Multimodal Responses request: system turn + a user turn whose
// content is an array of `input_image` + `input_text` parts.
const result = await xai.post.v1.responses({
model: "grok-4",
input: [
{ role: "system", content: SYSTEM_PROMPT },
{
role: "user",
content: [
{
type: "input_image",
image_url: `data:image/jpeg;base64,${base64}`,
detail: "high",
},
{
type: "input_text",
text: 'Analyze this image and produce a reproduction-ready JSON description with keys "prompt", "shot", and "pose".',
},
],
},
],
text: { format: { type: "json_object" } },
store: false,
temperature: 0,
max_output_tokens: 300,
});
// 4. The Responses API wraps output in a typed item array. Find the
// assistant message, then the first `output_text` part inside it.
// Discriminated unions narrow `item.type === "message"` so
// `item.content` is statically typed.
const message = result.output.find((item) => item.type === "message");
const outputText =
message?.type === "message"
? message.content.find((part) => part.type === "output_text")?.text
: undefined;
if (!outputText) throw new Error("Grok did not return output_text");
const analysis = JSON.parse(outputText) as {
prompt: string;
shot: string;
pose: string;
};
console.log(analysis.shot);
// → "medium close-up, eye-level"
console.log(analysis.pose);
// → "upright torso facing forward, head straight and centered, shoulders squared, arms relaxed downward (implied)"
// 5. Reasoning-token accounting. Grok-4 spent 623 of its 728 output
// tokens reasoning before emitting the 105-token JSON answer —
// surfaced in `usage.output_tokens_details.reasoning_tokens`.
console.log(result.usage);
// → {
// input_tokens: 2684,
// input_tokens_details: { cached_tokens: 679 },
// output_tokens: 728,
// output_tokens_details: { reasoning_tokens: 623 },
// total_tokens: 3412,
// }
页:1
store: false不让XAI的历史表面出现反应。 翻转到true链式后续previous_response_id- 用于 多回转改进 ("现在描述衣柜") 不重装 每次图像.- 反应输出阵列还包含推理项目和工具调用
当在现相. 总是歧视
item.type读取内容之前; TypeScript的收缩 让你诚实. - 用于原始聊天方式,而不使用响应包,使用
xai.post.v1.chat.completions换句话说,同样的认证,同样的模型目录, 只是OpenAI兼容的请求/响应形状. - 表面错误为
XaiError与status与附着的经文, 这样try { ... } catch (e) { if (e instanceof XaiError) ... }给你 直接发生上游错误.
想象文件 API 集成
xAI 想象图像和视频端点可以参考私有文件 API 资产,并且可以将生成的资产持续到文件存储.
- 输入: 任何地方 想象接受一个公共 URL 或 base64 图像/视频,
通过存储
file_id换句话说 Apicity 接受原始 REST 形状 (单位:千美元)image: { file_id }, (中文(简体) ),images: [{ file_id }], (中文(简体) ),last_frame: { file_id }, (中文(简体) ),video: { file_id }, (中文(简体) ),reference_images: [{ file_id }]+ 方便别名 (单位:千美元)image_file_id, (中文(简体) ),image_file_ids, (中文(简体) ),last_frame_file_id, (中文(简体) ),video_file_id,以及reference_image_file_ids页:1 在 HTTP 请求之前. - 产出:通过
storage_options附有所需filename坚持下去 生成的图像或视频。 奥米public_url或设定为false用于私有文件; 设置public_url: true或者说public_url: { expires_after: 86400 }创建可共享的 URL. - 答复中仍然包括默认电平
imgen.x.ai或者说vidgen.x.ai生成 URL。 当请求存储时 ưμ㼯Afile_output编辑 生成图像或完成的视频.
参考到视频、被绑框和预设声音
xai.post.v1.videos.generations 支持使用
最多14个参考图像 grok-imagine-video-1.5 家庭(7个
grok-imagine-video),一到三个预设的声音,或者两者兼有. 图像
引用可能使用公共 HTTPS URL、 数据 URI 或 文件 API ID
混合剂。 预设语音使用开放式的,对大小写不敏感的xAI语音标识; 3;
辣度保存每个 voice_id 语音识别留给
xAI. 预设的声音和被绑框要求 grok-imagine-video-1.5
经济、社会、文化权利委员会 -preview 和日期别名。 无型号请求
带有引用、 最后一个框或密钥框默认为条形
grok-imagine-video-1.5 型号.
const video = await xai.post.v1.videos.generations({
prompt: "The person from <IMAGE_0> speaks the line with the voice from <AUDIO_0>",
model: "grok-imagine-video-1.5",
reference_images: [{ url: "https://example.com/character.png" }],
reference_audios: [{ voice_id: "eve" }],
duration: 15,
});
在1.5个家庭里,一个请求也可以指针框. image (或
image_file_id)是第一个框架,单独或附带参考;
last_frame (或 last_frame_file_id)是最后一个框架;和 keyframes
在剪辑内刻出四张图像 每个键框 timestamp_s 必须
大于 0 并小于 duration (省略时为8秒). 页:1
将键框按到一分之三秒的网格,所以有两个键框绕到
同一档次被否决. prompt 当一个框架被固定时是可选的;
文本到视频和仅引用请求仍然需要。 先被钉住
帧取取 <IMAGE_0>,然后从
<IMAGE_1>。 。 。 .
const timeLapse = await xai.post.v1.videos.generations({
model: "grok-imagine-video-1.5",
image: { url: "https://example.com/dawn.png" },
keyframes: [
{ image: { url: "https://example.com/noon.png" }, timestamp_s: 3.5 },
{ image: { url: "https://example.com/dusk.png" }, timestamp_s: 6.5 },
],
last_frame: { url: "https://example.com/night.png" },
duration: 10,
resolution: "720p",
});
相同的可调用程序接受只使用图像和音频的参考请求.
空引用和键框数组不活动 。 源视频( A)video
或者说 video_file_id)不包括每个模型的参考文献和被标注的框架,
财务报告和审定财务报表 grok-imagine-video 也拒绝 image 除了参考书目 提示
标记,例如 <IMAGE_0> 财务报告和审定财务报表 <AUDIO_0> 未经修改.
存储输入字段映射
当图像或视频已经存在于 xAI 文件时使用这些字段
存储。 辣度将方便化的别名化为REST
file_id 发送请求前的对象形状.
| 异想天开 | 存储输入字段 | 发送到xAI |
|---|---|---|
xai.post.v1.images.edits | image_file_id | image: { file_id } |
xai.post.v1.images.edits | image_file_ids | images: [{ file_id }] |
xai.post.v1.videos.generations | image_file_id | image: { file_id } |
xai.post.v1.videos.generations | last_frame_file_id | last_frame: { file_id } |
xai.post.v1.videos.generations | reference_image_file_ids | reference_images: [{ file_id }] |
xai.post.v1.videos.generations.imageToVideo | image_file_id | image: { file_id } |
xai.post.v1.videos.edits | video_file_id | video: { file_id } |
xai.post.v1.videos.extensions | video_file_id | video: { file_id } |
也可以直接通过原始的 REST 字段. images 财务报告和审定财务报表
reference_images 条目可以混合 { file_id } 财务报告和审定财务报表 { url }
条目,仅在一些引用时有用
已经是私有文件资产 。 存储的图像必须是 PNG, JPEG,
或 WebP; 存储的视频必须是 MP4; 文件上传必须是
在以“想象”结尾引用之前完成.
const gen = await xai.post.v1.images.generations({
prompt: "A futuristic city skyline at night",
model: "grok-imagine-image-2.0",
quality: "low",
storage_options: { filename: "city.jpg" },
});
const city = gen.data[0].file_output!.file_id!;
const edit = await xai.post.v1.images.edits({
prompt: "Add neon signs to the buildings",
model: "grok-imagine-image-2.0",
quality: "low",
image_file_id: city,
storage_options: { filename: "city-neon.jpg" },
});
const neonCity = edit.data[0].file_output!.file_id!;
const video = await xai.post.v1.videos.generations({
prompt: "A camera pulls back through the city",
model: "grok-imagine-video",
duration: 5,
image_file_id: neonCity,
storage_options: {
filename: "city-loop.mp4",
public_url: true,
},
});
const done = await xai.get.v1.videos(video.request_id);
console.log(done.video?.url);
console.log(done.video?.file_output?.public_url);
见xAI的 想象文件 API 集成, (中文(简体) ), 引用文件为输入, (中文(简体) ), 持续生成输出, (中文(简体) ), 管理文件, (中文(简体) ), 财务报告和审定财务报表 文件 公开 URL 用于上传、过期和公共 URL 生命周期细节的文件.
文件 公开 URL
上传到xAI存储的文件默认是私有的. 使用
xai.post.v1.files.publicUrl(fileId) 创建共享
用于已有文件的 xAI CDN URL, 然后独立撤销该 URL
与 xai.post.v1.files.publicUrl.revoke(fileId) 共享时
应该停止。 撤销公用URL让私用文件完好无损.
const file = await xai.post.v1.files(
new Blob(["diagram"], { type: "image/png" }),
"diagram.png",
"assistants"
);
const created = await xai.post.v1.files.publicUrl(file.id, {
expires_after: 86400,
});
console.log(created.public_url);
console.log(created.expires_at);
const withPublicUrls = await xai.get.v1.files({
filter: "public_url != null",
});
console.log(withPublicUrls.data[0]?.public_url);
await xai.post.v1.files.publicUrl.revoke(file.id);
公共 URL 生命周期
- 空创建机构使用 xAI 默认 。 过
expires_after以秒计 在1小时到30天后自动翻转 URL. - 公共 URL 无法超过其文件 。 如果文件有自己的文件
expires_at,省略的公共 URL 过期继承文件过期; 明确expires_after必须装入剩余文件 一辈子. - 创建为 idempotent , 而一个文件已经有一个活动的公共 URL : 重复调用返回相同的 URL 令牌,并可以更新其过期 .
get.v1.files(fileId)财务报告和审定财务报表get.v1.files({ filter })保护public_url财务报告和审定财务报表public_url_expires_at元数据,所以呼叫者可以 审计当前公开的文件.
见xAI的
文件 公开 URL, (中文(简体) ),
管理文件, (中文(简体) ),
财务报告和审定财务报表 想象文件 API 集成
用于支持的内容类型、大小限制和
storage_options.public_url 生成路径.
实时服务器传输
@apicity/xai/realtime 出口 connectXaiRealtime,一个 WebSocket
服务器侧语音会话的传输基于 ws发送到您的
作为 API 密钥 Authorization: Bearer 头,所以保留在服务器上;
浏览器应该与来自
xai.post.v1.realtime.clientSecrets 换句话说.
import { connectXaiRealtime } from "@apicity/xai/realtime";
const connection = await connectXaiRealtime({
apiKey: process.env.XAI_API_KEY!,
model: "grok-voice-latest",
onEvent: (event) => console.log(event.type),
});
connection.send({
type: "session.update",
session: { voice: "eve", audio: { output: { speed: 1.1 } } },
});
// Speak a scripted line without model inference. The force_message
// item is the whole turn, so do not follow it with response.create.
connection.send({
type: "conversation.item.create",
item: {
type: "force_message",
role: "assistant",
interruptible: false,
content: [{ type: "output_text", text: "This call is being recorded." }],
},
});
connection.close();
await connection.closed;
- 过
callId改为model附加到一个入境的SIP电话. audio.output.speed是从0.7到1.5的回放乘数 (默认 1. 0).interruptible: false将调用器音频发送到强制消息 完成播放( 默认)true) (中文(简体) ).timeout限制握手( 默认 15 s) 和signal终止它 或开口连接. 一个被拒绝的握手拒绝XaiError带有HTTP状态并解析出体.- 一个不是 JSON 文本框架的服务器事件
type关闭 联系和报告Invalid Realtime event结束onError。 。 。 .
见xAI的 对发言的发言 用于会话参数和活动的文件.
API 参考
55个端点横跨18个组. 每个方法都映射出上游的 URL 路径 .
键
GET xai.v1.apiKey
GET https://api.x.ai/v1/api-key
成本等级 : expensive
const res = await xai.get.v1.apiKey();
批号
GET xai.v1.batches
GET https://api.x.ai/v1/batches/{paramsOrIdOrSignal}
成本等级 : expensive
const res = await xai.get.v1.batches({ /* ... */ });
GET xai.v1.batches.requests
GET https://api.x.ai/v1/batches/{batchId}/requests{query}
成本等级 : expensive
const res = await xai.get.v1.batches.requests({ /* ... */ });
GET xai.v1.batches.results
GET https://api.x.ai/v1/batches/{batchId}/results{query}
成本等级 : expensive
const res = await xai.get.v1.batches.results({ /* ... */ });
POST xai.v1.batches
POST https://api.x.ai/v1/batches
成本等级 : expensive
const res = await xai.post.v1.batches({ /* ... */ });
POST xai.v1.batches.cancel
POST https://api.x.ai/v1/batches/{batchId}:cancel
成本等级 : expensive
const res = await xai.post.v1.batches.cancel({ /* ... */ });
POST xai.v1.batches.requests
POST https://api.x.ai/v1/batches/{batchId}/requests
成本等级 : expensive
const res = await xai.post.v1.batches.requests({ /* ... */ });
聊天
GET xai.v1.chat.deferredCompletion
GET https://api.x.ai/v1/chat/deferred-completion/{requestId}
成本等级 : expensive
const res = await xai.get.v1.chat.deferredCompletion({ /* ... */ });
POST xai.v1.chat.completions
POST https://api.x.ai/v1/chat/completions
成本等级 : expensive
const res = await xai.post.v1.chat.completions({ /* ... */ });
自定义声音
DELETE xai.v1.customVoices
DELETE https://api.x.ai/v1/custom-voices/{voiceId}
成本等级 : expensive
const res = await xai.delete.v1.customVoices({ /* ... */ });
GET xai.v1.customVoices
GET https://api.x.ai/v1/custom-voices/{paramsOrVoiceIdOrSignal}
成本等级 : expensive
const res = await xai.get.v1.customVoices({ /* ... */ });
GET xai.v1.customVoices.audio
GET https://api.x.ai/v1/custom-voices/{voiceId}/audio
成本等级 : expensive
const res = await xai.get.v1.customVoices.audio({ /* ... */ });
PATCH xai.v1.customVoices
PATCH https://api.x.ai/v1/custom-voices/{voiceId}
成本等级 : expensive
const res = await xai.patch.v1.customVoices({ /* ... */ });
POST xai.v1.customVoices
POST https://api.x.ai/v1/custom-voices
成本等级 : expensive
const res = await xai.post.v1.customVoices({ /* ... */ });
文档
POST xai.v1.documents.search
POST https://api.x.ai/v1/documents/search
成本等级 : expensive
const res = await xai.post.v1.documents.search({ /* ... */ });
文件
DELETE xai.v1.files
DELETE https://api.x.ai/v1/files/{fileId}
成本等级 : expensive
const res = await xai.delete.v1.files({ /* ... */ });
GET xai.v1.files
GET https://api.x.ai/v1/files/{paramsOrFileIdOrSignal}
成本等级 : expensive
const res = await xai.get.v1.files({ /* ... */ });
GET xai.v1.files.content
GET https://api.x.ai/v1/files/{fileId}/content
成本等级 : expensive
const res = await xai.get.v1.files.content({ /* ... */ });
POST xai.v1.files
POST https://api.x.ai/v1/files
成本等级 : expensive
const res = await xai.post.v1.files({ /* ... */ });
POST xai.v1.files.publicUrl
POST https://api.x.ai/v1/files/{fileId}/public-url
成本等级 : expensive
const res = await xai.post.v1.files.publicUrl({ /* ... */ });
POST xai.v1.files.publicUrl.revoke
POST https://api.x.ai/v1/files/{fileId}/public-url/revoke
成本等级 : expensive
const res = await xai.post.v1.files.publicUrl.revoke({ /* ... */ });
图像模式
GET xai.v1.imageGenerationModels
GET https://api.x.ai/v1/image-generation-models/{modelIdOrSignal}
成本等级 : expensive
const res = await xai.get.v1.imageGenerationModels({ /* ... */ });
图像
GET xai.v1.images
GET https://api.x.ai/v1/images/{requestId}
成本等级 : expensive
const res = await xai.get.v1.images({ /* ... */ });
POST xai.v1.images.edits
POST https://api.x.ai/v1/images/edits
成本等级 : prohibitive
const res = await xai.post.v1.images.edits({ /* ... */ });
POST xai.v1.images.generations
POST https://api.x.ai/v1/images/generations
成本等级 : prohibitive
const res = await xai.post.v1.images.generations({ /* ... */ });
语言模型
GET xai.v1.languageModels
GET https://api.x.ai/v1/language-models/{modelIdOrSignal}
成本等级 : expensive
const res = await xai.get.v1.languageModels({ /* ... */ });
管理辅助
DELETE xai.managementApi.v1.collections
DELETE https://management-api.x.ai/v1/collections/{collectionId}
成本等级 : expensive
const res = await xai.delete.managementApi.v1.collections({ /* ... */ });
DELETE xai.managementApi.v1.collections.documents
DELETE https://management-api.x.ai/v1/collections/{collectionId}/documents/{fileId}
成本等级 : expensive
const res = await xai.delete.managementApi.v1.collections.documents({ /* ... */ });
GET xai.managementApi.auth.teams.apiKeys
GET https://management-api.x.ai/auth/teams/{teamId}/api-keys{query}
成本等级 : expensive
const res = await xai.get.managementApi.auth.teams.apiKeys({ /* ... */ });
GET xai.managementApi.v1.billing.teams.postpaid.invoice.preview
GET https://management-api.x.ai/v1/billing/teams/{teamId}/postpaid/invoice/preview
成本等级 : expensive
const res = await xai.get.managementApi.v1.billing.teams.postpaid.invoice.preview({ /* ... */ });
GET xai.managementApi.v1.billing.teams.postpaid.spendingLimits
GET https://management-api.x.ai/v1/billing/teams/{teamId}/postpaid/spending-limits
成本等级 : expensive
const res = await xai.get.managementApi.v1.billing.teams.postpaid.spendingLimits({ /* ... */ });
GET xai.managementApi.v1.billing.teams.prepaid.balance
GET https://management-api.x.ai/v1/billing/teams/{teamId}/prepaid/balance
成本等级 : expensive
const res = await xai.get.managementApi.v1.billing.teams.prepaid.balance({ /* ... */ });
GET xai.managementApi.v1.collections
GET https://management-api.x.ai/v1/collections/{paramsOrIdOrSignal}
成本等级 : expensive
const res = await xai.get.managementApi.v1.collections({ /* ... */ });
GET xai.managementApi.v1.collections.documents
GET https://management-api.x.ai/v1/collections/{collectionId}/documents/{paramsOrFileId}
成本等级 : expensive
const res = await xai.get.managementApi.v1.collections.documents({ /* ... */ });
GET xai.managementApi.v1.collections.documents.batchGet
GET https://management-api.x.ai/v1/collections/{collectionId}/documents:batchGet{query}
成本等级 : expensive
const res = await xai.get.managementApi.v1.collections.documents.batchGet({ /* ... */ });
PATCH xai.managementApi.v1.collections.documents
PATCH https://management-api.x.ai/v1/collections/{collectionId}/documents/{fileId}
成本等级 : expensive
const res = await xai.patch.managementApi.v1.collections.documents({ /* ... */ });
POST xai.managementApi.v1.billing.teams.usage
POST https://management-api.x.ai/v1/billing/teams/{teamId}/usage
成本等级 : expensive
const res = await xai.post.managementApi.v1.billing.teams.usage({ /* ... */ });
POST xai.managementApi.v1.collections
POST https://management-api.x.ai/v1/collections
成本等级 : expensive
const res = await xai.post.managementApi.v1.collections({ /* ... */ });
POST xai.managementApi.v1.collections.documents
POST https://management-api.x.ai/v1/collections/{collectionId}/documents/{fileId}
成本等级 : expensive
const res = await xai.post.managementApi.v1.collections.documents({ /* ... */ });
PUT xai.managementApi.v1.collections
PUT https://management-api.x.ai/v1/collections/{collectionId}
成本等级 : expensive
const res = await xai.put.managementApi.v1.collections({ /* ... */ });
模型
GET xai.v1.models
GET https://api.x.ai/v1/models/{modelIdOrSignal}
成本等级 : expensive
const res = await xai.get.v1.models({ /* ... */ });
实时
POST xai.v1.realtime.clientSecrets
POST https://api.x.ai/v1/realtime/client_secrets
成本等级 : expensive
const res = await xai.post.v1.realtime.clientSecrets({ /* ... */ });
答复
DELETE xai.v1.responses
DELETE https://api.x.ai/v1/responses/{id}
成本等级 : expensive
const res = await xai.delete.v1.responses({ /* ... */ });
GET xai.v1.responses
GET https://api.x.ai/v1/responses/{id}
成本等级 : expensive
const res = await xai.get.v1.responses({ /* ... */ });
POST xai.v1.responses
POST https://api.x.ai/v1/responses
成本等级 : expensive
const res = await xai.post.v1.responses({ /* ... */ });
POST xai.v1.responses.compact
POST https://api.x.ai/v1/responses/compact
成本等级 : expensive
const res = await xai.post.v1.responses.compact({ /* ... */ });
标准
POST xai.v1.stt
成本等级 : expensive
const res = await xai.post.v1.stt({ /* ... */ });
标记文字
POST xai.v1.tokenizeText
POST https://api.x.ai/v1/tokenize-text
成本等级 : expensive
const res = await xai.post.v1.tokenizeText({ /* ... */ });
吨数
POST xai.v1.tts
成本等级 : expensive
const res = await xai.post.v1.tts({ /* ... */ });
视频模式
GET xai.v1.videoGenerationModels
GET https://api.x.ai/v1/video-generation-models/{modelIdOrSignal}
成本等级 : expensive
const res = await xai.get.v1.videoGenerationModels({ /* ... */ });
视频
GET xai.v1.videos
GET https://api.x.ai/v1/videos/{requestId}
成本等级 : expensive
const res = await xai.get.v1.videos({ /* ... */ });
POST xai.v1.videos.edits
POST https://api.x.ai/v1/videos/edits
成本等级 : prohibitive
const res = await xai.post.v1.videos.edits({ /* ... */ });
POST xai.v1.videos.extensions
POST https://api.x.ai/v1/videos/extensions
成本等级 : prohibitive
const res = await xai.post.v1.videos.extensions({ /* ... */ });
POST xai.v1.videos.generations
POST https://api.x.ai/v1/videos/generations
成本等级 : prohibitive
const res = await xai.post.v1.videos.generations({ /* ... */ });
POST xai.v1.videos.generations.imageToVideo
POST https://api.x.ai/v1/videos/generations
成本等级 : prohibitive
const res = await xai.post.v1.videos.generations.imageToVideo({ /* ... */ });
中间软件
import { createXai, withRetry } from "@apicity/xai";
const xai = createXai({ apiKey: process.env.XAI_API_KEY! });
const models = withRetry(xai.get.v1.models, { retries: 3 });
限制费率
客户端速率限制队列请求停留在xAI API限制范围内.
import {
createXai,
withRateLimit,
withRetry,
createRateLimiter,
XAI_RATE_LIMITS,
} from "@apicity/xai";
const xai = createXai({ apiKey: process.env.XAI_API_KEY! });
使用 xAI 级预设
// Use built-in tier presets (free, tier1, tier2, tier3, tier4)
const limiter = createRateLimiter(XAI_RATE_LIMITS.tier1);
// => { rpm: 60, concurrent: 10 }
const chat = withRateLimit(xai.post.v1.chat.completions, limiter);
自定义限制
const limiter = createRateLimiter({ rpm: 30, concurrent: 5 });
const chat = withRateLimit(xai.post.v1.chat.completions, limiter);
跨端点共享限制器
RPM限制在全球范围内适用,因此在所有终点共享一个单一的限值:
const limiter = createRateLimiter(XAI_RATE_LIMITS.tier2);
const chat = withRateLimit(xai.post.v1.chat.completions, limiter);
const responses = withRateLimit(xai.post.v1.responses, limiter);
用重试编译
地点 withRateLimit 最内层的重试计数到极限:
const limiter = createRateLimiter(XAI_RATE_LIMITS.tier1);
const chat = withRetry(
withRateLimit(xai.post.v1.chat.completions, limiter),
{ retries: 2 }
);
批处理
并行的点火请求——限制手柄自动间隔:
const limiter = createRateLimiter(XAI_RATE_LIMITS.tier1);
const chat = withRateLimit(xai.post.v1.chat.completions, limiter);
const prompts = ["Name a prime number.", "Name a noble gas."];
const results = await Promise.all(
prompts.map((p) =>
chat({
model: "grok-3",
messages: [{ role: "user", content: p }],
})
)
);
xAI 费率限制等级
| 预设 | 常规 | 同时 | 支出门槛值 |
|---|---|---|---|
free | 页:1 | 2个 | 0美元 (单位:美元) |
tier1 | 页:1 | 10个 | 0美元+ (单位:千美元) |
tier2 | 200个 | 第25条 | 100美元+ (单位:千美元) |
tier3 | 500个 | 第50条 | $500+ (单位:千美元) |
tier4 | 1 000个 | 100个 | 1 000美元+ (单位:千美元) |
部分 辣点 单相机.
许可证
麻省理工学院——见 自由主义。 。 。 .