初探检索增强生成(RAG) | 豆包MarsCode AI刷题

120 阅读5分钟

前言

今天学习了《用LangChain快速构建基于“易速鲜花”本地知识库的智能问答系统》,正好利用这个机会写一篇笔记记录一下知识点,顺便完成一下课后的思考题。

用LangChain快速构建基于“易速鲜花”本地知识库的智能问答系统

在这一节的课程中,主要是介绍了怎么基于LangChain搭建一个基本本地知识库的问答系统。之所以要搭建这样一个系统,是因为一般的大模型是在复杂多样的文本数据上进行训练的,如各种书籍文本,从互联网爬取的文本等。但是如果是针对某个企业,想打造企业内部的大模型的话,通用的大模型就无法胜任了。

打造专属大模型也有两条路线。分别是 对大模型进行微调使用检索信息增强(RAG) 这两种方法。基于微调的方法流程更加复杂,要准备微调数据集和硬件资源,并且微调的结果也并不是一定能达到预期。而基于RAG的方法更加方便快捷,只需要准备 本地知识库 ,然后使用LangChain和大模型搭建检索链就可以实现。

在这篇笔记中,和课程类似的知识就不再赘述了,主要是回答一下思考题。

1. 请你用自己的话简述一下这个基于文档的QA(问答)系统的实现流程?

做一个简单的RAG(检索增强生成)问答系统,需要以下几个步骤:

1. 加载相关文档: 可以是各种格式的文本,如txt、pdf、doc、csv、xlsx等。然后把它们用langchain_community.document_loaders的几个依赖加载到一个列表中。

2. 分割文档: 将文档列表按照需要进行分割,固定分割后的片段大小和重叠字符数。

3. 文档向量化并存储向量: 分割后的文档因为格式不是结构化的,所以需要用向量数据库进行存储。使用嵌入器将文本嵌入为向量,嵌入器可以选择openai的,也可以用其他模型的。在本次课程中的代码就是自己定义的doubao的嵌入器。数据库可以选择开源的向量数据库,如Qdrant、Chroma、Milvus等。使用向量数据库的原因是因为向量数据库可以存储和检索向量,而向量是由模型生成的,模型可以理解和生成文本。检索时可以使用余弦相似度和欧氏距离,但由于文本长度不一,并且余弦相似度更容易找到与问题方向更近的向量,所以一般使用余弦相似度进行检索。

4. 创建检索链: 实例化大模型,这个大模型可以是各种大模型的接口,实例方式和前面课程的一致;实例化多查询检索器MultiQueryRetriever,这可以将问题转换出多个相似问题,从而在检索过程中更容易检索到相关内容;构建检索链,把大模型和检索器作为参数传入RetrievalQA.from_chain_type函数。

5. 问答检索: 用户给出一个问题,问题首先进行文本嵌入,然后使用向量数据库检索最相关的文档。然后把问题和检索到的文档作为上下文,输入给大模型,再使用大模型的能力生成答案。

2. LangChain支持很多种向量数据库,你能否用另一种常用的向量数据库Chroma来实现这个任务?

这一部分就是替换向量数据库,但是要注意,Chroma的参数和Qdrant不尽相同,所以不能直接复制,需要根据实际要求传入参数。下面的代码段中,注释掉的是原来的Qdrant代码,Chroma的参数没有location,这个要注意。

from typing import Dict, List
from langchain_community.vectorstores import Chroma

# 需要修改一下DouBaoEmbeddings
class DoubaoEmbeddings(BaseModel, Embeddings):
    client: Ark = None
    api_key: str = ""
    model: str

    def __init__(self, **data: Dict) -> None:   # 主要是这行Any改成Dict

# # 定义向量数据库Qdrant
# vectorstore = Qdrant.from_documents(
#     documents=chunked_documents,    # 传入分割后的文档列表
#     embedding=DoubaoEmbeddings(model=os.environ["EMBEDDING_MODELEND"]), # 传入自定义的Embeddings类
#     location=":memory:",    # 向量数据库存储在内存中
#     collection_name="my_documents"  # 向量数据库的名称
# )
# 使用chroma向量数据库
vectorstore = Chroma.from_documents(
    documents=chunked_documents,    # 传入分割后的文档列表
    embedding=DoubaoEmbeddings(model=os.environ["EMBEDDING_MODELEND"]), # 传入自定义的Embeddings类
    collection_name="my_documents"  # 向量数据库的名称
)

如果直接替换代码,在AI练中学直接运行的话,可能会出现一些库版本不兼容的情况,处理起来还是有些麻烦的。直接运行上述代码会出现sqlite3版本不匹配的错误,要求大于3.50,因但是AI练中学只能更新到3.47,所以需要先安装一个库pip install pysqlite3-binary,然后修改一下chromadb库中的一些代码,打开下面这个文件,/home/cloudide/.local/lib/python3.12/site-packages/chromadb/__init__.py,在开头添加下面的代码即可。具体的修改方法参考这个链接

__import__('pysqlite3')
import sys
sys.modules['sqlite3'] = sys.modules.pop('pysqlite3')

然后就可以运行了!

3. LangChain支持很多种大语言模型,你能否用HuggingFace网站提供的开源模型 google/flan-t5-xl 代替GPT-3.5完成这个任务?

这里就是替换大模型,并且需要一个hugging face账号,注册之后,要在设置里面生成一个token,让代码可以访问huggingface中的模型,但是AI练中学有可能访问不了hf,所以可以通过环境变量设置镜像export HF_ENDPOINT=https://hf-mirror.com。而且我还想吐个槽,模型名是flan-t5-xl,但是题目打成了flan-t5-x1,帮助别的同学避个坑,别抄错了。

代码如下:

import os
from langchain_community.llms import HuggingFaceHub

os.environ["HUGGINGFACEHUB_API_TOKEN"] = "your_token"

# 实例化大模型,,调用豆包的API
# llm = ChatOpenAI(
#     model=os.environ["LLM_MODELEND"],
#     temperature=0
# )

# 设置 Hugging Face Hub token,确保有 Hugging Face 帐号
llm = HuggingFaceHub(
    repo_id="google/flan-t5-xl",
    model_kwargs={"temperature": 0, "max_length": 200}
)