返回列表 发布新帖

0基础在Windows本地搭建“DeepSeek”私人知识库 (附源码)

594 0
小K网牛逼 发表于 3 小时前 | 查看全部 阅读模式 <

马上注册,结交更多好友,享用更多功能,让你轻松玩转小K网。

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

×
[保姆级教程] 0基础在Windows本地搭建“DeepSeek私人知识库 (附源码)
在这个AI爆发的时代,你是否想过把电脑里的几百份PDF、Word文档变成一个可以随时提问的“超级大脑”?而且完全免费、不用联网、数据不出本地!

今天手把手教大家利用 Ollama + DeepSeek + Python 搭建一个本地 RAG(检索增强生成)系统。不用怕代码,照着做就行!

🛠️ 第一步:准备环境 (Windows篇)
我们需要两个核心工具:Ollama(运行AI的大脑)和 Python(处理文档的管家)。
1. 安装 Ollama
  • 下载:访问 Ollama官网 下载 Windows 版本并安装。
  • 验证:安装完成后,打开电脑的“命令提示符”(按 Win+R,输入 cmd,回车)。
  • 拉取模型:在黑框里输入以下命令并回车(这一步需要联网下载模型,约 9GB):
  1. ollama pull DeepSeek-r1:14b
复制代码
💡 注意:如果不差显存(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,建议参照下面的结构存放文件:
  1. MyLocalAI/  (你的项目主文件夹)
  2. ├── build_kb.py          <-- (等下要创建的代码文件1,负责吃书)
  3. ├── chat_rag.py          <-- (等下要创建的代码文件2,负责聊天)
  4. └── 📂 知识库 (你可以随便起名,把所有资料丢这里)
  5.     │
  6.     ├── 📂 2024工作总结/
  7.     │   ├── 年终汇报.pptx
  8.     │   └── 部门会议纪要.docx
  9.     │
  10.     ├── 📂 行业研报/
  11.     │   ├── AI发展趋势.pdf
  12.     │   └── 竞品分析.pdf
  13.     │
  14.     └── 📂 财务数据/
  15.         └── Q4预算表.xlsx
复制代码
2. 支持的文件类型
你可以随意往里面丢以下格式的文件:
  • PDF (.pdf):各种论文、扫描件(必须是文字版,纯图片PDF读不了)。
  • Word (.docx):工作文档、合同、论文。
  • PPT (.pptx):汇报胶片、课件。
  • Excel (.xlsx):简单的表格数据(程序会转成文本读取)。

💻 第三步:安装依赖库
我们需要安装一些 Python 插件来处理文件。
在 MyLocalAI 文件夹的空白处,按住 Shift 键 + 点击鼠标右键,选择 “在此处打开 Powershell 窗口” (或者CMD)。

复制下面这行命令粘贴进去,回车:
  1. 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能读懂的向量格式。
  1. import os
  2. import gc
  3. import shutil
  4. import logging
  5. import numpy as np
  6. import faiss
  7. import pandas as pd
  8. from pypdf import PdfReader
  9. from docx import Document
  10. from pptx import Presentation
  11. from fastembed import TextEmbedding
  12. from tqdm import tqdm
  13. # =========================
  14. # ⚙️ 配置区域
  15. # =========================
  16. # 设置国内镜像,解决下载慢的问题
  17. os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
  18. logging.getLogger("pypdf").setLevel(logging.ERROR)
  19. BASE_DIR = "." # 扫描当前目录
  20. INDEX_FILE = "kb.index"
  21. CHUNKS_FILE = "kb_chunks.npy"
  22. BATCH_SIZE = 256
  23. # =========================
  24. # 📄 文档加载器
  25. # =========================
  26. def load_pdf(path):
  27.     try:
  28.         reader = PdfReader(path)
  29.         return "\n".join([page.extract_text().strip() for page in reader.pages if page.extract_text()])
  30.     except: return ""
  31. def load_docx(path):
  32.     try:
  33.         doc = Document(path)
  34.         return "\n".join([p.text.strip() for p in doc.paragraphs if p.text.strip()])
  35.     except: return ""
  36. def load_pptx(path):
  37.     try:
  38.         prs = Presentation(path)
  39.         out = []
  40.         for slide in prs.slides:
  41.             for shape in slide.shapes:
  42.                 if hasattr(shape, "text_frame"):
  43.                     for p in shape.text_frame.paragraphs:
  44.                         if p.text.strip(): out.append(p.text.strip())
  45.         return "\n".join(out)
  46.     except: return ""
  47. def load_xlsx(path):
  48.     try:
  49.         return pd.read_excel(path).to_markdown(index=False)
  50.     except: return ""
  51. def split_text(text, size=500, overlap=50):
  52.     res = []
  53.     for i in range(0, len(text), size - overlap):
  54.         chunk = text[i:i + size].strip()
  55.         if len(chunk) > 20: res.append(chunk)
  56.     return res
  57. def scan_files():
  58.     print("📂 正在扫描当前目录及子文件夹下的文档...")
  59.     chunks = []
  60.     supported_ext = ['.pdf', '.docx', '.pptx', '.xlsx']
  61.     files = []
  62.     for root, _, filenames in os.walk(BASE_DIR):
  63.         for f in filenames:
  64.             if any(f.lower().endswith(ext) for ext in supported_ext):
  65.                 files.append(os.path.join(root, f))
  66.     print(f"📄 找到 {len(files)} 个文件,开始解析...")
  67.     for file_path in tqdm(files, desc="解析文件"):
  68.         content = ""
  69.         ext = os.path.splitext(file_path)[1].lower()
  70.         if ext == '.pdf': content = load_pdf(file_path)
  71.         elif ext == '.docx': content = load_docx(file_path)
  72.         elif ext == '.pptx': content = load_pptx(file_path)
  73.         elif ext == '.xlsx': content = load_xlsx(file_path)
  74.         if content:
  75.             # 在内容前加上文件名,方便AI知道出处
  76.             file_name = os.path.basename(file_path)
  77.             chunk_list = split_text(content)
  78.             chunks.extend([f"【来源:{file_name}】\n{c}" for c in chunk_list])
  79.     return chunks
  80. # =========================
  81. # 🚀 主程序
  82. # =========================
  83. def main():
  84.     # 1. 扫描文件并制作切片
  85.     # 如果想强制重新扫描,删除目录下的 kb_chunks.npy 即可
  86.     if os.path.exists(CHUNKS_FILE):
  87.         print("✅ 检测到旧缓存,直接加载 (如需更新请删除 kb_chunks.npy)...")
  88.         chunks = np.load(CHUNKS_FILE, allow_pickle=True).tolist()
  89.     else:
  90.         chunks = scan_files()
  91.         if not chunks:
  92.             print("❌ 没有找到有效内容,请检查文件夹里有没有文档!")
  93.             return
  94.         np.save(CHUNKS_FILE, np.array(chunks, dtype=object))
  95.     print(f"📦 共生成 {len(chunks)} 个文本块,准备向量化...")
  96.     # 2. 初始化模型
  97.     model_name = "BAAI/bge-small-zh-v1.5"
  98.     try:
  99.         embedder = TextEmbedding(model_name=model_name)
  100.     except:
  101.         print("⚠️ 模型加载受阻,尝试自动修复...")
  102.         cache_dir = os.path.join(os.getcwd(), ".fastembed")
  103.         if os.path.exists(cache_dir): shutil.rmtree(cache_dir)
  104.         embedder = TextEmbedding(model_name=model_name)
  105.     # 3. 向量化并建立索引
  106.     print("🚀 正在将文本转化为向量 (如果是第一次运行,会自动下载模型,请耐心等待)...")
  107.     embeddings = list(embedder.embed(chunks))
  108.     embeddings_np = np.array([list(e) for e in embeddings]).astype('float32')
  109.     dim = embeddings_np.shape[1]
  110.     index = faiss.IndexFlatIP(dim)
  111.     index.add(embeddings_np)
  112.     faiss.write_index(index, INDEX_FILE)
  113.     print(f"🎉 知识库构建完成!索引文件: {INDEX_FILE}")
  114. if __name__ == "__main__":
  115.     main()
复制代码
文件 2:chat_rag.py (开始对话)
这个脚本负责连接 Ollama 和刚才建好的知识库。
  1. import os
  2. import faiss
  3. import numpy as np
  4. import ollama
  5. from fastembed import TextEmbedding
  6. # =========================
  7. # ⚙️ 配置区域
  8. # =========================
  9. os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"
  10. INDEX_FILE = "kb.index"
  11. CHUNKS_FILE = "kb_chunks.npy"
  12. # ⚠️ 如果你安装的是 7b 模型,请把下面这行改成 "deepseek-r1:7b"
  13. OLLAMA_MODEL = "deepseek-r1:14b"
  14. EMBED_MODEL = "BAAI/bge-small-zh-v1.5"
  15. def main():
  16.     if not os.path.exists(INDEX_FILE):
  17.         print("❌ 没找到知识库!请先运行 build_kb.py")
  18.         return
  19.     print("⏳ 正在加载大脑...")
  20.     index = faiss.read_index(INDEX_FILE)
  21.     chunks = np.load(CHUNKS_FILE, allow_pickle=True).tolist()
  22.     embedder = TextEmbedding(model_name=EMBED_MODEL)
  23.     print("\n" + "="*40)
  24.     print(f"🤖 本地AI知识库助手 ({OLLAMA_MODEL}) 已启动")
  25.     print("💡 输入 'exit' 退出")
  26.     print("="*40)
  27.     while True:
  28.         query = input("\n🙋 你的问题: ").strip()
  29.         if query.lower() in ['exit', 'quit']: break
  30.         if not query: continue
  31.         # 1. 检索
  32.         print("🔍 正在翻阅资料...", end="\r")
  33.         query_vec = list(embedder.embed([query]))[0]
  34.         D, I = index.search(np.array([query_vec], dtype="float32"), k=4)
  35.         context = []
  36.         for idx in I[0]:
  37.             if idx >= 0: context.append(chunks[idx])
  38.         # 2. 生成
  39.         prompt = f"""
  40.         基于以下资料回答问题。如果资料里没有提到,就说不知道,不要瞎编。
  41.         【资料】:
  42.         {"\n---".join(context)}
  43.         【问题】:{query}
  44.         """
  45.         print("\n🤖 DeepSeek 回答:")
  46.         try:
  47.             stream = ollama.chat(model=OLLAMA_MODEL, messages=[{'role': 'user', 'content': prompt}], stream=True)
  48.             for chunk in stream:
  49.                 print(chunk['message']['content'], end='', flush=True)
  50.             print("\n")
  51.         except Exception as e:
  52.             print(f"❌ 也就是这里出错了: {e}")
  53.             print("请检查 Ollama 是否已在后台运行!")
  54. if __name__ == "__main__":
  55.     main()
复制代码
▶️ 第五步:运行起来!
1. 构建知识库
在命令窗口输入:
  1. python build_kb.py
复制代码
  • 第一次运行会下载一个约 100MB 的向量模型(已配置国内镜像,很快)。
  • 你会看到进度条在扫描你的文档。
  • 显示 🎉 知识库构建完成! 就成功了。

2. 开始聊天
在命令窗口输入:
  1. python chat_rag.py
复制代码
  • 程序启动后,输入你的问题,比如:“总结一下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.npykb.index 这两个旧文件,重新运行 python build_kb.py 即可重建索引。

教程结束,祝大家搭建愉快!

回复

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

您需要 登录 后才可以回复,轻松玩转社区,没有帐号?立即注册
快速回复
关灯 在本版发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表