马上注册,结交更多好友,享用更多功能,让你轻松玩转小K网。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
[保姆级教程] 0基础在Windows本地搭建“DeepSeek”私人知识库 (附源码)
在这个AI爆发的时代,你是否想过把电脑里的几百份PDF、Word文档变成一个可以随时提问的“超级大脑”?而且完全免费、不用联网、数据不出本地!
今天手把手教大家利用 Ollama + DeepSeek + Python 搭建一个本地 RAG(检索增强生成)系统。不用怕代码,照着做就行!
🛠️ 第一步:准备环境 (Windows篇)
我们需要两个核心工具:Ollama(运行AI的大脑)和 Python(处理文档的管家)。
1. 安装 Ollama
- 下载:访问 Ollama官网 下载 Windows 版本并安装。
- 验证:安装完成后,打开电脑的“命令提示符”(按 Win+R,输入 cmd,回车)。
- 拉取模型:在黑框里输入以下命令并回车(这一步需要联网下载模型,约 9GB):
复制代码 💡 注意:如果不差显存(12G以上)用 14b 效果最好;如果电脑配置一般(8G/16G内存),建议把命令换成 ollama pull deepseek-r1:7b,速度会快很多。
2. 安装 Python
- 下载:访问 Python官网 下载最新的 Python 3.10 或 3.11 版本。
- 关键一步:安装界面最下方一定要勾选 "Add Python to PATH" (添加到环境变量),然后点 Install Now。
📂 第二步:搭建项目文件夹 (把资料喂给AI)
这一步最关键!我们要把资料整理好,放在项目文件夹里。
DeepSeek 不挑食,你可以把文件直接散乱地堆在根目录,也可以建各种子文件夹分类存放,程序会自动把它们全部扫描出来。
1. 推荐的目录结构
在桌面上新建一个文件夹叫 MyLocalAI,建议参照下面的结构存放文件:
- MyLocalAI/ (你的项目主文件夹)
- │
- ├── build_kb.py <-- (等下要创建的代码文件1,负责吃书)
- ├── chat_rag.py <-- (等下要创建的代码文件2,负责聊天)
- │
- └── 📂 知识库 (你可以随便起名,把所有资料丢这里)
- │
- ├── 📂 2024工作总结/
- │ ├── 年终汇报.pptx
- │ └── 部门会议纪要.docx
- │
- ├── 📂 行业研报/
- │ ├── AI发展趋势.pdf
- │ └── 竞品分析.pdf
- │
- └── 📂 财务数据/
- └── Q4预算表.xlsx
复制代码 2. 支持的文件类型
你可以随意往里面丢以下格式的文件:
- PDF (.pdf):各种论文、扫描件(必须是文字版,纯图片PDF读不了)。
- Word (.docx):工作文档、合同、论文。
- PPT (.pptx):汇报胶片、课件。
- Excel (.xlsx):简单的表格数据(程序会转成文本读取)。
💻 第三步:安装依赖库
我们需要安装一些 Python 插件来处理文件。
在 MyLocalAI 文件夹的空白处,按住 Shift 键 + 点击鼠标右键,选择 “在此处打开 Powershell 窗口” (或者CMD)。
复制下面这行命令粘贴进去,回车:
- pip install numpy faiss-cpu pandas pypdf python-docx python-pptx fastembed tqdm ollama openpyxl -i https://pypi.tuna.tsinghua.edu.cn/simple
复制代码 (这里使用了清华镜像源,下载速度飞快)
📝 第四步:创建代码文件 (直接复制)
我们需要在文件夹里创建两个 Python 文件。
方法:新建一个文本文件 -> 粘贴代码 -> 保存 -> 重命名为 xxx.py。
文件 1:build_kb.py (构建知识库)
这个脚本负责扫描刚才那些文件夹,把文档“嚼碎”并存成AI能读懂的向量格式。
- import os
- import gc
- import shutil
- import logging
- import numpy as np
- import faiss
- import pandas as pd
- from pypdf import PdfReader
- from docx import Document
- from pptx import Presentation
- from fastembed import TextEmbedding
- from tqdm import tqdm
-
- # =========================
- # ⚙️ 配置区域
- # =========================
- # 设置国内镜像,解决下载慢的问题
- os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
- logging.getLogger("pypdf").setLevel(logging.ERROR)
-
- BASE_DIR = "." # 扫描当前目录
- INDEX_FILE = "kb.index"
- CHUNKS_FILE = "kb_chunks.npy"
- BATCH_SIZE = 256
-
- # =========================
- # 📄 文档加载器
- # =========================
- def load_pdf(path):
- try:
- reader = PdfReader(path)
- return "\n".join([page.extract_text().strip() for page in reader.pages if page.extract_text()])
- except: return ""
-
- def load_docx(path):
- try:
- doc = Document(path)
- return "\n".join([p.text.strip() for p in doc.paragraphs if p.text.strip()])
- except: return ""
-
- def load_pptx(path):
- try:
- prs = Presentation(path)
- out = []
- for slide in prs.slides:
- for shape in slide.shapes:
- if hasattr(shape, "text_frame"):
- for p in shape.text_frame.paragraphs:
- if p.text.strip(): out.append(p.text.strip())
- return "\n".join(out)
- except: return ""
-
- def load_xlsx(path):
- try:
- return pd.read_excel(path).to_markdown(index=False)
- except: return ""
-
- def split_text(text, size=500, overlap=50):
- res = []
- for i in range(0, len(text), size - overlap):
- chunk = text[i:i + size].strip()
- if len(chunk) > 20: res.append(chunk)
- return res
-
- def scan_files():
- print("📂 正在扫描当前目录及子文件夹下的文档...")
- chunks = []
- supported_ext = ['.pdf', '.docx', '.pptx', '.xlsx']
-
- files = []
- for root, _, filenames in os.walk(BASE_DIR):
- for f in filenames:
- if any(f.lower().endswith(ext) for ext in supported_ext):
- files.append(os.path.join(root, f))
-
- print(f"📄 找到 {len(files)} 个文件,开始解析...")
-
- for file_path in tqdm(files, desc="解析文件"):
- content = ""
- ext = os.path.splitext(file_path)[1].lower()
- if ext == '.pdf': content = load_pdf(file_path)
- elif ext == '.docx': content = load_docx(file_path)
- elif ext == '.pptx': content = load_pptx(file_path)
- elif ext == '.xlsx': content = load_xlsx(file_path)
-
- if content:
- # 在内容前加上文件名,方便AI知道出处
- file_name = os.path.basename(file_path)
- chunk_list = split_text(content)
- chunks.extend([f"【来源:{file_name}】\n{c}" for c in chunk_list])
-
- return chunks
-
- # =========================
- # 🚀 主程序
- # =========================
- def main():
- # 1. 扫描文件并制作切片
- # 如果想强制重新扫描,删除目录下的 kb_chunks.npy 即可
- if os.path.exists(CHUNKS_FILE):
- print("✅ 检测到旧缓存,直接加载 (如需更新请删除 kb_chunks.npy)...")
- chunks = np.load(CHUNKS_FILE, allow_pickle=True).tolist()
- else:
- chunks = scan_files()
- if not chunks:
- print("❌ 没有找到有效内容,请检查文件夹里有没有文档!")
- return
- np.save(CHUNKS_FILE, np.array(chunks, dtype=object))
-
- print(f"📦 共生成 {len(chunks)} 个文本块,准备向量化...")
-
- # 2. 初始化模型
- model_name = "BAAI/bge-small-zh-v1.5"
- try:
- embedder = TextEmbedding(model_name=model_name)
- except:
- print("⚠️ 模型加载受阻,尝试自动修复...")
- cache_dir = os.path.join(os.getcwd(), ".fastembed")
- if os.path.exists(cache_dir): shutil.rmtree(cache_dir)
- embedder = TextEmbedding(model_name=model_name)
-
- # 3. 向量化并建立索引
- print("🚀 正在将文本转化为向量 (如果是第一次运行,会自动下载模型,请耐心等待)...")
- embeddings = list(embedder.embed(chunks))
-
- embeddings_np = np.array([list(e) for e in embeddings]).astype('float32')
-
- dim = embeddings_np.shape[1]
- index = faiss.IndexFlatIP(dim)
- index.add(embeddings_np)
-
- faiss.write_index(index, INDEX_FILE)
- print(f"🎉 知识库构建完成!索引文件: {INDEX_FILE}")
-
- if __name__ == "__main__":
- main()
复制代码 文件 2:chat_rag.py (开始对话)
这个脚本负责连接 Ollama 和刚才建好的知识库。
- import os
- import faiss
- import numpy as np
- import ollama
- from fastembed import TextEmbedding
-
- # =========================
- # ⚙️ 配置区域
- # =========================
- os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
- INDEX_FILE = "kb.index"
- CHUNKS_FILE = "kb_chunks.npy"
- # ⚠️ 如果你安装的是 7b 模型,请把下面这行改成 "deepseek-r1:7b"
- OLLAMA_MODEL = "deepseek-r1:14b"
- EMBED_MODEL = "BAAI/bge-small-zh-v1.5"
-
- def main():
- if not os.path.exists(INDEX_FILE):
- print("❌ 没找到知识库!请先运行 build_kb.py")
- return
-
- print("⏳ 正在加载大脑...")
- index = faiss.read_index(INDEX_FILE)
- chunks = np.load(CHUNKS_FILE, allow_pickle=True).tolist()
- embedder = TextEmbedding(model_name=EMBED_MODEL)
-
- print("\n" + "="*40)
- print(f"🤖 本地AI知识库助手 ({OLLAMA_MODEL}) 已启动")
- print("💡 输入 'exit' 退出")
- print("="*40)
-
- while True:
- query = input("\n🙋 你的问题: ").strip()
- if query.lower() in ['exit', 'quit']: break
- if not query: continue
-
- # 1. 检索
- print("🔍 正在翻阅资料...", end="\r")
- query_vec = list(embedder.embed([query]))[0]
- D, I = index.search(np.array([query_vec], dtype="float32"), k=4)
-
- context = []
- for idx in I[0]:
- if idx >= 0: context.append(chunks[idx])
-
- # 2. 生成
- prompt = f"""
- 基于以下资料回答问题。如果资料里没有提到,就说不知道,不要瞎编。
-
- 【资料】:
- {"\n---".join(context)}
-
- 【问题】:{query}
- """
-
- print("\n🤖 DeepSeek 回答:")
- try:
- stream = ollama.chat(model=OLLAMA_MODEL, messages=[{'role': 'user', 'content': prompt}], stream=True)
- for chunk in stream:
- print(chunk['message']['content'], end='', flush=True)
- print("\n")
- except Exception as e:
- print(f"❌ 也就是这里出错了: {e}")
- print("请检查 Ollama 是否已在后台运行!")
-
- if __name__ == "__main__":
- main()
复制代码 ▶️ 第五步:运行起来!
1. 构建知识库
在命令窗口输入:
复制代码
- 第一次运行会下载一个约 100MB 的向量模型(已配置国内镜像,很快)。
- 你会看到进度条在扫描你的文档。
- 显示 🎉 知识库构建完成! 就成功了。
2. 开始聊天
在命令窗口输入:
复制代码
- 程序启动后,输入你的问题,比如:“总结一下Q4预算表的内容”、“2024年工作汇报里提到了什么”。
- 你会发现 AI 回答的内容完全是基于你文件夹里的文件!
❓ 常见问题 (FAQ)
Q: 运行 build_kb.py 报错说 SSL 连接错误?
A: 这是网络问题。代码里已经加了 HF_ENDPOINT 镜像,如果还不行,尝试关掉你的科学上网工具,或者切换手机热点试试。
Q: 聊天时电脑非常卡,出字很慢?
A: 你的模型可能太大了。
去 CMD 运行 ollama rm deepseek-r1:14b 删除大模型。
运行 ollama pull deepseek-r1:1.5b (这个超快,渣机也能跑)。
记得修改 chat_rag.py 里的配置代码。
Q: 我往文件夹里加了新文档,AI 怎么不知道?
A: 只要删掉文件夹里的 kb_chunks.npy 和 kb.index 这两个旧文件,重新运行 python build_kb.py 即可重建索引。
教程结束,祝大家搭建愉快!
|