""" 学习导师 — Flask Web 应用 模块:小学数学苏格拉底导师 + 七年级历史背诵问答 """ import json import uuid from flask import Flask, request, jsonify, render_template, session from tutor.wiki import StudentWiki from tutor.socratic import build_socratic_prompt, detect_topic, build_visual_hint from tutor.hermes_bridge import call_hermes from tutor.visualize import ( pie_chart, number_line, grid_array, bar_chart, shapes_library ) from tutor.history_quiz import get_quiz app = Flask(__name__) app.secret_key = "math-tutor-socratic-2026" def get_or_create_wiki() -> StudentWiki: if "student_id" not in session: session["student_id"] = f"student_{uuid.uuid4().hex[:8]}" return StudentWiki(session["student_id"]) # ──── 数学导师路由 ──── @app.route("/") def index(): wiki = get_or_create_wiki() return render_template("index.html", student_id=wiki.student_id, shapes=shapes_library()) @app.route("/ask", methods=["POST"]) def ask(): data = request.json or {} question = data.get("question", "").strip() if not question: return jsonify({"error": "请输入你的问题哦~"}), 400 wiki = get_or_create_wiki() student_profile = wiki.get_knowledge_summary() topic = detect_topic(question) prompt = build_socratic_prompt(question, student_profile, topic) socratic_reply = call_hermes(prompt) visual_hint = build_visual_hint(topic, question) svg = _generate_svg_for_topic(topic, question) wiki.ingest_session(question, "", [], "") return jsonify({ "reply": socratic_reply, "visual_hint": visual_hint, "topic": topic, "svg": svg, "student_profile": student_profile }) @app.route("/draw", methods=["POST"]) def draw(): data = request.json or {} viz_type = data.get("type", "pie") params = data.get("params", {}) svg = "" if viz_type == "pie": svg = pie_chart(params.get("fractions", [1, 1]), params.get("title", "")) elif viz_type == "numberline": svg = number_line(params.get("start", 0), params.get("end", 10), params.get("highlights", [])) elif viz_type == "grid": svg = grid_array(params.get("rows", 3), params.get("cols", 4), params.get("highlight_cells", [])) elif viz_type == "bar": svg = bar_chart(params.get("values", [3, 7, 2, 5]), params.get("labels", []), params.get("title", "")) return jsonify({"svg": svg}) @app.route("/profile", methods=["GET"]) def profile(): wiki = get_or_create_wiki() return jsonify(wiki.get_schema()) @app.route("/milestone", methods=["POST"]) def milestone(): wiki = get_or_create_wiki() data = request.json or {} wiki.record_milestone(data.get("topic", ""), data.get("desc", "")) return jsonify({"ok": True}) def _generate_svg_for_topic(topic, question): """占位 SVG 生成""" return "" # ──── 历史问答路由 ──── @app.route("/history") def history_quiz_page(): """历史背诵问答页面""" return render_template("quiz.html") @app.route("/quiz/units") def quiz_units(): """获取所有单元""" quiz = get_quiz() return jsonify({"units": quiz.get_units()}) @app.route("/quiz/random") def quiz_random(): """随机获取一道题""" quiz = get_quiz() unit_id = request.args.get("unit", None) q_type = request.args.get("type", None) return jsonify(quiz.get_random_question(unit_id=unit_id, question_type=q_type)) @app.route("/quiz/batch") def quiz_batch(): """批量获取题目""" quiz = get_quiz() count = min(int(request.args.get("count", 10)), 50) unit_id = request.args.get("unit", None) return jsonify({"questions": quiz.get_batch(count=count, unit_id=unit_id)}) @app.route("/quiz/check", methods=["POST"]) def quiz_check(): """检查答案""" quiz = get_quiz() data = request.json or {} qid = data.get("question_id", "") answer = data.get("answer", "") return jsonify(quiz.check_answer(qid, answer)) @app.route("/quiz/stats") def quiz_stats(): """题库统计""" quiz = get_quiz() return jsonify(quiz.get_stats()) if __name__ == "__main__": app.run(debug=True, host="0.0.0.0", port=5000)