现在ChatGPT的API是无状态的,意味着你需要自己去维持会话状态,保存上下文,每次请求的时候将之前的历史消息全部发过去,但是这里面有两个问题:1. 请求内容会越来越大;2. 费用很高。
今天在Twitter上看到有人分享的一个很好的解决方案,可以借助OpenAI的embedding模型和自己的数据库,现在本地搜索数据获得上下文,然后在调用ChatGPT的API的时候,加上本地数据库中的相关内容,这样就可以让ChatGPT从你自己的数据集获得了上下文,再结合ChatGPT自己庞大的数据集给出一个更相关的理想结果。
这种模式尤其适合针对一些特定著作、资料库的搜索和问答。我想之前有人做了模拟乔布斯风格的问答应该也是基于这种模式来做的。
具体解释一下它的实现原理(参考图一)。
首先准备好你要用来学习的文本资料,把它变成CSV或者Json这样易于处理的格式,并且分成小块(chunks),每块不要超过8191个Tokens,因为这是OpenAI embeddings模型的输入长度限制
然后用一个程序,分批调用OpenAI embedding的API,目前最新的模式是text-embedding-ada-002,将文本块变成文本向量。
platform.openai.com/docs/guides/embeddings/what-are-embeddings
这里简单解释一下,对于OpenAI来说,要判断两段文本的相似度,它需要先将两段文本变成数字向量(vector embeddings),就像一堆坐标轴数字,然后通过数字比较可以得出一个0-1之间的小数,数字越接近1相似度越高。
所以要借助OpenAI检索相似度,将文本编码成数字向量必不可少。
(参考图一从Script到OpenAI的步骤)
当然你保存的时候,需要把原始的文本块和数字向量一起存储,这样才能根据数字向量反向获得原始文本。
这一步有点类似于全文索引中给数据建索引。
(参考图一从Script到DB的步骤)
(参考图一 Search App到OpenAI)
拿到这个数字向量后,再去自己的数据库进行检索,那么就可以得到一个结果集,这个结果集会根据匹配的相似度有个打分,分越高说明越匹配,这样就可以按照匹配度倒序返回一个相关结果。
(参考图一 Search App到DB的步骤)
当用户提问后,需要先根据提问内容去本地数据库中搜索到一个相关结果集。