如何查询 Watson Assistant 每位用户的 API calls 与 billing details
结论
Watson Assistant 控制台不提供“每位终端用户的 API 调用次数和账单明细”。
context.metadata.user_id 主要用于识别活跃用户和关联会话日志,Billing Usage 页面不会根据这个字段拆分费用。IBM Cloud 通常按账号、资源实例和计费指标汇总用量与账单,而不是按 chatbot 的终端用户统计。
如需获取这类数据,可以采用以下两种方式:
- 通过 Watson Assistant 日志查询指定
user_id的交互记录,分析历史调用情况。 - 由 client application 的后端记录每次 Watson Assistant 请求,长期、准确地统计各用户的调用量,再结合实例账单计算或分摊费用。
为什么控制台中看不到
user_id 是应用传入的业务标识,例如:
{
"context": {
"metadata": {
"user_id": "user-12345"
}
}
}
Watson Assistant 可以用这个标识统计活跃用户,也可能将其保留在日志上下文中,但 IBM Cloud Billing 不会将它作为计费维度。
因此:
- Active users 图表显示的是去重后的用户数量;
- Improve 页面主要用于分析对话和日志,不是逐用户计费报表;
- Billing 的 Usage 页面显示资源实例的总用量,不会按
context.metadata.user_id拆分; user_id也无法证明某个请求一定对应一个可计费单位。
API 请求数、消息数、活跃用户数和最终计费用量不一定相同,具体取决于使用的 Watson Assistant 版本、套餐和当期计费规则。
查询指定用户的历史日志
如果所用的 Watson Assistant API 支持日志查询,可以读取日志并按 context.metadata.user_id 过滤。以下示例采用旧版 Workspace API 的调用方式:
curl -u "apikey:${WATSON_API_KEY}" \
"https://api.<region>.assistant.watson.cloud.ibm.com/instances/<instance-id>/v1/workspaces/<workspace-id>/logs?version=<api-version>&filter=context.metadata.user_id::user-12345&page_limit=100"
其中:
<region>是服务实例所在区域;<instance-id>是 Watson Assistant 服务实例 ID;<workspace-id>是对应的 workspace ID;<api-version>必须替换为目标环境实际支持的 API 版本日期;page_limit只控制每页返回的数量,完整统计还需要处理分页。
Watson Assistant 的 Classic、V1 Workspace 和较新的 Assistant V2 架构使用不同的接口及过滤语法。如果当前使用 V2 assistant、environment 或 session API,不能直接使用上面的 Workspace URL,应以该实例实际开放的日志或分析接口为准。
取得日志后,可以按 user_id 聚合记录:
const counts = {};
for (const log of logs) {
const userId = log.response?.context?.metadata?.user_id
?? log.request?.context?.metadata?.user_id;
if (!userId) continue;
counts[userId] = (counts[userId] ?? 0) + 1;
}
console.log(counts);
这段代码统计的是返回的日志条数,不一定等于实际 API 请求数。是否一致取决于日志生成规则,例如失败请求、重试请求、被采样或已经过期的日志,都可能导致记录不完整。
推荐的准确统计方式
更可靠的办法是在应用后端调用 Watson Assistant 时记录审计事件:
async function sendMessage(userId, message) {
const startedAt = Date.now();
try {
const response = await assistant.message({
assistantId: process.env.WATSON_ASSISTANT_ID,
sessionId: await getSessionId(userId),
input: {
message_type: "text",
text: message
}
});
await saveUsageEvent({
userId,
operation: "message",
success: true,
occurredAt: new Date().toISOString(),
durationMs: Date.now() - startedAt
});
return response.result;
} catch (error) {
await saveUsageEvent({
userId,
operation: "message",
success: false,
occurredAt: new Date().toISOString(),
durationMs: Date.now() - startedAt,
statusCode: error.code
});
throw error;
}
}
建议至少保存以下字段:
{
"userId": "user-12345",
"operation": "message",
"occurredAt": "2026-09-01T08:30:00Z",
"success": true,
"statusCode": 200,
"requestId": "application-generated-request-id"
}
随后按用户和账期进行聚合:
SELECT
user_id,
COUNT(*) AS api_calls,
SUM(CASE WHEN success = TRUE THEN 1 ELSE 0 END) AS successful_calls
FROM watson_usage_events
WHERE occurred_at >= :billing_period_start
AND occurred_at < :billing_period_end
GROUP BY user_id;
这些数据最好由可信的应用后端记录,不要依赖浏览器或移动端自行上报。客户端数据可能被篡改或遗漏,也可能因网络重试而产生重复记录。
如何得到每位用户的费用
IBM Cloud 提供的账单金额通常对应整个服务实例。如果业务上必须展示“每位用户费用”,需要自行制定分摊规则。例如,在确认套餐确实按相关调用量计费后,可以按调用占比分摊:
用户估算费用 = 实例账期费用 × 用户有效调用量 ÷ 实例有效调用总量
这个结果只适合内部成本分摊,并不等同于 IBM Cloud 出具的逐用户账单。如果套餐包含固定费用、免费额度、阶梯价格、活跃用户计费、超额用量或其他服务费用,简单按 API 调用次数分摊会产生偏差,需要根据实际账单中的计费指标建模。
注意事项
- 不要直接用邮箱、手机号等敏感信息作为
user_id,应优先使用稳定的内部匿名 ID。 - 同一用户应始终使用相同的
user_id,否则活跃用户统计可能重复计数。 - 日志通常有保留期限,不适合作为永久计量数据库。
- 记录重试、失败请求和幂等标识,并明确业务上“一次调用”的计算口径。
- 最终费用以 IBM Cloud 账单为准。应用侧数据适合用于用户归因、用量统计和内部费用分摊。
备注:内容仅供参考。
