Understanding directory - #4439
Conversation
# Conflicts: # tests/parse/test_understanding_api.py
# Conflicts: # openviking/service/resource_service.py
# Conflicts: # openviking/parse/understanding_api.py # openviking/service/resource_service.py # tests/parse/test_understanding_api.py
qin-ctx
left a comment
There was a problem hiding this comment.
目录逐文件路由到 Understanding 的方向合理。本次 review 有一个必须在合并前解决的问题:嵌套 ZIP 的子文件失败详情会被外层聚合丢掉;另外提示一下,嵌套 ZIP 也会重置目录文件数和深度限制。
| include=kwargs.get("include"), | ||
| exclude=kwargs.get("exclude"), | ||
| additional_can_process=parser_router.should_use_understanding_api, | ||
| max_files=directory_config.max_files, |
There was a problem hiding this comment.
[Bug] (non-blocking)
嵌套 ZIP 会让一次目录导入绕过 max_files 和 max_depth。外层扫描只把每个 .zip 计为一个入选文件;处理 ZIP 时,ZipParser 解压后会重新创建 DirectoryParser,文件数和深度从零开始计算。
例如 max_files=1000,目录里有两个 ZIP,每个 ZIP 各包含 1000 个 PDF。外层以 2 个文件通过,这两个内层扫描也分别以 1000 个文件通过,最终一次导入会提交 2000 个 Understanding 任务。连续嵌套 ZIP 同样会重置深度。嵌套 ZIP 是 ZipParser 明确支持的正常输入,因此这与文档所说的“一次目录在发起 Understanding 请求前完成完整预检”不一致。
请确认这里的限制预期是约束一次逻辑导入,还是每次递归 Parser 调用;是否处理、怎么处理由你决定。
| } | ||
| meta = detail.get("meta") | ||
| if isinstance(meta, dict): | ||
| for key in ( |
There was a problem hiding this comment.
[Bug] (blocking)
嵌套 ZIP 中有文件解析失败时,最终结果会把失败信息全部丢掉,只报告这个 ZIP 成功。
例如目录里有 bundle.zip,其中 good.md 成功,bad.pdf 的 Understanding 请求失败。内层 DirectoryParser 会保留 good.md,并在自己的 meta.failed_files 中记录 bad.pdf 的错误和远端 ID。ZipParser 原样返回这份结果,外层 _process_single_file 也把内层 meta 放进了文件状态;但这里构造外层状态时只复制 doc_name、file_id、response_id 等单文件字段,没有继续传递内层 failed_files。
最终外层只记录 bundle.zip 已处理成功,meta.failed_files 为空。用户不知道 bad.pdf 没有导入,也拿不到排查远端任务所需的 ID。这违反了本 PR 对目录部分失败返回详情的说明。
这个问题需要在合并前解决。请确认嵌套 ZIP 的叶子失败是否属于 meta.failed_files 契约;如果不属于,请说明受支持的嵌套 ZIP 为什么可以在子文件失败时只报告整体成功。具体怎么处理由你决定。
Description
支持普通目录和 HTML 页面目录按文件使用 UnderstandingAPI 解析。复用
ParserRouter,根据parser_api.extensions为每个入选文件选择解析后端,并补充并发限制、失败详情、空解析产物清理,以及导入失败后新预占空目标的清理。覆盖本地目录、内置 ZipParser 展开的目录 ZIP,以及 HTTPAccessor/WebImporter 物化的 HTML 页面目录。关闭
parser_api.enable或扩展名未命中时,仍走原生解析;不修改网页抓取流程。Human Involvement
Related Issue
Type of Change
兼容性说明:新增目录默认上限为 1000 个入选文件、10 层深度,超过时拒绝导入,可通过
parsers.directory调整。这些限制同样适用于原生解析,因此标记为行为兼容性变更;没有移除或重命名公开 API 参数。Changes Made
ParserRouter逐文件路由,保留过滤和目录结构;命中 Understanding 时提前拒绝no_split。meta.failed_files,保留真实错误原因和远端 ID。Testing
I have added tests that prove my fix is effective or that my feature works
New and existing unit tests pass locally with my changes
I have tested this on the following platforms:
目录过滤、阈值、共享并发、HTML 路由、Understanding 错误处理、原生解析回退、飞书、异步任务及 temp-upload 接口等 21 个测试文件:554 passed,4 个 Pydantic 既有弃用警告。
清理相关回归覆盖:空产物不创建合并目标、全失败时清理聚合临时目录、已有目标不标记清理、非空目标不删除,以及
file_id任务返回错误或抛出异常时按标记清理。补充 6 个组合用例验证错误原因、远端 ID 和清理行为。当前 PR 相对主干的 22 个 Python 文件执行
ruff check:通过。同一批 22 个 Python 文件执行
ruff format --check:通过;合并核对还覆盖了双方涉及的全部 27 个 Python 文件。相对两个合并父版执行
git diff --check:通过;已核对双方改动保留情况。Checklist
Screenshots (if applicable)
Additional Notes