news 2026/5/10 7:29:56

AI应用成本计算利器tokencost:精准追踪LLM API调用费用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI应用成本计算利器tokencost:精准追踪LLM API调用费用

1. 项目概述:一个为AI应用算清“经济账”的利器

最近在折腾各种大语言模型(LLM)应用,从简单的聊天机器人到复杂的多智能体工作流,有一个问题总是绕不开:成本。每次调用GPT-4、Claude-3或者使用那些动辄千亿参数的嵌入模型时,心里都在打鼓,这次又花了多少钱?尤其是在做原型验证、A/B测试或者优化提示词的时候,频繁的调用会让账单变得难以预测和追踪。更头疼的是,不同的模型提供商(OpenAI、Anthropic、Azure、Google等)计价方式五花八门,输入输出token分开算,不同模型费率天差地别,手动计算几乎是个不可能完成的任务。

直到我发现了tokencost这个项目。它不是一个复杂的AI框架,而是一个极其专注的“成本计算器”。简单来说,tokencost能帮你精确计算每一次LLM API调用的费用,支持市面上几乎所有主流模型。无论是评估不同模型的性价比,还是在你的AI应用中集成实时成本监控和预算控制,它都能派上大用场。对于独立开发者、创业团队甚至是大公司里负责控制AI预算的工程师来说,这玩意儿就像给你的AI项目装了一个清晰的“计价器”,让每一分钱都花得明明白白。

这个项目由AgentOps-AI团队维护,定位非常清晰:做LLM生态里的“成本感知”基础设施。它不处理模型推理,不管理对话状态,只专心做好一件事——算钱。接下来,我就结合自己的使用和集成经验,带你彻底拆解这个项目,看看它如何工作,怎么用,以及如何帮你避开那些“账单惊吓”的坑。

2. 核心设计思路:统一且可扩展的成本计算模型

tokencost的设计哲学非常值得学习,它把一个看似杂乱的问题抽象得异常清晰。其核心思路可以概括为:通过一个统一的接口,将不同厂商、不同模型的定价策略和token计算方式标准化,并提供灵活的集成方案。

2.1 为什么需要统一的成本计算?

在LLM应用开发中,成本计算面临几个核心挑战:

  1. 模型与供应商碎片化:OpenAI按每千个输入/输出token计价,Anthropic可能略有不同,而像Azure OpenAI虽然模型相同,但计价单位可能又是另一种方式。自托管模型(如通过vLLM服务)的成本计算逻辑更是完全不同。
  2. 计价维度复杂:除了基础的输入(Prompt)和输出(Completion)token,有些场景还涉及嵌入模型(按token或按请求)、微调训练、图像生成(按分辨率)等,维度多样。
  3. 动态定价:模型的定价并非一成不变,供应商可能会调整价格。一个健壮的成本计算库必须能相对容易地更新这些费率。
  4. 集成便捷性:成本计算不应该成为应用开发的主要负担。理想情况下,开发者只需要几行代码就能为现有的LLM调用链加上成本追踪。

tokencost的解决方案是建立一个“模型-供应商-价格表”的映射体系。它为每个支持的模型(如gpt-4oclaude-3-5-sonnet-20241022text-embedding-3-small)定义了一个标准化的结构,包含了该模型在特定供应商处的输入单价和输出单价(单位通常是每百万或每千个token)。

2.2 核心抽象:CostCalculator与价格表

项目最核心的部分是一个全局的、可更新的价格表。这个价格表本质上是一个大字典,键是模型标识符,值是一个包含了input_cost_per_tokenoutput_cost_per_token等信息的对象。

当你调用calculate_cost函数时,你需要提供:

  • model_name: 字符串,指定使用的模型。
  • input_tokens: 整数,本次调用消耗的输入token数。
  • output_tokens: 整数,本次调用生成的输出token数(可选,默认为0)。

函数内部会根据model_name去价格表中查找对应的费率,然后执行一个简单的乘法加法运算:总成本 = input_tokens * 输入单价 + output_tokens * 输出单价

这种设计的巧妙之处在于:

  • 解耦:计算逻辑与价格数据分离。更新价格时,你只需要更新价格表这个数据源,无需修改计算函数。
  • 可扩展:要支持一个新模型或新供应商,你只需要向价格表中添加一条新的记录,并确保其模型标识符的命名规则与你的调用方式匹配即可。
  • 透明:所有计算都是确定性的,基于公开的定价和准确的token数,没有黑盒。

注意tokencost本身不负责统计token数量。Token计数依赖于你所使用的模型和分词器(Tokenizer)。通常,你需要使用对应模型的分词器(如OpenAI的tiktoken, Anthropic的SDK自带方法,或Hugging Face的transformers库)来获取准确的input_tokensoutput_tokenstokencost专注于“已知token数,求费用”这个环节。

3. 快速上手指南:安装与基础使用

理论讲完了,我们直接上手。使用tokencost极其简单。

3.1 安装

通过pip即可安装:

pip install tokencost

3.2 基础计算示例

假设你刚调用完一次GPT-4,通过OpenAI的API响应,你得知这次调用使用了850个输入token,生成了150个输出token。

from tokencost import calculate_cost # 计算单次调用成本 cost_usd = calculate_cost( model_name="gpt-4o", # 使用 GPT-4o 模型 input_tokens=850, output_tokens=150 ) print(f"本次调用成本约为: ${cost_usd:.6f}") # 输出可能类似于: 本次调用成本约为: $0.001050

是的,就这么简单。calculate_cost函数内部已经集成了最新的官方定价(截至库发布时)。它会自动将token数乘以对应的费率(例如GPT-4o可能是$5.00 / 1M输入token,$15.00 / 1M输出token),并返回一个以美元为单位的浮点数。

3.3 获取支持的模型列表

如果你不确定某个模型标识符是否被支持,或者想查看所有预置的模型和价格,可以这样做:

from tokencost import models # 打印所有已配置的模型名称 print("所有支持的模型:") for model in models.keys(): print(f" - {model}") # 你也可以查看某个模型的详细定价信息 gpt4_info = models.get("gpt-4o") if gpt4_info: print(f"\nGPT-4o 定价信息: {gpt4_info}")

4. 高级功能与集成实战

基础计算只是开胃菜。tokencost真正强大的地方在于它能无缝集成到你的AI应用架构中,实现成本监控、预算告警和多租户计费。

4.1 集成到LangChain应用

LangChain是当前构建LLM应用最流行的框架之一。tokencost可以很方便地通过CallbackHandler集成到LangChain的调用链中,自动追踪每一步的成本。

下面是一个为LangChainLLMChain添加成本回调的示例:

from langchain_openai import ChatOpenAI from langchain_core.prompts import ChatPromptTemplate from langchain_core.callbacks import BaseCallbackHandler from tokencost import calculate_cost import json # 1. 自定义一个成本回调处理器 class TokenCostCallbackHandler(BaseCallbackHandler): """一个简单的回调处理器,用于累计LLM调用的成本""" def __init__(self): self.total_cost_usd = 0.0 self.call_details = [] # 记录每次调用的详情 def on_llm_end(self, response, **kwargs): """在LLM调用结束时触发""" # 从响应中提取必要信息。注意:不同LLM提供商返回的结构不同。 # 这里以OpenAI的ChatOpenAI为例 llm_output = response.llm_output or {} token_usage = llm_output.get("token_usage", {}) model_name = kwargs.get("model_name", "gpt-3.5-turbo") # 最好从run_id或其它上下文中获取更准确的模型名 input_tokens = token_usage.get("prompt_tokens", 0) output_tokens = token_usage.get("completion_tokens", 0) if model_name and (input_tokens or output_tokens): try: call_cost = calculate_cost( model_name=model_name, input_tokens=input_tokens, output_tokens=output_tokens ) self.total_cost_usd += call_cost self.call_details.append({ "model": model_name, "input_tokens": input_tokens, "output_tokens": output_tokens, "cost": call_cost }) print(f"[成本追踪] 单次调用: {model_name}, 输入{input_tokens}/输出{output_tokens} tokens, 成本 ${call_cost:.6f}") except Exception as e: print(f"[成本追踪] 计算成本时出错: {e}") def get_summary(self): """获取成本汇总""" return { "total_calls": len(self.call_details), "total_input_tokens": sum(d["input_tokens"] for d in self.call_details), "total_output_tokens": sum(d["output_tokens"] for d in self.call_details), "total_cost_usd": self.total_cost_usd, "details": self.call_details } # 2. 在LangChain中使用这个回调 prompt = ChatPromptTemplate.from_messages([ ("system", "你是一个有用的助手,用中文回答。"), ("human", "{query}") ]) llm = ChatOpenAI(model="gpt-4o", temperature=0.7) # 创建回调处理器实例 cost_handler = TokenCostCallbackHandler() chain = prompt | llm # 执行链,并传入回调处理器 response = chain.invoke( {"query": "请解释一下量子计算的基本原理。"}, config={"callbacks": [cost_handler]} # 关键:在这里传入回调 ) print(f"\n回答: {response.content}\n") # 3. 打印成本汇总 summary = cost_handler.get_summary() print("="*50) print("本次会话成本汇总:") print(f" 总调用次数: {summary['total_calls']}") print(f" 总输入Token数: {summary['total_input_tokens']}") print(f" 总输出Token数: {summary['total_output_tokens']}") print(f" 总估算成本: ${summary['total_cost_usd']:.6f}") print("="*50)

通过这种方式,你的LangChain应用就具备了自动成本审计功能。对于复杂的多步骤链(SequentialChain)或涉及工具调用的智能体(Agent),这个回调处理器会在每一个LLM调用节点触发,帮你累计全局成本。

4.2 预算控制与告警

知道成本后,下一步就是控制成本。你可以在成本回调处理器中加入简单的预算逻辑。

class BudgetAwareCostCallback(TokenCostCallbackHandler): """带预算控制的成本回调处理器""" def __init__(self, budget_usd=0.1): super().__init__() self.budget_usd = budget_usd self._budget_exceeded = False def on_llm_end(self, response, **kwargs): super().on_llm_end(response, **kwargs) # 每次调用后检查总成本是否超预算 if not self._budget_exceeded and self.total_cost_usd > self.budget_usd: self._budget_exceeded = True # 这里可以触发告警:发送邮件、Slack消息、记录日志等 print(f"\n⚠️ [预算告警] 当前会话成本已超过预设预算(${self.budget_usd})!") # 在实际应用中,你可能会选择抛出异常或停止后续的LLM调用 # raise BudgetExceededError(f"成本已超预算: ${self.total_cost_usd:.6f} > ${self.budget_usd}")

将这个处理器集成到你的Web服务或长期运行的智能体中,就能有效防止某个用户会话或任务因意外循环导致天价账单。

4.3 处理非OpenAI模型及自定义模型

tokencost项目预置了众多模型的价格,包括Anthropic的Claude系列、Google的Gemini系列、Cohere的命令系列,以及各类开源和嵌入模型。使用方法完全一致,只需改变model_name参数。

# 计算一次 Anthropic Claude 3 Sonnet 调用的成本 cost_claude = calculate_cost( model_name="claude-3-5-sonnet-20241022", input_tokens=1200, output_tokens=450 ) # 计算一次文本嵌入的成本 (例如使用 OpenAI 的 text-embedding-3-small) # 注意:嵌入模型通常只按输入token计费 cost_embedding = calculate_cost( model_name="text-embedding-3-small", input_tokens=5000, # 嵌入5000个token output_tokens=0 ) print(f"Claude调用成本: ${cost_claude:.6f}") print(f"嵌入成本: ${cost_embedding:.6f}")

如果你的公司使用的是私有化部署的模型(比如通过vLLM服务化的Llama 3),或者某个新出的模型尚未被tokencost收录,你可以轻松地扩展价格表。

from tokencost import models # 方法一:直接更新全局价格表(适用于简单自定义) models["my-company/llama-3-70b-instruct"] = { "input_cost_per_token": 0.0000004, # 假设 $0.40 / 1M tokens "output_cost_per_token": 0.0000004, "currency": "USD", "source": "my-company-internal-pricing" } # 现在你可以像使用预置模型一样使用它 cost_custom = calculate_cost( model_name="my-company/llama-3-70b-instruct", input_tokens=1000, output_tokens=500 ) # 方法二:创建自定义计算器(适用于更复杂的逻辑,如根据部署区域不同计价) from tokencost import CostCalculator class MyCompanyCostCalculator(CostCalculator): def __init__(self): super().__init__() # 加载或定义你自己的价格表 self.custom_price_list = {...} def calculate(self, model_name, input_tokens, output_tokens=0): # 先尝试从自定义表查找 if model_name in self.custom_price_list: rate = self.custom_price_list[model_name] return (input_tokens * rate["input"] + output_tokens * rate["output"]) / 1_000_000 # 假设费率是每百万token # 如果没找到,回退到父类(标准价格表)查找 else: return super().calculate(model_name, input_tokens, output_tokens) my_calc = MyCompanyCostCalculator() cost = my_calc.calculate("my-company/llama-3-70b-instruct", 1000, 500)

5. 实战场景与避坑指南

在实际项目中集成tokencost,我积累了一些经验和踩过的一些坑,这里分享给你。

5.1 场景一:A/B测试模型效果与成本

你的产品有一个总结功能,正在考虑是使用gpt-4o还是更便宜的gpt-3.5-turbo。除了效果,成本是关键因素。

def evaluate_model_for_summary(text, model_name): """模拟调用LLM进行总结,并返回结果和成本""" # 1. 模拟调用LLM并获取token使用情况 (这里需要真实的API调用和token计数) # 假设我们通过某种方式得到了以下数据 simulated_input_tokens = len(text) // 4 # 非常粗略的估算,实际请用tiktoken simulated_output_tokens = 200 # 假设总结输出约200个token # 2. 计算成本 cost = calculate_cost(model_name, simulated_input_tokens, simulated_output_tokens) # 3. 返回评估结果 (这里应包含真实的总结文本和质量评分) return { "model": model_name, "estimated_cost": cost, "input_tokens": simulated_input_tokens, "output_tokens": simulated_output_tokens } # 测试文本 sample_text = "这是一篇关于人工智能历史的长篇文章,内容涵盖了从图灵测试到深度学习革命的多个阶段..." * 100 # 对比两个模型 models_to_test = ["gpt-4o", "gpt-3.5-turbo-0125"] results = [] for model in models_to_test: result = evaluate_model_for_summary(sample_text, model) results.append(result) # 打印对比结果 print("模型A/B测试成本对比:") for r in results: print(f" 模型: {r['model']:30} 预估成本: ${r['estimated_cost']:.6f} (输入{r['input_tokens']}/输出{r['output_tokens']} tokens)")

通过这样的量化对比,你就能在效果和成本之间做出数据驱动的决策。

5.2 场景二:为多租户SaaS应用提供成本分账

如果你运营一个允许用户调用多种AI模型的SaaS平台,tokencost可以帮助你实现精确的按使用量计费。

from datetime import datetime import sqlite3 # 示例用SQLite,生产环境请用更健壮的数据库 class BillingService: def __init__(self, db_path="billing.db"): self.conn = sqlite3.connect(db_path) self._init_db() def _init_db(self): """初始化计费记录表""" cursor = self.conn.cursor() cursor.execute(""" CREATE TABLE IF NOT EXISTS api_usage ( id INTEGER PRIMARY KEY AUTOINCREMENT, tenant_id TEXT NOT NULL, model_name TEXT NOT NULL, input_tokens INTEGER NOT NULL, output_tokens INTEGER NOT NULL, cost_usd REAL NOT NULL, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, metadata TEXT ) """) self.conn.commit() def record_usage(self, tenant_id, model_name, input_tokens, output_tokens, metadata=None): """记录一次API使用并计算成本""" cost = calculate_cost(model_name, input_tokens, output_tokens) cursor = self.conn.cursor() cursor.execute(""" INSERT INTO api_usage (tenant_id, model_name, input_tokens, output_tokens, cost_usd, metadata) VALUES (?, ?, ?, ?, ?, ?) """, (tenant_id, model_name, input_tokens, output_tokens, cost, str(metadata) if metadata else None)) self.conn.commit() print(f"[计费] 租户 {tenant_id} 使用 {model_name}, 成本 ${cost:.6f} 已记录。") return cost def get_tenant_bill(self, tenant_id, start_date, end_date): """获取指定租户在时间范围内的账单汇总""" cursor = self.conn.cursor() cursor.execute(""" SELECT model_name, SUM(input_tokens) as total_input, SUM(output_tokens) as total_output, SUM(cost_usd) as total_cost, COUNT(*) as call_count FROM api_usage WHERE tenant_id = ? AND timestamp BETWEEN ? AND ? GROUP BY model_name """, (tenant_id, start_date, end_date)) rows = cursor.fetchall() return rows # 使用示例 billing = BillingService() # 当用户“company_a”调用一次API后 billing.record_usage( tenant_id="company_a", model_name="gpt-4o", input_tokens=1500, output_tokens=320, metadata={"request_id": "req_123", "endpoint": "/v1/chat/completions"} ) # 月末生成账单 bill = billing.get_tenant_bill("company_a", "2024-01-01", "2024-01-31") print("\n月度账单明细:") for model, inp, out, cost, calls in bill: print(f" 模型{model}: 调用{calls}次, 输入{inp}, 输出{out}, 总费用 ${cost:.4f}")

5.3 常见问题与排查技巧

  1. Model 'xxxx' not found错误

    • 原因:你传入的model_name字符串与tokencost内部价格表中的键不匹配。
    • 排查:首先运行print(list(models.keys()))查看所有支持的模型名称。OpenAI模型名通常是gpt-4ogpt-3.5-turbo-0125这种格式。Anthropic模型名类似claude-3-5-sonnet-20241022。确保完全一致,包括横杠和版本号。
    • 解决:如果确实是一个新模型或私有模型,按照前面“自定义模型”部分的方法添加即可。
  2. 成本计算结果为0或极小

    • 原因:最可能的原因是input_tokensoutput_tokens参数传错了(比如传成了0),或者你使用的模型费率极低(如gpt-3.5-turbo)。
    • 排查:打印出你传入的token数确认。用models.get(“your-model”)查看该模型的定价信息,确认单价是否正常。
    • 解决:确保你从API响应或分词器中获取了正确的token计数。对于嵌入模型,通常只有input_tokens会计费。
  3. 价格不是最新的

    • 原因tokencost库版本可能较旧,而AI服务商更新了定价。
    • 排查:去官方GitHub仓库的tokencost/models目录下查看价格表文件(通常是JSON或Python字典),对比AI服务商官网的最新定价。
    • 解决:更新tokencost到最新版本pip install -U tokencost。如果最新版仍未更新,可以暂时手动覆盖全局models字典中的对应条目,并最好给项目提一个Issue或Pull Request。
  4. 如何准确获取token数?

    • 这是成本计算准确性的基石。不要用简单的“字符数除以4”来估算,这非常不准确。
    • 对于OpenAI模型:使用tiktoken库。tokencost项目本身可能包含一些辅助函数,但核心token计数需要你自己做。
      import tiktoken def num_tokens_from_string(string: str, model_name: str) -> int: encoding = tiktoken.encoding_for_model(model_name) return len(encoding.encode(string))
    • 对于Anthropic模型:使用Anthropic官方SDK中的count_tokens方法。
    • 对于通用或开源模型:使用Hugging Facetransformers库中的对应分词器。
    • 最佳实践:尽量从LLM API的响应体中直接获取usage字段(如OpenAI返回的response.usage.prompt_tokensresponse.usage.completion_tokens),这是最准确的方式。
  5. 汇率与货币转换

    • 注意tokencost默认计算和返回的是美元(USD)成本。如果你的业务结算货币是其他币种(如CNY、EUR),需要在计算出美元成本后,再乘以一个实时或固定的汇率进行转换。
    • 建议:在计费记录层或展示层做货币转换,保持核心成本计算逻辑的纯净和一致。

6. 总结与项目价值

经过上面的拆解,你应该能感受到tokencost这个项目的精妙之处。它没有试图去解决AI应用开发中的所有问题,而是精准地切入“成本可视化与控制”这个在AI规模化应用中日益突出的痛点。

它的核心价值在于:

  • 标准化:为混乱的LLM定价市场提供了一个统一的抽象层。
  • 轻量级:几乎零依赖,安装简单,集成快速,不会给你的项目带来负担。
  • 可扩展:无论是支持新模型,还是接入自定义的定价策略,都非常灵活。
  • 实用性强:直接从真实的开发场景(如A/B测试、预算控制、多租户计费)出发,提供了切实可行的集成方案。

在我自己的项目中引入tokencost后,最直接的感受是“心里有底了”。在做提示词工程优化时,我可以清晰地看到每次调整带来的成本变化;在部署面向用户的智能体服务时,我可以设置成本阈值和告警,避免意外开销;在评估不同技术路线时,成本成了一个可量化、可比较的维度。

最后一个小建议:将成本监控作为你AI应用开发的基础设施之一,从项目早期就开始考虑。就像我们为服务设置性能监控和错误报警一样,成本监控也应该成为标准实践。tokencost这样的工具,让这件事变得简单了许多。你可以从简单的日志记录开始,逐步演进到实时的预算控制和精细化的成本分析,从而更自信、更可持续地开发和运营你的AI应用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 7:27:45

物联网硬件安全:从加密加速到PUF技术实践

1. 物联网安全架构的硬件基石在智能电表遭遇恶意固件升级、智能门锁被无线破解的案例频发的今天,硬件级安全防护已成为物联网设备的刚需。我曾参与某工业传感器项目的安全审计,发现多数漏洞源于开发者在设计初期对硬件信任链的忽视。真正的物联网安全必须…

作者头像 李华
网站建设 2026/5/10 7:20:17

英雄联盟界面定制新纪元:在合规边界内重塑你的游戏身份

英雄联盟界面定制新纪元:在合规边界内重塑你的游戏身份 【免费下载链接】LeaguePrank 项目地址: https://gitcode.com/gh_mirrors/le/LeaguePrank 想象一下,你刚刚开始英雄联盟的征程,但好友列表里那些闪亮的段位图标让你感到些许压力…

作者头像 李华
网站建设 2026/5/10 7:14:14

CANN/ge Tiling下沉特性分析

Tiling 下沉(Tiling Sink)特性分析 【免费下载链接】ge GE(Graph Engine)是面向昇腾的图编译器和执行器,提供了计算图优化、多流并行、内存复用和模型下沉等技术手段,加速模型执行效率,减少模型…

作者头像 李华
网站建设 2026/5/10 7:07:59

FIPSOC架构:嵌入式系统设计的革命性突破

1. FIPSOC架构解析:嵌入式系统设计的革命性突破在嵌入式系统开发领域,我们正经历着一场静悄悄的革命。传统设计中,工程师需要将微控制器、FPGA和模拟前端芯片组合在PCB上,通过复杂的布线实现系统功能。而FIPSOC(Field …

作者头像 李华
网站建设 2026/5/10 7:06:57

浏览器资源嗅探技术深度解析:从网络请求到媒体文件提取

浏览器资源嗅探技术深度解析:从网络请求到媒体文件提取 【免费下载链接】cat-catch 猫抓 浏览器资源嗅探扩展 / cat-catch Browser Resource Sniffing Extension 项目地址: https://gitcode.com/GitHub_Trending/ca/cat-catch 在当今多媒体的互联网时代&…

作者头像 李华