File size: 3,877 Bytes
b6c412f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/bin/bash
# ============================================================
# VetCopilot DAPT v3.1 一键部署脚本
# 适用:GPU 服务器 (A100/RTX 40x0)
# ============================================================
set -e

echo "============================================"
echo "  VetCopilot DAPT v3.1 部署"
echo "  引擎: Qwen2.5-3B DAPT + LCPS 2.0 + FAISS RAG"
echo "  $(date)"
echo "============================================"

# ─── 配置 ───
MODEL_PATH="${VET_MODEL:-./vet-qwen3b-v3-dapt}"
PORT_AI="${AI_PORT:-8000}"
PORT_APP="${APP_PORT:-8080}"
KB_DIR="${KB_DIR:-./knowledge_base_simple}"

echo ""
echo "[0/4] 检查环境..."
python -c "import torch; print(f'  CUDA: {torch.cuda.is_available()}'); print(f'  GPU: {torch.cuda.get_device_name(0) if torch.cuda.is_available() else \"N/A\"}')" || {
    echo "[错误] PyTorch CUDA 不可用"
    exit 1
}

# ─── 1. 下载 DAPT 模型(如果不存在)───
echo ""
echo "[1/4] 准备 DAPT 模型..."
if [ ! -f "$MODEL_PATH/config.json" ]; then
    echo "  模型不存在,从 ModelScope 下载..."
    pip install modelscope -q
    python -c "
from modelscope.hub.snapshot_download import snapshot_download
snapshot_download('WWSCA123/vet-qwen3b-v3-dapt-inference', local_dir='./vet-qwen3b-v3-dapt')
"
    # 补全 tokenizer(从 HF mirror)
    python -c "
from huggingface_hub import snapshot_download
import os, shutil
tokenizer_dir = snapshot_download('Qwen/Qwen2.5-3B-Instruct', allow_patterns=['tokenizer*', 'vocab*', 'merges*', 'generation_config*', 'special_tokens*'], local_dir='./_tokenizer_tmp')
for f in os.listdir(tokenizer_dir):
    src = os.path.join(tokenizer_dir, f)
    dst = os.path.join('$MODEL_PATH', f)
    if not os.path.exists(dst):
        shutil.copy(src, dst)
rm -rf ./_tokenizer_tmp
echo '  模型准备完成'
"
else
    echo "  模型已存在: $MODEL_PATH"
fi

# ─── 2. 安装依赖 ───
echo ""
echo "[2/4] 安装 Python 依赖..."
pip install -r vetnetv2.0/requirements_gpu.txt -q 2>/dev/null || {
    pip install torch transformers accelerate fastapi uvicorn sentence-transformers faiss-gpu -q
}
pip install -r vetcopilot-backend/requirements.txt -q 2>/dev/null || true
echo "  依赖安装完成"

# ─── 3. 启动 DAPT 推理服务 ───
echo ""
echo "[3/4] 启动 DAPT 推理服务 (端口 $PORT_AI)..."
cd vetnetv2.0
nohup python server_gpu.py > ../logs/ai_server.log 2>&1 &
AI_PID=$!
echo "  PID: $AI_PID"

# 等待推理服务就绪
echo "  等待推理服务就绪..."
for i in $(seq 1 60); do
    if curl -s http://localhost:$PORT_AI/health | grep -q '"status":"ok"'; then
        echo "  推理服务就绪"
        break
    fi
    if [ $i -eq 60 ]; then
        echo "  [警告] 推理服务启动超时,检查日志: logs/ai_server.log"
    fi
    sleep 5
done
cd ..

# ─── 4. 启动 VetCopilot 应用 ───
echo ""
echo "[4/4] 启动 VetCopilot 应用 (端口 $PORT_APP)..."
cd vetcopilot-backend
nohup python -m uvicorn app.main:app --host 0.0.0.0 --port $PORT_APP > ../logs/app_server.log 2>&1 &
APP_PID=$!
echo "  PID: $APP_PID"

# ─── 完成 ───
echo ""
echo "============================================"
echo "  部署完成!"
echo ""
echo "  DAPT 推理服务: http://localhost:$PORT_AI"
echo "    - 健康检查: GET /health"
echo "    - LCPS 诊断: POST /api/v1/diagnose"
echo "    - 自由问答: POST /chat"
echo ""
echo "  VetCopilot 应用: http://localhost:$PORT_APP"
echo "    - 前端: http://localhost:$PORT_APP (Vite dev)"
echo "    - API:  http://localhost:$PORT_APP/api"
echo ""
echo "  进程 ID:"
echo "    推理服务: $AI_PID"
echo "    应用服务: $APP_PID"
echo ""
echo "  停止服务: kill $AI_PID $APP_PID"
echo "  查看日志: tail -f logs/ai_server.log"
echo "           tail -f logs/app_server.log"
echo "============================================"