# 选手提交压缩包规范

本文档说明选手提交代码压缩包的格式与运行要求。不符合以下任一约束，评测将失败或总分计 0。

---

## 1. 压缩包格式

- **允许的后缀**：`.zip`、`.tar.gz`、`.tar`。其他后缀评测会直接失败。
- **目录布局**：压缩包解压后，所有文件必须**直接位于根目录**，不得包含最外层包裹目录。

错误示例（解压后多一层目录）：
```
submit.zip
└── my_code/
    └── infer.py
```

正确示例：
```
submit.zip
├── infer.py
├── requirements.txt    # 可选
└── build_env.sh        # 可选
```

---

## 2. 必需文件

### 2.1 `infer.py`（必需）

根目录必须存在可被 Python 正常 `import` 的 `infer` 模块（即 `infer.py` 或 `infer/__init__.py`），并对外提供以下接口：

| 接口 | 签名 / 说明 |
|------|-------------|
| `load_sample_files` | `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` | `make_collate_fn(max_slot_id) -> Callable`，用作 `DataLoader` 的 `collate_fn` |
| `load_model` | `load_model(ckpt_path: Path) -> (model, device)` |
| `move_batch_to_device` | `move_batch_to_device(batch, device) -> batch` |
| `model(batch)` | 前向返回 `(logits, moe_loss)`；`logits.squeeze(-1)` 经 `sigmoid` 应为点击概率 |

`batch` 必须包含以下键：
- `logid`：样本 logid，需支持 `.shape[0]` 与 `[pred_mask].cpu().tolist()`
- `pred_mask`：可转 `bool` 的掩码 Tensor

### 2.2 评测端提供、选手**不得**自带的文件

评测端会统一提供下列路径，选手**不要**在压缩包中包含同名文件/目录：

- `dataset/`：测试与历史数据
- `ckpt.pt`：模型权重

---

## 3. 可选文件

| 文件 | 行为 | 失败条件 |
|------|------|----------|
| `requirements.txt` | 评测前安装依赖（使用阿里云 PyPI 镜像：`https://mirrors.aliyun.com/pypi/simple`） | 安装失败则评测失败 |
| `build_env.sh` | 在代码根目录下执行 `sh build_env.sh`，**超时 720 秒** | 超时或返回码非 0 则评测失败 |

依赖必须可通过阿里云 PyPI 镜像安装；`build_env.sh` 若需访问外部资源，请自行保证在 720 秒内完成。

---

## 4. 运行时与指标约束

### 4.1 推理延迟

- 延迟阈值：**300 秒**。
- 只统计**模型前向**时间（逐 batch 累加 `model(batch)` 耗时），数据加载、模型加载不计入。
- 延迟得分：`score_latency = (300 - latency) / 300`。
- 若 `latency ≥ 300`，`score_latency = 0`，**总分直接置 0**。

### 4.2 模型指标门槛

以下任一不满足，策略分 `score_model = 0`，**总分直接置 0**：

- `AUC ∈ [0.65, 1.0]`
- `PCOC ∈ [0.85, 1.15]`，其中 `PCOC = mean(predictions) / mean(labels)`

### 4.3 总分公式

仅当 `score_latency > 0` 且 `score_model > 0` 时：

```
score_all = score_latency * 70 + score_model * 30
```

否则 `score_all = 0`。

---

## 5. 违规清单（评测失败或 0 分）

1. 压缩包后缀非 `.zip` / `.tar.gz` / `.tar`。
2. 压缩包内含最外层包裹目录，导致根目录找不到 `infer.py`。
3. 缺失 `infer.py`，或其任一必需接口签名/返回值结构不符。
4. `requirements.txt` 安装失败。
5. `build_env.sh` 执行超过 720 秒或返回码非 0。
6. 推理总耗时 ≥ 300 秒。
7. `AUC` 不在 `[0.65, 1.0]` 或 `PCOC` 不在 `[0.85, 1.15]`。
8. 压缩包自带 `dataset/` 或 `ckpt.pt`，覆盖评测端提供的路径。

---

## 6. 最小可用提交示例

```
submit.zip
├── infer.py              # 实现第 2.1 节全部接口
└── requirements.txt      # 可选；列出 torch 等依赖
```