1. 背景与整体架构
本文记录我在一台阿里云入门级服务器上搭建本地 AI 知识库的完整过程。核心需求是:把内部文档(Markdown、TXT、PDF 等)变成可以提问的知识库,并且数据和推理都留在本地服务器上,不依赖外部 API。
服务器配置如下:
- CPU:2 核(vCPU)
- 内存:2 GiB
- 操作系统:Alibaba Cloud Linux 3.2104 LTS 64 位
- 无独立 GPU
整体思路很清晰:本地大模型 + 嵌入模型 + 向量检索 + 知识库前端。
| 组件 | 作用 |
|---|---|
| Ollama | 运行本地语言模型和嵌入模型 |
| 对话模型 | 负责回答问题(如 Qwen2.5-0.5B) |
| 嵌入模型 | 把文档向量化,用于检索(如 nomic-embed-text) |
| 知识库前端 | 上传文档、切片、向量入库、对话交互 |
方案选型
常见方案有三种,对比如下:
| 方案 | 难度 | 界面 | 自定义程度 | 推荐场景 |
|---|---|---|---|---|
| Ollama + AnythingLLM | 低 | 图形化 | 中 | 个人/小团队快速搭建 |
| Ollama + Open WebUI | 中 | 图形化 | 中高 | 需要对话 + 知识库结合 |
| Python 自建 | 高 | 无 | 完全可控 | 开发集成 |
本文最终采用的是「Ollama + Open WebUI」,原因和网页端配置会在第 7 节详细说明。
2. 服务器配置评估:2 核 2G 能跑什么
2 核 2G、无 GPU 意味着只能跑小参数量模型,且必须选择量化版本。FP16 全精度模型在这个配置下基本跑不动。
推荐可用的最小模型:
| 模型 | 参数量 | 量化版本 | 内存占用 | 备注 |
|---|---|---|---|---|
| Qwen2.5-0.5B | 0.5B | Q4_K_M | ~400MB | 阿里出品,中文友好,推荐 |
| TinyLlama-1.1B | 1.1B | Q4_K_M | ~800MB | 最小可用,效果一般 |
| Llama 3.2-1B | 1B | Q4_K_M | ~700MB | Meta 小模型,英文更好 |
| Gemma-2B | 2B | Q4_K_M | ~1.3GB | Google 出品 |
| Phi-2 | 2.7B | Q4_K_M | ~1.5GB | 小模型里效果较好 |
关键结论:
- 必须选
Q4_K_M或Q4_0量化版本,FP16 跑不动; - 纯 CPU 推理,一个问题可能要 10~30 秒,CPU 会跑满,属于预期现象;
- 2G 内存只适合单用户、纯文本知识库,不建议处理扫描件或图片 PDF;
- 内存非常紧张,强烈建议加 swap 空间。
3. 安装 Ollama
Ollama 负责在本地运行模型,官方提供一键安装脚本:
bash
curl -fsSL https://ollama.com/install.sh | sh
安装完成后确认服务状态:
bash
systemctl status ollama
ss -tlnp | grep 11434
Ollama 默认监听 11434 端口。需要注意:如果按官方文档直接执行 ollama pull qwen2.5:0.5b,在国内服务器上大概率会卡在 TLS 握手超时,这是本文后续要重点解决的坑。
4. 模型下载:从 TLS 超时到国内镜像
4.1 问题现象
执行 ollama pull 时,报 TLS 握手超时:
text
Error: pulling manifest: Get "https://registry.ollama.ai/...": TLS handshake timeout
原因很直接:Ollama 官方仓库 registry.ollama.ai 位于海外,阿里云服务器访问海外网络不稳定或被限制,TLS 握手阶段就超时,根本还没开始下载。
4.2 解决思路
绕过 ollama pull,直接从国内镜像下载 GGUF 量化文件,再用 ollama create 手动导入模型。
国内可用下载源:
- ModelScope(魔搭):首选,国内网络速度快;
- HF-Mirror(Hugging Face 镜像):备用。
先准备目录,下载对话模型 Qwen2.5-0.5B:
bash
mkdir -p ~/models && cd ~/models
# 首选:ModelScope
wget -c --show-progress --timeout=120 \
"https://modelscope.cn/models/qwen/Qwen2.5-0.5B-Instruct-GGUF/resolve/master/qwen2.5-0.5b-instruct-q4_0.gguf" \
-O qwen2.5-0.5b-instruct-q4_0.gguf
# 备用:HF-Mirror
wget -c --show-progress --timeout=120 \
"https://hf-mirror.com/Qwen/Qwen2.5-0.5B-Instruct-GGUF/resolve/main/qwen2.5-0.5b-instruct-q4_0.gguf" \
-O qwen2.5-0.5b-instruct-q4_0.gguf
再下载嵌入模型 nomic-embed-text(这是知识库向量化必需的):
bash
cd ~/models
# 首选:ModelScope
wget -c --show-progress --timeout=120 \
"https://modelscope.cn/models/nomic-ai/nomic-embed-text-v1.5-GGUF/resolve/main/nomic-embed-text-v1.5.Q4_K_M.gguf" \
-O nomic-embed-text-v1.5.Q4_K_M.gguf
# 备用:HF-Mirror
wget -c --show-progress --timeout=120 \
"https://hf-mirror.com/nomic-ai/nomic-embed-text-v1.5-GGUF/resolve/main/nomic-embed-text-v1.5.Q4_K_M.gguf" \
-O nomic-embed-text-v1.5.Q4_K_M.gguf
4.3 更稳的下载方式:Python + Hugging Face 镜像
wget 有时会中途断连或卡在最后阶段,用 Python 下载会更稳定:
bash
pip install huggingface-hub -q
export HF_ENDPOINT=https://hf-mirror.com
python3 << 'PY'
from huggingface_hub import hf_hub_download
import os
os.makedirs("/root/models", exist_ok=True)
hf_hub_download(
repo_id="Qwen/Qwen2.5-0.5B-Instruct-GGUF",
filename="qwen2.5-0.5b-instruct-q4_0.gguf",
local_dir="/root/models",
local_dir_use_symlinks=False,
)
hf_hub_download(
repo_id="nomic-ai/nomic-embed-text-v1.5-GGUF",
filename="nomic-embed-text-v1.5.Q4_K_M.gguf",
local_dir="/root/models",
local_dir_use_symlinks=False,
)
print("全部下载完成")
PY
也可以使用 ModelScope SDK:
bash
pip install modelscope -q
python3 << 'PY'
from modelscope import snapshot_download
import os
os.makedirs("/root/models", exist_ok=True)
snapshot_download(
"qwen/Qwen2.5-0.5B-Instruct-GGUF",
allow_patterns=["*.gguf"],
local_dir="/root/models",
)
snapshot_download(
"nomic-ai/nomic-embed-text-v1.5-GGUF",
allow_patterns=["*.gguf"],
local_dir="/root/models",
)
print("全部下载完成")
PY
如果服务器彻底下载不下来,还有一个保底方案:在本地电脑访问 ModelScope 或 HF-Mirror 下载 GGUF 文件,然后通过 scp 上传到服务器的 ~/models/ 目录,再执行后面的 ollama create 命令即可。
5. 手动导入 GGUF 模型
5.1 先校验文件完整性
下载后务必验证文件头。GGUF 文件应以 GGUF(十六进制 47475546)开头,这一步能提前发现下载不完整或下载到 HTML 错误页的情况:
bash
cd ~/models
# 查看文件大小
ls -lh *.gguf
# 对话模型约 300~500MB,嵌入模型约 270MB
# 如果只有几 KB,说明下载失败
# 查看文件头
head -c 4 qwen2.5-0.5b-instruct-q4_0.gguf | xxd
# 应显示:47475546(即 "GGUF")
如果文件头不对,删除后重新下载:
bash
rm -f qwen2.5-0.5b-instruct-q4_0.gguf
rm -f nomic-embed-text-v1.5.Q4_K_M.gguf
rm -rf ~/.ollama/models/*
5.2 创建对话模型
编写 Modelfile 并导入:
bash
cd ~/models
cat > Modelfile.chat << 'EOF'
FROM ./qwen2.5-0.5b-instruct-q4_0.gguf
PARAMETER temperature 0.7
PARAMETER num_ctx 2048
TEMPLATE """{{ if .System }}<|im_start|>system
{{ .System }}<|im_end|>
{{ end }}{{ if .Prompt }}<|im_start|>user
{{ .Prompt }}<|im_end|>
{{ end }}<|im_start|>assistant
{{ .Response }}<|im_end|>"""
EOF
ollama create qwen2.5-0.5b -f Modelfile.chat
5.3 导入嵌入模型
bash
cd ~/models
cat > Modelfile.embed << 'EOF'
FROM ./nomic-embed-text-v1.5.Q4_K_M.gguf
EOF
ollama create nomic-embed-text -f Modelfile.embed
5.4 验证安装
bash
ollama list
# 应显示 qwen2.5:0.5b 和 nomic-embed-text 两个模型
ollama run qwen2.5-0.5b "你好,请自我介绍"
6. 部署知识库前端:Open WebUI 的坑
完成模型准备后,开始部署知识库前端。最初尝试的是 Open WebUI。
6.1 部署 Open WebUI
bash
docker run -d -p 3000:8080 \
--name open-webui \
-v ~/.open-webui:/app/backend/data \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
ghcr.io/open-webui/open-webui:main
访问 http://服务器公网IP:3000 进行初始化。
6.2 遇到的问题
在 2G 内存服务器上,Open WebUI 产生了一系列问题:
- 页面直接 500 错误:Open WebUI 的后端 Python 进程(FastAPI)启动时因内存不足崩溃,只剩 Nginx 前端在运行;
- 容器健康但请求 500 :数据库
webui.db损坏或锁定(目录里同时出现webui.db-shm、webui.db-wal); - 模型关联不上:容器内访问 Ollama 时,需要确认 Ollama 监听地址与容器访问宿主机使用的 IP。
排查命令:
bash
# 检查容器状态
docker ps -a | grep open-webui
# 实时看日志
docker logs -f --tail=0 open-webui
# 检查内存
free -h
# 测试 Ollama API
curl -s http://127.0.0.1:11434/api/tags
6.3 内存不足的处理
先加 4G swap,再限制容器内存重启:
bash
# 加 swap
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
free -h
# 限制内存并重启容器
docker rm -f open-webui
docker run -d -p 3000:8080 \
--name open-webui \
--memory="1.5g" \
--memory-swap="3g" \
-v ~/.open-webui:/app/backend/data \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
ghcr.io/open-webui/open-webui:main
6.4 数据库损坏的处理
bash
docker stop open-webui
rm -f ~/.open-webui/webui.db*
docker start open-webui
7. 使用 Open WebUI 完成知识库搭建与网页端配置
经过第 6 节的排查和处理,最终仍然选择 Open WebUI 作为知识库前端。原因是 Open WebUI 自带文档管理、知识库和 RAG 能力,可以满足需求。只要通过增加 swap、限制容器内存并正确配置 Ollama 地址,就能在 2G 内存服务器上稳定运行。
7.1 稳定部署 Open WebUI
清理旧容器后,使用带内存限制的方式启动:
bash
docker rm -f open-webui 2>/dev/null
docker run -d \
--name open-webui \
--network host \
--memory="1.5g" \
--memory-swap="3g" \
-v ~/.open-webui:/app/backend/data \
-e OLLAMA_BASE_URL=http://127.0.0.1:11434 \
ghcr.io/open-webui/open-webui:main
这里使用 --network host 是为了让容器直接访问宿主机上 Ollama 的 11434 端口。如果不使用 host 网络,需要将 OLLAMA_BASE_URL 改为 docker0 网段 IP,例如 http://172.17.0.1:11434。
访问 http://服务器公网IP:3000 进行后续配置。
7.2 网页端初始化与连接 Ollama
首次打开会进入注册初始化页,创建第一个管理员账号并登录。
登录后配置 Ollama 连接:
- 点击左下角头像,进入 Admin Panel;
- 打开 Settings → Connections;
- 在 Ollama API 中填写
http://127.0.0.1:11434; - 点击 Save 保存;
- 刷新页面,确认模型列表能识别出
qwen2.5-0.5b和nomic-embed-text。
7.3 设置默认对话模型与 Embedding 模型
进入 Admin Panel → Settings → Models:
- 将默认对话模型设置为
qwen2.5-0.5b; - 将 Embedding 模型设置为
nomic-embed-text。
7.4 创建知识库并上传文档
Open WebUI 通过「知识库」管理 RAG 文档:
- 左侧导航进入 Workspace → Knowledge;
- 点击 Create a knowledge,填写知识库名称;
- 选择 Embedding 模型
nomic-embed-text; - 上传 Markdown、TXT 或 PDF 文档;
- 等待文档向量化完成,状态变为可用。
2G 内存服务器处理文档较慢,建议从少量小文件开始测试。
7.5 对话时引用知识库
新建对话后,点击输入框上方的 Knowledge 图标,勾选刚创建的知识库;之后提问时,Open WebUI 会先从知识库检索相关片段,再结合 qwen2.5-0.5b 生成回答。## 8. Docker 镜像拉取加速
拉取 Open WebUI 等容器镜像时同样可能卡住,这是 Docker Hub 的海外网络问题。解决办法是配置国内镜像源:
bash
sudo tee /etc/docker/daemon.json << 'EOF'
{
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn",
"https://hub-mirror.c.163.com",
"https://mirror.baidubce.com"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
# 重新拉取镜像
docker pull ghcr.io/open-webui/open-webui:main
9. 踩坑总结与建议
9.1 问题清单
| 问题 | 原因 | 解决方案 |
|---|---|---|
ollama pull TLS 握手超时 |
无法访问海外仓库 | 国内镜像下载 GGUF 后手动导入 |
| 嵌入模型同样下载失败 | 同上 | ModelScope / HF-Mirror |
| GGUF 文件报格式错误 | 下载不完整或文件损坏 | 校验文件头,删除后重新下载 |
| 下载卡在 100% | 网络最后阶段中断,或内存不足 | 换 Python 下载,或本地下载后 scp 上传 |
| Open WebUI 页面 500 | 后端进程 OOM 崩溃或数据库损坏 | 加 swap、限制容器内存、重置数据库 |
| 模型关联不上 | Ollama 监听地址与容器访问 IP 不一致 | 检查 ss -tlnp 与 docker0 网段 IP |
| Docker 镜像拉取慢 | 默认仓库在海外 | 配置 registry-mirrors |
9.2 经验总结
- 2 核 2G 服务器搭建 AI 知识库可行,但只能跑 0.5B~2B 的量化小模型,回答质量有限,适合做简单文档检索问答;
- 国内服务器部署 AI 相关组件,网络是第一大坑:Ollama 官方仓库、HuggingFace、Docker Hub 都可能超时,要提前准备好国内镜像源;
- 整个链路中模型文件下载最容易出问题,下载后务必校验文件头再导入;
- 知识库前端最终选择 Open WebUI,通过加 swap、限制容器内存并正确配置 Ollama 地址,可以在 2G 内存服务器上稳定运行;使用前务必完成网页端连接与知识库配置。
9.3 升级建议
如果想获得更好的体验,建议至少升级到 4 核 4GB,可以跑 7B 级别的量化模型;有预算的话,选择带 GPU 的实例会让推理速度明显提升。