之前我们实现过一个基于本地文档的QA系统,这就是所谓的RAG应用。

其全称为Retrieval-Augmented Generation 也就是检索增强生成,将文档检索和回答生成结合,可以给大模型赋予外部文档数据库查询的能力,在进行回答的时候,可以利用外部数据库进行查询,从而生成合适的回答。这也是当今企业实际中最常见的需求。

RAG的工作过程可以分为

对文档进行检索,这一步往往是将输入文本向量化后和文档向量进行匹配。

然后是上下文编码,根据文档进行一起编码。

最后是生成,使用编码的上下文,一同计算后输出答案。

那么我们看下RAG在LangChain中相关的组件。

1.     文档加载

这一部分很简单,直接使用由LangChain提供的不同种类的文档加载器。

图片

https://python.langchain.com/docs/modules/data_connection/document_loaders/

2.     文档转换

基本上就是将长文档转换为更小的块,从而方便模型的加载。

https://python.langchain.com/docs/modules/data_connection/document_transformers/

其就是将文本切分为小的块

然后将这些小的块组合为一个更大的块,在组合的过程中会加入一些上个块的文档,从而保持块之间的上下文。

对于实际的切分,可以由分隔符,或者有特殊结构体,或者是根据LLM的令牌进行分割。

图片

比如支持分隔符,或者html,markdown中标签,标题

或者token,主要是为了兼容token的长度。

关于不同的长度选择,也可以参考任务类型,比如任务需要比较细致的情感分析,可以考虑较小的块,如果需要全面了解文本,那么可以考虑较大的块。

除此外还有些配合文本转换的工具

比如过滤冗余的文档,使用EmbeddingsRedudantFilter工具来识别相似文档并过滤

比如利用doctran进行文档翻译

比如提取元数据信息

3.     文档嵌入

利用LLM进行嵌入,可以将文本转换为数值表示。可以在得到用户输入的时候,尽快搜索到合适的文本

如何获取一个Embedding类,如何利用其将文本块转换为向量,这些其实都在之前有使用过。

这里我们重复展示下

from langchain_openai import OpenAIEmbeddings

embeddings_model = OpenAIEmbeddings(openai_api_key=”…”)

其具有两个方法

一个是embed_documents 为文档创建嵌入,接收多个文本作为输入,并获取其向量表示。

另一个是embed_query 为查询创建嵌入,只接收一个文本作为输入

https://python.langchain.com/docs/modules/data_connection/text_embedding/

embeddings = embeddings_model.embed_documents(

[

“Hi there!”,

“Oh, hello!”,

“What’s your name?”,

“My friends call me World”,

“Hello World!”

]

)

len(embeddings), len(embeddings[0])

(5, 1536)
embedded_query = embeddings_model.embed_query(“What was the name mentioned in the conversation?”)

embedded_query[:5]

[0.0053587136790156364,

-0.0004999046213924885,

0.038883671164512634,

-0.003001077566295862,

-0.00900818221271038]

在计算嵌入完成之后,为了减少每次计算带来的性能消耗,可以对计算的存储进行缓存,也可以直接进行存储

对于缓存,我们不多说,简单说可以直接使用CacheBackedEmbeddings

对于存储,则是使用Vector Store来进行保存。也就是所说的向量数据库

这里常见的有Chroma FAISS Lance等

图片

针对上述的向量数据库,我们需要根据需求进行选型。

根据数据的规模,成本,社区规模,特性来进行具体的选型。

4.     向量检索

最后我们要说的是根据向量去检索其他的向量,也就是根据用户输入检索我们向量数据库中的数据。

在LangChain中,向量检索器是封装程度相当之高的。

# 设置OpenAI的API密钥

import osos.environ[“OPENAI_API_KEY”] = ‘Your OpenAI Key’

# 导入文档加载器模块,并使用TextLoader来加载文本文件

from langchain.document_loaders import

TextLoaderloader = TextLoader(‘LangChainSamples/OneFlower/易速鲜花花语大全.txt’, encoding=’utf8′)

# 使用VectorstoreIndexCreator来从加载器创建索引

from langchain.indexes import Vectorstore

IndexCreatorindex = VectorstoreIndexCreator().from_loaders([loader])

# 定义查询字符串, 使用创建的索引执行查询

query = “玫瑰花的花语是什么?”

result = index.query(query)

print(result) # 打印查询结果

其使用相对简单,但内部还是调用了不同的Vector Store存储,以及相关的模型进行向量解析。

https://python.langchain.com/docs/modules/data_connection/retrievers/

5.     索引

最后是索引,其本质上就是避免重复内容,提高查询效率的组件

LangChain利用记录管理器(RecordManager)来跟踪文档是否被写入了向量存储

https://python.langchain.com/docs/modules/data_connection/indexing

如果一个文档已经保存完成了,相关信息就会被记录在记录管理器中

其中包含文档哈希 写入时间等信息。

从而确保其被正确的管理和索引了。

那么我们总结一下,我们说了RAG的基本使用

对于这类非结构化的数据,需要进行向量生成,并根据向量进行搜索。

所以分为了文本加载,文本分割,向量解析,向量搜索等步骤

那么这里我们说完了非结构化文档的搜索

我们将在下一章说下如何对结构化数据进行搜索。

发表评论

邮箱地址不会被公开。 必填项已用*标注