feat: support loading models from memory#153
Conversation
Add ModelSource (Path | Memory) and thread it through AdapterBuilder, all model/adapter/predictor builders, and the OAROCR/OARStructure builders. Every model-accepting build() now takes impl Into<ModelSource>, so existing path-based call sites are unchanged while raw ONNX bytes (include_bytes!, decrypted buffers) load via ort commit_from_memory. The character dictionary can likewise be supplied as an in-memory string via character_dict_content(). In-memory sources skip auto-download resolution.
There was a problem hiding this comment.
Code Review
This pull request introduces a ModelSource abstraction to support loading ONNX models either from a filesystem path or directly from in-memory bytes (e.g., via include_bytes!). Consequently, all model-accepting builders, adapters, predictors, and pipeline builders (such as OAROCRBuilder and OARStructureBuilder) have been updated to accept impl Into instead of rigid file paths. Additionally, support for in-memory character dictionaries has been added via the character_dict_content builder method, and the documentation has been updated to demonstrate these new in-memory loading capabilities. There are no review comments, so no further feedback is provided.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c67a7c5d87
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ModelSource::Path(path) => builder.commit_from_file(path).map_err(|e| { | ||
| OCRError::model_load_error(path, SESSION_CREATION_FAILURE, suggestion, Some(e)) | ||
| })?, | ||
| ModelSource::Memory(bytes) => builder.commit_from_memory(bytes).map_err(|e| { |
There was a problem hiding this comment.
Keep memory buffers alive for zero-copy ORT configs
When a caller loads ModelSource::Memory together with ORT config entries such as session.use_ort_model_bytes_directly or session.use_ort_model_bytes_for_initializers, ONNX Runtime can keep pointers into the supplied buffer instead of copying it; the ort crate models that case with an InMemorySession lifetime. Here the Arc<[u8]> is local to load_session_with and OrtInfer stores only a display path, so the buffer can be dropped immediately after session creation, leaving ORT with dangling model data. Please either keep the memory source alive for the session lifetime or reject those zero-copy entries for in-memory sources.
Useful? React with 👍 / 👎.
| model_source | ||
| .as_path() | ||
| .and_then(TableStructureModelFamily::detect_from_path) | ||
| .unwrap_or(TableStructureModelFamily::Wired) |
There was a problem hiding this comment.
Require the table family for in-memory table models
For in-memory SLANet/SLANet_plus table-structure bytes where the caller does not set model_name, as_path() is always None, so this now silently falls through to the wired family. That selects the wired adapter/default shape instead of the wireless/SLANet pipeline, corrupting predictions rather than telling the caller the model family cannot be inferred from bytes. Please return a configuration error for memory sources without model_name or require an explicit family before building.
Useful? React with 👍 / 👎.
#154) - Add docs/FAQ.md (Windows MSVC linker requirements from #105, GPU vs CPU expectations for PP-OCRv6 from #151) and link it from the README. - Mention in-memory model loading in the README and crate docs, and note in docs/models.md that in-memory sources bypass auto-download path resolution. - Bump workspace version to 0.8.0: #153 changed the AdapterBuilder::build signature, which is a breaking API change.
Summary
Implements #37: models can now be loaded from memory (e.g.
include_bytes!for single-binary deployments, or buffers decrypted at runtime) instead of only from file paths.ModelSource(Path(PathBuf) | Memory(Arc<[u8]>)) inoar-ocr-corewithFromconversions for paths, strings,Vec<u8>,&'static [u8]/arrays, andArc<[u8]>.AdapterBuilder::build, every model builder (DBModelBuilder,CRNNModelBuilder, ...), every adapter builder, every task predictorbuild(), and theOAROCRBuilder/OARStructureBuildermodel setters now takeimpl Into<ModelSource>— existing path-based call sites compile unchanged.Memorysources go through ort'scommit_from_memory;Pathsources keep the exact previous behavior, including auto-download resolution (in-memory sources skip it).OAROCRBuilder::character_dict_content(...)(e.g.include_str!).model_name/model_variantsetters for in-memory sources.Usage:
Documented in
docs/usage.md("Loading Models from Memory"). Models with external-data sidecar files cannot be loaded from memory (ONNX Runtime limitation); PP-OCR models are single-file and unaffected.Testing
cargo fmt --check,cargo clippy --workspace --all-targets(no warnings),cargo test --workspace— 594 tests + doctests pass.ModelSourceconversions.Vec<u8>model bytes + in-memory dict — and verified byte-identical recognition output on a real image; also re-ran the path-basedocrexample as a regression check.Closes #37.
🤖 Generated with Claude Code