作者: qiancheng

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

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


    用一台腾讯云轻量服务器 + 宝塔面板,把字节开源的 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。软件版本迭代较快,命令与配置项请以官方文档为准。

  • 世界,您好!

    欢迎使用 WordPress。这是您的第一篇文章。编辑或删除它,然后开始写作吧!