一、多轮对话
1、概念
-
多轮对话(Multi-turn Dialogue) 指的是系统与用户之间进行 连续的问答互动,每一轮都可能依赖之前的对话内容
-
换句话说,它不仅处理当前用户输入,还要理解上下文,以生成更连贯、有针对性的回答
-
例如:
- 用户问:"今天天气怎么样?"
- 助手答:"晴天,28℃。"
- 用户接着问:"那适合去公园吗?"
- 助手会根据之前的“晴天”回答给出建议
2、原理
3、实现
- 修改对话的时候,message 消息的格式就行
4、KV Cache
- KV 缓存(Key-Value Cache)适用于 Transformer 结构中,常用于加速推理或多轮对话的场景,也包含了实际应用层的视角,如 LLM 推理中的 KV 缓存机制
4.1 概述
-
KV 缓存(Key-Value Cache)是一种将 Transformer 中间计算结果(尤其是注意力机制中的 Key 和 Value)缓存起来,从而在解码时避免重复计算的加速技术
-
主要应用场景:
-
LLM 推理加速
-
多轮对话保持上下文效率
-
流式生成
-
4.2 原理
4.2.1 Attention 机制
- 在自注意力机制中:
$$
Attention(Q, K, V) = softmax\left(\frac{QK^T}{\sqrt{d_k}}\right)V
$$
-
Q:当前时间步的 Query -
K、V:历史及当前的 Key 和 Value -
在生成式模型(Decoder-only)中,解码是逐 token 进行的,因此对于每一个新 token:
-
只需要 新增一个Query
-
但是需要和之前的所有Key、Value计算注意力
-
4.2.2 存在价值
- 若每次生成一个 token 都重新计算所有之前的 Key 和 Value,会非常耗时,可以缓存历史的 K/V,在下一步生成时直接复用
4.3 KV缓存结构
通常按层维护:
# 假设模型有 N 层,每层都有自己的 KV 缓存
kv_cache = [
{"key": [T1, T2, ..., Tn], "value": [...]}, # Layer 1
{"key": [T1, T2, ..., Tn], "value": [...]}, # Layer 2
...
]
-
更新方式:
-
每生成一个新token,将其 $K/V$ 附加到对应层的缓存中
-
缓存长度最多为上下文窗口(context length)
-
4.5 应用案例
- 每轮对话传入已有的 KV 缓存
- 模型仅处理新增问题部分的 Query
- 最终合并 KV 缓存,用于下一轮
4.6 注意事项
- 缓存过长:超过最大上下文窗口需截断
- 缓存分离:不同 batch 的缓存要单独存储
- 缓存迁移:KV 缓存不能跨模型版本、设备迁移
- 多语言模型:KV 缓存不兼容多种 Tokenizer 混用
5、对话历史记录
5.1 解释
-
例如:
用户:我叫张三 AI:你好张三 -
下一轮:
用户:我叫什么? -
系统需要:
保存之前对话 -
否则模型根本不知道“张三”是谁
5.2 存储
- 内存中
- redis 中
- PostgreSQL 数据库中【langchain 推荐】
6、KV Cache 和对话历史记录
- 历史记录最终会进入 Prompt
System:
你是AI助手
History:
用户:我叫张三
AI:你好张三
User:
我叫什么?
- Prompt 进入模型后才产生 KV Cache
历史记录 → Prompt文本
Prompt → Token
Token → KV Cache
- 区别
| 对比 | KV Cache | 历史记录 |
|---|---|---|
| 层级 | 模型内部 | 应用层 |
| 生命周期 | 一次推理期间 | 长期存在 |
| 存储内容 | Token的K/V向量 | 原始对话文本 |
| 是否持久化 | ❌ 通常不会 | ✅ 会 |
| 作用 | 推理加速 | 上下文记忆 |
| 用户可见 | ❌ 不可见 | ✅ 可见 |
7、上下文连续对话
- 上下文连续对话(Multi-turn Conversation)的实现,本质上依赖两部分能力协同工作:
7.1 应用层历史记录
-
负责“记忆”用户与模型之前的对话内容
-
通常会保存:
-
用户问题
-
模型回答
-
系统提示词(System Prompt)
-
会话元数据
-
-
常见存储方式:
-
内存(Memory)
-
Redis
-
MySQL / PostgreSQL
-
MongoDB
-
向量数据库(长期记忆场景)
-
-
其核心作用是:
让模型在下一轮对话时能够看到之前的聊天内容。
7.2 KV Cache
-
负责“推理加速”
-
Transformer 在生成 Token 时,会缓存历史 Token 的:
-
Key
-
Value
-
-
下一轮生成时无需重复计算之前的 Attention,从而显著降低推理开销
-
其本质是:
用显存空间换取推理速度。
-
KV Cache 通常存储在:
-
GPU 显存
-
推理服务缓存区
-
-
它属于:
-
模型层优化
-
推理阶段缓存
-
7.3 上下文连续对话完整流程
用户输入
↓
读取历史记录(Memory)
↓
拼接 Prompt
↓
Tokenizer
↓
送入 LLM
↓
Transformer 推理
↓
KV Cache 缓存 Attention
↓
生成回答
7.4 历史记录不能无限增长
- 在实际工程中,历史消息必须进行控制,原因有以下两个
7.4.1 Token 消耗问题
-
大模型是按 Token 计费和计算的
-
历史记录越长:
-
Prompt 越大
-
Token 消耗越高
-
推理成本越高
-
响应速度越慢
-
-
例如:
历史记录 2k tokens
+
用户问题 500 tokens
+
模型输出 1k tokens
- 一次请求可能就达到:高并发场景下成本会迅速增加
3500+ tokens
7.4.2 上下文窗口限制
-
LLM 并不能无限接收文本
-
每个模型都有最大上下文长度,例如:
| 模型 | 上下文窗口 |
|---|---|
| GPT-4o | 128K |
| Qwen 部分模型 | 32K / 128K |
| Llama | 8K ~ 128K |
-
如果超过窗口限制:
-
早期对话会被截断
-
或请求直接失败
-
7.5 常见优化方案
7.5.1 滑动窗口
- 只保留最近 N 轮对话:
最近5轮
最近10轮
-
优点:
-
实现简单
-
成本低
-
-
缺点:
- 长期记忆会丢失
7.5.2 对话摘要
- 使用 LLM 对历史内容进行摘要压缩:
“用户是一名Java开发工程师,
最近在学习RAG系统开发”
-
优点:
-
保留长期语义
-
降低 Token 消耗
-
-
缺点:
- 摘要可能丢失细节
7.5.3 向量检索记忆
-
将历史对话向量化后存入:
-
ChromaDB
-
Milvus
-
FAISS
-
-
对话时:
- 根据当前问题检索相关历史,而不是全部拼接
-
优点:
-
支持长期记忆
-
更适合 AI Agent
-
7.5.4 Memory 分层设计
- 企业级 AI 系统通常采用:
短期记忆 + 长期记忆
- 例如:
| 类型 | 存储 |
|---|---|
| 短期上下文 | Recent Chat |
| 长期记忆 | Vector DB |
| 用户画像 | Profile DB |
-
这样既能保证:
-
上下文连续性
-
又能控制 Token 成本
-
7.6 总结
- 上下文连续对话依赖“历史记录提供记忆”与“KV Cache提升推理效率”共同实现
- 历史记录需要通过滑动窗口、摘要压缩、向量检索等方式进行优化,以解决 Token 成本和上下文窗口限制问题
浙公网安备 33010602011771号