chore(deploy): 向量化本地模型(Ollama+bge-m3)纳入部署脚本

- deploy/ollama_restart.sh(新): Ollama 幂等拉起+嵌入模型校验,二进制多候选
  探测(零硬编码),模型缺失只告警不阻断;start_all.sh 在四服务前先拉起
- vstore/vstore_restart.sh(新): 部署树与安装包共用版(路径从脚本位置推导,
  零硬编码),替换部署树旧硬编码脚本(实测重启后 210 文档+210 chunks 完整)
- build_all.sh: 组装段纳入 vstore 明文源码+启动脚本+env 模板;start_all.sh
  heredoc 增加 Ollama 拉起段——安装包自此包含向量化环节

实测: ollama_restart.sh 幂等(已运行跳过,bge-m3 就绪);vstore 新脚本重启
UP(210/210);bash -n 全过。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 00:46:31 +08:00
co-authored by Claude Fable 5
parent 5931ddca5e
commit dbe2037116
3 changed files with 100 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
# ollama_restart.sh —— 向量化本地模型服务(Ollama + bge-m3 嵌入)幂等拉起
# 用途:部署树与安装包共用;start_all.sh 在启动各服务前调用。
# 零硬编码:Ollama 二进制多候选探测(PATH → /usr/local/bin/ollama → ~/ollama/bin/ollama → $OLLAMA_BIN)。
# 行为:已监听 11434 则直接校验模型并返回;未起才拉起(setsid 脱离,日志 /tmp/plantai-ollama.log)。
# 用法: bash ollama_restart.sh [embed-model]
set -uo pipefail
MODEL="${1:-${VSTORE_EMBED_MODEL:-bge-m3:567m}}"
PORT="${OLLAMA_PORT:-11434}"
OLLAMA_BIN="${OLLAMA_BIN:-}"
find_ollama() {
for cand in "$OLLAMA_BIN" /usr/local/bin/ollama "$HOME/ollama/bin/ollama"; do
[ -n "$cand" ] && [ -x "$cand" ] && { echo "$cand"; return 0; }
done
command -v ollama 2>/dev/null || true
}
OLLAMA_BIN="$(find_ollama)"
if [ -z "$OLLAMA_BIN" ]; then
echo "[ollama] 未找到 Ollama 二进制(/usr/local/bin/ollama 或 ~/ollama/bin/ollama),向量化将不可用" >&2
echo "[ollama] 安装:https://ollama.com/download/linux,然后 ollama pull $MODEL" >&2
exit 2
fi
if curl -s --max-time 2 "http://127.0.0.1:$PORT/api/tags" >/dev/null 2>&1; then
echo "[ollama] 已在运行($OLLAMA_BIN,端口 $PORT),跳过拉起"
else
echo "[ollama] 拉起本地模型服务($OLLAMA_BIN)"
setsid "$OLLAMA_BIN" serve > /tmp/plantai-ollama.log 2>&1 < /dev/null &
disown
for _ in $(seq 1 30); do
sleep 1
curl -s --max-time 2 "http://127.0.0.1:$PORT/api/tags" >/dev/null 2>&1 && break
done
fi
# 嵌入模型校验(向量化必需:bge-m3;缺失给出拉取命令,不阻断其他服务启动)
if curl -s --max-time 5 "http://127.0.0.1:$PORT/api/tags" | grep -q "\"name\":\"$MODEL\""; then
echo "[ollama] 嵌入模型 $MODEL 就绪"
else
echo "[ollama] 警告:嵌入模型 $MODEL 未安装,向量化/私有资料检索将降级" >&2
echo "[ollama] 安装命令:$OLLAMA_BIN pull $MODEL" >&2
fi
+11
View File
@@ -88,6 +88,15 @@ cp -r "$PROJECT_ROOT/ui/dist" "$RELEASE_ROOT/ui/dist"
cp "$PROJECT_ROOT/agent/qa/scripts/"*.sh "$RELEASE_ROOT/qa/scripts/" 2>/dev/null || true
cp "$PROJECT_ROOT/agent/methodology/scripts/"*.sh "$RELEASE_ROOT/methodology/scripts/" 2>/dev/null || true
cp "$PROJECT_ROOT/agent/legacy-rag/scripts/"*.sh "$RELEASE_ROOT/legacy-rag/scripts/" 2>/dev/null || true
# 向量化环节(本地模型):vstore 明文源码 + 启动脚本 + Ollama 拉起脚本
cp -r "$PROJECT_ROOT/vstore" "$RELEASE_ROOT/vstore"
rm -rf "$RELEASE_ROOT/vstore/tests" "$RELEASE_ROOT/vstore/__pycache__"
cp "$PROJECT_ROOT/vstore/vstore_restart.sh" "$RELEASE_ROOT/vstore_restart.sh"
cp "$PROJECT_ROOT/deploy/ollama_restart.sh" "$RELEASE_ROOT/ollama_restart.sh"
# env 模板(VSTORE_ROOT/KEY/EMBED 等;真实值不入包)
cp "$PROJECT_ROOT/vstore/.env.example" "$RELEASE_ROOT/vstore/.env.example" 2>/dev/null || true
# env 模板
for t in qa methodology legacy-rag; do
cp "$PROJECT_ROOT/agent/$t/env/prod.env.example" "$RELEASE_ROOT/$t/env/prod.env.example" 2>/dev/null || true
@@ -104,6 +113,8 @@ set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BIND="${1:-0.0.0.0}"
echo "== 启动 PlantAI-rag-new 四服务 =="
# 向量化本地模型(bge-m3 嵌入):先拉起 Ollama(已运行则跳过),模型缺失只告警不阻断
bash "$ROOT/ollama_restart.sh" 2>/dev/null || echo "[ollama] 拉起失败,向量化降级(不阻断其余服务)"
bash "$ROOT/qa/scripts/start.sh" 8091 || true
bash "$ROOT/methodology/scripts/start.sh" 8092 || true
bash "$ROOT/legacy-rag/scripts/start.sh" 8093 app || true
+44
View File
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
# vstore_restart.sh —— 向量库服务(8094)幂等重启(部署树与安装包共用,路径从脚本位置推导)
# 用法: bash vstore_restart.sh [python] [port]
# 说明: vstore 是包(部署根/vstore 目录),uvicorn 必须从父目录 -m vstore.api:app,
# cd 进 vstore/ 会导致 ModuleNotFoundError(先例注释保留)。
# 零硬编码:venv/python/数据根全部环境变量或脚本位置推导。
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # .../vstore
ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" # 部署根
PYTHON="${1:-${PLANTAI_PYTHON:-$ROOT/venv/bin/python}}"
PORT="${2:-${VSTORE_PORT:-8094}}"
HOST="${VSTORE_BIND_HOST:-127.0.0.1}"
[ -x "$PYTHON" ] || PYTHON="$(command -v python3 2>/dev/null || true)"
[ -n "$PYTHON" ] && [ -x "$PYTHON" ] || { echo "[vstore] Python 不可执行,请指定: vstore_restart.sh <python>" >&2; exit 2; }
# 杀旧进程([v]store 正则技巧防 pkill 自匹配;端口优先精确)
if command -v lsof >/dev/null 2>&1; then
OLD_PID="$(lsof -ti tcp:"$PORT" 2>/dev/null || true)"
[ -n "$OLD_PID" ] && kill "$OLD_PID" 2>/dev/null || true
else
pkill -f "[v]store.api:app" 2>/dev/null || true
fi
sleep 2
cd "$ROOT"
set -a
[ -f "$SCRIPT_DIR/.env" ] && source "$SCRIPT_DIR/.env"
set +a
setsid "$PYTHON" -m uvicorn vstore.api:app --host "$HOST" --port "$PORT" \
> /tmp/plantai-vstore.log 2>&1 < /dev/null &
disown
sleep 8
if curl -s --max-time 5 "http://127.0.0.1:$PORT/api/vstore/health" | grep -q '"ok"'; then
echo "VSTORE UP ($HOST:$PORT)"
curl -s --max-time 5 "http://127.0.0.1:$PORT/api/vstore/health"
echo
else
echo "VSTORE FAIL —— 日志尾部:" >&2
tail -20 /tmp/plantai-vstore.log >&2 || true
exit 1
fi