184 lines
7.8 KiB
Bash
184 lines
7.8 KiB
Bash
|
|
#!/usr/bin/env bash
|
|||
|
|
# ══════════════════════════════════════════════════
|
|||
|
|
# 07_smoke_test.sh
|
|||
|
|
# 端到端冒烟测试:验证三条业务闭环
|
|||
|
|
# 用法:bash scripts/07_smoke_test.sh
|
|||
|
|
# ══════════════════════════════════════════════════
|
|||
|
|
set -euo pipefail
|
|||
|
|
|
|||
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||
|
|
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
|
|||
|
|
cd "$PROJECT_DIR"
|
|||
|
|
|
|||
|
|
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; BLUE='\033[0;34m'; NC='\033[0m'
|
|||
|
|
info() { echo -e "${BLUE}[INFO]${NC} $*"; }
|
|||
|
|
ok() { echo -e "${GREEN}[✓]${NC} $*"; }
|
|||
|
|
fail() { echo -e "${RED}[✗]${NC} $*"; FAILED=$((FAILED+1)); }
|
|||
|
|
warn() { echo -e "${YELLOW}[~]${NC} $*"; }
|
|||
|
|
|
|||
|
|
FAILED=0
|
|||
|
|
API_BASE="http://localhost"
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo -e "${BLUE}══════════════════════════════════════════${NC}"
|
|||
|
|
echo -e "${BLUE} AI合规智能中枢 端到端冒烟测试${NC}"
|
|||
|
|
echo -e "${BLUE}══════════════════════════════════════════${NC}"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# ── 基础健康检查 ────────────────────────────────
|
|||
|
|
info "=== 基础设施健康检查 ==="
|
|||
|
|
|
|||
|
|
check_service() {
|
|||
|
|
local name=$1; local url=$2
|
|||
|
|
if curl -sf "$url" > /dev/null 2>&1; then
|
|||
|
|
ok "$name"
|
|||
|
|
else
|
|||
|
|
fail "$name($url 不可达)"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
check_service "API 网关 (Nginx)" "http://localhost/health"
|
|||
|
|
check_service "业务后端 (FastAPI)" "http://localhost:8000/health"
|
|||
|
|
check_service "嵌入服务 (BGE-M3)" "http://localhost:8010/health"
|
|||
|
|
check_service "解析服务 (MinerU)" "http://localhost:8011/health"
|
|||
|
|
check_service "Milvus HTTP" "http://localhost:9091/healthz"
|
|||
|
|
check_service "Neo4j Browser" "http://localhost:7474"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# ── 嵌入服务测试 ────────────────────────────────
|
|||
|
|
info "=== 嵌入服务测试 ==="
|
|||
|
|
EMBED_RESP=$(curl -sf -X POST http://localhost:8010/embed \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{"texts": ["GB 18384 电动汽车碰撞安全要求"], "batch_size": 1}' 2>/dev/null || echo "{}")
|
|||
|
|
|
|||
|
|
if echo "$EMBED_RESP" | python3 -c "import sys,json; d=json.load(sys.stdin); assert len(d.get('dense',[])[0])==1024" 2>/dev/null; then
|
|||
|
|
ok "BGE-M3 嵌入:返回 1024 维向量"
|
|||
|
|
else
|
|||
|
|
fail "BGE-M3 嵌入失败,响应:${EMBED_RESP:0:200}"
|
|||
|
|
fi
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# ── 创建测试 PDF ────────────────────────────────
|
|||
|
|
info "=== 创建测试文档 ==="
|
|||
|
|
TEST_PDF="$PROJECT_DIR/data/uploads/test_regulation.txt"
|
|||
|
|
cat > "$TEST_PDF" << 'EOF'
|
|||
|
|
GB 18384-2020 电动汽车安全要求
|
|||
|
|
|
|||
|
|
第一章 总则
|
|||
|
|
本标准规定了电动汽车的安全要求,适用于M1类纯电动汽车。
|
|||
|
|
|
|||
|
|
第二章 电气安全
|
|||
|
|
2.1 绝缘电阻要求
|
|||
|
|
直流电路绝缘电阻不得低于100Ω/V。
|
|||
|
|
2.2 碰撞安全
|
|||
|
|
车辆碰撞后,高压电系统应自动断电。
|
|||
|
|
碰撞后5秒内,高压系统电压应降至60V以下。
|
|||
|
|
|
|||
|
|
第三章 防水要求
|
|||
|
|
高压系统防护等级应达到IP67。
|
|||
|
|
EOF
|
|||
|
|
ok "测试文档创建:$TEST_PDF"
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# ── 闭环①:文件上传 → 向量化 → 问答 ───────────
|
|||
|
|
info "=== 闭环①:法规入库 → 检索问答 ==="
|
|||
|
|
|
|||
|
|
# 创建工作空间
|
|||
|
|
WORKSPACE_RESP=$(curl -sf -X POST "$API_BASE/api/kb/workspaces" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{"name": "测试法规库", "domain": "vehicle_safety"}' 2>/dev/null || echo "{}")
|
|||
|
|
WS_ID=$(echo "$WORKSPACE_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || echo "")
|
|||
|
|
|
|||
|
|
if [[ -n "$WS_ID" ]]; then
|
|||
|
|
ok "工作空间创建:$WS_ID"
|
|||
|
|
else
|
|||
|
|
warn "工作空间创建失败(可能接口未完全实现),跳过后续上传测试"
|
|||
|
|
WS_ID="test-workspace"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# 上传文件
|
|||
|
|
UPLOAD_RESP=$(curl -sf -X POST "$API_BASE/api/kb/files/upload" \
|
|||
|
|
-F "file=@$TEST_PDF" \
|
|||
|
|
-F "workspace_id=$WS_ID" 2>/dev/null || echo "{}")
|
|||
|
|
TASK_ID=$(echo "$UPLOAD_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('task_id',''))" 2>/dev/null || echo "")
|
|||
|
|
|
|||
|
|
if [[ -n "$TASK_ID" ]]; then
|
|||
|
|
ok "文件上传任务已创建:$TASK_ID"
|
|||
|
|
|
|||
|
|
# 轮询任务状态(最多等待120秒)
|
|||
|
|
info "等待向量化完成..."
|
|||
|
|
for i in {1..24}; do
|
|||
|
|
TASK_STATUS=$(curl -sf "$API_BASE/api/kb/tasks/$TASK_ID" 2>/dev/null | \
|
|||
|
|
python3 -c "import sys,json; print(json.load(sys.stdin).get('status','unknown'))" 2>/dev/null || echo "unknown")
|
|||
|
|
if [[ "$TASK_STATUS" == "completed" ]]; then
|
|||
|
|
ok "向量化完成(${i}×5s)"
|
|||
|
|
break
|
|||
|
|
elif [[ "$TASK_STATUS" == "failed" ]]; then
|
|||
|
|
fail "向量化失败"
|
|||
|
|
break
|
|||
|
|
fi
|
|||
|
|
echo -n "."
|
|||
|
|
sleep 5
|
|||
|
|
done
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# 检索问答
|
|||
|
|
QA_RESP=$(curl -sf -X POST "$API_BASE/api/kb/qa" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d "{\"query\": \"碰撞后高压系统电压要求\", \"workspace_id\": \"$WS_ID\", \"top_k\": 3}" 2>/dev/null || echo "{}")
|
|||
|
|
ANSWER=$(echo "$QA_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('answer','')[:100])" 2>/dev/null || echo "")
|
|||
|
|
|
|||
|
|
if [[ -n "$ANSWER" ]]; then
|
|||
|
|
ok "问答成功:${ANSWER}..."
|
|||
|
|
else
|
|||
|
|
warn "问答返回空(LLM API 可能未配置或响应缓慢)"
|
|||
|
|
fi
|
|||
|
|
else
|
|||
|
|
warn "文件上传失败(接口可能未实现)"
|
|||
|
|
fi
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# ── 闭环②:合规审查 ────────────────────────────
|
|||
|
|
info "=== 闭环②:文档上传 → 合规审查 ==="
|
|||
|
|
|
|||
|
|
CHECK_RESP=$(curl -sf -X POST "$API_BASE/api/compliance/check" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{"query": "供应商文件是否符合GB 18384碰撞安全要求", "domains": ["vehicle_safety"]}' 2>/dev/null || echo "{}")
|
|||
|
|
RISK=$(echo "$CHECK_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('risk_level','unknown'))" 2>/dev/null || echo "unknown")
|
|||
|
|
|
|||
|
|
if [[ "$RISK" != "unknown" && -n "$RISK" ]]; then
|
|||
|
|
ok "合规审查完成,风险等级:$RISK"
|
|||
|
|
else
|
|||
|
|
warn "合规审查接口返回空(功能可能未完全实现)"
|
|||
|
|
fi
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# ── 闭环③:法规监控 ────────────────────────────
|
|||
|
|
info "=== 闭环③:法规监控源配置 ==="
|
|||
|
|
|
|||
|
|
SOURCE_RESP=$(curl -sf -X POST "$API_BASE/api/regulation/sources" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{"name": "测试监控源", "url": "https://std.samr.gov.cn", "domain": "vehicle_safety"}' 2>/dev/null || echo "{}")
|
|||
|
|
SOURCE_ID=$(echo "$SOURCE_RESP" | python3 -c "import sys,json; print(json.load(sys.stdin).get('id',''))" 2>/dev/null || echo "")
|
|||
|
|
|
|||
|
|
if [[ -n "$SOURCE_ID" ]]; then
|
|||
|
|
ok "监控源配置成功:$SOURCE_ID"
|
|||
|
|
else
|
|||
|
|
warn "监控源配置返回空(功能可能未完全实现)"
|
|||
|
|
fi
|
|||
|
|
echo ""
|
|||
|
|
|
|||
|
|
# ── 汇总 ────────────────────────────────────────
|
|||
|
|
echo ""
|
|||
|
|
echo -e "${BLUE}══════════════════════════════════════════${NC}"
|
|||
|
|
if [[ $FAILED -eq 0 ]]; then
|
|||
|
|
echo -e "${GREEN} 全部检查通过!${NC}"
|
|||
|
|
else
|
|||
|
|
echo -e "${YELLOW} 完成,${FAILED} 项失败${NC}(部分功能可能尚未实现)"
|
|||
|
|
fi
|
|||
|
|
echo -e "${BLUE}══════════════════════════════════════════${NC}"
|
|||
|
|
echo ""
|
|||
|
|
echo "查看服务日志:"
|
|||
|
|
echo " docker compose logs -f compliance-backend"
|
|||
|
|
echo " docker compose logs -f celery-worker"
|