按模型和功能跟踪 OpenAI API 成本
要跟踪 OpenAI API 成本,记录令牌使用情况、型号、延迟、重试和估计请求成本以及引发呼叫的产品功能和客户。这会将无法解释的提供商发票转换为您可以按模型、功能、团队和结果查询的支出。
请求级遥测将成本趋势与导致成本趋势的模型和工作负载联系起来。
最有用的事件将提供商的使用情况与产品上下文结合起来。代币数量解释了消费情况; feature、team_id、status 和 accepted 等字段说明请求是否产生值。
一分钟内即可查看 OpenAI 成本仪表板
从免费样品 OpenAI 使用活动开始。该快速入门会创建一个明确标记的事件,打开一个准备运行的成本查询,并将结果保留在您的入门仪表板上。您可以在更改应用程序代码之前检查工作流程。
生成的样本使用最小有用成本形状:
{
"provider": "openai",
"model": "gpt-5",
"input_tokens": 1250,
"output_tokens": 340,
"cost_usd": 0.0184,
"latency_ms": 842,
"status": "ok",
"sample": true
}
立即针对生成的 telemetry_quickstart 表运行此命令:
SELECT
model,
COUNT(*) AS requests,
SUM(input_tokens) AS input_tokens,
SUM(output_tokens) AS output_tokens,
ROUND(SUM(cost_usd), 4) AS total_cost_usd,
ROUND(AVG(latency_ms), 0) AS average_latency_ms
FROM telemetry_quickstart
WHERE provider = 'openai'
GROUP BY model
ORDER BY total_cost_usd DESC;
先决条件
- Telemetry API 钥匙
- OpenAI API 钥匙
- Node.js 和官方的 OpenAI JavaScript SDK
1. 安装并初始化SDK
npm install openai telemetry-sh
import OpenAI from "openai";
import telemetry from "telemetry-sh";
const openai = new OpenAI();
telemetry.init(process.env.TELEMETRY_API_KEY);
将两个 API 密钥保留在服务器端环境变量中。不要将它们放入源代码管理或浏览器代码中。
2. 将定价置于仪器之外
OpenAI 定价和型号可用性可能会发生变化。从 OpenAI 官方定价页面 读取当前费率并存储您在配置中使用的费率。
此示例使用每百万代币的美元:
OPENAI_MODEL="YOUR_MODEL"
OPENAI_INPUT_USD_PER_MILLION="YOUR_CURRENT_INPUT_RATE"
OPENAI_CACHED_INPUT_USD_PER_MILLION="YOUR_CURRENT_CACHED_INPUT_RATE"
OPENAI_CACHE_WRITE_USD_PER_MILLION="YOUR_CURRENT_CACHE_WRITE_RATE"
OPENAI_OUTPUT_USD_PER_MILLION="YOUR_CURRENT_OUTPUT_RATE"
OPENAI_PRICING_VERSION="provider-price-sheet-reviewed-YYYY-MM-DD"
const pricing = {
inputUsdPerMillion: Number(process.env.OPENAI_INPUT_USD_PER_MILLION),
cachedInputUsdPerMillion: Number(
process.env.OPENAI_CACHED_INPUT_USD_PER_MILLION
),
cacheWriteUsdPerMillion: Number(
process.env.OPENAI_CACHE_WRITE_USD_PER_MILLION
),
outputUsdPerMillion: Number(process.env.OPENAI_OUTPUT_USD_PER_MILLION),
};
function estimateCostUsd({
inputTokens,
cachedInputTokens,
cacheWriteTokens,
outputTokens,
}) {
const uncachedInputTokens = Math.max(
0,
inputTokens - cachedInputTokens - cacheWriteTokens
);
return (
(uncachedInputTokens * pricing.inputUsdPerMillion +
cachedInputTokens * pricing.cachedInputUsdPerMillion +
cacheWriteTokens * pricing.cacheWriteUsdPerMillion +
outputTokens * pricing.outputUsdPerMillion) /
1_000_000
);
}
使用您的提供商发票作为计费的真实来源。缓存输入、推理令牌、批处理、工具、图像、音频或其他模型功能可能需要额外的字段和定价规则。
当缓存读取或 缓存写入速率未知。将估计标记为不完整,直到当前 供应商价格表已经过审查。提供商的关键定价配置, 模型、服务层级和有效时间,而不是就地覆盖它。
3. 检测响应 API 请求
当前的 OpenAI JavaScript SDK 通过 client.responses.create 公开响应 API。完整的响应包括 usage 对象以及 input_tokens、output_tokens 和 total_tokens。
async function createDraftReply({ input, teamId, userId, attempt = 1 }) {
const model = process.env.OPENAI_MODEL;
const startedAt = Date.now();
try {
const response = await openai.responses.create({
model,
input,
});
const inputTokens = response.usage?.input_tokens ?? 0;
const outputTokens = response.usage?.output_tokens ?? 0;
const cachedInputTokens =
response.usage?.input_tokens_details?.cached_tokens ?? 0;
const cacheWriteTokens =
response.usage?.input_tokens_details?.cache_write_tokens ?? 0;
const reasoningTokens =
response.usage?.output_tokens_details?.reasoning_tokens ?? 0;
const estimatedCostUsd = estimateCostUsd({
inputTokens,
cachedInputTokens,
cacheWriteTokens,
outputTokens,
});
await telemetry.log("llm_request_completed", {
response_id: response.id,
provider: "openai",
model: response.model ?? model,
feature: "draft_reply",
team_id: teamId,
user_id: userId,
status: "success",
attempt,
input_tokens: inputTokens,
cached_input_tokens: cachedInputTokens,
cache_write_tokens: cacheWriteTokens,
output_tokens: outputTokens,
reasoning_tokens: reasoningTokens,
total_tokens: response.usage?.total_tokens ?? inputTokens + outputTokens,
estimated_cost_usd: estimatedCostUsd,
latency_ms: Date.now() - startedAt,
service_tier: response.service_tier ?? "not_reported",
pricing_version: process.env.OPENAI_PRICING_VERSION,
});
return response.output_text;
} catch (error) {
await telemetry.log("llm_request_failed", {
provider: "openai",
model,
feature: "draft_reply",
team_id: teamId,
user_id: userId,
status: "error",
attempt,
error_type: error?.constructor?.name ?? "unknown_error",
latency_ms: Date.now() - startedAt,
});
throw error;
}
}
默认情况下,不记录原始提示、完成情况、工具参数、凭据或私人客户内容。优先选择安全类别,例如 feature、workflow、input_category、output_category 和 error_type。
OpenAI当前提示缓存指导文档cached_tokens下
usage.input_tokens_details 用于回复 API 结果和文档
cache_write_tokens 适用于报告缓存写入的模型系列。它还显示
输出令牌详细信息下的 reasoning_tokens。参见官方提示缓存
要求。
推理令牌是响应的输出令牌会计中的详细信息;做
在估算代币总数时,不要再次将它们添加到 output_tokens 中。
保留单独的字段,因为它可以解释成本、延迟或
行为。
4. 将重试计入成本
即使用户看到,应用程序级重试也是一个新的计费请求
一项产品行动。在尝试和增量中携带稳定的 operation_id
attempt。单独记录终端应用程序结果。
await telemetry.log("ai_operation_completed", {
operation_id: operationId,
response_id: response.id,
team_id: teamId,
feature: "draft_reply",
attempts: attempt,
outcome: "accepted",
accepted: true,
});
这支持每个逻辑操作的成本、每个接受的输出的成本以及重试
放大。不要仅仅因为请求成本事件共享而对它们进行重复数据删除
operation_id;每个提供商的请求都会产生成本。
5. 将支出与成果联系起来
每个请求的成本并不能告诉您输出是否有用。当用户接受、复制、保存、重新生成或丢弃结果时记录单独的结果事件。
await telemetry.log("ai_output_reviewed", {
response_id: responseId,
team_id: teamId,
user_id: userId,
feature: "draft_reply",
outcome: "accepted",
accepted: true,
});
稳定的 response_id 可让您将使用情况和结果结合起来,而无需存储模型输出本身。
6.按功能、型号查询每日费用
Telemetry 自动添加 timestamp_utc,因此应用程序不需要发送自己的时间戳字段。
SELECT
date_trunc('day', timestamp_utc) AS day,
feature,
model,
COUNT(*) AS requests,
SUM(input_tokens) AS input_tokens,
SUM(cached_input_tokens) AS cached_input_tokens,
SUM(cache_write_tokens) AS cache_write_tokens,
SUM(output_tokens) AS output_tokens,
SUM(reasoning_tokens) AS reasoning_tokens,
ROUND(SUM(estimated_cost_usd), 4) AS estimated_cost_usd,
ROUND(AVG(latency_ms), 0) AS avg_latency_ms
FROM llm_request_completed
WHERE timestamp_utc >= now() - INTERVAL '30 days'
GROUP BY day, feature, model
ORDER BY day ASC, estimated_cost_usd DESC;
将 estimated_cost_usd 可视化为由 feature 或 model 分割的堆积折线图或面积图。将其与请求量和接受输出率配对,以便可以根据上下文解释成本增加。
7. 将估算与发票进行核对
请求遥测答案支出来自何处。提供商发票答案 计费内容是什么。在共享粒度(例如提供商项目)上协调两者, 型号、服务等级、货币和 UTC 计费日。
SELECT
date_trunc('day', timestamp_utc) AS day,
model,
service_tier,
pricing_version,
COUNT(*) AS requests,
ROUND(SUM(estimated_cost_usd), 4) AS estimated_cost_usd
FROM llm_request_completed
WHERE timestamp_utc >= now() - INTERVAL '30 days'
GROUP BY
date_trunc('day', timestamp_utc),
model,
service_tier,
pricing_version
ORDER BY day ASC, model ASC, service_tier ASC;
将发票总额存储在单独的财务控制数据集中,然后进行比较 类似的时期。差异可能来自价格变化,不完整 事件、积分、批量或优先处理、非代币工具、图像、音频、 货币转换,或应用程序遥测中缺少提供商项目。 不要仅仅为了强迫达成一致而“修复”事件历史;记录对账 解释。
需要警惕什么
有用的告警包括:
- 每日预计支出高于预期预算;
- 高于测试阈值的每个接受输出的成本;
- 一种模型或功能的重试或失败次数增加;
- 提示或工具模式更改后缓存输入份额下降;
- 缓存写入增加,但没有相应的未来缓存读取优势;
- 一个提示版本或工作流程的推理令牌份额发生变化;
- p95 延迟增加,而接受输出率保持平稳或下降;
- 使用事件到达时未识别
pricing_version。
后续步骤
使用完整的 按功能划分的 LLM 成本 SQL 配方 检查示例结果和仪表板设计。然后添加 接受的人工智能产出每美元配方 将产品价值与预计支出进行比较。
如需完整的实施路径,请继续了解 OpenAI 代理集成、LLM 成本跟踪模板 和 AI代理遥测产品指南。这些页面将请求级成本数据与代理运行、工具调用、仪表板和保留的产品结果连接起来。
对于基础 API 形状,请参阅 OpenAI 开发者快速入门 和 回复 API 参考。