在深入研究实现之前,我们确保已安装以下工具和库:
Python 3.8+ Python 3.8+ 版
用于构建由大型语言模型 ()LLMs 提供支持的应用程序的框架,支持轻松检索、推理和工具集成
一个高性能的向量数据库,专为高效的相似性搜索和嵌入存储而设计。
创建用户友好的 Web 界面。
运行以下命令以安装必要的依赖项:
!pip install langchain chromadb gradio
!pip install -U langchain-community
安装上述依赖项后,运行以下 import 命令:
import gradio as gr
from langchain_community.document_loaders import PyMuPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.vectorstores import Chroma
from langchain_community.embeddings import OllamaEmbeddings
import ollama
导入库后,我们将处理上传的 PDF。
def process_pdf(pdf_bytes):
if pdf_bytes is None:
return None, None, None
loader = PyMuPDFLoader(pdf_bytes)
data = loader.load()
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=500, chunk_overlap=100
)
chunks = text_splitter.split_documents(data)
embeddings = OllamaEmbeddings(model="deepseek-r1")
vectorstore = Chroma.from_documents(
documents=chunks, embedding=embeddings, persist_directory="./chroma_db"
)
retriever = vectorstore.as_retriever()
return text_splitter, vectorstore, retriever
process_pdf
功能:
加载并准备 PDF 内容以进行基于检索的回答。
检查 PDF 是否已上传。
使用 PyMuPDFLoader
提取文本。
使用 RecursiveCharacterTextSplitter
将文本拆分为多个块。
使用 OllamaEmbeddings
生成向量嵌入。
将嵌入存储在 Chroma 向量存储中,以便进行高效检索。
检索到嵌入后,接下来我们需要将它们拼接在一起。combine_docs()
函数将检索到的多个文档块合并到一个字符串中。
def combine_docs(docs):
return "\n\n".join(doc.page_content for doc in docs)
由于基于检索的模型提取相关摘录而不是整个文档,因此此功能可确保提取的内容在传递到 DeepSeek-R1 之前保持可读性和正确格式。
现在,我们对模型的输入已经准备好了。让我们使用 Ollama 设置 DeepSeek R1。
import re
def ollama_llm(question, context):
formatted_prompt = f"Question: {question}\n\nContext: {context}"
response = ollama.chat(
model="deepseek-r1",
messages=[{"role": "user", "content": formatted_prompt}],
)
response_content = response["message"]["content"]
# Remove content between and tags to remove thinking output
final_answer = re.sub(r".*? ", "", response_content, flags=re.DOTALL).strip()
return final_answer
ollama_llm()
函数将用户的问题和检索到的文档上下文格式化为结构化提示。然后,此格式化输入通过 ollama.chat()
发送到 DeepSeek-R1,后者在给定上下文中处理问题并返回相关答案。如果您需要没有模型思维脚本的答案,请使用 strip()
函数返回最终答案。
现在我们有了所有必需的组件,让我们为演示构建 RAG 管道。
def rag_chain(question, text_splitter, vectorstore, retriever):
retrieved_docs = retriever.invoke(question)
formatted_content = combine_docs(retrieved_docs)
return ollama_llm(question, formatted_content)
上述函数首先使用 retriever.invoke(question)
搜索向量存储,返回最相关的文档摘录。这些摘录使用 combine_docs
函数格式化为结构化输入并发送到 ollama_llm
,确保 DeepSeek-R1 根据检索到的内容生成明智的答案。
我们已经准备好了 RAG 管道。现在,我们可以在本地构建 Gradio 接口以及 DeepSeek-R1 模型,以处理 PDF 输入并提出与之相关的问题。
def ask_question(pdf_bytes, question):
text_splitter, vectorstore, retriever = process_pdf(pdf_bytes)
if text_splitter is None:
return None # No PDF uploaded
result = rag_chain(question, text_splitter, vectorstore, retriever)
return {result}
interface = gr.Interface(
fn=ask_question,
inputs=[
gr.File(label="Upload PDF (optional)"),
gr.Textbox(label="Ask a question"),
],
outputs="text",
title="Ask questions about your PDF",
description="Use DeepSeek-R1 to answer your questions about the uploaded PDF document.",
)
interface.launch()
我们执行以下步骤:
检查是否已上传 PDF。
使用 process_pdf
函数处理 PDF,以提取文本并生成文档嵌入。
将用户的查询和文档嵌入向量传递给 rag_chain()
函数,以检索相关信息并生成上下文准确的响应。
设置基于 Gradio 的 Web 界面,以允许用户上传 PDF 并询问有关其内容的问题。
使用 gr.Interface()
函数定义布局,接受 PDF 文件和文本查询作为输入。
使用 interface.launch()
启动应用程序,通过 Web 浏览器启用无缝的、基于文档的交互式 Q&A。
使用 Ollama 在本地运行 DeepSeek-R1 可以实现更快、私有且经济高效的模型推理。通过简单的安装过程、CLI 交互、API 支持和 Python 集成,您可以将 DeepSeek-R1 用于各种 AI 应用程序,从一般查询到基于检索的复杂任务。