# AIMO-2
> Last updated: 2026-01-23
> Source count: 1
---

### AIMO-2 (2025) - 2025-01-22
**Source:** [Kaggle Competition](https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-2) | [Paper](https://arxiv.org/abs/2504.16891)
**Category:** NLP/LLM (数学推理)
**Key Techniques:**
- **MARIO 框架**: MAth Reasoning with code Interpreter
- **代码执行集成**: Python 代码在沙盒中执行
- **OpenMathReasoning 数据集**: ~290K 高质量数学问题，3.2M CoT，1.7M TIR
- **三阶段训练**: CoT → TIR → GenSelect
- **GenSelect**: 多答案生成 + 基于排序的投票
- **Qwen2.5 架构**: 1.5B/7B/14B/32B 模型家族
- **自一致性 + TIR**: 32 候答案生成 + 多数投票
- **AoPS 数据源**: 从 Art of Problem Solving 论坛提取

**Results:** NVIDIA (NemoSkills) 34/50 正确 (68%), OpenMath-Nemotron-32B 达到 SOTA

---

## Competition Brief (竞赛简介)

### AIMO-2 - AI Mathematical Olympiad Progress Prize 2

**竞赛背景：**
- **主办方**：AIMO (AI Mathematical Olympiad)
- **目标**：解决国家奥林匹克级数学问题
- **特殊性质**：测试 AI 的**数学推理能力**，不是传统 NLP 任务

**竞赛规模：**
- **问题数量**: 50 道国家奥林匹克级数学问题
- **时间限制**: 5 小时解决所有问题
- **总队伍数**: 约 100+ teams
- **奖项池**: >$2,000,000

**任务格式：**
```
数学问题文本
    ↓
生成解决方案（推理 + 代码）
    ↓
执行代码（如有）
    ↓
提取最终答案
```

**评估指标：**
- **准确率**: 完全正确才算对（34/50 = 68%）
- **答案格式**: 多选题（A-E）或数值答案
- **时间限制**: 5 小时，平均每题 6 分钟

**关键洞察：**
1. **代码执行是关键**: 纯 LLM 推理不够，需要代码执行进行计算
2. **数据质量 > 数量**: 从 AoPS 提取的高质量数据
3. **三阶段训练有效**: CoT → TIR → GenSelect
4. **小模型可以很强**: 1.5B 模型达到有竞争力的性能
5. **自一致性 + 排序投票**: 比简单多数投票更有效

**前排方案总结（Top 12+）：**

| 排名 | 队伍 | 正确数 | 核心技术 | 模型 | 推理引擎 |
|------|------|--------|---------|------|---------|
| **1st** | NVIDIA (NemoSkills) | 34/50 | MARIO, TIR, GenSelect, OpenMathReasoning | Qwen2.5-14B | TensorRT-LLM |
| **2nd** | imagination-research | ~30/50 | SFT + DPO (长度优化), 代码执行 | DeepSeek-R1-Distill-Qwen-14B | lmdeploy |
| **3rd** | Aliev | ~29/50 | Self-consistency, Early stopping | DeepSeek-R1-Distill-Qwen-14B AWQ | vLLM |
| **4th** | Soren Ravn Andersen | ~28/50 | AWQ 量化, Self-consistency | DeepSeek-R1-Distill-Qwen-14B AWQ | vLLM |
| **5th** | usernam | ~27/50 | lmdeploy 高吞吐量 | DeepSeek-R1-Distill-Qwen-14B AWQ | lmdeploy |
| **7th** | tascj | ~26/50 | AWQ 量化 | DeepSeek-R1-Distill-Qwen-14B AWQ | lmdeploy |
| **8th** | MPWARE | ~25/50 | 自定义 AWQ 量化, Self-consistency | DeepSeek-R1-Distill-Qwen-14B AWQ | vLLM |
| **9th** | Fast-Math-R1–14B | ~24/50 | SFT + GRPO (效率优化) | Fine-tuned DeepSeek-R1-Distill-Qwen-14B | - |
| **11th** | farsail | ~22/50 | One-shot prompting, 自定义 vLLM | DeepSeek-R1-Distill-Qwen-14B AWQ | vLLM |
| **17th** | ippeiogawa | ~18/50 | Multi-stage prompting, 代码生成 | DeepSeek-R1-Distill-Qwen-14B AWQ | vLLM |
| **20th** | Arek Paterek | ~15/50 | AWQ 量化 | DeepSeek-R1-Distill-Qwen-32B AWQ | - |
| **22nd** | K-Piece | ~13/50 | Base model + prompting | DeepSeek-R1 系列 | - |

**技术趋势分析：**

1. **模型选择**：几乎所有前排方案都使用 `DeepSeek-R1-Distill-Qwen-14B AWQ`（4-bit 量化）
2. **微调方法**：
   - **SFT**：几乎所有队伍的基础起点
   - **DPO**：第 2 名用于减少输出长度
   - **TIR**：第 1 名的核心创新（工具集成推理）
   - **GRPO**：第 9 名尝试用于效率优化（结果不稳定）
3. **推理引擎**：
   - **vLLM**：最常用（4th, 7th, 8th, 11th, 17th）
   - **lmdeploy**：高吞吐量选择（2nd, 5th, 7th）
   - **TensorRT-LLM**：第 1 名专用
4. **推理策略**：
   - **Self-consistency/Majority voting**：通用标配
   - **Early stopping**：节省时间和 tokens
   - **代码执行**：提升计算精度

**核心创新 - MARIO 框架（1st Place）：**
- **MA**: Math（数学推理）
- **RI**: Reasoning（推理）+ Interpreter（代码解释器）
- **O**: Open（开源）

**数据集规模：**
- OpenMathReasoning: ~290K 问题
- 3.2M CoT（长思维链）
- 1.7M TIR（工具集成推理）

#### 前排方案详细技术分析

**1st Place - NVIDIA (NemoSkills) - 34/50 (68%)**

核心技巧：
- **MARIO 框架**：Math + Reasoning + Interpreter 整合
- **OpenMathReasoning 数据集**：从 AoPS 提取的 ~290K 高质量数据
- **三阶段训练**：CoT → TIR → GenSelect 逐步训练
- **代码执行集成**：Python 代码在沙盒中执行
- **GenSelect 策略**：32 候选答案 + 基于排序的投票

实现细节：
- Qwen2.5-14B 主模型，TensorRT-LLM 推理优化
- CoT：长思维链推理，提取推理过程
- TIR：生成推理 + Python 代码，代码执行验证结果
- GenSelect：32 候选答案，基于推理质量排序选择
- 数据：3.2M CoT + 1.7M TIR 格式
- 最终成绩：34/50 正确（68%）

**2nd Place - imagination-research - ~30/50 (60%)**

核心技巧：
- **SFT + DPO 组合**：监督微调 + 直接偏好优化
- **DPO 长度优化**：第 2 阶段减少输出长度，提升效率
- **代码执行集成**：Python 代码生成和执行
- **DeepSeek-R1-Distill-Qwen-14B AWQ**：4-bit 量化模型

实现细节：
- SFT：OpenR1 Math + Light-R1 数据集监督微调
- DPO：第 2 阶段训练，优化输出长度和推理质量
- 量化：AWQ 4-bit 量化，降低内存占用
- 推理引擎：lmdeploy 高吞吐量推理
- 最终成绩：~30/50 正确

**3rd Place - Aliev - ~29/50 (58%)**

核心技巧：
- **Self-consistency**：自洽性，生成多个解取最频繁答案
- **Early stopping**：提前停止节省推理时间
- **DeepSeek-R1-Distill-Qwen-14B AWQ**：4-bit 量化
- **vLLM 推理引擎**：高效推理框架

实现细节：
- Self-consistency：生成多个候选答案，多数投票
- Early stopping：前 5 个候选中出现 4 个相同则停止
- vLLM：PagedAttention 高效内存管理
- 量化：AWQ Activation-aware Weight Quantization
- 最终成绩：~29/50 正确

**4th Place - Soren Ravn Andersen - ~28/50 (56%)**

核心技巧：
- **AWQ 量化**：Activation-aware Weight Quantization
- **Self-consistency**：多候选答案生成
- **vLLM 推理引擎**：PagedAttention 优化
- **DeepSeek-R1-Distill-Qwen-14B AWQ**

实现细节：
- AWQ：识别关键权重，保护重要权重，量化其他
- Self-consistency：标准多数投票策略
- vLLM：PagedAttention 减少 KV Cache 内存占用
- 最终成绩：~28/50 正确

**5th Place - usernam - ~27/50 (54%)**

核心技巧：
- **lmdeploy 高吞吐量**：高吞吐量推理框架
- **DeepSeek-R1-Distill-Qwen-14B AWQ**：4-bit 量化
- **Batch 推理优化**：大 batch 推理提升吞吐

实现细节：
- lmdeploy：连续批处理优化
- 量化：AWQ 4-bit，减少内存和计算
- Batch size：根据 GPU 内存动态调整
- 最终成绩：~27/50 正确

**7th Place - tascj - ~26/50 (52%)**

核心技巧：
- **AWQ 量化**：4-bit 量化优化
- **lmdeploy 推理**：高吞吐量推理
- **DeepSeek-R1-Distill-Qwen-14B AWQ**

实现细节：
- AWQ：自定义量化配置
- lmdeploy：高吞吐量，多 GPU 并行
- 最终成绩：~26/50 正确

**8th Place - MPWARE - ~25/50 (50%)**

核心技巧：
- **自定义 AWQ 量化**：自定义量化策略
- **Self-consistency**：多候选投票
- **vLLM 推理引擎**

实现细节：
- 自定义 AWQ：根据模型特性定制量化
- vLLM：PagedAttention 内存优化
- 最终成绩：~25/50 正确

**9th Place - Fast-Math-R1–14B - ~24/50 (48%)**

核心技巧：
- **SFT + GRPO**：监督微调 + Group Relative Policy Optimization
- **GRPO 效率优化**：减少推理步数，提升效率（结果不稳定）
- **Fine-tuned DeepSeek-R1-Distill-Qwen-14B**：微调模型

实现细节：
- SFT：OpenR1 Math 数据集微调
- GRPO：优化推理步骤数，减少 tokens
- 不稳定性：优化到一定程度后"灾难性偏移"
- 使用早期 checkpoint 获得最佳结果
- 最终成绩：~24/50 正确

**11th Place - farsail - ~22/50 (44%)**

核心技巧：
- **One-shot prompting**：单样本提示，无需微调
- **自定义 vLLM**：自定义推理引擎配置
- **DeepSeek-R1-Distill-Qwen-14B AWQ**

实现细节：
- One-shot：提供 1-2 个示例作为提示
- 自定义 vLLM：优化 PagedAttention 参数
- 最终成绩：~22/50 正确

**17th Place - ippeiogawa - ~18/50 (36%)**

核心技巧：
- **Multi-stage prompting**：多阶段提示策略
- **代码生成**：强制生成 Python 代码
- **DeepSeek-R1-Distill-Qwen-14B AWQ**

实现细节：
- Multi-stage：分解问题，逐步生成代码
- 代码生成：要求模型生成可执行代码
- vLLM：高效推理引擎
- 最终成绩：~18/50 正确

**20th Place - Arek Paterek - ~15/50 (30%)**

核心技巧：
- **AWQ 量化**：4-bit 量化
- **DeepSeek-R1-Distill-Qwen-32B AWQ**：32B 大模型量化
- **Base model + prompting**：基础模型 + 提示工程

实现细节：
- 32B 模型：更大模型，更多知识
- AWQ 量化：4-bit 量化降低内存
- 无微调：直接使用提示
- 最终成绩：~15/50 正确

**22nd Place - K-Piece - ~13/50 (26%)**

核心技巧：
- **Base model + prompting**：基础模型 + 提示工程
- **DeepSeek-R1 系列**：使用不同大小的 DeepSeek-R1
- **Self-consistency**：多候选投票

实现细节：
- 提示工程：精心设计的提示模板
- DeepSeek-R1：14B, 32B 等不同变体
- Self-consistency：生成 5-10 个候选答案
- 最终成绩：~13/50 正确

**技术总结：**

| 技术维度 | 关键发现 |
|---------|---------|
| **模型选择** | DeepSeek-R1-Distill-Qwen-14B AWQ 是最受欢迎 |
| **微调方法** | SFT（基础）+ DPO（长度优化）+ TIR（工具集成） |
| **推理引擎** | vLLM（通用）<br>lmdeploy（高吞吐）<br>TensorRT-LLM（第 1 名专用） |
| **推理策略** | Self-consistency（标配）<br>Early stopping（节省时间）<br>代码执行（提升精度） |
| **核心创新** | MARIO 框架：Math + Reasoning + Interpreter |

---

### MARIO 框架 - 数学推理 + 代码解释器

**关键洞察：** 纯 LLM 推理不够，需要代码执行进行计算

```python
import subprocess
import tempfile
import os

class MARIOFramework:
    """
    MARIO: MAth Reasoning with code Interpreter
    NVIDIA AIMO-2 第 1 名方案

    核心思想：
    1. LLM 生成自然语言推理 + Python 代码
    2. 代码在沙盒环境中执行
    3. 执行结果指导后续推理
    4. 迭代直到得到最终答案
    """
    def __init__(self, model, max_iterations=10):
        self.model = model
        self.max_iterations = max_iterations

    def solve_math_problem(self, problem_text):
        """
        解决数学问题

        Args:
            problem_text: 数学问题文本

        Returns:
            answer: 最终答案（多选 A-E 或数值）
        """
        # 初始化对话
        conversation = [
            {"role": "system", "content": "You are a math expert. Solve the problem step by step."},
            {"role": "user", "content": problem_text}
        ]

        for iteration in range(self.max_iterations):
            # 生成推理 + 代码
            response = self.model.generate(conversation)

            # 提取 Python 代码
            code_blocks = self.extract_code_blocks(response)

            if code_blocks:
                # 执行代码
                execution_results = []
                for code in code_blocks:
                    result = self.execute_code_safely(code)
                    execution_results.append(result)

                # 将执行结果添加到对话
                conversation.append({"role": "assistant", "content": response})
                conversation.append({
                    "role": "user",
                    "content": f"Execution results: {execution_results}. Continue reasoning."
                })
            else:
                # 没有代码，直接返回答案
                conversation.append({"role": "assistant", "content": response})
                break

        # 提取最终答案
        answer = self.extract_final_answer(conversation[-1]['content'])
        return answer

    def extract_code_blocks(self, text):
        """
        提取 Python 代码块
        """
        import re
        pattern = r'```python\n(.*?)```'
        matches = re.findall(pattern, text, re.DOTALL)
        return matches

    def execute_code_safely(self, code, timeout=10):
        """
        在沙盒环境中安全执行代码
        """
        try:
            # 创建临时文件
            with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f:
                f.write(code)
                temp_file = f.name

            # 执行代码，设置超时和资源限制
            result = subprocess.run(
                ['python', temp_file],
                capture_output=True,
                text=True,
                timeout=timeout,
                # 资源限制
                # (实际实现需要更严格的沙盒)
            )

            # 删除临时文件
            os.unlink(temp_file)

            return result.stdout
        except subprocess.TimeoutExpired:
            return "Execution timeout"
        except Exception as e:
            return f"Error: {str(e)}"
```

### 三阶段训练 (CoT → TIR → GenSelect)

**关键洞察：** 逐步训练模型掌握推理、工具使用和答案选择

```python
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

class ThreeStageTraining:
    """
    NVIDIA 三阶段训练流程
    Stage 1: CoT (Chain-of-Thought) - 知识获取
    Stage 2: TIR (Tool-Integrated Reasoning) - 工具集成推理
    Stage 3: GenSelect - 生成选择
    """
    def __init__(self, model_name="Qwen/Qwen2.5-32B"):
        self.model = AutoModelForCausalLM.from_pretrained(model_name)
        self.tokenizer = AutoTokenizer.from_pretrained(model_name)

    def stage1_cot_training(self, cot_dataset):
        """
        Stage 1: Chain-of-Thought 训练
        纯推理训练，不使用代码执行
        """
        for example in cot_dataset:
            problem = example['problem']
            cot_solution = example['cot_solution']  # 长思维链

            prompt = f"""
            Problem: {problem}

            Solution:
            {cot_solution}

            Answer: {example['answer']}
            """

            # 训练模型生成推理链
            inputs = self.tokenizer(prompt, return_tensors="pt")
            labels = self.tokenizer(cot_solution, return_tensors="pt")

            outputs = self.model(**inputs, labels=labels)
            loss = outputs.loss

            # 反向传播（简化）
            loss.backward()

    def stage2_tir_training(self, tir_dataset):
        """
        Stage 2: Tool-Integrated Reasoning 训练
        训练模型生成推理 + Python 代码
        """
        for example in tir_dataset:
            problem = example['problem']
            tir_solution = example['tir_solution']  # 推理 + 代码

            prompt = f"""
            Problem: {problem}

            Solve the problem step by step. Use Python code for calculations.

            Solution:
            {tir_solution}

            Answer: {example['answer']}
            """

            inputs = self.tokenizer(prompt, return_tensors="pt")
            labels = self.tokenizer(tir_solution, return_tensors="pt")

            outputs = self.model(**inputs, labels=labels)
            loss = outputs.loss

            loss.backward()

    def stage3_genselect_training(self, validation_dataset):
        """
        Stage 3: GenSelect 训练
        学习多答案生成 + 排序投票
        """
        # 训练时模拟多个答案生成
        predictions = []

        for example in validation_dataset:
            problem = example['problem']

            # 生成多个候选答案
            candidate_answers = []
            for _ in range(32):  # 32 个候选答案
                prompt = f"Problem: {problem}\nSolution: Let's think step by step."
                inputs = self.tokenizer(prompt, return_tensors="pt")
                outputs = self.model.generate(**inputs, max_new_tokens=2048)

                answer = self.extract_answer(outputs)
                candidate_answers.append(answer)

            # 基于排序的投票
            final_answer = self.rank_based_voting(candidate_answers)
            predictions.append(final_answer)

    def rank_based_voting(self, answers):
        """
        基于排序的投票（优于简单多数投票）

        NVIDIA 创新：
        - 不只是计数答案出现次数
        - 根据推理质量加权
        - 考虑答案的置信度
        """
        # 统计每个答案的投票数
        from collections import Counter
        counts = Counter(answers)

        # 加权投票（推理质量）
        # 这里简化为多数投票
        return counts.most_common(1)[0][0]
```

### GenSelect - 多答案生成与投票

**关键洞察：** 候选答案的排序投票优于简单多数投票

```python
import numpy as np
from collections import Counter

def genselect_answer(model, problem_text, n_candidates=32):
    """
    GenSelect: 生成选择方法

    NVIDIA AIMO-2 核心创新：
    1. 生成多个候选答案
    2. 对每个答案评分
    3. 基于排序选择最终答案
    """
    candidate_answers = []
    scores = []

    for _ in range(n_candidates):
        # 生成推理 + 答案
        prompt = f"""
Problem: {problem_text}

Let's think step by step. We need to find the final answer.
"""
        response = model.generate(prompt, max_new_tokens=2048)

        # 提取答案
        answer = extract_answer(response)
        confidence = estimate_confidence(response)

        candidate_answers.append(answer)
        scores.append(confidence)

    # 基于排序的投票
    # 不只是选择出现最多的答案
    # 考虑答案的置信度排序
    sorted_indices = np.argsort(scores)[::-1]  # 降序

    # 选择置信度最高的答案
    # 或者使用加权组合
    final_answer = candidate_answers[sorted_indices[0]]

    return final_answer


def extract_answer(response_text):
    """
    从推理文本中提取最终答案
    """
    import re

    # 匹配模式 1: "Answer: X"
    match = re.search(r'Answer:\s*([A-E]|-?\d+)', response_text)
    if match:
        return match.group(1)

    # 匹配模式 2: "最终答案是 X"
    match = re.search(r'最终答案[是为]\s*([A-E]|-?\d+)', response_text)
    if match:
        return match.group(1)

    # 匹配模式 3: "Therefore, the answer is X"
    match = re.search(r'Therefore,?\s*the\s+answer\s+is\s+([A-E]|-?\d+)', response_text)
    if match:
        return match.group(1)

    return None


def estimate_confidence(response_text):
    """
    估计答案的置信度

    方法：
    - 推理链的完整性
    - "Therefore"、"Thus"等确定性词汇
    - 答案的明确程度
    """
    confidence = 0.5  # 基础置信度

    # 检查确定性词汇
    certainty_keywords = ['therefore', 'thus', 'hence', 'consequently']
    for keyword in certainty_keywords:
        if keyword in response_text.lower():
            confidence += 0.1

    # 检查不确定性词汇
    uncertainty_keywords = ['maybe', 'perhaps', 'possibly', 'probably']
    for keyword in uncertainty_keywords:
        if keyword in response_text.lower():
            confidence -= 0.1

    # 检查推理链长度
    reasoning_length = len(response_text.split('.'))
    confidence += min(reasoning_length / 100, 0.3)

    return np.clip(confidence, 0, 1)
```

### OpenMathReasoning 数据集构建

**关键洞察：** 从 AoPS 论坛提取高质量数学问题

```python
import requests
from bs4 import BeautifulSoup

def build_openmath_dataset():
    """
    从 AoPS (Art of Problem Solving) 论坛构建数据集

    NVIDIA AIMO-2 方法：
    1. 爬取 AoPS 论坛的高质量回答
    2. 使用 LLM 提取结构化信息
    3. 过滤低质量数据
    4. 生成 CoT 和 TIR 格式
    """
    base_url = "https://artofproblemsolving.com"

    # 1. 爬取论坛帖子
    posts = []
    for forum in ["algebra", "combinatorics", "number_theory"]:
        url = f"{base_url}/{forum}"
        posts.extend(scrape_aops_forum(url))

    # 2. 提取问题和解答
    extracted_data = []
    for post in posts:
        # 使用 LLM 提取结构化信息
        prompt = f"""
        Extract from this AoPS forum post:
        {post['content']}

        Extract:
        1. Problem statement
        2. Solution steps
        3. Final answer
        """

        extraction = llm_extract(prompt)

        extracted_data.append({
            'problem': extraction['problem'],
            'solution': extraction['solution'],
            'answer': extraction['answer'],
            'source': post['url']
        })

    # 3. 过滤质量
    filtered_data = filter_quality(extracted_data)

    # 4. 生成 CoT 格式
    cot_data = []
    for item in filtered_data:
        cot = generate_cot_from_solution(item['solution'])
        cot_data.append({
            'problem': item['problem'],
            'cot_solution': cot,
            'answer': item['answer']
        })

    # 5. 生成 TIR 格式
    tir_data = []
    for item in filtered_data:
        tir = generate_tir_from_solution(item['solution'])
        tir_data.append({
            'problem': item['problem'],
            'tir_solution': tir,
            'answer': item['answer']
        })

    return cot_data, tir_data


def generate_cot_from_solution(solution):
    """
    从解答生成长思维链 (CoT)
    """
    prompt = f"""
    Convert this solution into a step-by-step chain-of-thought explanation:

    Solution: {solution}

    Make sure to:
    1. Explain each step clearly
    2. Show your work
    3. Explain why we take each step
    """

    return llm_generate(prompt)


def generate_tir_from_solution(solution):
    """
    从解答生成工具集成推理 (TIR)
    """
    prompt = f"""
    Convert this solution into a format that includes Python code:

    Solution: {solution}

    Make sure to:
    1. Include Python code for calculations
    2. Explain what the code does
    3. Show intermediate results
    """

    return llm_generate(prompt)
```

### 2nd Place 方案 - 代码生成 + 执行流水线

**关键洞察：** 先生成 Python 代码，再执行验证

```python
def solve_math_with_code_generation(model, problem_text):
    """
    2nd Place (imagination-research) 方法

    流水线：
    1. 提示模型生成 Python 代码
    2. 提取 Python 代码
    3. 在解释器中执行代码
    4. 验证结果
    5. 返回最终答案
    """
    # Step 1: 生成代码
    prompt = f"""
    Write a Python program to solve this math problem:

    {problem_text}

    The program should:
    1. Define the problem
    2. Implement the solution
    3. Print the final answer
    """

    response = model.generate(prompt)
    python_code = extract_python_code(response)

    # Step 2: 执行代码
    result = execute_python_code(python_code)

    # Step 3: 提取答案
    answer = extract_answer_from_output(result)

    return answer


def extract_python_code(text):
    """
    从响应中提取 Python 代码
    """
    import re
    pattern = r'```python\n(.*?)\n```'
    match = re.search(pattern, text, re.DOTALL)
    if match:
        return match.group(1)

    # 备选：找 indented 代码块
    lines = text.split('\n')
    code_lines = []
    in_code_block = False
    indent_level = 0

    for line in lines:
        if '```' in line:
            in_code_block = not in_code_block
        elif in_code_block:
            code_lines.append(line)

    return '\n'.join(code_lines)


def execute_python_code(code):
    """
    执行 Python 代码并返回输出
    """
    import sys
    from io import StringIO

    old_stdout = sys.stdout
    old_stderr = sys.stderr

    sys.stdout = StringIO()
    sys.stderr = StringIO()

    try:
        exec(code, {})
        output = sys.stdout.getvalue()
        error = sys.stderr.getvalue()
    except Exception as e:
        output = ""
        error = str(e)
    finally:
        sys.stdout = old_stdout
        sys.stderr = old_stderr

    return output if output else error
```

---

## Best Practices

### ARC/抽象推理任务策略

| 策略 | 何时使用 | 说明 |
|------|---------|------|
| **Refinement Loops** | 需要逐步优化答案 | 递归改进是智能的核心 (TRM) |
| **合成数据生成** | 原始任务不足时 | 通过组合生成新任务，采样二次方空间 |
| **LLM 微调** | 有基础模型可用 | Qwen-4B 在合成数据上微调 |
| **Test-Time Training** | 每个任务独立 | 在测试时为每个任务单独训练 |
| **进化程序合成** | 需要探索程序空间 | LLM 在搜索轨迹上微调 (SOAR) |
| **极小模型** | 计算受限或追求效率 | TRM (7M), CompressARC (76K) |
| **数据增强** | 任务数量有限时 | 几何变换 + 颜色排列 |
| **Tokenizer 优化** | 词汇表冗余时 | 减少到任务需要的最小 tokens |

### 抽象推理 vs 传统 NLP

| 方面 | 传统 NLP | ARC/抽象推理 |
|------|----------|-------------|
| **任务类型** | 分类、序列标注、生成 | 程序合成、推理 |
| **评估方式** | Accuracy/F1/Perplexity | 完全正确才算对 |
| **数据格式** | 文本序列 | 网格变换 |
| **泛化挑战** | 分布偏移 | Out-of-Distribution |
| **训练方式** | 大规模预训练 | 测试时训练为主 |
| **模型大小** | 越大越好 | 越小越高效 (TRM, CompressARC) |

### 数学推理任务策略

| 策略 | 何时使用 | 说明 |
|------|---------|------|
| **代码执行集成** | 需要精确计算 | 纯推理不够，需要 Python 代码执行 |
| **多答案生成 + 投票** | 答案不确定时 | 32 个候选 + 排序投票 |
| **三阶段训练** | 有大量高质量数据时 | CoT → TIR → GenSelect |
| **高质量数据源** | 数据不足时 | 从 AoPS 等专业论坛提取 |
| **小模型竞争力** | 计算受限时 | 1.5B 模型可达有竞争力 |

### 数学推理 vs 抽象推理 vs 传统 NLP

| 方面 | 传统 NLP | 数学推理 | 抽象推理 |
|------|----------|---------|-------------|
| **任务类型** | 分类、序列标注 | 数学问题求解 | 程序合成、推理 |
| **输出格式** | 标签、文本 | 数值答案、选项 | 网格变换 |
| **核心挑战** | 语义理解 | 逻辑推理、计算 | 泛化能力 |
| **关键能力** | 语言理解 | 数学知识、推理 | 抽象能力 |
| **解决方案** | 微调 LLM | 代码执行 + GenSelect | Refinement Loops |

### MARIO 框架详解

**核心组件：**

| 组件 | 功能 | 实现方式 |
|------|------|---------|
| **MA** | Math（数学推理） | 理解问题、生成推理 |
| **RI** | Reasoning + Interpreter | 生成代码、执行、验证 |
| **O** | Open（开源） | 开源模型和数据 |

**流程：**
```
问题文本
    ↓
[LLM 推理 + Python 代码]
    ↓
[沙盒环境执行代码]
    ↓
[执行结果反馈]
    ↓
[迭代优化]
    ↓
最终答案
```

### 数据质量 vs 数量

**NVIDIA 发现：**

| 方面 | 传统方法 | NVIDIA 方法 |
|------|---------|-----------|
| **数据量** | 追求数量 | 质量优先 |
| **数据源** | 通用数据集 | 专业论坛 (AoPS) |
| **质量验证** | 简单过滤 | LLM 提取 + 人工验证 |
| **效果** | 300K 低质量 | 290K 高质量 |

**OpenMathReasoning 数据集：**
- **问题数量**: ~290K（不是最初宣传的 540K）
- **CoT 格式**: 3.2M 长思维链
- **TIR 格式**: 1.7M 工具集成推理
- **来源**: AoPS (Art of Problem Solving) 论坛

### GenSelect vs 简单多数投票

| 方法 | 准确率 | 计算成本 | 说明 |
|------|--------|----------|------|
| **GenSelect** | 68% (34/50) | 32 × 推理 | 基于排序投票 |
| **简单多数投票** | ~60% | 32 × 推理 | 只选出现最多的 |
| **单次推理** | ~50% | 1 × 推理 | 不生成多次 |

**GenSelect 优势：**
- 考虑推理质量
- 加权置信度
- 处理答案分布不均

### 模型大小 vs 性能

| 模型 | 参数量 | 性能 | 成本 |
|------|--------|------|------|
| **OpenMath-Nemotron-1.5B** | 1.5B | ~40% | 低 |
| **OpenMath-Nemotron-7B** | 7B | ~50% | 中 |
| **OpenMath-Nemotron-14B** | 14B | ~60% | 高 |
| **OpenMath-Nemotron-32B** | 32B | 68% | 最高 |
| **DeepSeek-R1** | ~? | ~70% | 未知 |

**结论：** 小模型（1.5B）在有良好训练的情况下可达有竞争力的性能

### AoPS 数据提取策略

**关键步骤：**

1. **论坛选择**
   - Algebra（代数）
   - Combinatorics（组合）
   - Number Theory（数论）

2. **质量指标**
   - 回答质量（被选为最佳回答）
   - 推理完整性
   - 可验证性

3. **LLM 提取**
   - 问题陈述
   - 解决步骤
   - 最终答案
   - 结构化格式

4. **过滤策略**
   - 移除低质量解答
   - 验证数学正确性
   - 去重

### 代码执行安全

**沙盒环境要求：**

| 方面 | 要求 |
|------|------|
| **隔离** | 独立进程，不污染主环境 |
| **超时** | 10 秒执行时间限制 |
| **资源限制** CPU、内存、磁盘限制 |
| **网络** | 禁止网络访问 |
| **文件系统** | 临时文件，只读访问 |

**实现方式：**
- Docker 容器
- subprocess + resource limits
- 云端执行环境

### 前沿模型的进展

**竞赛期间（2024-08）：**
- Claude Sonnet: ~30%
- GPT-4o: ~35%

**竞赛结束后（2024-12）：**
- Gemini 2 Pro: ~50%
- DeepSeek-R1: ~70%
- Claude Opus: ~65%

**原因：**
- 前沿模型在数学数据上预训练
- 代码生成能力增强
- 推理能力提升

---

### 前排方案技术细节（Top 12+）

#### 微调方法总结

| 方法 | 使用队伍 | 效果 | 说明 |
|------|---------|------|------|
| **SFT** | 几乎所有队伍 | 基础必备 | 使用 OpenR1 Math, Light-R1, 自定义数据集 |
| **DPO** | 2nd place | 长度优化 | 第 2 阶段减少输出长度，保持推理能力 |
| **TIR** | 1st place | 核心创新 | 训练模型使用外部工具（Python 沙盒） |
| **GRPO** | 9th place | 效率提升（不稳定） | 奖励优化到一定程度后"灾难性偏移" |

**微调方法对比：**

1. **SFT (Supervised Fine-Tuning)** - 基础起点
   - 数据集：OpenR1 Math, Light-R1, 自定义数学问题
   - 目标：学习数学推理模式
   - 阶段：几乎所有队伍的第一阶段

2. **DPO (Direct Preference Optimization)** - 第 2 名使用
   - 目标：减少输出长度（提升效率）
   - 数据构建：基于正确性、长度比、最小长度、相似性
   - 效果：第 2 阶段有效减少输出长度

3. **TIR (Tool-Integrated Reasoning)** - 第 1 名核心
   - 目标：集成外部工具（Python 代码执行）
   - 效果：显著提升计算精度和推理能力
   - 数据：OpenMathReasoning (1.7M TIR 格式)

4. **GRPO (Generative Reinforcement Preference Optimization)** - 第 9 名尝试
   - 目标：用更少 tokens 达到准确结论
   - 奖励函数：格式正确性、余弦相似性、长度奖励
   - 结果：优化到一定程度后出现"灾难性偏移"，需使用早期 checkpoint

#### 推理策略总结

| 策略 | 使用队伍 | 效果 | 说明 |
|------|---------|------|------|
| **Self-consistency** | 1st, 2nd, 3rd, 5th, 11th, 17th | 标配 | 生成多个解，取最频繁答案 |
| **Early Stopping (Sample)** | 2nd | 节省 tokens | 找到答案或生成代码后立即停止 |
| **Early Stopping (Question)** | 1st, 2nd, 3rd, 11th, 17th | 节省时间 | 早期共识出现后停止整个问题生成 |
| **Time Management** | 多个队伍 | 动态资源分配 | 根据剩余时间/问题难度调整参数 |

**Self-consistency 实现：**
```python
def self_consistency_solve(model, problem, n_samples=32):
    """
    自一致性求解：生成多个解，取最频繁答案
    """
    answers = []
    for _ in range(n_samples):
        ans = model.generate(problem)
        answers.append(ans)

    # 多数投票
    from collections import Counter
    counter = Counter(answers)
    return counter.most_common(1)[0][0]
```

**Early Stopping 变体（1st Place）：**
```python
def early_stopping_genselect(model, problem, n_candidates=32):
    """
    第 1 名的 Early Stopping 策略
    如果前 5 个生成中有 4 个相同，取消剩余生成
    """
    answers = []
    for i in range(n_candidates):
        ans = model.generate(problem)
        answers.append(ans)

        # Early stopping check
        if i >= 4:
            from collections import Counter
            counter = Counter(answers)
            most_common_count = counter.most_common(1)[0][1]
            if most_common_count >= 4:
                break  # 提前停止

    return counter.most_common(1)[0][0]
```

#### 推理引擎对比

| 引擎 | 使用队伍 | 优势 | 劣势 |
|------|---------|------|------|
| **vLLM** | 4th, 7th, 8th, 11th, 17th | 最常用，成熟 | 默认配置可能不够优化 |
| **lmdeploy** | 2nd, 5th, 7th | 高吞吐量 | 配置相对复杂 |
| **TensorRT-LLM** | 1st | 最优性能 | 需要专业优化 |

#### 量化技术

| 量化方法 | 使用队伍 | 效果 | 说明 |
|---------|---------|------|------|
| **AWQ 4-bit** | 几乎所有队伍 | 平衡性能和效率 | Activation-aware Weight Quantization |
| **FP8** | 1st place | 进一步优化 | 第 1 名使用 |
| **8-bit KV cache** | 2nd, 7th | 节省内存 | KV cache 量化 |

**AWQ 原理：**
- 不是所有权重都同等重要
- 识别被大激活值乘以的关键权重
- 保护这些关键权重，牺牲不重要的权重
- 结果：更小、更快的模型，性能几乎不变

#### Prompt Engineering 最佳实践

**1. System Prompts（角色设置）：**

```python
# 基础版
"You are a helpful math assistant."

# 更权威（8th Place 风格）
"You are an expert in solving AIMO-level mathematics problems. Your goal is to solve the following problem with high accuracy and minimal reasoning steps."

# 行为 + 模型特定（Fast-Math-R1-14B）
"You are a helpful and harmless assistant. You are Qwen developed by Alibaba. You should think step-by-step..."

# 特定特质（21st Place 教师模型）
"You are the most powerful math expert. Please solve the problems with deep reasoning. You are careful and always recheck your deductions. You will never give an answer directly until you have enough confidence."
```

**2. User Instructions（任务定义）：**

```python
# 核心输出格式（通用）
"""
You must put the final answer in \\boxed{}.
If the final answer is greater than 1000, then take the modulo of 1000.
"""

# 鼓励 CoT（2nd Place）
"""
You excel at reasoning.
Think carefully and thoroughly, avoid duplication.
"""

# 鼓励代码输出（2nd Place）
"""
You excel at coding.
You must provide the python code, avoid redundant analysis.
The answer must be integer.
There is only one answer for each question.
Import necessary libraries.
"""

# 特定行动序列（8th Place）
"""
1. Read the problem carefully and identify the key components.
2. Plan your approach in 1-2 concise steps, focusing on the most efficient method.
3. Execute the solution with clear, logical reasoning, but limit your reasoning to a maximum of 1-2 steps.
4. Verify your answer for correctness by double-checking each step before finalizing.
5. Provide the final answer in a boxed format... and stop further reasoning.
"""
```

**3. Few-Shot / One-Shot Prompts（11th Place）：**

```python
# One-shot prompting 示例
system_prompt = """
You are a Python code assistant. You will be given a mathematical problem that has integer solutions. Your task is to convert this complex math problem into Python code. Let's have Python do the tedious calculations for us!

- There are multiple ways to solve this problem, so find the most efficient one.
- The final answer should be an integer.
- The final answer should be modulo 1000.
- Please return Python code only following the format below.
"""

few_shot_example = """
```python
import math

# Intermediate calculations
result = ...
print(result % 1000)
```
"""
```

**4. Multi-Stage Prompting（17th Place）：**

```python
# Stage 1: Initial thought
stage1_output = model.generate(f"{problem}\nThink step by step:")

# Stage 2: Code generation
stage2_prompt = f"""
Problem: {problem}
Previous thought: {stage1_output}

Please make a short summary of your approach, including python code.
"""
stage2_output = model.generate(stage2_prompt)

# Stage 3: Error fixing (if needed)
if execution_failed:
    stage3_prompt = f"""
Problem: {problem}
Previous code: {stage2_output}
Error: {error_message}

Please fix the code.
"""
    stage3_output = model.generate(stage3_prompt)
```

#### 模型选择建议

**前排方案共识：**

1. **DeepSeek-R1-Distill-Qwen-14B AWQ** 是最受欢迎的选择
   - 4-bit 量化，内存效率高
   - 推理能力强
   - 推理速度快

2. **Qwen2.5-14B** 是第 1 名的基础模型
   - 更强的推理能力
   - 需要更多优化

3. **模型大小选择：**
   - 14B AWQ：最佳平衡（3rd-22nd）
   - 32B AWQ：更大但更慢（20th）
   - 7B AWQ：更快但精度略低

---

## Metadata

| Source | Date | Tags |
|--------|------|------|
| [ARC Prize 2025](https://www.kaggle.com/competitions/arc-prize-2025) | 2025-01-22 | 抽象推理, Refinement Loops, 合成数据, Test-Time Training, TRM, SOAR, CompressARC |
| [AI Mathematical Olympiad Progress Prize 2](https://www.kaggle.com/competitions/ai-mathematical-olympiad-progress-prize-2) | 2025-01-22 | 数学推理, MARIO, 代码执行集成, OpenMathReasoning, GenSelect, 三阶段训练, AoPS |
| [Eedi - Mining Misconceptions in Mathematics](https://www.kaggle.com/competitions/eedi-mining-misconceptions-in-mathematics) | 2024-09 | 教育 AI, 误解检测, 检索+重排, Qwen LLM, Distractor prediction,亲和度预测 |
| [MAP - Charting Student Math Misunderstandings](https://www.kaggle.com/competitions/map-charting-student-math-misunderstandings) | 2025-01-22 | 教育 AI, 误解检测, MiRAGE, Shared-prefix attention, Soft labels, Multi-task learning, CoT distillation, Ensemble fusion, Eedi 后续竞赛 |
