Token 计费、吞吐与成本意识:先做预算再谈规模
正在读取学习记录…
模型调用的费用通常与请求和响应中的用量有关。Agent 可能为一个任务多次调用模型,所以要把整条执行过程的用量合起来看。预算器做两步:调用前预留一笔可能的费用,收到实际用量后再结算。
先用一笔固定教学价格的请求算出预留与结算,运行本地账本,观察余额怎样变化。理解正常路径后,再处理并发调用、重复请求和超时后用量未知的情况。示例人民币价格只为方便算数;接真实服务须核对当时的计费规则。
先修:Token 与上下文窗口、模型 API 与配置和任务建模。前两篇告诉你一次请求装了什么、怎样发出去;任务建模先界定什么才算完成。这里才讨论完成这件事要消耗多少资源。
0. 为什么 Agent 的成本比聊天框更难算
普通聊天也有多轮历史,但 Agent 还会把工具定义、检索材料、工具结果和中间状态带进后续请求。一次业务任务可能出现下面这条轨迹:
| 阶段 | 可能新增的计费内容 | 最容易漏记的地方 |
|---|---|---|
| 理解任务 | 系统指令、用户问题、结构化输出要求 | 固定指令每轮重复进入输入 |
| 检索资料 | 查询改写、候选摘要、引用片段 | 召回太多导致后续每轮输入膨胀 |
| 调用工具 | 工具描述、参数、返回值 | 大段工具结果原样回填 |
| 失败恢复 | 错误信息、再次请求、替代方案 | 重试被当作“同一次请求” |
| 结果复核 | 候选答案、检查规则、修订输出 | 复核模型本身也要计费 |
所以真正需要估算的是“每个业务任务的调用轨迹”,不是首页上那一次请求。先从单次费用算对,再把每次调用用同一个 task_id 串起来。
1. 六个概念先分开
| 概念 | 它是什么 | 常见误解 |
|---|---|---|
| 输入 token | 供应商计入本次请求的输入数量 | 字符数可以直接替代 token 数 |
| 输出 token | 模型实际生成并计费的数量 | 设置上限后一定会生成到上限 |
| 并发 | 同一时刻仍在途的请求数 | 并发 10 就是每秒完成 10 个 |
| 吞吐 | 某个时间窗口内完成的工作量 | 只看发出多少,不看完成多少 |
| 延迟 | 一项请求或任务从开始到结果的时间 | 只记录平均值就能说明体验 |
| 预算 | 系统允许在周期内承担的费用上限 | 环境变量写了 100 就会自动止损 |
限流是供应商或本地系统对请求速率、并发等施加的约束。DeepSeek 当前官方说明把并发连接从请求发出计算到响应完成,超过账户并发上限时返回 HTTP 429。这个数字会随模型和账户变化,不能复制进代码后永远不更新。
2. 按用量和单价计算费用
若供应商分别报告缓存命中输入、缓存未命中输入和输出,用量费用可以写成:
费用 = 命中输入 token × 命中单价
+ 未命中输入 token × 未命中单价
+ 输出 token × 输出单价单价通常按 100 万 token 展示,计算时还要除以 1,000,000。币种、模型版本、价格生效时间和峰谷区间都属于价格配置,不能只保存三个数字。
DeepSeek 的计价项与最新价格可查阅 Models & Pricing。示例代码从配置读取价格;真实系统保存本次请求使用的价格版本,方便费用对账。
浮点数也不适合直接累计货币。二进制浮点无法精确表示许多十进制小数,长时间累加会出现意外尾差。这里使用 Python 标准库 Decimal,并要求价格与金额由字符串构造。
3. 先预留,再调用,最后结算
为什么不在请求结束后才检查余额?假设账户只剩 1 元,十个并发请求同时看见这 1 元,然后各自消费 0.5 元。事后检查已经来不及。生产系统所需的顺序是通过共享存储原子地预留各自的费用上界,预留失败的请求不进入供应商;下文单进程内存账本只演示这个状态顺序,没有证明跨进程的原子性。
预留值可以保守地按“输入全部缓存未命中 + 输出达到最大值”估算:
预留 = 最大输入 × 未命中输入单价 + 最大输出 × 输出单价这不是最终账单。成功响应回来后,用实际的命中、未命中和输出 token 结算,释放多余预留。若请求超时,不知道供应商是否已经完成计算,就把状态记为 unknown,等待查供应商请求记录或账单。直接释放会给下一个请求制造虚假的可用余额。
4. 跑通离线成本账本
复制下方完整代码,保存为 cost_guard.py 和 test_cost_guard.py,放到同一个新文件夹。打开 PowerShell 后进入该目录:
完整代码:cost_guard.py
"""按输入输出Token数量计算费用,并在请求前预留预算。"""
from dataclasses import dataclass
from decimal import Decimal
MILLION = Decimal("1000000")
def _token_count(name: str, value: int) -> int:
if type(value) is not int:
raise TypeError(f"{name} must be an integer")
if value < 0:
raise ValueError(f"{name} must be non-negative")
return value
def _money(name: str, value: Decimal, *, allow_zero: bool = True) -> Decimal:
if not isinstance(value, Decimal):
raise TypeError(f"{name} must be Decimal")
if not value.is_finite():
raise ValueError(f"{name} must be finite")
if value < 0 or (not allow_zero and value == 0):
raise ValueError(f"{name} must be positive")
return value
@dataclass(frozen=True)
class Pricing:
currency: str
input_cache_hit_per_million: Decimal
input_cache_miss_per_million: Decimal
output_per_million: Decimal
def __post_init__(self) -> None:
if not isinstance(self.currency, str) or not self.currency.strip():
raise ValueError("currency is required")
_money("input_cache_hit_per_million", self.input_cache_hit_per_million)
_money("input_cache_miss_per_million", self.input_cache_miss_per_million)
_money("output_per_million", self.output_per_million)
@dataclass(frozen=True)
class Usage:
cache_hit_input: int
cache_miss_input: int
output: int
def __post_init__(self) -> None:
_token_count("cache_hit_input", self.cache_hit_input)
_token_count("cache_miss_input", self.cache_miss_input)
_token_count("output", self.output)
def actual_cost(usage: Usage, pricing: Pricing) -> Decimal:
"""按供应方报告的实际用量计算这次请求费用。"""
return (
Decimal(usage.cache_hit_input) * pricing.input_cache_hit_per_million
+ Decimal(usage.cache_miss_input) * pricing.input_cache_miss_per_million
+ Decimal(usage.output) * pricing.output_per_million
) / MILLION
def reserve_cost(max_input_tokens: int, max_output_tokens: int, pricing: Pricing) -> Decimal:
"""按输入全部未命中缓存、输出达到上限来保守预留。"""
input_count = _token_count("max_input_tokens", max_input_tokens)
output_count = _token_count("max_output_tokens", max_output_tokens)
return (
Decimal(input_count) * pricing.input_cache_miss_per_million
+ Decimal(output_count) * pricing.output_per_million
) / MILLION
class BudgetLedger:
"""用内存演示预留;生产环境需要持久化且原子更新的存储。"""
def __init__(self, limit: Decimal, currency: str) -> None:
self.limit = _money("limit", limit, allow_zero=False)
if not isinstance(currency, str) or not currency.strip():
raise ValueError("currency is required")
self.currency = currency
self.spent = Decimal("0")
self._requests: dict[str, dict[str, Decimal | str]] = {}
@property
def reserved(self) -> Decimal:
return sum(
(record["amount"] for record in self._requests.values()
if record["status"] in {"reserved", "unknown"}),
start=Decimal("0"),
)
@property
def available(self) -> Decimal:
return self.limit - self.spent - self.reserved
def reserve(self, request_id: str, amount: Decimal) -> Decimal:
if not isinstance(request_id, str) or not request_id.strip():
raise ValueError("request_id is required")
amount = _money("amount", amount, allow_zero=False)
existing = self._requests.get(request_id)
if existing:
if existing["status"] == "unknown":
raise ValueError("reconcile required before another reservation")
if existing["amount"] != amount:
raise ValueError("request_id already has a different amount")
return existing["amount"]
if amount > self.available:
raise ValueError("budget is insufficient")
self._requests[request_id] = {"status": "reserved", "amount": amount}
return amount
def settle(self, request_id: str, actual: Decimal) -> Decimal:
actual = _money("actual", actual)
record = self._requests.get(request_id)
if not record:
raise ValueError("reservation not found")
if record["status"] == "settled":
if record["actual"] != actual:
raise ValueError("request_id already settled with a different amount")
return record["actual"]
if record["status"] == "unknown":
raise ValueError("reconcile required before settlement")
if actual > record["amount"]:
raise ValueError("actual cost exceeds reservation")
record["status"] = "settled"
record["actual"] = actual
self.spent += actual
return actual
def mark_unknown(self, request_id: str) -> None:
record = self._requests.get(request_id)
if not record:
raise ValueError("reservation not found")
if record["status"] != "reserved":
raise ValueError("only a reserved request can become unknown")
record["status"] = "unknown"
def reconcile(self, request_id: str, confirmed_actual: Decimal) -> Decimal:
"""独立确认实际金额后,结清这条结果未知的请求。"""
actual = _money("confirmed_actual", confirmed_actual)
record = self._requests.get(request_id)
if not record:
raise ValueError("reservation not found")
if record["status"] == "settled":
if record["actual"] != actual:
raise ValueError("request_id already settled with a different amount")
return record["actual"]
if record["status"] != "unknown":
raise ValueError("only an unknown request can be reconciled")
if actual > record["amount"]:
raise ValueError("actual cost exceeds reservation")
record["status"] = "settled"
record["actual"] = actual
self.spent += actual
return actual
if __name__ == "__main__":
usage = Usage(cache_hit_input=200_000, cache_miss_input=300_000, output=50_000)
estimate = reserve_cost(500_000, 100_000, PRICING := Pricing(
"CNY", Decimal("0.20"), Decimal("2.00"), Decimal("8.00")
))
observed = actual_cost(usage, PRICING)
ledger = BudgetLedger(limit=Decimal("100.00"), currency="CNY")
ledger.reserve("demo-001", estimate)
ledger.settle("demo-001", observed)
print(f"reserved={estimate} {ledger.currency}")
print(f"actual={observed} {ledger.currency}")
print(f"available={ledger.available} {ledger.currency}")完整代码:test_cost_guard.py
# 核对Token 计费、吞吐与成本意识的正常结果和错误分支;断言失败时会显示对应的测试。
import unittest
from decimal import Decimal
from cost_guard import BudgetLedger, Pricing, Usage, actual_cost, reserve_cost
PRICING = Pricing(
currency="CNY",
input_cache_hit_per_million=Decimal("0.20"),
input_cache_miss_per_million=Decimal("2.00"),
output_per_million=Decimal("8.00"),
)
class CostFormulaTests(unittest.TestCase):
def test_cost_separates_hit_miss_and_output_tokens(self):
usage = Usage(cache_hit_input=200_000, cache_miss_input=300_000, output=50_000)
self.assertEqual(actual_cost(usage, PRICING), Decimal("1.04"))
def test_reservation_uses_cache_miss_and_maximum_output(self):
self.assertEqual(reserve_cost(500_000, 100_000, PRICING), Decimal("1.80"))
def test_boolean_negative_and_inconsistent_counts_are_rejected(self):
invalid = [
lambda: Usage(cache_hit_input=True, cache_miss_input=0, output=0),
lambda: Usage(cache_hit_input=-1, cache_miss_input=0, output=0),
lambda: reserve_cost(10, -1, PRICING),
lambda: Pricing("CNY", Decimal("NaN"), Decimal("1"), Decimal("1")),
]
for operation in invalid:
with self.subTest(operation=operation), self.assertRaises((TypeError, ValueError)):
operation()
class BudgetLedgerTests(unittest.TestCase):
def test_unknown_reconciles_once_from_confirmed_amount(self):
ledger = BudgetLedger(Decimal("100"), "CNY")
ledger.reserve("req-1", Decimal("1.80"))
ledger.mark_unknown("req-1")
ledger.reconcile("req-1", Decimal("1.04"))
ledger.reconcile("req-1", Decimal("1.04"))
self.assertEqual(ledger.spent, Decimal("1.04"))
self.assertEqual(ledger.available, Decimal("98.96"))
with self.assertRaises(ValueError):
ledger.reconcile("req-1", Decimal("1.05"))
def test_reconcile_rejects_unconfirmed_state_and_over_reservation(self):
ledger = BudgetLedger(Decimal("100"), "CNY")
ledger.reserve("req-1", Decimal("1.80"))
with self.assertRaises(ValueError):
ledger.reconcile("req-1", Decimal("1.04"))
ledger.mark_unknown("req-1")
with self.assertRaises(ValueError):
ledger.reconcile("req-1", Decimal("2"))
self.assertEqual(ledger.available, Decimal("98.20"))
def test_duplicate_reservation_is_idempotent(self):
ledger = BudgetLedger(limit=Decimal("100.00"), currency="CNY")
first = ledger.reserve("req-1", Decimal("1.80"))
second = ledger.reserve("req-1", Decimal("1.80"))
self.assertEqual(first, second)
self.assertEqual(ledger.reserved, Decimal("1.80"))
def test_over_budget_is_rejected_before_external_call(self):
ledger = BudgetLedger(limit=Decimal("1.00"), currency="CNY")
with self.assertRaisesRegex(ValueError, "budget"):
ledger.reserve("req-1", Decimal("1.80"))
self.assertEqual(ledger.reserved, Decimal("0"))
def test_settlement_charges_actual_and_releases_unused_reservation(self):
ledger = BudgetLedger(limit=Decimal("100.00"), currency="CNY")
ledger.reserve("req-1", Decimal("1.80"))
ledger.settle("req-1", Decimal("1.04"))
self.assertEqual(ledger.spent, Decimal("1.04"))
self.assertEqual(ledger.reserved, Decimal("0.00"))
self.assertEqual(ledger.available, Decimal("98.96"))
def test_unknown_result_keeps_reservation(self):
ledger = BudgetLedger(limit=Decimal("100.00"), currency="CNY")
ledger.reserve("req-1", Decimal("1.80"))
ledger.mark_unknown("req-1")
self.assertEqual(ledger.reserved, Decimal("1.80"))
self.assertEqual(ledger.available, Decimal("98.20"))
with self.assertRaisesRegex(ValueError, "reconcile"):
ledger.reserve("req-1", Decimal("1.80"))
def test_actual_cost_above_reservation_requires_reconciliation(self):
ledger = BudgetLedger(limit=Decimal("100.00"), currency="CNY")
ledger.reserve("req-1", Decimal("1.80"))
with self.assertRaisesRegex(ValueError, "reservation"):
ledger.settle("req-1", Decimal("2.10"))
self.assertEqual(ledger.spent, Decimal("0"))
self.assertEqual(ledger.reserved, Decimal("1.80"))
def test_duplicate_settlement_does_not_charge_twice(self):
ledger = BudgetLedger(limit=Decimal("100.00"), currency="CNY")
ledger.reserve("req-1", Decimal("1.80"))
first = ledger.settle("req-1", Decimal("1.04"))
second = ledger.settle("req-1", Decimal("1.04"))
self.assertEqual(first, second)
self.assertEqual(ledger.spent, Decimal("1.04"))
if __name__ == "__main__":
unittest.main()pwd
ls
python --version
python -B -X utf8 cost_guard.py
python -B -X utf8 -m unittest -v test_cost_guard.py它只使用 Python 标准库。正常示例会打印:
reserved=1.80 CNY
actual=1.04 CNY
available=98.96 CNY这三个数来自教学价格:缓存命中输入每百万 0.20 元、未命中 2.00 元、输出 8.00 元。它们只用于检查公式,不是供应商报价。示例先为 50 万最大输入和 10 万最大输出预留 1.80 元;实际用量较少,结算 1.04 元,剩余预算回到 98.96 元。
先读懂两条计算函数
# 按固定输入观察Token 计费、吞吐与成本意识的处理过程和返回结果。
def actual_cost(usage: Usage, pricing: Pricing) -> Decimal:
return (
Decimal(usage.cache_hit_input) * pricing.input_cache_hit_per_million
+ Decimal(usage.cache_miss_input) * pricing.input_cache_miss_per_million
+ Decimal(usage.output) * pricing.output_per_million
) / MILLION
def reserve_cost(max_input_tokens: int, max_output_tokens: int, pricing: Pricing) -> Decimal:
return (
Decimal(max_input_tokens) * pricing.input_cache_miss_per_million
+ Decimal(max_output_tokens) * pricing.output_per_million
) / MILLIONactual_cost 使用已经观察到的三类用量。reserve_cost 暂按没有缓存优惠来预留,因为调用前还不知道供应商会不会给折扣。完整源码会拒绝布尔值、负数和特殊数字:NaN 表示“不是有效数字”,无穷大也不能对应一个可结算的价格。Python 里的 True 虽然能参与整数运算,但“是/否”开关显然不该当作一个 token 数。
账本状态为什么比一个余额数字多
BudgetLedger.reserve() 通过 request_id 保证重复提交不会重复占用;settle() 只允许已经预留的请求结算。若实际费用超过预留,示例停止并要求核对,而不是悄悄让余额变成负数。出现未知结果后,同一个请求 ID 也不能再次预留,避免把一次远端调用变成两次。
这个账本先放在程序内存里,适合观察“预留→结算”的每一步。程序退出,记录会消失;同时启动两个进程,它们也看不到彼此的余额。真正上线收费请求前,要把账本放到共享存储里,用事务或原子更新处理并发,还要记录账户、月份、币种、模型、价格版本和供应商请求 ID。
未知请求怎样恢复结算
超时就像支付后没收到回执:钱可能已经花了,先留住占用,等核对记录后再结算。同目录新建 try_reconcile.py:
# 按固定输入观察Token 计费、吞吐与成本意识的处理过程和返回结果。
from decimal import Decimal
from cost_guard import BudgetLedger
ledger = BudgetLedger(Decimal("100"), "CNY")
ledger.reserve("request-1", Decimal("1.80"))
ledger.mark_unknown("request-1")
print("等待核对:", ledger.available)
ledger.reconcile("request-1", Decimal("1.04"))
print("核对完成:", ledger.available)
ledger.reconcile("request-1", Decimal("1.04"))
print("重复回执:", ledger.available)运行 python -X utf8 try_reconcile.py,依次得到98.20、98.96、98.96。这里传入固定金额观察状态变化;接供应商时,这个金额应来自已核实的请求用量或账单。重复相同回执不会扣两次,金额不一致则要求重新核查。
十一项测试分别守住什么
| 测试类别 | 输入或动作 | 想防止的错误 |
|---|---|---|
| 费用拆分 | 命中、未命中、输出同时存在 | 把全部输入套同一个单价 |
| 保守预留 | 最大输入和最大输出 | 把缓存优惠提前算进可用余额 |
| 非法数据 | 布尔、负数、NaN | 产生无法解释的金额 |
| 幂等预留 | 相同请求 ID 重复提交 | 同一请求占两次预算 |
| 超额拦截 | 预留高于可用余额 | 先调用后发现没钱 |
| 成功结算 | 实际费用小于预留 | 多余预留永久不释放 |
| 未知状态 | 调用结果无法确认 | 把可能发生的费用记成零 |
| 预留不足 | 实际费用超过预留 | 静默超支 |
| 重复结算 | 相同金额再次结算 | 同一请求扣两次 |
另两项测试检查未知请求对账、重复回执和错误状态拦截。你可以把对账金额改为2.00,程序会拒绝超过1.80预留的结算,并保留原占用。
5. 并发、吞吐、延迟和限流怎样一起看
并发是“此刻有多少请求还没结束”,吞吐是“这段时间完成了多少”,延迟是“单个请求等了多久”。如果并发从 5 调到 20,而供应商只能稳定处理 8 个,多出来的请求可能排队、超时或收到 429;吞吐未必达到四倍,预算预留却会立刻增大。
容量测试至少记录:模型标识、输入/输出长度分布、流式与否、并发阶梯、测试时长、成功数、429 数、超时数、p50/p95 延迟和每分钟完成 token。只写“100 并发没问题”没有复查价值。
p50、p95、p99 是延迟的百分位。把100次请求从快到慢排列,p50约对应第50个,p95约对应第95个,p99约对应第99个。p95为2秒表示大约95%的请求在2秒以内完成;剩下少量更慢的请求可能让用户明显感觉卡顿。这些数值帮助看出平均值容易掩盖的慢请求。
重试也不能无条件扩大吞吐。429 通常表示当前请求速度或并发不合适,应按供应商语义处理,并设置总重试上限和退避;参数错误或鉴权失败重复提交不会自动变好。每次真正发到供应商的重试都可能产生用量,需要沿用业务任务 ID,并用新的请求尝试 ID 记录。
6. 100 元上限怎样落到程序里
“每月最多 100 元”至少要回答以下问题:
| 决策 | 需要明确的规则 |
|---|---|
| 周期 | 按自然月、滚动 30 天还是课程会员周期 |
| 主体 | 全站共用、每个用户、每个套餐还是每个项目 |
| 币种 | 供应商以美元计价时使用哪一时点的汇率与来源 |
| 预留 | 按最大输出、历史分位数还是固定单次上限 |
| 未知费用 | 保留多久,由谁核对,何时暂停新请求 |
| 价格变化 | 价格版本何时切换,旧请求按哪一版结算 |
| 并发 | 多个进程如何原子地共享同一额度 |
设定100元预算的应用要把账本放在服务端;浏览器只收到“可用、额度不足或需要对账”的结果,不拿供应商密钥,也不能自行声明价格。免费每日批改额度与人民币成本上限是两层规则:前者控制产品权益,后者控制实际费用,两者都通过才允许调用。
价格或账本出错时,采用失败关闭:价格配置缺失、汇率来源过期、账本不可用或存在大量未知费用时,暂停新的付费批改,仍允许用户阅读和本地做题。价格恢复并核对后,再继续付费请求。
7. 从单次请求汇总到业务任务
每次模型调用至少记录下面这些非敏感字段:
| 字段 | 用途 | 记录方式 |
|---|---|---|
| task_id / request_id | 把多次调用归入同一任务并支持幂等 | 使用程序生成的标识 |
| model / price_version | 确定能力和计价依据 | 保存完整模型名与价格版本 |
| input_hit / input_miss / output | 按类别计算实际费用 | 保存供应商实际返回的用量;缺失时待核对 |
| reserved / actual / currency | 核对预算变化 | 金额与币种分别保存 |
| status | reserved、settled、unknown、rejected | 回执未知时保留 unknown 与预留 |
| started_at / finished_at | 计算延迟和定位价格生效区间 | 使用服务端时间 |
已确认成本是这条轨迹下所有已结算请求的实际费用之和;仍处于未知状态的预留不是账单,不能加进已确认成本。计算剩余额度时则要同时扣除已结算费用和未结算、未知请求的保守预留,避免同一笔额度再次被使用。展示给用户时分列“已结算费用”和“暂时占用”,未知请求查单对账后再更新,不能把占用伪装成已经发生的支出。
8. 常见异常按证据排查
| 现象 | 先检查 | 可能原因 | 下一步 |
|---|---|---|---|
| 费用突然升高 | 任务调用次数、上下文、输出长度、价格版本 | 工具结果变长、重试、模型或价格切换 | 按请求对比新旧用量与单价 |
| 预算很快耗尽 | 并发预留与未知请求数量 | 大量请求同时在途或超时未对账 | 先核对未知请求,再释放剩余预留 |
| 429 增多 | 账户并发、发出速率、重试策略 | 容量达到上限或重试风暴 | 降低发出速率,按约定等待重试 |
| 本地金额与账单不一致 | 用量字段、峰谷时段、币种、价格生效时间 | 旧价格配置、汇率或缓存分类错误 | 按账单逐项复算 |
| 平均延迟正常但用户抱怨 | p95/p99、任务总调用链 | 少量长尾或串行多步调用 | 找出慢请求和对应步骤 |
费用对不上时,先检查记录里是否缺少用量或价格字段。保存原始供应商用量和价格版本,修汇总逻辑时新增修订记录,后续就能解释总价如何变化。
9. Java 与 TypeScript 对照
Python 使用 Decimal;Java 对应 BigDecimal,应从字符串构造并明确舍入;TypeScript 原生 number 仍是二进制浮点,金额可存最小货币单位的整数,或使用经过评估的十进制库。三种语言都需要运行时校验,静态类型不能阻止配置文件里的负数、NaN 或过期价格。
并发账本也不能靠进程内锁跨服务器生效。Java 的 synchronized、Node.js 的单线程事件循环和 Python 的普通对象,都只解决各自进程里的竞争;多实例部署需要数据库事务、条件更新或具备原子语义的共享存储。
10. 改一笔金额,观察余额
课后练习展开习题收起习题
正在读取本地记录…
不调用模型,不执行代码。简答、代码和场景题仅保存答案并展示自查标准,不生成评分、徽章或认证。输入内容不会自动保存,请点击提交;不要填写个人信息或密钥。
选择题 · 怎样估算一次调用费用?
已知输入1000 tokens、输出500 tokens,输入与输出单价分别为每百万tokens 2元和8元,不考虑缓存。费用是多少?
对应知识点:L0-cost
简答题 · 解释一个失败
请写出“Token 计费、吞吐与成本意识:先做预算再谈规模”中一个可能失败的输入或环境,并说明如何记录证据。
对应知识点:L0-cost
代码题 · 增加边界测试
为本篇示例增加正常、边界和失败三组输入,写出预期结果。
对应知识点:L0-cost
场景题 · 结果未知
系统没有足够证据判断任务是否完成时,你会如何设计状态和人工接管?
对应知识点:L0-cost
在 try_reconcile.py 中把两处1.04同时改为0.80,再运行。先预测:预留时仍剩98.20,核对后应剩99.20,重复回执仍是99.20。恢复为1.04后,再把第二次回执改成1.05,观察为什么同一请求不能结算成两个金额。
回顾
用这里账本数字写一张收支卡:调用前预留 1.80 元,拿到实际用量后结算 1.04 元,100 元教学预算剩余 98.96 元。超时且用量未知时,保留预留占用,等查单拿到实际费用再结算。
这是一组为了练习计算而设的人民币价格,不是 DeepSeek 报价。真正接入时,要记录供应商用量字段、价格版本、每笔请求 ID 和预算状态,并用服务端共享账本处理同时到来的请求。当前价格与限制可查 DeepSeek 官方价格和限流说明。下一步读L1 模型输入输出总览。
参考资料
- DeepSeek Models & Pricing:查看当前模型、计价项和价格。
- DeepSeek Rate Limit & Isolation:核对并发定义和 429 行为;具体上限以账户与当前页面为准。
- Python decimal:十进制运算、上下文和异常规则。
- Anthropic Building effective agents:理解 Agent 用成本和延迟换取灵活性的工程取舍。
至此,L0 的知识点按目录走完。回到 L0 总览检查是否能独立运行每个最小实验,再进入 L1:模型交互与结构化输出。
描述会发送给本站维护者,用于修订文章,保存90天。请只填写文章问题,省略个人信息、密钥和内部资料。