为了塞下更多信息 ,我们最后给大模型输入的(context window)他大小是有限制的,比如gpt-4o 这个模型他的context window的限制就只有128k
k是数量单位,1k ===1000 token
1 token约等于 1-1.5个汉字或4个字符
点击查看 openAI token输出输出价格清单
网上有些说法里说 压缩上下文是为了减少每次输入的token消耗,从而实现省钱,其实这不是主要原因。因为压缩token 这件事,要么把当前的历史记给大模型进行压缩(这一步本来就要花钱),要么存进向量数据库(存储费用和每次生成向量的费用本来也是要花钱的)
压缩上下文主要是为了提高信息密度,在有限 context window 里 ,保留最重要的信息,让对话能够持续,并提高模型推理质量 省钱这个事情,只是压缩上下文的副作用。非主意图。
context window的大致的组成部分是:历史会话 + 系统提示词 + rag内容(如果有的话) + 用户输入 + 模型输出
我们说的压缩上下文指的就是压缩 context window 中的 历史会话
context window 中有一个非常重要的组成部分是 历史记录,我们所谓的压缩上下文,主要就是压缩这玩意。
即:把获取所有历史记录,先把他们单独走一次 大模型,让大模型压缩这段历史记录,留下重要信息形成摘要。最后把”摘要”重新作为历史记录拼接回context window。
触发时机:一般来说,我们每次给到大模型以前,都会使用一些库或者自定义方法判断下当前 context window 的大小是否超出限制。一但检测到超出限制了,就走gpt 教程摘要压缩逻辑,然后继续进行当前问答。
示例
javascript 代码案例
python案例
java案例
这种压缩方式的优缺点
- 优点:
- 简单,直观
- 缺点:
- 摘要可能丢掉一些细节
这种方式操作简单暴力,只适合业务不太复杂的聊天机器人
第一种方法是直接压缩当前的历史记录,但如果当前历史记录是在非常非常长,那么他的弊端也明显,压缩之后的摘要,内容会丢失的越来越多。语义向量压缩就是解决这个问题的。
语义向量压缩,就是把对话历史,直接存进向量数据库,然后在后续的每次回答中,再去向量数据库中向量检索相关内容拼接到context window中。
具体步骤如下
- 将历史对话 向量化(embedding),存进向量数据库。
- 新对话时,只取最相关的向量重写成新 prompt。
流程
javascript代码实例
python代码实例
java代码实例
这种压缩方式的优缺点
- 优点:
- 可以长期记忆
- 可以检索最相关的上下文
- 缺点:
- 需要额外数据库
- 模型不知道聊天的 连续语境
这是市面上 AI产品里最常用的方法
主流 AI 系统基本都是这种结构:
很多框架默认就是这种架构,比如:
- LangChain
- LlamaIndex
- AutoGPT
为什么分层记忆最常用
因为它解决了 三个问题:
1.保证上下文连贯
只用向量检索会有一个问题:
模型不知道聊天的 连续语境。
例如:
第二句话如果只用向量检索:
模型可能不知道 Spring Boot 是对刚才教程的补充。
所以必须保留:
2.防止 Context Window 爆炸
历史对话越来越长:
如果全部塞进 context window: 必炸,或者需要裁剪,内容大量丢失
所以要:
3.支持长期记忆
例如:
几天后再问:
如果没有 向量记忆:
模型已经忘了。
所以要:
真实 AI 系统的 Context 结构
假定 当前模型的context window限制128k
一个完整 prompt 通常长这样:
示例:
总共:
超限的取舍
如果我们最后的prompt超出了目标模型的context window的限制,应该做什么取舍。
这取决于你的业务逻辑的权重 ,一般来说:都是 summary memory二次压缩 或 RAG documents 截断,在这两个中做出取舍,其他三个组成部分都非常重要。
总结一波
- 市面上最常用的是ai记忆结构是分层记忆,即:短期记忆+长期记忆+摘要记忆
- 真实的AI系统完整的prompt组成部分大概是:系统提示词 + 对话摘要 + 历史记录 + RAG数据 + 用户输入
- 压缩上下文主要是为了提高信息密度,在有限 context window 里 ,保留最重要的信息,让对话能够持续,并提高模型推理质量
- token计费单位中k是数量
- 单位 k是数量单位,1k ===1000 token
如果对你有用的话
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/275833.html原文链接:https://javaforall.net
