Skip to content

Commit

Permalink
feat: ✨ 添加向量数据库的文档
Browse files Browse the repository at this point in the history
  • Loading branch information
enson0131 committed Jun 13, 2024
1 parent c3e5950 commit 37ed186
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 5 deletions.
3 changes: 0 additions & 3 deletions docs/guide/ai/Embedding之大规模数据拆分.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,3 @@ console.log(splitDocs);

![输出结果](./../../public/assets/ai/9.png)



##
69 changes: 68 additions & 1 deletion docs/guide/ai/Retriever 常见的优化方式.md
Original file line number Diff line number Diff line change
@@ -1 +1,68 @@
# Retriever 常见的优化方式
# Retriever 常见的优化方式

上一节我们通过厂商提供的 Embedding 算法去制作匹配向量,通过 Facebook 提供的 Faiss 作为向量数据库,将数据存储到向量数据库中。

接下来我们将优化 Retriever 检索数据的方式


## MultiQueryRetriever

MultiQueryRetriever 思路,或者说其他解决 llm 缺陷的思路基本都是一致的:加入更多 llm。

而 MultiQueryRetriever 是其中比较简单的一种解决方案,它使用 LLM 去将用户的输入改写成多个不同写法,从不同的角度来表达同一个意思,来克服因为关键词或者细微措词导致检索效果差的问题。

```js
// MultiQueryRetriever:
import "dotenv/config";
import { FaissStore } from "@langchain/community/vectorstores/faiss";
import { BaiduQianfanEmbeddings } from "@langchain/community/embeddings/baidu_qianfan";
import { MultiQueryRetriever } from "langchain/retrievers/multi_query";
import { TextLoader } from "langchain/document_loaders/fs/text";
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
import ollama from './utils/ollama-llm.mjs';
import ernieTurbo from './utils/baidu-llm.mjs';

const loader = new TextLoader('./data/kong.txt');

const docs = await loader.load();

const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 100, // 分块的大小
chunkOverlap: 20, // 块之间的重叠
});

const splitDocs = await splitter.splitDocuments(docs); // 对文章进行切片

const embedding = new BaiduQianfanEmbeddings(); // Embedding-V1是基于百度文心大模型技术的文本表示模型,将文本转化为用数值表示的向量形式,用于文本检索、信息推荐、知识挖掘等场景。

const vectorStore = await FaissStore.fromDocuments(splitDocs, embedding); // 从文档中创建一个向量存储

const retriever = MultiQueryRetriever.fromLLM({ // 通过 LLM 去生存不同的检索
llm: ernieTurbo, // 传入的 LLM 模型
retriever: vectorStore.asRetriever(3), // 向量数据库的 retriever
queryCount: 3, // 生成 3 条不同的描述
verbose: true, // 设置为 true 会打印出 chain 内部的详细执行过程方便 debug
});

const res = await retriever.invoke("茴香豆是做什么用的"); // 一共会生成 9 条数据,再做去重

console.log(`res`, res);
```

执行上面的代码我们可以看到,通过 LLM 目前,可以将我们的描述生成 3 条不同的描述,避免语意偏差。

```js
茴香豆的主要用途是什么?
茴香豆通常用于哪些场合或文化中?
茴香豆在烹饪中有什么作用?
```

因为用户的原始输入是 `茴香豆是做什么用的`,这是一个非常模糊和有歧义性的问题,作为写这个问题的用户,他可能了解想要的答案是 “茴香豆是下酒用的”,但因为自然语言的特点,这是有歧义的的。

MultiQueryRetriever 的意义就是,找出这句话所有可能的意义,然后用这些可能的意义去检索,避免因为歧义导致检索错误。


## Document Compressor



90 changes: 89 additions & 1 deletion docs/guide/ai/Retriever之向量数据库.md
Original file line number Diff line number Diff line change
@@ -1 +1,89 @@
# Retriever 之向量数据库
# Retriever 之向量数据库

经过前面的学习,我们知道了如何对 数据进行加载和切割,接下来我们就要学习如何将数据通过 Embedding 算法转化为向量加载到向量数据库中。

## Embedding

这里我们用最简单的词袋(words bag)模型来描述一下最简单的 embedding 过程,让大家更具象化的理解这个。

简单地说,词袋模型首先将一篇文章拆分成一个个单词,然后将其放入袋子里面。

例如我们有十篇文章,我们可以将文章拆分成一个个单词,然后统计单词出现的次数

```js

第一篇文章:
enson: 10 cool: 5 handsome: 8

第二篇文章:
monkey: 8 cute: 2 handsome: 4

```

那我们尝试构建一个向量,也就是一个数组,每个位置有一个值,代表每个单词在这个文章中出现的次数

`[enson, cool, handsome, monkey, cute]`

那每篇文章,都能用一个变量来表示

```js
[10, 5, 8, 0, 0]
[0, 0, 8, 8, 4]
```

可以用最简单的余弦定理去计算两个向量之间的夹角,以此确定两个向量的距离。 这样,我们就有了通过向量和向量之间的余弦夹角的,来衡量文章之间相似度的能力。

回到我们 RAG 流程中,我们将切分后的每一个文档块使用 embedding 算法转换成一个向量,存储到向量数据库中(vector store)中。这样,每一个原始数据都有一个对应的向量,可以用来检索。

在企业开发中,一般会使用厂商提供的 Embedding 服务,例如



## VectorStore

Vector store 提供提供的是存储向量和原始文档,并且提供基于向量进行相关性检索的能力。

因为 js 并不是一个面向后端和机器学习相关的语言,所以原生的 vector store 并不多,大多数还是以支持 python 为主。目前也有像 [lanceDB](https://lancedb.com/) 原生支持 js 的,但毕竟是少数。

我们将使用由 facebook 开源的 [faiss](https://github.com/facebookresearch/faiss) 向量数据库,目前有 27.7k star,是向量数据库中非常流行的开源解决方案。选择这个的原因是其可以将向量数据库导出成文件,并且提供了 python 和 nodejs 的处理方式。


```js
// 安装 faiss
yarn add faiss-node
```


```js
// https://js.langchain.com/v0.2/docs/integrations/vectorstores/faiss/#create-a-new-index-from-texts
import "dotenv/config";
import { FaissStore } from "@langchain/community/vectorstores/faiss";
import { TextLoader } from "langchain/document_loaders/fs/text";
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
import { BaiduQianfanEmbeddings } from "@langchain/community/embeddings/baidu_qianfan"; // 开通千帆 Embedding 模型, https://cloud.baidu.com/doc/VDB/s/Nltgvlg7k

const loader = new TextLoader('./data/kong.txt');

const docs = await loader.load();

const splitter = new RecursiveCharacterTextSplitter({
chunkSize: 100, // 分块的大小
chunkOverlap: 20, // 块之间的重叠
});

const splitDocs = await splitter.splitDocuments(docs);

const embedding = new BaiduQianfanEmbeddings(); // Embedding-V1是基于百度文心大模型技术的文本表示模型,将文本转化为用数值表示的向量形式,用于文本检索、信息推荐、知识挖掘等场景。

const vectorStore = await FaissStore.fromDocuments(splitDocs, embedding);

const retriever = vectorStore.asRetriever(2); // 获取最相关的俩个文档片段
const res = await retriever.invoke("茴香豆是做什么用的");

console.log(res);

```


![输出结果](./../../public/assets/ai/10.png)

Binary file added docs/public/assets/ai/10.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/public/assets/ai/11.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 37ed186

Please sign in to comment.