大家好,我是橙哥!如果你是开发者或AI爱好者,可能希望能从庞大的文档中快速提取答案,而不需要翻阅每一页。今天,我将带你了解如何通过构建一个本地化的检索增强生成(RAG)系统,直接从文档中获取精准答案。通过结合
DeepSeek R1
和
Ollama
,你可以轻松实现这一目标,而无需依赖云服务,也能避免云 API 延迟的困扰。
完整代码请见文末。
了解 DeepSeek R1
DeepSeek R1 作为一款开源推理模型,凭借其超高性价比,它迅速成为了许多开发者的首选。与 OpenAI 的模型相比,DeepSeek R1 具有约 95% 更低的费用,但在推理性能上也丝毫不逊色。最重要的是,它能够直接在本地运行,大大提高了效率与数据安全性。使用 DeepSeek R1,你可以从 PDF 中提取最相关的信息,并且在不依赖外部 API 的情况下进行推理。
本地化 RAG 系统的核心要素
要构建一个有效的本地化 RAG 系统,首先需要准备以下几个关键组件:
1.
Ollama
:这是一个轻量级框架,允许你在本地运行 DeepSeek R1 模型。它支持多种不同的模型变体,可以根据需求选择合适的大小与参数。
2.
PDF 文档处理
:由于 RAG 系统的核心是文档检索与生成,因此你需要一个工具来高效地处理 PDF 文件并提取其内容。我们将利用
PDFPlumberLoader
来加载 PDF 并提取文本。
3.
文本切分与嵌入
:为了提高检索的准确性,我们需要将文档内容分割成语义块,并生成向量嵌入,利用 FAISS 向量数据库来实现快速搜索。
4.
检索问答链
:最终,我们将构建一个能够理解和回答问题的问答链,通过 DeepSeek R1 模型来生成高质量的答案。
从 PDF 文档提取数据
首先,我们通过
Streamlit
创建一个简单的用户界面,让用户能够上传 PDF 文件。接下来,我们使用
PDFPlumberLoader
来加载文档,并提取其中的文本内容。以下是相关的代码:
import streamlit as st
from langchain_community.document_loaders importPDFPlumberLoader
uploaded_file = st.file_uploader("上传一个 PDF 文件", type="pdf")
if uploaded_file:
# 临时保存 PDF 文件
with open("temp.pdf", "wb") as f:
f.write(uploaded_file.getvalue())
# 加载 PDF 内容
loader = PDFPlumberLoader("temp.pdf")
docs = loader.load()
这段代码实现了一个简单的文件上传功能,将 PDF 文件保存到本地并使用
PDFPlumberLoader
加载文件内容。接下来,我们可以对文档进行切分,以便进行高效检索。
文本切分与向量嵌入
为了能够快速检索到相关内容,我们将文档文本切分成较小的语义块。
SemanticChunker
是我们用来切分文本的工具,它能够根据语义将文本划分为合理的片段,以便后续处理。
from langchain_experimental.text_splitter importSemanticChunker
from langchain_community.embeddings importHuggingFaceEmbeddings
text_splitter = SemanticChunker(HuggingFaceEmbeddings())
documents = text_splitter.split_documents(docs)
接下来,我们将这些切分出来的文本片段转换为向量嵌入,并将其存储在
FAISS
向量数据库中,这样就可以实现快速检索了。
from langchain_community.vectorstores import FAISS
embeddings = HuggingFaceEmbeddings()
vector_store = FAISS.from_documents(documents, embeddings)
retriever = vector_store.as_retriever(search_kwargs={"k": 3}) # 检索最相关的 3 个片段
构建问答链
在这一步,我们将 DeepSeek R1 模型与文本检索系统结合,创建一个问答链。通过构建合适的提示模板,我们可以确保模型的回答是基于文档内容的,而不是模型自身的训练数据。
from langchain_community.llms importOllama
from langchain.prompts importPromptTemplate
llm = Ollama(model="deepseek-r1:1.5b") # 使用 DeepSeek R1 1.5B 参数模型
# 创建提示模板
prompt = """
1.只使用以下上下文。
2.如果不确定,回答“我不知道”。
3.保持答案不超过 4句话。
上下文:{context}
问题:{question}
答案:
"""
QA_CHAIN_PROMPT = PromptTemplate.from_template(prompt)
在提示模板中,我们要求模型仅仅依赖文档中的上下文来回答问题,这样可以有效避免错误或不准确的回答。
整合 RAG 流程
现在,我们将前面所有的步骤整合成一个完整的 RAG 流程。用户输入的问题将被传递给检索器,检索到的相关文档片段将被传递给 DeepSeek R1 模型生成答案。以下是流程代码:
from langchain.chains importLLMChain
from langchain_community.chains importRetrievalQA
from langchain_community.chains importStuffDocumentsChain
llm_chain = LLMChain(llm=llm, prompt=QA_CHAIN_PROMPT)