使用 DeepSeek R1 和 Ollama 開發(fā) RAG 系統(tǒng)(包含完整代碼)
是否想過直接向PDF文檔或技術手冊提問?本文將演示如何通過開源推理工具DeepSeek R1與本地AI模型框架Ollama搭建檢索增強生成(RAG)系統(tǒng)。
高效工具推薦:用Apidog簡化API測試流程
圖片
Apidog作為一體化API解決方案,可實現(xiàn):
- 零腳本自動化核心流程
- 無縫對接CI/CD管道
- 精準定位性能瓶頸
- 可視化接口管理
DeepSeek R1核心優(yōu)勢
相比OpenAI o1模型成本降低95%,具備:
- 精準檢索:每次僅調用3個文檔片段
- 嚴謹輸出:未知問題主動返回"暫不了解"
- 本地運行:徹底消除云端API延遲
環(huán)境準備
1. Ollama本地部署
# 安裝基礎框架
ollama run deepseek-r1 # 默認使用7B模型
Ollama官網(wǎng)下載:https://ollama.ai
圖片
2. 模型選擇策略
# 輕量級場景推薦1.5B版本
ollama run deepseek-r1:1.5b
硬件建議:70B大模型需32GB內存支持
RAG系統(tǒng)構建全流程
Step 1: 導入依賴庫
- 用于文檔處理和檢索的 LangChain。
- 流利使用用戶友好的Web界面。
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
圖片
Step 2: PDF文件上傳與解析
利用 Streamlit 的文件上傳器選擇本地 PDF。使用 PDFPlumberLoader 高效提取文本,無需手動解析。
# 創(chuàng)建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()
Step 3: 文檔語義分塊
利用 Streamlit 的文件上傳器選擇本地 PDF。使用 PDFPlumberLoader 高效提取文本,無需手動解析。
# 初始化語義分塊器
text_splitter = SemanticChunker(
HuggingFaceEmbeddings(model_name="all-MiniLM-L6-v2")
)
# 執(zhí)行分塊操作
documents = text_splitter.split_documents(docs)
圖片
Step 4: 構建向量數(shù)據(jù)庫
# 生成文本嵌入
embeddings = HuggingFaceEmbeddings()
vector_store = FAISS.from_documents(documents, embeddings)
# 配置檢索器
retriever = vector_store.as_retriever(search_kwargs={"k": 3})
Step 5: 配置DeepSeek R1模型
# 初始化本地模型
llm = Ollama(model="deepseek-r1:1.5b")
# 定義提示模板
prompt_template = """
根據(jù)以下上下文:
{context}
問題:{question}
回答要求:
1. 僅使用給定上下文
2. 不確定時回答"暫不了解"
3. 答案控制在四句話內
最終答案:
"""
QA_PROMPT = PromptTemplate.from_template(prompt_template)
Step 6: 組裝RAG處理鏈
# 創(chuàng)建LLM處理鏈
llm_chain = LLMChain(llm=llm, prompt=QA_PROMPT)
# 配置文檔組合模板
document_prompt = PromptTemplate(
template="上下文內容:\n{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
)
Step 7: 啟動交互界面
# 創(chuàng)建問題輸入框
user_question = st.text_input("輸入您的問題:")
if user_question:
with st.spinner("正在生成答案..."):
# 執(zhí)行查詢并顯示結果
response = qa(user_question)["result"]
st.success(response)
完整的代碼:https://gist.github.com/lisakim0/0204d7504d17cefceaf2d37261c1b7d5.js
技術實現(xiàn)要點
語義分塊優(yōu)化:采用SemanticChunker替代傳統(tǒng)滑動窗口,提升上下文連貫性
# 示例:調整分塊策略
text_splitter = SemanticChunker(
embeddings,
breakpoint_threshold=0.85 # 調整語義分割閾值
)
檢索優(yōu)化配置:動態(tài)調整檢索數(shù)量
# 根據(jù)問題復雜度動態(tài)調整k值
def dynamic_retriever(question):
complexity = len(question.split())
return vector_store.as_retriever(search_kwargs={"k": min(complexity, 5)})
混合檢索策略:結合關鍵詞與向量搜索
from langchain.retrievers import BM25Retriever, EnsembleRetriever
bm25_retriever = BM25Retriever.from_documents(documents)
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6]
)
最后
DeepSeek R1 只是一個開始。憑借即將推出的自我驗證和多跳推理等功能,未來的 RAG 系統(tǒng)可以自主辯論和完善其邏輯。