首页 / 文章

私有AI第二大脑:结合AnythingLLM、Ollama与Obsidian的本地RAG系统

私人第二大脑:通过 Proxmox 虚拟机上的 AnythingLLM 与嵌入模型,结合 Ollama RAG 技术,让本地的 Mistral 7B 模型能够实时查询 Obsidian 笔记,同时准确反映资源使用情况。

发布者:REACTAPP.TOP阅读约 8 分钟1758 词

来源: Giving My Local AI a Memory: Turning It Into a Private AI Second Brain with RAG and AnythingLLM

一位出色的失忆者

本地语言模型能够进行对话、解释概念并协助思考,而且所有操作都不会让任何数据流出设备。但它无法直接调出你保存的任何内容。

想象一下积累了一年的 Obsidian 笔记:午夜时保存的链接、未完成的想法、一篇关于搜索引擎的长文、招聘信息以及工作坊笔记。所有这些内容都存放在笔记本电脑的文件夹中,而对于那个花了整个周末才能在离线环境下运行的 AI 来说却是不可见的。

存储从来都不是问题,问题在于检索。在恰当的时刻找到正确的笔记,才能让一堆链接变成真正的知识,而非仅仅是一个整理得井井有条的杂物箱。因此,对于私人 AI 设置而言,接下来的自然步骤就是让它能够访问这些笔记。

RAG 是什么以及为何重要

大多数“在本地运行 AI”的指南都会跳过这部分内容,可能是因为嵌入向量听起来很枯燥。的确有点枯燥,但值得了解。

RAG 即检索增强生成。它能让语言模型利用你自己的文档,无需重新训练,也无需将数据上传到第三方服务器。

可以把它想象成雇佣一位速度极快的图书管理员,而不是要求 AI 记住所有书籍。图书管理员不会记住你的笔记内容,只知道当你提问时该去取哪本书。

其具体流程如下:

  1. 文档被分割成多个片段,并转化为嵌入向量,即意义的数值表示,这些向量会被存储在向量数据库中。
  2. 问题也会被转化为一个嵌入向量。
  3. 数据库会找出与问题意义最接近的那些片段。
  4. 这些片段会作为上下文传递给语言模型。
  • 该模型会依据您的真实文档来回答问题,而不仅仅依赖训练时所学的内容。
  • 工具:AnythingLLM

    AnytingLLM之所以适合这种构建方式,原因有以下几点:

    • 工作区能为不同场景(如笔记、研究资料或博客草稿)保留独立的知识库。
    • 它可直接读取Markdown格式,因此Obsidian笔记无需转换。
    • 它能直接与Ollama连接。
    • 它是自托管的,以Docker容器形式运行,无需账号也不依赖云端。
    • 它还配有桌面应用,方便那些没有家庭实验室的人使用。

    这并非唯一的选择,Open WebUI也内置了RAG功能。但AnythingLLM的工作区模式更契合“第二大脑”的概念,其界面也足够友好,适合推荐给非技术用户。

    构建环境

    起点

    该架构以如下基础环境为前提:

    • 一台纯硬件的 Proxmox VE 主机;
    • 一台运行 Ubuntu 24.04 的虚拟机,其中安装了带有 Mistral 7B 模型的 Ollama;
    • 使用 Open WebUI 作为聊天界面。

    在现有架构基础上还会再添加一台虚拟机。

    在 Proxmox 中创建新虚拟机

    为 AnythingLLM 创建一台全新的 Ubuntu 24.04 LTS 虚拟机。将其与 Ollama 虚拟机分开可以方便地创建快照,以及有意识地破坏系统后再恢复,而不会影响到实际的推理设置。主动破坏系统总比日后意外出问题要好。

    建议的配置参数:

    • 4 个虚拟 CPU
    • 8 GB 内存
    • 40 GB 磁盘空间,因为向量数据库需要占用大量空间

    这里没有什么难懂的。相关文档已经做了说明,再加上一些试错,尤其是对于那些已经搭建好 Ollama 虚拟机的人来说。真正的限制在于手头的硬件,而在这个限制条件下进行操作正是这项练习的目的。

    安装嵌入模型

    大多数指南都会跳过这一步,而这正是最让人困惑的地方。

    RAG 需要两种模型。一种是推理模型,Mistral 7B 已经具备;另一种是嵌入模型,用于将文本转换为向量。两者是不同的东西,但很少有指南会在一开始就说明这一点。

    在现有的 Ollama 虚拟机上,拉取嵌入模型:

    ollama pull nomic-embed-text
    

    nomic-embed-text 的体积约为270 MB,运行在CPU上速度很快,对英文文本的处理效果也不错,对于没有GPU的硬件来说是个不错的选择。

    另一个问题是:Ollama默认只监听本地主机。如果要让运行在另一台虚拟机上的AnythingLLM能够访问它,Ollama必须绑定到所有网络接口。首先需要编辑相关服务配置:

    sudo systemctl edit ollama
    

    然后添加此覆盖配置:

    [Service]
    Environment="OLLAMA_HOST=0.0.0.0"
    

    重新加载 systemd 并重启该服务:

    sudo systemctl daemon-reload
    sudo systemctl restart ollama
    

    接下来,在 Proxmox 防火墙中打开两个虚拟机之间的 11434 端口。情况又重演了:服务本身没有问题,模型也没有问题,出问题的是那种认为所有组件默认就能互相通信的假设。

    网络设置本可以更严格,而且最终也确实应该如此。这是典型的业余爱好者做法:先让系统运行起来,了解其架构,然后再拆解并重新正确构建。

    通过 Docker 使用 AnythingLLM

    在新的虚拟机上,首先安装 Docker:

    # Install Docker
    curl -fsSL <https://get.docker.com> | sh
    sudo usermod -aG docker $USER
    newgrp docker
    

    然后启动 AnythingLLM:

    # Run AnythingLLM
    docker run -d \
      -p 3001:3001 \
      --name anythingllm \
      -v ~/.anythingllm:/app/server/storage \
      mintplexlabs/anythingllm
    

    在浏览器中打开 http://:3001。首次运行时的配置为:

    • 大语言模型提供方:Ollama,地址为 http://:11434
    • 聊天模型:Mistral 7B
    • 嵌入模型提供方:Ollama,使用 nomic-embed-text
    • 向量数据库:LanceDB,内置无需额外配置

    向系统输入笔记

    创建一个名为“Second Brain”的工作空间,并将AnythingLLM指向Obsidian的存储库。其文档管理器支持上传文件夹,因此将笔记目录提供给它,让它自动处理所有内容。

    该系统可以处理 .md、.txt、.pdf、.docx 和 .csv 格式的文件。Obsidian的canvas文件实际上是以JSON格式存在的,因此不会导致错误,但也不会产生有用的信息。

    文本被输入后,工作区会显示分块数量及嵌入状态。每条笔记会被分割成约500个标记的重叠片段,这意味着一篇关于搜索引擎的较长文章会变成数十个可单独检索的片段。

    点击即用的时刻

    真正的考验在于普通请求,比如让助手查看名为“homelab improvements”的特定笔记。

    它会找到对应的文件,注明文件名,并附上时间戳引用原文的准确内容。引用信息还会包含源文档名称和发布日期。检索效果正如宣传的那样:文件能被准确命名并找到,没有编造的内容,也没有含糊的转述,仅有准确的信息及引用依据。

    有趣的是,当模型试图解释那张笔记时会发生什么。它将 Claude Code 描述成某种个人助手或服务。而仅依靠 CPU 在家庭实验室设备上离线运行的 Mistral 7B 则完全不知道 Claude Code 或 MCP 服务器是什么,它虽然能获取相关文字,却无法完全理解其含义。

    这才是更有价值的教训:信息检索与理解是两回事。RAG 虽能为模型提供合适的上下文,但模型对上下文的理解能力仍存在局限。对于规模较小的 7B 模型而言,且在没有网络连接的情况下,其能力上限会很快出现。

    出了什么问题以及它带来了什么启示

    在构建过程中,有一些假设并不成立。

    • RAG 并非魔法。它的效用完全取决于输入的内容,杂乱的笔记只会产生杂乱的结果——垃圾进,垃圾出。
  • 网络架构从项目初期就开始纳入规划。一旦服务分散在多台机器上,确保它们能够可靠地相互通信与配置每台机器同样重要。
  • 不要过早指责模型本身。有时候问题出在所提供的上下文中。良好的检索功能能让小型模型展现出惊人的实用性,但它无法为模型提供其原本不具备的知识。
  • 最终得到的成果及其成本

    一年间保存的链接、想法和未完成的思路都可以被检索出来,而且不仅是通过关键词,还能通过语义进行检索。询问某个概念,就能找到那些你早已忘记却与之相关的笔记,每条笔记都会标注出其来源文件。

    测试用的机器是一台配备i5处理器、32GB内存且没有GPU的EliteDesk,所有操作都在离线状态下进行。那次测试的测量结果如下:

    项目 结果
    端到端查询时间 1分35.9秒,其中AnythingLLM显示生成时间为41.9秒
    AnythingLLM空闲时的内存占用 在7.76GB的分配内存中约使用了440MB
    Ollama虚拟机的内存使用情况 在19GB的分配内存中使用了7.8GB
    Mistral运行时的内存占用 约6.5GB
    nomic-embed-text的内存占用 约360MB
    Open WebUI的内存占用 约1GB

    两次计时之间约54秒的差距原因不明,一种可能的原因是Ollama正在从硬盘重新加载模型。

    这些速度都算不上快,也本就不应如此。这只是一个刚开始搭建RAG系统的家庭实验室的第一天,还处于摸索阶段,不能作为与专业系统的对比基准。等到本地硬件每秒能处理更多token时,再回顾这些数据会很有意思。

    你将获得什么

    这个项目始于一个简单的目标——让本地人工智能能够查看你的笔记,同时还会教授更多相关知识。在这个过程中,你将了解RAG的运作原理、向量数据库的功能、决定检索效果的关键因素,以及为何合适的上下文比更大的模型更重要。

    更重要的是,最终得到的成果是你可以实际使用的。十二个月来积累的知识不再分散在各个文件夹中,而是变成了你可以直接查询的内容。所有这些都在房间角落里的一台二手笔记本电脑上运行,对于一台原本即将被淘汰的机器来说已经相当不错了。

    RAG确实有效。但能否真正理解则另当别论。

    延伸阅读

    AnythingLLM、Ollama、LanceDB和Obsidian的文档中详细介绍了相关内容。最初的RAG论文《Retrieval-Augmented Generation for Knowledge-Intensive NLP Tasks》阐述了其背后的理念。所有描述的功能均在改造后的硬件上运行,无需使用云服务,无需订阅,且数据不会离开网络。

    相关阅读

  • 利用四台MCP服务器在LM Studio中构建本地研究代理 — 将文件系统、GitHub、SearXNG和Camofox的MCP服务器整合到同一个LM Studio聊天界面中,简化工具架构,添加研究计划提示,并通过演示验证其功能。
  • 一个字符的承载令牌如何攻破LiteLLM的MCP网关 — 蜜罐系统捕获了攻击者利用LiteLLM的MCP认证绕过机制及代码执行漏洞进行的攻击行为。本文介绍了攻击流程以及强化防护的六步检查清单。