
用 Python 构建一个反刷题式学习行为激励系统不考核答对多少而奖励提出多少好问题——把提问本身变成一等公民的学习行为。内容紧扣心理健康与创新能力课程保持去营销化、中立、可教学、可复用不涉及任何教育产品推广。项目名QuestionFirst — 提问优先的学习行为激励器一、实际应用场景描述在心理健康与创新能力课程中有一个核心命题创新思维的起点不是知道答案而是提出好问题现实学习场景包括- 刷题系统只统计正确率错误 失败- 学生学会猜标准答案而非质疑前提- 提问行为被边缘化——问得多反而显得不会- 创新力在追求正确的过程中被系统性抑制教育学与心理学研究指出- 提问质量与创造力高度正相关Guilford, Torrance- 心理安全感是提问行为的前提Amy Edmondson- 过度强调正确率 → 评价焦虑 → 思维收敛 → 创新力下降QuestionFirst 的目标不是替代刷题而是在学习过程中把主动提出疑问从隐形行为变为可量化、可奖励的核心指标二、引入痛点现有学习工具的评估盲区维度 刷题软件 QuestionFirst核心指标 正确率 提问数量与质量错误处理 扣分 不计分保留价值行为导向 追求唯一正确答案 鼓励发散性提问创新影响 收敛思维 发散思维真实痛点- 学习者形成提问 暴露无知的负向认知- 错题只被当作要消灭的错误而非思维的路标- 系统没有机制奖励这个问题本身很有价值- 创新思考习惯缺乏可操作的培养工具三、核心逻辑讲解先讲思想核心隐喻答案解决已知问题问题创造未知可能程序做了什么1. 记录学习过程中的主动提问行为- 不评价问题对不对- 只记录提出时间、问题内容、问题类型2. 错题不计分转化为问题素材- 每道错题自动生成可追问方向- 鼓励学生对错误本身提问3. 设计提问奖励机制- 基础分每提出 1 个问题 1 分- 发散奖励非常规角度提问 ×2 倍- 追问奖励对同一知识点连续追问 ×1.5 倍4. 生成提问力报告- 提问总量、类型分布、发散指数- 对比答题正确率与提问活跃度的相关性关键设计原则- 不替代正确率考核而是平行增加提问维度- 错题是资产不是负债- 奖励好奇而非聪明四、代码模块化设计项目结构question_first/│├── README.md├── requirements.txt├── main.py├── core/│ ├── question_logger.py # 提问行为记录│ ├── error_reframer.py # 错题 → 追问素材│ ├── scoring_engine.py # 提问奖励计分│ └── reporter.py # 提问力报告└── data/└── learning_log.json五、核心代码实现Python1️⃣ 提问行为记录器question_logger.py# core/question_logger.pyfrom datetime import datetimefrom pathlib import Pathimport jsonfrom typing import Optionalclass QuestionLogger:记录学习过程中的主动提问行为不评价问题质量只记录行为与类型def __init__(self):self.path Path(data/learning_log.json)self.path.parent.mkdir(exist_okTrue)if not self.path.exists():self._write({questions: [], errors: []})def _read(self):with open(self.path, r, encodingutf-8) as f:return json.load(f)def _write(self, data):with open(self.path, w, encodingutf-8) as f:json.dump(data, f, ensure_asciiFalse, indent2)def log_question(self,content: str,question_type: str curiosity,topic: str ,is_from_error: bool False):question_type:- curiosity : 好奇型为什么是这样- challenge : 质疑型这个前提成立吗- analogy : 联想型这个和XX有什么相似- perspective : 视角型如果从XX角度看呢- method : 方法型有没有其他方式entry {id: self._next_id(),timestamp: datetime.now().isoformat(),content: content,type: question_type,topic: topic,is_from_error: is_from_error}data self._read()data[questions].append(entry)self._write(data)return entry[id]def log_error(self, question_id: int, error_content: str):将错题与提问关联data self._read()data[errors].append({question_id: question_id,error_content: error_content,reframed: False})self._write(data)def _next_id(self) - int:data self._read()questions data.get(questions, [])return max((q[id] for q in questions), default0) 1设计说明将提问作为一等公民数据对象与错题解耦但可关联2️⃣ 错题重构器error_reframer.py# core/error_reframer.pyfrom .question_logger import QuestionLoggerclass ErrorReframer:将错题转化为追问素材不纠错而是打开问题空间def __init__(self):self.logger QuestionLogger()def reframe(self, error_content: str) - list[str]:从一道错题中自动生成可追问的方向使用模板法不依赖大模型prompts [f为什么我会认为『{self._short(error_content)}』是正确的,f这个错误的背后隐藏了什么未被质疑的假设,f如果换一种思路来看『{self._short(error_content)}』会有什么不同,f这个知识点和我已经掌握的哪些东西产生了冲突,f如果要把这个错误变成一道更有趣的题它会是什么样]return promptsdef _short(self, text: str, max_len: int 30) - str:return text[:max_len] … if len(text) max_len else textdef auto_suggest(self, error_content: str) - list[int]:自动生成追问建议并返回新问题 ID 列表prompts self.reframe(error_content)ids []for prompt in prompts:qid self.logger.log_question(contentprompt,question_typereframed_error,is_from_errorTrue)ids.append(qid)# 标记原错题已重构data self.logger._read()for err in data[errors]:if err[error_content] error_content:err[reframed] Trueself.logger._write(data)return ids设计说明核心哲学一道错题至少值得 5 个好问题3️⃣ 提问奖励计分引擎scoring_engine.py# core/scoring_engine.pyfrom collections import Counterfrom .question_logger import QuestionLoggerclass ScoringEngine:计算提问行为的奖励分数刻意不与正确率挂钩# 问题类型权重发散性越强的权重越高TYPE_WEIGHTS {curiosity: 1.0, # 基础好奇challenge: 2.0, # 质疑前提高发散analogy: 2.0, # 联想迁移高发散perspective: 1.5, # 视角切换method: 1.5, # 方法探索reframed_error: 1.8, # 错题重构中高发散}def __init__(self):self.logger QuestionLogger()def calculate_score(self) - dict:data self.logger._read()questions data.get(questions, [])if not questions:return {total: 0, by_type: {}, bonus: 0}# 基础分 提问数量 × 类型权重type_counts Counter(q[type] for q in questions)type_scores {t: count * self.TYPE_WEIGHTS.get(t, 1.0)for t, count in type_counts.items()}# 发散奖励非常规类型challenge / analogy加倍divergent_count sum(type_counts.get(t, 0)for t in [challenge, analogy, perspective])divergent_bonus divergent_count * 0.5# 追问奖励错题转化error_reframed sum(1 for q in questions if q.get(is_from_error))reframe_bonus error_reframed * 1.0total sum(type_scores.values()) divergent_bonus reframe_bonusreturn {total: round(total, 1),by_type: {k: round(v, 1) for k, v in type_scores.items()},divergent_bonus: round(divergent_bonus, 1),reframe_bonus: round(reframe_bonus, 1),question_count: len(questions)}设计说明计分逻辑完全透明便于课堂讨论什么算一个好问题4️⃣ 提问力报告reporter.py# core/reporter.pyfrom .scoring_engine import ScoringEnginefrom .question_logger import QuestionLoggerclass Reporter:生成提问力报告与正确率报告平行存在def __init__(self):self.scorer ScoringEngine()self.logger QuestionLogger()def generate_report(self):score self.scorer.calculate_score()data self.logger._read()questions data.get(questions, [])print(\n 提问力报告)print( * 50)print(f提问总数{score[question_count]})print(f提问总得分{score[total]})print(f发散奖励加成{score[divergent_bonus]})print(f错题重构奖励{score[reframe_bonus]})print(\n 按类型分布)for qtype, pts in score[by_type].items():count sum(1 for q in questions if q[type] qtype)print(f {qtype}: {count} 次 → {pts} 分)# 提炼最高价值问题if questions:print(\n 最具发散性的提问类型, end)best max(score[by_type].items(),keylambda x: x[1])print(f{best[0]})print(\n 教学提示)print(1. 本工具不考核答对多少只激励问了多少)print(2. 错题不计分但重构为问题后可获奖励)print(3. 质疑型与联想型提问权重最高鼓励发散思维)print(4. 目标不是取代正确率而是让它不再孤独)return score5️⃣ 主程序main.py# main.pyfrom core.question_logger import QuestionLoggerfrom core.error_reframer import ErrorReframerfrom core.reporter import Reporterdef main():logger QuestionLogger()reframer ErrorReframer()reporter Reporter()# 模拟学生主动提出疑问logger.log_question(content为什么这个公式只考虑了一种情况,question_typechallenge,topic数学-导数)logger.log_question(content这个解法能不能用在物理题上,question_typeanalogy,topic数学-导数)logger.log_question(content如果从几何角度理解呢,question_typeperspective,topic数学-导数)# 模拟做错题后系统自动生成追问建议error 我算错了复合函数求导把内层导数漏掉了logger.log_error(question_id1, error_contenterror)suggested_ids reframer.auto_suggest(error)print(f\n 错题重构已自动生成 {len(suggested_ids)} 个追问建议)# 生成报告reporter.generate_report()if __name__ __main__:main()六、README 文件# QuestionFirst一个提问优先的学习行为激励工具。## 目的- 把主动提问从隐形行为变为可量化、可奖励的核心指标- 错题不计分转化为发散追问的素材- 与正确率考核平行运行而非替代- 培养创新思考习惯而非追求标准答案## 使用说明### 运行环境- Python 3.8- 仅使用标准库### 启动bashpython main.py### 记录提问修改 main.py 中的 log_question 调用pythonlogger.log_question(content你的问题,question_typecuriosity, # 见下方类型说明topic知识主题)### 问题类型与权重| 类型 | 说明 | 权重 ||---|---|---|| curiosity | 好奇型为什么 | 1.0x || challenge | 质疑型前提成立吗 | 2.0x || analogy | 联想型和XX像吗 | 2.0x || perspective | 视角型换个角度看 | 1.5x || method | 方法型有别的方式吗 | 1.5x || reframed_error | 错题重构 | 1.8x |### 错题重构pythonreframer.auto_suggest(你的错题描述)自动生成 5 个追问方向计入提问得分。## 输出内容- 提问总数与总得分- 按类型分布- 发散奖励与重构奖励- 教学提示## 适用场景- 数学/科学课堂的提问习惯培养- 创新思维能力训练- 心理健康课中的心理安全感实验- 对抗标准答案焦虑## 核心原则- 不评判问题的对错- 不替代正确率考核- 错题是资产不是负债- 所有数据本地存储七、核心知识点卡片去营销化卡片 1提问与创造力的关系- 关键词发散思维、问题发现、认知灵活性- 要点提出好问题比给出正确答案更需要创造力卡片 2心理安全感与学习行为- 关键词评价焦虑、探索性学习、内在动机- 要点当犯错不再被惩罚提问行为才会真正释放卡片 3重构式错误处理- 关键词认知重构、错误价值化、元认知- 要点把我错了转化为这个问题为什么值得追问八、总结工程师视角这个程序不是在帮学生刷题而是在悄悄重新定义什么算学习。技术层面- 用不到 200 行代码构建了一个完整的行为激励微系统- 数据结构极其简单但行为设计经过多层推敲- 刻意避免引入 AI 评分保持透明与可辩论性教学层面- 给提问一个可操作的入口- 让好奇变成可积累的资本- 让犯错变成创意的起跑线最终价值不是告诉你多提问题而是给你一个工具让每一次提问都被看见、被记录、被奖励——直到问出一个好问题比答对一道题更让你感到自豪。利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛