1.概述

掌握如何借助 DeepSeek R1 与 Ollama 搭建检索增强生成(RAG)系统。本文将通过代码示例,为你提供详尽的分步指南、设置说明,分享打造智能 AI 应用的最佳实践。

2.内容

2.1 为什么选择DeepSeek R1?

在这篇文章中,我们将探究性能上可与 OpenAI 的 o1 相媲美、但成本却低 95% 的 DeepSeek R1,如何为你的检索增强生成(RAG)系统带来强大助力。我们来深入剖析为何开发者们纷纷热衷于这项技术,以及你怎样利用它构建自己的 RAG 流程。

DeepSeek R1 的 15 亿参数模型在这方面表现出色,原因如下:
  • 精准检索:每个答案仅关联 3 个文档片段
  • 严格提示:采用 “我不知道” 策略,避免模型产生幻觉
  • 本地执行:与云 API 相比,实现零延迟

环境:

组件 成本
DeepSeek R1 1.5B 免费
Ollama 免费
16GB 内存的个人电脑 0 元

2.2 构建本地 RAG 系统所需的条件

1.Ollama

Ollama 允许你在本地运行诸如 DeepSeek R1 之类的模型。

  • 下载:Ollama
  • 设置:通过终端安装并运行以下命令。
ollama run deepseek-r1  # For the 7B model (default)  

2.DeepSeek R1 模型

DeepSeek R1 的参数范围从 1.5B 到 671B。对于轻量级 RAG 应用程序,请从1.5B 模型开始。

ollama run deepseek-r1:1.5b 

提示:更大的模型(例如 70B)提供更好的推理能力,但需要更多的 RAM。

2.3 构建 RAG 管道

1.导入库

我们将使用:

import streamlit as st
from langchain_community.document_loaders import PDFPlumberLoader
from langchain_experimental.text_splitter import SemanticChunker
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.llms import Ollama

2.上传并处理 PDF

利用 Streamlit 的文件上传器选择本地 PDF。用于PDFPlumberLoader高效提取文本,无需手动解析。

# Streamlit文件上传器
uploaded_file = st.file_uploader("Upload a PDF file", 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()

3.策略性地整理文件

我们打算使用递归字符文本分割器(RecursiveCharacterTextSplitter),该代码会将原始的 PDF 文本拆分成更小的片段(块)。下面我们来解释一下合理分块与不合理分块的概念:

为什么要进行语义分块呢?
语义分块能够将相关的句子归为一组(例如,“Milvus 如何存储数据” 这样的内容会保持完整),还能避免拆分表格或图表。

利用 Streamlit 的文件上传器选择本地 PDF。用于PDFPlumberLoader高效提取文本,无需手动解析。

# 将文本拆分为语义块
text_splitter = SemanticChunker(HuggingFaceEmbeddings())
documents = text_splitter.split_documents(docs)

这一步通过让各文本片段稍有重叠来保留上下文信息,这有助于语言模型更准确地回答问题。小而明确的文档片段还能让搜索变得更高效、更具相关性。

4.创建可搜索的知识库

分割完成后,流程会为这些文本片段生成向量嵌入表示,并将它们存储在 FAISS 索引中。

# Generate embeddings
embeddings = HuggingFaceEmbeddings()
vector_store = FAISS.from_documents(documents, embeddings) # Connect retriever
retriever = vector_store.as_retriever(search_kwargs={"k": 3}) # Fetch top 3 chunks

这一过程将文本转换为一种数值表示形式,从而使查询变得更加容易。后续的查询操作将针对该索引展开,以找出上下文最为相关的文本片段。

5.配置 DeepSeek R1

在这里,你要使用 Deepseek R1 1.5B 参数模型作为本地大语言模型(LLM)来实例化一个检索问答(RetrievalQA)链。

llm = Ollama(model="deepseek-r1:1.5b")  # Our 1.5B parameter model  

# Craft the prompt template
prompt = """
1. Use ONLY the context below.
2. If unsure, say "I don’t know".
3. Keep answers under 4 sentences. Context: {context} Question: {question} Answer:
"""
QA_CHAIN_PROMPT = PromptTemplate.from_template(prompt)

这个模板会迫使模型依据你 PDF 文档的内容来给出答案。通过将语言模型与和 FAISS 索引绑定的检索器相结合,任何通过该链发起的查询都会从 PDF 内容中查找相关上下文,从而让答案有原始材料作为依据。

6.组装RAG链

接下来,你可以将上传、分块和检索这几个步骤整合为一个连贯的流程。

# Chain 1: Generate answers
llm_chain = LLMChain(llm=llm, prompt=QA_CHAIN_PROMPT) # Chain 2: Combine document chunks
document_prompt = PromptTemplate(
template="Context:\ncontent:{page_content}\nsource:{source}",
input_variables=["page_content", "source"]
) # Final RAG pipeline
qa = RetrievalQA(
combine_documents_chain=StuffDocumentsChain(
llm_chain=llm_chain,
document_prompt=document_prompt
),
retriever=retriever
)

这就是检索增强生成(RAG)设计的核心所在,它为大语言模型提供经过验证的上下文信息,而非让其单纯依赖自身的内部训练数据。

7.启动 Web 接口

最后,代码利用了 Streamlit 的文本输入和输出函数,这样用户就可以直接输入问题并立即查看回答。

# Streamlit UI
user_input = st.text_input("Ask your PDF a question:") if user_input:
with st.spinner("Thinking..."):
response = qa(user_input)["result"]
st.write(response)

一旦用户输入查询内容,检索链就会找出最匹配的文本片段,将其输入到语言模型中,并显示答案。只要正确安装了langchain库,代码现在应该就能正常运行,不会再触发模块缺失的错误。
提出并提交问题,即可立即获得答案!

8.完整示例代码

import streamlit as st
from langchain_community.document_loaders import PDFPlumberLoader
from langchain_experimental.text_splitter import SemanticChunker
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_community.llms import Ollama
from langchain.prompts import PromptTemplate
from langchain.chains.llm import LLMChain
from langchain.chains.combine_documents.stuff import StuffDocumentsChain
from langchain.chains import RetrievalQA # color palette
primary_color = "#1E90FF"
secondary_color = "#FF6347"
background_color = "#F5F5F5"
text_color = "#4561e9" # Custom CSS
st.markdown(f"""
<style>
.stApp {{
background-color: {background_color};
color: {text_color};
}}
.stButton>button {{
background-color: {primary_color};
color: white;
border-radius: 5px;
border: none;
padding: 10px 20px;
font-size: 16px;
}}
.stTextInput>div>div>input {{
border: 2px solid {primary_color};
border-radius: 5px;
padding: 10px;
font-size: 16px;
}}
.stFileUploader>div>div>div>button {{
background-color: {secondary_color};
color: white;
border-radius: 5px;
border: none;
padding: 10px 20px;
font-size: 16px;
}}
</style>
""", unsafe_allow_html=True) # Streamlit app title
st.title("Build a RAG System with DeepSeek R1 & Ollama") # Load the PDF
uploaded_file = st.file_uploader("Upload a PDF file", type="pdf") if uploaded_file is not None:
# Save the uploaded file to a temporary location
with open("temp.pdf", "wb") as f:
f.write(uploaded_file.getvalue()) # Load the PDF
loader = PDFPlumberLoader("temp.pdf")
docs = loader.load() # Split into chunks
text_splitter = SemanticChunker(HuggingFaceEmbeddings())
documents = text_splitter.split_documents(docs) # Instantiate the embedding model
embedder = HuggingFaceEmbeddings() # Create the vector store and fill it with embeddings
vector = FAISS.from_documents(documents, embedder)
retriever = vector.as_retriever(search_type="similarity", search_kwargs={"k": 3}) # Define llm
llm = Ollama(model="deepseek-r1") # Define the prompt
prompt = """
1. Use the following pieces of context to answer the question at the end.
2. If you don't know the answer, just say that "I don't know" but don't make up an answer on your own.\n
3. Keep the answer crisp and limited to 3,4 sentences. Context: {context} Question: {question} Helpful Answer:""" QA_CHAIN_PROMPT = PromptTemplate.from_template(prompt) llm_chain = LLMChain(
llm=llm,
prompt=QA_CHAIN_PROMPT,
callbacks=None,
verbose=True) document_prompt = PromptTemplate(
input_variables=["page_content", "source"],
template="Context:\ncontent:{page_content}\nsource:{source}",
) combine_documents_chain = StuffDocumentsChain(
llm_chain=llm_chain,
document_variable_name="context",
document_prompt=document_prompt,
callbacks=None) qa = RetrievalQA(
combine_documents_chain=combine_documents_chain,
verbose=True,
retriever=retriever,
return_source_documents=True) # User input
user_input = st.text_input("Ask a question related to the PDF :") # Process user input
if user_input:
with st.spinner("Processing..."):
response = qa(user_input)["result"]
st.write("Response:")
st.write(response)
else:
st.write("Please upload a PDF file to proceed.")

3.总结

本文详细介绍了利用 DeepSeek R1 和 Ollama 构建检索增强生成(RAG)系统的方法。首先说明了 DeepSeek R1 1.5B 模型的优势,如精准检索、避免幻觉、零延迟等。接着阐述了搭建流程,包括用 Ollama 本地运行模型、上传 PDF 文件、使用递归字符文本分割器进行语义分块、生成向量嵌入并存储于 FAISS 索引、实例化检索问答链,最后整合各步骤形成连贯流程。通过 Streamlit 实现用户输入问题并即时获取答案,且确保安装langchain库可避免错误。

4.结束语

这篇博客就和大家分享到这里,如果大家在研究学习的过程当中有什么问题,可以加群进行讨论或发送邮件给我,我会尽我所能为您解答,与君共勉!

另外,博主出新书了《深入理解Hive》、同时已出版的《Kafka并不难学》和《Hadoop大数据挖掘从入门到进阶实战》也可以和新书配套使用,喜欢的朋友或同学, 可以在公告栏那里点击购买链接购买博主的书进行学习,在此感谢大家的支持。关注下面公众号,根据提示,可免费获取书籍的教学视频。

使用 DeepSeek R1 和 Ollama 开发 RAG 系统的更多相关文章

  1. 二十九、EFW框架开发的系统支持SaaS模式和实现思路

    回<[开源]EFW框架系列文章索引>        EFW框架源代码下载V1.3:http://pan.baidu.com/s/1c0dADO0 EFW框架实例源代码下载:http://p ...

  2. P6 EPPM 16 R1 文档和帮助系统

    P6 EPPM 16 R1 文档和帮助系统 https://docs.oracle.com/cd/E74894_01/ http://docs.oracle.com/cd/E68202_01/clie ...

  3. android开发中系统自带语音模块的使用

    android开发中系统自带语音模块的使用需求:项目中需要添加语音搜索模块,增加用户体验解决过程:在网上搜到语音搜索例子,参考网上代码,加入到了自己的项目,完成产品要求.这个问题很好解决,网上能找到很 ...

  4. 利用微软Speech SDK 5.1开发语音识别系统主要步骤

    利用微软Speech SDK 5.1开发语音识别系统主要步骤 2009-09-17 10:21:09|  分类: 知识点滴|字号 订阅 微软语音识别分两种模式:文本识别模式和命令识别模式.此两种模式的 ...

  5. php开发之系统函数

    一些常用的php开发之系统函数的使用,可以使我们的开发效率,事倍功半 1) BC高精度函数库 2)

  6. 开发MIS系统的相关技术

    Java Web应用的核心技术包括以下几个方面:● JSP:进行输入和输出的基本手段.● JavaBean:完成功能的处理.● Servlet:对应用的流程进行控制.● JDBC:是与数据库进行交互不 ...

  7. 如何整合Office Web Apps至自己开发的系统(一)

    在前面我的一篇博客中 Office Web Apps安装部署(一),有一张介绍Office Web Apps与其他系统的关系图,   从上述图中,可知实际上Office Web Apps也是可以接入自 ...

  8. 如何整合Office Web Apps至自己开发的系统(二)

    WOPI项目的创建 首先用vs2012创建一个mvc4的程序.如图: 从上一篇我们可以知道,WOPI通讯主要通过两个服务: 一个是CheckFileInfo服务, 一个是GetFile服务. 所以下面 ...

  9. 基于jeesite+android开发 电子商务系统免费教程

    下载地址: jeesite免费教程 基于jeesite+android开发 电子商务系统免费教程 基于jeesite+android开发 电子商务系统免费教程 这个教程已经录制完很久了,一直没有公开, ...

  10. 三、利用EnterpriseFrameWork快速开发Winform系统(C/S)

    EnterpriseFrameWork框架实例源代码下载: 实例下载 上一章讲解了开发Web系统的详细步骤,以书籍的管理作实例实现对书籍的增.删.改.查功能,本章接着上面的实例继续补充用Winform ...

随机推荐

  1. 【Amadeus原创】Docker容器的备份与还原

    主要作用: 就是让配置好的容器,可以得到复用,后面用到得的时候就不需要重新配置. 其中涉及到的命令有: docker commit 将容器保存为镜像 docker save -o 将镜像备份为tar文 ...

  2. 【Amadeus原创】更改docker run启动参数

    经过一整天的摸索,答案: 没法直接修改.只能另外创建. 但是还好不用完全重头来,用docker commit命令可以基于当前修改的内容创建一个新的image. 执行docker 看看帮助先: Comm ...

  3. React 的界面与数据分离问题

    React 生态庞大,没办法只能学一点.第一段学完就有一个根本性的问题了:它竟然把数据.业务逻辑和界面混在一起,组件变成了有"业务状态"的组件,这就意味着UI和业务绑定了.而这种糟 ...

  4. 用Python让两组数据纵向排序

    一.引言 在数据处理和分析中,排序是一项非常基础且重要的操作.排序可以帮助我们更好地理解数据,发现数据中的模式和规律.在Python中,我们可以使用多种方法对数据进行排序.本文将详细介绍如何使用Pyt ...

  5. 【网站搭建】Docsify+Gittalk的配置过程记录分享。原创!

    Gittalk 配置 这个不一定最先配置,我也不建议你最先配置这个,这个最好最后配置. 萌狼蓝天把这个的配置写在第一条,是因为我在这折腾了很久,就是因为网上抄来抄去的答案,除了迷惑萌狼蓝天难以给萌狼蓝 ...

  6. Qt/C++音视频开发81-采集本地麦克风/本地摄像头带麦克风/桌面采集和麦克风/本地设备和桌面推流

    一.前言 随着直播的兴起,采集本地摄像头和麦克风进行直播推流,也是一个刚需,最简单的做法是直接用ffmpeg命令行采集并推流,这种方式简单粗暴,但是不能实时预览画面,而且不方便加上一些特殊要求.之前就 ...

  7. Qt音视频开发3-vlc录像存储

    一.前言 录像功能是视频监控系统的常用功能,就是将打开的视频流或者视频文件重新保存成MP4文件,当然也可以保存成其他格式,一般默认用MP4比较好,比较标准一些,MP4格式的兼容性最好,基本上没有说那台 ...

  8. 《Hough变换及其在信息处理中的应用》电子书下载

    <Hough变换及其在信息处理中的应用>电子书下载:百度云盘,  提取码:9zyi

  9. Appium_iOS测试脚本(1)

    经过不断的调试WebDriverAgent, 现在终于可以执行ios的自动化测试脚本了, # This sample code uses the Appium python client # pip ...

  10. biancheng-HBase

    目录http://c.biancheng.net/view/6509.html 1HBase是什么?2HBase的优势有哪些?3Hadoop与HBase的关系4HDFS5HDFS的特点与使用场景6HB ...