from flask import Flask, request, jsonify from flask_cors import CORS from duplicate_checker import QuestionDuplicateChecker app = Flask(__name__) CORS(app) # 启用跨域支持 # 初始化查重器(全局单例,避免重复加载索引) checker = QuestionDuplicateChecker() @app.route('/api/check_duplicate', methods=['POST']) def check_duplicate(): """ 题目查重 API 接口 (提交前预检模式) 参数: stem, options, answer, solution """ data = request.get_json() print(f"📥 收到查重请求 (内容比对): {data}") if not data: return jsonify({"code": -1, "message": "Missing content"}), 400 # 提取内容字段 question_data = { "stem": data.get('stem', ''), "options": data.get('options', ''), "answer": data.get('answer', ''), "solution": data.get('solution', '') } if not question_data["stem"]: return jsonify({"code": -1, "message": "stem is required"}), 400 # 确保索引已加载(多进程下避免空索引) checker.ensure_index_loaded() # 执行基于内容的查重 result = checker.check_duplicate_by_content(question_data) # 增加详细日志 top_score = result["top_similar"][0]["similarity"] if result.get("top_similar") else "N/A" print(f"🔍 查重决策详情: status={result.get('status')}, " f"is_duplicate={result.get('is_duplicate')}, " f"max_score={top_score}, " f"gpt_checked={result.get('gpt_checked', False)}") if result.get("status") == "error": return jsonify({"code": -1, "message": result.get("message")}), 500 if result.get("is_duplicate"): item = result["top_similar"][0] gpt_info = " (经 GPT-4o 深度核验)" if result.get("gpt_checked") else "" return jsonify({ "code": -1, "result": { "repeatIdList": [{ "questionsId": item["id"], "repeatMsg": f"相似度: {item['similarity']}{gpt_info}。相似点: {item['similar_point']}" }] } }) else: return jsonify({"code": 0, "result": "ok"}) @app.route('/api/sync', methods=['POST']) def sync_index(): """手动触发全量同步接口""" print("🔄 收到同步索引请求") try: checker.ensure_index_loaded() started = checker.sync_all_from_db() if started: return jsonify({"code": 0, "result": "Sync completed"}) return jsonify({"code": 0, "result": "Sync already running"}) except Exception as e: return jsonify({"code": -1, "message": str(e)}), 500 @app.route('/api/confirm_repeat', methods=['POST']) def confirm_repeat(): """ 人工确认查重结果接口 参数: questionId, isRepeat (0: 无相似, 1: 有重复) """ data = request.get_json() print(f"📥 收到确认结果请求: {data}") if not data: return jsonify({"code": -1, "message": "Missing JSON body"}), 400 question_id = data.get('questionId') is_repeat = data.get('isRepeat') if question_id is None or is_repeat is None: return jsonify({"code": -1, "message": "Missing questionId or isRepeat"}), 400 try: checker.ensure_index_loaded() success = checker.confirm_repeat(int(question_id), int(is_repeat)) if success: return jsonify({"code": 0, "result": "ok"}) else: return jsonify({"code": -1, "message": "Failed to update"}), 500 except Exception as e: return jsonify({"code": -1, "message": str(e)}), 500 @app.route('/api/question_info', methods=['GET']) def get_question_info(): """ 查询题目在向量库中的信息 参数: questionId """ question_id = request.args.get('questionId') if not question_id: return jsonify({"code": -1, "message": "Missing questionId"}), 400 try: checker.ensure_index_loaded() result = checker.get_question_data(int(question_id)) return jsonify({ "code": 0, "result": result }) except ValueError: return jsonify({"code": -1, "message": "Invalid questionId format"}), 400 except Exception as e: return jsonify({"code": -1, "message": str(e)}), 500 @app.route('/api/index_info', methods=['GET']) def get_index_info(): """查看当前索引文件路径及条数""" checker.ensure_index_loaded() index_count = int(checker.index.ntotal) if checker.index else 0 return jsonify({ "code": 0, "result": { "index_path": checker.index_path, "metadata_path": checker.metadata_path, "index_count": index_count, "metadata_count": len(checker.metadata) } }) if __name__ == '__main__': # 启动服务,默认 5000 端口 app.run(host='0.0.0.0', port=8888, debug=False)