Commit a7653f3c7e5240e3f02a50ef1d5e7a18d7cafb43
1 parent
16c42787
补充脚本
Showing
12 changed files
with
265 additions
and
973 deletions
Show diff stats
=0.1.9 deleted
| @@ -1,14 +0,0 @@ | @@ -1,14 +0,0 @@ | ||
| 1 | -Looking in indexes: https://mirrors.aliyun.com/pypi/simple | ||
| 2 | -Collecting slowapi | ||
| 3 | - Using cached https://mirrors.aliyun.com/pypi/packages/2b/bb/f71c4b7d7e7eb3fc1e8c0458a8979b912f40b58002b9fbf37729b8cb464b/slowapi-0.1.9-py3-none-any.whl (14 kB) | ||
| 4 | -Collecting limits>=2.3 (from slowapi) | ||
| 5 | - Using cached https://mirrors.aliyun.com/pypi/packages/40/96/4fcd44aed47b8fcc457653b12915fcad192cd646510ef3f29fd216f4b0ab/limits-5.6.0-py3-none-any.whl (60 kB) | ||
| 6 | -Collecting deprecated>=1.2 (from limits>=2.3->slowapi) | ||
| 7 | - Using cached https://mirrors.aliyun.com/pypi/packages/84/d0/205d54408c08b13550c733c4b85429e7ead111c7f0014309637425520a9a/deprecated-1.3.1-py2.py3-none-any.whl (11 kB) | ||
| 8 | -Requirement already satisfied: packaging>=21 in /data/tw/miniconda3/envs/searchengine/lib/python3.10/site-packages (from limits>=2.3->slowapi) (25.0) | ||
| 9 | -Requirement already satisfied: typing-extensions in /data/tw/miniconda3/envs/searchengine/lib/python3.10/site-packages (from limits>=2.3->slowapi) (4.15.0) | ||
| 10 | -Collecting wrapt<3,>=1.10 (from deprecated>=1.2->limits>=2.3->slowapi) | ||
| 11 | - Downloading https://mirrors.aliyun.com/pypi/packages/c6/93/5cf92edd99617095592af919cb81d4bff61c5dbbb70d3c92099425a8ec34/wrapt-2.0.1-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl (113 kB) | ||
| 12 | -Installing collected packages: wrapt, deprecated, limits, slowapi | ||
| 13 | - | ||
| 14 | -Successfully installed deprecated-1.3.1 limits-5.6.0 slowapi-0.1.9 wrapt-2.0.1 |
| @@ -0,0 +1,50 @@ | @@ -0,0 +1,50 @@ | ||
| 1 | +#!/bin/bash | ||
| 2 | + | ||
| 3 | +# Restart script for SearchEngine services | ||
| 4 | +# This script stops all services first, then starts them again | ||
| 5 | + | ||
| 6 | +cd "$(dirname "$0")" | ||
| 7 | + | ||
| 8 | +GREEN='\033[0;32m' | ||
| 9 | +YELLOW='\033[1;33m' | ||
| 10 | +RED='\033[0;31m' | ||
| 11 | +NC='\033[0m' | ||
| 12 | + | ||
| 13 | +echo -e "${GREEN}========================================${NC}" | ||
| 14 | +echo -e "${GREEN}SearchEngine服务重启脚本${NC}" | ||
| 15 | +echo -e "${GREEN}========================================${NC}" | ||
| 16 | + | ||
| 17 | +# Step 1: Stop all services | ||
| 18 | +echo -e "\n${YELLOW}Step 1/2: 停止现有服务${NC}" | ||
| 19 | +if [ -f "./scripts/stop.sh" ]; then | ||
| 20 | + ./scripts/stop.sh | ||
| 21 | + if [ $? -eq 0 ]; then | ||
| 22 | + echo -e "${GREEN}✓ 所有服务已成功停止${NC}" | ||
| 23 | + else | ||
| 24 | + echo -e "${YELLOW}⚠ 停止服务时出现警告,继续重启流程${NC}" | ||
| 25 | + fi | ||
| 26 | +else | ||
| 27 | + echo -e "${RED}✗ 停止脚本不存在,无法安全重启${NC}" | ||
| 28 | + exit 1 | ||
| 29 | +fi | ||
| 30 | + | ||
| 31 | +# Wait a moment for services to fully stop | ||
| 32 | +echo -e "\n${YELLOW}等待服务完全关闭...${NC}" | ||
| 33 | +sleep 3 | ||
| 34 | + | ||
| 35 | +# Step 2: Start all services | ||
| 36 | +echo -e "\n${YELLOW}Step 2/2: 重新启动服务${NC}" | ||
| 37 | +if [ -f "./run.sh" ]; then | ||
| 38 | + ./run.sh | ||
| 39 | + if [ $? -eq 0 ]; then | ||
| 40 | + echo -e "${GREEN}========================================${NC}" | ||
| 41 | + echo -e "${GREEN}服务重启完成!${NC}" | ||
| 42 | + echo -e "${GREEN}========================================${NC}" | ||
| 43 | + else | ||
| 44 | + echo -e "${RED}✗ 服务启动失败${NC}" | ||
| 45 | + exit 1 | ||
| 46 | + fi | ||
| 47 | +else | ||
| 48 | + echo -e "${RED}✗ 启动脚本不存在,无法完成重启${NC}" | ||
| 49 | + exit 1 | ||
| 50 | +fi | ||
| 0 | \ No newline at end of file | 51 | \ No newline at end of file |
start_all.sh renamed to run.sh
| 1 | #!/bin/bash | 1 | #!/bin/bash |
| 2 | 2 | ||
| 3 | -# One-click startup script for SearchEngine | ||
| 4 | -# This script starts everything you need | ||
| 5 | - | ||
| 6 | -# Don't exit on error - we want to continue even if some checks fail | ||
| 7 | -# set -e | 3 | +# Production startup script for SearchEngine services |
| 4 | +# This script starts frontend and backend services (no data ingestion) | ||
| 8 | 5 | ||
| 9 | cd "$(dirname "$0")" | 6 | cd "$(dirname "$0")" |
| 10 | 7 | ||
| @@ -14,62 +11,16 @@ RED='\033[0;31m' | @@ -14,62 +11,16 @@ RED='\033[0;31m' | ||
| 14 | NC='\033[0m' | 11 | NC='\033[0m' |
| 15 | 12 | ||
| 16 | echo -e "${GREEN}========================================${NC}" | 13 | echo -e "${GREEN}========================================${NC}" |
| 17 | -echo -e "${GREEN}SearchEngine一键启动脚本${NC}" | 14 | +echo -e "${GREEN}SearchEngine服务启动脚本${NC}" |
| 18 | echo -e "${GREEN}========================================${NC}" | 15 | echo -e "${GREEN}========================================${NC}" |
| 19 | 16 | ||
| 20 | -# Step 0: Stop existing services first | ||
| 21 | -echo -e "\n${YELLOW}Step 0/5: 停止现有服务${NC}" | ||
| 22 | -if [ -f "./scripts/stop.sh" ]; then | ||
| 23 | - ./scripts/stop.sh | ||
| 24 | - sleep 2 # Wait for services to fully stop | ||
| 25 | -else | ||
| 26 | - echo -e "${YELLOW}停止脚本不存在,手动检查端口...${NC}" | ||
| 27 | - # Kill any existing processes on our ports | ||
| 28 | - fuser -k 6002/tcp 2>/dev/null || true | ||
| 29 | - fuser -k 6003/tcp 2>/dev/null || true | ||
| 30 | - sleep 2 | ||
| 31 | -fi | ||
| 32 | - | ||
| 33 | -# Step 1: Setup environment | ||
| 34 | -echo -e "\n${YELLOW}Step 1/5: 设置环境${NC}" | ||
| 35 | -./setup.sh | ||
| 36 | - | ||
| 37 | -# Step 2: Check if data is already ingested | ||
| 38 | -echo -e "\n${YELLOW}Step 2/5: 检查数据${NC}" | ||
| 39 | -source /home/tw/miniconda3/etc/profile.d/conda.sh | ||
| 40 | -conda activate searchengine | ||
| 41 | - | ||
| 42 | -# Check if index exists | ||
| 43 | -INDEX_EXISTS=$(python -c " | ||
| 44 | -from config.env_config import get_es_config | ||
| 45 | -from utils.es_client import ESClient | ||
| 46 | -from config import ConfigLoader | ||
| 47 | - | ||
| 48 | -es_config = get_es_config() | ||
| 49 | -es_client = ESClient(hosts=[es_config['host']], username=es_config.get('username'), password=es_config.get('password')) | ||
| 50 | - | ||
| 51 | -config_loader = ConfigLoader('config/schema') | ||
| 52 | -config = config_loader.load_customer_config('customer1') | ||
| 53 | - | ||
| 54 | -if es_client.index_exists(config.es_index_name): | ||
| 55 | - doc_count = es_client.count(config.es_index_name) | ||
| 56 | - print(f'{doc_count}') | ||
| 57 | -else: | ||
| 58 | - print('0') | ||
| 59 | -" 2>/dev/null || echo "0") | ||
| 60 | - | ||
| 61 | -if [ "$INDEX_EXISTS" = "0" ]; then | ||
| 62 | - echo -e "${YELLOW}索引不存在,开始导入数据...${NC}" | ||
| 63 | - echo -e "${YELLOW}注意: 首次导入会下载模型文件,可能需要10-30分钟${NC}" | ||
| 64 | - echo -e "${YELLOW}导入1000条数据进行快速测试(跳过embedding以加快速度)${NC}" | ||
| 65 | - ./scripts/ingest.sh 1000 true | ||
| 66 | -else | ||
| 67 | - echo -e "${GREEN}数据已存在,包含 $INDEX_EXISTS 条文档${NC}" | ||
| 68 | -fi | 17 | +# Create logs directory if it doesn't exist |
| 18 | +mkdir -p logs | ||
| 69 | 19 | ||
| 70 | -# Step 3: Start backend in background | ||
| 71 | -echo -e "\n${YELLOW}Step 3/5: 启动后端服务${NC}" | 20 | +# Step 1: Start backend in background |
| 21 | +echo -e "\n${YELLOW}Step 1/2: 启动后端服务${NC}" | ||
| 72 | echo -e "${YELLOW}后端服务将在后台运行...${NC}" | 22 | echo -e "${YELLOW}后端服务将在后台运行...${NC}" |
| 23 | + | ||
| 73 | nohup ./scripts/start_backend.sh > logs/backend.log 2>&1 & | 24 | nohup ./scripts/start_backend.sh > logs/backend.log 2>&1 & |
| 74 | BACKEND_PID=$! | 25 | BACKEND_PID=$! |
| 75 | echo $BACKEND_PID > logs/backend.pid | 26 | echo $BACKEND_PID > logs/backend.pid |
| @@ -78,7 +29,7 @@ echo -e "${GREEN}日志文件: logs/backend.log${NC}" | @@ -78,7 +29,7 @@ echo -e "${GREEN}日志文件: logs/backend.log${NC}" | ||
| 78 | 29 | ||
| 79 | # Wait for backend to start | 30 | # Wait for backend to start |
| 80 | echo -e "${YELLOW}等待后端服务启动...${NC}" | 31 | echo -e "${YELLOW}等待后端服务启动...${NC}" |
| 81 | -MAX_RETRIES=12 | 32 | +MAX_RETRIES=30 |
| 82 | RETRY_COUNT=0 | 33 | RETRY_COUNT=0 |
| 83 | BACKEND_READY=false | 34 | BACKEND_READY=false |
| 84 | 35 | ||
| @@ -95,7 +46,7 @@ done | @@ -95,7 +46,7 @@ done | ||
| 95 | # Check if backend is running | 46 | # Check if backend is running |
| 96 | if [ "$BACKEND_READY" = true ]; then | 47 | if [ "$BACKEND_READY" = true ]; then |
| 97 | echo -e "${GREEN}✓ 后端服务运行正常${NC}" | 48 | echo -e "${GREEN}✓ 后端服务运行正常${NC}" |
| 98 | - # Try health check, but don't fail if it's not ready yet | 49 | + # Try health check |
| 99 | if curl -s http://localhost:6002/admin/health > /dev/null 2>&1; then | 50 | if curl -s http://localhost:6002/admin/health > /dev/null 2>&1; then |
| 100 | echo -e "${GREEN}✓ 健康检查通过${NC}" | 51 | echo -e "${GREEN}✓ 健康检查通过${NC}" |
| 101 | else | 52 | else |
| @@ -104,11 +55,42 @@ if [ "$BACKEND_READY" = true ]; then | @@ -104,11 +55,42 @@ if [ "$BACKEND_READY" = true ]; then | ||
| 104 | else | 55 | else |
| 105 | echo -e "${RED}✗ 后端服务启动失败,请检查日志: logs/backend.log${NC}" | 56 | echo -e "${RED}✗ 后端服务启动失败,请检查日志: logs/backend.log${NC}" |
| 106 | echo -e "${YELLOW}提示: 后端服务可能需要更多时间启动,或者检查端口是否被占用${NC}" | 57 | echo -e "${YELLOW}提示: 后端服务可能需要更多时间启动,或者检查端口是否被占用${NC}" |
| 107 | - # Don't exit - let user decide whether to continue | 58 | + exit 1 |
| 59 | +fi | ||
| 60 | + | ||
| 61 | +# Step 2: Start frontend in background | ||
| 62 | +echo -e "\n${YELLOW}Step 2/2: 启动前端服务${NC}" | ||
| 63 | +echo -e "${YELLOW}前端服务将在后台运行...${NC}" | ||
| 64 | + | ||
| 65 | +nohup ./scripts/start_frontend.sh > logs/frontend.log 2>&1 & | ||
| 66 | +FRONTEND_PID=$! | ||
| 67 | +echo $FRONTEND_PID > logs/frontend.pid | ||
| 68 | +echo -e "${GREEN}前端服务已启动 (PID: $FRONTEND_PID)${NC}" | ||
| 69 | +echo -e "${GREEN}日志文件: logs/frontend.log${NC}" | ||
| 70 | + | ||
| 71 | +# Wait for frontend to start | ||
| 72 | +echo -e "${YELLOW}等待前端服务启动...${NC}" | ||
| 73 | +MAX_RETRIES=15 | ||
| 74 | +RETRY_COUNT=0 | ||
| 75 | +FRONTEND_READY=false | ||
| 76 | + | ||
| 77 | +while [ $RETRY_COUNT -lt $MAX_RETRIES ]; do | ||
| 78 | + sleep 2 | ||
| 79 | + if curl -s http://localhost:6003/ > /dev/null 2>&1; then | ||
| 80 | + FRONTEND_READY=true | ||
| 81 | + break | ||
| 82 | + fi | ||
| 83 | + RETRY_COUNT=$((RETRY_COUNT + 1)) | ||
| 84 | + echo -e "${YELLOW} 等待中... ($RETRY_COUNT/$MAX_RETRIES)${NC}" | ||
| 85 | +done | ||
| 86 | + | ||
| 87 | +# Check if frontend is running | ||
| 88 | +if [ "$FRONTEND_READY" = true ]; then | ||
| 89 | + echo -e "${GREEN}✓ 前端服务运行正常${NC}" | ||
| 90 | +else | ||
| 91 | + echo -e "${YELLOW}⚠ 前端服务可能还在启动中,请稍后访问${NC}" | ||
| 108 | fi | 92 | fi |
| 109 | 93 | ||
| 110 | -# Step 4: Start frontend | ||
| 111 | -echo -e "\n${YELLOW}Step 4/5: 启动前端服务${NC}" | ||
| 112 | echo -e "${GREEN}========================================${NC}" | 94 | echo -e "${GREEN}========================================${NC}" |
| 113 | echo -e "${GREEN}所有服务启动完成!${NC}" | 95 | echo -e "${GREEN}所有服务启动完成!${NC}" |
| 114 | echo -e "${GREEN}========================================${NC}" | 96 | echo -e "${GREEN}========================================${NC}" |
| @@ -120,13 +102,10 @@ echo -e " ${GREEN}API文档: http://localhost:6002/docs${NC}" | @@ -120,13 +102,10 @@ echo -e " ${GREEN}API文档: http://localhost:6002/docs${NC}" | ||
| 120 | echo "" | 102 | echo "" |
| 121 | echo -e "日志文件:" | 103 | echo -e "日志文件:" |
| 122 | echo -e " 后端: logs/backend.log" | 104 | echo -e " 后端: logs/backend.log" |
| 105 | +echo -e " 前端: logs/frontend.log" | ||
| 123 | echo "" | 106 | echo "" |
| 124 | echo -e "停止服务:" | 107 | echo -e "停止服务:" |
| 125 | -echo -e " 后端: kill \$(cat logs/backend.pid)" | ||
| 126 | -echo -e " 前端: Ctrl+C" | ||
| 127 | -echo "" | ||
| 128 | -echo -e "${YELLOW}正在启动前端服务...${NC}" | ||
| 129 | -echo -e "${YELLOW}按 Ctrl+C 停止前端服务${NC}" | ||
| 130 | -echo "" | ||
| 131 | - | ||
| 132 | -./scripts/start_frontend.sh | 108 | +echo -e " 所有服务: ./stop.sh" |
| 109 | +echo -e " 单独停止后端: kill \$(cat logs/backend.pid)" | ||
| 110 | +echo -e " 单独停止前端: kill \$(cat logs/frontend.pid)" | ||
| 111 | +echo "" | ||
| 133 | \ No newline at end of file | 112 | \ No newline at end of file |
scripts/stop.sh
| @@ -63,6 +63,17 @@ if [ -f "logs/backend.pid" ]; then | @@ -63,6 +63,17 @@ if [ -f "logs/backend.pid" ]; then | ||
| 63 | rm -f logs/backend.pid | 63 | rm -f logs/backend.pid |
| 64 | fi | 64 | fi |
| 65 | 65 | ||
| 66 | +if [ -f "logs/frontend.pid" ]; then | ||
| 67 | + FRONTEND_PID=$(cat logs/frontend.pid 2>/dev/null) | ||
| 68 | + if [ ! -z "$FRONTEND_PID" ] && kill -0 $FRONTEND_PID 2>/dev/null; then | ||
| 69 | + echo "Stopping frontend server via PID file (PID: $FRONTEND_PID)..." | ||
| 70 | + kill -TERM $FRONTEND_PID 2>/dev/null || true | ||
| 71 | + sleep 2 | ||
| 72 | + kill -KILL $FRONTEND_PID 2>/dev/null || true | ||
| 73 | + fi | ||
| 74 | + rm -f logs/frontend.pid | ||
| 75 | +fi | ||
| 76 | + | ||
| 66 | echo "========================================" | 77 | echo "========================================" |
| 67 | echo "All services stopped successfully!" | 78 | echo "All services stopped successfully!" |
| 68 | echo "========================================" | 79 | echo "========================================" |
| 69 | \ No newline at end of file | 80 | \ No newline at end of file |
| @@ -0,0 +1,155 @@ | @@ -0,0 +1,155 @@ | ||
| 1 | +#!/bin/bash | ||
| 2 | + | ||
| 3 | +# Complete test script for SearchEngine | ||
| 4 | +# This script performs full testing including data ingestion and service restart | ||
| 5 | + | ||
| 6 | +cd "$(dirname "$0")" | ||
| 7 | + | ||
| 8 | +GREEN='\033[0;32m' | ||
| 9 | +YELLOW='\033[1;33m' | ||
| 10 | +RED='\033[0;31m' | ||
| 11 | +NC='\033[0m' | ||
| 12 | + | ||
| 13 | +echo -e "${GREEN}========================================${NC}" | ||
| 14 | +echo -e "${GREEN}SearchEngine完整测试脚本${NC}" | ||
| 15 | +echo -e "${GREEN}========================================${NC}" | ||
| 16 | + | ||
| 17 | +# Step 1: Setup environment | ||
| 18 | +echo -e "\n${YELLOW}Step 1/4: 设置环境${NC}" | ||
| 19 | +if [ -f "./setup.sh" ]; then | ||
| 20 | + ./setup.sh | ||
| 21 | + if [ $? -eq 0 ]; then | ||
| 22 | + echo -e "${GREEN}✓ 环境设置完成${NC}" | ||
| 23 | + else | ||
| 24 | + echo -e "${RED}✗ 环境设置失败${NC}" | ||
| 25 | + exit 1 | ||
| 26 | + fi | ||
| 27 | +else | ||
| 28 | + echo -e "${YELLOW}⚠ setup脚本不存在,跳过环境设置${NC}" | ||
| 29 | +fi | ||
| 30 | + | ||
| 31 | +# Step 2: Check and ingest data if needed | ||
| 32 | +echo -e "\n${YELLOW}Step 2/4: 检查并准备数据${NC}" | ||
| 33 | +source /home/tw/miniconda3/etc/profile.d/conda.sh | ||
| 34 | +conda activate searchengine | ||
| 35 | + | ||
| 36 | +# Check if index exists | ||
| 37 | +INDEX_EXISTS=$(python -c " | ||
| 38 | +from config.env_config import get_es_config | ||
| 39 | +from utils.es_client import ESClient | ||
| 40 | +from config import ConfigLoader | ||
| 41 | + | ||
| 42 | +try: | ||
| 43 | + es_config = get_es_config() | ||
| 44 | + es_client = ESClient(hosts=[es_config['host']], username=es_config.get('username'), password=es_config.get('password')) | ||
| 45 | + | ||
| 46 | + config_loader = ConfigLoader('config/schema') | ||
| 47 | + config = config_loader.load_customer_config('customer1') | ||
| 48 | + | ||
| 49 | + if es_client.index_exists(config.es_index_name): | ||
| 50 | + doc_count = es_client.count(config.es_index_name) | ||
| 51 | + print(f'{doc_count}') | ||
| 52 | + else: | ||
| 53 | + print('0') | ||
| 54 | +except Exception as e: | ||
| 55 | + print(f'0') | ||
| 56 | +" 2>/dev/null || echo "0") | ||
| 57 | + | ||
| 58 | +if [ "$INDEX_EXISTS" = "0" ]; then | ||
| 59 | + echo -e "${YELLOW}索引不存在,开始导入数据...${NC}" | ||
| 60 | + echo -e "${YELLOW}注意: 首次导入会下载模型文件,可能需要10-30分钟${NC}" | ||
| 61 | + echo -e "${YELLOW}导入1000条数据进行快速测试(跳过embedding以加快速度)${NC}" | ||
| 62 | + | ||
| 63 | + if [ -f "./scripts/ingest.sh" ]; then | ||
| 64 | + ./scripts/ingest.sh 1000 true | ||
| 65 | + if [ $? -eq 0 ]; then | ||
| 66 | + echo -e "${GREEN}✓ 数据导入完成${NC}" | ||
| 67 | + else | ||
| 68 | + echo -e "${RED}✗ 数据导入失败${NC}" | ||
| 69 | + exit 1 | ||
| 70 | + fi | ||
| 71 | + else | ||
| 72 | + echo -e "${RED}✗ 数据导入脚本不存在${NC}" | ||
| 73 | + exit 1 | ||
| 74 | + fi | ||
| 75 | +else | ||
| 76 | + echo -e "${GREEN}✓ 数据已存在,包含 $INDEX_EXISTS 条文档${NC}" | ||
| 77 | +fi | ||
| 78 | + | ||
| 79 | +# Step 3: Restart services (stop first, then start) | ||
| 80 | +echo -e "\n${YELLOW}Step 3/4: 重启服务${NC}" | ||
| 81 | +if [ -f "./restart.sh" ]; then | ||
| 82 | + ./restart.sh | ||
| 83 | + if [ $? -eq 0 ]; then | ||
| 84 | + echo -e "${GREEN}✓ 服务重启完成${NC}" | ||
| 85 | + else | ||
| 86 | + echo -e "${RED}✗ 服务重启失败${NC}" | ||
| 87 | + exit 1 | ||
| 88 | + fi | ||
| 89 | +else | ||
| 90 | + echo -e "${RED}✗ 重启脚本不存在${NC}" | ||
| 91 | + exit 1 | ||
| 92 | +fi | ||
| 93 | + | ||
| 94 | +# Step 4: Test the services | ||
| 95 | +echo -e "\n${YELLOW}Step 4/4: 测试服务${NC}" | ||
| 96 | +sleep 3 | ||
| 97 | + | ||
| 98 | +# Test backend health | ||
| 99 | +echo -e "${YELLOW}测试后端服务健康状态...${NC}" | ||
| 100 | +if curl -s http://localhost:6002/admin/health > /dev/null 2>&1; then | ||
| 101 | + echo -e "${GREEN}✓ 后端服务健康检查通过${NC}" | ||
| 102 | +else | ||
| 103 | + echo -e "${YELLOW}⚠ 后端服务健康检查失败,但服务可能仍在启动${NC}" | ||
| 104 | +fi | ||
| 105 | + | ||
| 106 | +# Test frontend | ||
| 107 | +echo -e "${YELLOW}测试前端服务...${NC}" | ||
| 108 | +if curl -s http://localhost:6003/ > /dev/null 2>&1; then | ||
| 109 | + echo -e "${GREEN}✓ 前端服务可访问${NC}" | ||
| 110 | +else | ||
| 111 | + echo -e "${YELLOW}⚠ 前端服务可能还在启动中${NC}" | ||
| 112 | +fi | ||
| 113 | + | ||
| 114 | +# Test API endpoint | ||
| 115 | +echo -e "${YELLOW}测试API端点...${NC}" | ||
| 116 | +API_TEST_RESULT=$(curl -s -X GET "http://localhost:6002/search?q=test&size=5" 2>/dev/null | python -c " | ||
| 117 | +import json | ||
| 118 | +import sys | ||
| 119 | +try: | ||
| 120 | + data = json.load(sys.stdin) | ||
| 121 | + if 'results' in data and len(data['results']) > 0: | ||
| 122 | + print('API_TEST_OK') | ||
| 123 | + else: | ||
| 124 | + print('API_TEST_EMPTY') | ||
| 125 | +except: | ||
| 126 | + print('API_TEST_ERROR') | ||
| 127 | +" 2>/dev/null || echo "API_TEST_ERROR") | ||
| 128 | + | ||
| 129 | +case $API_TEST_RESULT in | ||
| 130 | + "API_TEST_OK") | ||
| 131 | + echo -e "${GREEN}✓ API测试通过,返回搜索结果${NC}" | ||
| 132 | + ;; | ||
| 133 | + "API_TEST_EMPTY") | ||
| 134 | + echo -e "${YELLOW}⚠ API测试通过,但返回空结果${NC}" | ||
| 135 | + ;; | ||
| 136 | + *) | ||
| 137 | + echo -e "${YELLOW}⚠ API测试失败,服务可能还在启动中${NC}" | ||
| 138 | + ;; | ||
| 139 | +esac | ||
| 140 | + | ||
| 141 | +echo -e "${GREEN}========================================${NC}" | ||
| 142 | +echo -e "${GREEN}完整测试流程结束!${NC}" | ||
| 143 | +echo -e "${GREEN}========================================${NC}" | ||
| 144 | +echo "" | ||
| 145 | +echo -e "服务状态:" | ||
| 146 | +echo -e " ${GREEN}前端界面: http://localhost:6003${NC}" | ||
| 147 | +echo -e " ${GREEN}后端API: http://localhost:6002${NC}" | ||
| 148 | +echo -e " ${GREEN}API文档: http://localhost:6002/docs${NC}" | ||
| 149 | +echo "" | ||
| 150 | +echo -e "可用脚本:" | ||
| 151 | +echo -e " ${YELLOW}./run.sh${NC} - 仅启动服务(不导入数据)" | ||
| 152 | +echo -e " ${YELLOW}./stop.sh${NC} - 停止所有服务" | ||
| 153 | +echo -e " ${YELLOW}./restart.sh${NC} - 重启所有服务" | ||
| 154 | +echo -e " ${YELLOW}./test_all.sh${NC}- 完整测试(包含数据导入)" | ||
| 155 | +echo "" | ||
| 0 | \ No newline at end of file | 156 | \ No newline at end of file |
test_cleaned_api.py deleted
| @@ -1,143 +0,0 @@ | @@ -1,143 +0,0 @@ | ||
| 1 | -#!/usr/bin/env python3 | ||
| 2 | -""" | ||
| 3 | -测试清理后的API行为 | ||
| 4 | -验证用户不再需要传递enable_translation等参数 | ||
| 5 | -""" | ||
| 6 | - | ||
| 7 | -import sys | ||
| 8 | -import os | ||
| 9 | - | ||
| 10 | -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | ||
| 11 | - | ||
| 12 | -def test_cleaned_api(): | ||
| 13 | - """测试清理后的API行为""" | ||
| 14 | - print("🧪 测试清理后的API行为") | ||
| 15 | - print("=" * 60) | ||
| 16 | - | ||
| 17 | - try: | ||
| 18 | - from api.models import SearchRequest | ||
| 19 | - from search.searcher import Searcher | ||
| 20 | - from config.config_loader import ConfigLoader | ||
| 21 | - from context.request_context import create_request_context | ||
| 22 | - | ||
| 23 | - # 测试API模型不再包含内部参数 | ||
| 24 | - print("📝 测试API模型...") | ||
| 25 | - | ||
| 26 | - # 创建搜索请求 | ||
| 27 | - search_request = SearchRequest( | ||
| 28 | - query="消防", | ||
| 29 | - size=10, | ||
| 30 | - from_=0, | ||
| 31 | - filters=None, | ||
| 32 | - min_score=None | ||
| 33 | - ) | ||
| 34 | - | ||
| 35 | - print(f"✅ SearchRequest创建成功:") | ||
| 36 | - print(f" - query: {search_request.query}") | ||
| 37 | - print(f" - size: {search_request.size}") | ||
| 38 | - print(f" - from_: {search_request.from_}") | ||
| 39 | - print(f" - filters: {search_request.filters}") | ||
| 40 | - print(f" - min_score: {search_request.min_score}") | ||
| 41 | - | ||
| 42 | - # 验证不再包含内部参数 | ||
| 43 | - print(f"\n🚫 验证内部参数已移除:") | ||
| 44 | - internal_params = ['enable_translation', 'enable_embedding', 'enable_rerank'] | ||
| 45 | - for param in internal_params: | ||
| 46 | - if hasattr(search_request, param): | ||
| 47 | - print(f" ❌ {param} 仍然存在") | ||
| 48 | - return False | ||
| 49 | - else: | ||
| 50 | - print(f" ✅ {param} 已移除") | ||
| 51 | - | ||
| 52 | - # 测试搜索器使用配置默认值 | ||
| 53 | - print(f"\n🔧 测试搜索器使用配置默认值...") | ||
| 54 | - | ||
| 55 | - loader = ConfigLoader() | ||
| 56 | - config = loader.load_customer_config("customer1") | ||
| 57 | - | ||
| 58 | - print(f"✅ 配置默认值:") | ||
| 59 | - print(f" - enable_translation: {config.query_config.enable_translation}") | ||
| 60 | - print(f" - enable_text_embedding: {config.query_config.enable_text_embedding}") | ||
| 61 | - | ||
| 62 | - # 创建模拟搜索器测试 | ||
| 63 | - class MockESClient: | ||
| 64 | - def search(self, **kwargs): | ||
| 65 | - return { | ||
| 66 | - "hits": {"hits": [], "total": {"value": 0}, "max_score": 0.0}, | ||
| 67 | - "took": 15 | ||
| 68 | - } | ||
| 69 | - | ||
| 70 | - es_client = MockESClient() | ||
| 71 | - searcher = Searcher(config, es_client) | ||
| 72 | - | ||
| 73 | - # 测试搜索器方法签名 | ||
| 74 | - import inspect | ||
| 75 | - search_signature = inspect.signature(searcher.search) | ||
| 76 | - search_params = list(search_signature.parameters.keys()) | ||
| 77 | - | ||
| 78 | - print(f"\n📋 搜索器方法参数:") | ||
| 79 | - for param in search_params: | ||
| 80 | - print(f" - {param}") | ||
| 81 | - | ||
| 82 | - # 验证不再包含内部参数 | ||
| 83 | - print(f"\n🚫 验证搜索器参数已清理:") | ||
| 84 | - for param in internal_params: | ||
| 85 | - if param in search_params: | ||
| 86 | - print(f" ❌ {param} 仍然存在") | ||
| 87 | - return False | ||
| 88 | - else: | ||
| 89 | - print(f" ✅ {param} 已移除") | ||
| 90 | - | ||
| 91 | - # 测试实际的搜索调用 | ||
| 92 | - print(f"\n🧪 测试实际搜索调用...") | ||
| 93 | - context = create_request_context("cleaned_api_test", "test_user") | ||
| 94 | - | ||
| 95 | - result = searcher.search( | ||
| 96 | - query="消防", | ||
| 97 | - size=10, | ||
| 98 | - from_=0, | ||
| 99 | - filters=None, | ||
| 100 | - min_score=None, | ||
| 101 | - context=context | ||
| 102 | - ) | ||
| 103 | - | ||
| 104 | - print(f"✅ 搜索调用成功!") | ||
| 105 | - print(f" - 返回结果类型: {type(result).__name__}") | ||
| 106 | - print(f" - 总命中数: {result.total}") | ||
| 107 | - | ||
| 108 | - # 检查上下文中的功能标志 | ||
| 109 | - feature_flags = context.metadata.get('feature_flags', {}) | ||
| 110 | - print(f"\n🚩 实际使用的功能标志:") | ||
| 111 | - for flag, value in feature_flags.items(): | ||
| 112 | - print(f" - {flag}: {value}") | ||
| 113 | - | ||
| 114 | - # 验证使用了配置默认值 | ||
| 115 | - expected_translation = config.query_config.enable_translation | ||
| 116 | - expected_embedding = config.query_config.enable_text_embedding | ||
| 117 | - | ||
| 118 | - actual_translation = feature_flags.get('translation_enabled') | ||
| 119 | - actual_embedding = feature_flags.get('embedding_enabled') | ||
| 120 | - | ||
| 121 | - print(f"\n📊 功能验证:") | ||
| 122 | - print(f" 翻译功能: 期望={expected_translation}, 实际={actual_translation} {'✅' if expected_translation == actual_translation else '❌'}") | ||
| 123 | - print(f" 向量功能: 期望={expected_embedding}, 实际={actual_embedding} {'✅' if expected_embedding == actual_embedding else '❌'}") | ||
| 124 | - | ||
| 125 | - if expected_translation == actual_translation and expected_embedding == actual_embedding: | ||
| 126 | - print(f"\n🎉 API清理成功!") | ||
| 127 | - print(f"✅ 用户不再需要传递内部参数") | ||
| 128 | - print(f"✅ 后端自动使用配置默认值") | ||
| 129 | - print(f"✅ 功能完全透明") | ||
| 130 | - return True | ||
| 131 | - else: | ||
| 132 | - print(f"\n⚠️ 功能验证失败") | ||
| 133 | - return False | ||
| 134 | - | ||
| 135 | - except Exception as e: | ||
| 136 | - print(f"❌ 测试失败: {e}") | ||
| 137 | - import traceback | ||
| 138 | - traceback.print_exc() | ||
| 139 | - return False | ||
| 140 | - | ||
| 141 | -if __name__ == "__main__": | ||
| 142 | - success = test_cleaned_api() | ||
| 143 | - sys.exit(0 if success else 1) | ||
| 144 | \ No newline at end of file | 0 | \ No newline at end of file |
test_context.py deleted
| @@ -1,136 +0,0 @@ | @@ -1,136 +0,0 @@ | ||
| 1 | -""" | ||
| 2 | -测试RequestContext功能的简单脚本 | ||
| 3 | -""" | ||
| 4 | - | ||
| 5 | -import sys | ||
| 6 | -import os | ||
| 7 | - | ||
| 8 | -# 添加项目根目录到Python路径 | ||
| 9 | -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | ||
| 10 | - | ||
| 11 | -from context import RequestContext, RequestContextStage, create_request_context | ||
| 12 | - | ||
| 13 | - | ||
| 14 | -def test_basic_context_functionality(): | ||
| 15 | - """测试基本的context功能""" | ||
| 16 | - print("=== 测试基本RequestContext功能 ===") | ||
| 17 | - | ||
| 18 | - # 创建context | ||
| 19 | - context = create_request_context("test123", "user456") | ||
| 20 | - | ||
| 21 | - print(f"Request ID: {context.reqid}") | ||
| 22 | - print(f"User ID: {context.uid}") | ||
| 23 | - | ||
| 24 | - # 测试阶段计时 | ||
| 25 | - context.start_stage(RequestContextStage.QUERY_PARSING) | ||
| 26 | - import time | ||
| 27 | - time.sleep(0.1) # 模拟工作 | ||
| 28 | - duration = context.end_stage(RequestContextStage.QUERY_PARSING) | ||
| 29 | - | ||
| 30 | - print(f"查询解析阶段耗时: {duration:.2f}ms") | ||
| 31 | - | ||
| 32 | - # 测试存储查询分析结果 | ||
| 33 | - context.store_query_analysis( | ||
| 34 | - original_query="iphone 13", | ||
| 35 | - normalized_query="iphone 13", | ||
| 36 | - rewritten_query="apple iphone 13", | ||
| 37 | - detected_language="en" | ||
| 38 | - ) | ||
| 39 | - | ||
| 40 | - # 测试存储中间结果 | ||
| 41 | - context.store_intermediate_result('test_key', {'test': 'value'}) | ||
| 42 | - | ||
| 43 | - # 获取摘要 | ||
| 44 | - summary = context.get_summary() | ||
| 45 | - print("Context摘要:") | ||
| 46 | - print(f" - 原始查询: {summary['query_analysis']['original_query']}") | ||
| 47 | - print(f" - 检测语言: {summary['query_analysis']['detected_language']}") | ||
| 48 | - print(f" - 阶段耗时: {summary['performance']['stage_timings_ms']}") | ||
| 49 | - | ||
| 50 | - print("✅ 基本功能测试通过\n") | ||
| 51 | - | ||
| 52 | - | ||
| 53 | -def test_context_as_context_manager(): | ||
| 54 | - """测试context作为上下文管理器的功能""" | ||
| 55 | - print("=== 测试上下文管理器功能 ===") | ||
| 56 | - | ||
| 57 | - # 使用上下文管理器 | ||
| 58 | - with create_request_context("cm123", "user789") as context: | ||
| 59 | - context.start_stage(RequestContextStage.QUERY_PARSING) | ||
| 60 | - import time | ||
| 61 | - time.sleep(0.05) | ||
| 62 | - context.end_stage(RequestContextStage.QUERY_PARSING) | ||
| 63 | - | ||
| 64 | - context.start_stage(RequestContextStage.QUERY_BUILDING) | ||
| 65 | - time.sleep(0.03) | ||
| 66 | - context.end_stage(RequestContextStage.QUERY_BUILDING) | ||
| 67 | - | ||
| 68 | - print(f"Context ID: {context.reqid}") | ||
| 69 | - | ||
| 70 | - # 退出时会自动记录性能摘要 | ||
| 71 | - print("✅ 上下文管理器测试通过\n") | ||
| 72 | - | ||
| 73 | - | ||
| 74 | -def test_error_handling(): | ||
| 75 | - """测试错误处理功能""" | ||
| 76 | - print("=== 测试错误处理功能 ===") | ||
| 77 | - | ||
| 78 | - context = create_request_context("error123") | ||
| 79 | - | ||
| 80 | - # 设置错误 | ||
| 81 | - try: | ||
| 82 | - raise ValueError("这是一个测试错误") | ||
| 83 | - except Exception as e: | ||
| 84 | - context.set_error(e) | ||
| 85 | - | ||
| 86 | - print(f"有错误: {context.has_error()}") | ||
| 87 | - print(f"错误信息: {context.metadata['error_info']}") | ||
| 88 | - | ||
| 89 | - print("✅ 错误处理测试通过\n") | ||
| 90 | - | ||
| 91 | - | ||
| 92 | -def test_performance_summary(): | ||
| 93 | - """测试性能摘要功能""" | ||
| 94 | - print("=== 测试性能摘要功能 ===") | ||
| 95 | - | ||
| 96 | - context = create_request_context("perf123") | ||
| 97 | - | ||
| 98 | - # 模拟多个阶段 | ||
| 99 | - stages = [ | ||
| 100 | - RequestContextStage.QUERY_PARSING, | ||
| 101 | - RequestContextStage.BOOLEAN_PARSING, | ||
| 102 | - RequestContextStage.QUERY_BUILDING, | ||
| 103 | - RequestContextStage.ELASTICSEARCH_SEARCH, | ||
| 104 | - RequestContextStage.RESULT_PROCESSING | ||
| 105 | - ] | ||
| 106 | - | ||
| 107 | - import time | ||
| 108 | - durations = [50, 20, 80, 150, 30] # 模拟各阶段耗时(ms) | ||
| 109 | - | ||
| 110 | - for stage, expected_duration in zip(stages, durations): | ||
| 111 | - context.start_stage(stage) | ||
| 112 | - time.sleep(expected_duration / 1000.0) # 转换为秒 | ||
| 113 | - context.end_stage(stage) | ||
| 114 | - | ||
| 115 | - # 设置总耗时 | ||
| 116 | - context.performance_metrics.total_duration = sum(durations) | ||
| 117 | - | ||
| 118 | - # 计算百分比 | ||
| 119 | - percentages = context.calculate_stage_percentages() | ||
| 120 | - | ||
| 121 | - print("各阶段耗时占比:") | ||
| 122 | - for stage, percentage in percentages.items(): | ||
| 123 | - print(f" - {stage}: {percentage}%") | ||
| 124 | - | ||
| 125 | - print("✅ 性能摘要测试通过\n") | ||
| 126 | - | ||
| 127 | - | ||
| 128 | -if __name__ == "__main__": | ||
| 129 | - print("开始测试RequestContext功能...\n") | ||
| 130 | - | ||
| 131 | - test_basic_context_functionality() | ||
| 132 | - test_context_as_context_manager() | ||
| 133 | - test_error_handling() | ||
| 134 | - test_performance_summary() | ||
| 135 | - | ||
| 136 | - print("🎉 所有测试通过!RequestContext功能正常。") | ||
| 137 | \ No newline at end of file | 0 | \ No newline at end of file |
test_default_features.py deleted
| @@ -1,106 +0,0 @@ | @@ -1,106 +0,0 @@ | ||
| 1 | -#!/usr/bin/env python3 | ||
| 2 | -""" | ||
| 3 | -测试默认功能是否正确开启 | ||
| 4 | -""" | ||
| 5 | - | ||
| 6 | -import sys | ||
| 7 | -import os | ||
| 8 | - | ||
| 9 | -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | ||
| 10 | - | ||
| 11 | -def test_default_features(): | ||
| 12 | - """测试默认功能是否正确开启""" | ||
| 13 | - print("🧪 测试默认功能开启状态") | ||
| 14 | - print("=" * 60) | ||
| 15 | - | ||
| 16 | - try: | ||
| 17 | - from config.config_loader import ConfigLoader | ||
| 18 | - from search.searcher import Searcher | ||
| 19 | - from utils.es_client import ESClient | ||
| 20 | - from context.request_context import create_request_context | ||
| 21 | - | ||
| 22 | - # 加载配置 | ||
| 23 | - print("📝 加载配置...") | ||
| 24 | - loader = ConfigLoader() | ||
| 25 | - config = loader.load_customer_config("customer1") | ||
| 26 | - | ||
| 27 | - print(f"✅ 配置文件设置:") | ||
| 28 | - print(f" - enable_translation: {config.query_config.enable_translation}") | ||
| 29 | - print(f" - enable_text_embedding: {config.query_config.enable_text_embedding}") | ||
| 30 | - | ||
| 31 | - # 创建搜索器(模拟没有ES连接的情况) | ||
| 32 | - print(f"\n🔍 创建搜索器...") | ||
| 33 | - | ||
| 34 | - # 创建一个模拟的ES客户端用于测试 | ||
| 35 | - class MockESClient: | ||
| 36 | - def search(self, **kwargs): | ||
| 37 | - return { | ||
| 38 | - "hits": {"hits": [], "total": {"value": 0}, "max_score": 0.0}, | ||
| 39 | - "took": 10 | ||
| 40 | - } | ||
| 41 | - | ||
| 42 | - es_client = MockESClient() | ||
| 43 | - searcher = Searcher(config, es_client) | ||
| 44 | - | ||
| 45 | - # 测试不同参数组合 | ||
| 46 | - test_cases = [ | ||
| 47 | - {"name": "不传递任何参数", "params": {}}, | ||
| 48 | - {"name": "显式传递None", "params": {"enable_translation": None, "enable_embedding": None}}, | ||
| 49 | - {"name": "显式传递False", "params": {"enable_translation": False, "enable_embedding": False}}, | ||
| 50 | - {"name": "显式传递True", "params": {"enable_translation": True, "enable_embedding": True}}, | ||
| 51 | - ] | ||
| 52 | - | ||
| 53 | - print(f"\n🧪 测试不同参数组合:") | ||
| 54 | - for test_case in test_cases: | ||
| 55 | - print(f"\n 📋 {test_case['name']}:") | ||
| 56 | - | ||
| 57 | - try: | ||
| 58 | - # 执行搜索 | ||
| 59 | - result = searcher.search( | ||
| 60 | - query="推车", | ||
| 61 | - context=create_request_context("test_features", "test_user"), | ||
| 62 | - **test_case['params'] | ||
| 63 | - ) | ||
| 64 | - | ||
| 65 | - # 检查上下文中的功能标志 | ||
| 66 | - context_summary = create_request_context("test_features", "test_user").get_summary() | ||
| 67 | - # 由于我们无法直接获取内部的context,我们检查配置 | ||
| 68 | - print(f" ✅ 搜索执行成功") | ||
| 69 | - | ||
| 70 | - except Exception as e: | ||
| 71 | - print(f" ❌ 搜索失败: {e}") | ||
| 72 | - | ||
| 73 | - # 测试配置驱动的默认行为 | ||
| 74 | - print(f"\n🔧 配置驱动的默认行为测试:") | ||
| 75 | - | ||
| 76 | - # 模拟API调用(不传递参数,应该使用配置默认值) | ||
| 77 | - context = create_request_context("config_default_test", "config_user") | ||
| 78 | - | ||
| 79 | - print(f" 配置默认值:") | ||
| 80 | - print(f" - 翻译功能: {'启用' if config.query_config.enable_translation else '禁用'}") | ||
| 81 | - print(f" - 向量功能: {'启用' if config.query_config.enable_text_embedding else '禁用'}") | ||
| 82 | - | ||
| 83 | - # 验证配置逻辑 | ||
| 84 | - expected_translation = config.query_config.enable_translation | ||
| 85 | - expected_embedding = config.query_config.enable_text_embedding | ||
| 86 | - | ||
| 87 | - print(f"\n✅ 预期行为:") | ||
| 88 | - print(f" 当API调用不传递enable_translation参数时,应该: {'启用翻译' if expected_translation else '禁用翻译'}") | ||
| 89 | - print(f" 当API调用不传递enable_embedding参数时,应该: {'启用向量' if expected_embedding else '禁用向量'}") | ||
| 90 | - | ||
| 91 | - if expected_translation and expected_embedding: | ||
| 92 | - print(f"\n🎉 配置正确!系统默认启用翻译和向量功能。") | ||
| 93 | - return True | ||
| 94 | - else: | ||
| 95 | - print(f"\n⚠️ 配置可能需要调整。") | ||
| 96 | - return False | ||
| 97 | - | ||
| 98 | - except Exception as e: | ||
| 99 | - print(f"❌ 测试失败: {e}") | ||
| 100 | - import traceback | ||
| 101 | - traceback.print_exc() | ||
| 102 | - return False | ||
| 103 | - | ||
| 104 | -if __name__ == "__main__": | ||
| 105 | - success = test_default_features() | ||
| 106 | - sys.exit(0 if success else 1) | ||
| 107 | \ No newline at end of file | 0 | \ No newline at end of file |
test_fixed_query.py deleted
| @@ -1,127 +0,0 @@ | @@ -1,127 +0,0 @@ | ||
| 1 | -#!/usr/bin/env python3 | ||
| 2 | -""" | ||
| 3 | -测试修复后的查询解析功能 | ||
| 4 | -验证翻译和向量生成是否正常工作 | ||
| 5 | -""" | ||
| 6 | - | ||
| 7 | -import sys | ||
| 8 | -import os | ||
| 9 | - | ||
| 10 | -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | ||
| 11 | - | ||
| 12 | -def test_fixed_query_parsing(): | ||
| 13 | - """测试修复后的查询解析""" | ||
| 14 | - print("🧪 测试修复后的查询解析功能") | ||
| 15 | - print("=" * 60) | ||
| 16 | - | ||
| 17 | - try: | ||
| 18 | - from context.request_context import create_request_context | ||
| 19 | - from query.query_parser import QueryParser | ||
| 20 | - from config import CustomerConfig | ||
| 21 | - from config.config_loader import ConfigLoader | ||
| 22 | - | ||
| 23 | - # 加载配置 | ||
| 24 | - print("📝 加载配置...") | ||
| 25 | - loader = ConfigLoader() | ||
| 26 | - config = loader.load_customer_config("customer1") | ||
| 27 | - print(f"✅ 配置加载成功: {config.customer_id}") | ||
| 28 | - print(f" - 翻译功能: {'启用' if config.query_config.enable_translation else '禁用'}") | ||
| 29 | - print(f" - 向量功能: {'启用' if config.query_config.enable_text_embedding else '禁用'}") | ||
| 30 | - | ||
| 31 | - # 创建解析器和上下文 | ||
| 32 | - parser = QueryParser(config) | ||
| 33 | - context = create_request_context("test_fixed", "test_user") | ||
| 34 | - | ||
| 35 | - # 测试查询 | ||
| 36 | - test_query = "推车" | ||
| 37 | - print(f"\n🔍 测试查询: '{test_query}'") | ||
| 38 | - | ||
| 39 | - # 执行解析 | ||
| 40 | - result = parser.parse( | ||
| 41 | - test_query, | ||
| 42 | - context=context, | ||
| 43 | - generate_vector=config.query_config.enable_text_embedding | ||
| 44 | - ) | ||
| 45 | - | ||
| 46 | - # 显示结果 | ||
| 47 | - print(f"\n📊 查询解析结果:") | ||
| 48 | - print(f" 原查询: {result.original_query}") | ||
| 49 | - print(f" 标准化: {result.normalized_query}") | ||
| 50 | - print(f" 重写后: {result.rewritten_query}") | ||
| 51 | - print(f" 检测语言: {result.detected_language}") | ||
| 52 | - print(f" 域: {result.domain}") | ||
| 53 | - print(f" 翻译结果: {result.translations}") | ||
| 54 | - | ||
| 55 | - if result.query_vector is not None: | ||
| 56 | - print(f" 向量: ✅ 已生成 (形状: {result.query_vector.shape})") | ||
| 57 | - print(f" 向量类型: {type(result.query_vector)}") | ||
| 58 | - print(f" 向量前5个值: {result.query_vector[:5]}") | ||
| 59 | - else: | ||
| 60 | - print(f" 向量: ❌ 未生成") | ||
| 61 | - | ||
| 62 | - # 检查翻译质量 | ||
| 63 | - if result.translations: | ||
| 64 | - print(f"\n🌍 翻译质量检查:") | ||
| 65 | - for lang, translation in result.translations.items(): | ||
| 66 | - if translation: | ||
| 67 | - print(f" {lang}: '{translation}' ✅") | ||
| 68 | - else: | ||
| 69 | - print(f" {lang}: 翻译失败 ❌") | ||
| 70 | - else: | ||
| 71 | - print(f"\n🌍 翻译: 无翻译结果") | ||
| 72 | - | ||
| 73 | - # 测试上下文存储 | ||
| 74 | - print(f"\n💾 上下文存储检查:") | ||
| 75 | - stored_query = context.get_intermediate_result('normalized_query') | ||
| 76 | - stored_lang = context.get_intermediate_result('detected_language') | ||
| 77 | - stored_translations = context.get_intermediate_result('translations') | ||
| 78 | - | ||
| 79 | - print(f" 存储的查询: {stored_query}") | ||
| 80 | - print(f" 存储的语言: {stored_lang}") | ||
| 81 | - print(f" 存储的翻译: {stored_translations}") | ||
| 82 | - | ||
| 83 | - # 性能摘要 | ||
| 84 | - summary = context.get_summary() | ||
| 85 | - print(f"\n📈 性能摘要:") | ||
| 86 | - print(f" 请求ID: {summary['request_info']['reqid']}") | ||
| 87 | - print(f" 用户ID: {summary['request_info']['uid']}") | ||
| 88 | - print(f" 有错误: {summary['request_info']['has_error']}") | ||
| 89 | - print(f" 警告数量: {summary['request_info']['warnings_count']}") | ||
| 90 | - print(f" 查询有向量: {summary['query_analysis']['has_vector']}") | ||
| 91 | - | ||
| 92 | - # 判断修复是否成功 | ||
| 93 | - print(f"\n🎯 修复结果评估:") | ||
| 94 | - | ||
| 95 | - translation_success = ( | ||
| 96 | - result.translations and | ||
| 97 | - any(translation is not None and translation != result.original_query | ||
| 98 | - for translation in result.translations.values()) | ||
| 99 | - ) | ||
| 100 | - | ||
| 101 | - vector_success = result.query_vector is not None | ||
| 102 | - | ||
| 103 | - print(f" 翻译功能: {'✅ 修复成功' if translation_success else '❌ 仍有问题'}") | ||
| 104 | - print(f" 向量功能: {'✅ 修复成功' if vector_success else '❌ 仍有问题'}") | ||
| 105 | - | ||
| 106 | - if translation_success and vector_success: | ||
| 107 | - print(f"\n🎉 所有功能修复成功!") | ||
| 108 | - return True | ||
| 109 | - else: | ||
| 110 | - print(f"\n⚠️ 还有功能需要修复") | ||
| 111 | - return False | ||
| 112 | - | ||
| 113 | - except Exception as e: | ||
| 114 | - print(f"❌ 测试失败: {e}") | ||
| 115 | - import traceback | ||
| 116 | - traceback.print_exc() | ||
| 117 | - return False | ||
| 118 | - | ||
| 119 | -if __name__ == "__main__": | ||
| 120 | - success = test_fixed_query_parsing() | ||
| 121 | - | ||
| 122 | - if success: | ||
| 123 | - print(f"\n✨ 修复验证完成 - 系统正常运行!") | ||
| 124 | - else: | ||
| 125 | - print(f"\n💥 修复验证失败 - 需要进一步检查") | ||
| 126 | - | ||
| 127 | - sys.exit(0 if success else 1) | ||
| 128 | \ No newline at end of file | 0 | \ No newline at end of file |
test_frontend_simulation.py deleted
| @@ -1,142 +0,0 @@ | @@ -1,142 +0,0 @@ | ||
| 1 | -#!/usr/bin/env python3 | ||
| 2 | -""" | ||
| 3 | -模拟前端调用API | ||
| 4 | -验证清理后的API对用户友好 | ||
| 5 | -""" | ||
| 6 | - | ||
| 7 | -import sys | ||
| 8 | -import os | ||
| 9 | -import json | ||
| 10 | - | ||
| 11 | -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | ||
| 12 | - | ||
| 13 | -def simulate_frontend_call(): | ||
| 14 | - """模拟前端API调用""" | ||
| 15 | - print("🌐 模拟前端API调用") | ||
| 16 | - print("=" * 60) | ||
| 17 | - | ||
| 18 | - try: | ||
| 19 | - from api.models import SearchRequest | ||
| 20 | - | ||
| 21 | - print("📱 前端发送搜索请求...") | ||
| 22 | - | ||
| 23 | - # 模拟前端发送的请求(简洁明了) | ||
| 24 | - frontend_request_data = { | ||
| 25 | - "query": "芭比娃娃", | ||
| 26 | - "size": 10, | ||
| 27 | - "from_": 0, | ||
| 28 | - "filters": { | ||
| 29 | - "categoryName": "玩具" | ||
| 30 | - } | ||
| 31 | - } | ||
| 32 | - | ||
| 33 | - print(f"📤 请求数据:") | ||
| 34 | - print(json.dumps(frontend_request_data, indent=2, ensure_ascii=False)) | ||
| 35 | - | ||
| 36 | - # 创建API请求对象 | ||
| 37 | - search_request = SearchRequest(**frontend_request_data) | ||
| 38 | - | ||
| 39 | - print(f"\n✅ API请求创建成功!") | ||
| 40 | - print(f" - 查询: '{search_request.query}'") | ||
| 41 | - print(f" - 大小: {search_request.size}") | ||
| 42 | - print(f" - 偏移: {search_request.from_}") | ||
| 43 | - print(f" - 过滤器: {search_request.filters}") | ||
| 44 | - | ||
| 45 | - # 验证请求不包含内部参数 | ||
| 46 | - internal_params = ['enable_translation', 'enable_embedding', 'enable_rerank'] | ||
| 47 | - print(f"\n🔒 内部参数检查:") | ||
| 48 | - for param in internal_params: | ||
| 49 | - if hasattr(search_request, param): | ||
| 50 | - print(f" ❌ {param}: 仍然暴露给用户") | ||
| 51 | - return False | ||
| 52 | - else: | ||
| 53 | - print(f" ✅ {param}: 对用户透明") | ||
| 54 | - | ||
| 55 | - print(f"\n🎉 前端调用验证成功!") | ||
| 56 | - print(f"✅ API接口简洁明了") | ||
| 57 | - print(f"✅ 用户只需提供基本搜索参数") | ||
| 58 | - print(f"✅ 复杂功能对用户完全透明") | ||
| 59 | - print(f"✅ 后端自动处理翻译、向量搜索等功能") | ||
| 60 | - | ||
| 61 | - # 模拟响应结构 | ||
| 62 | - print(f"\n📤 后端响应示例:") | ||
| 63 | - response_example = { | ||
| 64 | - "hits": [], | ||
| 65 | - "total": 0, | ||
| 66 | - "max_score": 0.0, | ||
| 67 | - "took_ms": 45, | ||
| 68 | - "aggregations": {}, | ||
| 69 | - "query_info": { | ||
| 70 | - "original_query": "芭比娃娃", | ||
| 71 | - "rewritten_query": "brand:芭比 OR name:芭比娃娃娃娃", | ||
| 72 | - "detected_language": "zh", | ||
| 73 | - "translations": { | ||
| 74 | - "en": "Barbie doll", | ||
| 75 | - "ru": "кукла Барби" | ||
| 76 | - } | ||
| 77 | - }, | ||
| 78 | - "performance_info": { | ||
| 79 | - "request_info": { | ||
| 80 | - "reqid": "abc123", | ||
| 81 | - "has_error": False, | ||
| 82 | - "warnings_count": 0 | ||
| 83 | - }, | ||
| 84 | - "performance": { | ||
| 85 | - "total_duration_ms": 45.0, | ||
| 86 | - "stage_timings_ms": { | ||
| 87 | - "query_parsing": 25.0, | ||
| 88 | - "boolean_parsing": 1.0, | ||
| 89 | - "query_building": 2.0, | ||
| 90 | - "elasticsearch_search": 10.0, | ||
| 91 | - "result_processing": 1.0 | ||
| 92 | - } | ||
| 93 | - } | ||
| 94 | - } | ||
| 95 | - } | ||
| 96 | - | ||
| 97 | - print(json.dumps(response_example, indent=2, ensure_ascii=False)) | ||
| 98 | - | ||
| 99 | - return True | ||
| 100 | - | ||
| 101 | - except Exception as e: | ||
| 102 | - print(f"❌ 模拟失败: {e}") | ||
| 103 | - import traceback | ||
| 104 | - traceback.print_exc() | ||
| 105 | - return False | ||
| 106 | - | ||
| 107 | -def show_api_comparison(): | ||
| 108 | - """显示清理前后的API对比""" | ||
| 109 | - print(f"\n📊 API接口对比:") | ||
| 110 | - print("=" * 60) | ||
| 111 | - | ||
| 112 | - print(f"❌ 清理前(暴露内部参数):") | ||
| 113 | - print(json.dumps({ | ||
| 114 | - "query": "芭比娃娃", | ||
| 115 | - "size": 10, | ||
| 116 | - "from_": 0, | ||
| 117 | - "enable_translation": True, # ❌ 用户不需要关心 | ||
| 118 | - "enable_embedding": True, # ❌ 用户不需要关心 | ||
| 119 | - "enable_rerank": True, # ❌ 用户不需要关心 | ||
| 120 | - "min_score": None | ||
| 121 | - }, indent=2, ensure_ascii=False)) | ||
| 122 | - | ||
| 123 | - print(f"\n✅ 清理后(用户友好):") | ||
| 124 | - print(json.dumps({ | ||
| 125 | - "query": "芭比娃娃", | ||
| 126 | - "size": 10, | ||
| 127 | - "from_": 0, | ||
| 128 | - "filters": {"categoryName": "玩具"}, | ||
| 129 | - "min_score": None | ||
| 130 | - }, indent=2, ensure_ascii=False)) | ||
| 131 | - | ||
| 132 | -if __name__ == "__main__": | ||
| 133 | - success = simulate_frontend_call() | ||
| 134 | - show_api_comparison() | ||
| 135 | - | ||
| 136 | - if success: | ||
| 137 | - print(f"\n🎊 API清理完全成功!") | ||
| 138 | - print(f"🌟 现在的API对用户非常友好!") | ||
| 139 | - else: | ||
| 140 | - print(f"\n💥 还有问题需要解决") | ||
| 141 | - | ||
| 142 | - sys.exit(0 if success else 1) | ||
| 143 | \ No newline at end of file | 0 | \ No newline at end of file |
test_multilang_config.py deleted
| @@ -1,155 +0,0 @@ | @@ -1,155 +0,0 @@ | ||
| 1 | -#!/usr/bin/env python3 | ||
| 2 | -""" | ||
| 3 | -Test script to validate multi-language configuration. | ||
| 4 | - | ||
| 5 | -This script validates that: | ||
| 6 | -1. language_field_mapping is correctly loaded from config | ||
| 7 | -2. All referenced fields exist and have correct analyzers | ||
| 8 | -3. Multi-language query builder works correctly | ||
| 9 | -""" | ||
| 10 | - | ||
| 11 | -import sys | ||
| 12 | -import json | ||
| 13 | -from config import ConfigLoader | ||
| 14 | - | ||
| 15 | -def test_config_loading(): | ||
| 16 | - """Test that configuration loads correctly with language_field_mapping.""" | ||
| 17 | - print("=" * 60) | ||
| 18 | - print("Testing Configuration Loading") | ||
| 19 | - print("=" * 60) | ||
| 20 | - | ||
| 21 | - try: | ||
| 22 | - loader = ConfigLoader() | ||
| 23 | - config = loader.load_customer_config('customer1') | ||
| 24 | - | ||
| 25 | - print(f"\n✓ Configuration loaded successfully") | ||
| 26 | - print(f" Customer: {config.customer_name}") | ||
| 27 | - print(f" ES Index: {config.es_index_name}") | ||
| 28 | - | ||
| 29 | - # Validate configuration | ||
| 30 | - errors = loader.validate_config(config) | ||
| 31 | - if errors: | ||
| 32 | - print(f"\n✗ Configuration validation failed:") | ||
| 33 | - for error in errors: | ||
| 34 | - print(f" - {error}") | ||
| 35 | - return False | ||
| 36 | - else: | ||
| 37 | - print(f"\n✓ Configuration validation passed") | ||
| 38 | - | ||
| 39 | - # Check indexes with language_field_mapping | ||
| 40 | - print(f"\nIndexes with multi-language support:") | ||
| 41 | - for index in config.indexes: | ||
| 42 | - if index.language_field_mapping: | ||
| 43 | - print(f"\n {index.name} ({index.label}):") | ||
| 44 | - print(f" Fields: {index.fields}") | ||
| 45 | - print(f" Language mapping:") | ||
| 46 | - for lang, fields in index.language_field_mapping.items(): | ||
| 47 | - print(f" {lang}: {fields}") | ||
| 48 | - else: | ||
| 49 | - print(f"\n {index.name} ({index.label}): No language mapping") | ||
| 50 | - | ||
| 51 | - return True | ||
| 52 | - | ||
| 53 | - except Exception as e: | ||
| 54 | - print(f"\n✗ Error loading configuration: {e}") | ||
| 55 | - import traceback | ||
| 56 | - traceback.print_exc() | ||
| 57 | - return False | ||
| 58 | - | ||
| 59 | - | ||
| 60 | -def test_multilang_query_builder(): | ||
| 61 | - """Test that MultiLanguageQueryBuilder works correctly.""" | ||
| 62 | - print("\n" + "=" * 60) | ||
| 63 | - print("Testing Multi-Language Query Builder") | ||
| 64 | - print("=" * 60) | ||
| 65 | - | ||
| 66 | - try: | ||
| 67 | - from config import ConfigLoader | ||
| 68 | - from query import QueryParser | ||
| 69 | - from search.multilang_query_builder import MultiLanguageQueryBuilder | ||
| 70 | - from indexer import MappingGenerator | ||
| 71 | - | ||
| 72 | - loader = ConfigLoader() | ||
| 73 | - config = loader.load_customer_config('customer1') | ||
| 74 | - | ||
| 75 | - # Initialize query builder | ||
| 76 | - mapping_gen = MappingGenerator(config) | ||
| 77 | - text_embedding_field = mapping_gen.get_text_embedding_field() | ||
| 78 | - image_embedding_field = mapping_gen.get_image_embedding_field() | ||
| 79 | - | ||
| 80 | - query_builder = MultiLanguageQueryBuilder( | ||
| 81 | - config=config, | ||
| 82 | - index_name=config.es_index_name, | ||
| 83 | - text_embedding_field=text_embedding_field, | ||
| 84 | - image_embedding_field=image_embedding_field | ||
| 85 | - ) | ||
| 86 | - | ||
| 87 | - print(f"\n✓ MultiLanguageQueryBuilder initialized") | ||
| 88 | - | ||
| 89 | - # Get domain summary | ||
| 90 | - summary = query_builder.get_domain_summary() | ||
| 91 | - print(f"\nDomain Summary:") | ||
| 92 | - for domain, info in summary.items(): | ||
| 93 | - print(f" {domain}:") | ||
| 94 | - print(f" Label: {info['label']}") | ||
| 95 | - print(f" Has multilang mapping: {info['has_multilang_mapping']}") | ||
| 96 | - if info['has_multilang_mapping']: | ||
| 97 | - print(f" Supported languages: {info['supported_languages']}") | ||
| 98 | - | ||
| 99 | - # Test query parsing | ||
| 100 | - query_parser = QueryParser(config) | ||
| 101 | - test_queries = [ | ||
| 102 | - "芭比娃娃", | ||
| 103 | - "title:芭比娃娃", | ||
| 104 | - "default:玩具" | ||
| 105 | - ] | ||
| 106 | - | ||
| 107 | - print(f"\nTesting query parsing:") | ||
| 108 | - for query in test_queries: | ||
| 109 | - print(f"\n Query: '{query}'") | ||
| 110 | - parsed = query_parser.parse(query, generate_vector=False) | ||
| 111 | - print(f" Domain: {parsed.domain}") | ||
| 112 | - print(f" Detected language: {parsed.detected_language}") | ||
| 113 | - print(f" Translations: {list(parsed.translations.keys())}") | ||
| 114 | - | ||
| 115 | - # Build query | ||
| 116 | - es_query = query_builder.build_multilang_query( | ||
| 117 | - parsed_query=parsed, | ||
| 118 | - query_vector=None, | ||
| 119 | - filters=None, | ||
| 120 | - size=10, | ||
| 121 | - enable_knn=False | ||
| 122 | - ) | ||
| 123 | - print(f" ES Query keys: {list(es_query.keys())}") | ||
| 124 | - | ||
| 125 | - return True | ||
| 126 | - | ||
| 127 | - except Exception as e: | ||
| 128 | - print(f"\n✗ Error testing query builder: {e}") | ||
| 129 | - import traceback | ||
| 130 | - traceback.print_exc() | ||
| 131 | - return False | ||
| 132 | - | ||
| 133 | - | ||
| 134 | -if __name__ == "__main__": | ||
| 135 | - print("Multi-Language Configuration Test") | ||
| 136 | - print("=" * 60) | ||
| 137 | - | ||
| 138 | - success = True | ||
| 139 | - | ||
| 140 | - # Test 1: Configuration loading | ||
| 141 | - if not test_config_loading(): | ||
| 142 | - success = False | ||
| 143 | - | ||
| 144 | - # Test 2: Multi-language query builder | ||
| 145 | - if not test_multilang_query_builder(): | ||
| 146 | - success = False | ||
| 147 | - | ||
| 148 | - print("\n" + "=" * 60) | ||
| 149 | - if success: | ||
| 150 | - print("✓ All tests passed!") | ||
| 151 | - sys.exit(0) | ||
| 152 | - else: | ||
| 153 | - print("✗ Some tests failed") | ||
| 154 | - sys.exit(1) | ||
| 155 | - |
test_search_integration.py deleted
| @@ -1,80 +0,0 @@ | @@ -1,80 +0,0 @@ | ||
| 1 | -#!/usr/bin/env python3 | ||
| 2 | -""" | ||
| 3 | -测试搜索集成的自测脚本 | ||
| 4 | -验证请求上下文和日志系统是否正常工作 | ||
| 5 | -""" | ||
| 6 | - | ||
| 7 | -import sys | ||
| 8 | -import os | ||
| 9 | - | ||
| 10 | -# 添加项目路径 | ||
| 11 | -sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) | ||
| 12 | - | ||
| 13 | -def test_search_integration(): | ||
| 14 | - """测试搜索集成""" | ||
| 15 | - print("🧪 开始搜索集成自测...") | ||
| 16 | - | ||
| 17 | - try: | ||
| 18 | - # 导入模块 | ||
| 19 | - from context.request_context import create_request_context | ||
| 20 | - from utils.logger import get_logger, setup_logging | ||
| 21 | - | ||
| 22 | - # 设置日志 | ||
| 23 | - setup_logging(log_level="INFO", log_dir="test_logs") | ||
| 24 | - logger = get_logger("test") | ||
| 25 | - | ||
| 26 | - print("✅ 模块导入成功") | ||
| 27 | - | ||
| 28 | - # 创建请求上下文 | ||
| 29 | - context = create_request_context("test123", "testuser") | ||
| 30 | - print(f"✅ 请求上下文创建成功: reqid={context.reqid}") | ||
| 31 | - | ||
| 32 | - # 测试日志记录 | ||
| 33 | - context.logger.info("测试日志记录", extra={'reqid': context.reqid, 'uid': context.uid}) | ||
| 34 | - print("✅ 日志记录正常") | ||
| 35 | - | ||
| 36 | - # 测试存储中间结果 | ||
| 37 | - context.store_intermediate_result("test_query", "芭比娃娃") | ||
| 38 | - context.store_intermediate_result("test_language", "zh") | ||
| 39 | - print("✅ 中间结果存储正常") | ||
| 40 | - | ||
| 41 | - # 测试查询分析存储 | ||
| 42 | - context.store_query_analysis( | ||
| 43 | - original_query="芭比娃娃", | ||
| 44 | - normalized_query="芭比娃娃", | ||
| 45 | - rewritten_query="芭比娃娃", | ||
| 46 | - detected_language="zh", | ||
| 47 | - domain="default" | ||
| 48 | - ) | ||
| 49 | - print("✅ 查询分析存储正常") | ||
| 50 | - | ||
| 51 | - # 测试性能摘要 | ||
| 52 | - context.log_performance_summary() | ||
| 53 | - print("✅ 性能摘要记录正常") | ||
| 54 | - | ||
| 55 | - # 测试完整的上下文摘要 | ||
| 56 | - summary = context.get_summary() | ||
| 57 | - print(f"✅ 上下文摘要生成成功,包含 {len(str(summary))} 字符的数据") | ||
| 58 | - | ||
| 59 | - print("\n📊 测试摘要:") | ||
| 60 | - print(f" 请求ID: {summary['request_info']['reqid']}") | ||
| 61 | - print(f" 用户ID: {summary['request_info']['uid']}") | ||
| 62 | - print(f" 查询: '{summary['query_analysis']['original_query']}'") | ||
| 63 | - print(f" 语言: {summary['query_analysis']['detected_language']}") | ||
| 64 | - | ||
| 65 | - print("\n🎉 所有自测通过!搜索集成功能正常工作。") | ||
| 66 | - return True | ||
| 67 | - | ||
| 68 | - except Exception as e: | ||
| 69 | - print(f"❌ 自测失败: {e}") | ||
| 70 | - import traceback | ||
| 71 | - traceback.print_exc() | ||
| 72 | - return False | ||
| 73 | - | ||
| 74 | -if __name__ == "__main__": | ||
| 75 | - success = test_search_integration() | ||
| 76 | - if success: | ||
| 77 | - print("\n✨ 系统已就绪,可以正常处理搜索请求!") | ||
| 78 | - else: | ||
| 79 | - print("\n💥 请检查错误信息并修复问题") | ||
| 80 | - sys.exit(1) | ||
| 81 | \ No newline at end of file | 0 | \ No newline at end of file |