OpenViking 部署实录:从零跑通 AI 记忆库的 HTTPS 检索与对话机器人

OpenViking 部署教程封面

作者:


用一台腾讯云轻量服务器 + 宝塔面板,把字节开源的 AI Agent 上下文数据库 OpenViking 部署上线,并通过自己的域名跑通 HTTPS、语义检索和对话机器人。全文记录每一步命令、每一处报错和原因。

OpenViking 部署教程封面

一、这东西是干什么的,为什么值得部署

OpenViking 是火山引擎开源的、专门给 AI Agent 用的上下文数据库。它把 Agent 需要的三类东西——记忆(Memory)、资源(Resource)、技能(Skill)——统一成一套虚拟文件系统,用 viking:// 协议寻址。

和传统 RAG 最大的区别有两点:

  • 分层供给:写入时自动生成三层——L0 摘要(256 字符,用于向量召回)、L1 概览(4000 字符,用于精排)、L2 全文(按需加载)。不用一次性把海量内容塞进提示词。
  • 目录递归检索:先向量定位到高分目录,再在目录里二次检索、逐层下探。比平铺式向量搜索更能理解”这句话在什么语境里说”。

说白了:它让你的 AI 助手有长期记忆,而且这套记忆是可以用 lsfindread 直接查看和调试的,不是黑箱。

二、开工前的准备

2.1 你需要什么

项目 说明
一台云服务器 本文用腾讯云 2 核 3.5G 轻量服务器,系统 OpenCloudOS 9.6(RHEL 系,用 dnf
宝塔面板 本文用 宝塔 Linux 面板 11.8 腾讯云专享版,用来做反向代理和 SSL
一个域名 需要已备案(国内服务器必须)
模型 API Key 需要两个模型:一个 Embedding(向量化)、一个 VLM(视觉多模态)。本文用 MiniMax

关键认知:为什么需要”两个”模型?

Embedding 负责把文本变成向量(检索用),VLM 负责读图和理解内容(解析用)。这两个是 OpenViking 的硬依赖,缺一个 doctor 就不过。

2.2 先做环境体检

cat /etc/os-release | head -3
uname -m
python3 -V
free -h
df -h /
ss -lntp | grep 1933 || echo "1933 端口空闲"

本文环境的实测结果:

检查项 实测值 结论
系统 OpenCloudOS 9.6 RHEL 9 兼容,用 dnf不要用 apt
架构 x86_64 有预编译包,不需要源码编译
Python 3.11.6 满足 ≥3.10 要求
内存 3.5G 总量 / 2.3G 可用 超过 2G 及格线
1933 端口 空闲 OpenViking 默认端口,无冲突

三、安装

3.1 装 uv,建独立虚拟环境

curl -LsSf https://astral.sh/uv/install.sh | sh
source ~/.bashrc

# 建一个专用虚拟环境(不要装进系统 Python,也不要动宝塔自己的 pyenv)
uv venv /opt/openviking/venv --python 3.11

为什么必须用独立虚拟环境? 宝塔面板自己的 Python 在 /www/server/panel/pyenv,那是面板的命根子,装任何东西进去都可能把面板搞挂。

3.2 安装 OpenViking

source /opt/openviking/venv/bin/activate
uv pip install openviking
openviking-server --version   # 本文实测 0.4.20
deactivate

四、写配置文件 ov.conf

配置文件放在 /etc/openviking/ov.conf

mkdir -p /etc/openviking
cat > /etc/openviking/ov.conf <<'EOF'
{
  "server": {
    "host": "127.0.0.1",
    "port": 1933,
    "root_api_key": "CHANGE_ME_ROOT_KEY"
  },
  "storage": {
    "workspace": "./data",
    "agfs": { "backend": "local" },
    "vectordb": { "backend": "local" }
  },
  "embedding": {
    "dense": {
      "provider": "minimax",
      "model": "embo-01",
      "api_key": "CHANGE_ME_EMBEDDING_KEY",
      "api_base": "https://api.minimax.cn/v1/embeddings"
    }
  },
  "vlm": {
    "provider": "openai",
    "model": "MiniMax-M3",
    "api_key": "CHANGE_ME_VLM_KEY",
    "api_base": "https://api.minimax.cn/v1"
  }
}
EOF

chmod 600 /etc/openviking/ov.conf
python3 -m json.tool /etc/openviking/ov.conf > /dev/null && echo "JSON 合法"

⚠️ 坑 1:Embedding 的 api_base 必须写到 /embeddings 这一级

这是全文最容易踩、也最难查的一个坑。

MiniMax 的 Embedding 端点是 https://api.minimax.cn/v1/embeddings,而 OpenViking 源码里是直接 POST 到 api_base 这个值,不会自动帮你拼 /embeddings 路径。所以如果你只写 https://api.minimax.cn/v1,请求会 404。

正确写法:api_base 一路写到 /embeddings 为止。

另外,网上一些老教程会让你配 GroupId / extra_headers——那是针对 MiniMax 老平台的。新版平台不需要,加了反而可能报 token not match group

五、自检 doctor

/opt/openviking/venv/bin/openviking-server doctor

跑完应该看到各组件全绿。如果 embedding 报错,回到第四章检查 api_base

你会看到一条 WARN,不用慌:

VikingBot: WARN  bot.ov_server not configured and ovcli.conf api_key not configured

这条是给可选的对话机器人组件 VikingBot 用的,和核心功能(文件系统 / 检索 / 会话)完全无关。它是”功能开关没打开”,不是”坏了”——后面第十一章我们会把它正式启用。

六、用 systemd 做成常驻服务

cat > /etc/systemd/system/openviking.service <<'EOF'
[Unit]
Description=OpenViking HTTP Server
After=network.target

[Service]
Type=simple
WorkingDirectory=/opt/openviking
ExecStart=/opt/openviking/venv/bin/openviking-server
Restart=always
RestartSec=5
Environment="OPENVIKING_CONFIG_FILE=/etc/openviking/ov.conf"

[Install]
WantedBy=multi-user.target
EOF

systemctl daemon-reload
systemctl enable --now openviking
systemctl status openviking --no-pager | head -12
curl -s http://127.0.0.1:1933/health; echo

为什么 ExecStart 要写绝对路径? 这样 systemd 不依赖任何 shell 环境变量,也不需要预先 activate 虚拟环境,更稳。

七、宝塔反向代理 + HTTPS

请求链路:客户端 → 域名 → nginx → OpenViking

7.1 建站 + 加反向代理

  1. 宝塔面板 → 网站 → 添加站点,域名填你的(例如 your-domain.com
  2. 站点设置 → 反向代理 → 添加,目标 URL 填 http://127.0.0.1:1933,代理目录填 /结尾不要带斜杠

宝塔 11.8 的反代配置在哪儿? 不在站点主配置里,而在独立目录/www/server/panel/vhost/nginx/proxy/your-domain.com/*.conf。站点 conf 只是 include 了它。改反代参数要改这个目录里的文件。

7.2 补转发头和超时(重要)

AI 服务响应慢,而且需要知道真实的协议和域名。把下面这几行加进反代配置的 location里面

proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_buffering off;
proxy_set_header X-Forwarded-Proto $schema;
proxy_set_header X-Forwarded-Host $host;

⚠️ 坑 2:转发头必须写在 location 内部,不能写在 server 级

nginx 的 proxy_set_header / add_header 继承规则是全有或全无:本层只要出现任意一条,就会完全覆盖上层的全部,而不是逐条合并。

宝塔会在 server 级预置一批转发头。如果你在 server 级再补一条,反而会把宝塔那批全部顶掉。所以:要加就加在 location 里。

另外 proxy_buffering off 对 SSE 流式输出是必须的,否则你会看到”回答卡住不吐字”。

7.3 申请 SSL 证书

宝塔站点设置 → SSL → Let’s Encrypt → 申请(勾选自动续签)。

⚠️ 坑 3:先申请证书,再开”强制 HTTPS”

Let’s Encrypt 的 HTTP-01 校验是通过 80 端口来验证域名所有权的。如果你先开了强制 HTTPS,80 的请求会被 301 跳到 443——而这时候证书还没签下来,443 用不了,校验必然失败,死锁

正确顺序:申请证书 → 验证 https:// 能通 → 再开强制 HTTPS。

7.4 验证

curl -s https://your-domain.com/health
# {"status":"ok","healthy":true,"version":"0.4.20","auth_mode":"api_key"}

八、建租户,拿 API Key

因为配置里设了 root_api_key,系统处于多租户模式。先建一个租户:

export OV=/opt/openviking/venv/bin/ov

curl -s -X POST https://your-domain.com/api/v1/admin/accounts \
  -H "X-API-Key: YOUR_ROOT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"account_id":"myteam","admin_user_id":"admin"}' \
  | python3 -m json.tool

返回里会带一个 user_key(一长串),这就是日常使用的凭据

🔒 安全三原则:

  1. user_key / root_api_key 绝不要贴进聊天、截图、日志、Git 仓库;
  2. 只把 key 输出到一个 600 权限的文件里,屏幕上只打印长度确认;
  3. 终端里的明文 key 记得清理,浏览器登录框里的也别忘了。

另外注意:.../users/{user_id}/key 这个接口是 POST = 重新生成(轮换),不是”读取”。调一次旧 key 就失效了,别乱试。

九、命令行验证

# 配置(非交互,key 从 stdin 读,不进 shell 历史)
ov config add custom --name myblog \
  --url https://your-domain.com \
  --api-key-stdin --activate

# 看全局状态
ov status

# 语义检索(这是"能用"而不是"活着"的证据)
ov find "你的问题"

ov find 返回带相关性分数排序、带 L0/L1/L2 分层标记、带内容摘要的结果时,说明向量库、Embedding 模型、检索排序、分层阅读这整条 AI 能力链路全部可用

关于 add-resource 抓取失败: 如果你灌入的是 GitHub 之类的境外 URL,可能会遇到 PROCESSING_ERROR: Parse error: HTTP request failed: timeout

注意错误码是 PROCESSING_ERROR——说明请求已经到了 OpenViking、也开始处理了,是它去下载那个 URL 时超时。这不是部署问题,是服务器访问境外网络的问题。

对策:优先用国内可达的源,或先把文件 wget 到本地再用本地路径导入。

十、验证:看整体健康

ov status

全组件健康 + 语义检索有结果 = 部署成功。这时候浏览器打开 https://your-domain.com/studio 就能看到 Web 管理界面了。

十一、启用 VikingBot(对话机器人)

VikingBot 对话机器人

打开管理后台的 /studio/monitoring,你会看到一条提示:

请启用 VikingBot
当前服务未启用 Agent 对话功能。请使用以下参数启动服务后重试。
openviking-server --with-bot

核心就一句话:让服务带 --with-bot 启动。 你是 systemd 托管的,所以把它写进服务文件:

# 1) 先备份,方便一条命令回滚
cp /etc/systemd/system/openviking.service /root/openviking.service.bak

# 2) 给启动命令加上 --with-bot
sed -i '/^ExecStart=/ s|$| --with-bot|' /etc/systemd/system/openviking.service
grep '^ExecStart' /etc/systemd/system/openviking.service

# 3) 生效
systemctl daemon-reload && systemctl restart openviking

⚠️ 坑 4:VikingBot 是”可选依赖”,基础版安装不带它

加完 --with-bot 重启,日志里出现:

Warning: vikingbot not found. Please install vikingbot first.
Error: --with-bot was requested, but VikingBot could not be started.

而且因为 Restart=always,服务开始崩溃循环systemctl is-active 显示 activating),网站直接 502。先止血:

systemctl stop openviking

然后排查。vikingbot not found 有两个完全不同的原因,必须看详细报错才能区分

坑 4-A:systemd 的 PATH 里没有虚拟环境的 bin

ExecStart 写的是绝对路径,所以 server 本身能启动;但它去启动 vikingbot 子进程时是按名字找的,走 PATH——而 systemd 服务的 PATH 里没有 /opt/openviking/venv/bin,于是”找不到”。

验证:ls -l /opt/openviking/venv/bin/vikingbot——文件明明在,就是找不着。

修复:给 unit 补一行 PATH。

Environment="PATH=/opt/openviking/venv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

坑 4-B:依赖没装全(本次真正的根因)

补完 PATH 后仍然失败,日志给出了详细原因:

File "/opt/openviking/venv/bin/vikingbot", line 4, in <module>
    from vikingbot.cli.commands import app
ModuleNotFoundError: No module named 'prompt_toolkit'
Error: vikingbot gateway exited early (code 1)

脚本在、包在,但运行时依赖缺失。安装时用了基础包 openviking,没有装可选依赖 openviking[bot]

修复(注意钉住版本,避免顺带把 OpenViking 升级):

source /opt/openviking/venv/bin/activate
uv pip install "openviking[bot]==0.4.20"
vikingbot --version
deactivate

systemctl restart openviking

注意日志里的建议命令是”源码安装”写法。 报错会告诉你 uv pip install -e ".[bot,dev]",但那是给 git clone 源码装的人用的。你是 PyPI 安装,照抄会失败——正确写法是 openviking[bot]

验证 Bot 起来了

systemctl is-active openviking
curl -s http://127.0.0.1:1933/bot/v1/health; echo
ss -lntp | grep 18790
journalctl -u openviking -n 30 --no-pager | grep -iE 'vikingbot|gateway'

然后回管理后台点「重新检测」,状态从”未启用”变为运行中;控制台里 ov chat -m "你好" 能正常回复,就成功了。

一个容易误判的细节: grep -i error 会命中 uvicorn.error 这样的日志器名字,看起来像报错其实不是。判断要看内容,别只看关键词。

十二、日常运维

日常运维:备份、升级与自动化

12.1 备份

tar -czf /root/ov-backup-$(date +%F).tar.gz \
  -C /opt/openviking data /etc/openviking/ov.conf

建议加进 crontab 每天凌晨跑一次,保留最近 7 份。

12.2 升级

source /opt/openviking/venv/bin/activate
uv pip install openviking --upgrade
systemctl restart openviking
curl -s http://127.0.0.1:1933/ready

升级前先备份。向量库的 schema 跨版本可能有变更,这一步不能省。

12.3 让知识库自动更新

OpenViking 支持给资源设定自动重抓周期。对做电商运营的人来说,这相当于把你的”平台规则页 / 类目政策 / 竞品页面”变成会自动刷新的知识源:

ov add-resource https://example.com/类目规则页 \
  -p viking://resources/平台规则 --watch-interval 1440

--watch-interval 单位是分钟,1440 就是每天重抓一次。

12.4 调用量对账

curl -s https://your-domain.com/api/v1/console/tokens \
  -H "X-API-Key: YOUR_USER_KEY" | python3 -m json.tool

建议每周看一次,确认调用量和实际使用行为相符——这是发现 key 泄露最直接的办法。

12.5 常用排障

systemctl status openviking --no-pager
journalctl -u openviking -n 200 --no-pager
ss -lntp | grep -E '1933|18790'

实测更正: 网上一些旧文档提到要手动 pkill agfs 清理子进程。在 0.4.20 上不需要——日志里的 Loaded RAGFS Rust binding 说明 AGFS 是以进程内 Rust 绑定运行的,和主进程同生共死。systemctl stop 一次就收干净,正常只有 1 个进程。

十三、踩坑总清单

# 现象 原因 对策
1 Embedding 404 源码直接 POST api_base,不拼路径 api_base 写到 /embeddings 这一级
2 转发头不生效 proxy_set_header 继承是”全有或全无” 写在 location 内,不要写 server 级
3 SSL 申请失败 先开了强制 HTTPS,80 被 301 走 先签证书,验证 https 通,再开强制跳转
4 Bot 启用后服务崩溃循环 + 502 服务找不到 vikingbot stop 止血;给 unit 补 PATH
5 补 PATH 后仍失败 缺可选依赖 prompt_toolkit uv pip install "openviking[bot]==版本号"
6 回答”卡住不吐字” nginx 缓冲了 SSE proxy_buffering off
7 导入境外 URL 超时 服务器访问境外网络不稳 换国内源,或先下到本地再导入

十四、小结

整套流程跑下来说实话并不复杂,真正花时间的是四处”看起来一样、原因完全不同”的报错

回头看,最有价值的一条经验是:

给 systemd 托管的 Python 服务启用”可选子组件”时,按这个顺序查:

  1. 子组件可执行文件在不在ls -l .../bin/xxx
  2. service 的 PATH 有没有含虚拟环境的 bin——ExecStart 用绝对路径能启动,不等于子进程也能按名字找到
  3. 依赖装全了没——必须看详细报错,官方建议的命令可能是源码安装写法,与你无关
  4. 万一进了崩溃循环——先 systemctl stop 止血,改 unit 前先备份,一条命令就能回滚

还有一条心得:每次动生产配置之前,花 10 秒确认”零件在不在”。这次就是漏了 vikingbot --version 这一句检查,代价是一轮崩溃循环加一次 502。它不是多余的步骤,它是保险。


本文记录于 2026 年 9 月,OpenViking v0.4.20。软件版本迭代较快,命令与配置项请以官方文档为准。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注