【Token分析】从单轮到多轮:Ark / OpenAI 风格大模型 API 的上下文管理与 Token 成本分析

从单轮到多轮:Ark / OpenAI 风格大模型 API 的上下文管理与 Token 成本分析

一、单轮请求

1.1 单轮请求是什么

​ 首先,我们用最简单、也是最基础的方式发起一次模型请求,生成初始响应。

  • 所谓单轮请求,是指:
    • 本次调用不依赖任何历史对话
    • 模型只根据当前输入完成一次推理
    • 每一次请求之间完全相互独立
  • 本质上,这是一场一次性、无记忆的推理过程
  • 请求实现如下:
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["VOLC_ACCESS_KEY"],
    base_url="https://ark.cn-beijing.volces.com/api/v3"
)

initial_input = [
    {"role": "system", "content": "你是一名技术文档写作助手"},
    {"role": "user", "content": "请帮我总结以下内容的核心观点:Python 是一门广泛使用的编程语言,适合数据分析、人工智能开发和自动化脚本。"}
]

first_response = client.responses.create(
    model="deepseek-v3-1-terminus",
    input=initial_input
)

print("第一次响应:")
print(first_response.output_text)
print("Token 消耗:", first_response.usage)

1.2 system / user 在单轮中的职责

  • 在这一请求中,消息只包含两种角色:

    • system:定义模型的角色与行为边界
    • user:描述当前需要完成的具体任务
  • 需要特别强调的是:模型是无状态的(stateless)

  • 所谓“对话能力”,并不是模型在内部保存了记忆,而是由调用方在每一次请求中显式携带上下文信息

    换句话说:

    • 模型不会记住你之前问过什么
    • 如果你不把历史内容传给它,它就一定会“忘记”

1.3 单轮请求中的 Token 消耗

​ 本次请求返回的 response.usage 如下,包含了完整的 Token 使用情况。

ResponseUsage(
    input_tokens=35,
    input_tokens_details=InputTokensDetails(cached_tokens=0),
    output_tokens=149,
    output_tokens_details=OutputTokensDetails(reasoning_tokens=0),
    total_tokens=184
)

​ 这意味着,所有输入 Token 都是首次计算,没有任何上下文复用(cached_tokens=0)。

  • 各字段含义如下:
字段含义说明
input_tokens本次发送给模型的 token 数量包含 system + user 的 token 编码长度,这里是 35
input_tokens_details.cached_tokens缓存 token 数量0 表示本次没有复用缓存 token
output_tokens模型生成的 token 数量149,表示模型输出长度
output_tokens_details.reasoning_tokens推理/中间 token0,一般用于计划式推理模型
total_tokens总消耗 token184 = input + output

​ 在单轮场景下,这样的消耗是可预测且稳定的

二、从单轮到多轮:问题从哪里开始

​ 单轮请求非常适合演示、测试和一次性任务。但在真实应用中,用户往往会不断追问:

  • “能再详细一点吗?”
  • “你刚才的结论和 XX 有什么关系?”
  • “基于前面的讨论,给我一个方案。”

​ 此时,如果模型无法理解“之前发生了什么”,对话就无法继续。于是,多轮对话成为几乎所有 LLM 应用的默认形态。

三、多轮对话的挑战:显式拼接历史

3.1 最直观的多轮实现方式

​ 在多轮对话中,最常见、也最直观的实现方式是:每一轮都将 system + 历史消息 + 新 user 输入 一并发送给模型。

messages = [
    {"role": "system", "content": "你是一名技术助手(长文档)"},
    {"role": "assistant", "content": first_response.output_text}, # 显式加入上一轮回答
    {"role": "user", "content": "它和 RNN 的 hidden state 有什么区别?"}
]

response = client.responses.create(
    model="deepseek-v3-1-terminus",
    input=messages
)

print(response.output_text)
print("Token 消耗:", response.usage)

3.2 关于assistant

  • 在消息序列中,assistant 并不是模型自动保存的记忆,而只是一个普通的输入字段
    • 它的内容,来自上一轮模型生成的文本结果
    • 它是否出现,完全由调用方决定
  • 可以从工程角度这样理解:assistant 是一段被重新发送给模型的“对话日志”,而不是模型内部的状态。
  • 模型并不知道哪些内容是“历史输出”,它只是在处理你当前提供的 input。

3.3 为什么要传入 assistant

​ 是否传入 assistant,会直接影响模型的行为:

  • 传入 assistant

    • 模型可以基于上一轮回答继续推理
    • 多轮输出具备连贯性
  • 不传 assistant

    • 模型无法感知上一轮内容
    • 可能重复回答,或偏离上下文

    这再次印证了一个核心事实:多轮对话的连续性,完全是由输入 Token 构造出来的效果。

3.4 显示拼接Token消耗

​ 对多轮调用进行统计,返回的 response.usage 为:

ResponseUsage(input_tokens=105, input_tokens_details=InputTokensDetails(cached_tokens=0), 
output_tokens=1054, 
output_tokens_details=OutputTokensDetails(reasoning_tokens=0), total_tokens=1159)

  • 各字段含义如下:
字段含义说明
input_tokens本次请求传给模型的 token 数量包含 system + assistant + user 的编码长度(这里是 105)
input_tokens_details.cached_tokens缓存 token 数量0 表示没有复用历史内容,全部重新计费
output_tokens模型生成的 token 数量1054,表示模型生成了较长回答
output_tokens_details.reasoning_tokens推理/中间 token0,通常用于计划式或链式推理模型
total_tokens总 token 消耗1159 = input + output,表示本次调用的全部成本

3.5 显式拼接的成本

  • 显式拼接历史虽然简单,但存在明显代价:
    • 每一轮都会重复计算:system、所有历史 assistant
    • Token 成本会随轮数线性增长
    • 对长系统提示或长回答尤为明显
  • 从本质上看:显式拼接历史,是一种用 Token 换取上下文连续性的方案。
  • 它实现简单、行为直观,但并不适合长对话或高频调用的生产环境。

四、小结

  • 大模型 API 本身是无状态的

  • 多轮对话并不是模型的“记忆能力”,而是调用方通过输入 Token 显式模拟出来的效果

  • 在最直观的实现方式下,上下文连续性与 Token 成本几乎等价增长

    理解这一点,是后续讨论 上下文缓存、摘要压缩、向量检索(RAG) 等优化手段的前提。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值