fix(bm25): 修复 BM25 索引覆盖 bug + 综合评测集 v2 + 检索增强
核心修复: - knowledge/base.py: BM25Index.add_documents 从覆盖改为追加+去重, 修复只有最后上传文件的 chunks 保留在 BM25 中的严重 bug (影响: 2.docx/3.docx/PDF 的 755 个 chunk 在 BM25 中完全缺失) 检索增强 (延续上次会话): - core/engine.py: section cluster boost + lexical match exemption - api/chat_routes.py: lexical/cluster rescue 层 + SSE 事件 - core/mmr.py: MMR 去重改进 评测体系: - tests/eval_dataset_v2.json: 62 题综合评测集 (9 种题型×4 文档) - scripts/eval_e2e.py: 推理模型 LLM 评分兼容 + 新数据集格式支持 - scripts/validate_eval_dataset.py: 数据集验证工具 其他: - parsers/mineru_parser.py: 解析器改进
This commit is contained in:
@@ -137,8 +137,8 @@ def parse_with_mineru_online(
|
||||
file_path: str,
|
||||
api_token: str = None,
|
||||
api_url: str = None,
|
||||
model_version: str = "vlm",
|
||||
timeout: int = 300
|
||||
model_version: str = None,
|
||||
timeout: int = None
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
使用 MinerU 在线 API 解析文档
|
||||
@@ -157,8 +157,8 @@ def parse_with_mineru_online(
|
||||
file_path: 文档文件路径
|
||||
api_token: API Token(默认从 config 读取)
|
||||
api_url: API 地址
|
||||
model_version: 模型版本 (vlm / pipeline / MinerU-HTML)
|
||||
timeout: 请求超时(秒)
|
||||
model_version: 模型版本 (vlm / pipeline / MinerU-HTML),默认从 config 读取
|
||||
timeout: 轮询超时(秒),默认从 config 读取
|
||||
|
||||
Returns:
|
||||
解析结果(与 parse_with_mineru 格式相同)
|
||||
@@ -167,10 +167,12 @@ def parse_with_mineru_online(
|
||||
import time
|
||||
import zipfile
|
||||
import io
|
||||
from config import MINERU_API_TOKEN, MINERU_API_URL
|
||||
from config import MINERU_API_TOKEN, MINERU_API_URL, MINERU_MODEL_VERSION, MINERU_ONLINE_TIMEOUT
|
||||
|
||||
token = api_token or MINERU_API_TOKEN
|
||||
url = api_url or MINERU_API_URL
|
||||
model_version = model_version or MINERU_MODEL_VERSION
|
||||
timeout = timeout or MINERU_ONLINE_TIMEOUT
|
||||
|
||||
if not token:
|
||||
raise RuntimeError("MinerU 在线 API Token 未配置,请在 config.py 中设置 MINERU_API_TOKEN")
|
||||
@@ -241,9 +243,15 @@ def parse_with_mineru_online(
|
||||
result_resp.raise_for_status()
|
||||
result = result_resp.json()
|
||||
|
||||
# 检查 API 层面的错误码,快速失败而非静默等到超时
|
||||
api_code = result.get("code")
|
||||
if api_code and api_code != 0:
|
||||
api_msg = result.get("msg", "未知错误")
|
||||
raise RuntimeError(f"MinerU API 错误 (code={api_code}): {api_msg}")
|
||||
|
||||
extract_results = result.get("data", {}).get("extract_result", [])
|
||||
if not extract_results:
|
||||
logger.debug(f"等待解析结果... ({waited}s)")
|
||||
logger.debug(f"等待解析结果... ({waited}s/{max_wait}s)")
|
||||
continue
|
||||
|
||||
# 取第一个文件的结果
|
||||
@@ -276,11 +284,16 @@ def parse_with_mineru_online(
|
||||
if progress:
|
||||
extracted = progress.get("extracted_pages", 0)
|
||||
total = progress.get("total_pages", 0)
|
||||
logger.info(f"解析进度: {extracted}/{total} 页 ({waited}s)")
|
||||
logger.info(f"解析进度: {extracted}/{total} 页 ({waited}s/{max_wait}s, model={model_version})")
|
||||
else:
|
||||
logger.debug(f"状态: {state}, 等待中... ({waited}s)")
|
||||
logger.debug(f"状态: {state}, 等待中... ({waited}s/{max_wait}s)")
|
||||
|
||||
raise RuntimeError("MinerU 在线解析超时")
|
||||
raise RuntimeError(
|
||||
f"MinerU 在线解析超时 ({max_wait}s)"
|
||||
f",当前 model_version={model_version}"
|
||||
f",可尝试: 1) 设置 MINERU_MODEL_VERSION=pipeline 加速"
|
||||
f" 2) 增大 MINERU_ONLINE_TIMEOUT"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"MinerU 在线 API 调用失败: {e}")
|
||||
@@ -737,7 +750,7 @@ def parse_with_mineru(
|
||||
lang: str = "ch",
|
||||
enable_table: bool = True,
|
||||
enable_formula: bool = True,
|
||||
backend: str = "pipeline",
|
||||
backend: str = None,
|
||||
start_page: int = 0,
|
||||
end_page: int = 99999
|
||||
) -> Dict[str, Any]:
|
||||
@@ -770,6 +783,14 @@ def parse_with_mineru(
|
||||
if not file_path.exists():
|
||||
raise FileNotFoundError(f"文件不存在: {file_path}")
|
||||
|
||||
# 从 config 读取默认 backend
|
||||
if backend is None:
|
||||
try:
|
||||
from config import MINERU_LOCAL_BACKEND
|
||||
backend = MINERU_LOCAL_BACKEND
|
||||
except ImportError:
|
||||
backend = 'pipeline'
|
||||
|
||||
# 检查文件大小
|
||||
file_size = file_path.stat().st_size
|
||||
if file_size > MAX_PDF_SIZE:
|
||||
@@ -814,7 +835,6 @@ def parse_with_mineru(
|
||||
|
||||
cmd = [
|
||||
str(mineru_exe),
|
||||
"--",
|
||||
"-p", str(file_path),
|
||||
"-o", str(output_dir),
|
||||
"-m", "auto",
|
||||
@@ -859,7 +879,7 @@ def parse_with_mineru(
|
||||
logger.error(f"MinerU 解析失败: {e}")
|
||||
raise
|
||||
finally:
|
||||
清理临时目录
|
||||
# 清理临时目录
|
||||
if cleanup_output and os.path.exists(output_dir):
|
||||
shutil.rmtree(output_dir, ignore_errors=True)
|
||||
|
||||
@@ -1688,7 +1708,7 @@ def parse_with_mineru_persistent(
|
||||
lang: str = "ch",
|
||||
enable_table: bool = True,
|
||||
enable_formula: bool = True,
|
||||
backend: str = "pipeline",
|
||||
backend: str = None,
|
||||
start_page: int = 0,
|
||||
end_page: int = 99999,
|
||||
cleanup_after_image_move: bool = True
|
||||
@@ -1727,6 +1747,14 @@ def parse_with_mineru_persistent(
|
||||
if not file_path.exists():
|
||||
raise FileNotFoundError(f"文件不存在: {file_path}")
|
||||
|
||||
# 从 config 读取默认 backend
|
||||
if backend is None:
|
||||
try:
|
||||
from config import MINERU_LOCAL_BACKEND
|
||||
backend = MINERU_LOCAL_BACKEND
|
||||
except ImportError:
|
||||
backend = 'pipeline'
|
||||
|
||||
# 检查文件大小
|
||||
file_size = file_path.stat().st_size
|
||||
if file_size > MAX_PDF_SIZE:
|
||||
|
||||
Reference in New Issue
Block a user