Skip to content

Entropyorder/Math-Forge

Repository files navigation

MathForge

MathForge is an adversarial synthesis pipeline for olympiad-grade math problems — it forges high-difficulty, short-answer, machine-verifiable problems that are hard enough to stump frontier LLMs (target: first-attempt pass_rate ≤ 80%).

Starting from a pool of hard seed problems, it generates new originals, filters out unreliable statements and invalid answer shapes, then uses a strong model (gpt-5.5) to solve each surviving problem from the statement alone and write the ground-truth answer plus a standard solution. Finally it gates each problem by having a target model actually attempt it — keeping only the ones it fails.

The stages are fully decoupled: generation never verifies (it just mass-produces at high concurrency); a separate filter rejects ill-posed or malformed generated statements; gpt-5.5 establishes ground-truth answers; difficulty only judges "hard or not".


Pipeline(生成 → 题干可靠性预筛 → gpt-5.5 定答案/解析 → 难度)

seeds (data/seeds.jsonl)   ← 任意格式新种子可经 `python -m mathforge.ingest` 归一入库
        │
        ▼
[1] generate     种子调度器 + 出题(纯生成,满并发,不验证)
        ▼  generated.jsonl
[2] reliability filter  deepseek-v4-flash 判断题干可靠性、边界漏洞、答案形态和 LaTeX 格式;不通过则不进 gpt-5.5/豆包
        ▼  generated.filtered.jsonl (+ generated.filtered.dropped.jsonl)
[3] batch verify gpt-5.5 只看题干独立解题(默认 10 题/次):返回 reliable + answer + solution
        │          reliable=true → reference_answer/answer 覆盖为 gpt-5.5 答案,groundtruth_solution 写入解析
        │          reliable=false → dropped,不进难度门
        ▼  verified.jsonl (+ verified.jsonl.dropped.jsonl)
[4] difficulty   难度门:目标模型(豆包)干净作答 K 次,对比真答案;做错=合格
        ▼  final.jsonl + final.qualified.jsonl
   合格 = 筛选通过 ∧ gpt-5.5 给出标准答案/解析 ∧ 目标模型做错

为什么改用 gpt-5.5 解题定答案:旧的"模型写脚本本机实算"对纯证明/非数值题不适用; 裁判式 verify 又容易被 proposed answer 干扰。新流程只把题干发给强模型,让它独立给出 answersolution,作为下游判分的 ground truth。

Directory layout

MathForge/
├── README.md
├── requirements.txt
├── run_pipeline.py          # 一键全流程编排
├── data/
│   ├── seeds.jsonl          # 默认种子池(193 = 93 成题 + 100 出题指令)
│   └── seeds_top93.jsonl    # 93 颗成题种子(Omni-MATH 难度≥9,含 question/answer)
├── docs/
│   └── prompt.md            # 提示词规范(IMO 风格 / 对抗强化版)
└── mathforge/               # 主包
    ├── config.py            # 端点 / 各环节默认模型 / API key 解析
    ├── llm.py               # 异步客户端、重试、JSON 解析
    ├── ingest.py            # 种子接入:任意格式 → 标准 schema 并追加入库(去重/备份/dry-run)
    ├── prompts.py           # 全流程提示词
    ├── scheduler.py         # 种子调度器(加权采样+反馈调权)
    ├── generate.py          # 阶段一 · 纯出题
    ├── reliability_filter.py # 阶段二 · 题干可靠性 + 答案形态预筛
    ├── batch_verify.py      # 阶段三 · gpt-5.5 只看题干,写答案 + 解析
    ├── difficulty.py        # 阶段四 · 豆包难度门(做错=合格)
    ├── verify.py            # (旧)独立计算验证,保留备用,不在新流程使用
    └── sandbox.py           # (旧)计算脚本本地执行,配合 verify.py

种子接入(新种子"发来即入库")

新种子可能是任意字段格式(json/jsonl/csv/tsv)。用 ingest 自动按别名映射到标准 schema、 按"题面+答案"去重、追加进 data/seeds.jsonl(自动备份 .bak),之后照常出题:

# 先预览(不写库):看清字段映射 / 缺字段 / 重复 / 新增
python -m mathforge.ingest --input new_seeds.csv --dry-run

# 字段名不标准时手动指定映射,然后入库
python -m mathforge.ingest --input new_seeds.csv --map question=problem answer=label --source batchA

常见别名自动识别(如 problem/stem→questionlabel/gt→answertopic→category); 无答案的记录会被当作 seed_type=directive(出题方向指令)入库。

Install

pip install -r requirements.txt

需要一个 aihubmix 的 API key(OpenAI 兼容端点)。 API key 不写进代码,通过命令行 --api-key 或环境变量 AIHUBMIX_API_KEY 提供。

Quick start(一键全流程)

# key 作为启动参数
python run_pipeline.py --api-key sk-xxxxxx --num 30

# 或先设环境变量
export AIHUBMIX_API_KEY=sk-xxxxxx
python run_pipeline.py --num 30

产物默认在 ./output/generated.jsonl → generated.filtered.jsonl → verified.jsonl → final.jsonl, 其中合格题会单独追加到 final.qualified.jsonl

分阶段单独运行(推荐:四段独立,可分别重跑)

# ① 出题:满并发大批量产题,不做任何验证
python -m mathforge.generate   --api-key sk-xxx --num 200 --concurrency 30 --output output/generated.jsonl

# ② 题干可靠性+答案形态预筛:不通过则不进 gpt-5.5/豆包
python -m mathforge.reliability_filter --api-key sk-xxx --input output/generated.jsonl --reliable-output output/generated.filtered.jsonl --unreliable-output output/generated.filtered.dropped.jsonl

# ③ gpt-5.5 解题:只给题干,一次处理一批,返回 reliable + answer + solution
#    输出 verified.jsonl(可靠且有答案+解析) 与 verified.jsonl.dropped.jsonl(不可靠/缺字段/API异常)
python -m mathforge.batch_verify --api-key sk-xxx --input output/generated.filtered.jsonl --output output/verified.jsonl

# ④ 豆包难度门:目标模型作答 K 次,对比 gpt-5.5 真答案,做错=合格(--no-rubric)
python -m mathforge.difficulty --api-key sk-xxx --input output/verified.jsonl --output output/final.jsonl --no-rubric

默认模型(均可用 CLI 覆盖)

环节 默认模型
出题 / 改写 / 对抗 deepseek-v4-flash
题干可靠性 + 答案形态预筛 deepseek-v4-flash
gpt-5.5 解题定 ground truth(只给题干,返回答案+解析) gpt-5.5(batch=10)
难度门 · 目标模型(被挑战者) doubao-seed-2-0-pro
难度门 · 判分(目标答案≟真答案) deepseek-v4-pro

输出字段(合格题)

每条记录是统一 schema,依次累积各阶段产物:

  • 出题:question / answer / answer_format / key_points / from_seeds / gen_mode
  • 题干可靠性预筛:reliability_filter.{reliable, model_reliable, quality_score, difficulty_score, combined_score, reason, difficulty_reason}; 其中 difficulty_score 保留为兼容字段,当前预筛不按难度或题型偏好拦截
  • batch verify:batch_verify.{usable, reliable, reliability_reason, model_answer, original_answer, answer_corrected, solution}, 并把 answer / reference_answer 覆盖为 gpt-5.5 答案,groundtruth_solution 写入标准解析
  • 难度门:difficulty_gate.{verdict, rubric_score, rubric, solved, k, correct_count, rollouts[]}difficulty.pass_rate / difficulty.doubao_solved
  • 合格题单独文件:final.qualified.jsonl,只包含 difficulty_gate.verdict == "合格" 的题

其中 groundtruth_solution 是 gpt-5.5 在 batch verify 阶段生成的标准题目解析; rollouts[] 保留目标模型每次作答的 final_answer完整解答全文 solution

说明

  • API key 安全:切勿把 key 提交到仓库;.gitignore 已忽略 .envoutput/
  • 沙箱:验证阶段会本地执行 LLM 生成的计算脚本(已加超时与临时目录隔离),生产环境建议放进容器 / nsjail。
  • 速度deepseek / doubao 多为重推理模型,单题可能数分钟,请用 --concurrency 提升吞吐。
  • 难度:默认不对抗(--adv-rounds 0)直接出题,速度快;如需更难,可加 --adv-rounds 2 开启对抗。
  • 验证适用范围:独立计算验证对有确切数值/可程序化答案的题是客观判定;纯证明/开放题不适用。

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages