Skip to content

Feat/onnx export#7

Open
singjc wants to merge 10 commits into
developfrom
feat/onnx_export
Open

Feat/onnx export#7
singjc wants to merge 10 commits into
developfrom
feat/onnx_export

Conversation

@singjc

@singjc singjc commented Jul 5, 2026

Copy link
Copy Markdown
Owner

This pull request adds ONNX export support to the redeem CLI and underlying libraries, enabling users to export supported property models (full models or decoder-only) to ONNX format. It introduces new dependencies, a CLI subcommand, and comprehensive documentation and tests around this feature.

The most important changes are:

ONNX Export Feature

  • Added a new to-onnx subcommand to the redeem properties CLI, allowing users to export supported property models to ONNX, with options for full-model or decoder/head-only export, device selection, opset version, and external data handling. (redeem-cli/src/main.rs, redeem-cli/src/properties/onnx.rs, redeem-cli/src/properties/mod.rs) [1] [2] [3] [4]
  • Implemented the ONNX export logic in redeem-properties (behind the onnx-export feature flag), supporting rt_cnn_tf and ccs_cnn_tf full-model export, and decoder export for other architectures. (redeem-properties/src/lib.rs, redeem-properties/Cargo.toml, redeem-cli/Cargo.toml) [1] [2] [3]

Dependency and Feature Management

  • Updated dependencies to use patched versions of candle-core, candle-nn, candle-transformers, and added candle-onnx-export from a fork with ONNX export support. Feature flags and optional dependencies are set up accordingly in both redeem-properties and redeem-cli. (Cargo.toml, redeem-properties/Cargo.toml, redeem-cli/Cargo.toml) [1] [2] [3] [4]

Documentation and Testing

  • Added documentation to redeem-cli/README.md describing the new ONNX export functionality, with usage examples for both full-model and decoder export.
  • Added CLI smoke tests to verify the presence and help output of the new to-onnx subcommand and its arguments. (redeem-cli/tests/cli_smoke.rs)

These changes provide a robust and user-friendly way to export property models to ONNX, facilitating interoperability and deployment in other environments.

Summary by CodeRabbit

  • New Features
    • Added a properties to-onnx CLI command supporting both full-model and decoder/head-only ONNX exports.
    • Enabled ONNX export support for additional model types, with explicit errors for models not yet fully supported.
    • Extended CUDA option wiring so GPU-related export paths are available end-to-end.
  • Documentation
    • Added a “Properties — ONNX Export” section with command syntax, flags, and examples.
  • Tests
    • Added CLI smoke tests covering help output and missing-arguments failure cases.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds ONNX export support across redeem-properties and redeem-cli. Candle crates move to a git fork with an onnx-export feature, property models gain export hooks, and the CLI adds a properties to-onnx command with docs and smoke tests.

Changes

ONNX Export Feature

Layer / File(s) Summary
Candle dependency and feature wiring
Cargo.toml, redeem-cli/Cargo.toml, redeem-properties/Cargo.toml, redeem-properties/src/lib.rs, redeem-openms-ffi/Cargo.toml, redeem-properties-py/Cargo.toml
Candle dependencies are redirected to a git fork, the onnx-export feature and optional candle-onnx-export dependency are added, CUDA feature propagation is expanded, and the ONNX export module is feature-gated.
ONNX graph construction
redeem-properties/src/onnx_export.rs
Adds RT/CCS ONNX graph entrypoints, input helpers, transformer and CNN blocks, decoder-head export, tensor plumbing, and ONNX-safe shape/name utilities.
Per-model ToOnnx implementations
redeem-properties/src/models/ccs_cnn_tf_model.rs, redeem-properties/src/models/rt_cnn_transformer_model.rs, redeem-properties/src/models/ccs_cnn_lstm_model.rs, redeem-properties/src/models/ms2_bert_model.rs, redeem-properties/src/models/rt_cnn_lstm_model.rs
Supported CNN-transformer models delegate to the exporter, while unsupported model families return explicit ONNX export errors.
redeem-cli to-onnx subcommand
redeem-cli/src/main.rs, redeem-cli/src/properties/mod.rs, redeem-cli/src/properties/onnx.rs, redeem-cli/README.md, redeem-cli/tests/cli_smoke.rs
Adds the properties to-onnx command path, argument parsing, export dispatch, help text, usage examples, and smoke tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CliUser
  participant MainRs
  participant OnnxRs
  participant OnnxExportRs
  CliUser->>MainRs: properties to-onnx --model ... --output ...
  MainRs->>OnnxRs: run_to_onnx(matches)
  OnnxRs->>OnnxExportRs: load_and_export_decoder or load_and_export_full
  OnnxExportRs->>OnnxRs: exported Value/OnnxGraph
  OnnxRs->>CliUser: save ONNX file, print success
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title is related to the change, but it is very generic and does not clearly describe the new CLI and library ONNX export work. Use a more specific title, such as "Add ONNX export support for redeem properties".
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/onnx_export

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

Choose a reason for hiding this comment

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

Actionable comments posted: 3

♻️ Duplicate comments (1)
redeem-cli/src/properties/onnx.rs (1)

48-51: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win

Root cause of the debug-mode panic lives here.

See the comment on redeem-cli/src/main.rs (to-onnx subcommand arg list) — "external_data_threshold" is never registered as a CLI argument, so this get_one call panics in debug builds on every invocation regardless of --external-data.

🤖 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 `@redeem-cli/src/properties/onnx.rs` around lines 48 - 51, The panic comes from
looking up an unregistered CLI arg in `onnx::properties`; update the
`get_one::<usize>("external_data_threshold")` access so it only happens after
the `to-onnx` command registers that argument in `main.rs`, or remove the lookup
if the option is no longer intended. Make the `onnx.rs` logic consistent with
the CLI definition by using the same symbol name for registration and retrieval,
and ensure the default path cannot call `get_one` for an absent arg.
🧹 Nitpick comments (4)
redeem-cli/src/main.rs (1)

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

Alias pattern arm is unreachable.

Some(("to_onnx", onnx_matches)) will never match: clap reports the canonical subcommand name ("to-onnx") in matches.subcommand() even when invoked via the to_onnx alias. The extra arm is dead code but harmless.

♻️ Simplify to just the canonical name
-        Some(("to-onnx", onnx_matches)) | Some(("to_onnx", onnx_matches)) => {
+        Some(("to-onnx", onnx_matches)) => {
🤖 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 `@redeem-cli/src/main.rs` around lines 376 - 384, The subcommand match in main
is carrying a dead alias arm because clap returns only the canonical name from
matches.subcommand(). Update the match around onnx::run_to_onnx to handle just
the canonical "to-onnx" case and remove the unreachable "to_onnx" pattern,
keeping the error handling and exit behavior unchanged.
redeem-cli/src/properties/onnx.rs (1)

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

Fallback value for component never matches the CLI default.

unwrap_or("decoder") here is dead code today since main.rs sets .default_value("full") for this arg, so get_one always returns Some. If that default is ever changed or the flag becomes optional without a default, behavior would silently diverge from intent. Consider aligning the fallback with the actual default for clarity.

🤖 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 `@redeem-cli/src/properties/onnx.rs` around lines 36 - 39, The fallback in the
component lookup is out of sync with the CLI default, and the dead-code path can
mislead future changes. Update the `component` handling in `onnx.rs` so the
fallback matches the actual default configured in `main.rs` for the same
argument, and keep the `matches.get_one::<String>("component")` logic consistent
with that source of truth.
redeem-cli/README.md (1)

111-130: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Docs omit --device and --opset flags.

Both flags exist on the to-onnx subcommand (main.rs) but aren't documented in the usage template or argument table here.

📝 Suggested doc addition
 redeem properties to-onnx \
     --model <MODEL_PATH> \
     --model_arch <MODEL_ARCH> \
     --output <OUTPUT_ONNX> \
     [--component full|decoder] \
     [--constants <CONSTANTS_YAML>] \
+    [--device cpu|cuda|cuda:<index>] \
+    [--opset <OPSET_VERSION>] \
     [--external-data]
 | `--constants` | Optional model constants YAML |
+| `--device` | Device used to load model tensors (`cpu`, or `cuda`/`cuda:<index>` with the cuda feature) |
+| `--opset` | ONNX opset version (default 18) |
 | `--external-data` | Store initializer bytes in a sidecar `.onnx.data` 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 `@redeem-cli/README.md` around lines 111 - 130, The README usage and argument
table for the redeem properties to-onnx command are missing the existing
--device and --opset options from the to-onnx subcommand. Update the usage block
and options table in this section to document both flags, including their
purpose and placement alongside the other export arguments, using the to-onnx
command and main.rs subcommand definitions as the source of truth.
Cargo.toml (1)

14-16: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Pin the Candle fork to an immutable revision.

These [patch.crates-io] entries track a mutable branch, so the dependency source can change without a manifest diff. Pin the fork with rev = "<commit-sha>" and apply the same pin to the member manifests that reference this fork directly.

Suggested shape
-candle-core = { git = "https://github.com/singjc/candle.git", branch = "add/candle-onnx-export" }
+candle-core = { git = "https://github.com/singjc/candle.git", rev = "<pinned-commit-sha>" }
🤖 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 `@Cargo.toml` around lines 14 - 16, The Candle fork is currently referenced by
a mutable branch in the [patch.crates-io] entries, so pin the fork to an
immutable commit revision instead. Update the candle-core, candle-nn, and
candle-transformers entries in Cargo.toml to use a fixed rev, and make the same
change in any member manifests that reference these crates directly so all uses
of the fork resolve to the same commit.
🤖 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 `@redeem-cli/src/main.rs`:
- Around line 144-221: The to-onnx command is missing the
external_data_threshold argument that redeem-cli/src/properties/onnx.rs expects
via matches.get_one::<usize>("external_data_threshold"). Add that flag to the
Command::new("to-onnx") builder in redeem-cli/src/main.rs with an appropriate
default/value parser, or change the ONNX export code to use
DEFAULT_EXTERNAL_DATA_THRESHOLD directly so the undeclared-id assertion is
avoided.

In `@redeem-properties/src/onnx_export.rs`:
- Around line 271-274: The hidden-dimension validation in the ONNX export path
is tautological and never rejects invalid widths. Update the check in the
mod-embedding export logic around the expected dimension calculation to
explicitly validate that mod_hidden_dim is greater than k and that the resulting
transformed weight/output width matches the intended graph shape. Keep the
existing InvalidGraph error path in this validation branch so invalid
configurations are caught before graph construction.
- Around line 139-141: The exported transformer shape is inconsistent because
export_transformer uses a dynamic seq in the TF input while the positional
encoding path is fixed to TF_MAX_LEN, which can cause shape mismatches for
longer inputs. Update export_transformer and the related add_*_tf_input setup so
the exported sequence length is bounded to TF_MAX_LEN, either by making the
exported seq fixed to 100 or by explicitly enforcing/documenting truncation
before export, and keep the positional encoding and input tensor dimensions
aligned.

---

Duplicate comments:
In `@redeem-cli/src/properties/onnx.rs`:
- Around line 48-51: The panic comes from looking up an unregistered CLI arg in
`onnx::properties`; update the `get_one::<usize>("external_data_threshold")`
access so it only happens after the `to-onnx` command registers that argument in
`main.rs`, or remove the lookup if the option is no longer intended. Make the
`onnx.rs` logic consistent with the CLI definition by using the same symbol name
for registration and retrieval, and ensure the default path cannot call
`get_one` for an absent arg.

---

Nitpick comments:
In `@Cargo.toml`:
- Around line 14-16: The Candle fork is currently referenced by a mutable branch
in the [patch.crates-io] entries, so pin the fork to an immutable commit
revision instead. Update the candle-core, candle-nn, and candle-transformers
entries in Cargo.toml to use a fixed rev, and make the same change in any member
manifests that reference these crates directly so all uses of the fork resolve
to the same commit.

In `@redeem-cli/README.md`:
- Around line 111-130: The README usage and argument table for the redeem
properties to-onnx command are missing the existing --device and --opset options
from the to-onnx subcommand. Update the usage block and options table in this
section to document both flags, including their purpose and placement alongside
the other export arguments, using the to-onnx command and main.rs subcommand
definitions as the source of truth.

In `@redeem-cli/src/main.rs`:
- Around line 376-384: The subcommand match in main is carrying a dead alias arm
because clap returns only the canonical name from matches.subcommand(). Update
the match around onnx::run_to_onnx to handle just the canonical "to-onnx" case
and remove the unreachable "to_onnx" pattern, keeping the error handling and
exit behavior unchanged.

In `@redeem-cli/src/properties/onnx.rs`:
- Around line 36-39: The fallback in the component lookup is out of sync with
the CLI default, and the dead-code path can mislead future changes. Update the
`component` handling in `onnx.rs` so the fallback matches the actual default
configured in `main.rs` for the same argument, and keep the
`matches.get_one::<String>("component")` logic consistent with that source of
truth.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro

Run ID: c72834ef-1e4a-41b8-b461-008d173056f0

📥 Commits

Reviewing files that changed from the base of the PR and between 6950129 and 9dfdaa2.

📒 Files selected for processing (17)
  • Cargo.toml
  • redeem-cli/Cargo.toml
  • redeem-cli/README.md
  • redeem-cli/src/main.rs
  • redeem-cli/src/properties/mod.rs
  • redeem-cli/src/properties/onnx.rs
  • redeem-cli/tests/cli_smoke.rs
  • redeem-properties/Cargo.toml
  • redeem-properties/assets/pretrained_models/redeem/redeem_ccs_cnn_tf.onnx
  • redeem-properties/assets/pretrained_models/redeem/redeem_rt_cnn_tf.onnx
  • redeem-properties/src/lib.rs
  • redeem-properties/src/models/ccs_cnn_lstm_model.rs
  • redeem-properties/src/models/ccs_cnn_tf_model.rs
  • redeem-properties/src/models/ms2_bert_model.rs
  • redeem-properties/src/models/rt_cnn_lstm_model.rs
  • redeem-properties/src/models/rt_cnn_transformer_model.rs
  • redeem-properties/src/onnx_export.rs

Comment thread redeem-cli/src/main.rs
Comment thread redeem-properties/src/onnx_export.rs
Comment thread redeem-properties/src/onnx_export.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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 `@redeem-properties-py/Cargo.toml`:
- Line 16: The Candle dependency is still tracking a moving git branch, so
update the `candle-core` dependency in `Cargo.toml` to a fixed commit revision
instead of `add/candle-onnx-export`, and make sure the same pinned revision is
used consistently in the matching workspace `Cargo.toml` entries. Use the
existing `candle-core` dependency declaration as the place to change, and keep
all Candle-related package entries aligned to the same commit.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6f496c13-459f-457b-a607-d3fb5a8af1fb

📥 Commits

Reviewing files that changed from the base of the PR and between 9dfdaa2 and c65ba09.

📒 Files selected for processing (6)
  • redeem-cli/src/main.rs
  • redeem-openms-ffi/Cargo.toml
  • redeem-properties-py/Cargo.toml
  • redeem-properties/assets/pretrained_models/redeem/redeem_ccs_cnn_tf.onnx
  • redeem-properties/assets/pretrained_models/redeem/redeem_rt_cnn_tf.onnx
  • redeem-properties/src/onnx_export.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • redeem-cli/src/main.rs
  • redeem-properties/src/onnx_export.rs

pyo3 = { version = "0.22", features = ["extension-module"] }
numpy = "0.22"
anyhow = "1.0"
candle-core = { git = "https://github.com/singjc/candle.git", branch = "add/candle-onnx-export" }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Files ==\n'
git ls-files '**/Cargo.toml' | sed -n '1,120p'

printf '\n== redeem-properties-py/Cargo.toml ==\n'
cat -n redeem-properties-py/Cargo.toml

printf '\n== Search singjc/candle.git ==\n'
rg -n --hidden --glob 'Cargo.toml' 'singjc/candle\.git|add/candle-onnx-export|rev\s*=' .

Repository: singjc/redeem

Length of output: 2772


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== Workspace manifests mentioning candle ==\n'
rg -n --hidden --glob 'Cargo.toml' 'candle-core|candle-nn|singjc/candle\.git|add/candle-onnx-export' redeem-properties-py redeem-openms-ffi . || true

printf '\n== Top-level manifest(s) ==\n'
fd -a -t f '^Cargo\.toml$' .

printf '\n== redeem-openms-ffi/Cargo.toml ==\n'
cat -n redeem-openms-ffi/Cargo.toml

Repository: singjc/redeem

Length of output: 4118


Pin the Candle fork to a commit

redeem-properties-py/Cargo.toml still depends on https://github.com/singjc/candle.git via the moving add/candle-onnx-export branch. Pin this to a commit and update the matching Cargo.toml entries in the workspace to the same revision.

🤖 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 `@redeem-properties-py/Cargo.toml` at line 16, The Candle dependency is still
tracking a moving git branch, so update the `candle-core` dependency in
`Cargo.toml` to a fixed commit revision instead of `add/candle-onnx-export`, and
make sure the same pinned revision is used consistently in the matching
workspace `Cargo.toml` entries. Use the existing `candle-core` dependency
declaration as the place to change, and keep all Candle-related package entries
aligned to the same commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant