# -*- coding: utf-8 -*- """初始化初中化学题库与知识图谱数据""" import sys import os sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from app import ( app, db, Question, KnowledgePoint, KnowledgeRelation, CurriculumTopic, ChemistryQuestionBank, ) def seed_questions(): """初中化学题库示例""" if Question.query.first(): print("题库已有数据,跳过") return data = [ ("下列物质中,不属于电解质的是?", "NaCl", "CH₃COOH", "Cu (金属铜)", "NaOH", "C", "电解质"), ("下列关于化学反应速率的说法正确的是?", "反应速率是指反应物浓度的减少", "反应速率是指生成物浓度的增加", "反应速率可以用单位时间内反应物浓度的减少来表示", "反应速率与反应物的性质无关", "C", "化学反应速率"), ("下列属于氧化还原反应的是?", "CaCO₃ 高温分解", "NaOH + HCl = NaCl + H₂O", "2H₂ + O₂ 点燃 2H₂O", "AgNO₃ + NaCl = AgCl↓ + NaNO₃", "C", "氧化还原反应"), ("物质的量的单位是?", "g", "mol", "L", "m³", "B", "物质的量"), ("元素周期表中,同周期元素从左到右,原子半径变化规律是?", "逐渐增大", "逐渐减小", "先增大后减小", "不变", "B", "元素周期律"), ("下列物质能在氧气中燃烧并产生大量白烟的是?", "碳", "硫", "磷", "铁丝", "C", "氧气性质"), ("原子核由什么组成?", "质子和电子", "质子和中子", "中子和电子", "质子、中子和电子", "B", "原子结构"), ("酸溶液能使紫色石蕊试液变?", "红色", "蓝色", "无色", "紫色", "A", "酸碱指示剂"), ("催化剂在化学反应中的作用是?", "增加反应物", "减少生成物", "改变化学反应速率", "改变反应条件", "C", "催化剂"), ("离子反应发生的条件是?", "有沉淀、气体或水生成", "有催化剂", "加热", "加压", "A", "离子反应"), ] for content, a, b, c, d, correct, kp in data: db.session.add(Question( content=content, option_a=a, option_b=b, option_c=c, option_d=d, correct_option=correct, knowledge_point=kp or None )) db.session.commit() print("已插入 %d 道题目" % len(data)) def seed_curriculum_topics(): """初始化课程主题""" if CurriculumTopic.query.first(): print("curriculum_topics 已有数据,跳过") return topics = [ dict(name="物质分类", phase="初中", chapter="第一章 走进化学世界", description="区分纯净物、混合物、单质、化合物等"), dict(name="原子结构", phase="初中", chapter="第二章 走进原子世界", description="认识质子、中子、电子及核外电子排布"), dict(name="化学方程式", phase="初中", chapter="基本概念与化学方程式", description="化学反应的符号表示及配平"), dict(name="化学实验基础", phase="初中", chapter="化学实验基本方法", description="常用仪器、操作规范、安全意识"), dict(name="溶液与浓度", phase="初中", chapter="溶液", description="溶液配制、溶质质量分数等"), dict(name="金属及其化合物", phase="初中", chapter="金属活动性顺序", description="金属与酸、盐溶液的反应与置换"), dict(name="酸碱盐", phase="初中", chapter="酸碱盐", description="常见酸碱盐的性质及反应"), dict(name="气体制取与性质", phase="初中", chapter="常见气体", description="氧气、二氧化碳等的制取与性质"), dict(name="微观粒子模型", phase="初中", chapter="微观与宏观", description="分子、原子、离子等微观示意图"), dict(name="化学安全与环保", phase="初中", chapter="化学与生活", description="安全操作、事故应急与环保意识"), ] db.session.bulk_save_objects([CurriculumTopic(**t) for t in topics]) db.session.commit() print("已插入 %d 个课程主题" % len(topics)) def seed_chemistry_question_bank(): """多题型统一题库(每类大约 10~20 题,后续可自行扩展)""" if ChemistryQuestionBank.query.first(): print("chemistry_question_bank 已有数据,跳过") return questions = [] # 1. 基础概念辨析题(choice)约 50 题 choice_data = [ dict( difficulty="easy", topic="物质分类", content="下列物质属于纯净物的是:A.空气 B.矿泉水 C.蒸馏水 D.泥水", answer_schema={ "options": {"A": "空气", "B": "矿泉水", "C": "蒸馏水", "D": "泥水"}, "correct": ["C"], }, hint="纯净物只有一种微粒组成", ), dict( difficulty="medium", topic="原子结构", content="原子核中一定含有的粒子是:A.质子 B.中子 C.电子 D.离子", answer_schema={ "options": {"A": "质子", "B": "中子", "C": "电子", "D": "离子"}, "correct": ["A"], }, hint="注意氢原子的特殊性", ), dict( difficulty="easy", topic="化学方程式", content="催化剂在化学反应中的作用是:A.提高产物质量 B.改变反应速率 C.增加反应物浓度 D.减少能量消耗", answer_schema={ "options": { "A": "提高产物质量", "B": "改变反应速率", "C": "增加反应物浓度", "D": "减少能量消耗", }, "correct": ["B"], }, hint="只改变速率,不改反应前后物质总能量", ), dict( difficulty="easy", topic="物质分类", content="下列属于金属单质的是:A.Fe B.Fe₂O₃ C.NaCl D.H₂O", answer_schema={ "options": {"A": "Fe", "B": "Fe₂O₃", "C": "NaCl", "D": "H₂O"}, "correct": ["A"], }, hint="元素与化合物的区分", ), dict( difficulty="easy", topic="物质分类", content="下列属于混合物的是:A.液氯 B.蒸馏水 C.干冰 D.生理盐水", answer_schema={ "options": { "A": "液氯", "B": "蒸馏水", "C": "干冰", "D": "生理盐水", }, "correct": ["D"], }, hint="盐溶解在水中形成混合物", ), dict( difficulty="medium", topic="酸碱盐", content="能使紫色石蕊溶液变红的是:A.NaCl溶液 B.NaOH溶液 C.HCl溶液 D.蒸馏水", answer_schema={ "options": { "A": "NaCl溶液", "B": "NaOH溶液", "C": "HCl溶液", "D": "蒸馏水", }, "correct": ["C"], }, hint="酸使石蕊变红,碱使石蕊变蓝", ), dict( difficulty="easy", topic="酸碱盐", content="下列属于碱的是:A.NaCl B.NaOH C.H₂SO₄ D.CO₂", answer_schema={ "options": {"A": "NaCl", "B": "NaOH", "C": "H₂SO₄", "D": "CO₂"}, "correct": ["B"], }, hint="含有金属阳离子和 OH⁻ 的化合物", ), dict( difficulty="medium", topic="金属及其化合物", content="在金属活动性顺序中,能从 CuSO₄ 溶液中置换出铜的金属是:A.Cu B.Ag C.Fe D.Hg", answer_schema={ "options": {"A": "Cu", "B": "Ag", "C": "Fe", "D": "Hg"}, "correct": ["C"], }, hint="Fe 比 Cu 活泼,可置换", ), dict( difficulty="easy", topic="化学安全与环保", content="下列行为有利于环境保护的是:A.露天焚烧垃圾 B.乱倒废酸 C.使用无磷洗衣粉 D.随意排放含重金属废水", answer_schema={ "options": { "A": "露天焚烧垃圾", "B": "乱倒废酸", "C": "使用无磷洗衣粉", "D": "随意排放含重金属废水", }, "correct": ["C"], }, hint="无磷洗衣粉可减轻水体富营养化", ), dict( difficulty="easy", topic="化学安全与环保", content="下列做法中符合化学实验室安全要求的是:A.品尝药品判断其性质 B.用鼻子直接凑近药品闻气味 C.用手扇动少量气体再闻 D.把药品带回家继续做实验", answer_schema={ "options": { "A": "品尝药品判断其性质", "B": "用鼻子直接凑近药品闻气味", "C": "用手扇动少量气体再闻", "D": "把药品带回家继续做实验", }, "correct": ["C"], }, hint="标准闻气体方法", ), ] # 补充自动生成的基础选择题示例,使 choice 题型接近 50 题 base_choice_count = len(choice_data) for i in range(base_choice_count + 1, 51): choice_data.append(dict( difficulty="easy" if i <= 14 else "medium", topic="物质分类" if i % 2 == 0 else "酸碱盐", content=f"【选择题示例{i}】下列说法中正确的是?", answer_schema={ "options": { "A": "这是一个占位示例选项 A", "B": "这是一个占位示例选项 B(正确)", "C": "这是一个占位示例选项 C", "D": "这是一个占位示例选项 D", }, "correct": ["B"], }, hint="用于系统演示的占位选择题,可后续替换为真实题目", )) for q in choice_data: questions.append(ChemistryQuestionBank( type="choice", difficulty=q["difficulty"], topic=q["topic"], content=q["content"], answer_schema=q["answer_schema"], hint=q.get("hint"), )) # 2. 化学方程式书写题(equation)约 50 题 equation_data = [ dict( difficulty="easy", topic="气体制取与性质", content="写出实验室用双氧水制氧气的化学方程式:", answer_schema={ "expected_equation": "2H2O2 → 2H2O + O2↑", "conditions": "MnO2 作催化剂", }, hint="注意配平和气体符号", ), dict( difficulty="easy", topic="金属及其化合物", content="写出铁在氧气中燃烧的化学方程式:", answer_schema={ "expected_equation": "3Fe + 2O2 → Fe3O4", "conditions": "点燃", }, hint="生成黑色固体 Fe3O4", ), dict( difficulty="easy", topic="气体制取与性质", content="写出碳酸钙与盐酸反应的化学方程式:", answer_schema={ "expected_equation": "CaCO3 + 2HCl → CaCl2 + H2O + CO2↑", "conditions": "常温", }, hint="实验室制备 CO2", ), dict( difficulty="easy", topic="酸碱盐", content="写出盐酸与氢氧化钠溶液反应的化学方程式:", answer_schema={ "expected_equation": "HCl + NaOH → NaCl + H2O", "conditions": "溶液", }, hint="典型中和反应", ), dict( difficulty="medium", topic="金属及其化合物", content="写出锌与稀盐酸反应的化学方程式:", answer_schema={ "expected_equation": "Zn + 2HCl → ZnCl2 + H2↑", "conditions": "常温", }, hint="金属与酸反应生成盐和氢气", ), dict( difficulty="medium", topic="金属及其化合物", content="写出铁与硫酸铜溶液反应的化学方程式:", answer_schema={ "expected_equation": "Fe + CuSO4 → FeSO4 + Cu", "conditions": "常温", }, hint="金属活动性顺序应用", ), dict( difficulty="medium", topic="酸碱盐", content="写出碳酸钠溶液与盐酸反应的化学方程式:", answer_schema={ "expected_equation": "Na2CO3 + 2HCl → 2NaCl + H2O + CO2↑", "conditions": "溶液", }, hint="注意 CO2 气体放出", ), dict( difficulty="medium", topic="酸碱盐", content="写出石灰水与二氧化碳反应的化学方程式:", answer_schema={ "expected_equation": "Ca(OH)2 + CO2 → CaCO3↓ + H2O", "conditions": "微量 CO2", }, hint="澄清石灰水变浑浊", ), ] # 补充自动生成的方程式题示例,使 equation 题型接近 50 题 base_equation_count = len(equation_data) for i in range(base_equation_count + 1, 51): equation_data.append(dict( difficulty="easy" if i <= 14 else "medium", topic="化学方程式", content=f"【方程式示例{i}】写出一个常见的初中化学反应方程式:", answer_schema={ "expected_equation": "示例:2H2 + O2 → 2H2O", "conditions": "可根据课堂情境自行设定", }, hint="本题为占位示例,可后续替换为具体反应方程式", )) for q in equation_data: questions.append(ChemistryQuestionBank( type="equation", difficulty=q["difficulty"], topic=q["topic"], content=q["content"], answer_schema=q["answer_schema"], hint=q.get("hint"), )) # 3. 实验操作与安全常识题(experiment)约 50 题 experiment_data = [ dict( difficulty="easy", topic="化学实验基础", content="稀释浓硫酸的正确操作是?", answer_schema={ "scenario": "稀释浓硫酸", "correct_operation": "将浓硫酸沿器壁慢慢倒入水中并不断搅拌", "key_point": "酸入水防飞溅", }, hint="牢记“酸入水”原则", ), dict( difficulty="easy", topic="化学实验基础", content="检查装置气密性的常用方法是?", answer_schema={ "scenario": "检查装置气密性", "correct_operation": "封闭系统后轻轻挤压或捂热容器,观察导管末端气泡变化", "key_point": "压强变化观察气泡", }, hint="不能用明火直接检查", ), dict( difficulty="medium", topic="化学实验基础", content="蒸发结晶停止加热的合适时机是?", answer_schema={ "scenario": "蒸发结晶", "correct_operation": "蒸发皿中出现大量晶体、溶液尚未全部蒸干时停止加热", "key_point": "防止暴沸和晶体飞溅", }, hint="不能把水分完全蒸干", ), dict( difficulty="easy", topic="化学安全与环保", content="酒精灯着火后,应采用哪种方法灭火最安全?", answer_schema={ "scenario": "酒精灯起火", "correct_operation": "用湿抹布或灯帽盖灭,隔绝空气", "key_point": "禁止向燃烧的灯内添加酒精", }, hint="突出隔绝空气", ), dict( difficulty="easy", topic="化学安全与环保", content="强酸不慎溅到皮肤上,正确的处理方式是?", answer_schema={ "scenario": "强酸溅到皮肤", "correct_operation": "立即用大量清水冲洗,再根据情况就医", "key_point": "大量清水冲洗稀释", }, hint="不要先用碱液中和", ), dict( difficulty="medium", topic="化学实验基础", content="用量筒量取液体时,视线应如何放置?", answer_schema={ "scenario": "量筒读数", "correct_operation": "视线与凹液面最低处所在水平线相平", "key_point": "避免视差", }, hint="读弯月面最低点", ), dict( difficulty="medium", topic="化学实验基础", content="过滤操作中,滤纸应如何贴紧漏斗?", answer_schema={ "scenario": "过滤", "correct_operation": "将滤纸润湿后贴紧漏斗内壁,过滤时液面低于滤纸边缘", "key_point": "防止液体从滤纸外流下", }, hint="常见过滤规范", ), dict( difficulty="medium", topic="化学安全与环保", content="若不慎吸入较多氯气,正确的紧急处理方式是?", answer_schema={ "scenario": "吸入有毒气体", "correct_operation": "迅速离开现场到空气新鲜处,必要时就医", "key_point": "远离气体来源并就医", }, hint="强调撤离与就医", ), ] # 补充自动生成的实验与安全题示例,使 experiment 题型接近 50 题 base_experiment_count = len(experiment_data) for i in range(base_experiment_count + 1, 51): experiment_data.append(dict( difficulty="easy" if i <= 14 else "medium", topic="化学实验基础" if i % 2 == 0 else "化学安全与环保", content=f"【实验与安全示例{i}】下列哪一项更符合规范的化学实验操作或安全要求?", answer_schema={ "scenario": "实验室规范操作占位情境", "correct_operation": "选择符合课本要求的规范操作步骤", "key_point": "遵守实验室安全与操作规范", }, hint="本题为占位示例,用于丰富题库数量,可后续替换为具体实验情境", )) for q in experiment_data: questions.append(ChemistryQuestionBank( type="experiment", difficulty=q["difficulty"], topic=q["topic"], content=q["content"], answer_schema=q["answer_schema"], hint=q.get("hint"), )) # 4. 计算类习题(calculation)约 50 题 calculation_data = [ dict( difficulty="medium", topic="溶液与浓度", content="将 20g 质量分数为 10% 的 NaCl 溶液稀释至 5%,需加水多少克?", answer_schema={ "formula": "w = m溶质 / m溶液 × 100%", "steps": [ "计算溶质质量:m溶质 = 20g × 10% = 2g", "设稀释后溶液质量为 m2,有 2 / m2 = 5% ⇒ m2 = 40g", "需加水质量 = 40g - 20g = 20g", ], "answer": 20.0, "unit": "g", }, hint="注意溶质质量不变", ), dict( difficulty="medium", topic="气体制取与性质", content="电解 18g 水可制得氢气多少克?(相对分子质量:H2O=18,H2=2)", answer_schema={ "formula": "2H2O → 2H2 + O2", "steps": [ "由方程式知:36g 水生成 4g 氢气", "18g 水生成 x 克氢气,x = 4 × 18 / 36 = 2g", ], "answer": 2.0, "unit": "g", }, hint="由化学方程式确定质量比", ), dict( difficulty="medium", topic="溶液与浓度", content="向 100g 质量分数为 5% 的 NaCl 溶液中加入 10g NaCl 固体,所得溶液的质量分数约为多少?", answer_schema={ "formula": "w = m溶质 / m溶液 × 100%", "steps": [ "原溶质质量:m1 = 100g × 5% = 5g", "加入溶质 10g,溶质总质量 m溶质 = 15g", "溶液总质量 m溶液 = 100g + 10g = 110g", "w ≈ 15 / 110 × 100% ≈ 13.6%", ], "answer": 13.6, "unit": "%", }, hint="既改变分子也改变分母", ), dict( difficulty="medium", topic="溶液与浓度", content="配制 200g 质量分数为 10% 的 NaCl 溶液,需要 NaCl 和水各多少克?", answer_schema={ "formula": "w = m溶质 / m溶液 × 100%", "steps": [ "m溶质 = 200g × 10% = 20g", "m溶剂(水) = 200g - 20g = 180g", ], "answer": {"solute": 20.0, "solvent": 180.0}, "unit": {"solute": "g", "solvent": "g"}, }, hint="先求溶质,再求溶剂", ), ] # 补充自动生成的计算题示例,使 calculation 题型接近 50 题 base_calculation_count = len(calculation_data) for i in range(base_calculation_count + 1, 51): calculation_data.append(dict( difficulty="medium", topic="溶液与浓度" if i % 2 == 0 else "气体制取与性质", content=f"【计算题示例{i}】根据给出的相对分子质量和化学方程式,完成一题质量或质量分数计算。", answer_schema={ "formula": "可结合题干给出的方程式与数据进行比例计算", "steps": [ "写出对应的化学方程式并配平", "根据物质的量关系列出质量比或浓度表达式", "代入数据计算并保留合适有效数字", ], "answer": None, "unit": "", }, hint="本题为占位示例,用于训练计算思路,可后续替换为具体数值题", )) for q in calculation_data: questions.append(ChemistryQuestionBank( type="calculation", difficulty=q["difficulty"], topic=q["topic"], content=q["content"], answer_schema=q["answer_schema"], hint=q.get("hint"), )) # 5. 物质推断题(inference)约 50 题 inference_data = [ dict( difficulty="medium", topic="金属及其化合物", content=( "A 为红色金属,B 能使澄清石灰水变浑浊,反应关系为:" "A + O₂ → B;B + Ca(OH)₂ → C。试推断 A、B、C 分别是什么物质?" ), answer_schema={ "clues": "A 为红色金属;B 能使澄清石灰水变浑浊", "reaction_chain": "A + O2 → B; B + Ca(OH)2 → C", "answer": ["Cu", "CO2", "CaCO3"], }, hint="结合颜色和使石灰水变浑浊的气体", ), dict( difficulty="medium", topic="金属及其化合物", content=( "X 与稀盐酸反应放出无色无味气体 Y,Y 能在空气中点燃呈淡蓝色火焰;" "金属 Z 能将 X 从其盐溶液中置换出来。试推断 X、Y、Z 分别可能是什么?" ), answer_schema={ "clues": "X 与酸反应放氢气;Z 能置换 X", "reaction_chain": "X + 2HCl → XCl2 + H2↑; Z + XCl2 → ZCl2 + X", "answer": ["Zn", "H2", "Fe"], }, hint="结合金属活动性顺序", ), dict( difficulty="medium", topic="酸碱盐", content=( "某白色固体 A 能溶于水,溶液能使紫色石蕊变红;" "A 溶液与一种无色溶液 B 反应生成白色沉淀 C。" "已知 B 中含有 Ba²⁺,推断 A、B、C 可能是什么?" ), answer_schema={ "clues": "A 溶液显酸性;B 中含 Ba2+;生成白色沉淀", "reaction_chain": "2H+ + SO4(2-) + Ba2+ → BaSO4↓ + 2H+", "answer": ["H2SO4 或 NaHSO4 等酸性物质", "BaCl2 溶液", "BaSO4"], }, hint="考虑生成难溶的硫酸钡沉淀", ), ] # 补充自动生成的物质推断题示例,使 inference 题型接近 50 题 base_inference_count = len(inference_data) for i in range(base_inference_count + 1, 51): inference_data.append(dict( difficulty="medium", topic="金属及其化合物" if i % 2 == 0 else "酸碱盐", content=( f"【物质推断示例{i}】已知某些物质在反应中会生成气体或沉淀," f"并且与金属活动性顺序或酸碱中和有关,请根据给出的线索推断相关物质。" ), answer_schema={ "clues": "结合题干给出的颜色变化、气体放出或沉淀生成等信息", "reaction_chain": "围绕金属活动性顺序或酸碱中和建立推断链", "answer": [], }, hint="本题为占位示例,用于训练推理链条,可后续替换为具体情境题", )) for q in inference_data: questions.append(ChemistryQuestionBank( type="inference", difficulty=q["difficulty"], topic=q["topic"], content=q["content"], answer_schema=q["answer_schema"], hint=q.get("hint"), )) # 6. 微观示意图分析题(diagram)约 50 题 diagram_data = [ dict( difficulty="easy", topic="微观粒子模型", content="下图为水分子分解示意图,该图可以解释哪一类化学变化?", answer_schema={ "diagram_url": "img/molecule_H2O.png", "description": "水分子电解分解为氢气和氧气的微观示意", "analysis_question": "该图示可解释何种反应?", "key_insight": "水发生化学变化,分子分裂生成新物质", }, hint="注意“分子分裂”为化学变化特征", ), dict( difficulty="easy", topic="微观粒子模型", content="下图为 NaCl 溶解电离的微观示意图,该溶液能导电的根本原因是?", answer_schema={ "diagram_url": "img/ionization_NaCl.png", "description": "NaCl 晶体在水中电离为 Na⁺ 和 Cl⁻", "analysis_question": "为何溶液能导电?", "key_insight": "溶液中有大量可以自由移动的离子", }, hint="区分金属导电与溶液导电机理", ), ] # 补充自动生成的微观示意图分析题示例,使 diagram 题型接近 50 题 base_diagram_count = len(diagram_data) for i in range(base_diagram_count + 1, 51): diagram_data.append(dict( difficulty="easy" if i <= 14 else "medium", topic="微观粒子模型", content=f"【微观示意图示例{i}】根据给出的粒子示意图,判断该图反映的是物质状态变化、化学变化或电离过程之一。", answer_schema={ "diagram_url": "img/example_micro_diagram.png", "description": "占位用微观粒子示意图,可表示分子间距、离子或原子的变化", "analysis_question": "图中反映的是哪一类微观变化?", "key_insight": "通过粒子种类、数目和排列方式的变化来判断物理或化学变化", }, hint="本题为占位示例,可后续替换为具体教材中的微观粒子示意图", )) for q in diagram_data: questions.append(ChemistryQuestionBank( type="diagram", difficulty=q["difficulty"], topic=q["topic"], content=q["content"], answer_schema=q["answer_schema"], hint=q.get("hint"), )) db.session.bulk_save_objects(questions) db.session.commit() print("已向 chemistry_question_bank 插入 %d 道多题型习题" % len(questions)) def seed_chemistry_hard_questions(): """为多题型题库补充 hard 难度习题,每种题型不少于 10 道 已有的 hard 题会被保留,只在数量不足的题型上补齐到 10 道。 """ TARGET_COUNT = 10 new_questions = [] # 1. choice 题型:补足到 10 道 hard existing_choice = ChemistryQuestionBank.query.filter_by( difficulty="hard", type="choice" ).count() if existing_choice < TARGET_COUNT: for i in range(existing_choice + 1, TARGET_COUNT + 1): content = ( f"【Hard 选择题 {i}】某反应前后有关物质的量或化合价发生变化," f"下列说法中正确的是?" ) answer_schema = { "options": { "A": "只要有气体生成就是氧化还原反应", "B": "只要有沉淀生成就是氧化还原反应", "C": "判断是否为氧化还原反应要看元素化合价是否变化", "D": "化学方程式两边原子个数不同也可能是氧化还原反应", }, "correct": ["C"], } new_questions.append(ChemistryQuestionBank( type="choice", difficulty="hard", topic="化学方程式", content=content, answer_schema=answer_schema, hint="掌握氧化还原反应的本质:元素化合价发生变化", )) # 2. equation 题型:补足到 10 道 hard existing_equation = ChemistryQuestionBank.query.filter_by( difficulty="hard", type="equation" ).count() if existing_equation < TARGET_COUNT: for i in range(existing_equation + 1, TARGET_COUNT + 1): content = ( f"【Hard 方程式 {i}】写出一个既体现金属活动性顺序," f"又能体现沉淀生成的离子反应的配平化学方程式。" ) answer_schema = { "expected_equation": "示例:Fe + CuSO4 → FeSO4 + Cu", "conditions": "常温,溶液中", } new_questions.append(ChemistryQuestionBank( type="equation", difficulty="hard", topic="化学方程式", content=content, answer_schema=answer_schema, hint="结合金属活动性顺序与难溶盐沉淀的知识,自拟一个合理的反应方程式", )) # 3. experiment 题型:补足到 10 道 hard existing_experiment = ChemistryQuestionBank.query.filter_by( difficulty="hard", type="experiment" ).count() if existing_experiment < TARGET_COUNT: for i in range(existing_experiment + 1, TARGET_COUNT + 1): content = ( f"【Hard 实验与安全 {i}】在设计验证某气体为 CO2 的实验时," f"如何合理选择试剂、装置并避免误判?" ) answer_schema = { "scenario": "验证某无色气体是否为 CO2", "correct_operation": ( "选用澄清石灰水检验,并设置对照实验;" "控制气体通入速度,防止生成 Ca(HCO3)2 造成再次澄清导致误判" ), "key_point": "有对照、控制变量,考虑条件变化对现象的影响", } new_questions.append(ChemistryQuestionBank( type="experiment", difficulty="hard", topic="化学实验基础", content=content, answer_schema=answer_schema, hint="思考如何通过对照与控制变量排除干扰因素", )) # 4. calculation 题型:补足到 10 道 hard existing_calculation = ChemistryQuestionBank.query.filter_by( difficulty="hard", type="calculation" ).count() if existing_calculation < TARGET_COUNT: for i in range(existing_calculation + 1, TARGET_COUNT + 1): content = ( f"【Hard 计算题 {i}】某 100g NaCl 溶液,质量分数为 15%," f"蒸发部分水并加入 10g NaCl 固体后,溶液质量分数变为 25%," f"求蒸发水的质量。" ) answer_schema = { "formula": "w = m溶质 / m溶液 × 100%", "steps": [ "原溶质质量 m1 = 100g × 15% = 15g", "加入固体 NaCl 10g 后,溶质总质量 m溶质 = 25g", "设蒸发水质量为 x,则溶液终质量 m2 = 100 + 10 - x = 110 - x", "由 25 / (110 - x) × 100% = 25%,得 25 / (110 - x) = 0.25", "解得 110 - x = 100 ⇒ x = 10(g)", ], "answer": 10.0, "unit": "g", } new_questions.append(ChemistryQuestionBank( type="calculation", difficulty="hard", topic="溶液与浓度", content=content, answer_schema=answer_schema, hint="同时注意溶质和溶剂质量的变化,建立方程求解", )) # 5. inference 题型:补足到 10 道 hard existing_inference = ChemistryQuestionBank.query.filter_by( difficulty="hard", type="inference" ).count() if existing_inference < TARGET_COUNT: for i in range(existing_inference + 1, TARGET_COUNT + 1): content = ( f"【Hard 物质推断 {i}】某白色固体 A 溶于水后溶液呈碱性," f"与稀盐酸反应放出无色无味气体 B,B 能在空气中点燃呈淡蓝色火焰;" f"A 溶液与硫酸铜溶液反应生成蓝色沉淀 C。推断 A、B、C 分别是什么。" ) answer_schema = { "clues": ( "溶液呈碱性且与稀盐酸反应放出氢气;" "能与 CuSO4 生成蓝色沉淀" ), "reaction_chain": ( "A + 2HCl → B↑ + 相应盐;" "A 溶液 + CuSO4 → C↓ + 其他产物" ), "answer": ["A:NaOH 或类似强碱", "B:H2", "C:Cu(OH)2"], } new_questions.append(ChemistryQuestionBank( type="inference", difficulty="hard", topic="酸碱盐", content=content, answer_schema=answer_schema, hint="结合气体性质和沉淀颜色,多步推断相关物质", )) # 6. diagram 题型:补足到 10 道 hard existing_diagram = ChemistryQuestionBank.query.filter_by( difficulty="hard", type="diagram" ).count() if existing_diagram < TARGET_COUNT: for i in range(existing_diagram + 1, TARGET_COUNT + 1): content = ( f"【Hard 微观示意图 {i}】给出某反应前后微观粒子示意图:" f"反应前为双原子分子与单原子金属颗粒的混合," f"反应后生成新的离子晶体。根据图示判断该反应类型并说明理由。" ) answer_schema = { "diagram_url": "img/hard_example_micro_diagram.png", "description": "金属与酸或盐溶液反应生成新晶体和气体/离子的示意图", "analysis_question": "判断反应类型(置换、复分解等),并从微观角度解释", "key_insight": "从粒子种类和数目变化判断是否有新物质生成及反应类型", } new_questions.append(ChemistryQuestionBank( type="diagram", difficulty="hard", topic="微观粒子模型", content=content, answer_schema=answer_schema, hint="结合微观粒子变化与反应类型的宏观特征进行分析", )) if not new_questions: print("chemistry_question_bank 各题型的 hard 难度习题数量已达到或超过 10 道,跳过") return db.session.bulk_save_objects(new_questions) db.session.commit() print("已向 chemistry_question_bank 追加 %d 道 hard 难度习题" % len(new_questions)) def seed_knowledge_points(): """从题目与知识图谱中同步知识点到 knowledge_points 表""" if KnowledgePoint.query.first(): return names = set() for (kp,) in db.session.query(Question.knowledge_point).filter( Question.knowledge_point.isnot(None), Question.knowledge_point != "", ).distinct().all(): if kp: names.add(kp) for s, p, o in [ ("电解质", "定义", "在水溶液或熔融状态下能够导电的化合物"), ("氧化还原反应", "特征", "有元素化合价发生变化的反应"), ("物质的量", "单位", "mol(摩尔)"), ("原子", "结构", "原子核和核外电子"), ]: names.add(s) if isinstance(o, str): names.add(o) for name in names: if not KnowledgePoint.query.filter_by(name=name).first(): db.session.add(KnowledgePoint(name=name)) db.session.commit() print("已同步 %d 个知识点到 knowledge_points" % len(names)) def seed_knowledge_graph(): """初中化学知识图谱三元组""" if KnowledgeRelation.query.first(): print("知识图谱已有数据,跳过") return data = [ ("电解质", "定义", "在水溶液或熔融状态下能够导电的化合物"), ("电解质", "包含", "酸、碱、盐"), ("非电解质", "定义", "在水溶液和熔融状态下都不导电的化合物"), ("非电解质", "举例", "蔗糖、酒精"), ("氧化还原反应", "特征", "有元素化合价发生变化的反应"), ("氧化还原反应", "包含", "氧化反应和还原反应"), ("物质的量", "单位", "mol(摩尔)"), ("物质的量", "表示", "含有一定数目粒子的集合体"), ("元素周期律", "内容", "元素的性质随原子序数递增呈周期性变化"), ("元素周期律", "表现", "原子半径、金属性、非金属性等"), ("离子反应", "条件", "有沉淀、气体或弱电解质生成"), ("化学反应速率", "定义", "单位时间内反应物或生成物浓度的变化"), ("催化剂", "特点", "能改变化学反应速率而本身质量和化学性质不变"), ("原子", "结构", "原子核和核外电子"), ("原子核", "组成", "质子和中子"), ] for s, p, o in data: db.session.add(KnowledgeRelation(subject=s, predicate=p, obj=o)) db.session.commit() print("已插入 %d 条知识图谱三元组" % len(data)) def main(): with app.app_context(): seed_questions() seed_knowledge_graph() seed_knowledge_points() seed_curriculum_topics() seed_chemistry_question_bank() seed_chemistry_hard_questions() print("初始化完成") if __name__ == "__main__": main()