概念
上下文窗口就是大模型能一次处理的文本长度上限,有包括:系统提示词、工具定义、对话历史、工具调用结果、推理过程等。
- Agent是多轮执行的,每一轮都回家新的东西,一个复杂的任务很容易达到几十万token。
- 上下文长度大导致大模型的注意力衰减,中间的信息容易被忽略。
- 上下文长度大会导致推理时间和成本太大。
解决方法
所谓解决方法要从根因上解决:系统提示词、工具定义、对话历史、工具调用结果、推理过程。
滑动窗口( 对话历史**)**
比较垃圾的做法是用滑动窗口来保留最近N轮的对话,更早的就丢掉或者压缩。缺点是容易丢掉关键的记忆。
分层记忆( 对话历史**)**
分层记忆就是把重要的信息写入外部存储,像向量数据库,需要的时候按需通过检索拼到滑动窗口里。
记忆压缩( 对话历史**)**
把比较早的对话用再叫替代,比如说用专门的模型将前N轮的对话压缩成多少token等。有研究表示大模型对窗口的首尾注意力更强,那就是说最好压缩中间部分。
动态加载工具( 工具定义**)**
不将所有工具塞进上下文,根据上下文只加载相关的可能用到的工具。
精简工具描述、合成相关工具、分阶段工具调用( 工具定义**)**
压缩工具的描述,保留工具的关键信息。
将相关的工具合成一个大工具(比如将CRUD用户的工具合成一个用户管理工具)。
将工具名字和描述分开,让模型先选然后再加载详细的描述来让模型挑选。
工具结果截断( 工具结果**)**
一次数据库查询可能返回几千行数据,全塞进上下文既浪费token又干扰模型注
意力。可以只保留前50-100行,或者让模型自己指定只要哪些字段需要多少行数据。
事前控制、事中截断、事后摘要( 工具调用结果**)**
事前控制:在调用工具前就限制返回数据的数量,比如数据库查询加limit,限制接口返回的条数,可以把limit这些参数告诉Agent,让他自己控制。
**事中截断:**在工具返回数据后,在应用层做截断,比如按token按条数截,截断后可以附上数据的总结(统计信息),让模型知道一些样例数据和数据全貌。
**事后摘要:**就是把工具返回的数据,让另外一个专门的大模型压缩成关键信息。
分页加载( 工具调用结果**)**
就是让工具支持limit等参数,告诉大模型第一页的数据以及翻页需要的参数格式,大模型自己决定是否翻页。(需要告诉ai比如说最多翻页多少)
结构化截断( 工具调用结果**)**
截断不是简单的按照token阶段,而是要保留前几条完整数据、数据总数、以及数据统计让模型理解数据结构和特点。比如:
查询到了500条信息,前5条实例:
********
统计:平均成绩:90分,高于90分的50人,低于60分的120人,最高分99,最低分45。
多级压缩( 工具调用结果**)**
- 工具层limit的控制
- 结构化截断
- 如果还超过token阈值,做LLM语义压缩
监控Agent 的上下文使用
在应用层做token技术,每轮或者几轮循环前算一下上下文大小,接近阈值就压缩(可以这样设置:先压缩早期对话,接着截断工具结果,然后还是不行的话吧关键的记忆持久化然后卡一个新的对话(chatgpt就有这样的方式))。
大模型对上下文的注意力问题
大模型对上下文首尾的注意力比较强,可以将系统提示词放到首位将关键的信息放到尾部,压缩的历史信息放到中间。