最近GPT相关的开源项目层出不穷,感觉有段时间每天都有几个不同版本的XXGPT出现。生活中我已经时常用到ChatGPT了,虽然答案不保证正确,但多数情况下ChatGPT可以给出来正确的方向。
我也尝试在工作中使用ChatGPT,比较好用的场景是忘记一个函数的接口、一些配置文件的语法、或者是不太熟悉的语言但想写一些很简单的逻辑。这些场景下,通过ChatGPT基本上都可以很快的得到可用的代码。
感受是工作中常用的搜索的场景似乎都可以换用对话的形式来替代,比如每个公司都有很多内部的技术文档或者是业务文档,以对话的形式查询信息肯定比目前的搜索来得高效的多。可是很明显的问题是,我们不可能把内部数据都喂给OpenAI。如果我们可以私有化部署一个类似的ChatBot在公司内部的资料上,来支持基于内部材料的对话就比较合适了。
在开源社区如此活跃的时代,简单的想法基本上都会有现成的实现。就这个需求就看到有个privateGPT的项目。想说看看代码学习一下最近的技术,看了一下代码之后,并没有了解到多少技术细节,只是感觉到软件的工业化程度真的是越来越高了。
和硬件相比,制造软件的生产资料几乎是唾手可得,进一步导致开源社区正在快速地生产出各种组件。像PrivateGPT这种项目,基本上是简单地搭积木。
PrivateGPT主要用到的三个组件是: GPT4ALL, Chroma, 和Langchain。
GPT4ALL:
这个是一个Public的LLM,基本上是从Facebook半自愿放出来的大模型微调出来的;微调用的数据是通过不断调用OpenAI的接口拿到的,居然只花了几百刀就得到了不错的效果,当真是花小钱办大事。
LLM作为一个组件,接口的定义是很简洁明确的。所以也导致了大家很容易地搭积木。LLM(question) -> reply ,如果Prompt是一个问题,LLM本身就是一个问答系统的最上层接口。但我们需要的是让LLM在我们自己的语料上面进行问答,所以我们需要的接口形式是 (question, corpus) -> reply。
在语料不多的情况下,可以简单的把语料作为prompt的一部分给LLM达到同样的效果。也就是 LLM(question+corpus) -> reply。但语料太多的话,LLM不能支持太长的Context,所以就需要先在语料库里面找到和问题相关的内容,再利用LLM输出回答,也就是 Retrieval(question, corpus) -> context LLM(question+context) -> reply。因此这个项目就用到了另外一个包 Chroma 来提供Retrieval的能力。
Chroma:
最近比较火的一个概念叫VectorDB。文档通过模型都就变成了一组vector,所以检索文档的各种操作都涉及到vector之间相似度的比对。Chroma是一个开源的VectorDB,提供了很多上层操作的接口,我理解在最底层还是在比较两个vector之间的相似度。不知道是不是我理解有偏差,但感觉在Vision很早就有这套东西了,比如FLANN,早先很多工作都是在加速这种大规模向量检索的场景。
回到前面的需求,Chroma可以用来先把语料库转成一堆向量 Index(corpus) -> DB,之后再通过 Retrieval(question,DB) -> context 来完成前面需要的检索操作。这里Index()这个接口实际会需要用到具体的某个算法/模型来提取文本特征,Chroma默认是使用SentenceTransformers这个包完成这件事情,当然这里也有很多其他的替代选项可以使用。
到此为止,需要的几个组件都有了。给定一个语料库(corpus),一个问题(question),我们通过搭积木就可以得到私有化部署的问答系统了:
Index(corpus) -> DB # 这个只需要先做一次,和问题无关
Retrieval(question, DB) -> context
LLM(question+context) -> reply
Langchain这个包就是作为工具链把上面这些个操作串起来。
这么看下来,AutoGPT这类项目虽然在宣传上夸大其词,但实际的动机也是有道理的。像这样搭积木的操作确实不太需要太多的经验或者思考,让AI自己快速搭建这样的DEMO不成问题。只是从DEMO到实际应用产生价值,中间还有很多具体而且困难的问题需要更多的思考和创造。