docs(deploy): 部署方法 Skill 化——含换机/无生信/自定义库路径变体与提示词示例
与本地 Claude Code skill(plantai-deploy)同源,面向 agent 自动执行; 新增 §7 部署变体(7.1 换机=密钥+路径+基础设施一次准备;7.2 无生信= 不部署 bioflow 树+env 关 BIOFLOW_ENABLED,start_all 自动跳过;7.3 自定义 库路径=QA_DB_ROOT/VSTORE_ROOT env 纯配置)与 §9 提示词示例(全量/新机 裁剪/纯前端/换库四种)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
# PlantAI-rag-new 打包部署 Skill(175 构建机 → 176 生产)
|
||||
|
||||
> 本文件是 Claude Code skill 形态的部署方法(与 DEPLOY_FLOW.md 流程互补,侧重 agent 自动执行)。
|
||||
> 生成于 2026-09-12,融合当日全部实战陷阱;2026-09-12 晚增补部署变体(换机/无生信/自定义库路径)与提示词示例。
|
||||
> skill 源文件:本地 ~/.claude/skills/plantai-deploy/SKILL.md。
|
||||
|
||||
## 0. 前置事实(agent 必读,勿想当然)
|
||||
|
||||
- **175 = 构建机/开发仓库**(8.163.92.8,公网 `ssh -p 26518 xzq@8.163.92.8`):仓库 `/home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new`,分支 `feature/bioflow-conversation-orchestration`,Gitea 在 `http://127.0.0.1:3000`。
|
||||
- **176 = 生产**(8.138.231.183,公网 `ssh -p 26518 xzq@8.138.231.183`):部署根 `/srv/plantai/`(install/ + qa-db/ + data/ + docgen/ + bioflow/ + mineru-*)。
|
||||
- **端口终态**:nginx 80(唯一客户入口)→ BFF 8090;QA 8091/methodology 8092/legacy 8093/vstore 8094/bioflow 8098 全回环;裸进程库 Neo4j 19888/Qdrant 27433;Ollama 11434。
|
||||
- **两机传输用 P2P 内网直连**(175 上密钥 `~/.ssh/id_ed25519_p2p`,勿走跳板机):
|
||||
`rsync -a --numeric-ids -e 'ssh -i ~/.ssh/id_ed25519_p2p -p 26518 -o BatchMode=yes' <src>/ xzq@192.168.0.176:<dst>/`
|
||||
- **BFF 静态托管 ui/dist**:前端改动部署 = 只同步 dist 资产 + 清旧哈希文件,不需整包重编。
|
||||
|
||||
## 1. 构建(175,全量约 30-40 分钟)
|
||||
|
||||
```bash
|
||||
cd /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new
|
||||
git status --short # 先确认无未提交改动
|
||||
bash tooling/build_all.sh # 串行:五树 Cython 编译→双审计→冒烟 import→组装→SHA256SUMS→泄露门禁
|
||||
```
|
||||
|
||||
- 版本与 env 在 `tooling/tooling.env`(VERSION=2.0.0,SKIP_KB=1 数据库未定版)。
|
||||
- **产物断言**:`tooling/build/2.0.0/install/` 应含 sdk/qa/methodology/legacy-rag/vstore/ui/start_all.sh/vstore_restart.sh/ollama_restart.sh/SHA256SUMS。
|
||||
- **SHA256SUMS 校验的已知良性失败**:`./SHA256SUMS: 失败` 是清单自引用条目,永远不匹配;其余 1367 项应全 OK。
|
||||
- **start_all.sh 由 build_all 模板生成**(heredoc),改动模板=`tooling/build_all.sh`,不是产物文件。
|
||||
- **UI dist 内置**:build_all 内部会跑 `npm run build`;前端单测(r3debug 89 + 主套件 373)在构建前跑一遍:
|
||||
`cd ui && npx vitest run --config tests/r3debug/vitest.config.js && npx vitest run`
|
||||
|
||||
## 2. 部署前准备
|
||||
|
||||
```bash
|
||||
# 2.1 176 备份(必做;恢复依据)
|
||||
ssh -p 26518 xzq@8.138.231.183 "cp -a /srv/plantai/install /srv/plantai/install.bak-$(date +%s)"
|
||||
# 2.2 从 175 发起 P2P 连通性预检
|
||||
ssh -i ~/.ssh/id_ed25519_p2p -p 26518 -o BatchMode=yes -o ConnectTimeout=8 xzq@192.168.0.176 'hostname'
|
||||
```
|
||||
|
||||
## 3. 传输(rsync --delete,必须 exclude 四个本地产物)
|
||||
|
||||
```bash
|
||||
cd /home/xzq/5090/teamWorkspace/zh/PlantAI-rag-new/tooling/build/2.0.0
|
||||
rsync -a --numeric-ids --delete \
|
||||
--exclude 'venv' \
|
||||
--exclude 'sdk/data' \
|
||||
--exclude '.env' \
|
||||
-e 'ssh -i ~/.ssh/id_ed25519_p2p -p 26518 -o BatchMode=yes' \
|
||||
install/ xzq@192.168.0.176:/srv/plantai/install/
|
||||
```
|
||||
|
||||
**exclude 原理**(2026-09-12 实测,漏掉会删生产数据):源构建树不含 176 的 `install/venv`(1.8G Python 环境)、`install/sdk/data`(plantai.db/docgen 数据)、`install/.env`、`install/sdk/.env`;`--delete` 会把这些删掉。
|
||||
|
||||
**传输后必做——恢复三份 prod.env**:rsync 会删 176 的 `{qa,methodology,legacy-rag}/env/prod.env`(源构建树只有 .example)。从刚做的备份恢复:
|
||||
|
||||
```bash
|
||||
ssh -p 26518 xzq@8.138.231.183 '
|
||||
for t in qa methodology legacy-rag; do
|
||||
cp /srv/plantai/install.bak-*/$t/env/prod.env /srv/plantai/install/$t/env/prod.env
|
||||
done
|
||||
# 幸存校验:venv/sdk/data/.env 应仍在
|
||||
ls -d /srv/plantai/install/venv /srv/plantai/install/sdk/data /srv/plantai/install/sdk/.env
|
||||
'
|
||||
```
|
||||
|
||||
## 4. 重启(注意 BFF 不随 start_all 换进程)
|
||||
|
||||
```bash
|
||||
# 4.1 手动杀旧 BFF(lsof 只取 LISTEN;start_all 不替换在跑进程——E-6 陷阱)
|
||||
ssh -p 26518 xzq@8.138.231.183 'kill $(lsof -ti tcp:8090 -sTCP:LISTEN) 2>/dev/null; sleep 2'
|
||||
# 4.2 杀 QA/methodology/legacy(让它们吃到新代码)
|
||||
ssh -p 26518 xzq@8.138.231.183 '
|
||||
for p in 8091 8092 8093; do kill $(lsof -ti tcp:$p -sTCP:LISTEN) 2>/dev/null; done; sleep 2'
|
||||
# 4.3 新版 start_all.sh 一键拉起(五服务 + 生信编排,自带 disown 不卡)
|
||||
ssh -p 26518 xzq@8.138.231.183 'cd /srv/plantai/install && timeout 180 bash start_all.sh'
|
||||
```
|
||||
|
||||
**lsof 陷阱**:`lsof -ti tcp:PORT` 会返回该端口**所有 socket** 的进程(含已建立连接);**必须加 `-sTCP:LISTEN` 只取监听者**,且 kill 不加引号。vstore/bioflow 的 restart.sh 已内置此过滤,直接调即可:
|
||||
|
||||
```bash
|
||||
bash /srv/plantai/install/vstore_restart.sh # vstore 幂等重启(自带 lsof LISTEN + disown)
|
||||
bash /srv/plantai/bioflow/bioflow_service/restart.sh # 生信(独立树,不在 install 内)
|
||||
```
|
||||
|
||||
**start_all 编排行为**(2026-09-12 起):ollama → QA/methodology/legacy(已跑则跳过)→ vstore → **探测 install 同级 bioflow/ 树,存在则启动/重启生信 8098**(不存在静默跳过)→ BFF。BFF 段有 `disown -a`,脚本正常退出不会卡。
|
||||
|
||||
## 5. 部署后质检(逐条核对)
|
||||
|
||||
```bash
|
||||
# 5.1 六服务端口全景(8090/8091/8092/8093/8094/8098 应全 LISTEN 且是新进程 lstart)
|
||||
ssh -p 26518 xzq@8.138.231.183 'for p in 8090 8091 8092 8093 8094 8098; do
|
||||
ss -tlnp | grep ":$p " | grep -o "pid=[0-9]*" | head -1; done'
|
||||
# 5.2 BFF health 五上游全 ok
|
||||
curl -s http://127.0.0.1:8090/api/health
|
||||
# 5.3 生信 TAB 依赖的端点(掉进程时 TAB 静默消失;无生信部署此项应为 UPSTREAM_DOWN 且属预期)
|
||||
curl -s http://127.0.0.1:8090/api/bioflow/health
|
||||
# 5.4 nginx 80 全链(唯一客户入口)
|
||||
curl -s http://127.0.0.1:80/api/health
|
||||
# 5.5 前端新资产已服务 + 旧哈希已清
|
||||
curl -s http://127.0.0.1:80/ | grep -o 'index-[A-Za-z0-9_-]*\.\(js\|css\)'
|
||||
# 5.6 SHA256SUMS(排除 SHA256SUMS 自引用条目,其余应全 OK)
|
||||
cd /srv/plantai/install && sha256sum -c SHA256SUMS 2>&1 | grep -cv 'OK$'
|
||||
```
|
||||
|
||||
## 6. 纯前端改动快速部署(不重编)
|
||||
|
||||
```bash
|
||||
# 175 构建后:
|
||||
rsync -a --numeric-ids -e 'ssh -i ~/.ssh/id_ed25519_p2p -p 26518 -o BatchMode=yes' \
|
||||
ui/dist/ xzq@192.168.0.176:/srv/plantai/install/ui/dist/
|
||||
# 176 清旧哈希资产(先看 index.html 引用哪个,删其余):
|
||||
ssh -p 26518 xzq@8.138.231.183 'cd /srv/plantai/install/ui/dist && grep -o "index-[A-Za-z0-9_-]*\.\(js\|css\)" index.html'
|
||||
# BFF 是静态托管,无需重启;浏览器强刷即生效
|
||||
```
|
||||
|
||||
## 7. 部署变体(换机/裁剪/自定义库路径)
|
||||
|
||||
本 skill 主体以「175 → 176 全量」为模板;以下变体全部实测可行,机制均内建:
|
||||
|
||||
### 7.1 部署到其他机器
|
||||
|
||||
业务层流程(§1-6)原样复用,只需替换三处:
|
||||
- **P2P 密钥**:把 175 的 `~/.ssh/id_ed25519_p2p.pub` 装进新机器 authorized_keys(或改用新机器自己的 SSH 端口/凭据),rsync 命令的目标地址同步替换。
|
||||
- **部署根路径**:rsync 目标与后续命令里的 `/srv/plantai` 换成新机器路径。
|
||||
- **基础设施一次准备**(新机器首次,业务层外):按 `docs/DEPLOY_FLOW.md` §5.1-5c 做 py3.12 venv+依赖清单、各树 env(路径类键改目标机布局)、nginx 80 反代、MinerU(可选)、Ollama(可选);数据库用 `deploy/qa-db/` 的 systemd 脚本裸装(数据目录见 §7.3)。
|
||||
- 数据库数据从现网同步:整目录 rsync(82G 约 8 分钟),或 `replace_db.sh` 整库替换(自动探活+回滚)。
|
||||
|
||||
### 7.2 不含生信部分(零配置,自动行为)
|
||||
|
||||
start_all 的生信编排(9d7ed1b)探测 `install 同级 bioflow/bioflow_service/restart.sh`,**树不存在即静默跳过**。彻底不含生信的做法:
|
||||
1. **不部署 bioflow 树**(不传 `/srv/plantai/bioflow/`),也不搬运 8 个镜像(40G);
|
||||
2. `sdk/.env` 不加 `BIOFLOW_ENABLED`(或设为 false)——前端生信 TAB 按 `/api/bioflow/health` 轮询显隐,自然不显示。
|
||||
> 注意:start_all 只看「树是否存在」,不看 env——若树在而 env 关,8098 仍会拉起。要彻底不含,树和 env 都去掉。
|
||||
> 质检时 §5.3 的 bioflow health 返回 UPSTREAM_DOWN 属预期,跳过该项。
|
||||
|
||||
### 7.3 三个向量库用自定义路径(纯配置,零代码改动)
|
||||
|
||||
| 库 | 数据路径决定 | 连接键(QA 服务 env) |
|
||||
|---|---|---|
|
||||
| Neo4j | `QA_DB_ROOT` env → `$QA_DB_ROOT/neo4j/data`(install_neo4j.sh 的 server.directories.data) | `NEO4J_URI` |
|
||||
| Qdrant | 同脚本 `storage_path: $STORAGE`(源于 QA_DB_ROOT) | `QDRANT_URL` / `V15_QDRANT_COLLECTION` / `NORMALIZED_RELEASE_ID` |
|
||||
| vstore | `VSTORE_ROOT` env(vstore_restart.sh source 自己的 .env) | `VSTORE_BASE_URL`(BFF 侧) |
|
||||
|
||||
- 「向量库放 xxxx 路径」= 数据库 systemd 安装阶段设 `QA_DB_ROOT=xxxx` + qa env 连接 URI 指向对应端口——无代码改动。
|
||||
- 换库(如水产库)是同一机制:换路径 + 换 `NORMALIZED_RELEASE_ID`/`V15_QDRANT_COLLECTION` 两个键,整库替换走 `replace_db.sh`(自动探活+回滚)。
|
||||
- **db 层不在 start_all 编排**:systemd 的 neo4j/qdrant 在安装期定路径,之后 start_all 不动它们。
|
||||
|
||||
## 8. 陷阱速查(全部实测)
|
||||
|
||||
1. **rsync --delete 删本地产物**:必须 exclude venv/sdk/data/.env;prod.env 传输后从备份恢复。
|
||||
2. **start_all 不杀在跑的 BFF**:新 uvicorn 端口被占静默退出,自检看到的是旧进程——先 `kill $(lsof -ti tcp:8090 -sTCP:LISTEN)`。
|
||||
3. **lsof 不带 LISTEN 过滤**:kill 多行 PID(含已建立连接进程)失败,旧进程存活、新进程绑定失败静默退出。
|
||||
4. **start_all 缺 disown**:bash 尾部隐式 wait BFF 永不返回(已修,勿回退)。
|
||||
5. **生信 TAB 消失 = 8098 掉进程**:bioflow_service 独立树,start_all 现会自拉;排查先 curl `/api/bioflow/health`。
|
||||
6. **figures 双键 + registry**(r4):`PLANTAI_FIGURES_MINERU_ROOT/REGISTRY` 缺一即静默降级纯 PMC;registry 文件需单独传输。
|
||||
7. **cython .so 验证必须 runtime import**:`strings` 探不到 env 键,会误判旧代码。
|
||||
8. **vstore 数据完整性**:health 计数异常先查进程 environ(VSTORE_* 键),再怀疑数据。
|
||||
9. **MinerU 缺 accelerate**:启动期 `ValueError: requires accelerate`,目标机需 `pip install accelerate`。
|
||||
10. **QA LLM 截断重试**:`LLM output was truncated by the token limit` 会重试 4 次(每 ~9.5s),最终仍出答案,非部署故障。
|
||||
|
||||
## 9. 提示词示例(直接复制给 agent)
|
||||
|
||||
**全量部署到 176(默认形态)**:
|
||||
```
|
||||
按 plantai-deploy skill 部署:175 仓库最新代码打包部署到 176,含生信,部署后跑完整质检并汇报。
|
||||
```
|
||||
|
||||
**部署到新机器 + 不含生信 + 自定义库路径**:
|
||||
```
|
||||
按 plantai-deploy skill 部署到一台新机器(192.168.0.177,ssh 端口 26518,部署根 /srv/plantai)。
|
||||
要求:不含生信部分(不部署 bioflow 树、不搬运镜像、sdk/.env 不开 BIOFLOW_ENABLED);
|
||||
Neo4j 与 Qdrant 的数据目录放在 /data/qa-db(即 QA_DB_ROOT=/data/qa-db);
|
||||
基础设施按 DEPLOY_FLOW §5.1 从零准备,数据库数据从 176 的 /srv/plantai/qa-db 同步;
|
||||
完成后跑质检(生信项按无生信预期)并汇报。
|
||||
```
|
||||
|
||||
**纯前端快速部署**:
|
||||
```
|
||||
按 plantai-deploy skill 把 175 最新前端 dist 部署到 176(纯前端,不重编),并验证 nginx 80 已服务新资产。
|
||||
```
|
||||
|
||||
**换库部署(以水产库为例)**:
|
||||
```
|
||||
按 plantai-deploy skill 换库部署:用水产库(kb-libraries/aqua)替换 176 当前植物库。
|
||||
换库是纯配置:NORMALIZED_RELEASE_ID 与 V15_QDRANT_COLLECTION 换成 aqua 值,
|
||||
Neo4j/Qdrant 数据目录指向 aqua 库位置,replace_db.sh 整库替换;
|
||||
植物库保留原位可回滚;部署后跑金标问答质检并汇报。
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user