前言
写了一堆P话,被我删了,今天主要谈谈模型记忆力的问题。
很显然的是,我们需要模型具有更长,更准确的记忆力,才能更好的进行对话,或支持业务。
具体做法往下看。
模型记忆力的重要性
略,
如果你不知道模型记忆力的重要性,可以划走了
基座模型
每个模型自身能够容纳的tokens是有限的,它的容量,是一般意义上的模型记忆力的大小,也就是所谓的上下文窗口大小。
但是,它是非常宝贵和稀缺的。即便是openai新发的gpt-4-1106-preview gpt-4-0125-preview,也依然只有128k大小,看起来很多,但实际用起来完全不够用。
如果你在初期用的3.5,后面想增加模型的短期记忆能力,可以直接通过更换基座模型来实现。
如果你已经在用128k的模型,想继续增加记忆力,请继续阅读。
短期记忆力
一般来说,所谓的短期记忆力,就是你和模型在过去,一段时间内发生的行为和结果。
简单来说就是聊天的上文。
会话
在实际应用的时候,我们并不会将所有聊天内容当做一个会话处理,而应该是一段一段的会话。
举个例子,我们在chatgpt上聊天,如果是一个新的话题,我们通常会新建一个对话。这个时候,你在不同的对话上聊天,就会携带不同的上下文。
对应到我们的应用中,比如openai平台上的助手,或者苹果手机上的sami,我们会在一个对话里一直聊,这种情况下,就需要先将一整个对话,切成一段段的会话(session
)。这个时候,我们聊天只需要携带当前会话的上文即可。
我们之后提到的,所有上下文,都是指当前会话中的记录。
至于会话窗口如何切分,不是本文重点,如果有需要,我以后单开一文说。
记录召回
只要一直聊天,会话记录总有超过限制的时候,这种情况下,可以采用召回记录的方法避免窗口限制。
这种方法很好理解,假设窗口大小为10,每次聊天(query
)的时候,基于query对过往100条记录召回10条,作为聊天上下文传给模型。
通过这种方式能够极大的增加短期记忆力。
当然缺点也很明显,这会带来极大的开发成本。需要将每个记录向量化处理,召回也会增加耗时,准确率不够高的时候,会让模型效果劣化。
记录总结
同样是优化记录的思路,对过往记录用模型进行总结,提取关键信息,在聊天的时候作为上下文传值给模型。
实时情况下,耗时超高。(小模型的耗时还可以)
离线情况下,效果劣化严重。
LongLLMLingua 关键信息提取
LongLLMLingua
的思路是,在大模型执行之前,先用小模型进行关键信息提取,也可以理解为对内容进行压缩。
这就一定程度上允许我们有更大的窗口。
实际测试效果不明显。偶尔有延时问题,小模型对效果影响明显。由于它是直接对token进行压缩,框架依赖度比较高。
长期记忆力
PE动态组装
用户个性化是大模型应用中,非常重要的一环,也是模型具有长期记忆力最明显的表现。
举个例子,我们的云端存储着用户的画像,在和模型对话的时候,将画像中的内容组装到prompt中,这时候模型对每个用户的反应就是不同的。
同理,我们可以将一些已知的用户相关的内容memory
放入到prompt,不仅限于用户信息,也可以是时间,地点,从而让模型拥有长期记忆力。
这属于一个基础能力,实际应用中可能用户信息非常多,需要先召回。
我们并没有用现成的LangChain
中的memory模块,而是把这个功能做在了用户画像系统里。
记忆关注和更新
如果你的系统没有用户的画像,或者用户相关的信息缺失。
这时候可以用模型提供的function call
的功能,慢慢补全用户信息。
举个例子,我们在tools中声明一个function,它的入参是用户姓名。用户在聊天的时候,如果出现类似"俺是王大锤"的记录,就会回调我们的function,我们可以在数据库中更新这个信息。从而让模型具有长期记忆力和更新记忆力的能力。
实际体验相对很好,在不同的模型中表现都还可以。
knowledge
knowledge
主要体现了用户无关的记忆力,比如司内比较私密的信息,或者特定领域的专属知识。
这个方案比较成熟,langchain中也有现成的能力,算是基础功能之一了。
记忆提取
短期记录能提取,长期记忆当然也能提取。
就像让模型对一篇文章进行总结那样,对会话信息进行记忆力相关的信息提取。
和短期记忆提取不同的是,长期记忆的提取通常是离线的,可以用一些比较复杂的模型,效果更好。
实际体验还行,不同用户之前表现还是有很大差异的。
更多方案验证中,待补充。。。
尾语
我们在大模型应用时,往往关心的是agent,rag,pe这种分门别类的。但是实际应用往往是综合起来的。
在记忆力,耗时,成本等等方面上都需要加以考量。
比如gpt4的窗口更大,短期记忆更长,但是成本更高,耗时更长。3.5虽然窗口小,但是成本低,速度快。实际用那个药根据具体的情况来。