背景
最近Chatgpt很火,在自然语言聊天和问答方面的能力非常的强劲,但不足是Chatgpt的训练数据都是基于2021年之前的网上数据,没法让他帮我回答基于时间较近的网页内容的问题或者基于私人或公司的私有数据进行聊天问答,即Chatgpt没有插上实时搜索网页的能力。虽然当前有new bing,以及chatgpt-retrieve-plugin即将上线,还需要在waiting list里面耐心等待。
最近我们产品想要把我们搜集的财务会计相关知识的网址汇集成一个知识库,能够服务于我们的客户,帮助他们解决财务方面的问题,那么这些专业的私有数据如何当做一个数据源让chatgpt接入集成,并通过聊天QA的方式来获取信息呢?
本文要叙述的方案即通过chatgpt接入私有数据集合,通过聊天的交互方式进行FAQ。
效果
首先我们来看下效果,假使我们的私有数据来自如下网址:kruzeconsulting.com/cash-burn-r… 该网址内容是有关财务相关知识,那么我需要将网站中的内容爬取下来,然后让chatgpt能够理解网站中的内容,用户通过问答的方式获取到对应的知识内容。当然你可以把知识库相关的所有网址都一股脑的往里扔。
由上面两张图可以看到,自然语言的提问均获得了不错的答案(答案也都来自于我们给定的网址),并且将答案相关的URL也展示了出来,完成了一次自然语言的搜索任务。
原理
要解决私有数据的自然语言查询,我觉得要先解决以下几个问题
- 私有数据的存储私有数据需要解决大数据量存储和查询的问题,由于chatgpt是个大语言模型,1750亿个参数,不可能将自己的数据喂给他微调做对应的子任务模型,成本太高。那么必然我们需要将自己的私有数据存储在自己的私有数据库中,这个时候向量数据库(vector database)就出现了
- 如何通过自然语言进行问答自然语言的问答,自然需要借助chatgpt的能力,但是chatgpt的一次Prompt是有字数限制的,我不可能把私有数据所有的数据都一起组装成Prompt来问chatgpt,如何能够突破Prompt的字数限制呢?一个可行的想法就是将私有数据库中相关的内容抽取出来,当做Prompt来问,这是个行之有效的方式。那么如何提取和问答相关性比较大的内容呢,这个时候Embeddings技术就出现了
什么是Embeddings?
OpenAI的官方文档给出了相关的解释:Text Embeddings用于测量文本字符串之间的相关性大小,一段文字你可以看成是有限字符的有序排列,一次Embedding操作就是将一段文本转化为一个vector向量,即浮点数组。通过计算两个向量之间的距离来测量两段文字的相关性。小距离表示高相关,大距离表示低相关。
比如说一下几个短语:
- “狗咬耗子”
- “犬类捕食啮齿动物”
- “我家养了只狗”
那很明显1和2是类似的,即使它们之间没有任何相同的文字。那么怎么让计算机知道1和2很相似呢?
如果我们把之前的短语对应的向量能画在坐标轴上,它看起来像图中那样。短句1和短句2会离得很近,而短句3和他们离得比较远。这样我们就可以通过向量之间距离的计算来判断短语之间的相似度大小。
总结下来Embeddings 可以用于如下场景:
Search (where results are ranked by relevance to a query string)
Clustering (where text strings are grouped by similarity)
Recommendations (where items with related text strings are recommended)
Anomaly detection (where outliers with little relatedness are identified)
Diversity measurement (where similarity distributions are analyzed)
Classification (where text strings are classified by their most similar label)
整体流程
下图是我直接截取@宝玉xp画的流程图,基本上可以很容易得理解整个流程
整个流程可以分为两大部分: 第一大部分:私有数据切片&存储
第二大部分:筛选和提问相关性高的内容整合一齐向Openai提问
第一大部分:私有数据切片&存储:
1、首先需要将原始文本按照固定长度截取为一段一段文本,原因是希望通过openai的Embedding能力生成对应阶段文本的向量数据集合,由于openai对于输入有文本长度的限制,所以需要截取到固定长度。
2、调用openai的Embeddings接口,将一段段文本转成向量,这样每段文本就有一个向量与之对应。
3、将原始文本和对应的向量存储到之前提到的向量数据库中
第二大部分:筛选和提问相关性高的内容整合一齐向Openai提问:
1、将用户输入的问题字符串当做输入,调用openai的Embeddings能力换取对应的vector向量
2、将用户输入文本对应的向量去向量数据库中查询高相似度的向量集合,即对应的相关性文本列表就都查了出来。
3、将从向量数据库中查出来的相关性文本和原始的问题组成一个Prompt直接问chatgpt,既可以得出来结果。
对应的Prompt的结构如下:
You are a helpful assistant. When given CONTEXT you answer questions using only that information, and you always format your output in markdown. You include code snippets if relevant. If you are unsure and the answer is not explicitly written in the CONTEXT provided, you say "Sorry, I don't know how to help with that." If the CONTEXT includes source URLs include them under a SOURCES heading at the end of your response. Always include all of the relevant source urls from the CONTEXT, but never list a URL more than once (ignore trailing forward slashes when comparing for uniqueness). Never include URLs that are not in the CONTEXT sections. Never make up URLs`;
CONTEXT:
There are a couple of different ways to calculate a startup's burn rate. One of the easiest methods is to take the average decrease in the company's cash position over the past several months, exclusive of any financing events. For example, if a company had $300,000 in the bank, then $275,000 the next month, then $250,000 the last month, then the metric would be $25,000 a month. You should also include other non-checking account balances, such as your payment processor, a money market account, a savings account, etc. that likely contain dollars that should be included in the analysis...
Q:
How to calculate BURN RATE?
A:
复制代码
实践
可以基于github.com/gannonh/gpt… Readme的方式搭建,本文就不在赘述,实践中选用的向量数据库为Supabase,最终存储在Supabase里面数据形式大概如下:
引用
Supabase技术文档接入AI搜索后,能支持自然语言,能写代码,甚至能debug,估计很多人好奇它是怎么实现的。 https://t.co/WRumhepdR6 by @dotey(宝玉)