386 lines
12 KiB
Bash
Executable File
386 lines
12 KiB
Bash
Executable File
#!/bin/bash
|
||
# =============================================================================
|
||
# AI Agent 启动与管理脚本
|
||
# 用法: ./start.sh [check|backend|frontend|both|docker-up|docker-down]
|
||
# =============================================================================
|
||
|
||
set -e
|
||
|
||
# 颜色定义
|
||
GREEN='\033[0;32m'
|
||
BLUE='\033[0;34m'
|
||
RED='\033[0;31m'
|
||
YELLOW='\033[1;33m'
|
||
NC='\033[0m' # No Color
|
||
|
||
# 项目根目录
|
||
PROJECT_DIR="/home/huang/Study/AIProject/Agent1"
|
||
|
||
echo -e "${BLUE}========================================${NC}"
|
||
echo -e "${BLUE} AI Agent - 个人生活助手${NC}"
|
||
echo -e "${BLUE}========================================${NC}"
|
||
echo ""
|
||
|
||
# =============================================================================
|
||
# 配置检查函数
|
||
# =============================================================================
|
||
check_config() {
|
||
echo -e "${BLUE}📋 开始环境配置检查...${NC}"
|
||
echo ""
|
||
|
||
PASS=0
|
||
FAIL=0
|
||
WARN=0
|
||
|
||
# 辅助函数
|
||
check_pass() {
|
||
echo -e "${GREEN}✓${NC} $1"
|
||
((PASS++))
|
||
}
|
||
|
||
check_fail() {
|
||
echo -e "${RED}✗${NC} $1"
|
||
((FAIL++))
|
||
}
|
||
|
||
check_warn() {
|
||
echo -e "${YELLOW}⚠${NC} $1"
|
||
((WARN++))
|
||
}
|
||
|
||
# 1. 检查 .env 文件
|
||
echo "🔍 检查配置文件..."
|
||
if [ -f "$PROJECT_DIR/.env" ]; then
|
||
check_pass ".env 文件存在"
|
||
|
||
# 检查文件格式
|
||
if grep -q "^EOF" .env 2>/dev/null; then
|
||
check_fail ".env 文件格式错误:发现多余的 EOF 标记"
|
||
else
|
||
check_pass ".env 文件格式正确"
|
||
fi
|
||
else
|
||
check_fail ".env 文件不存在"
|
||
echo " 提示: 请创建 .env 文件并配置环境变量"
|
||
return 1
|
||
fi
|
||
|
||
# 2. 检查必需的环境变量
|
||
echo ""
|
||
echo "🔑 检查环境变量..."
|
||
|
||
# 检查 ZHIPUAI_API_KEY
|
||
if grep -q "^ZHIPUAI_API_KEY=" "$PROJECT_DIR/.env" 2>/dev/null; then
|
||
API_KEY=$(grep "^ZHIPUAI_API_KEY=" "$PROJECT_DIR/.env" | head -1 | cut -d'=' -f2- | tr -d '[:space:]')
|
||
if [ ${#API_KEY} -gt 10 ]; then
|
||
check_pass "ZHIPUAI_API_KEY 已配置(长度: ${#API_KEY})"
|
||
else
|
||
check_fail "ZHIPUAI_API_KEY 配置可能无效(过短)"
|
||
fi
|
||
else
|
||
check_fail "ZHIPUAI_API_KEY 未配置或格式错误"
|
||
fi
|
||
|
||
# 检查 VLLM_LOCAL_KEY
|
||
if grep -q "^VLLM_LOCAL_KEY=" "$PROJECT_DIR/.env" 2>/dev/null; then
|
||
check_pass "VLLM_LOCAL_KEY 已配置"
|
||
else
|
||
check_warn "VLLM_LOCAL_KEY 未配置(如不使用本地模型可忽略)"
|
||
fi
|
||
|
||
# 检查 DB_URI
|
||
if grep -q "^DB_URI=" "$PROJECT_DIR/.env" 2>/dev/null; then
|
||
check_pass "DB_URI 已配置"
|
||
else
|
||
check_warn "DB_URI 未配置(将使用默认值)"
|
||
fi
|
||
|
||
# 3. 检查 Docker 环境
|
||
echo ""
|
||
echo "🐳 检查 Docker 环境..."
|
||
|
||
if command -v docker &> /dev/null; then
|
||
check_pass "Docker 已安装"
|
||
|
||
if docker info &> /dev/null; then
|
||
check_pass "Docker 守护进程正在运行"
|
||
else
|
||
check_fail "Docker 守护进程未运行"
|
||
echo " 提示: sudo systemctl start docker"
|
||
fi
|
||
else
|
||
check_fail "Docker 未安装"
|
||
fi
|
||
|
||
if command -v docker compose version &> /dev/null || command -v docker-compose &> /dev/null; then
|
||
check_pass "Docker Compose 已安装"
|
||
else
|
||
check_fail "Docker Compose 未安装"
|
||
fi
|
||
|
||
# 4. 检查端口占用
|
||
echo ""
|
||
echo "🔌 检查端口占用..."
|
||
|
||
for port in 8001 8501; do
|
||
if lsof -i :$port &> /dev/null; then
|
||
check_warn "端口 $port 已被占用"
|
||
else
|
||
check_pass "端口 $port 可用"
|
||
fi
|
||
done
|
||
|
||
# 总结
|
||
echo ""
|
||
echo "=========================================="
|
||
echo " 检查结果汇总"
|
||
echo "=========================================="
|
||
echo -e "${GREEN}通过: $PASS${NC}"
|
||
echo -e "${RED}失败: $FAIL${NC}"
|
||
echo -e "${YELLOW}警告: $WARN${NC}"
|
||
echo ""
|
||
|
||
if [ $FAIL -eq 0 ]; then
|
||
echo -e "${GREEN}✅ 配置检查通过!${NC}"
|
||
return 0
|
||
else
|
||
echo -e "${RED}❌ 发现 $FAIL 个错误,请修复后重试${NC}"
|
||
return 1
|
||
fi
|
||
}
|
||
|
||
# =============================================================================
|
||
# Docker 容器检查函数
|
||
# =============================================================================
|
||
check_vllm() {
|
||
echo -e "${BLUE}🔍 检查 vLLM 容器...${NC}"
|
||
if ! docker ps --format '{{.Names}}' | grep -q "^gemma4-server$"; then
|
||
echo -e "${YELLOW}⚠️ vLLM 容器未运行${NC}"
|
||
return 1
|
||
else
|
||
echo -e "${GREEN}✓ vLLM 容器正在运行 (gemma4-server)${NC}"
|
||
return 0
|
||
fi
|
||
}
|
||
|
||
check_postgres() {
|
||
echo -e "${BLUE}🔍 检查 PostgreSQL 容器...${NC}"
|
||
if ! docker ps --format '{{.Names}}' | grep -q "^postgres-langgraph$"; then
|
||
echo -e "${YELLOW}⚠️ PostgreSQL 容器未运行${NC}"
|
||
return 1
|
||
else
|
||
echo -e "${GREEN}✓ PostgreSQL 容器正在运行 (postgres-langgraph)${NC}"
|
||
return 0
|
||
fi
|
||
}
|
||
|
||
# =============================================================================
|
||
# 启动 Docker 依赖服务
|
||
# =============================================================================
|
||
start_vllm() {
|
||
echo -e "${BLUE}🚀 启动 vLLM 容器...${NC}"
|
||
|
||
# 检查模型文件
|
||
if [ ! -d "/home/huang/Study/AIModel/gemma-4-E2B-it" ]; then
|
||
echo -e "${RED}✗ 错误:模型目录不存在: /home/huang/Study/AIModel/gemma-4-E2B-it${NC}"
|
||
exit 1
|
||
fi
|
||
|
||
docker run -d \
|
||
--name gemma4-server \
|
||
--group-add=video \
|
||
--cap-add=SYS_PTRACE \
|
||
--security-opt seccomp=unconfined \
|
||
--device=/dev/kfd \
|
||
--device=/dev/dri \
|
||
-v /home/huang/Study/AIModel/gemma-4-E2B-it:/models/gemma-4-E2B-it \
|
||
-e VLLM_ROCM_USE_AITER=0 \
|
||
-e HF_TOKEN="${HF_TOKEN:-}" \
|
||
-p 8000:8000 \
|
||
--ipc=host \
|
||
--entrypoint vllm \
|
||
my-vllm-gemma4:working \
|
||
serve /models/gemma-4-E2B-it \
|
||
--served-model-name gemma-4-E2B-it \
|
||
--dtype auto \
|
||
--api-key token-abc123 \
|
||
--trust-remote-code \
|
||
--port 8000 \
|
||
--gpu-memory-utilization 0.85 \
|
||
--max-model-len 8192
|
||
|
||
echo -e "${GREEN}✓ vLLM 容器已启动${NC}"
|
||
echo -e "${YELLOW}⏳ 等待模型加载(可能需要几分钟)...${NC}"
|
||
sleep 10
|
||
}
|
||
|
||
start_postgres() {
|
||
echo -e "${BLUE}🚀 启动 PostgreSQL 容器...${NC}"
|
||
|
||
docker run -d \
|
||
--name postgres-langgraph \
|
||
-e POSTGRES_PASSWORD=mysecretpassword \
|
||
-e POSTGRES_DB=langgraph_db \
|
||
-p 5432:5432 \
|
||
-v ~/docker_volumes/postgres_data:/var/lib/postgresql/data \
|
||
postgres:16
|
||
|
||
echo -e "${GREEN}✓ PostgreSQL 容器已启动${NC}"
|
||
sleep 3
|
||
}
|
||
|
||
# =============================================================================
|
||
# 启动 Python 服务
|
||
# =============================================================================
|
||
start_backend() {
|
||
echo -e "\n${BLUE}🚀 启动后端服务 (端口 8001)...${NC}"
|
||
cd "$PROJECT_DIR"
|
||
|
||
# 加载 .env 文件中的环境变量
|
||
set -a
|
||
source .env 2>/dev/null || true
|
||
set +a
|
||
|
||
export PYTHONPATH="$PROJECT_DIR"
|
||
python app/backend.py &
|
||
BACKEND_PID=$!
|
||
echo -e "${GREEN}✓ 后端服务已启动 (PID: $BACKEND_PID)${NC}"
|
||
sleep 2
|
||
}
|
||
|
||
start_frontend() {
|
||
echo -e "\n${BLUE}🎨 启动前端界面 (端口 8501)...${NC}"
|
||
cd "$PROJECT_DIR"
|
||
|
||
# 加载 .env 文件中的环境变量
|
||
set -a
|
||
source .env 2>/dev/null || true
|
||
set +a
|
||
|
||
export PYTHONPATH="$PROJECT_DIR"
|
||
streamlit run frontend/frontend.py &
|
||
FRONTEND_PID=$!
|
||
echo -e "${GREEN}✓ 前端服务已启动 (PID: $FRONTEND_PID)${NC}"
|
||
echo -e "${GREEN}✓ 访问地址:${NC}"
|
||
echo -e " 本地开发: http://localhost:8501"
|
||
echo -e " Nginx代理: http://your-domain.com"
|
||
}
|
||
|
||
# =============================================================================
|
||
# Docker Compose 管理
|
||
# =============================================================================
|
||
docker_up() {
|
||
echo -e "${BLUE}🐳 使用 Docker Compose 启动所有服务...${NC}"
|
||
cd "$PROJECT_DIR"
|
||
|
||
# 检查 .env 文件
|
||
if [ ! -f ".env" ]; then
|
||
echo -e "${RED}✗ 错误:.env 文件不存在${NC}"
|
||
echo " 请先复制配置文件:"
|
||
echo " cp .env.docker .env # 服务器部署"
|
||
echo " 或"
|
||
echo " cp .env.local .env # 本地开发"
|
||
exit 1
|
||
fi
|
||
|
||
docker compose -f docker/docker-compose.yml up -d --build
|
||
|
||
echo -e "\n${GREEN}✓ Docker Compose 服务已启动${NC}"
|
||
echo -e "${BLUE}📊 查看服务状态:${NC} docker compose -f docker/docker-compose.yml ps"
|
||
echo -e "${BLUE}📝 查看日志:${NC} docker compose -f docker/docker-compose.yml logs -f"
|
||
echo -e "${BLUE}🌐 访问应用:${NC} http://localhost:8501"
|
||
}
|
||
|
||
docker_down() {
|
||
echo -e "${BLUE}🛑 停止 Docker Compose 服务...${NC}"
|
||
cd "$PROJECT_DIR"
|
||
docker compose -f docker/docker-compose.yml down
|
||
echo -e "${GREEN}✓ 服务已停止${NC}"
|
||
}
|
||
|
||
# =============================================================================
|
||
# 清理函数
|
||
# =============================================================================
|
||
cleanup() {
|
||
echo -e "\n${RED}🛑 正在停止 Python 服务...${NC}"
|
||
if [ ! -z "$BACKEND_PID" ]; then
|
||
kill $BACKEND_PID 2>/dev/null || true
|
||
echo -e "${GREEN}✓ 后端服务已停止${NC}"
|
||
fi
|
||
if [ ! -z "$FRONTEND_PID" ]; then
|
||
kill $FRONTEND_PID 2>/dev/null || true
|
||
echo -e "${GREEN}✓ 前端服务已停止${NC}"
|
||
fi
|
||
echo -e "${YELLOW}💡 提示:Docker 容器需要手动停止${NC}"
|
||
echo -e " 停止 vLLM: docker stop gemma4-server"
|
||
echo -e " 停止 PostgreSQL: docker stop postgres-langgraph"
|
||
echo -e " 或使用: $0 docker-down"
|
||
exit 0
|
||
}
|
||
|
||
# 捕获 Ctrl+C
|
||
trap cleanup SIGINT SIGTERM
|
||
|
||
# =============================================================================
|
||
# 主逻辑
|
||
# =============================================================================
|
||
case "${1:-help}" in
|
||
check)
|
||
check_config
|
||
;;
|
||
|
||
backend)
|
||
check_config || exit 1
|
||
check_vllm || start_vllm
|
||
check_postgres || start_postgres
|
||
start_backend
|
||
echo -e "\n${GREEN}后端服务正在运行,按 Ctrl+C 停止${NC}"
|
||
wait $BACKEND_PID
|
||
;;
|
||
|
||
frontend)
|
||
check_config || exit 1
|
||
start_frontend
|
||
echo -e "\n${GREEN}前端服务正在运行,按 Ctrl+C 停止${NC}"
|
||
wait $FRONTEND_PID
|
||
;;
|
||
|
||
both)
|
||
check_config || exit 1
|
||
check_vllm || start_vllm
|
||
check_postgres || start_postgres
|
||
start_backend
|
||
start_frontend
|
||
echo -e "\n${GREEN}所有服务正在运行,按 Ctrl+C 停止 Python 服务${NC}"
|
||
echo -e "${YELLOW}注意:Docker 容器会在后台继续运行${NC}"
|
||
wait
|
||
;;
|
||
|
||
docker-up)
|
||
check_config || exit 1
|
||
docker_up
|
||
;;
|
||
|
||
docker-down)
|
||
docker_down
|
||
;;
|
||
|
||
help|*)
|
||
echo -e "${BLUE}用法:${NC} $0 [command]"
|
||
echo ""
|
||
echo -e "${BLUE}命令:${NC}"
|
||
echo " check 检查环境配置"
|
||
echo " backend 仅启动后端服务"
|
||
echo " frontend 仅启动前端服务"
|
||
echo " both 启动前后端服务(默认)"
|
||
echo " docker-up 使用 Docker Compose 启动所有服务"
|
||
echo " docker-down 停止 Docker Compose 服务"
|
||
echo " help 显示此帮助信息"
|
||
echo ""
|
||
echo -e "${BLUE}示例:${NC}"
|
||
echo " $0 check # 检查配置"
|
||
echo " $0 both # 启动本地开发环境"
|
||
echo " $0 docker-up # 启动 Docker 部署环境"
|
||
;;
|
||
esac
|