本地基于GGUF部署的DeepSeek实现轻量级调优之二:检索增强生成(RAG)

前文,我们在本地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模型,请看我之后的文档哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/968014.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

16vue3实战-----动态路由

16vue3实战-----动态路由 1.思路2.实现2.1创建所有的vue组件2.2创建所有的路由对象文件(与上述中的vue文件一一对应)2.3动态加载所有的路由对象文件2.4根据菜单动态映射正确的路由2.5解决main页面刷新的问题2.6解决main的第一个页面匹配显示的问题2.7根据path匹配menu 1.思路 …

WPS如何接入DeepSeek(通过JS宏调用)

WPS如何接入DeepSeek 一、文本扩写二、校对三、翻译 本文介绍如何通过 WPS JS宏调用 DeepSeek 大模型,实现自动化文本扩写、校对和翻译等功能。 一、文本扩写 1、随便打开一个word文档,点击工具栏“工具”。 2、点击“开发工具”。 3、点击“查看代码”…

前端快速生成接口方法

大家好,我是苏麟,今天聊一下OpenApi。 官网 : umijs/openapi - npm 安装命令 npm i --save-dev umijs/openapi 在根目录(项目目录下)创建文件 openapi.config.js import { generateService } from umijs/openapi// 自…

云消息队列 ApsaraMQ Serverless 演进:高弹性低成本、更稳定更安全、智能化免运维

如今,消息队列已成为分布式架构中不可或缺的关键服务,为电商、物联网、游戏和教育等行业,提供了异步解耦、集成、高性能和高可靠的核心价值。 过去一年,我们发布了云消息队列 ApsaraMQ 全系列产品 Serverless 化,面向…

Spring依赖注入方式

写在前面:大家好!我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正,感谢大家的不吝赐教。我的唯一博客更新地址是:https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油,冲鸭&#x…

Mysql索引失效的场景

对索引列使用函数或表达式,或参与计算(优化方法:将计算移到条件右侧:)例 优化 对索引列进行隐式类型转换,条件中的数据类型与索引列的数据类型不匹配,会进行隐式类型转换 以like 通配符开头索…

CTFHub-RCE系列wp

目录标题 引言什么是RCE漏洞 eval执行文件包含文件包含php://input读取源代码远程包含 命令注入无过滤过滤cat过滤空格过滤目录分隔符过滤运算符综合过滤练习 引言 题目共有如下类型 什么是RCE漏洞 RCE漏洞,全称是Remote Code Execution漏洞,翻译成中文…

算法学习笔记之并查集

简介 问题描述:将编号为1-N的N个对象划分为不相交集合,在每个集合中,选择其中的某个元素代表所在集合。 常见两种操作: 1.合并两个集合 2.查找某元素属于哪个集合 实现方法1 用编号最小的元素标记所在集合; 定义…

渗透利器工具:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)

Burp Suite 联动 XRAY 图形化工具.(主动扫描被动扫描) Burp Suite 和 Xray 联合使用,能够将 Burp 的强大流量拦截与修改功能,与 Xray 的高效漏洞检测能力相结合,实现更全面、高效的网络安全测试,同时提升漏…

菌贝:云南鸡枞菌走向世界的第一品牌

云南,这片神奇的土地,孕育了无数珍稀的野生菌,而鸡枞菌无疑是其中的佼佼者。它以其独特的口感和丰富的营养价值,被誉为“菌中之王”。在云南鸡枞菌的品牌化进程中,菌贝以其卓越的品质和广泛的影响力,成为云…

如何恢复使用 Command+Option+Delete 删除的文件:完整指南

在日常使用 Mac 时,我们经常会使用 CommandOptionDelete 组合键来快速删除文件。这种删除方式会将文件直接移出废纸篓,而不会经过废纸篓的中间步骤,因此文件看似被永久删除。然而,即使文件被这样删除,仍然有几种方法可…

windows生成SSL的PFX格式证书

生成crt证书: 安装openssl winget install -e --id FireDaemon.OpenSSL 生成cert openssl req -x509 -newkey rsa:2048 -keyout private.key -out certificate.crt -days 365 -nodes -subj "/CN=localhost" 转换pfx openssl pkcs12 -export -out certificate.pfx…

用户认证综合实验

实验需求 需求一:根据下表,完成相关配置 需求二:配置DHCP协议,具体要求如下 需求三:防火墙安全区域配置 需求四:防火墙地址组信息 需求五:管理员 为 FW 配置一个配置管理员。要求管理员可以通…

5.7.2 进度管理

文章目录 进度管理Gantt图PERT图 进度管理 进度安排:通过将项目分解成多个活动,分析活动间的依赖关系,估算工作量,分配资源,制定活动时序。 Gantt图 Gantt图横坐标表示时间,纵坐标表示不同任务。使用一条条…

MQTT(Message Queuing Telemetry Transport)协议(二)

下面为你详细介绍如何基于 TCP 协议对 MQTT 进行封装&#xff0c;包括实现思路、代码示例及代码解释。 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h>…

b站——《【强化学习】一小时完全入门》学习笔记及代码(1-3 多臂老虎机)

问题陈述 我们有两个多臂老虎机&#xff08;Multi-Armed Bandit&#xff09;&#xff0c;分别称为左边的老虎机和右边的老虎机。每个老虎机的奖励服从不同的正态分布&#xff1a; 左边的老虎机&#xff1a;奖励服从均值为 500&#xff0c;标准差为 50 的正态分布&#xff0c;即…

Unity 接入Tripo 文生模型,图生模型

官方网站&#xff1a;https://www.tripo3d.ai/app/home自行注册账号并且登陆下载Unity插件&#xff1a;https://cdn-web.tripo3d.ai/plugin/tripo-unity.zip申请apikey&#xff1a; https://platform.tripo3d.ai/api-keys使用&#xff08;后续过程就按照第二步下载的插件里面的…

Arduino 第十一章:温度传感器

Arduino 第十一章&#xff1a;LM35 温度传感器 一、LM35 简介 LM35 是美国国家半导体公司&#xff08;现德州仪器&#xff09;生产的一款精密集成电路温度传感器。与基于热力学原理的传统温度传感器不同&#xff0c;LM35 能直接将温度转换为电压输出&#xff0c;且输出电压与…

【并发控制、更新、版本控制】.NET开源ORM框架 SqlSugar 系列

系列文章目录 &#x1f380;&#x1f380;&#x1f380; .NET开源 ORM 框架 SqlSugar 系列 &#x1f380;&#x1f380;&#x1f380; 文章目录 系列文章目录一、并发累计&#xff08;累加&#xff09;1.1 单条批量累计1.2 批量更新并且字段11.3 批量更新并且字段list中对应的…

5 分钟用满血 DeepSeek R1 搭建个人 AI 知识库(含本地部署)

最近很多朋友都在问&#xff1a;怎么本地部署 DeepSeek 搭建个人知识库。 老实说&#xff0c;如果你不是为了研究技术&#xff0c;或者确实需要保护涉密数据&#xff0c;我真不建议去折腾本地部署。 为什么呢&#xff1f; 目前 Ollama 从 1.5B 到 70B 都只是把 R1 的推理能力…