通用聊天机器人并不了解你的产品、价格、流程和内部文档,而把这些资料粘贴到公共 AI 服务中往往又不可接受。借助检索增强生成(RAG),助手会先在你自己的文档中检索,再根据检索到的内容作答,并附上引用来源。本文在你自己的服务器上部署 AnythingLLM,并使用由 Ollama 提供的本地模型,内容包括:安装、接入语言模型和向量嵌入模型、将文档上传到工作区、配置仅基于文档作答、添加用户以及通过 HTTPS 发布。如需规划更大规模的部署(地区、向量数据库、数据保护),请参见在独立服务器上搭建私有 AI 客服知识库。
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;回答问题时使用的是对话模型。
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 反向代理访问。
将 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;
}
}
打开 https://kb.example.com 并完成初始设置,以下各项之后都可以在 Settings(设置)中修改:
http://host.docker.internal:11434,对话模型选择 qwen2.5:7b。nomic-embed-text(或使用 AnythingLLM 内置的嵌入器)。上传任何内容之前,先在安全设置中启用多用户模式,并设置管理员密码。然后为每位同事创建账号并分配 Default 角色,这样他们可以在你分配的工作区中对话,但无法修改设置,也看不到其他工作区。
工作区是一个独立的知识库,拥有自己的文档和设置,例如“产品目录”“客服流程”或“人事制度”。
干净的文本型文档效果最好。扫描版 PDF 需要先做 OCR;标题清晰的长文档,比一个包罗万象的超大文件更容易检索。
在工作区设置中:
每条回答都会显示引用来源,点击即可查看使用了哪个文档片段。
文档有更新时,先从工作区中移除旧版本,再上传新版本,以免引用过时的价格或流程。请定期备份 /opt/anythingllm,其中包含文档、向量、用户和聊天记录。AnythingLLM 还提供 API 和可嵌入的聊天小部件,方便你以后在自己的网站或应用中调用某个工作区。
将工作区切换为 Query 模式,收紧系统提示词,并检查引用来源。如果始终检索不到正确的片段,请把文档拆分成多个标题清晰的小文件,或尝试更大的对话模型。
大部分时间花在对话模型用 CPU 生成文本上。快速查询可使用较小的模型,减少每次回答使用的片段数量,并让模型常驻内存(参见 Ollama 教程中的性能优化建议)。
可以,AnythingLLM 支持多种模型服务商。但请注意,这样一来你的文档和问题都会发送给该服务商,并且只能使用其服务条款所允许的服务商和地区。对于机密资料,本文的本地部署方案可以让所有数据都留在你的服务器上。
如果按以上步骤操作后问题仍未解决,请提交工单联系 IMIDC 7×24 技术支持,并附上服务器 IP、系统版本、CPU 和内存配置、docker logs anythingllm 的输出以及完整报错信息,方便工程师快速定位。