Skip to content

feat: OCR 模型 v5 到 v6 平滑迁移 - #2681

Merged
ShadowLemoon merged 3 commits into
OneDragon-Anything:mainfrom
kawayiYokami:feat/ocr-v6-smooth-upgrade
Aug 11, 2026
Merged

feat: OCR 模型 v5 到 v6 平滑迁移#2681
ShadowLemoon merged 3 commits into
OneDragon-Anything:mainfrom
kawayiYokami:feat/ocr-v6-smooth-upgrade

Conversation

@kawayiYokami

@kawayiYokami kawayiYokami commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

为什么改

PR #2515 强制切 v6(默认改 v6、配置立刻改写、下载选项只留 v6),老用户有 v5 也会被强制切走,v6 没下好时 OCR 直接不可用。本改动实现平滑迁移:有 V5 先顶着用,V6 后台下载完成后下次启动再切。

改动要点

  • 正常模式下 init_ocr 按本地文件状态向 V6 收敛:有 V6 直接用并落盘配置;有 V5 没 V6 先用 V5 顶住、后台下载 V6 成功后落盘配置;都没有直接下载 V6
  • V6 下载成功后只落盘配置、不立刻切换(立刻切换需先清 V5 再初始化 V6,失败会丢可用模型),下次启动自动生效
  • 配置只在 V6 就绪后改写,下载失败时 V5 保持可用,系统不崩
  • 调试模式下不自动切换,保留 v5/v6 手动选择
  • 按规范 os.path.exists 改 Path.exists

关联

正常模式下 init_ocr 按本地文件状态向 V6 收敛:
- 有 V6 直接用并落盘配置
- 有 V5 没 V6 先用 V5 顶住 后台下载 V6 成功后自动切换
- 都没有直接下载 V6
配置只在 V6 就绪后改写 下载失败时 V5 保持可用
调试模式下不自动切换 保留手动选择
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9890513b-0c86-41fd-9e37-b903c9df9c51

📥 Commits

Reviewing files that changed from the base of the PR and between d781cd5 and 2834b64.

📒 Files selected for processing (2)
  • src/one_dragon/base/operation/one_dragon_context.py
  • src/zzz_od/context/zzz_context.py

📝 Walkthrough

变更

  • 根据本地模型文件状态调整 init_ocr 的 OCR 模型选择逻辑。
  • 在仅有 v5 模型时继续使用 v5,并后台下载 v6。
  • 在 v6 模型就绪后保存配置,并在下次启动时切换至 v6。
  • 在 v5、v6 均不存在时触发 v6 模型下载。
  • 在调试模式下保留 v5 和 v6 的手动选择。
  • 在下载失败或异常时保留当前模型配置。
  • 补充 OCR 模型选择和迁移行为文档。

Walkthrough

新增 OCR 模型文件完整性检查和 V5/V6 选择逻辑。正常模式优先使用已就绪的 V6。仅 V5 就绪时使用 V5,并后台下载 V6。下载成功后保存配置,失败时保留当前模型。

Changes

OCR 模型收敛

Layer / File(s) Summary
OCR 模型选择与初始化
src/one_dragon/base/operation/one_dragon_context.py, src/zzz_od/context/zzz_context.py
新增 _decide_ocr_model_name() 扩展点。ZContext 根据调试模式和 V5/V6 模型文件状态选择模型。OCR 初始化使用选择后的模型名称。
V6 后台下载与配置更新
src/zzz_od/context/zzz_context.py, docs/develop/one_dragon/initialization.md
仅 V5 可用时启动一次 V6 后台下载。下载成功后保存 V6 配置。下载失败或异常时保留当前模型。文档补充启动行为和配置规则。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: a-nony-mous

Sequence Diagram(s)

sequenceDiagram
  participant ZContext
  participant onnx_ocr_matcher
  participant OnnxOcrParam
  participant OCR配置
  ZContext->>onnx_ocr_matcher: 检查 V5/V6 模型文件
  onnx_ocr_matcher-->>ZContext: 返回模型就绪状态
  ZContext->>OnnxOcrParam: 传入选择后的模型名称
  ZContext->>onnx_ocr_matcher: 启动 V6 后台下载
  onnx_ocr_matcher-->>ZContext: 返回下载结果
  ZContext->>OCR配置: 下载成功后保存 V6 配置
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 标题准确概括了 OCR 模型从 v5 到 v6 的平滑迁移,且与主要代码变更一致。
Description check ✅ Passed 描述说明了 OCR 模型迁移的背景、主要改动、失败处理和关联测试,与变更内容相关。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/one_dragon/base/operation/one_dragon_context.py (1)

497-516: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

在 V6 初始化成功前保留当前 OCR 实例。

后台线程在 Line 581 调用 init_ocr()。该方法会在 Line 497-510 清理当前 V5 实例并替换服务引用,然后才在 Line 513-516 初始化候选 V6。

如果 init_model() 失败,异常只会被下载线程记录。旧 V5 已不可用,OcrService 已指向未初始化的 V6 实例。下载成功不保证 ONNX session 初始化成功。

请先初始化候选 OCR。初始化成功后,再通过受同步保护的切换操作更新 self.ocrself.ocr_service.ocr_matchercv_service.ocr,最后清理旧实例。后台回调中的 ONNX 初始化必须通过 gpu_executor.submit 执行。

As per coding guidelines, “GPU/ONNX session 的异步调用必须通过 gpu_executor.submit,不要并发直接调用多个 session”。

Also applies to: 578-581

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon/base/operation/one_dragon_context.py` around lines 497 - 516,
调整 init_ocr 及其后台回调流程:先创建并初始化候选 OnnxOcrMatcher,且所有 GPU/ONNX 初始化必须通过
gpu_executor.submit 执行;仅在 init_model 成功后,通过受同步保护的切换操作更新
self.ocr、self.ocr_service.ocr_matcher 和 cv_service.ocr,最后再清理旧 OCR
实例,初始化失败时保留现有实例及服务引用。

Source: Coding guidelines

🧹 Nitpick comments (1)
src/one_dragon/base/operation/one_dragon_context.py (1)

553-553: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

使用 pathlib 检查模型文件。

此处新增了 os.path.exists()。本文件已经使用 Path。请改为 Path(file_path).exists(),并删除新增的 os 导入。

建议修改
-import os
-
-        return all(os.path.exists(f) for f in get_final_file_list(ocr_model_name))
+        return all(Path(file_path).exists() for file_path in get_final_file_list(ocr_model_name))

As per coding guidelines, “路径操作使用 pathlib”。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon/base/operation/one_dragon_context.py` at line 553, 在检查 OCR
模型文件的逻辑中,将 os.path.exists 调用替换为 Path(file_path).exists(),并移除新增但不再使用的 os 导入;保留
get_final_file_list 和 all 的现有行为。

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/one_dragon/base/operation/one_dragon_context.py`:
- Around line 527-589: 补充 OCR 迁移状态的单元测试和对应开发文档,覆盖 _decide_ocr_model_name 的调试模式、仅
V6 就绪、仅 V5 就绪及两者缺失场景,并覆盖 _download_ocr_v6_in_background 的下载失败、异常和成功后切换场景。验证 V6
下载完成后调用 init_ocr 失败时,仍能保留可用的 V5 OCR 配置,不因切换失败破坏现有能力;同步记录迁移行为与验证结果到开发文档。

---

Outside diff comments:
In `@src/one_dragon/base/operation/one_dragon_context.py`:
- Around line 497-516: 调整 init_ocr 及其后台回调流程:先创建并初始化候选 OnnxOcrMatcher,且所有
GPU/ONNX 初始化必须通过 gpu_executor.submit 执行;仅在 init_model 成功后,通过受同步保护的切换操作更新
self.ocr、self.ocr_service.ocr_matcher 和 cv_service.ocr,最后再清理旧 OCR
实例,初始化失败时保留现有实例及服务引用。

---

Nitpick comments:
In `@src/one_dragon/base/operation/one_dragon_context.py`:
- Line 553: 在检查 OCR 模型文件的逻辑中,将 os.path.exists 调用替换为
Path(file_path).exists(),并移除新增但不再使用的 os 导入;保留 get_final_file_list 和 all 的现有行为。
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fcff4d74-e0f9-4c9c-bd7e-e9fa457107b3

📥 Commits

Reviewing files that changed from the base of the PR and between 920ee93 and 6f126ef.

📒 Files selected for processing (1)
  • src/one_dragon/base/operation/one_dragon_context.py

Comment thread src/one_dragon/base/operation/one_dragon_context.py Outdated
编程兔 review 指出: 立刻切换需先清理 V5 再初始化 V6, V6 初始化失败时
当前可用 V5 也丢了. 改为下载成功后只落盘配置, 下次启动 init_ocr 自然
用 V6, 本次会话始终稳定. 同时按规范将 os.path.exists 改为 Path.exists,
补充 OCR 模型选择行为文档.
@kawayiYokami

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor
⚠️ Action not completed

Already reviewed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/one_dragon/base/operation/one_dragon_context.py (1)

494-503: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

先完成候选模型初始化,再替换当前 OCR。

Line 497-499 会先清理当前 self.ocrLine 501-510 又在 init_model() 成功前更新 self.ocrself.ocr_servicecv_service。如果 V6 文件存在但 ONNX session 初始化失败,init() 只会记录异常,原本可用的 V5 已无法恢复。

请先初始化候选 matcher。只有初始化成功后,才更新服务引用并清理旧实例。V6 初始化失败且 V5 文件就绪时,应回退到 V5。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon/base/operation/one_dragon_context.py` around lines 494 - 503,
调整 OCR 初始化流程:在替换当前 self.ocr、self.ocr_service 和 cv_service 前,先完成候选 OnnxOcrMatcher
的初始化并确认成功。仅在候选模型可用后清理旧 OCR 实例并更新服务引用;当 V6 初始化失败且 V5 文件就绪时,回退并使用 V5
模型,避免破坏现有可用实例。
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/one_dragon/base/operation/one_dragon_context.py`:
- Line 552: 更新 _is_ocr_model_ready() 的 OCR 模型就绪检查,使用 Path.is_file() 排除同名目录;同时按
OCR 模型实际必需的文件范围构造检查列表,确保必需的 _dict.txt 被纳入校验,不要仅依赖 get_final_file_list()
的条件性收集结果。

---

Outside diff comments:
In `@src/one_dragon/base/operation/one_dragon_context.py`:
- Around line 494-503: 调整 OCR 初始化流程:在替换当前 self.ocr、self.ocr_service 和 cv_service
前,先完成候选 OnnxOcrMatcher 的初始化并确认成功。仅在候选模型可用后清理旧 OCR 实例并更新服务引用;当 V6 初始化失败且 V5
文件就绪时,回退并使用 V5 模型,避免破坏现有可用实例。
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c9b4fa81-1189-4868-8e5b-e5074a62bda6

📥 Commits

Reviewing files that changed from the base of the PR and between 6f126ef and d781cd5.

📒 Files selected for processing (2)
  • docs/develop/one_dragon/initialization.md
  • src/one_dragon/base/operation/one_dragon_context.py

"""
判断某个 OCR 模型的文件是否已经全部就绪
"""
return all(Path(f).exists() for f in get_final_file_list(ocr_model_name))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -C 8 \
  'get_final_file_list|get_ocr_model_dict_name|dict\.txt|character_dict|def init_model' \
  src/one_dragon/base/matcher/ocr || true

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 10366


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== one_dragon_context around _is_ocr_model_ready =="
fd -a 'one_dragon_context.py' . | while read -r f; do
  echo "--- $f"
  wc -l "$f"
  sed -n '520,570p' "$f"
done

echo "== onnx_ocr_matcher get_final_file_list and model init =="
sed -n '54,72p' src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
sed -n '74,180p' src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
sed -n '200,290p' src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py

echo "== usages of _is_ocr_model_ready / get_final_file_list =="
rg -n '_is_ocr_model_ready|get_final_file_list\(' src/one_dragon || true

echo "== common downloader check_existed semantics =="
fd -a '.*downloader.*\.py' src/one_dragon | while read -r f; do
  echo "--- $f"
  rg -n -C 5 'check_existed|check_existed_list|exists|is_file|skip_if_existed' "$f" || true
done

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 16743


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== dict usage around model loading =="
fd -i '*onnx*ocr*.py' src/one_dragon base | while read -r f; do
  echo "--- $f"
  rg -n -C 6 '_dict|dict_name|character_dict|PaddleOCR|ONNXPaddleOcr|rec_config|det|rec|cls' "$f" || true
done

echo "== download URLs / expected files =="
rg -n -C 4 'PPOCRV6_MODEL_NAME|DEFAULT_OCR_MODEL_NAME|ocr_model_dir|get_ocr_download_url|_dict\.txt|simfang\.ttf' src tests .github docs README* ipp* 2>/dev/null || true

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 564


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== dict/model config usages =="
rg -n -C 6 '_dict|dict_name|character_dict|PaddleOCR|ONNXPaddleOcr|rec_config|det_config|cls_config|skip_crnn' src/one_dragon || true

echo "== OCR model names and file expectations =="
rg -n -C 4 'PPOCRV6_MODEL_NAME|DEFAULT_OCR_MODEL_NAME|ocr_model_dir|get_ocr_download_url|_dict\.txt|simfang\.ttf|det\.onnx|rec\.onnx|cls\.onnx' src/one_dragon tests .github README* docs ipp* 2>/dev/null || true

echo "== common path semantics probe =="
tmp="$(mktemp -d)"
python3 - <<'PY' "$tmp" | sed 's#$tmp#<tmp>`#g`'
import sys, pathlib, os
tmp = pathlib.Path(sys.argv[1])
(p := tmp/'pathy_dir').mkdir(parents=True)
paths = [tmp/'missing', p, tmp/'existing.txt']
for f in paths:
    f.touch() if f.name == 'existing.txt' else None
    print(f, 'exists=', f.exists(), 'is_file=', f.is_file())
PY
rm -rf "$tmp"

Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon

Length of output: 45638


更换 OCR 模型路径的存在性检查为普通文件检查。

_is_ocr_model_ready() 使用 Path.exists(),同名目录也会返回 True,会在下载或解压残留同名目录时错误选择 V6;get_final_file_list() 只在发现 _dict.txt 时才将其加入就绪列表,若字典文件必需则当前逻辑可能漏检。应改用 Path.is_file(),并按实际必需文件范围构造检查列表。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/one_dragon/base/operation/one_dragon_context.py` at line 552, 更新
_is_ocr_model_ready() 的 OCR 模型就绪检查,使用 Path.is_file() 排除同名目录;同时按 OCR
模型实际必需的文件范围构造检查列表,确保必需的 _dict.txt 被纳入校验,不要仅依赖 get_final_file_list() 的条件性收集结果。

@ShadowLemoon ShadowLemoon added the test-branch 合入 test 分支 label Aug 8, 2026
@ShadowLemoon
ShadowLemoon merged commit 84ed14c into OneDragon-Anything:main Aug 11, 2026
7 of 8 checks passed
@github-actions github-actions Bot locked as resolved and limited conversation to collaborators Aug 14, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

test-branch 合入 test 分支

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants