scripts/ 是整套“PDF -> OCR -> 翻译 -> 保留排版渲染”的脚本工程目录。
现在顶层按职责分成五层:
runtime/运行时编排层,只放 pipeline。services/OCR、MinerU、翻译、渲染等具体实现层。foundation/配置、共享工具和提示词资源。entrypoints/人工执行入口。devtools/实验、迁移、示例、测试探针、诊断脚本。
其中 services/ 内部现在又明确分成两类:
- provider / translation / rendering 这类能力模块
services/pipeline_shared/这类跨阶段共享协议模块
核心流程可以概括成:
PDF -> OCR provider -> document_schema -> services/translation -> services/rendering -> PDF
更具体一点:
normalize.stage.v1OCR provider 原始结果进入document_schema,产出ocr/normalized/document.v1.json和document.v1.report.jsontranslate.stage.v1翻译链只读取document.v1.json,抽取正文白名单 block,补 continuation / orchestration 元数据,输出translated/render.stage.v1渲染链只读取翻译产物和源 PDF,输出rendered/*.pdfbook.stage.v1顶层整书流程,只负责编排normalize -> translate -> render,不再让下游直接猜 provider 原始结构
现在的正式块级契约是:
geometrycontentlayout_rolesemantic_rolestructure_rolepolicyprovenance
说明:
type/sub_type/bbox/text/lines/segments仍保留,但已经降级为兼容字段- translation / rendering 主线不应该再基于 raw OCR 字段或
derived/sub_type重新猜正文 - 是否进入翻译,以
policy.translate为唯一正式入口 - translation payload 的正式消费口径也已固定为 strict top-level contract,不再依赖
metadata镜像
日常使用优先走这些入口:
scripts/entrypoints/run_book.py当前最上层完整入口。通过book.stage.v1串起normalize -> translate -> render,适合人工本地跑整条主链路。scripts/entrypoints/run_provider_case.py本地一条命令跑“provider -> normalize -> translate -> render”的通用入口名。底层由 provider 分发层决定具体 OCR 实现,入口名不暴露 provider。scripts/entrypoints/run_document_flow.py已经有 OCR JSON 和 PDF 时,优先用这个中性入口名跑完整流程。scripts/entrypoints/run_normalize_ocr.py顶层 normalize worker。把 raw OCR JSON 收口成document.v1.json。scripts/entrypoints/run_provider_ocr.py本地 OCR-only 通用入口名。只跑 provider -> unpack -> normalize。scripts/entrypoints/run_translate_only.py顶层 translate worker。只接受已经标准化的document.v1.json。scripts/entrypoints/run_render_only.py顶层 render worker。只接受翻译产物和 PDF。scripts/entrypoints/translate_book.py只翻译,不渲染。scripts/entrypoints/build_book.py只渲染,不重新翻译。scripts/entrypoints/build_page.py单页渲染调试入口。scripts/entrypoints/translate_page.py单页翻译调试入口。scripts/entrypoints/validate_document_schema.py契约排错入口。只用于检查document.v1或 adapter 行为,不是日常整链路入口。scripts/devtools/tests/document_schema/regression_check.py长期回归工具,不是主流程入口。
不要把测试脚本当主入口。正常验证整条链路时,优先跑:
run_book.py --spec <job_root>/specs/book.spec.json- 或 Rust API 提交 job,让 Rust 通过 spec 驱动三个 worker
如果要改翻译链路,推荐阅读顺序是:
services/translation/README.mdservices/translation/llm/README.md- 再按需要进入
services/translation/llm/providers/或services/translation/llm/shared/orchestration/
如果后续要接新的 OCR provider,先按这个顺序走,不要直接改翻译/渲染主线:
- 先看
scripts/services/ocr_provider/README.md先把 provider API 层边界、状态、原始产物职责定义清楚。 - 再看
scripts/services/document_schema/README.md明确字段应该落到geometry/content/layout_role/semantic_role/structure_role/policy/provenance的哪一层。 - 准备最小 raw fixture
放到
scripts/devtools/tests/document_schema/fixtures/。 - 新增 provider 实现和 adapter
通过
scripts/services/document_schema/adapters.py接进统一 schema。 - 把 fixture 登记到
scripts/devtools/tests/document_schema/fixtures/registry.py不要手改主线去兼容 provider 原始 JSON。 - 跑
scripts/devtools/tests/document_schema/regression_check.py至少确认 detector、adapt、validation、extractor smoke 全都通过。
services/mineruMinerU 接入、下载、解包、job 组织。services/pipeline_sharedprovider / translate / render 共用的阶段协议、summary 和 JSON IO。services/translationOCR payload 到翻译 JSON。services/rendering翻译 JSON 到 PDF。runtime/pipeline翻译和渲染的总编排层。services/README.md具体能力实现层总说明。foundation/config路径、字体、版式和运行时默认配置。foundation/shared输入解析、job 目录、环境变量、提示词加载等共享能力。foundation/prompts可编辑提示词模板。devtools/experiments实验性流程,不属于稳定主链路。devtools/tests测试探针和排版实验。devtools/tools示例脚本、迁移工具和诊断脚本。
任务输出统一落到标准 job root 下。Rust API 默认是:
DATA_ROOT/jobs/<job-id>/sourceDATA_ROOT/jobs/<job-id>/ocrDATA_ROOT/jobs/<job-id>/translatedDATA_ROOT/jobs/<job-id>/renderedDATA_ROOT/jobs/<job-id>/artifactsDATA_ROOT/jobs/<job-id>/logs
其中:
ocr/unpacked/或 provider raw 目录保留 OCR provider 原始产物;MinerU 常见为layout.json,Paddle 常见为paddle_result.json/paddle_rawocr/normalized/document.v1.json是当前翻译/渲染主链路使用的统一 OCR 输入ocr/normalized/document.v1.report.json记录 adapter/provider 探测、defaults 默认补齐和 schema 校验摘要translated/translation-manifest.json与其引用的逐页 payload 是翻译阶段正式产物rendered/*.pdf是最终输出 PDFrendered/typst/保留 Typst 中间产物,便于查错和回溯artifacts/放 summary、bundle 索引等下载产物logs/放阶段日志和结构化事件输出
当前约定:
- 主链路优先消费
document.v1.json document.v1.json的正式消费口径是geometry/content/layout_role/semantic_role/structure_role/policy/provenance- 如果入口给的是 raw
layout.json,会先做一次显式规范化,再进入翻译主线 - raw MinerU 结构保留给 adapter、调试和回溯,不再作为主链路的隐式数据契约
- 如果只是做排错、状态展示或 API 输出摘要,优先消费
document.v1.report.json - Python 侧统一通过
services/document_schema/reporting.py读取 report 和生成 normalization summary specs/保存阶段 spec JSON,当前已覆盖:normalize.spec.json->normalize.stage.v1translate.spec.json->translate.stage.v1render.spec.json->render.stage.v1provider.spec.json->provider.stage.v1book.spec.json->book.stage.v1
当前 Rust API 到 Python worker 的稳定协议,已经固定为:
python -u <entrypoint> --spec DATA_ROOT/jobs/<job-id>/specs/<stage>.spec.json
约定如下:
- spec 只保存阶段输入、参数和 job 引用,不再把 Python 内部实现细节暴露给 Rust
job.job_root是路径推导锚点;各阶段内部通过job_dirs.py派生source/ocr/translated/rendered/artifacts/logs- 密钥不明文写入 spec
- 翻译 key 通过
credential_ref=env:RETAIN_TRANSLATION_API_KEY - 如果 provider 是
mineru,对应 token 通过credential_ref=env:RETAIN_MINERU_API_TOKEN - 运行时由 Rust 注入环境变量,Python 通过
stage_specs.resolve_credential_ref(...)读取
- 翻译 key 通过
- Rust 主工作流和本地 book/translate 入口都已切到 spec-only
run_normalize_ocr.pyrun_provider_ocr.pyrun_translate_only.pyrun_render_only.pyrun_translate_from_ocr.pyrun_document_flow.pyrun_provider_case.pyrun_book.pytranslate_book.py
本地开发入口当前也已统一到 stage spec 主路径:
entrypoints/run_provider_case.py-> 当前 provider-backed full workflow 的本地通用入口名entrypoints/run_document_flow.py-> 当前 normalized-document full flow 的本地通用入口名entrypoints/run_provider_ocr.py-> 当前 OCR-only provider flow 的本地通用入口名services/document_schema/normalize_pipeline.py->normalize.stage.v1services/translation/translate_only_pipeline.py->translate.stage.v1services/rendering/workflow/render_only.py->render.stage.v1services/translation/from_ocr_pipeline.py->book.stage.v1entrypoints/run_book.py->book.stage.v1
也就是说,当前“最上层整个流程”的真实执行口径是:
- 本地:
run_book.py --spec .../book.spec.json - Rust API:创建 job,由 Rust 生成
specs/*.spec.json并依次启动 worker - 测试脚本:只做回归,不代表主执行路径
当前 Python 依赖已经收敛到仓库根目录的 pyproject.toml。
不要直接手改这些 requirements 文件:
docker/requirements-app.txtdocker/requirements-test.txtdesktop/requirements-desktop-posix.txtdesktop/requirements-desktop-windows.txtdesktop/requirements-desktop-macos.txt
修改依赖后统一执行:
python backend/scripts/devtools/sync_python_requirements.py --repo-root .只检查是否漂移:
python backend/scripts/devtools/sync_python_requirements.py --repo-root . --check兼容说明:
- 旧任务目录如果还是
originPDF/jsonPDF/transPDF/typstPDF,当前后端会直接拒绝详情/下载接口,请重新跑任务生成标准 schema - 旧的逐页 translation JSON 直扫模式已经退出主线;render-only 必须提供
translation-manifest.json
- PIPELINE_DIRECTORY_MAP.md
- foundation/config/README.md
- foundation/shared/README.md
- runtime/pipeline/README.md
- services/README.md
- services/ocr_provider/README.md
- services/translation/README.md
- services/translation/orchestration/README.md
- services/translation/continuation/README.md
- services/translation/policy/README.md
- services/rendering/README.md
- services/mineru/README.md
services/translation不直接操作 PDFservices/rendering不直接决定翻译策略runtime/pipeline负责编排,不下沉到实现细节foundation/不承载具体业务流程entrypoints/只做入口,不承载核心实现devtools/不能反向成为主链路依赖
日常改动建议至少跑这两条:
python3 backend/rust_api/scripts/check_architecture.pypython3 backend/scripts/devtools/check_pipeline_architecture.py
第二条负责卡住 Python 主链最容易回退的边界:
runtime/pipeline重新直接 importservices.ocr_provider/services.mineruruntime/pipeline重新理解 provider raw token,例如layoutParsingResultsservices/translation/services/rendering重新碰 provider raw adapterentrypoints/*绕过稳定入口,直接连深层实现services/ocr_provider/__init__.py丢掉显式公共导出面services/ocr_provider/provider_pipeline.py丢掉稳定 compat symbol 或不再承担主链 handoffservices/ocr_provider/paddle_*反向依赖runtime/pipeline/services/translation/services/rendering