我是如何构建我的第一个 RAG 管道

原文:towardsdatascience.com/how-i-built-my-first-rag-pipeline-6e178326e3c8

LLM 的幻觉甚至对像谷歌这样的科技巨头都是一个问题(只需问 Gemini 每天推荐吃多少石头……剧透一下,是一天一个)。虽然我们仍然不知道如何教授 LLM 常识知识,但我们能做的是为您的特定用例提供足够的上下文。这就是检索增强生成(RAG)发挥作用的地方!在这篇文章中,我将向您展示我是如何实现一个可以阅读我的简历并与招聘人员交谈的 RAG 管道**

嘘!如果你没有会员资格,你可以在这里阅读文章这里

什么是检索增强生成(RAG)?

首先,让我们打好基础,确保我们理解什么是 RAG 以及它是如何工作的。简而言之,检索增强生成(RAG)是一种技术,其中 LLM 的答案生成通过从一组领域知识中检索到的额外相关信息得到增强。RAG 管道从您的私有数据中挑选出最相关的文本片段,并让 LLM 在提示的同时阅读它,以生成答案。例如,在这篇文章中,我正在构建一个裸骨聊天机器人,为我回答招聘人员的问题。为了使 LLM 能够准确完成其工作,我必须“告诉”它我是谁。使用 RAG 管道,我可以让它检索每个招聘人员问题的最相关部分,从而增强LLM 的答案生成。

简单 RAG 管道的工作原理

现在我们已经了解了它的工作的高层次理论,让我们深入了解它的细节。这就是一个简单的 RAG 管道的样子:

https://github.com/OpenDocCN/towardsdatascience-blog-zh-2024/raw/master/docs/img/dc2cd6fa8e979fa6d215e639509c20a2.png

作者提供的简单 RAG 管道图。

如图中所示,构建简单 RAG 管道有两个阶段:

  1. 数据索引

  2. 数据检索和生成

数据索引

它从数据索引开始,这意味着将文本数据转换为可搜索的向量嵌入数据库。首先,在数据索引阶段,文档集合被分成更小的文本片段。这样,在需要时可以给 LLM 提供更小、更精确的文本片段,而不是用太多信息压倒它。然后,文本片段被转换为向量嵌入。向量嵌入将自然语言文本的意义编码成计算机可以读取的数字。最后,向量嵌入存储在向量数据库中,以便它们可以轻松搜索。

数据检索和生成

现在上下文数据块已存储在可搜索的数据库中,数据检索和生成开始。首先,用户的查询(或提示)被转换为一个向量嵌入,就像向量数据库中的上下文数据一样。然后,查询向量与向量数据库中所有上下文数据的向量进行比较,以选择与用户查询最相似的顶部 k 个上下文数据块。最后,用户查询和选定的上下文块被输入到 LLM 中,生成答案。就是这样!

我是如何构建一个简单的 RAG 管道

现在我们已经了解了 RAG 管道背后的理论,让我们将其付诸实践!

这些是我们将遵循的步骤:

  1. 设置环境

  2. 导入 LLM

  3. 导入嵌入模型

  4. 准备数据

  5. 提示工程

  6. 创建查询引擎

设置环境

首先,我们需要导入所有必要的库。我们将使用以下库:

  • Chroma - 一个 AI 原生开源向量数据库。Chroma 将允许我们为向量嵌入创建一个向量数据库。

  • LlamaIndex - 一个用于构建基于 LLM 的上下文增强生成式 AI 应用的框架。LlamaIndex 将处理从读取上下文数据到创建向量嵌入、创建提示模板以及在本地提示 Llama LLM 的所有事情。

import chromadb
from llama_index.core import PromptTemplate
from llama_index.core import Settings
from llama_index.core import SimpleDirectoryReader
from llama_index.core import StorageContext
from llama_index.core import VectorStoreIndex
from llama_index.core.node_parser import SentenceSplitter
from llama_index.embeddings.huggingface import HuggingFaceEmbedding
from llama_index.llms.ollama import Ollama
from llama_index.vector_stores.chroma import ChromaVectorStore

要安装这些库,您可以运行以下命令:

pip install chromadb
pip install llama-index

导入 Llama LLM

现在所有必要的库都已导入,我们可以开始导入一个 LLM。我选择使用 Llama,因为它允许我在本地运行它,这意味着它是免费且私有的!Ollama 库使得导入变得非常简单——只需指定您想使用的版本,然后通过调用*.complete*来提示它。

llm = Ollama(model="llama3")
response = llm.complete("Who is Laurie Voss? write in 10 words")
print(response)

导入嵌入模型

接下来,我们导入一个嵌入模型,它处理从文本到上下文数据和提示的向量嵌入的转换。您可以从大量嵌入模型中进行选择。我使用了来自 Hugging Face 的"BAAI/bge-small-en-v1.5",因为它是一个小型模型。模型越小,实现速度越快,但以模型的能力为代价。由于我的 RAG 管道只是一个 POC,我不介意次优性能,而且额外的速度提升是一个加分项。

embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-en-v1.5")
Settings.llm = llm
Settings.embed_model = embed_model

准备数据

嵌入模型作为数据准备的一部分被使用。为了准备数据,我们首先使用SimpleDirectoryReader读取包含上下文的文件。在这种情况下,它是我一页简历的 PDF。然后我们使用Chroma创建一个向量数据库。最后,我们将上下文数据作为向量嵌入存储在向量数据库中,并使用VectorStoreIndex执行文本块转换。

documents = SimpleDirectoryReader(input_files=["./resume.pdf"]).load_data()
chroma_client = chromadb.EphemeralClient()
chroma_collection = chroma_client.create_collection("ollama")
vector_store = ChromaVectorStore(chroma_collection=chroma_collection)
storage_context = StorageContext.from_defaults(vector_store=vector_store)
index = VectorStoreIndex.from_documents(documents, 
                                        storage_context=storage_context, 
                                        embed_model=embed_model,
                                        transformations=[SentenceSplitter(chunk_size=256, chunk_overlap=10)])

提示工程

现在 RAG 管道的内部工作已经设置好,我们编写一个模板查询,为 LLM 分配任务和角色,提供相关上下文,并插入问题。

template = (
    "Imagine you are a data scientist's assistant and "
    "you answer a recruiter's questions about the data scientist's experience."
    "Here is some context from the data scientist's "
    "resume related to the query::n"
    "-----------------------------------------n"
    "{context_str}n"
    "-----------------------------------------n"
    "Considering the above information, "
    "please respond to the following inquiry:nn"
    "Question: {query_str}nn"
    "Answer succinctly and ensure your response is "
    "clear to someone without a data science background."
    "The data scientist's name is Diana."
)
qa_template = PromptTemplate(template)

创建查询引擎

最后,我们创建一个查询引擎,它组装所有的乐高积木!

query_engine = index.as_query_engine(text_qa_template=qa_template,
                                                          similarity_top_k=3)

运行 RAG 管道

现在,让我们来到构建 AI 应用的有趣部分——看到它工作!要运行 RAG 管道,只需向查询引擎提出一个问题,然后,哇!

response = query_engine.query("Do you have experience with Python?")
print(response.response)
'Yes, I can confirm that Diana Morales has extensive experience working 
with Python as a Data Scientist at Accenture. According to her resume, 
she listed Python as one of her core skills, indicating a strong 
proficiency in the programming language. Additionally, her projects and 
achievements highlight her ability to leverage Python for various data 
science tasks, such as natural language processing (NLP), machine learning, 
and data visualizations.'

真的很不错,不是吗?

在我的下一篇文章中,我将更深入地介绍 RAG 管道,涉及更多高级主题。如果你喜欢这篇文章,别忘了点赞和评论,并分享你根据这篇文章构建的所有令人惊叹的 RAG 管道!下次再见!

### 使用 LangChain 构建和实现 RAG(检索增强生成)的最佳实践 #### 1. 理解 RAG 的核心组件 RAG 系统的核心在于将用户的知识库内容通过 embedding 存入向量数据库,并在运行时利用用户查询的 embedding 检索最相关的知识片段[^2]。这些片段随后被用作上下文,与用户问题一起提交给大语言模型(LLM)以生成回答。 #### 2. 数据索引流程 构建 RAG 系统的第一步是创建一个从源数据中提取并索引信息的管道。这通常是一个离线过程,涉及以下步骤: - **数据加载**:从文档、网页或其他来源加载原始数据。 - **文本分割**:将长文本分割成较小的块,以便于后续处理。 - **嵌入生成**:使用嵌入模型(如 OpenAI 的 `text-embedding-ada-002` 或 Hugging Face 的模型)为每个文本块生成向量表示。 - **向量存储**:将生成的嵌入存储到向量数据库中,例如 Pinecone、Weaviate 或 FAISS。 以下是使用 LangChain 进行数据索引的代码示例: ```python from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.vectorstores import FAISS from langchain.embeddings.openai import OpenAIEmbeddings # 加载和分割文本 text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0) texts = text_splitter.split_text("这里是你的文档内容") # 创建嵌入模型 embeddings = OpenAIEmbeddings() # 将文本块和嵌入存储到向量数据库 vectorstore = FAISS.from_texts(texts, embeddings) ``` #### 3. 查询与生成流程 在运行时,RAG 系统接受用户查询并执行以下操作: - **查询嵌入**:将用户的自然语言查询转换为嵌入表示。 - **相似性检索**:从向量数据库中检索与查询最相关的文本块。 - **上下文生成**:将检索到的相关文本块作为上下文,与用户问题一起传递给 LLM。 - **响应生成**:LLM 根据上下文生成最终的回答。 以下是实现查询与生成的代码示例: ```python from langchain.chains import RetrievalQA from langchain.llms import OpenAI # 初始化 LLM llm = OpenAI(temperature=0) # 创建检索链 qa_chain = RetrievalQA.from_chain_type( llm=llm, chain_type="stuff", retriever=vectorstore.as_retriever() ) # 执行查询 response = qa_chain.run("请回答关于你的文档的问题") print(response) ``` #### 4. RAG Prompt 模板构建 为了提高生成质量,可以自定义 RAG 的 Prompt 模板。模板应明确指示 LLM 使用检索到的上下文来生成回答。例如: ```python from langchain.prompts import PromptTemplate template = """使用以下上下文回答问题。如果上下文不足以回答,请说明。 {context} 问题: {question} 回答: """ prompt = PromptTemplate(template=template, input_variables=["context", "question"]) ``` 然后,将此模板集成到检索链中: ```python from langchain.chains import ConversationalRetrievalChain qa_chain = ConversationalRetrievalChain.from_llm( llm=llm, retriever=vectorstore.as_retriever(), combine_docs_chain_kwargs={"prompt": prompt} ) ``` #### 5. 最佳实践 - **选择合适的嵌入模型**:确保嵌入模型能够捕捉文本语义,推荐使用经过验证的模型如 `text-embedding-ada-002`[^2]。 - **优化文本分割策略**:根据数据特性调整 `chunk_size` 和 `chunk_overlap` 参数,以平衡检索效率和上下文完整性[^1]。 - **监控性能**:定期评估 RAG 系统的表现,包括检索准确性和生成回答的质量。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值