# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## 项目概述

百度商业AI技术创新大赛 (CTI) 2026 — **生成式推荐广告排序推理性能优化**。

目标：给定 GRAB Transformer 模型，在**不改模型结构、不在测试集训练**的前提下，极致优化推理性能。量化/稀疏/剪枝明确允许。

## 环境与常用命令

```powershell
# 激活虚拟环境
.\.venv\Scripts\Activate.ps1

# 本地运行推理（需要 dataset/ 和 ckpt.pt）
.\.venv\Scripts\python.exe 代码\code\infer.py
.\.venv\Scripts\python.exe 代码\code\infer.py --ckpt path/to/ckpt.pt

# AI Studio SDK（下载数据集、提交）
.\.venv\Scripts\aistudio.exe download --dataset <id> --local_dir ./dataset --token <token>
.\.venv\Scripts\aistudio.exe download --model <id> --local_dir . --token <token>

# 打包提交
cd 代码/code && zip -r ../../submit.zip infer.py requirements.txt build_env.sh
```

本地环境仅装 `numpy` + `tqdm` + `aistudio-sdk`（轻量），完整 PyTorch 依赖见 `代码/code/requirements.txt`，训练/推理在服务端跑。

## 代码架构

```
infer.py  (单文件，~730 行，所有逻辑集中于此)
├── 数据加载层
│   ├── _detect_has_clk()          — 检测 CSV 是否有 clk 列
│   ├── load_sample_files()        — 加载 CSV → item_dict + user_seq
│   ├── load_logids_from_file()    — 快速提取文件中所有 logid
│   └── CTRUserDataset(Dataset)    — 按用户组织的 CTR 数据集
│       └── make_collate_fn()      — 将用户样本拼接为 batch（含 slot 特征展开）
├── 模型层
│   ├── RepEncoder                 — Slot-wise Embedding → LayerNorm → Linear
│   │   └── Embedding(5M vocab, 512d) × 28 slots → segment_reduce(sum) → concat
│   ├── TransformerEncoder (8 层)
│   │   ├── QKV Projection → Multi-Head Attention (scaled_dot_product)
│   │   ├── SMoE FFN（8 experts, Top-2 gating, 每层独立）
│   │   └── Pre-LayerNorm + Residual
│   ├── CTRModel                   — RepEncoder + Transformer → Linear → logit
│   │   └── Causal mask: 同一用户的 tokens 因果遮罩，不同用户隔离
│   └── load_model(ckpt_path, device) — 模型构建 + 权重加载入口
├── 推理循环 (main)
│   ├── 数据加载（优先缓存 shard_*.pt）
│   ├── 逐 batch 推理 + 计时（只计 model(batch) 耗时）
│   └── 按 test.csv 顺序写 predict.txt
└── 打分工具
    └── _cal_score() — AUC + PCOC + latency → score_all
```

**模型参数规模**：Embedding 5M×512 + 8 层 Transformer (d_model=512, n_heads=8, dim_ff=1024) × MoE(8 experts) ≈ ~6.5M~11.3M 参数。

## 关键接口（评测系统调用契约）

评测系统通过 `from infer import ...` 加载代码，以下是**必须**对齐的接口（来自 `代码/任务提交接口说明.md`）：

| 接口 | 签名 | 说明 |
|------|------|------|
| `load_sample_files` | `(sample_files_list: List[Path]) -> (item_dict, user_seq)` | 数据加载 |
| `CTRTestSeqDataset` | `(test_logids_ordered, item_dict, user_seq, max_feasign_per_slot, max_ctx_len)` | **必须有 `max_slot_id` 属性** |
| `make_collate_fn` | `(max_slot_id) -> Callable` | DataLoader 的 collate_fn |
| `load_model` | `(ckpt_path: Path) -> (model, device)` | 第一个参数是 Path |
| `move_batch_to_device` | `(batch, device) -> batch` | |
| `model(batch)` | `-> (logits, moe_loss)` | logits 经 sigmoid 后是点击概率 |

**致命不匹配**（baseline `infer.py` 当前存在，提交前必须修复）：
1. 类名 `CTRUserDataset` → 应为 `CTRTestSeqDataset`
2. 构造参数 `pred_logids` → 应为 `test_logids_ordered`，缺少 `max_ctx_len`
3. `load_model(device='cuda:0', ckpt_path=None)` → 应为 `load_model(ckpt_path, device='cuda:0')`（Path 作为第一参数）

## 提交规范

### 压缩包结构
```
submit.zip
├── infer.py              # 必需，实现上述全部接口
├── requirements.txt      # 可选，阿里云 PyPI 镜像安装
└── build_env.sh          # 可选，超时 720s，非 0 退出即失败
```

### 硬约束（任一违反 → 总分 0）
- 推理耗时 < 300s（只计 `model(batch)` 逐 batch 累加）
- AUC ∈ [0.65, 1.0]，PCOC ∈ [0.85, 1.15]
- 压缩包内**不能**有 `dataset/` 或 `ckpt.pt`
- 包后缀只能是 `.zip`/`.tar.gz`/`.tar`，解压后文件在根目录
- 每天最多提交 10 次

### 总分公式
```
score_latency = max(0, (300 - latency) / 300)
score_model   = ((AUC - 0.65) * 1000 + (0.15 - |PCOC - 1|) / 0.15 * 10) / 360
score_all     = score_latency * 70 + score_model * 30
```

### 评测环境

- **硬件**: NVIDIA A800 (80GB, SM80)
- **软件**: Python 3.10 + PyTorch 2.6.0
- **评测数据集 ≠ baseline 数据集**（AUC 天然有差异）

### 优化合规边界（来自官方 Q&A）

| 操作 | 状态 | 说明 |
|------|------|------|
| 量化（FP16/INT8） | ✅ 允许 | |
| Flash Attention | ✅ 允许 | 数学等价实现 |
| 参数级剪枝/稀疏化（权重置零/mask，形状不变） | ✅ 允许 | 权重矩阵大小、层数、head 数、FFN 维度均不变 |
| 减少 Transformer 层数 | ❌ 违规 | 改变组网结构 |
| 减少 hidden 维度 | ❌ 违规 | 改变张量形状 |
| 删除 attention head | ❌ 违规 | 改变组网结构 |
| 减少 FFN channel | ❌ 违规 | 改变组网结构 |
| 序列采样/截断 | ❌ 违规 | |
| 对测试集训练 | ❌ 违规 | |

**策略指标以 baseline 为上限**，指标下降会扣分，超出范围直接 0 分。

## 数据分析

### 数据规模

| 维度 | 数值 |
|------|------|
| 历史数据 | 15 文件 × ~650K 行 = **923 万行**，15GB |
| 测试集 | **7,774 条预测**，13MB |
| 缓存 batch | 9 个 shard，17GB，共 **2,039 batch** |
| Slot 数量 | 1-28（28 个特征槽） |

### 数据格式

```
# History（5 列，含 clk）:
logid,userid,adid,clk,timestamp,sign:slot,...

# Test（4 列，无 clk）:
logid,userid,adid,timestamp,sign:slot,...
```

### 特征分布特征

1. **Slot 28 是瓶颈槽位**：每个样本含 30-50 个 `sign:28` 特征，远超其他 slot。`segment_reduce` 在 slot 28 上占据 RepEncoder 最大开销。
2. **Slot 19 高度冗余**：同一样本内连续出现大量相同 `sign:19`（如 `96:19` 重复 40+ 次）。在 `segment_reduce(sum)` 中，N 个相同 sign 等价于 `N × emb`，但代码独立查表 N 次再求和，浪费 embedding 带宽。
3. **特征极度稀疏**：百万级 sign id，每个样本仅 100-200 个 sign。Embedding 查表是主要内存瓶颈。

### 数据驱动的可优化方向

| 方向 | 合规性 | 预估收益 | 说明 |
|------|--------|----------|------|
| Slot 19 同值合并 | ⚠️ | 小 | N 个相同 sign 合并为 `N × emb`，减少 embedding 查表次数。属数据预处理灰区 |
| Slot 28 segment_reduce 融合 | ✅ | 中 | 将 slot 28 的大量 sign 预先按 offset 分桶，减少 kernel launch |
| Embedding 查表带宽 | ✅ | 小 | 已用 FP16，embedding 5M×512 约 5GB |

## 优化路线图（来自 `推理优化方案.md`）

Baseline 数据：推理 229s，AUC 0.759，PCOC 1.110，得分 25.85。

1. ✅ **接口对齐** — 确认能在评测系统跑通（得分 > 0）
2. ✅ **FP16 量化** — `model.half()`，Embedding 保留 FP32，152s
3. ✅ **Flash Attention** — 替换 `scaled_dot_product` 为 `F.scaled_dot_product_attention`，94.5s
4. ✅ **inference_mode()** — 替代 `no_grad()`，92.5s（+2s 小幅提升）
5. ❌ **torch.compile** — reduce-overhead 和 default 模式均因动态 batch 形状反效果，彻底放弃
6. ❌ **MoE Top-1 gating** — PCOC 从 1.059 炸到 2.075，已回退
7. ❌ **2:4 结构化稀疏** — PCOC 炸到 2.067，耗时反增 265s。to_sparse_semi_structured 与 nn.Linear 不兼容
8. ✅ **SMoE 消除 GPU 同步** — 移除 mask.any()（64 次 GPU→CPU 同步/forward），88.1s

CUDA Graph 已评估并放弃（batch 形状不固定，不适用）。

每步完成后必须在 AI Studio 提交验证，AUC/PCOC 不达标立即回退。

## 关键文件

| 路径 | 用途 |
|------|------|
| `代码/code/infer.py` | 推理主脚本（提交的核心文件） |
| `代码/code/requirements.txt` | 服务端依赖（torch 2.6.0 + CUDA 12.4） |
| `代码/code/build_env.sh` | 环境构建脚本（目前为空壳） |
| `代码/任务提交接口说明.md` | 官方接口规范 |
| `推理优化方案.md` | 完整优化方案（含合规审查） |
| `论文/GRAB_*.pdf` | GRAB 论文（baseline 模型） |
| `论文/HSTU_*.pdf` | HSTU 论文（架构基础） |
| `.gitignore` | 排除 ckpt.pt, dataset/, *.zip, .venv/ |

## 提交记录

| 日期 | 提交次数 | 得分 | AUC | PCOC | 耗时 | 优化手段 | 备注 |
|------|----------|------|-----|------|------|----------|------|
| 06/13 | 12 | **58.49** | 0.7526 | 1.059 | 88.1s | + SMoE 消除 GPU 同步 | **当前最优** |
| 06/13 | 11 | 0 | 0.748 | 2.067 | 265.5s | 2:4 sparse | ❌ 炸毁 |
| 06/13 | 10 | 57.45 | 0.7526 | 1.059 | 92.5s | + inference_mode | |
| 06/13 | 9 | 51.42 | 0.7525 | 1.059 | 118.4s | + compile(default) | 反效果 |
| 06/12 | 8 | 0 | 0.736 | 2.075 | 119.6s | MoE k=1 + compile | PCOC 炸毁 |
| 06/12 | 6 | 56.98 | 0.7526 | 1.059 | 94.5s | + Flash Attention | |
| 06/12 | 3 | 43.55 | 0.7525 | 1.059 | 152s | + FP16 量化 | |
