补充说明:Ark中关于previous_response_id的使用需要结合上下文缓存机制。
一、引言:为什么“上下文复用”在工程中很重要
1.1 多轮对话是 LLM 工程的常态
在真实的 LLM 工程场景中,多轮对话几乎是默认形态。
-
一个典型的请求通常包含:
- 较长的 system prompt(角色设定、规则约束、业务或技术文档)
- 连续的 用户追问
- 对模型在多轮中 保持语义连续性 的要求
-
这意味着,模型并不是只完成一次性问答,而是需要在多轮交互中持续“沿着同一上下文”进行推理与生成。
1.2 显式拼接历史带来的工程问题
最直观、也是最常见的实现方式,是在每一轮请求中:显式拼接 system + 历史消息 + 新的 user 输入,一并发送给模型。
这种方式虽然简单,但在工程上会迅速暴露问题:
- Token 成本线性增长
system 和历史内容在每一轮都会被重复编码和计费 - 推理延迟增加
输入越长,模型处理时间越久 - 更容易触及上下文窗口上限
长对话在实际运行中难以持续 - 输出质量不稳定
历史信息冗余,模型更容易生成重复或偏离重点的回答
1.3 工程问题:Token 成本线性增长
显式拼接的直接后果是:system 和历史内容会在每一轮被重复编码并计费。
由此带来的工程问题包括:
-
Token 成本随轮数线性增长
-
推理延迟逐轮增加
-
更容易触及模型上下文窗口上限
-
历史信息冗余,输出稳定性下降
当 system prompt 较长、对话轮数较多时,这些问题会被进一步放大。
1.4 一个容易产生的误解:服务端“上下文复用”
在 OpenAI 官方 Responses API 中,存在 previous_response_id 等机制,可以由服务端缓存历史上下文,从而减少重复的 input token 计费。
因此,很多工程师在使用 火山方舟 Ark 时,也会自然地产生一个预期:Ark 是否也提供了类似的“服务端上下文复用”能力?
本文正是围绕这一问题展开。
二、一个重要澄清:Ark 并不提供 server-side 上下文复用
2.1 API 兼容 ≠ 能力等价
火山方舟 Ark 的 Responses API 在接口风格上与 OpenAI 保持高度兼容,但兼容接口形式,并不意味着能力完全一致。
在查阅 Ark 官方文档后可以确认:Ark 当前并未对外提供 previous_response_id 这类服务端上下文缓存能力。
换句话说,Ark 的每一次调用,本质上仍是 完全无状态的请求。所有上下文管理,都需要由调用方自行完成
2.2 为什么传了 previous_response_id 也“不报错”
在实际代码中,即使你在调用时传入了 previous_response_id:
client.responses.create(
model="deepseek-v3-1-terminus",
previous_response_id="xxx",
input=[{"role": "user", "content": "..."}]
)
请求通常依然可以成功返回。
-
原因在于:
- Ark 使用 OpenAI SDK 兼容层
- SDK 不会对未生效字段强制校验
- 服务端会 直接忽略该字段
-
因此你看到的现象是:
- 请求成功
- 响应正常
- 但 token 行为与“没有上下文复用”完全一致
这并不是缓存未命中,而是 功能本身并不存在。
三、Ark 的真实对话模型:完全无状态
3.1 模型不会“记住”任何历史
在 Ark 中模型不会自动保留任何历史对话状态。
每一次调用,模型只会看到你本次请求中显式提供的 input。
3.2 assistant 消息的真实含义
在多轮对话中,assistant 消息常常让人产生误解。
-
需要明确的是:
assistant不是模型的内部记忆- 它只是你将 上一轮输出的文本副本 再次发送给模型
- 模型会将其当作普通上下文内容重新编码
-
因此:是否保留历史、保留多少历史,完全由调用方决定。
四、Token 消耗是如何产生的
在 Ark 的 Responses API 中,每一次请求都是完全独立的。模型不会记住任何历史上下文,token 的计算也只基于本次请求体中实际发送的内容。
4.1 Token 的构成来源
-
一次请求中的 token,通常来自三部分:
- system 消息:角色定义、规则说明、长提示词
- user 消息:当前用户输入
- 显式拼接的历史消息(如有)
-
这些由调用方手动拼接进请求
⚠️ 无论内容是否“之前发过”,只要再次发送,就会再次计费
4.2 为什么多轮对话 token 会线性增长
在多轮对话中,如果你采用:
system + user1 + assistant1
system + user1 + assistant1 + user2
system + user1 + assistant1 + user2 + assistant2
那么:
-
system 会被重复编码
-
历史 assistant 输出也会反复计费
-
token 数量随轮次近似线性上升
这是调用策略带来的结果,而不是模型“记住了上下文”。
4.3 一个常见误区
有一个常见误区,“我用了 assistant role,模型应该记住上下文吧?”这种想法是错误的。原因如下:
assistant只是请求中的一个 role 字段- 模型并不知道哪些是“旧输出”
- 是否复用,完全取决于你是否再次发送文本
五、Token 与成本分析:输入 vs 输出(工程视角)
理解 token 的来源后,才能讨论钱真正花在哪里。
5.1 输入 token(Input Tokens)
- 含义:发送给模型的所有 token,包括:system + user + 显式历史
(1) 成本特征
- 单价通常低于输出 token
- 但在多轮对话中,历史累积极快
(2) 在 Ark 上可行的优化策略
- 精简 system prompt(避免“万能模板”)
- 不重复发送完整长文档
- 将历史对话 摘要化 / 结构化后再发送
- 只保留对当前任务真正有用的上下文
核心原则:减少“重复但无信息增量”的输入
5.2 输出 token(Output Tokens)
- 含义:模型实际生成的文本 token
(1) 成本特征
-
单价通常高于输入 token
-
往往是总成本的大头
(2) 优化策略
- 明确设置
max_output_tokens - 拆分长任务为多次短生成
- 优先使用摘要 / 结构化输出,避免冗余表达
5.3 输入 vs 输出:工程上的取舍
| 类型 | 成本特征 | 主要风险 | 优化方向 |
|---|---|---|---|
| 输入 token | 单价低,易累积 | 历史重复发送 | 精简、摘要、裁剪 |
| 输出 token | 单价高,占比大 | 模型啰嗦 | 限长、拆分、明确指令 |
在 Ark 场景下:上下文管理的本质,是输入 token 的工程治理,而不是平台能力。
综上所述,Token 成本不是模型问题,而是请求构造问题。
五、在没有上下文复用的前提下,如何做 Token 优化
既然 Ark 不提供 server-side 上下文缓存,那么工程优化的重点就非常明确了:通过调用方策略,降低重复输入和冗余输出。
5.1 固定 system,本地缓存
- system prompt 尽量保持稳定
- 在应用层统一管理
- 避免在不同模块中重复拼接、微小改动
5.2 历史消息压缩与摘要
常见策略包括:
- 只保留最近 N 轮
- 将早期对话压缩为摘要
- 用结构化状态替代自然语言历史
5.3 控制输出长度
- 合理设置
max_output_tokens - 避免无约束的长文本生成
- 将长任务拆分为多步
5.4 任务级上下文而非对话级上下文
在很多场景下:
- 任务状态比自然语言历史更重要
- 明确结构化输入,反而能降低 token 消耗并提升稳定性
六、工程实践建议
- 不要假设 Ark 提供 server-side 上下文复用
- 把 Ark 调用视为 完全无状态请求
- 上下文管理与 token 优化,必须在调用方完成
- 优先减少输入冗余,其次控制输出长度
七、总结
- 火山方舟 Ark 当前不提供
previous_response_id等服务端上下文缓存能力 - API 风格兼容,并不意味着能力等价
- 多轮对话的上下文管理,需要完全由调用方实现
- 工程上真正稳定的 token 优化,来自:
- 固定 system
- 历史压缩
- 输出控制
理解这一点,才能避免对上下文复用产生不切实际的预期。
1225

被折叠的 条评论
为什么被折叠?



