ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DeepSeek Harness 小白入门 38:每次调用花多少?用 usage 做一张成本与缓存账单(TaoToken 统一 Key 版)

DeepSeek Harness 小白入门 38:每次调用花多少?用 usage 做一张成本与缓存账单(TaoToken 统一 Key 版) 1. 一次对话到底花了多少钱为什么你算不明白很多人第一次用 DeepSeek Harness 跑通对话后盯着控制台那行回复就以为完事了。等到月底看账单发现费用比预期高出一截却完全说不清钱花在哪。问题不在模型而在于你从没认真看过返回结果里的usage字段。usage是每次 API 调用后服务端回传的用量凭证它告诉你这次请求消耗了多少输入 Token、多少输出 Token、有多少命中了缓存。DeepSeek Harness 作为第三方协议适配层会把这部分信息整理成结构化对象交给你。但小白常见的做法是只打印message.content把usage直接丢掉等于每次调用都在“盲付”。这篇面向刚上手 Harness 的读者用一个真实对话演示从返回结果里提取prompt_tokens、completion_tokens和缓存命中信息算清单次成本最后落成一张可聚合的 JSONL 账单。全程用 TaoToken 统一 Key 接入方便你在一个控制台里核对用量、验证缓存是否真的生效。适合谁已经能跑通 Harness 最小对话、但还没建立成本观测习惯的开发者。2. 用 TaoToken 统一 Key 接入先把用量口径对齐在算钱之前得先保证你看到的usage是可信的。如果你同时用多个 Key、多个端点账单口径就会打架。TaoToken 的做法是给你一个统一 Key模型对话、Coding Plan、API 调用都走同一个入口用量在控制台里集中呈现核对起来不用来回切换。接入动作很简单打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 注册后进入控制台在 API Keys 页面生成一个 Key。这个 Key 就是你后面所有请求的凭证。注意Key 只在生成时完整显示一次复制后立刻存进环境变量别写进代码。拿到 Key 后把 Harness 的 Base URL 指向 TaoToken 的 API 地址 https://taotoken.net/api。这样你的请求会经过统一网关返回的usage字段和 TaoToken 控制台里的用量统计是同一套口径。后面算出来的成本才能和控制台对得上。注意TaoToken 是统一接入与用量管理入口不是让你绕过任何合规流程。Key 的权限范围、余额、调用记录都在控制台可查出问题先看那里。如果你还没生成 Key直接去 API Keys 页面https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 里面有各语言的 Base URL 配置示例。3. 可复制的 usage 解析脚本与账单模板3.1 环境准备先建一个干净的测试目录装好依赖。Python 用 3.10 以上Harness 用你当前核验过的版本。Key 通过环境变量注入别硬编码。mkdir -p ~/harness-billing cd ~/harness-billing python3 -m venv .venv source .venv/bin/activate pip install deepseek-harness export TAOTOKEN_API_KEY你的Key3.2 最小调用与 usage 提取下面这段脚本做三件事发一次短对话、把usage完整打印出来、把不含正文和密钥的账单追加进 JSONL 文件。你可以直接复制运行。import os import json import time from deepseek_harness import DeepSeekHarness client DeepSeekHarness( api_keyos.environ[TAOTOKEN_API_KEY], base_urlhttps://taotoken.net/api, disable_thinking_by_defaultTrue, ) out client.chat( modeldeepseek-v4-flash, messages[{role: user, content: 用不超过 80 字解释什么是缓存命中}], max_tokens256, extra_body{thinking: {type: disabled}}, ) usage out.get(usage) or {} message out.get(message) or {} record { ts: int(time.time()), model: out.get(model), finish_reason: out.get(finish_reason), prompt_tokens: usage.get(prompt_tokens), completion_tokens: usage.get(completion_tokens), total_tokens: usage.get(total_tokens), prompt_cache_hit_tokens: usage.get(prompt_cache_hit_tokens), prompt_cache_miss_tokens: usage.get(prompt_cache_miss_tokens), estimated_cost_usd: usage.get(estimated_cost_usd), } print(回复:, message.get(content)) print(用量:, json.dumps(record, ensure_asciiFalse)) with open(billing.jsonl, a, encodingutf-8) as f: f.write(json.dumps(record, ensure_asciiFalse) \n)跑完后你会看到类似这样的输出回复: 缓存命中指请求的内容与之前已缓存的前缀一致服务端直接复用无需重新计算从而降低延迟和费用。 用量: {ts: 1755..., model: deepseek-v4-flash, finish_reason: stop, prompt_tokens: 42, completion_tokens: 38, total_tokens: 80, prompt_cache_hit_tokens: 0, prompt_cache_miss_tokens: 42, estimated_cost_usd: 0.000021}3.3 字段含义对照表字段含义小白怎么理解prompt_tokens输入 Token 总数你发出去的内容占多少completion_tokens输出 Token 总数模型回给你的内容占多少total_tokens总 Token上面两项相加prompt_cache_hit_tokens命中缓存的输入 Token这部分通常更便宜prompt_cache_miss_tokens未命中缓存的输入 Token这部分按正常价算estimated_cost_usd估算费用单次成本用于聚合3.4 账单表格模板JSONL 适合程序聚合但人看还是表格直观。你可以用下面这个模板把多次调用汇总成一张账单。把billing.jsonl里的记录读出来按模型和日期分组即可。import json from collections import defaultdict agg defaultdict(lambda: {calls: 0, prompt: 0, completion: 0, hit: 0, cost: 0.0}) with open(billing.jsonl, encodingutf-8) as f: for line in f: r json.loads(line) key r[model] agg[key][calls] 1 agg[key][prompt] r[prompt_tokens] or 0 agg[key][completion] r[completion_tokens] or 0 agg[key][hit] r[prompt_cache_hit_tokens] or 0 agg[key][cost] r[estimated_cost_usd] or 0.0 print(f{模型:20}{调用:6}{输入:8}{输出:8}{缓存命中:10}{费用USD:10}) for model, v in agg.items(): print(f{model:20}{v[calls]:6}{v[prompt]:8}{v[completion]:8}{v[hit]:10}{v[cost]:10.6f})这张表就是你自己的成本账单。每次实验后跑一遍费用变化一目了然。4. 验证请求缓存命中到底有没有生效4.1 设计一个能触发缓存的实验缓存命中的前提是请求前缀稳定。DeepSeek 的缓存机制对相同前缀的输入会复用计算结果。所以你要做的是第一次发一个带长系统提示的请求第二次发同样的系统提示、只改用户问题观察prompt_cache_hit_tokens是否从 0 变成正数。system_prompt 你是一个严谨的技术助手回答必须简洁不超过 100 字。 * 20 def ask(question): out client.chat( modeldeepseek-v4-flash, messages[ {role: system, content: system_prompt}, {role: user, content: question}, ], max_tokens128, extra_body{thinking: {type: disabled}}, ) u out.get(usage) or {} return { q: question, hit: u.get(prompt_cache_hit_tokens), miss: u.get(prompt_cache_miss_tokens), cost: u.get(estimated_cost_usd), } print(ask(什么是 Token)) print(ask(什么是缓存))4.2 成功结果长什么样第一次调用hit应该是 0miss等于prompt_tokens。第二次调用因为系统提示前缀完全一致hit应该变成正数miss明显下降estimated_cost_usd也随之降低。如果你看到第二次的hit大于 0说明缓存生效了。实测下来稳定前缀越长第二次的命中比例越高单次成本下降越明显。这也是为什么工程上建议把系统提示、工具 Schema 这些不变内容放在前面把用户问题放在后面。4.3 用 TaoToken 控制台交叉核对脚本跑完后去 TaoToken 控制台看用量记录。找到对应时间段的调用核对prompt_tokens和completion_tokens是否和你的 JSONL 账单一致。如果一致说明你的解析逻辑没问题如果不一致先检查是不是有别的请求混进来了。控制台入口在 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。5. 本篇常见错排查5.1 usage 是空的最常见的原因是中间层把usage字段丢了。有些封装只返回message不返回完整响应对象。解决方法是确认你用的 Harness 版本会透传usage并且你没有在代码里手动裁剪返回结果。另外流式模式下usage可能只在最后一个 chunk 出现需要单独收集。5.2 缓存命中一直是 0先检查前缀是否真的稳定。系统提示里如果混入了时间戳、随机 ID、动态拼接的用户名前缀每次都变缓存自然不命中。把动态内容移到用户消息里系统提示保持纯静态。其次确认模型和端点一致换模型或换 Base URL 都会导致缓存失效。5.3 费用对不上estimated_cost_usd是估算值实际计费以控制台为准。如果你发现脚本算的和控制台差很多先确认是不是有并发请求没写进 JSONL或者 Key 被别的地方用了。另外缓存命中的 Token 单价和未命中不同如果你的估算公式没区分这两部分结果会偏高。5.4 401 或 403Key 没注入成功或者环境变量名写错了。检查TAOTOKEN_API_KEY是否在当前终端可见别把 Key 写进代码后提交到 Git。如果确认 Key 没问题去控制台看余额和权限范围。5.5 finish_reason 是 length输出被max_tokens截断了。这时候completion_tokens等于你设的上限但内容不完整。算成本时要注意截断的请求照样计费。要么提高上限要么把任务拆小。6. 把成本观测变成习惯到这里你已经有了三样东西一个能提取usage的脚本、一张能聚合的账单表、一套验证缓存命中的方法。接下来要做的不是继续加功能而是把这三样固定成每次实验的收尾动作。我的建议是每次跑完 Harness 实验先看finish_reason是不是stop再看usage有没有写进 JSONL最后跑一遍聚合脚本看当天总费用。如果缓存命中率低于预期回头检查前缀是否稳定。这套动作花不了两分钟但能让你在费用失控之前就发现问题。如果你还没生成统一 Key现在去 https://taotoken.net/console/api-keys?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 建一个接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。想先验证模型返回的usage结构可以直接在模型对话页试一次https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。如果你打算长期跑编码类 AgentCoding Plan 页面有更集中的用量视图https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 。下一篇会接着讲怎么用 pytest 锁住消息、缓存和流式这三条底线让成本观测从手动变成自动。
返回列表