refactor(config): signature paddle 경로 미디어화 + 바이트 불변 골든

ocr_engine_version_for_sig 가 det/rec/dict 를 호출자(미디어별)로부터 받도록
인자화 — image 는 [ingest.image.ocr], pdf 는 [ingest.pdf.ocr]. v2 의 pdf↔image
paddle 비대칭 제거. engine_version_for_paths 신설(kebab-parse-image). 출력
문자열은 값 기반이라 v2 와 바이트 동일(불변식 #1). test seam + 골든 추가.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-04 12:44:27 +00:00
parent d5c69f6715
commit 3d45994693
4 changed files with 116 additions and 42 deletions

View File

@@ -34,7 +34,10 @@ pub mod paddle_onnx;
pub use caption::{apply_caption, caption_image};
pub use ocr::{OLLAMA_VISION_ENGINE, OcrEngine, OllamaVisionOcr, apply_ocr};
pub use paddle_onnx::{ModelPaths, OnnxPaddleOcr, PADDLE_ONNX_ENGINE, engine_version_for_config};
pub use paddle_onnx::{
ModelPaths, OnnxPaddleOcr, PADDLE_ONNX_ENGINE, engine_version_for_config,
engine_version_for_paths,
};
use anyhow::{Context, Result};
use kebab_core::{

View File

@@ -474,6 +474,26 @@ pub fn engine_version_for_config(config: &kebab_config::Config) -> Result<String
compute_engine_version(&ModelPaths::from_config(config))
}
/// v3: `engine_version` 을 명시적 (det,rec,dict) override 로부터 계산한다.
/// `ingest_config_signature` 의 미디어별 경로(image 는 `[ingest.image.ocr]`,
/// pdf 는 `[ingest.pdf.ocr]`)를 받아 쓰기 위함 — v2 의 "pdf 가 image paddle
/// 경로를 빌려쓰던" 비대칭 제거. `None` override 는 번들 모델로 fallback.
/// `engine_version_for_config` 과 동일하게 ~17 MB 를 읽으므로 호출자가
/// (det,rec,dict) triple 별로 memoize 해야 한다.
pub fn engine_version_for_paths(
det: Option<&str>,
rec: Option<&str>,
dict: Option<&str>,
) -> Result<String> {
let defaults = ModelPaths::from_default_dir();
let paths = ModelPaths {
det: det.map(PathBuf::from).unwrap_or(defaults.det),
rec: rec.map(PathBuf::from).unwrap_or(defaults.rec),
dict: dict.map(PathBuf::from).unwrap_or(defaults.dict),
};
compute_engine_version(&paths)
}
/// blake3 over det + rec + dict bytes → stable `engine_version`.
fn compute_engine_version(paths: &ModelPaths) -> Result<String> {
let mut hasher = blake3::Hasher::new();