run.sh 8.24 KB
#!/bin/bash

######################
## 因为内容相似 会影响在线服务(打满ES)所以暂时关闭
######################

# 设置 Python 路径,让脚本能找到 db_service, config, deepwalk 等模块
export PYTHONPATH=/home/tw/recommendation/offline_tasks:$PYTHONPATH

cd /home/tw/recommendation/offline_tasks

# mkdir bak___before_rm_run_all_py
# mv output logs nohup.out bak___before_rm_run_all_py/
# mkdir output
# mkdir logs

# 检测并激活conda环境
if [ "$CONDA_DEFAULT_ENV" != "tw" ]; then
    echo "当前环境不是 tw,正在激活 tw 环境..."
    source /home/tw/miniconda3/etc/profile.d/conda.sh
    conda activate tw
    echo "已激活 tw 环境"
else
    echo "当前已经在 tw 环境中,无需重复激活"
fi

# ============================================================================
# 配置区域
# ============================================================================

# 算法参数
LOOKBACK_DAYS=768
TOP_N=50
DEBUG_MODE="--debug"  # 留空则不开启debug

# Redis配置

# 内存监控阈值
MEM_WARN_THRESHOLD=25  # GB
MEM_KILL_THRESHOLD=35  # GB

# ============================================================================
# 工具函数
# ============================================================================

# 内存监控函数
check_memory() {
    local pid=$1
    local task_name=$2
    
    while kill -0 $pid 2>/dev/null; do
        local mem_mb=$(ps -p $pid -o rss= 2>/dev/null | awk '{print int($1/1024)}')
        
        if [ -n "$mem_mb" ]; then
            local mem_gb=$(echo "scale=2; $mem_mb/1024" | bc)
            local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
            
            if [ $(echo "$mem_gb >= $MEM_KILL_THRESHOLD" | bc) -eq 1 ]; then
                echo "[$timestamp] ❌ [$task_name] 内存超限!${mem_gb}GB, 强制终止" | tee -a logs/memory_monitor.log
                kill -9 $pid
                break
            elif [ $(echo "$mem_gb >= $MEM_WARN_THRESHOLD" | bc) -eq 1 ]; then
                echo "[$timestamp] ⚠️  [$task_name] 内存警告: ${mem_gb}GB" | tee -a logs/memory_monitor.log
            fi
        fi
        
        sleep 60
    done
}

# 运行任务函数
run_task() {
    local task_name=$1
    local task_cmd=$2
    
    echo ""
    echo "======================================================================"
    echo "[$task_name] 开始 - $(date '+%Y-%m-%d %H:%M:%S')"
    echo "======================================================================"
    
    eval $task_cmd &
    local pid=$!
    
    # 启动内存监控
    check_memory $pid "$task_name" &
    local monitor_pid=$!
    
    # 等待任务完成
    wait $pid
    local exit_code=$?
    
    # 停止内存监控
    kill $monitor_pid 2>/dev/null
    
    if [ $exit_code -eq 0 ]; then
        echo "✓ [$task_name] 完成"
        return 0
    else
        echo "✗ [$task_name] 失败,退出码: $exit_code"
        return $exit_code
    fi
}

# ============================================================================
# 环境准备
# ============================================================================

# 清理旧进程
ps -ef | grep "python3.*scripts" | grep -v grep | awk '{print $2}' | xargs kill -9 2>/dev/null

# 创建必要目录
mkdir -p logs output

echo "======================================================================"
echo "开始运行离线推荐任务 - $(date '+%Y-%m-%d %H:%M:%S')"
echo "配置: lookback_days=$LOOKBACK_DAYS, top_n=$TOP_N"
echo "内存监控: 警告=${MEM_WARN_THRESHOLD}GB, 终止=${MEM_KILL_THRESHOLD}GB"
echo "======================================================================"

# ============================================================================
# 前置任务
# ============================================================================

# 前置任务1: 获取商品属性
run_task "前置任务1: 获取商品属性" \
    "python3 scripts/fetch_item_attributes.py $DEBUG_MODE"
if [ $? -ne 0 ]; then
    echo "⚠️  商品属性获取失败,但继续执行"
fi

# 前置任务2: 生成Session文件
run_task "前置任务2: 生成Session文件" \
    "python3 scripts/generate_session.py --lookback_days $LOOKBACK_DAYS --format both $DEBUG_MODE"
if [ $? -ne 0 ]; then  
    echo "❌ Session文件生成失败,退出"
    exit 1
fi

# 前置任务3: C++ Swing算法
echo ""
echo "======================================================================"
echo "[前置任务3: C++ Swing算法] 开始 - $(date '+%Y-%m-%d %H:%M:%S')"
echo "======================================================================"
cd collaboration
bash run.sh
SWING_EXIT=$?
cd ..

if [ $SWING_EXIT -eq 0 ]; then
    echo "✓ [前置任务3: C++ Swing算法] 完成"
else
    echo "⚠️  [前置任务3: C++ Swing算法] 失败,但继续执行"
fi

# ============================================================================
# i2i相似度任务
# ============================================================================

# Task 1: Python Swing算法
run_task "Task 1: Python Swing算法" \
    "python3 scripts/i2i_swing.py --lookback_days $LOOKBACK_DAYS --top_n $TOP_N --use_daily_session $DEBUG_MODE"
if [ $? -ne 0 ]; then
    echo "⚠️  Python Swing失败,但继续执行"
fi

# Task 2: Session W2V
run_task "Task 2: Session W2V" \
    "python3 scripts/i2i_session_w2v.py --lookback_days $LOOKBACK_DAYS --top_n $TOP_N --save_model $DEBUG_MODE"
if [ $? -ne 0 ]; then
    echo "⚠️  Session W2V失败,但继续执行"
fi

# Task 3: DeepWalk
run_task "Task 3: DeepWalk" \
    "python3 scripts/i2i_deepwalk.py --lookback_days $LOOKBACK_DAYS --top_n $TOP_N --save_model --save_graph $DEBUG_MODE"
if [ $? -ne 0 ]; then
    echo "⚠️  DeepWalk失败,但继续执行"
fi
# 
# # Task 4: 内容相似度
# run_task "Task 4: 内容相似度" \
#     "python3 scripts/i2i_content_similar.py --top_n $TOP_N $DEBUG_MODE"
# if [ $? -ne 0 ]; then
#     echo "⚠️  内容相似度失败,但继续执行"
# fi
# 
# Task 5: Item行为相似度
run_task "Task 5: Item行为相似度" \
    "python3 scripts/i2i_item_behavior.py --lookback_days $LOOKBACK_DAYS --top_n $TOP_N $DEBUG_MODE"
if [ $? -ne 0 ]; then
    echo "⚠️  Item行为相似度失败,但继续执行"
fi

# Task 6: Tag分类相似度
run_task "Task 6: Tag分类相似度" \
    "python3 scripts/tag_category_similar.py --lookback_days $LOOKBACK_DAYS --top_n $TOP_N $DEBUG_MODE"
if [ $? -ne 0 ]; then
    echo "⚠️  Tag分类相似度失败,但继续执行"
fi

# ============================================================================
# 兴趣聚合任务
# ============================================================================

# Task 7: 兴趣聚合
run_task "Task 7: 兴趣聚合" \
    "python3 scripts/interest_aggregation.py --lookback_days $LOOKBACK_DAYS --top_n 1000 $DEBUG_MODE"
if [ $? -ne 0 ]; then
    echo "⚠️  兴趣聚合失败,但继续执行"
fi

# ============================================================================
# 加载到Redis
# ============================================================================

echo ""
echo "======================================================================"
echo "[加载到Redis] 开始 - $(date '+%Y-%m-%d %H:%M:%S')"
echo "======================================================================"

python3 scripts/load_index_to_redis.py
LOAD_EXIT=$?

if [ $LOAD_EXIT -eq 0 ]; then
    echo "✓ [加载到Redis] 完成"
else
    echo "❌ [加载到Redis] 失败,退出码: $LOAD_EXIT"
    exit 1
fi

# ============================================================================
# 完成
# ============================================================================

echo ""
echo "======================================================================"
echo "所有任务完成 - $(date '+%Y-%m-%d %H:%M:%S')"
echo "======================================================================"
echo ""
echo "输出文件位置:"
echo "  - 商品属性: output/item_attributes_mappings.json"
echo "  - Session文件: output/session.txt.*"
echo "  - C++ Swing: collaboration/output/swing_similar.txt"
echo "  - Python算法: output/i2i_*.txt"
echo "  - Item行为相似度: output/i2i_item_behavior_*.txt"
echo "  - Tag分类相似度: output/tag_category_similar_*.txt"
echo "  - 兴趣聚合: output/interest_aggregation_*.txt"
echo "  - 日志: logs/"
echo ""