-

MacBook本地AI知识库部署计划

前言

【主要诉求】

我现在用的是macbook电脑,我现在需要搭建我个人的本地AI知识库,我要达成的步骤如下:

  1. 在本地部署deepseek模型,要求能把模型跑起来
  2. 将我的知识库(txt文件格式)和模型关联起来,采用rag模型的方式,后续每次我问deepseek问题,他都可以先去访问一遍我的知识库。
  3. 我的知识库会补充内容的,我希望每次deepseek问的问题都可以从最新的知识库进行读取

【补充信息】

  1. 我的macbook是48GB内存,M3的芯片,可用存储空间100G,你可以先部署最小参数的模型,先把流程跑通久好
  2. 不限制版本,轻量级就好,我要先把流程跑通
  3. 我的知识库大概有6万多个字,200多个文档
  4. 有python编程经验,但没有机器学习的经验,所以关于机器学习的步骤你要讲究的详细一点
  5. 允许一定的延迟

概述

本文档提供了在MacBook上部署DeepSeek模型并实现RAG(检索增强生成)功能的详细步骤,使模型能够访问并利用本地txt文件知识库。

系统需求

  • 硬件:MacBook M3芯片,48GB内存,100GB可用存储空间
  • 操作系统:macOS
  • 知识库:约6万多字,200多个txt文档

部署架构

我们将采用以下架构来实现本地AI知识库:

  1. 模型部署:使用Ollama在本地部署DeepSeek-R1模型(7B或14B版本)
  2. 知识库处理:使用LangChain框架处理txt文件并创建向量存储
  3. RAG实现:通过检索增强生成技术将模型与知识库集成
  4. 动态更新机制:设计一个能够检测和处理知识库更新的机制

详细部署步骤

1. 安装必要软件

1.1 安装Ollama

Ollama是一个轻量级的工具,用于在本地运行大型语言模型。

1
2
3
# 访问Ollama官网下载macOS版本
# https://ollama.com/download
# 下载后安装.dmg文件

1.2 安装Docker Desktop(可选,用于Open WebUI)

如果需要图形化界面,可以安装Docker Desktop和Open WebUI。

1
2
3
# 访问Docker官网下载macOS版本
# https://docs.docker.com/desktop/install/mac-install/
# 下载后安装.dmg文件

1.3 安装Python依赖

1
2
3
4
5
6
# 创建虚拟环境
python3 -m venv ~/ai_knowledge_base_env
source ~/ai_knowledge_base_env/bin/activate

# 安装必要的Python包
pip install langchain langchain_community faiss-cpu sentence-transformers streamlit

2. 部署DeepSeek模型

2.1 下载并运行DeepSeek模型

基于您的硬件配置(M3芯片,48GB内存),我们推荐使用DeepSeek-R1的7B或14B模型。

1
2
3
4
5
6
7
8
# 启动Ollama服务
# 这通常在安装后自动启动,也可以通过应用程序启动

# 下载并运行DeepSeek-R1 7B模型
ollama run deepseek-r1:7b

# 或者,如果您想要更强大的推理能力且有足够内存,可以使用14B模型
# ollama run deepseek-r1:14b

2.2 验证模型部署

1
2
# 在终端中测试模型
ollama run deepseek-r1:7b "请简要介绍一下你自己"

3. 知识库集成

3.1 创建项目目录结构

1
mkdir -p ~/ai_knowledge_base/{knowledge,scripts,app}

3.2 处理txt文件知识库

创建一个Python脚本来处理txt文件并生成向量存储:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# ~/ai_knowledge_base/scripts/process_knowledge.py

import os
from langchain_community.document_loaders import TextLoader, DirectoryLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
import datetime

# 知识库目录
knowledge_dir = os.path.expanduser("~/ai_knowledge_base/knowledge")
# 向量存储目录
vector_store_path = os.path.expanduser("~/ai_knowledge_base/vector_store")

# 加载所有txt文件
loader = DirectoryLoader(knowledge_dir, glob="**/*.txt", loader_cls=TextLoader)
documents = loader.load()
print(f"加载了 {len(documents)} 个文档")

# 分割文档
text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=200,
length_function=len,
)
chunks = text_splitter.split_documents(documents)
print(f"创建了 {len(chunks)} 个文本块")

# 创建嵌入
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")

# 创建向量存储
vector_store = FAISS.from_documents(chunks, embeddings)

# 保存向量存储
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
save_path = f"{vector_store_path}_{timestamp}"
vector_store.save_local(save_path)

# 创建最新版本的符号链接
latest_path = f"{vector_store_path}_latest"
if os.path.exists(latest_path):
os.remove(latest_path)
os.symlink(save_path, latest_path)

print(f"向量存储已保存到 {save_path}")
print(f"最新版本链接: {latest_path}")

3.3 创建RAG应用

创建一个Python脚本来实现RAG功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# ~/ai_knowledge_base/app/rag_app.py

import os
from langchain_community.llms import Ollama
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain.prompts import PromptTemplate
from langchain.chains import RetrievalQA

# 加载向量存储
vector_store_path = os.path.expanduser("~/ai_knowledge_base/vector_store_latest")
embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2")
vector_store = FAISS.load_local(vector_store_path, embeddings)
retriever = vector_store.as_retriever(search_kwargs={"k": 5})

# 设置Ollama模型
llm = Ollama(model="deepseek-r1:7b")

# 创建提示模板
template = """
你是一个有用的AI助手,使用提供的上下文来回答问题。
如果你不知道答案,就说你不知道,不要试图编造答案。

上下文信息:
{context}

问题: {question}

回答:
"""
prompt = PromptTemplate(template=template, input_variables=["context", "question"])

# 创建RAG链
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
chain_type="stuff",
retriever=retriever,
chain_type_kwargs={"prompt": prompt}
)

# 交互式问答
def ask(question):
return qa_chain.run(question)

if __name__ == "__main__":
while True:
question = input("\n请输入您的问题 (输入'退出'结束): ")
if question.lower() in ['退出', 'exit', 'quit']:
break
answer = ask(question)
print(f"\n回答: {answer}")

3.4 创建Web界面(可选)

使用Streamlit创建一个简单的Web界面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# ~/ai_knowledge_base/app/web_app.py

import streamlit as st
import sys
import os

# 添加父目录到路径
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from app.rag_app import ask

st.title("DeepSeek知识库问答系统")

# 初始化会话状态
if "messages" not in st.session_state:
st.session_state.messages = []

# 显示聊天历史
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])

# 接收用户输入
if prompt := st.chat_input("请输入您的问题"):
# 添加用户消息到聊天历史
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)

# 生成回答
with st.chat_message("assistant"):
with st.spinner("思考中..."):
response = ask(prompt)
st.markdown(response)

# 添加助手回答到聊天历史
st.session_state.messages.append({"role": "assistant", "content": response})

4. 实现知识库动态更新机制

创建一个脚本来检测知识库变化并更新向量存储:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# ~/ai_knowledge_base/scripts/update_knowledge.py

import os
import time
import hashlib
import subprocess
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class KnowledgeUpdateHandler(FileSystemEventHandler):
def __init__(self, knowledge_dir, update_script):
self.knowledge_dir = knowledge_dir
self.update_script = update_script
self.last_hash = self.get_directory_hash()
self.cooldown = False
self.cooldown_time = 60 # 冷却时间(秒)

def get_directory_hash(self):
"""计算目录中所有txt文件的哈希值"""
hash_md5 = hashlib.md5()
for root, _, files in os.walk(self.knowledge_dir):
for file in sorted(files):
if file.endswith('.txt'):
file_path = os.path.join(root, file)
with open(file_path, 'rb') as f:
for chunk in iter(lambda: f.read(4096), b""):
hash_md5.update(chunk)
return hash_md5.hexdigest()

def on_modified(self, event):
if self.cooldown:
return

current_hash = self.get_directory_hash()
if current_hash != self.last_hash:
print(f"检测到知识库变化,正在更新向量存储...")
subprocess.run(['python', self.update_script])
self.last_hash = current_hash
self.cooldown = True
time.sleep(self.cooldown_time)
self.cooldown = False

if __name__ == "__main__":
knowledge_dir = os.path.expanduser("~/ai_knowledge_base/knowledge")
update_script = os.path.expanduser("~/ai_knowledge_base/scripts/process_knowledge.py")

event_handler = KnowledgeUpdateHandler(knowledge_dir, update_script)
observer = Observer()
observer.schedule(event_handler, knowledge_dir, recursive=True)
observer.start()

try:
print(f"开始监控知识库目录: {knowledge_dir}")
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()

5. 创建启动脚本

创建一个便捷的启动脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# ~/ai_knowledge_base/start.sh

#!/bin/bash

# 激活虚拟环境
source ~/ai_knowledge_base_env/bin/activate

# 检查Ollama服务是否运行
if ! pgrep -x "ollama" > /dev/null; then
echo "正在启动Ollama服务..."
open -a Ollama
sleep 5
fi

# 检查知识库目录是否存在
KNOWLEDGE_DIR=~/ai_knowledge_base/knowledge
if [ ! -d "$KNOWLEDGE_DIR" ]; then
echo "创建知识库目录..."
mkdir -p "$KNOWLEDGE_DIR"
echo "请将您的txt文件放入 $KNOWLEDGE_DIR 目录"
fi

# 检查向量存储是否存在,如果不存在则创建
VECTOR_STORE=~/ai_knowledge_base/vector_store_latest
if [ ! -d "$VECTOR_STORE" ]; then
echo "初始化向量存储..."
python ~/ai_knowledge_base/scripts/process_knowledge.py
fi

# 启动知识库监控(后台运行)
echo "启动知识库监控..."
python ~/ai_knowledge_base/scripts/update_knowledge.py &
MONITOR_PID=$!

# 启动Web界面
echo "启动Web界面..."
streamlit run ~/ai_knowledge_base/app/web_app.py

# 当Web界面关闭时,停止监控进程
kill $MONITOR_PID

使用说明

  1. 将您的txt文件放入~/ai_knowledge_base/knowledge目录
  2. 运行启动脚本:bash ~/ai_knowledge_base/start.sh
  3. 在Web界面中提问,系统会自动从您的知识库中检索相关信息并生成回答
  4. 当您向知识库添加新的txt文件或修改现有文件时,系统会自动检测变化并更新向量存储

注意事项

  1. 首次处理大量文档可能需要一些时间
  2. 模型推理速度取决于您的硬件性能
  3. 为获得最佳性能,请确保您的MacBook连接电源并处于良好的散热条件下
  4. 如果遇到内存不足的问题,可以尝试使用更小的模型(如DeepSeek-R1:1.5b)

故障排除

  1. 如果Ollama服务无法启动,请检查安装是否正确
  2. 如果向量存储创建失败,请检查知识库目录中是否有有效的txt文件
  3. 如果模型响应速度过慢,可以考虑使用更小的模型或减少检索的文档数量
  4. 如果遇到Python依赖问题,请确保已安装所有必要的包