Firebase AI SDK 的 UsageMetadata 接口详解:读懂生成式 AI 调用的 Token 用量明细

发布时间:2026/10/15 3:17:17
Firebase AI SDK 的 UsageMetadata 接口详解:读懂生成式 AI 调用的 Token 用量明细 开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载导读UsageMetadata是 Firebase JavaScript SDK 的 AI 模块firebase/ai即 Vertex AI in Firebase 与 Google AI 的统一前端中用于描述一次 GenerateContentResponse 调用所产生 token 消耗的元数据接口。本文以 docs-devsite/ai.usagemetadata.md 为骨架结合仓库源码public-types.ts、googleai-mappers.ts 与测试用例逐一拆解该接口的全部 9 个属性并说明它如何通过generateContent()/generateContentStream()返回、如何按模态文本、图片、视频、音频、文档细分、如何与缓存计数和countTokens()相互印证。读完本文你将能准确解析任何一次 Gemini 生成调用的 token 账单并据此做用量统计与成本估算。一、接口定位生成内容响应中的“Token 账单”1.1 从GenerateContentResponse中读取在 Firebase AI SDK 中UsageMetadata不作为独立 API 暴露给开发者直接构造而是作为GenerateContentResponse的一个可选字段随生成结果返回。其源码定义位于 packages/ai/src/public-types.ts#L106-L147export interface GenerateContentResponse { candidates?: GenerateContentCandidate[]; promptFeedback?: PromptFeedback; usageMetadata?: UsageMetadata; // ← 本次调用的 token 用量 }而UsageMetadata本身的声明与文档签名一致为export interface UsageMetadata { promptTokenCount: number; candidatesTokenCount: number; thoughtsTokenCount?: number; totalTokenCount: number; toolUsePromptTokenCount?: number; promptTokensDetails?: ModalityTokenCount[]; candidatesTokensDetails?: ModalityTokenCount[]; toolUsePromptTokensDetails?: ModalityTokenCount[]; cachedContentTokenCount?: number; cacheTokensDetails?: ModalityTokenCount[]; }从类型签名可以立即读出两条信息promptTokenCount、candidatesTokenCount、totalTokenCount三个字段是必填的它们构成最基础的用量三件套其余字段全部可选?仅在对应场景如使用了思考过程、工具调用、按模态细分、隐式缓存下才会被填充。1.2 统一两种后端的响应格式Firebase AI SDK 同时支持 Google AI 与 Vertex AIAgent Platform两种后端。网络层返回的原始响应被内部类型 GoogleAIGenerateContentResponse 承载export interface GoogleAIGenerateContentResponse { candidates?: GoogleAIGenerateContentCandidate[]; promptFeedback?: PromptFeedback; usageMetadata?: UsageMetadata; }随后由映射函数 mapGenerateContentResponse 原样透传给公开 APIexport function mapGenerateContentResponse( googleAIResponse: GoogleAIGenerateContentResponse ): GenerateContentResponse { const generateContentResponse { candidates: googleAIResponse.candidates ? mapGenerateContentCandidates(googleAIResponse.candidates) : undefined, prompt: googleAIResponse.promptFeedback ? mapPromptFeedback(googleAIResponse.promptFeedback) : undefined, usageMetadata: googleAIResponse.usageMetadata }; return generateContentResponse; }可以看到usageMetadata是被直接透传的不做任何改写因此文档中给出的属性含义与线路上 Google AI / Vertex AI API 的语义保持一致。开发者只要读response.usageMetadata就能拿到统一的用量视图。二、属性全解9 个字段逐一说明下表是 docs-devsite/ai.usagemetadata.md 中的属性清单其中英文描述为文档原文中文说明为结合源码与场景的解读属性类型必填文档描述 / 说明promptTokenCountnumber✅输入提示prompt消耗的 token 总数candidatesTokenCountnumber✅模型生成候选内容candidates消耗的 token 总数totalTokenCountnumber✅本次调用累计消耗的 token 总数通常 ≈ prompt candidatesthoughtsTokenCountnumber❌模型内部“思考”过程消耗的 token 数toolUsePromptTokenCountnumber❌工具tool use消耗的 token 数promptTokensDetailsModalityTokenCount[]❌输入 token 按模态文本/图片/视频/音频/文档的细分明细candidatesTokensDetailsModalityTokenCount[]❌输出 token 按模态的细分明细toolUsePromptTokensDetailsModalityTokenCount[]❌工具消耗的 token 按模态的细分明细cachedContentTokenCountnumber❌提示中被缓存服务cache命中的 token 数未启用隐式缓存或未命中时恒为 0cacheTokensDetailsModalityTokenCount[]❌缓存命中的 token 按模态的细分明细2.1 三个必填字段最基础的用量三件套promptTokenCount本次请求发送给模型的输入含系统指令、历史对话、工具声明等折算的 token 数。candidatesTokenCount模型为本次请求生成的候选输出折算的 token 数。totalTokenCountprompt与candidates的合计是衡量单次调用成本最直接的指标。在源码测试 packages/ai/src/methods/generate-content.test.ts#L150-L176 中对模拟响应unary-success-basic-response-long-usage-metadata.json的断言验证了这三个字段的真实取值形态expect(result.response.usageMetadata?.totalTokenCount).to.equal(1913); expect(result.response.usageMetadata?.candidatesTokenCount).to.equal(76); expect( result.response.usageMetadata?.promptTokensDetails?.[0].modality ).to.equal(IMAGE); expect( result.response.usageMetadata?.promptTokensDetails?.[0].tokenCount ).to.equal(1806); expect( result.response.usageMetadata?.candidatesTokensDetails?.[0].modality ).to.equal(TEXT); expect( result.response.usageMetadata?.candidatesTokensDetails?.[0].tokenCount ).to.equal(76);这段测试同时揭示了一个典型场景一次多模态请求中输入以图片为主IMAGE模态消耗 1806 token而输出为纯文本TEXT模态消耗 76 token最终totalTokenCount为 1913。2.2 两个“思考/工具”字段思维链与工具调用的成本thoughtsTokenCount模型内部“thinking”思考过程消耗的 token 数。只有当 ThinkingConfig 中开启思考、且模型支持思维链输出时才会出现配合响应侧的thoughtSummary()见 packages/ai/src/types/responses.ts#L76-L90可以理解模型推理开销。toolUsePromptTokenCount工具function calling 等调用环节消耗的 token 数用于把“工具开销”从普通 prompt 中区分出来便于单独核算。2.3 三个...TokensDetails字段按模态细分这三个字段的类型都是ModalityTokenCount[]对应文档中的配套接口 ModalityTokenCount其定义为export interface ModalityTokenCount { /** The modality associated with this token count. */ modality: Modality; /** The number of tokens counted. */ tokenCount: number; }modality取值为Modality枚举定义于 packages/ai/src/types/enums.ts#L371-L402export const Modality { MODALITY_UNSPECIFIED: MODALITY_UNSPECIFIED, TEXT: TEXT, IMAGE: IMAGE, VIDEO: VIDEO, AUDIO: AUDIO, DOCUMENT: DOCUMENT // 例如 PDF } as const; export type Modality (typeof Modality)[keyof typeof Modality];因此promptTokensDetails告诉你输入的每一类内容如 3 张图片 一段文字各自占了多少 tokencandidatesTokensDetails告诉你输出中是否包含非文本内容如生成图片、音视频及其占比toolUsePromptTokensDetails告诉你工具调用部分按模态的开销。它们为成本归因提供了“细粒度”视角是文档强调的“granular insight into which parts of the content were cached”的同类机制。2.4 两个缓存字段隐式缓存命中统计cachedContentTokenCount提示中由隐式缓存implicit caching服务命中的 token 数。若隐式缓存未启用、或没有内容命中缓存该值恒为0。cacheTokensDetails缓存命中的 token 按模态如文本、图片的细分用于精确判断“提示的哪一部分命中了缓存”。这两个字段对成本优化至关重要缓存命中的 token 通常计费更低读它能帮助判断重复前缀如固定的系统指令、长文档背景是否已进入缓存。三、实战在代码中读取与解析 UsageMetadata3.1 单次生成非流式import { getGenerativeModel, GoogleGenerativeAI } from firebase/ai; // 或使用 Vertex AIimport { getGenerativeModel, VertexAI } from firebase/ai; const model getGenerativeModel(ai, gemini-2.0-flash); const result await model.generateContent(用一句话解释量子纠缠); const usage result.response.usageMetadata; console.log(输入 tokens:, usage?.promptTokenCount); console.log(输出 tokens:, usage?.candidatesTokenCount); console.log(总计 tokens:, usage?.totalTokenCount); console.log(思考 tokens:, usage?.thoughtsTokenCount ?? 0); console.log(缓存命中 tokens:, usage?.cachedContentTokenCount ?? 0); // 按模态打印输入明细 usage?.promptTokensDetails?.forEach(detail { console.log( ${detail.modality}: ${detail.tokenCount}); });3.2 流式生成使用generateContentStream()时响应按 chunk 返回GenerateContentResponse在每个 chunk 中携带见 packages/ai/src/types/responses.ts#L99-L110 的注释“generateContentStream()will return one in each chunk until the stream is done”。通常最后一个 chunk携带完整的usageMetadataconst stream model.generateContentStream(写一首关于秋天的短诗); let usage; for await (const chunk of stream) { if (chunk.usageMetadata) { usage chunk.usageMetadata; // 以最后一次出现为准流结束时的汇总 } // process chunk.text() 等 } if (usage) { console.log(流式调用总计 tokens:, usage.totalTokenCount); }注意流式场景下中间的 chunk 可能只携带部分用量汇总应以最后一个 chunk 为准因此用“覆盖式赋值”而非“累加”。3.3 常见取值边界未开启思考模式时thoughtsTokenCount为undefined?.取值为undefined宜用?? 0兜底未启用隐式缓存或未命中时cachedContentTokenCount为0文档明确说明非多模态请求纯文本输入、纯文本输出时*TokensDetails数组可能缺失遍历前需判空。四、与 countTokens() 的配合事前预估 事后核算除生成后的用量回执外SDK 还提供GenerativeModel.countTokens()做事前预估。其响应类型 CountTokensResponse 同样使用ModalityTokenCount[]承载按模态明细export interface CountTokensResponse { promptTokensDetails?: ModalityTokenCount[]; // 按模态细分的 prompt 消耗 totalTokens: number; // 全部实例合计的 token 数 }其实现位于 packages/ai/src/methods/count-tokens.ts#L34-L75export async function countTokensOnCloud( apiSettings: ApiSettings, model: string, params: CountTokensRequest, singleRequestOptions?: SingleRequestOptions ): PromiseCountTokensResponse { params cleanCountTokensRequestForWire(params); // ... return response.json(); }需要注意两个限制countTokens()走云端计费接口对InferenceMode.ONLY_ON_DEVICE的端侧模型会直接抛出AIErrorcountTokens() is not supported for on-device models.见 packages/ai/src/methods/count-tokens.ts#L68-L73预估结果与实际的usageMetadata.promptTokenCount可能存在小幅偏差应以生成后的实际回执为准。典型用法是“先预估、后核算”用countTokens()在发送大 prompt 前检查预算用usageMetadata在每次生成后累计真实消耗。五、按模态做用量归因的最佳实践结合UsageMetadata与ModalityTokenCount可以构建一个简单的成本归因工具function summarizeUsage(usage: UsageMetadata | undefined) { if (!usage) return null; const byModality new Mapstring, number(); // 输入侧普通 prompt 工具调用 缓存命中 usage.promptTokensDetails?.forEach(d byModality.set(d.modality, (byModality.get(d.modality) ?? 0) d.tokenCount)); usage.toolUsePromptTokensDetails?.forEach(d byModality.set(d.modality, (byModality.get(d.modality) ?? 0) d.tokenCount)); usage.cacheTokensDetails?.forEach(d byModality.set(d.modality, (byModality.get(d.modality) ?? 0) d.tokenCount)); // 输出侧 usage.candidatesTokensDetails?.forEach(d byModality.set(d.modality, (byModality.get(d.modality) ?? 0) d.tokenCount)); return { total: usage.totalTokenCount, prompt: usage.promptTokenCount, candidates: usage.candidatesTokenCount, thought: usage.thoughtsTokenCount ?? 0, cached: usage.cachedContentTokenCount ?? 0, byModality: Object.fromEntries(byModality) }; }实践建议日志审计每次generateContent()/generateContentStream()后记录totalTokenCount与各明细字段形成用量时间序列缓存优化观察cachedContentTokenCount是否持续为 0若是则考虑调整 prompt 结构如将固定上下文前置以最大化隐式缓存命中多模态监控当输入包含图片/视频/PDF 时promptTokensDetails能精确指出哪一类内容最“贵”辅助压缩素材。六、源码索引与延伸阅读内容仓库路径UsageMetadata与ModalityTokenCount的类型定义packages/ai/src/public-types.ts#L117-L159GenerateContentResponse.usageMetadata字段packages/ai/src/types/responses.ts#L106-L147后端原始响应类型Google AI 格式packages/ai/src/types/googleai.ts#L47-L51响应映射usageMetadata 透传packages/ai/src/googleai-mappers.ts#L96-L110Modality枚举定义packages/ai/src/types/enums.ts#L371-L402用量断言测试多模态示例packages/ai/src/methods/generate-content.test.ts#L150-L176countTokens()实现与端侧限制packages/ai/src/methods/count-tokens.ts#L34-L75公开 API 审查清单中的UsageMetadatacommon/api-review/ai.api.md#L1528-L1544配套接口按模态计数docs-devsite/ai.modalitytokencount.md配套接口countTokens 响应docs-devsite/ai.counttokensresponse.md生成内容响应主文档docs-devsite/ai.generatecontentresponse.md结语UsageMetadata是 Firebase AI SDK 中理解模型调用成本的核心入口三个必填计数给出总体账单thoughts/toolUse字段拆出推理与工具开销*TokensDetails与cacheTokensDetails提供按模态、按缓存命中的细粒度归因。结合countTokens()的事前预估与测试用例所验证的多模态取值形态开发者可以据此构建完整的用量监控、成本核算与 prompt 缓存优化体系。赞分享开发工具后端【免费下载链接】firebase-js-sdkFirebase Javascript SDK项目地址https://gitcode.com/gh_mirrors/fi/firebase-js-sdk点击查看免费下载相关推荐Firebase AI Logicfirebase-js-sdkCountTokensRequest 接口详解Token 计数请求的完整配置指南Firebase AI Logicfirebase js sdkCountTokensRequest 接口详解Token 计数请求的完整配置指南 Coun开发工具后端Firebase JS SDK 中 GenerateContentRequest 接口详解构建 firebase/ai 生成请求的完整参数体系Firebase JS SDK 中 GenerateContentRequest 接口详解构建 firebase/ai 生成请求的完整参数体系 本文聚焦 f开发工具后端Firebase JS SDK 的 FunctionDeclaration 接口详解为 Gemini 模型声明可调用函数Firebase JS SDK 的 FunctionDeclaration 接口详解为 Gemini 模型声明可调用函数 导读 在 Firebase JS S开发工具后端上一篇HEIF格式兼容性解决方案Windows平台HEIC图片处理实践指南下一篇解密艾尔登法环存档管理终极方案EldenRingSaveCopier重塑角色数据迁移体验创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询