Files
PlantAI-rag-new/tooling/legacy_plantai_server_package/phase_f_migrate_data.sh
T
jerryandClaude Fable 5 27946edc2b P0/M1: 收编 encryption-test 工具链入 tooling/
- legacy_plantai_server_package/: phase_a–f + compile_* + bin/plantai_admin.py
  + tools/(audit/elf_visibility/smoke/build_delivery_manifest) 完整基线
- legacy_docker_packager/: protected 形态参考
- crypto/client/: plantai_core.py(AES-GCM 原语) + install_plantai.sh 参考
- secrets/provision 严格排除(gitignore),入 git 前已脱敏清理
- LEGACY_MAPPING.md 记录源与改造方向

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 12:59:29 +08:00

188 lines
7.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 阶段 F(供应商侧):备份三个核心知识库数据,打包发给客户。
# 你的一千多篇文章存在三个地方:
# 1. rag_kb_store/ ← 原文文件
# 2. Qdrant ← 向量索引(语义搜索用)
# 3. Neo4j ← 知识图谱(实体关系用)
#
# 客户侧恢复请使用 client/restore_data.sh。
set -euo pipefail
umask 077
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
[ -f "$SCRIPT_DIR/server.env" ] && . "$SCRIPT_DIR/server.env"
TEST_ROOT="${TEST_ROOT:-$(cd "$SCRIPT_DIR/../.." && pwd)}"
SERVER_ROOT="${SERVER_ROOT:-$TEST_ROOT/server}"
VERSION="${VERSION:-1.0.0}"
OUT_DIR="${OUT_DIR:-$SCRIPT_DIR/out/$VERSION}"
usage() {
cat >&2 <<EOF
用法: $(basename "$0") [选项]
备份三个核心知识库数据,发给客户。
必要参数:
--rag-kb-dir PATH rag_kb_store 所在目录(默认: \$SERVER_ROOT/PlantAI_compiled)
→ 你的一千多篇原文文件
Qdrant 参数:
--qdrant-url URL Qdrant HTTP 地址(默认: http://127.0.0.1:6333)
Neo4j 参数:
--neo4j-container NAME Neo4j 容器名(默认: neo4j-gene-family)
--neo4j-version VER Neo4j 镜像版本(默认: 5.15.0-community)
跳过选项:
--skip-rag-kb 跳过文件知识库
--skip-qdrant 跳过 Qdrant
--skip-neo4j 跳过 Neo4j
其他:
-h, --help 显示此帮助
EOF
exit 1
}
RAG_KB_DIR="${RAG_KB_DIR:-$SERVER_ROOT/PlantAI_compiled}"
QDRANT_URL="${QDRANT_URL:-http://127.0.0.1:6333}"
NEO4J_CONTAINER="${NEO4J_CONTAINER:-neo4j-gene-family}"
NEO4J_VERSION="${NEO4J_VERSION:-5.15.0-community}"
SKIP_RAG_KB=false
SKIP_QDRANT=false
SKIP_NEO4J=false
while [ $# -gt 0 ]; do
case "$1" in
--rag-kb-dir) RAG_KB_DIR="$2"; shift 2 ;;
--qdrant-url) QDRANT_URL="$2"; shift 2 ;;
--neo4j-container) NEO4J_CONTAINER="$2"; shift 2 ;;
--neo4j-version) NEO4J_VERSION="$2"; shift 2 ;;
--skip-rag-kb) SKIP_RAG_KB=true; shift ;;
--skip-qdrant) SKIP_QDRANT=true; shift ;;
--skip-neo4j) SKIP_NEO4J=true; shift ;;
-h|--help) usage ;;
*) usage ;;
esac
done
mkdir -p "$OUT_DIR"
have_cmd() { command -v "$1" >/dev/null 2>&1; }
echo "=============================================="
echo " 供应商侧 - 知识库迁移打包"
echo " 版本: $VERSION"
echo " 输出目录: $OUT_DIR"
echo ""
echo " 备份内容(你的一千篇文章的三种形态):"
echo " 1. rag_kb_store/ ← 原文文件"
echo " 2. Qdrant 快照 ← 向量索引(语义搜索)"
echo " 3. Neo4j dump ← 知识图谱(实体关系)"
echo "=============================================="
# ============================================================
# 1. rag_kb_store — 原始文章文件
# ============================================================
if [ "$SKIP_RAG_KB" = false ]; then
if [ -d "$RAG_KB_DIR/rag_kb_store" ]; then
echo "[1/3] 打包文件知识库 rag_kb_store(原文文件)"
tar --xattrs --acls -czf "$OUT_DIR/knowledge-$VERSION.tar.gz" \
-C "$RAG_KB_DIR" rag_kb_store
echo " -> 大小: $(du -h "$OUT_DIR/knowledge-$VERSION.tar.gz" | cut -f1)"
else
echo "[1/3] 错误: $RAG_KB_DIR/rag_kb_store 不存在,请指定 --rag-kb-dir"
exit 1
fi
fi
# ============================================================
# 2. Qdrant — 向量索引(文章段落的数学指纹)
# ============================================================
if [ "$SKIP_QDRANT" = false ]; then
echo "[2/3] Qdrant 向量库快照"
if have_cmd curl; then
collections="$(curl -sf "$QDRANT_URL/collections" | python3 -c "
import json,sys
data=json.load(sys.stdin)
cols=data.get('result',data.get('collections',[]))
for c in cols:
print(c.get('name',c))
" 2>/dev/null)" || collections=""
if [ -n "$collections" ]; then
mkdir -p "$OUT_DIR/qdrant-snapshots/$VERSION"
while IFS= read -r col; do
[ -z "$col" ] && continue
echo " -> 创建集合 '$col' 快照"
curl -sf -X POST "$QDRANT_URL/collections/$col/snapshots" >/dev/null && sleep 2
snaps="$(curl -sf "$QDRANT_URL/collections/$col/snapshots" | python3 -c "
import json,sys
data=json.load(sys.stdin)
for s in data.get('result',[]):
print(s.get('name',''))
" 2>/dev/null)" || snaps=""
for snap in $snaps; do
snap_path="$("${PLANTAI_PYTHON:-python3}" -c "
import json,sys
data=json.load(sys.stdin)
for s in data.get('result',[]):
if s.get('name') == '$snap':
print(s.get('path',''))
" 2>/dev/null <<< "$(curl -sf "$QDRANT_URL/collections/$col/snapshots")")" || true
if [ -n "$snap_path" ] && [ -f "$snap_path" ]; then
cp "$snap_path" "$OUT_DIR/qdrant-snapshots/$VERSION/${col}__${snap}"
echo " 已保存: ${col}__${snap}"
fi
done
done <<< "$collections"
echo " -> 快照总大小: $(du -sh "$OUT_DIR/qdrant-snapshots/$VERSION" | cut -f1)"
else
echo " -> Qdrant 无响应或无集合,跳过"
fi
fi
fi
# ============================================================
# 3. Neo4j — 知识图谱(文章之间的实体关系网络)
# ============================================================
if [ "$SKIP_NEO4J" = false ]; then
echo "[3/3] Neo4j 图数据库 dump"
if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "$NEO4J_CONTAINER"; then
echo " -> 停止容器 $NEO4J_CONTAINER"
docker stop "$NEO4J_CONTAINER"
NEO4J_DATA_DIR="$(docker inspect "$NEO4J_CONTAINER" --format '{{range .Mounts}}{{if eq .Destination "/data"}}{{.Source}}{{end}}{{end}}' 2>/dev/null)" || true
if [ -n "$NEO4J_DATA_DIR" ] && [ -d "$NEO4J_DATA_DIR" ]; then
mkdir -p "$OUT_DIR/neo4j-backup"
echo " -> 执行 neo4j-admin database dump"
docker run --rm \
-v "${NEO4J_DATA_DIR}:/data" \
-v "$OUT_DIR/neo4j-backup:/backups" \
"neo4j:${NEO4J_VERSION}" \
neo4j-admin database dump neo4j --to-path=/backups --overwrite-destination=true
echo " -> dump 文件: $(ls -lh "$OUT_DIR/neo4j-backup/")"
fi
echo " -> 重启容器 $NEO4J_CONTAINER"
docker start "$NEO4J_CONTAINER"
else
echo " -> 未运行 Neo4j 容器,跳过"
fi
fi
echo ""
echo "=============================================="
echo " 打包完成!发给客户的产物:"
echo " ┌────────────────────────────────────────────┐"
echo " │ 1. knowledge-$VERSION.tar.gz ← 原文文件 │"
ls -lh "$OUT_DIR/knowledge-$VERSION.tar.gz" 2>/dev/null || echo " │ (未打包)"
echo " │ 2. qdrant-snapshots/ ← 向量索引 │"
ls -lh "$OUT_DIR/qdrant-snapshots/$VERSION/" 2>/dev/null | head -3 || echo " │ (未打包)"
echo " │ 3. neo4j-backup/ ← 知识图谱 │"
ls -lh "$OUT_DIR/neo4j-backup/" 2>/dev/null | head -3 || echo " │ (未打包)"
echo " └────────────────────────────────────────────┘"
echo ""
echo " 客户机上执行 client/restore_data.sh 恢复。"
echo " 另外还需要发给客户的(跟知识库无关):"
echo " - plantai-rag-code-<VERSION>.tar.gz (代码包)"
echo " - plantai-provision-<DEVICE>.tar.gz (授权文件)"
echo "=============================================="