app.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from flask import Flask, request, jsonify
  2. from flask_cors import CORS
  3. from duplicate_checker import QuestionDuplicateChecker
  4. app = Flask(__name__)
  5. CORS(app) # 启用跨域支持
  6. # 初始化查重器(全局单例,避免重复加载索引)
  7. checker = QuestionDuplicateChecker()
  8. @app.route('/api/check_duplicate', methods=['POST'])
  9. def check_duplicate():
  10. """
  11. 题目查重 API 接口 (提交前预检模式)
  12. 参数: stem, options, answer, solution
  13. """
  14. data = request.get_json()
  15. print(f"📥 收到查重请求 (内容比对): {data}")
  16. if not data:
  17. return jsonify({"code": -1, "message": "Missing content"}), 400
  18. # 提取内容字段
  19. question_data = {
  20. "stem": data.get('stem', ''),
  21. "options": data.get('options', ''),
  22. "answer": data.get('answer', ''),
  23. "solution": data.get('solution', '')
  24. }
  25. if not question_data["stem"]:
  26. return jsonify({"code": -1, "message": "stem is required"}), 400
  27. # 执行基于内容的查重
  28. result = checker.check_duplicate_by_content(question_data)
  29. # 增加详细日志
  30. top_score = result["top_similar"][0]["similarity"] if result.get("top_similar") else "N/A"
  31. print(f"🔍 查重决策详情: status={result.get('status')}, "
  32. f"is_duplicate={result.get('is_duplicate')}, "
  33. f"max_score={top_score}, "
  34. f"gpt_checked={result.get('gpt_checked', False)}")
  35. if result.get("status") == "error":
  36. return jsonify({"code": -1, "message": result.get("message")}), 500
  37. if result.get("is_duplicate"):
  38. item = result["top_similar"][0]
  39. gpt_info = " (经 GPT-4o 深度核验)" if result.get("gpt_checked") else ""
  40. return jsonify({
  41. "code": -1,
  42. "result": {
  43. "repeatIdList": [{
  44. "questionsId": item["id"],
  45. "repeatMsg": f"相似度: {item['similarity']}{gpt_info}。相似点: {item['similar_point']}"
  46. }]
  47. }
  48. })
  49. else:
  50. return jsonify({"code": 0, "result": "ok"})
  51. @app.route('/api/sync', methods=['POST'])
  52. def sync_index():
  53. """手动触发全量同步接口"""
  54. print("🔄 收到同步索引请求")
  55. try:
  56. checker.sync_all_from_db()
  57. return jsonify({"code": 0, "result": "Sync completed"})
  58. except Exception as e:
  59. return jsonify({"code": -1, "message": str(e)}), 500
  60. @app.route('/api/confirm_repeat', methods=['POST'])
  61. def confirm_repeat():
  62. """
  63. 人工确认查重结果接口
  64. 参数: questionId, isRepeat (0: 无相似, 1: 有重复)
  65. """
  66. data = request.get_json()
  67. print(f"📥 收到确认结果请求: {data}")
  68. if not data:
  69. return jsonify({"code": -1, "message": "Missing JSON body"}), 400
  70. question_id = data.get('questionId')
  71. is_repeat = data.get('isRepeat')
  72. if question_id is None or is_repeat is None:
  73. return jsonify({"code": -1, "message": "Missing questionId or isRepeat"}), 400
  74. try:
  75. success = checker.confirm_repeat(int(question_id), int(is_repeat))
  76. if success:
  77. return jsonify({"code": 0, "result": "ok"})
  78. else:
  79. return jsonify({"code": -1, "message": "Failed to update"}), 500
  80. except Exception as e:
  81. return jsonify({"code": -1, "message": str(e)}), 500
  82. @app.route('/api/question_info', methods=['GET'])
  83. def get_question_info():
  84. """
  85. 查询题目在向量库中的信息
  86. 参数: questionId
  87. """
  88. question_id = request.args.get('questionId')
  89. if not question_id:
  90. return jsonify({"code": -1, "message": "Missing questionId"}), 400
  91. try:
  92. result = checker.get_question_data(int(question_id))
  93. return jsonify({
  94. "code": 0,
  95. "result": result
  96. })
  97. except ValueError:
  98. return jsonify({"code": -1, "message": "Invalid questionId format"}), 400
  99. except Exception as e:
  100. return jsonify({"code": -1, "message": str(e)}), 500
  101. if __name__ == '__main__':
  102. # 启动服务,默认 5000 端口
  103. app.run(host='0.0.0.0', port=8888, debug=False)