Linux 服务器

AnythingLLM + Ollama 搭建私有 AI 知识库:在自有服务器部署 RAG 文档问答机器人

8 个步骤 9 分钟阅读 33 次阅读 0
本文目录

通用聊天机器人并不了解你的产品、价格、流程和内部文档,而把这些资料粘贴到公共 AI 服务中往往又不可接受。借助检索增强生成(RAG),助手会先在你自己的文档中检索,再根据检索到的内容作答,并附上引用来源。本文在你自己的服务器上部署 AnythingLLM,并使用由 Ollama 提供的本地模型,内容包括:安装、接入语言模型和向量嵌入模型、将文档上传到工作区、配置仅基于文档作答、添加用户以及通过 HTTPS 发布。如需规划更大规模的部署(地区、向量数据库、数据保护),请参见在独立服务器上搭建私有 AI 客服知识库。

本文建立在使用 Ollama 运行本地大模型教程的基础上。请先完成该教程,包括其中的防火墙规则:Ollama 的 API 没有任何身份验证,11434 端口绝不能暴露在公网上。

步骤 1:准备模型

RAG 需要用到两个模型:向量嵌入模型(embedding model)负责把文档片段和问题转换成向量以便检索,对话模型(chat model)负责生成回答。两者都在 Ollama 中运行。

ollama pull nomic-embed-text      # embedding model (small and fast on CPU)
ollama pull qwen2.5:7b            # chat model; good with Chinese and English
ollama list

# AnythingLLM runs in a container, so Ollama must accept connections from Docker
# (OLLAMA_HOST=0.0.0.0 plus the firewall rules from the Ollama guide). Check:
curl -s http://172.17.0.1:11434/api/tags | head -c 300; echo

对于小团队,一台 8 核及以上、16 GB 内存的服务器即可流畅运行这套组合。上传大量文件时,文档向量化会占用一段时间的 CPU;回答问题时使用的是对话模型。

步骤 2:启动 AnythingLLM

AnythingLLM 运行在 Docker 中(参见我们的 Docker 安装教程)。

export STORAGE_LOCATION=/opt/anythingllm
mkdir -p $STORAGE_LOCATION && touch "$STORAGE_LOCATION/.env"
chown -R 1000:1000 $STORAGE_LOCATION      # the container runs as user ID 1000

docker run -d --name anythingllm --restart always \
  -p 127.0.0.1:3002:3001 \
  --cap-add SYS_ADMIN \
  --add-host=host.docker.internal:host-gateway \
  -v ${STORAGE_LOCATION}:/app/server/storage \
  -v ${STORAGE_LOCATION}/.env:/app/server/.env \
  -e STORAGE_DIR="/app/server/storage" \
  mintplexlabs/anythingllm

docker logs -f anythingllm      # wait until the server reports it is listening

Web 界面在容器内监听 3001 端口,并映射到宿主机的 127.0.0.1:3002,因此只能通过步骤 3 中的 HTTPS 反向代理访问。

步骤 3:通过 HTTPS 发布

将 kb.example.com 之类的子域名解析到服务器,申请证书(参见使用 Certbot 或 acme.sh 申请免费 SSL 证书),然后反向代理到容器:

server {
    listen 443 ssl;
    http2 on;
    server_name kb.example.com;

    ssl_certificate     /etc/letsencrypt/live/kb.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/kb.example.com/privkey.pem;
    client_max_body_size 100m;          # document uploads

    location / {
        proxy_pass         http://127.0.0.1:3002;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection "upgrade";
        proxy_set_header   Host $host;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
        proxy_read_timeout 600s;
    }
}

步骤 4:接入模型

打开 https://kb.example.com 并完成初始设置,以下各项之后都可以在 Settings(设置)中修改:

  • LLM 提供方:选择 Ollama,Base URL 填写 http://host.docker.internal:11434,对话模型选择 qwen2.5:7b。
  • 向量嵌入提供方:选择 Ollama 并使用 nomic-embed-text(或使用 AnythingLLM 内置的嵌入器)。
  • 向量数据库:使用内置的 LanceDB,无需额外配置。

步骤 5:启用多用户模式保障安全

上传任何内容之前,先在安全设置中启用多用户模式,并设置管理员密码。然后为每位同事创建账号并分配 Default 角色,这样他们可以在你分配的工作区中对话,但无法修改设置,也看不到其他工作区。

步骤 6:创建工作区并上传文档

工作区是一个独立的知识库,拥有自己的文档和设置,例如“产品目录”“客服流程”或“人事制度”。

  1. 创建工作区并打开它的上传对话框。
  2. 上传 PDF、Word、纯文本、Markdown 或 CSV 文件,或者通过 URL 抓取网页。
  3. 将上传的文件移入工作区,然后点击 Save and Embed(保存并向量化)。AnythingLLM 会把文件切分成片段并存储其向量。

干净的文本型文档效果最好。扫描版 PDF 需要先做 OCR;标题清晰的长文档,比一个包罗万象的超大文件更容易检索。

步骤 7:让回答限定在文档范围内

在工作区设置中:

  • 将对话模式设为 Query(查询模式):助手只有在找到相关片段时才会作答,否则会说明没有相关信息,而不是凭空猜测。
  • 编写系统提示词,例如:“你是 ACME 的内部助手。只根据提供的文档回答,注明出处,并使用提问所用的语言回复。”
  • 如果回答遗漏了相关事实或掺入了无关内容,可调整每次回答使用的片段数量和相似度阈值。

每条回答都会显示引用来源,点击即可查看使用了哪个文档片段。

步骤 8:维护知识库

文档有更新时,先从工作区中移除旧版本,再上传新版本,以免引用过时的价格或流程。请定期备份 /opt/anythingllm,其中包含文档、向量、用户和聊天记录。AnythingLLM 还提供 API 和可嵌入的聊天小部件,方便你以后在自己的网站或应用中调用某个工作区。

常见问题

助手给出了文档中没有的内容

将工作区切换为 Query 模式,收紧系统提示词,并检查引用来源。如果始终检索不到正确的片段,请把文档拆分成多个标题清晰的小文件,或尝试更大的对话模型。

回答速度慢

大部分时间花在对话模型用 CPU 生成文本上。快速查询可使用较小的模型,减少每次回答使用的片段数量,并让模型常驻内存(参见 Ollama 教程中的性能优化建议)。

可以用云端 AI API 代替 Ollama 吗?

可以,AnythingLLM 支持多种模型服务商。但请注意,这样一来你的文档和问题都会发送给该服务商,并且只能使用其服务条款所允许的服务商和地区。对于机密资料,本文的本地部署方案可以让所有数据都留在你的服务器上。

如果按以上步骤操作后问题仍未解决,请提交工单联系 IMIDC 7×24 技术支持,并附上服务器 IP、系统版本、CPU 和内存配置、docker logs anythingllm 的输出以及完整报错信息,方便工程师快速定位。

这篇文章有帮助吗?

相关教程