DeepSeek-R1私有化部署——基于 DeepSeek R1 和 Ollama 构建本地知识库(RAG)系统

概述

随着人工智能(AI)、自然语言处理(NLP)、大语言模型(LLM)技术的不断进步,传统的 LLM 虽然强大,但存在知识有限、准确性不足等问题。而检索增强生成(RAG)的出现,大大弥补了 LLM 的不足,有效克服了这些缺点。

一、 RAG

尽管 LLM 不断推动机器理解和实现的边界,但它们仍受到一些限制,例如对未见数据的准确响应困难或与最新信息保持同步的挑战,这些问题导致了幻觉的产生,而 RAG 正是为了应对这些问题而开发的。RAG 将 LLM 的能力与外部知识源相结合,以生成更具洞察力和准确性的响应。当接收到用户查询时,RAG 系统首先处理文本以理解其上下文和意图,然后从知识库中检索与用户查询相关的数据,并将其与查询一起作为上下文传递给 LLM。由于 LLM 存在上下文限制,即模型一次能够处理或理解的文本量有限,因此 RAG 只传递相关数据,而不是整个知识库。
在这里插入图片描述
具体来说,RAG 首先将查询转换为向量嵌入,使用嵌入模型进行处理。然后,将该嵌入向量与文档向量数据库进行比较,识别出最相关的文档。这些相关文档与原始查询结合,为 LLM 提供丰富的上下文,从而生成更准确的响应。这种混合方法使模型能够利用外部来源的最新信息,使 LLM 能够生成更具洞察力和准确性的响应。

1.1 长上下文窗口可能使 RAG 过时的原因

随着 LLM 的上下文窗口不断扩大,这些模型的输入和生成响应的方式将受到直接影响。通过增加 LLM 一次能够处理的文本量,扩展的上下文窗口增强了模型理解更全面的叙述和复杂思想的能力,提高了生成响应的整体质量和相关性。这使得 LLM 在处理更长文本时能够更有效地把握上下文及其细节,从而可能减少对 RAG 的依赖。

准确性

RAG 通过提供相关文档作为上下文来提高模型的准确性,但它不会实时适应或从上下文中学习。相反,它检索与用户查询相似的文档,这些文档可能并不总是最具上下文适应性的,从而可能导致响应不准确。相比之下,LLM 的长上下文窗口允许其内部的注意力机制专注于不同部分的上下文,以生成更精确的响应。此外,这种机制还可以进行微调,通过调整 LLM 模型以减少损失,从而生成更准确和上下文相关的响应。

信息检索

从知识库中检索信息以增强 LLM 的响应时,往往难以找到完整且相关的数据用于上下文窗口。检索到的数据是否完全回答了用户的查询始终存在不确定性。如果所选择的信息不足或与用户的实际意图不符,可能导致低效和错误的响应。

外部存储

传统上,LLM 无法同时处理大量信息,因为它们在处理上下文时受到限制。然而,随着上下文窗口的扩大,LLM 能够直接处理更多数据,从而消除了每个查询的单独存储需求。这简化了架构,加快了对外部数据库的访问速度,并提高了 AI 的效率。

1.2 RAG 将继续存在的原因

尽管 LLM 的扩展上下文窗口为模型提供了更深入的见解,但也带来了更高的计算成本和效率等挑战。RAG 通过选择性地检索最相关的信息来解决这些挑战,从而优化性能和准确性。

复杂的 RAG 将持续发展

简单的 RAG,其中数据被分成固定长度的文档并根据相似性进行检索,正在逐渐减少。然而,复杂的 RAG 系统不仅持续存在,而且发展迅速。复杂的 RAG 包括更广泛的功能,例如查询重写、数据清理、反思、优化的向量搜索、图搜索、重新排序器和更复杂的分块技术。这些增强不仅改进了 RAG 的功能,还扩展了其能力。

超越上下文长度的性能

尽管将 LLM 的上下文窗口扩展到数百万个标记看起来很有前景,但实际实现仍面临时间、效率和成本等多方面的挑战:

  • 时间:随着上下文窗口的扩大,LLM 处理更多标记的时间增加,导致延迟和响应时间延长。许多 LLM 应用程序需要快速响应,额外的延迟可能会严重影响其在实时场景中的性能,成为实现更大上下文窗口的主要瓶颈。
  • 效率:研究表明,与提供大量未经筛选的数据相比,LLM 在提供较少但更相关的文档时表现更好。最近的一项斯坦福研究发现,最先进的 LLM 在从广泛上下文窗口中提取有价值信息时经常遇到困难,尤其是当关键数据埋在大文本块的中间时,导致 LLM 忽略重要细节,数据处理效率低下。
  • 成本:LLM 中上下文窗口的扩大导致计算成本增加。处理更多的输入标记需要更多的资源,从而导致运营费用上升。例如,在 ChatGPT 等系统中,重点是限制处理的标记数量以控制成本。

相比之下,RAG 通过仅传递相关文档作为上下文,使 LLM 更快地处理信息,不仅减少了延迟,还提高了响应质量并降低了成本。

为什么微调不是最佳选择

除了使用更大的上下文窗口,RAG 的另一种替代方案是微调。然而,微调可能既昂贵又繁琐。每次有新信息进来时,更新 LLM 以使其保持最新状态是一项挑战。微调的其他问题包括:

  • 训练数据限制:无论 LLM 取得了多大的进展,总会有一些上下文在训练时不可用或被认为不相关。
  • 计算资源:对 LLM 进行微调并为其特定任务定制需要高计算资源。
  • 专业知识需求:开发和维护尖端 AI 并非易事。需要专业的技能和知识,而这可能难以获得。

其他问题还包括数据收集、质量保证以及模型部署等。

1.3 RAG 与微调或长上下文窗口的比较

以下是 RAG 与微调或长上下文窗口技术的比较概述(由于后两者具有相似的特点,因此在此图表中将它们合并)。它突出了成本、数据时效性和可扩展性等关键方面。

特征RAG微调/长上下文窗口
成本最低,无需训练高,需要广泛的训练和更新
数据时效性按需检索数据,确保实时性数据可能很快过时
透明度高,显示检索到的文档低,不清楚数据如何影响结果
可扩展性高,与各种数据源轻松集成有限,扩展需要大量资源
性能选择性数据检索提高性能性能可能随着上下文大小的增加而下降
适应性可根据特定任务进行定制而无需重新训练需要重新训练进行重大调整

1.4 使用向量数据库优化 RAG 系统

尽管最先进的 LLM 可以同时处理数百万个标记,但数据结构的复杂性和不断变化使 LLM 难以有效管理异构企业数据。RAG 解决了这些挑战,尽管检索准确性仍然是端到端性能的一个主要瓶颈。无论是 LLM 的大上下文窗口还是 RAG,目标都是充分利用大数据,并确保大规模数据处理的高效性。

使用先进的 SQL 向量数据库(如 MyScaleDB)将 LLM 与大数据进行集成,可以增强 LLM 的效果,并从大数据中提取更好的智能。此外,它可以减少模型幻觉,提供数据透明度,并提高可靠性。MyScaleDB 是一个基于 ClickHouse 的开源 SQL 向量数据库,专为大型 AI/RAG 应用程序量身定制。利用 ClickHouse 作为基础,并结合专有的 MSTG 算法,MyScaleDB 在管理大规模数据方面展示了 与其他向量数据库相比的卓越性能

二、环境搭建

2.1 Ollama

Ollama 允许在本地运行像 DeepSeek R1 这样的模型。

  • 下载链接:https://ollama.com/
  • 安装完成后,打开终端并运行以下命令:
    运行 DeepSeek R1
    测试环境:
ollama run deepseek-r1:1.5b

在这里插入图片描述

2.2 开发环境搭建

conda create -n deepseek python==3.10
activate deepseek
# langchain_community
pip install langchain langchain_community
# Chroma
pip install langchain_chroma
# Ollama
pip install langchain_ollama
pip install streamlit
pip install langchain-experimental
pip install pdfplumber
pip install sentence-transformers
pip install faiss-cpu

三、代码实现

3.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

LangChain + Streamlit 工作流

3.2 上传并处理 PDF 文件

这里使用 Streamlit 的文件上传器,让用户选择本地的 PDF 文件。

# Streamlit 文件上传器  
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()

上传完成后,PDFPlumberLoader 函数将从 PDF 中提取文本,为管道的下一步做好准备。这种方法的优点是它能够自动读取文件内容,无需手动进行繁琐的解析。

3.3 策略性地拆分文档

使用 RecursiveCharacterTextSplitter,代码将原始 PDF 文本拆分为更小的片段(块)。这里解释一下好的拆分与坏的拆分的概念:

好的拆分与坏的拆分对比

为什么使用语义拆分?

  • 将相关句子组合在一起(例如,“Milvus 如何存储数据”保持完整)
  • 避免拆分表格或图表
# 将文本拆分为语义块  
text_splitter = SemanticChunker(HuggingFaceEmbeddings())  
documents = text_splitter.split_documents(docs)

此步骤通过略微重叠片段来保留上下文,这有助于语言模型更准确地回答问题。小而明确的文档块也使搜索更高效、更相关。

3.4 创建可搜索的知识库

拆分完成后,管道将为片段生成向量嵌入,并将它们存储在 FAISS 索引中。

# 生成嵌入  
embeddings = HuggingFaceEmbeddings()  
vector_store = FAISS.from_documents(documents, embeddings)  

# 连接检索器  
retriever = vector_store.as_retriever(search_kwargs={"k": 3})  # 检索前 3 个块

这将文本转换为更易于查询的数值表示形式。后续的查询将针对此索引运行,以找到最相关的上下文片段。

3.5 配置 DeepSeek R1

在这里,使用 Deepseek R1 1.5B 作为本地 LLM,实例化一个检索增强型问答链。

llm = Ollama(model="deepseek-r1:1.5b")  # 我们的 1.5B 参数模型  

# 构建提示模板  
prompt = """  
1. 仅使用以下上下文。  
2. 如果不确定,请说“我不知道”。  
3. 回答不超过 4 句话。  

上下文:{context}  

问题:{question}  

答案:  
"""  
QA_CHAIN_PROMPT = PromptTemplate.from_template(prompt)

此模板强制模型根据 PDF 的内容进行回答。通过将语言模型与连接到 FAISS 索引的检索器包装在一起,任何通过链提出的查询都将从 PDF 的内容中查找上下文,从而使答案基于原始材料。

3.6 组装 RAG 链

可以将上传、拆分和检索步骤整合为一个连贯的管道。

# 链 1:生成答案  
llm_chain = LLMChain(llm=llm, prompt=QA_CHAIN_PROMPT)  

# 链 2:组合文档块  
document_prompt = PromptTemplate(  
    template="上下文:{page_content}\n来源:{source}",  
    input_variables=["page_content", "source"]  
)  

# 最终 RAG 管道  
qa = RetrievalQA(  
    combine_documents_chain=StuffDocumentsChain(  
        llm_chain=llm_chain,  
        document_prompt=document_prompt  
    ),  
    retriever=retriever  
)

这是 RAG(检索增强型生成)设计的核心,为大型语言模型提供经过验证的上下文,而不是完全依赖其内部训练。

3.7 启动 Web 界面

最后,代码使用 Streamlit 的文本输入和写入功能,让用户能够输入问题并立即查看答案。

# Streamlit UI  
user_input = st.text_input("向 PDF 提问:")  

if user_input:  
    with st.spinner("思考中..."):  
        response = qa(user_input)["result"]  
        st.write(response)

用户输入查询后,链将检索最匹配的块,将其输入到语言模型中,并显示答案。如果正确安装了 langchain 库,代码现在应该可以正常运行,而不会触发缺少模块的错误。

3.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

# 颜色主题
primary_color = "#1E90FF"  
secondary_color = "#FF6347"  
background_color = "#F5F5F5"  
text_color = "#4561e9"

# 自定义 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 应用标题
st.title("使用 DeepSeek R1 和 Ollama 构建 RAG 系统")

# 加载 PDF
uploaded_file = st.file_uploader("上传 PDF 文件", type="pdf")

if uploaded_file:  
    # 将上传的文件保存到临时位置  
    with open("temp.pdf", "wb") as f:  
        f.write(uploaded_file.getvalue())  

    # 加载 PDF  
    loader = PDFPlumberLoader("temp.pdf")  
    docs = loader.load()

    # 拆分为块  
    text_splitter = SemanticChunker(HuggingFaceEmbeddings())  
    documents = text_splitter.split_documents(docs)

    # 实例化嵌入模型  
    embedder = HuggingFaceEmbeddings()

    # 创建向量库并填充嵌入  
    vector = FAISS.from_documents(documents, embedder)  
    retriever = vector.as_retriever(search_type="similarity", search_kwargs={"k": 3})

    # 定义 LLM  
    llm = Ollama(model="deepseek-r1")

    # 定义提示  
    prompt = """  
    1. 使用以下上下文回答问题。  
    2. 如果不知道答案,请直接说“我不知道”,不要自行编造答案。  
    3. 回答简洁,控制在 3-4 句话以内。  

    上下文:{context}  

    问题:{question}  

    有用的回答:  
    """  
    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="上下文:\n内容:{page_content}\n来源:{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 = st.text_input("向 PDF 提问:")  

    # 处理用户输入  
    if user_input:  
        with st.spinner("处理中..."):  
            response = qa(user_input)["result"]  
            st.write("回答:")  
            st.write(response)  
    else:  
        st.write("请上传 PDF 文件以继续。")

上传文件
在这里插入图片描述
提问:
在这里插入图片描述
在这里插入图片描述

<think>好的,用户之前问过关于大模型如何开启联网功能的问题,现在他具体问到了DeepSeek-R1如何开启联网功能。我需要先确认DeepSeek-R1是什么,以及它是否支持联网功能。 首先,我应该回忆一下之前回答的内容,之前提到了ChatGPT的联网方式,比如Bing搜索、插件、API集成等。现在用户转到了DeepSeek-R1,这可能是一个特定的大模型,可能由深度求索公司开发。我需要检查是否有公开信息说明DeepSeek-R1的联网功能。 查找资料,发现DeepSeek-R1是深度求索公司推出的智能助手,可能具备联网能力。但具体如何开启可能需要参考其官方文档或设置。通常这类功能可能需要用户权限,或者通过特定的指令、设置选项来启用。 用户可能需要的是步骤式的指导,比如在应用中找到相关设置,开启联网权限,或者使用特定命令。但如果没有官方明确说明,需要提醒用户查阅官方指南或联系支持团队。 另外,用户可能已经知道大模型一般如何联网,但针对这个特定模型,可能操作方式不同。需要确认是否有官方提供的插件、API集成或合作伙伴的搜索引擎。 还要注意可能存在地区限制或服务条款,需要提醒用户遵守相关规定,注意隐私数据安全。如果无法找到具体信息,应建议用户查看官方资源或寻求技术支持,避免提供不准确的信息。</think>DeepSeek-R1(深度求索公司开发的智能助手)的联网功能通常需要通过**官方提供的接口或集成能力**实现。以下是目前常见的联网实现方式及建议: --- ### **1. 官方功能支持** - **直接联网模式(若开放)** 部分智能助手会默认或通过设置开启联网权限,例如: - 在对话中直接提问需要实时信息的问题(如“今天北京的天气如何?”),模型可能自动调用联网接口(需官方明确支持此功能)。 - 在设置中检查是否有类似“启用网络搜索”或“实时数据”的开关。 - **插件或扩展功能** 若DeepSeek-R1支持插件系统(类似ChatGPT),可通过安装浏览器插件(如网页访问、搜索引擎插件)获取实时信息。 --- ### **2. API开发者模式** 若你是开发者或通过API调用DeepSeek-R1- **结合搜索引擎API** 在调用模型前,先通过Bing/Google API获取实时数据,再将结果输入模型处理: ```python # 伪代码示例(需替换为真实API密钥) from deepseek_api import DeepSeek import requests def get_weather(city): # 调用天气API(示例) response = requests.get(f"https://api.weather.com/{city}") return response.json() weather_data = get_weather("北京") prompt = f"根据以下数据总结北京天气:{weather_data}" answer = DeepSeek.generate(prompt) ``` - **使用LangChain等框架** 通过LangChain的Agent模块,将DeepSeek-R1与联网工具链结合: ```python from langchain.agents import AgentType, initialize_agent from langchain.tools import Tool from deepseek_api import DeepSeekLLM # 定义联网工具(示例:Serper API) def search_tool(query): return google_search(query) # 需实现具体搜索逻辑 tools = [Tool(name="Search", func=search_tool, description="联网搜索")] agent = initialize_agent(tools, DeepSeekLLM(), agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION) agent.run("上海迪士尼乐园今天营业到几点?") ``` --- ### **3. 通过第三方平台间接联网** 若DeepSeek-R1本身未开放联网功能,可通过以下方式间接实现: - **与企业内部系统集成** 例如:将模型部署在支持访问内部数据库或知识库的服务器上,通过RAG(检索增强生成)扩展实时信息。 - **与钉钉、微信等平台结合** 通过聊天机器人平台(如钉钉机器人、微信公众号)调用联网API,再将结果返回给用户。 --- ### **注意事项** 1. **权限与合规性** - 确认DeepSeek-R1的API使用条款是否允许联网。 - 避免爬取受限制的网站或侵犯隐私数据。 2. **官方支持状态** - 目前DeepSeek-R1的联网能力可能处于灰度测试或定向开放阶段,建议关注[深度求索官方公告](https://www.deepseek.com)或联系技术支持。 3. **信息可靠性** - 网络检索结果需经过过滤验证,避免模型输出错误内容。 --- ### **总结** - **普通用户**:检查设置中的联网开关,或直接提问测试是否支持自动联网(例如“实时新闻”类问题)。 - **开发者**:通过API结合搜索引擎/爬虫工具链,或使用LangChain等框架扩展能力。 - **企业用户**:联系深度求索团队获取定制化联网解决方案(如私有化部署+RAG)。 若以上方法不适用,建议通过**官方渠道**(官网、客服、开发者文档)获取最新支持信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知来者逆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值