# Debug Model by Demo

用 `chatbot_mdm_block_causal.py` 跑 demo samples，读取真实 stdout 和 block-causal 解码 trace，然后做 LLM-as-Judge 质量分析。

## Usage Examples

```bash
# 用 checkpoint 路径
/debug-model-by-demo output_models/fastdllmv2_mmfr_8node_bd32_block_causal_no_dynamic_lr_1e-5_ds/checkpoint-300

# 用实验名（自动找最新 checkpoint）
/debug-model-by-demo fastdllmv2_mmfr_8node_bd32_block_causal_no_dynamic_lr_1e-5_ds

# 指定解码参数（与 chatbot_mdm_block_causal.py 对齐）
/debug-model-by-demo output_models/.../checkpoint-300 --block-size 16 --max-tokens 512 --threshold 0.9 --sub-block-size 8
```

## Execution Steps

### Step 1: Parse Input & Find Checkpoint

| Input Type | Detection | How to Find |
|------------|-----------|-------------|
| Checkpoint path | contains `checkpoint-` | Use directly |
| Experiment name or output_models/ path | no `checkpoint-` | `ls output_models/{name}/checkpoint-* \| sort -V \| tail -1` to find latest |
| Training script (.sh) | ends with `.sh` | Extract RUN_ID, then find latest checkpoint |

### Step 2: Activate Environment & Run Demo (MUST Save Full Log)

```bash
source /lustre/fsw/portfolios/nvr/users/chengyuew/anaconda3/etc/profile.d/conda.sh
conda activate dvlm

RUN_TS=$(date +%Y%m%d_%H%M%S)
EXP_NAME="{experiment_name}"
CKPT_NAME=$(basename "{checkpoint_path}")
LOG_DIR="log/${EXP_NAME}"
mkdir -p "${LOG_DIR}"
LOG_FILE="${LOG_DIR}/demo_debug_${CKPT_NAME}_${RUN_TS}.log"

CUDA_VISIBLE_DEVICES=0 python3 chengyue_script/dvlm/inference/chatbot_mdm_block_causal.py \
  --model-name {checkpoint_path} \
  --processor-name Qwen/Qwen2.5-VL-3B-Instruct \
  --demo \
  --block-size {block_size:-32} \
  --max-tokens {max_tokens:-1024} \
  --threshold {threshold:-0.9} \
  --sub-block-size {sub_block_size:-8} \
  > "${LOG_FILE}" 2>&1
```

**Important behavior (current implementation):**
- `chatbot_mdm_block_causal.py` 没有 `--debug` / `--output-file` 参数，不要传这两个参数。
- 该脚本内部已固定 `debug=True`，trace 文件固定写到 `decoded_output_inference.txt`。
- 每个 sample 会覆盖写该文件；跑完整个 `--demo` 后，文件通常只保留最后一个 sample 的 trace。
- `LOG_FILE` 是主分析依据，避免终端输出截断导致漏信息。

**Timeout**: 建议 600s（10 min）。9 个 demo sample 单卡通常约 5-8 分钟。

### Step 3: Collect Outputs

优先从 `LOG_FILE` 解析（不要只看终端）。每个 sample 典型结构：
```
================================================================================
Sample {i}/{N}
================================================================================
Image: {image_path}
Prompt: {prompt}
--------------------------------------------------------------------------------
step: {total_steps} gen_length: {gen_length}
Output:
{generated_text}
```

备注：
- `step/gen_length` 来自底层采样函数 stdout 打印。
- 不会打印 `Raw trace: ...` 路径行。

#### 3.1 Required Artifacts (MUST)

最终回复必须明确给出：

1. `checkpoint_path`（本次跑的是哪个 checkpoint）
2. `LOG_FILE`（完整 demo 原始输出路径）
3. `decoded_output_inference.txt`（trace 路径，且声明只覆盖最后 sample）

#### 3.2 Required Output Evidence (MUST)

最终回复必须贴 **原始 demo output 原文**，要求：

1. 默认贴 9 个 sample 的 `Output:` 原文（可用代码块）
2. 如果单条过长，可截断，但必须标记 `[truncated]`，并保留开头和结尾关键段
3. 至少额外给 3 个“问题证据”引用（如重复词、错误答案、格式损坏）

建议引用格式：

```text
Sample 4 raw output excerpt:
"Sure, let's analyze the the graph..."
"(A) Political instability instability leading to population decline"
```

### Step 4: Read & Analyze Raw Decoding Trace

读取 `decoded_output_inference.txt`，trace 形态通常为：

```
begin block causal sampling with sampling controls
Generation configs: block_size=..., force_left_to_right=False, ...
--------------------------------------------------
input_ids: ...
--------------------------------------------------
step 1
decoded x_t: ...
...
```

#### 4.1 Raw Trace Analysis

对可获取的 trace 报告：

| Trace Source | Related Sample | Total Steps | Tokens Generated | Avg Tok/Step | Decoding Pattern | Issues |
|---|---|---|---|---|---|---|
| decoded_output_inference.txt | Last sample in current run | ... | ... | ... | ... | ... |

**Decoding pattern categories**:
- **Smooth L2R**: 近似左到右推进，几乎无停滞
- **L2R with pauses**: 存在低效步（单步推进非常少）
- **Non-monotonic**: 置信度并行解掩码导致非严格 L2R（本脚本 `force_left_to_right=False`）
- **Repetition**: 连续重复 token/短语

**Issues to flag**:
- Repetitive tokens（如 `"and and and"`）
- Gibberish tokens 或编码异常
- Early stop（过早 EOS）
- Max token exhaustion（到 `max_tokens` 仍未结束）

### Step 5: LLM-as-Judge Quality Analysis

收集全部 sample 的最终输出文本后再做质量分析。

#### 5.1 Per-Sample Analysis Table

| # | Type | Prompt (short) | gen_length | total_steps | Quality | Notes |
|---|------|----------------|------------|-------------|---------|-------|
| 1 | Text | Who are you? | ... | ... | ⬤ Good/OK/Bad | ... |
| 2 | Text+Math | Natalia clips | ... | ... | ⬤ Good/OK/Bad | ... |
| 3 | Text+Math | Deep-sea monster | ... | ... | ⬤ Good/OK/Bad | ... |
| 4 | VLM+MCQ | MMMU Pro | ... | ... | ⬤ Good/OK/Bad | ... |
| 5 | VLM+Short | ChartQA | ... | ... | ⬤ Good/OK/Bad | ... |
| 6 | VLM+Desc | Beach dog | ... | ... | ⬤ Good/OK/Bad | ... |
| 7 | VLM+Math | Spring physics | ... | ... | ⬤ Good/OK/Bad | ... |
| 8 | VLM+MCQ | Triangle geometry | ... | ... | ⬤ Good/OK/Bad | ... |
| 9 | VLM+Math | Number puzzle | ... | ... | ⬤ Good/OK/Bad | ... |

Quality legend:
- ⬤ Good: 正确且连贯
- ⬤ OK: 基本合理但有明显瑕疵
- ⬤ Bad: 错误或不连贯

#### 5.2 Judge Criteria

对每个 sample 评估：

1. **Correctness**（数学/选择题优先）
   - Natalia clips: 应为 72
   - Deep-sea monster: 应为 121
   - Spring physics: \(d \approx 0.0115\mathrm{m}\)（或等价表达）
   - Triangle: C (120°)
   - Number puzzle: 检查推理链是否自洽
2. **Coherence**: 是否逻辑连贯、无明显重复或乱码
3. **Relevance**: 是否回答了问题本身
4. **Completeness**: 图像描述类是否覆盖关键视觉要素
5. **Format**: MCQ 是否按要求给出答案格式
6. **Trace Consistency**: trace 中是否出现异常解码迹象

#### 5.3 Summary

```
## Demo Quality Summary: {experiment_name} / {checkpoint}

**Overall**: {X}/9 Good, {Y}/9 OK, {Z}/9 Bad
**Text-only**: {score}/3
**VLM**: {score}/6
**Math reasoning**: {score}/4 correct
**Avg gen_length**: {N}
**Avg total_steps**: {N}

### Decoding Health (from available trace files)
- Trace files read: {file_list}
- Coverage: {which samples have trace}
- Repetition incidents: {N}
- Max token exhaustions: {N}

### Strengths
- ...

### Weaknesses
- ...
```

#### 5.4 Evidence-Driven Diagnosis (MUST)

除汇总分数外，必须给“带原文证据”的诊断：

1. **至少 1 个正例**（正确且连贯）
2. **至少 2 个负例**（错误/重复/截断/格式损坏）
3. 每个例子都要包含：
   - sample 编号
   - 原文片段（verbatim）
   - 为什么判定为 Good/OK/Bad
   - 对应风险类型（accuracy / coherence / format / truncation）

## Anti-Hallucination Protocol

1. **MUST run actual inference**，不能伪造输出
2. **MUST read actual stdout outputs**，不能猜答案
3. **MUST read `decoded_output_inference.txt`**，并明确说明 trace 覆盖范围（通常只覆盖最后一个 sample）
4. **Judge ONLY based on model outputs**，不能按“预期答案”脑补
5. **For math**: 手工校验计算链，不只看最终数字
6. **If inference fails**: 直接报告报错，不得用想象结果替代
7. **MUST cite artifact paths**: 至少包含 `LOG_FILE` 和 trace 文件路径
8. **MUST include verbatim evidence**: 不能只给抽象结论，必须贴原文例子
9. **MUST distinguish observed vs inferred**: 观察到的原文和主观判断分开写

## Demo Samples Reference

当前 `chatbot_mdm_block_causal.py` 的 9 个 demo sample：

| # | Type | Image | Expected Answer |
|---|------|-------|-----------------|
| 1 | Text-only | None | Identity/greeting |
| 2 | Text math | None | 72 clips |
| 3 | Text math | None | 121 people |
| 4 | VLM MCQ | mmmu_pro.png | Depends on image content |
| 5 | VLM short | chart_qa.png | Depends on chart |
| 6 | VLM description | beach_dog.jpeg | Scene description |
| 7 | VLM physics | mathvista_physics.png | d ≈ 0.0115 m |
| 8 | VLM geometry | mathverse.jpg | C: 120° |
| 9 | VLM puzzle | mathvision.jpg | Depends on image |

## Key Files

| File | Purpose |
|------|---------|
| `chengyue_script/dvlm/inference/chatbot_mdm_block_causal.py` | Demo inference entry（当前命令应调用） |
| `chengyue_script/dvlm/models/generation_functions.py` | `block_causal_sample_cache`（trace 写入逻辑） |
| `chengyue_script/dvlm/demo_images/` | Demo images directory |
| `log/{experiment_name}/demo_debug_{checkpoint}_{timestamp}.log` | 本次 demo 完整原始输出（主分析依据） |
| `decoded_output_inference.txt` | 当前实现的 trace 文件（通常仅最后 sample） |
