diff --git a/exam_pkg/manager.py b/exam_pkg/manager.py index 5a1fcca..1f0e80d 100644 --- a/exam_pkg/manager.py +++ b/exam_pkg/manager.py @@ -61,6 +61,113 @@ QUESTION_BANK_DIR = "./题库" DRAFT_DIR = "./题库/草稿" +# ==================== 文件状态检查 ==================== + +def check_file_indexed(file_path: str, collection: str) -> Dict: + """ + 检查文件是否已向量化 + + Args: + file_path: 文件路径 + collection: 向量库名称 + + Returns: + { + "indexed": True/False, # 是否已索引 + "chunk_count": 0, # 切片数量 + "status": "ready/not_found/indexing/error", + "message": "状态说明" + } + """ + if not file_path or not collection: + return { + "indexed": False, + "chunk_count": 0, + "status": "error", + "message": "缺少文件路径或向量库名称" + } + + try: + from core.engine import get_engine + engine = get_engine() + + if not engine: + return { + "indexed": False, + "chunk_count": 0, + "status": "error", + "message": "RAG 引擎未初始化" + } + + # 提取文件名 + filename = os.path.basename(file_path) + + # 查询向量库 + collections = [collection] if isinstance(collection, str) else list(collection) if collection else [] + + if not collections: + return { + "indexed": False, + "chunk_count": 0, + "status": "error", + "message": "未指定向量库" + } + + # 尝试检索文件切片 + total_chunks = 0 + found_collection = None + + for coll in collections: + try: + # 使用简单 query 查询文件 + results = engine.search_knowledge( + query="document", + collections=[coll], + source_filter=filename, + top_k=1 + ) + + if results and results.get('documents') and results['documents'][0]: + # 获取该文件的切片总数 + collection_obj = engine.kb_manager.get_collection(coll) + if collection_obj: + all_results = collection_obj.get( + where={"source": filename} + ) + if all_results and all_results.get('ids'): + total_chunks = len(all_results['ids']) + found_collection = coll + break + except Exception as e: + logger.warning(f"检查向量库 {coll} 失败: {e}") + continue + + if total_chunks > 0: + return { + "indexed": True, + "chunk_count": total_chunks, + "status": "ready", + "message": f"文件已索引,共 {total_chunks} 个切片", + "collection": found_collection + } + else: + return { + "indexed": False, + "chunk_count": 0, + "status": "not_found", + "message": f"文件 {filename} 未在向量库中找到,可能正在向量化或未上传" + } + + except Exception as e: + logger.error(f"检查文件索引状态失败: {e}") + return { + "indexed": False, + "chunk_count": 0, + "status": "error", + "message": f"检查状态异常: {str(e)}" + } + + # ==================== 新版出题接口 ==================== def generate_questions_from_file( @@ -102,6 +209,28 @@ def generate_questions_from_file( """ options = options or {} + # 🔥 新增:检查文件向量化状态 + file_status = check_file_indexed(file_path, collection) + + if not file_status["indexed"]: + # 文件未索引,返回明确的错误信息 + error_messages = { + "not_found": f"文件未向量化: {file_status['message']}", + "error": f"检查文件状态失败: {file_status['message']}", + } + + return { + "success": False, + "request_id": request_id, + "error_code": "FILE_NOT_INDEXED" if file_status["status"] == "not_found" else "STATUS_CHECK_ERROR", + "message": error_messages.get(file_status["status"], file_status["message"]), + "file_status": file_status["status"], + "chunk_count": file_status["chunk_count"], + "questions": [], + "total": 0, + "source_chunks_used": 0 + } + # 1. 检索文件的所有切片 chunks = retrieve_file_chunks( file_path=file_path,