Skip to main content

从零开始,用GPT打造个人知识库

要搭建基于GPT API的定制化知识库,涉及到给GPT输入(投喂)定制化的知识。但GPT-3.5,也就是当前免费版的ChatGPT一次交互(输入和输出)只支持最高4096个Token,约等于3000个单词或2300个汉字。这点容量对于绝大多数领域知识根本不够。为了使用GPT的语言能力来处理大量的领域知识,OpenAI提供了embedding API 解决方案。参考 OpenAI embedding documents。

理解embeddings

embeddings(直译为嵌入)是一个浮点数字的向量(列表)。两个向量之间的距离衡量它们的关联性。小距离表示高关联度,大距离表示低关联度。

进一步解释:

  • 向量(列表):向量是数学中表示大小和方向的一个量,通常用一串数字表示。在计算机科学和数据科学中,向量通常用列表(list)来表示。列表是一种数据结构,它包含一组有序的元素。例如,一个二维向量可以表示为 [2, 3],这意味着沿着两个轴的分量分别为2和3。在这里,"list" 是一种编程术语,意味着一系列有序的数据。
  • 向量之间的距离:向量之间的距离是一种度量两个向量相似性的方法。有多种方式可以计算两个向量之间的距离,最常见的是欧几里得距离。欧几里得距离计算方法是将两个向量的对应元素相减,然后取平方和,再开平方。例如,向量A = [1, 2] 和向量B = [4, 6] 之间的欧几里得距离为 sqrt((4-1)^2 + (6-2)^2) = 5。

较小距离意味着高相关性,因为向量间相似度高。在OpenAI词嵌入中,靠近向量的词语在语义上相似。例如,“猫”和“狗”距离近,它们都是宠物,与“汽车”距离远,相关性低。

文档上给了创建embeddings的示例

curl https://api.openai.com/v1/embeddings \
-H "Authorization: Bearer $OPENAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": "The food was delicious and the waiter...",
"model": "text-embedding-ada-002"
}'

上面的命令访问embeddings API接口,将input语句,转化成下面这一串浮点数字。

{
"object": "list",
"data": [
{
"object": "embedding",
"embedding": [
0.0023064255,
-0.009327292,
.... (1536 floats total **for** ada-002)
-0.0028842222,
],
"index": 0
}
],
"model": "text-embedding-ada-002",
"usage": {
"prompt_tokens": 8,
"total_tokens": 8
}
}

使用embeddings

上面将文本转换成向量(一串数字)能大大节省空间,它不是压缩,可简单理解为索引(Index)。接下来就有意思了。比如我有一个大文本,可以先把它拆分成若干个小文本块(也叫chrunk),通过embeddings API将小文本块转换成embeddings向量,这个向量是跟文本块的语义相关。在一个地方(向量储存库)中保存这些embeddings向量和文本块,作为问答的知识库。当用户提出一个问题时,该问题先通过embeddings API转换成问题向量,然后将这问题向量与向量储存库的所有文本块向量比对,查找距离最小的几个向量,把这几个向量对应的文本块提取出来,与原有问题组合成为新的prompt(问题/提示词),发送给GPT API。这样一来就不用一次会话中输入所有领域知识,而是输入了关联度最高的部分知识。

一图胜千言,转一张原理图。

x

再举一个极其简单的例子,比如有一篇万字长文,拆分成Chrunks包含:

  • 文本块1:本文作者:越山。xxxx。
  • 文本块2:公众号越山集的介绍:传播效率方法,分享AI应用,陪伴彼此在成长路上,共同前行。
  • 文本块3:《反脆弱》作者塔勒布xxxx。
  • 文本块4:“科技爱好者周刊”主编阮一峰会记录每周值得分享的科技内容,周五发布。
  • ...
  • 文本块n

如果提问是”此文作者是谁?“。可以直观的看出上面的文本块1跟这个问题的关联度最高,文本块3次之。通过比较embeddings向量也可以得到这结论。那最后发送给GPT API的问题会类似于 ”此文作者是谁?从以下信息中获取答案:本文作者:越山。xxxx。《反脆弱》作者塔勒布xxxx。“ 这样一来,大语言大概率能回答上这个问题。

大语言模型集成库 LangChain

当然可以参考OpenAI Reference调用原生的embeddings API。为了方便的集成使用大语言模型(LLM),开源社区提供了LangChain Python库,提供LLMs之间通用接口,封装了一些数据操作,比如数据加载,访问向量数据库等。

LangChain的核心思想是我们可以“链接”不同的组件,以创建更高级别的LLM用例。其应用场景包括但不限于聊天机器人、生成式问答、摘要等。参考 https://langchain.readthedocs.io/en/latest/index.html

它包含prompts管理,index管理,文档加载器,调用链等模块。该Python库于2022年10月创建,发展很快,本月LangChain获得了Benchmark Capital 1000万刀的投资。近一个月更新更多,基于GPT API的狂热开发热情让它收到众多Issues,新功能也层出不穷。比如最近新加了UnstructuredMarkdownLoader可以方便的加载Markdown文档,常见的PDF,csv,HTML,Directory等更不在话下。

具体使用可关注油管博主@DataIndependent,讲得浅显,入门友好。比如这集讲解了ChatPDF基本工作原理,Question A 300 Page Book (w/ OpenAI + Pinecone)

LangChain 连接大语言模型和外部数据:

x

原Jupytor nb不好用,这里提供一个调整后的Jupyter notebook. 其中会用到pinepone向量数据库。

x

x

GPT模型索引库 LlamaIndex

LlamaIndex 是更高一层LangChain的抽象,之前叫GPT Index。之前的文章基于GPT3.5搭建定制化知识库 中的例子就是使用的LlamaIndex包。它简化了LangChain对文本分割,查询这块的接口,提供了更丰富的Data Connector。LlamaIndex只针对GPT Model做Index,而LangChain是可以对接多个LLMs,可扩展性更强。参考 https://gpt-index.readthedocs.io/en/latest/

写在最后

最近各家大厂接连放大招,AI技术和应用突飞猛进,GPT-4接口已经支持最大32K输入,AI的开发和使用门槛肯定会越来越低,就像当年的Windows, Office。垂直领域知识库的搭建和优化可能更多的是一个业务问题,而不是一个技术问题。欢迎关注公众号”越山集“,多交流。让我们保持好奇心,不断探索,共同进步。