前文,我们在本地windows电脑基于GGUF文件,部署了DeepSeek R1 1.5B模型,如果想在离线模式下加载本地的DeepSeek模型自行对进行训练时,是不能直接使用GGUF文件进行训练的,但是可以对模型进行微调,以下说的是第二种微调的方法:检索增强生成(RAG)。
请参照我的文章在本地部署好模型之后再继续往下看:个人windows电脑上安装DeepSeek大模型(完整详细可用教程)-CSDN博客
第一种微调方法:提示工程。可以查看我的文章:本地基于GGUF部署的DeepSeek实现轻量级调优之一:提示工程(Prompt Engineering)(完整详细教程)-CSDN博客
一、GGUF文件的定位与限制
先说明一下基于GGUF文件部署的本地DeepSeek模型为什么不能直接训练,是因为基于GGUF文件的性质和特点导致的。
1.GGUF的作用:
(1)推理优化:GGUF(GPT-Generated Unified Format)是专为高效推理设计的二进制格式,常用于llama.cpp等工具在CPU/GPU上运行量化模型。
(2)量化支持:支持多种量化方法(如Q4_K_M、Q5_K_S),显著减少显存占用,但会损失部分精度。
2.训练限制:
(1)缺乏训练所需信息:GGUF文件仅包含推理所需的权重和架构简略信息,缺少训练必需的反向传播梯度计算图、优化器状态等。
(2)框架不兼容:主流训练框架(如PyTorch、TensorFlow)无法直接加载GGUF文件进行训练。
二、实现过程说明
我已经在本地的Windows系统上成功部署了基于GGUF格式的DeepSeek R1 1.5模型,使用llama.cpp工具进行加载DeepSeek和推理,现在想要进一步部署sentence-transformers/all-MiniLM-L6-v2模型,用于实现RAG(检索增强生成)的微调。其中,部署sentence-transformers模型用于将文档和查询编码为向量,以便进行相似性检索。使用all-MiniLM-L6-v2模型作为RAG中的嵌入模型,来增强DeepSeek模型的生成效果。GGUF模型通常用于推理,而RAG需要结合检索和生成两部分,因此需要将两者结合起来。
接下来,就是如何在Windows环境下本地部署entence-transformers/all-MiniLM-L6-v2这个嵌入模型,并集成到现有的RAG流程中。我需要考虑以下几个步骤:
1. 安装依赖
确保用户安装了必要的Python库,如sentence-transformers、torch等。同时,可能需要处理Windows特有的依赖问题,比如C++编译工具链,但sentence-transformers通常不需要编译,除非需要优化。
2. 下载并保存模型
用户需要将all-MiniLM-L6-v2模型下载到本地目录。这里需要指导用户如何通过代码或命令行下载,并保存到指定路径,以便离线使用。
3. 验证模型加载
确保模型可以离线加载,并且能够生成嵌入向量。可能需要测试一些示例代码,确认没有网络请求,完全离线运行。
4. 集成到RAG流程
用户现有的RAG流程可能已经使用其他嵌入模型或方法,现在需要替换或整合sentence-transformers模型。需要指导如何修改现有的向量数据库配置,使用新的嵌入模型。
5. 性能优化
考虑到Windows系统可能存在的性能限制,尤其是如果用户没有GPU,需要提供CPU优化的建议,比如使用量化或调整批处理大小。
6. 测试和验证
确保整个流程从文档加载、分块、嵌入生成到检索和生成都能正常工作。可能需要提供示例代码和测试用例。
结合外部知识库动态扩展模型输出,RAG无需修改GGUF模型权重。关键优化技巧:
方向 | 具体方法 |
检索质量 | 1. 调整分块大小(chunk_size=256-1024) 2. 添加元数据过滤(如文档来源、日期) |
生成控制 | 1. 设置temperature=0.3减少随机性 2. 使用max_tokens限制输出长度 |
性能提升 | 1. 启用llama.cpp的GPU加速(n_gpu_layers=20) 2. 缓存常用检索结果 |
本地部署全流程如下:
(1)知识库:ChromaDB + 自定义文档
(2)检索:Sentence Transformers + 混合策略
(3)生成:llama.cpp加载GGUF模型
(4)交互:Gradio快速搭建界面
三、部署sentence-transformers/all-MiniLM-L6-v2模型
1. 安装必要的python依赖
# 安装核心库
pip install sentence-transformers transformers torch
# 安装文档处理工具
pip install pypdf python-docx langchain chromadb
以上可能是部分,可以在调试过程中看到还有哪些缺少的依赖项,再安装。
2. 创建项目目录结构
可以直接在D盘创建一个文件夹my_deepseek_project,再按下面的结构进行设置多层文件夹。DeepSeek基于DeepSeek-R1-1.5B.gguf的RAG微调项目完整文件包,包括了DeepSeek-R1-Distill-Qwen-1.5B-GGUF、sentence-transformers/all-MiniLM-L6-v2模型和训练文档。完整项目文件有2.5G,有需要的可以联系我。
my_deepseek_project/
├── models/
│ ├── deepseek/ # 存放DeepSeek GGUF模型文件
│ └── st-minilm/ # 存放sentence-transformers模型
├── chroma_db/ # 向量数据库存储
└── docs/ # 知识库文档存放处
在个人windows电脑上安装DeepSeek大模型(完整详细可用教程)-CSDN博客。我设置的项目目录是直接在D盘根目录下,所以要修改一下。
(1)剪切D盘根目录下的DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf和Modelfile到D:\my_deepseek_project\models\deepseek目录下。
(2)修改Modelfile文件中的路径,如下图所示。
(3)打开终端或命令行界面,进入D:\my_deepseek_project\models\deepseek,运行以下命令来重新创建Ollama模型:
ollama create my_model_name -f Modelfile
3. 下载sentence-transformers模型到本地
(1)(不推荐)创建一个python文件,如download_sentence-transformers.py。python代码如下:
from sentence_transformers import SentenceTransformer
# 下载模型到指定目录
model = SentenceTransformer("sentence-transformers/all-MiniLM-L6-v2")
model.save("D:/my_deepseek_project/models/st-minilm")
CMD执行“py 再将download_sentence-transformers.py拖进去”执行。
这种可能会因为访问https://huggingface.co而无法下载,推荐使用下一种方法。
(2)CMD在魔塔社区下载(推荐)
先安装魔塔社区:pip install modelscope
在从魔塔社区下载:
modelscope download --model sentence-transformers/all-MiniLM-L6-v2
下载的模型文件都是在C盘下,C:\Users\lzm07\.cache\modelscope\hub\sentence-transformers\all-MiniLM-L6-v2。接下来将下载好的整个sentence-transformers文件夹剪接到我们设定好的项目目录D:\my_deepseek_project\models\st-minilm中。
4. 验证模型文件结构
确认D:/my_deepseek_project/models目录包含以下文件:
models/st-minilm/sentence-transformers/all-MiniLM-L6-v2
├── config.json
├── pytorch_model.bin
├── sentence_bert_config.json
├── tokenizer_config.json
└── vocab.txt
四、基于GGUF的轻量级调优之检索增强生成(RAG)
RAG核心流程:(1)知识库构建 → (2)检索相关文档 → (3)增强提示输入 → (4)生成最终回答。以下是分步实现方案:
1.本地知识库构建
向量数据库:ChromaDB(轻量级,支持本地运行)
文本嵌入模型:Sentence Transformers(离线使用all-MiniLM-L6-v2)
关键参数配置表
组件 | 参数 | 推荐值 | 说明 |
文本分块 | chunk_size | 512字符 | 平衡上下文完整性与检索效率 |
chunk_overlap | 50字符 | 防止信息割裂 | |
嵌入模型 | model_name | all-MiniLM-L6-v2 | 轻量级多语言模型 |
向量数据库 | persist_directory | ./chroma_db | 本地存储路径 |
混合检索 | weights | [0.4, 0.6] | BM25与向量检索权重比 |
(1)数据准备与格式转换
支持文档类型:
1)文本类:TXT、Markdown、HTML、JSON
2)办公文档:PDF(需OCR处理扫描件)、Word(.docx)、PowerPoint
3)代码:Python、Java等源代码文件
4)结构化数据:CSV、Excel(需转换为文本)
在确保本机上已经安装python的情况下,顺序安装python依赖项:langchain、langchain_community。如果使用清华镜像安装的命令为:pip install --extra-index-url https://pypi.tuna.tsinghua.edu.cn/simple langchain langchain_community。确保要全部安装成功。
还要安装python依赖:pip install pypdf python-docx pandas
python代码示例(完整代码在后面):
# 统一转换为纯文本
from pathlib import Path
from langchain.document_loaders import (
PyPDFLoader, # PDF
Docx2txtLoader, # Word
TextLoader, # TXT
CSVLoader # CSV
)
# 加载本地文档
def load_documents(directory):
docs = []
for ext in ["*.pdf", "*.docx", "*.txt", "*.csv"]:
for file in Path(directory).glob(ext):
if ext == "*.pdf":
loader = PyPDFLoader(str(file))
elif ext == "*.docx":
loader = Docx2txtLoader(str(file))
elif ext == "*.txt":
loader = TextLoader(str(file))
elif ext == "*.csv":
loader = CSVLoader(str(file))
docs.extend(loader.load())
return docs
(2)文本分块与清洗
分块策略:
递归字符分割:按段落、句号、换行符分块
重叠窗口:保留相邻块的部分重叠以防信息割裂
Python代码示例:
from langchain.text_splitter import RecursiveCharacterTextSplitter
# 文本分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=512, # 每块约500字符
chunk_overlap=50, # 块间重叠50字符
separators=["\n\n", "\n", "。", "?", "!"] # 中文友好分隔符
)
# 执行分块
split_docs = text_splitter.split_documents(documents)
清洗步骤:
去噪:移除特殊字符(如\x00)、乱码
标准化:统一全角/半角符号、繁体转简体
关键信息提取:保留标题、章节结构元数据
Python代码示例:
import re
from zhconv import convert # 中文繁简转换
# 清洗文本
def clean_text(text):
# 移除不可见字符
text = re.sub(r'[\x00-\x1F\x7F-\x9F]', '', text)
# 繁体转简体
text = convert(text, 'zh-cn')
# 合并连续空白
text = re.sub(r'\s+', ' ', text)
return text.strip()
for doc in split_docs:
doc.page_content = clean_text(doc.page_content)
(3)向量化与本地存储
嵌入模型选择:
轻量级本地模型:sentence-transformers/all-MiniLM-L6-v2(适用于中英文)
高性能本地模型:BAAI/bge-small-zh-v1.5(专为中文优化)
向量数据库选型:
ChromaDB:轻量级、纯Python实现,适合快速本地部署
FAISS:Facebook开发的高效相似性搜索库,支持GPU加速
1)安装必要的库
首先,确保安装了chromadb、sentence-transformers和transformers库。运行以下命令:
pip install chromadb sentence-transformers transformers
2)下载并加载 all-MiniLM-L6-v2 模型
all-MiniLM-L6-v2 模型可以从知识库中检索相关信息,用于将文本嵌入到向量空间中,以便进行相似性检索。使用 sentence-transformers 库加载模型。
Python代码示例(ChromaDB):
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
# 初始化嵌入模型(离线模式)
embeddings = HuggingFaceEmbeddings(
model_name="sentence-transformers/all-MiniLM-L6-v2", #更换成本地模型
model_kwargs={'device': 'cpu'}, # 无GPU时使用CPU
encode_kwargs={'normalize_embeddings': True}
)
# 创建向量库
vector_db = Chroma.from_documents(
documents=split_docs,
embedding=embeddings,
persist_directory="./chroma_db" # 本地存储路径
)
vector_db.persist() # 确保持久化
2.检索器配置
(1)元数据增强检索
为每个文本块添加结构化元数据,提升检索精度:
python代码示例:
# 示例:从文件名提取文档类别
for doc in split_docs:
source = doc.metadata['source']
if "技术文档" in source:
doc.metadata["category"] = "技术"
elif "产品手册" in source:
doc.metadata["category"] = "产品"
else:
doc.metadata["category"] = "通用"
# 检索时过滤类别
retriever = vector_db.as_retriever(
search_kwargs={"filter": {"category": "技术"}}
)
(2)检索策略优化
混合检索方案:
向量相似性检索:基于语义匹配
关键词检索(BM25):基于精确术语匹配
python代码示例:
from langchain.retrievers import BM25Retriever, EnsembleRetriever
# 向量检索
vector_retriever = vector_db.as_retriever(search_kwargs={"k": 3})
# 关键词检索
bm25_retriever = BM25Retriever.from_documents(split_docs)
bm25_retriever.k = 2
# 混合检索器
ensemble_retriever = EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6]
)
(3)知识库更新与维护
增量更新脚本:
python代码示例:
def update_knowledge_base(new_docs, vector_db_path):
# 加载现有库
existing_db = Chroma(
persist_directory=vector_db_path,
embedding_function=embeddings
)
# 处理新文档
new_split_docs = text_splitter.split_documents(new_docs)
existing_db.add_documents(new_split_docs)
existing_db.persist()
完整的python代码如下(在上面代码基础上稍有修改):
# 安装必要依赖(如果尚未安装)
# pip install pypdf python-docx langchain sentence-transformers chromadb zhconv docx2txt rank_bm25
from pathlib import Path
from langchain.document_loaders import (
PyPDFLoader, # PDF
Docx2txtLoader, # Word
TextLoader, # TXT
CSVLoader # CSV
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
import re
from zhconv import convert # 中文繁简转换
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.retrievers import BM25Retriever, EnsembleRetriever
# ----------------------
# 核心函数定义部分
# ----------------------
def load_documents(directory: str):
"""加载指定目录下的文档"""
docs = []
directory_path = Path(directory)
# 支持的扩展名映射表
loader_mapping = {
".pdf": PyPDFLoader,
".docx": Docx2txtLoader,
".txt": TextLoader,
".csv": CSVLoader
}
# 遍历目录下所有文件
for file_path in directory_path.glob("*"):
if file_path.suffix.lower() in loader_mapping:
try:
loader_class = loader_mapping[file_path.suffix.lower()]
loader = loader_class(str(file_path))
docs.extend(loader.load())
print(f"成功加载文件:{file_path.name}")
except Exception as e:
print(f"加载文件 {file_path.name} 失败:{str(e)}")
continue
return docs
def clean_text(text: str) -> str:
"""文本清洗处理"""
# 移除不可见字符
text = re.sub(r'[\x00-\x1F\x7F-\x9F]', '', text)
# 繁体转简体
text = convert(text, 'zh-cn')
# 合并连续空白
text = re.sub(r'\s+', ' ', text)
return text.strip()
def init_knowledge_base(data_dir: str = "D:/my_deepseek_project/docs", persist_dir: str = "D:/my_deepseek_project/chroma_db"):
"""初始化知识库"""
# 1. 加载文档
raw_documents = load_documents(data_dir)
if not raw_documents:
raise ValueError("未找到可处理的文档,请检查目录和文件格式")
# 2. 文本分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "?", "!"]
)
# 新增:保存分块后的文档列表
global split_docs # 用于后续检索器初始化
split_docs = text_splitter.split_documents(raw_documents)
# 3. 清洗文本
for doc in split_docs:
doc.page_content = clean_text(doc.page_content)
# 添加元数据(示例:从文件名提取类别)
if "技术" in doc.metadata["source"]:
doc.metadata["category"] = "技术"
elif "产品" in doc.metadata["source"]:
doc.metadata["category"] = "产品"
else:
doc.metadata["category"] = "通用"
# 4. 创建向量存储
embeddings = HuggingFaceEmbeddings(
model_name=r"D:\my_deepseek_project\models\st-minilm\sentence-transformers\all-MiniLM-L6-v2",
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': True}
)
vector_db = Chroma.from_documents(
documents=split_docs,
embedding=embeddings,
persist_directory=persist_dir
)
vector_db.persist()
return vector_db
def get_retriever(vector_db, use_ensemble: bool = True):
"""获取检索器"""
# 向量检索
vector_retriever = vector_db.as_retriever(search_kwargs={"k": 3})
if use_ensemble:
# 修正:使用原始Document对象初始化BM25
bm25_retriever = BM25Retriever.from_documents(split_docs) # 直接使用预处理的分块文档
bm25_retriever.k = 2
# 混合检索
return EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6]
)
else:
return vector_retriever
def update_knowledge_base(new_data_dir: str, vector_db_path: str = "D:/my_deepseek_project/chroma_db"):
"""更新知识库"""
# 加载现有库,指定本地模型路径
embeddings = HuggingFaceEmbeddings(
model_name=r"D:\my_deepseek_project\models\st-minilm\sentence-transformers\all-MiniLM-L6-v2", # Windows路径格式
model_kwargs={'device': 'cpu'} # 无GPU时使用CPU
)
existing_db = Chroma(
persist_directory=vector_db_path,
embedding_function=embeddings
)
# 处理新文档
new_docs = load_documents(new_data_dir)
if not new_docs:
print("未找到新文档可添加")
return
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50
)
new_split_docs = text_splitter.split_documents(new_docs)
# 清洗和添加元数据
for doc in new_split_docs:
doc.page_content = clean_text(doc.page_content)
doc.metadata["category"] = "new" # 标记为新添加
existing_db.add_documents(new_split_docs)
existing_db.persist()
print(f"成功添加 {len(new_split_docs)} 个新文档块")
# ----------------------
# 主程序执行部分
# ----------------------
if __name__ == "__main__":
# 初始化知识库
try:
vector_db = init_knowledge_base()
print("知识库初始化完成")
except Exception as e:
print(f"知识库初始化失败:{str(e)}")
exit(1)
# 获取检索器
retriever = get_retriever(vector_db)
print("检索器初始化成功!")
# 示例检索
sample_query = "请解释量子计算的基本原理"
docs = retriever.get_relevant_documents(sample_query)
print(f"检索到 {len(docs)} 条相关文档")
# 更新知识库示例(需要时取消注释)
# update_knowledge_base("D:/my_deepseek_project/new_docs")
使用说明:
(1)将自己的文档放入 D:/my_deepseek_project/docs 目录(支持PDF/Word/TXT/CSV)
(2)运行脚本完成初始化:python rag_pipeline.py
(3)后续添加新文档:
1)将新文档放入 D:/Dmy_deepseek_project/new_docs 目录
2)取消注释最后一行 update_knowledge_base("D:/my_deepseek_project/new_docs")
在CMD中运行结果如下
3.集成DeepSeek模型与RAG
(1)说明
1)准备RAG微调的数据
RAG(Retrieval-Augmented Generation)需要两个主要部分:
Retriever:用于从知识库中检索相关信息。
Generator:用于生成文本。
all-MiniLM-L6-v2 模型可以作为 Retriever,用于将文本嵌入到向量空间中,以便进行相似性检索。
2)配置RAG模型
我们前文已经部署了DeepSeek R1 1.5模型,可以使用transformers库中的RagTokenizer和RagRetriever来配置RAG模型。
3)微调RAG模型
微调RAG模型需要准备训练数据,并使用Trainer或TrainingArguments进行训练。
(2)实现步骤:
1)配置GGUF模型加载
from llama_cpp import Llama
# 加载DeepSeek模型
deepseek = Llama(
model_path=r"D:\my_deepseek_project\models\deepseek\DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf",
n_ctx=2048,
n_gpu_layers=20 # GPU加速层数(根据显存调整)
)
2)实现RAG问答链
def rag_query(question: str, top_k: int = 3):
# 1. 检索相关文档
retriever = vector_db.as_retriever(search_kwargs={"k": top_k})
context_docs = retriever.get_relevant_documents(question)
context = "\n".join([doc.page_content for doc in context_docs])
# 2. 构建增强提示
prompt = f"""基于以下上下文:
{context}
---
问题:{question}
请给出详细回答:"""
# 3. 生成回答
response = deepseek.create_chat_completion(
messages=[{"role": "user", "content": prompt}],
max_tokens=512,
temperature=0.3
)
return response['choices'][0]['message']['content']
3)强制禁用网络访问(可以不用)
import os
os.environ["TRANSFORMERS_OFFLINE"] = "1" # 禁用HF Hub
os.environ["LLAMA_NO_HTTP"] = "1" # 禁用llama.cpp的网络
4)测试问答流程
question = "候鸟优化算法是什么?"
answer = rag_query(question)
print(f"问题:{question}\n回答:{answer}")
将以上代码全部放到前面的python文件中的最后,就可以CMD运行了。以下也是全文的完整python代码:
# 安装必要依赖(如果尚未安装)
# pip install pypdf python-docx langchain sentence-transformers chromadb zhconv docx2txt rank_bm25
from pathlib import Path
from langchain.document_loaders import (
PyPDFLoader, # PDF
Docx2txtLoader, # Word
TextLoader, # TXT
CSVLoader # CSV
)
from langchain.text_splitter import RecursiveCharacterTextSplitter
import re
from zhconv import convert # 中文繁简转换
from langchain.embeddings import HuggingFaceEmbeddings
from langchain.vectorstores import Chroma
from langchain.retrievers import BM25Retriever, EnsembleRetriever
# ----------------------
# 核心函数定义部分
# ----------------------
def load_documents(directory: str):
"""加载指定目录下的文档"""
docs = []
directory_path = Path(directory)
# 支持的扩展名映射表
loader_mapping = {
".pdf": PyPDFLoader,
".docx": Docx2txtLoader,
".txt": TextLoader,
".csv": CSVLoader
}
# 遍历目录下所有文件
for file_path in directory_path.glob("*"):
if file_path.suffix.lower() in loader_mapping:
try:
loader_class = loader_mapping[file_path.suffix.lower()]
loader = loader_class(str(file_path))
docs.extend(loader.load())
print(f"成功加载文件:{file_path.name}")
except Exception as e:
print(f"加载文件 {file_path.name} 失败:{str(e)}")
continue
return docs
def clean_text(text: str) -> str:
"""文本清洗处理"""
# 移除不可见字符
text = re.sub(r'[\x00-\x1F\x7F-\x9F]', '', text)
# 繁体转简体
text = convert(text, 'zh-cn')
# 合并连续空白
text = re.sub(r'\s+', ' ', text)
return text.strip()
def init_knowledge_base(data_dir: str = "D:/my_deepseek_project/docs", persist_dir: str = "D:/my_deepseek_project/chroma_db"):
"""初始化知识库"""
# 1. 加载文档
raw_documents = load_documents(data_dir)
if not raw_documents:
raise ValueError("未找到可处理的文档,请检查目录和文件格式")
# 2. 文本分块
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50,
separators=["\n\n", "\n", "。", "?", "!"]
)
# 新增:保存分块后的文档列表
global split_docs # 用于后续检索器初始化
split_docs = text_splitter.split_documents(raw_documents)
# 3. 清洗文本
for doc in split_docs:
doc.page_content = clean_text(doc.page_content)
# 添加元数据(示例:从文件名提取类别)
if "技术" in doc.metadata["source"]:
doc.metadata["category"] = "技术"
elif "产品" in doc.metadata["source"]:
doc.metadata["category"] = "产品"
else:
doc.metadata["category"] = "通用"
# 4. 创建向量存储
embeddings = HuggingFaceEmbeddings(
model_name=r"D:\my_deepseek_project\models\st-minilm\sentence-transformers\all-MiniLM-L6-v2",
model_kwargs={'device': 'cpu'},
encode_kwargs={'normalize_embeddings': True}
)
vector_db = Chroma.from_documents(
documents=split_docs,
embedding=embeddings,
persist_directory=persist_dir
)
vector_db.persist()
return vector_db
def get_retriever(vector_db, use_ensemble: bool = True):
"""获取检索器"""
# 向量检索
vector_retriever = vector_db.as_retriever(search_kwargs={"k": 3})
if use_ensemble:
# 修正:使用原始Document对象初始化BM25
bm25_retriever = BM25Retriever.from_documents(split_docs) # 直接使用预处理的分块文档
bm25_retriever.k = 2
# 混合检索
return EnsembleRetriever(
retrievers=[bm25_retriever, vector_retriever],
weights=[0.4, 0.6]
)
else:
return vector_retriever
def update_knowledge_base(new_data_dir: str, vector_db_path: str = "D:/my_deepseek_project/chroma_db"):
"""更新知识库"""
# 加载现有库,指定本地模型路径
embeddings = HuggingFaceEmbeddings(
model_name=r"D:\my_deepseek_project\models\st-minilm\sentence-transformers\all-MiniLM-L6-v2", # Windows路径格式
model_kwargs={'device': 'cpu'} # 无GPU时使用CPU
)
existing_db = Chroma(
persist_directory=vector_db_path,
embedding_function=embeddings
)
# 处理新文档
new_docs = load_documents(new_data_dir)
if not new_docs:
print("未找到新文档可添加")
return
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=512,
chunk_overlap=50
)
new_split_docs = text_splitter.split_documents(new_docs)
# 清洗和添加元数据
for doc in new_split_docs:
doc.page_content = clean_text(doc.page_content)
doc.metadata["category"] = "new" # 标记为新添加
existing_db.add_documents(new_split_docs)
existing_db.persist()
print(f"成功添加 {len(new_split_docs)} 个新文档块")
# ----------------------
# 主程序执行部分
# ----------------------
if __name__ == "__main__":
# 初始化知识库
try:
vector_db = init_knowledge_base()
print("知识库初始化完成")
except Exception as e:
print(f"知识库初始化失败:{str(e)}")
exit(1)
# 获取检索器
retriever = get_retriever(vector_db)
print("检索器初始化成功!")
# 示例检索
sample_query = "请解释量子计算的基本原理"
docs = retriever.get_relevant_documents(sample_query)
print(f"检索到 {len(docs)} 条相关文档")
# 更新知识库示例(需要时取消注释)
# update_knowledge_base("D:/my_deepseek_project/new_docs")
#以下是集成DeepSeek模型与RAG
from llama_cpp import Llama
# 加载DeepSeek模型
deepseek = Llama(
model_path=r"D:\my_deepseek_project\models\deepseek\DeepSeek-R1-Distill-Qwen-1.5B-Q8_0.gguf",
n_ctx=2048,
n_gpu_layers=20 # GPU加速层数(根据显存调整)
)
def rag_query(question: str, top_k: int = 3):
# 1. 检索相关文档
retriever = vector_db.as_retriever(search_kwargs={"k": top_k})
context_docs = retriever.get_relevant_documents(question)
context = "\n".join([doc.page_content for doc in context_docs])
# 2. 构建增强提示
prompt = f"""基于以下上下文:
{context}
---
问题:{question}
请给出详细回答:"""
# 3. 生成回答
response = deepseek.create_chat_completion(
messages=[{"role": "user", "content": prompt}],
max_tokens=512,
temperature=0.3
)
return response['choices'][0]['message']['content']
import os
os.environ["TRANSFORMERS_OFFLINE"] = "1" # 禁用HF Hub
os.environ["LLAMA_NO_HTTP"] = "1" # 禁用llama.cpp的网络
# 示例查询
question = "候鸟优化算法是什么?"
answer = rag_query(question)
print(f"问题:{question}\n回答:{answer}")
CMD运行结果如下:
五、总结与建议
针对deepseek模型的微调还是原生训练,总结如下:
场景 | 推荐方案 | 可行性 |
直接训练模型 | 使用原始PyTorch模型文件 | ✅ |
快速适配模型行为 | 提示工程/RAG | ✅ |
必须基于GGUF的轻量级调整 | 转换为PyTorch格式(如支持)或使用外部增强 | x |
最终建议:
(1)优先使用原始PyTorch模型:确保文件完整(config.json + pytorch_model.bin)。
(2)离线加载配置,python代码如下:
from transformers import AutoModel
model = AutoModel.from_pretrained(
"./local/model_dir",
local_files_only=True # 强制离线模式
)
(3)避免依赖GGUF训练:除非有特殊工具链支持,否则GGUF不适合训练场景。
直接在原始PyTorch模型文件下训练deepseek模型,请看我之后的文档哦!