- yuxitong's blog
useless
- @ 2025-11-11 18:59:38
T1 小小数学助手
故事背景
你来到小学帮助小朋友学数学。孩子们每天都会来问你各种数学题:
- 有的小朋友只想知道简单的加减乘除结果;
- 有的小朋友希望你一次性帮他算一整页的练习题;
- 还有的小朋友要求答案统一、整齐,不要多余的话,这样才能方便对照答案本子。
不过,这里的小朋友们写题目时非常"自由"。有的在纸上写正常的 +、-,有的画奇怪的符号,比如 ⊕、-、➕、➖,甚至还有人用中文"加""减"。如果直接用普通计算器,往往认不出这些符号,会算错。
于是,你决定编写一个小小数学助手,让它能够理解孩子们各种各样的题目,并用统一的答案格式来回答。这个助手基于 PyTorch 和 Transformers 库,可以自动回答孩子们提出的数学问题。
任务目标
你需要在 submission.py 中完成三个核心函数,让数学助手具备以下能力:
1. 定义回答规则:build_system_prompt() -> str
编写一个 system prompt,引导模型识别各种数学符号并按照 [Answer]: 数值 的格式输出答案。
2. 构造对话模板:apply_chat_template_single(...) -> str
使用 tokenizer 将 system prompt 和用户问题组合成模型能理解的输入格式。
3. 实现推理:generate_single(...) 和 generate_batch(...)
实现单条推理和批量推理两种模式,返回模型生成的 token 序列。
注意:直接返回模型原始输出,不要做后处理。评测程序会统一处理输出格式。
实现要求
文件结构
T1/
├── data/
│ ├── test_data_1.jsonl # 阶段一测试数据(8题)
│ └── test_data_2.jsonl # 阶段二测试数据(32题)
├── evaluate.py # 评测主程序(不可修改)
├── submission.py # 考生实现文件(仅此文件可修改)
└── README.md # 本文档
修改规则
- ✅ 仅可修改
submission.py中标注的"考生实现区域" - ✅ 可以新增少量辅助函数
- ❌ 不得修改
evaluate.py的任何内容 - ❌ 不得在函数中做答案后处理(如提取数字、格式转换等)
技术要求
- 使用 PyTorch 和 Transformers 库
- 正确处理 tokenizer 的 padding 和 truncation
- 批量推理需要考虑内存和效率
评测说明
运行方式
演示模式(详细输出):
python evaluate.py
# 或
python evaluate.py --mode demo
- 展示每个题目的完整推理过程
- 显示模型原始输出、处理后文本、提取的答案
- 展示错误样例的详细信息
评分模式(简洁输出):
python evaluate.py --mode grading
- 简洁的进度输出
- 最终输出详细评分和性能指标
- 用于正式评测
评测流程
阶段一:逐条推理(8 题)
测试内容:
- 固定的 8 道数学题(基础四则运算 + 特殊符号)
- 逐条调用
generate_single进行推理 - 测试模型对各种符号和表达的理解能力
示例题目:
{"problem": "12 + 35", "answer": "47"}
{"problem": "6的平方?", "answer": "36"}
{"problem": "45 加 89", "answer": "134"}
输出内容(Demo 模式):
- 题目原文
- 模型原始输出(可能包含
<think>标签) - 非思考部分文本
- 提取的答案
- 判定结果(✅/❌)
- 单题耗时
评分标准:
- 正确性:每题 10 分,答对 ≥6 题给满分 60 分
阶段二:批量推理(32 题)
测试内容:
- 32 道数学题(包含多种符号和表达)
- 调用
generate_batch进行批量推理 - 测试批量处理的效率和准确性
示例题目:
{"problem": "91 + 24", "answer": "115"}
{"problem": "34 ⊕ 19", "answer": "53"}
{"problem": "47 - 41", "answer": "6"}
输出内容(Demo 模式):
- 仅展示错误的样例(正确的不显示)
- 全部正确时显示祝贺信息
评分标准:
- 正确性:每题 1.5 分,答对题数 × 1.5 分,满分 40 分
总分构成(100 分)
T2 多样性数据生成与相似度计算
故事背景
你正在为一个在线学习平台开发智能题库系统。为了让学生能够充分练习,题库需要满足两个核心要求:
- 准确的相似度判断:能够识别题目之间的相似程度,避免重复练习相同的题目
- 多样化的题目生成:能够生成大量风格各异的题目,让学生接触到不同的表达方式
然而,题目的相似度判断并不简单。同样是 12 + 35 这道题,可能会有很多种表达方式:
- 符号变体:
12+35、12 ⊕ 35 - 顺序变化:
35 + 12 - 文字表达:
12 加 35、计算:12 加 35
你需要实现一个能够准确计算文本相似度的函数,并基于此生成一批高质量、多样化的数学题目数据集。
任务目标
你需要完成两个核心任务:
1. 实现相似度计算:compute_similarity(text1, text2, model, tokenizer) -> float
编写一个函数,使用给定的 embedding 模型计算两个文本的余弦相似度。
技术要点:
- Last-token pooling(提取最后一个 token 的 hidden state)
- L2 normalization(归一化向量)
- 余弦相似度(归一化后的点积)
2. 生成多样化数据集:data/dataset.jsonl
生成 1024 条高质量的数学题目数据,满足以下要求:
- 所有题目唯一(无重复)
- 每个题目最多 3 个数字
- 答案为 3 位数(100-999)
- 平均相似度 ≤ 0.5(越低越好)
实现要求
文件结构
T2/
├── data/
│ ├── test_data_1.jsonl # 相似度测试用例(10组)
│ └── dataset.jsonl # 考生生成的数据集(1024条)
├── evaluate.py # 评测主程序(不可修改)
├── submission.py # 考生实现文件(仅此文件可修改)
└── README.md # 本文档
修改规则
- ✅ 仅可修改
submission.py中的compute_similarity函数 - ✅ 可以新增辅助函数用于数据生成
- ✅ 必须生成
data/dataset.jsonl文件(1024条数据) - ❌ 不得修改
evaluate.py的任何内容 - ❌ 不得修改
data/test_data_1.jsonl测试用例
技术要求
相似度计算:
- 使用 PyTorch 和 Transformers 库
- 正确实现 last-token pooling
- 正确实现 L2 normalization
- 返回值范围:[0, 1]
数据生成:
- JSON Lines 格式:每行一个 JSON 对象
- 必需字段:
problem(题目)、answer(答案) - 题目示例:
{"problem": "12 + 35", "answer": "47"}
评测说明
运行方式
演示模式(详细输出):
python evaluate.py
# 或
python evaluate.py --mode demo
- 展示每个测试用例的详细结果
- 显示数据多样性的详细统计
- 显示扣分明细和最终得分
评分模式(简洁输出):
python evaluate.py --mode grading
- 简洁的进度输出
- 最终输出详细评分
- 用于正式评测
评测流程
第一部分:相似度计算准确性(50 分)
测试内容:
- 10 组预定义的文本对测试用例
- 使用预计算的标准相似度进行对比
- 测试模型对各种相似度的判断能力
示例测试用例:
{"text1": "12 + 35", "text2": "12 + 35", "description": "完全相同", "standard_similarity": 1.0}
{"text1": "12 + 35", "text2": "12+35", "description": "符号不同", "standard_similarity": 0.877}
{"text1": "12 + 35", "text2": "35 + 12", "description": "顺序不同", "standard_similarity": 0.869}
输出内容(Demo 模式):
- 测试用例描述
- 两个输入文本
- 标准相似度
- 考生计算的相似度
- 误差值
- 判定结果(✅/❌)
评分标准:
- 每个测试用例 5 分,共 10 组
- 允许误差:≤ 0.03
- 通过 ≥ 8 组:满分 50 分
- ⚠️ 必须满分才能进行第二部分测试
第二部分:数据多样性(50 分)
前提条件:第一部分必须获得满分(50分)
测试内容:
- 加载
data/dataset.jsonl数据集 - 检查数据数量、质量
- 使用考生的模型计算数据集的平均相似度
数据要求:
-
数量要求:1024 条
- 每少/多 1 条扣 1 分
-
质量要求(每条问题扣 1 分):
- 所有题目必须唯一(不能有重复)
- 所有题目非空
- 每个题目最多 3 个数字
- 答案必须是 3 位数(100-999)
-
相似度要求:
- ≤ 0.5:满分 50 分
- 0.5 ~ 0.7:线性给分
-
0.7:0 分
示例数据:
{"problem": "818 ⊖ 10 减 89", "answer": "719"}
{"problem": "(98 - 30) 乘 9", "answer": "612"}
{"problem": "28 乘 19 / 4", "answer": "133"}
输出内容(Demo 模式):
- 数据数量统计
- 唯一性检查
- 数字个数检查
- 答案位数检查
- 平均相似度统计
- 扣分明细
- 最终得分
评分公式:
相似度得分:
- 平均相似度 ≤ 0.5:50 分
- 平均相似度 0.5~0.7:int(50 * (0.7 - avg_sim) / 0.2)
- 平均相似度 > 0.7:0 分
最终得分 = max(0, 相似度得分 - 数量扣分 - 质量扣分)
总分构成(100 分)
| 项目 | 分值 | 说明 |
|---|---|---|
| 第一部分 - 相似度计算 | 50 分 | 10组测试用例,每组5分,≥8组满分 |
| 第二部分 - 数据质量 | 0~50 分 | 数量扣分 + 质量扣分 |
| 第二部分 - 相似度评分 | 基于平均相似度 | |
| 最终得分 | 0~100 分 | 第一部分 + 第二部分(最低0分) |
⚠️ 重要提示:
- 第一部分未满分 → 第二部分跳过 → 总分最多 50 分
- 第二部分得分 = 相似度得分 - 数量扣分 - 质量扣分(最低0分)