Skip to content

Add session_options.custom_ops_libraries and share session options with auxiliary sessions - #2725

Merged
Tianlei Wu (tianleiwu) merged 3 commits into
mainfrom
tlwu/20261013/ga-b1-custom-ops-libraries
Oct 14, 2026
Merged

Tianlei Wu (tianleiwu) merged 3 commits into
mainfrom
tlwu/20261013/ga-b1-custom-ops-libraries

Conversation

@tianleiwu

@tianleiwu Tianlei Wu (tianleiwu) commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Description

Adds session_options.custom_ops_libraries, a list of custom-op libraries registered in order after the existing single custom_ops_library, and exports InheritSessionOptionsFromParent so components that create auxiliary sessions (for example MTP/draft heads) can inherit the decoder's providers, provider options, config entries and custom ops.

Models whose graphs use several custom-op domains (fused attention, hyper-connection, GEMM and head ops shipped next to the model package) currently cannot name more than one library. This change is generic and has no dependency on any model type; it is the first step of the Qwen3.8-Flash static-graph backend series (see the end of this description), but stands alone and targets main.

Summary of Changes

File Change
src/config.h, src/config.cpp New session_options.custom_ops_libraries (JSON string array; scalar values such as "custom_ops_libraries": "ops.so" are rejected during parsing). Overlays append to custom_ops_libraries (and [] leaves existing entries unchanged). InheritSessionOptionsFromParent exposes the existing inheritance helper; custom_ops_library and custom_ops_libraries are inherited together when the child sets neither (note that "custom_ops_libraries": [] leaves the vector empty and therefore still inherits from the parent unless custom_ops_library is set).
src/models/model.cpp custom_ops_library and then every custom_ops_libraries entry go through the same path-traversal and allow-list checks, with duplicate resolved paths registered once. All paths are validated against the allow-list before loading starts; validated libraries are then loaded and registered sequentially in order (so a later load/registration error can still leave earlier libraries registered on session_options).
test/CMakeLists.txt, test/cpp/engine/custom_ops_test_lib/custom_ops_test_lib.cpp, test/cpp/engine/custom_ops_libraries_tests.cpp Builds two small test custom-op shared libraries (custom_ops_test_first and custom_ops_test_second) and tests parsing/ordering, overlay rules, rejection of non-string entries and scalar values, inheritance (including [] and CreateMtpDecoderConfig), allow-list validation, and actual library loading, ordering, and deduplication.

Library Location Requirement

Every entry in custom_ops_library and custom_ops_libraries must resolve to an existing file inside one of the allowed directories:

  1. The model folder (alongside genai_config.json),
  2. A registered Execution Provider (EP) library directory, or
  3. The current working directory.

Previously, an unresolved bare library name in custom_ops_library was passed directly to RegisterCustomOpsLibrary and could be resolved through the platform loader search path (LD_LIBRARY_PATH / PATH). Unresolved entries are now rejected before loading so the directory allow-list cannot be bypassed; users should place custom-op libraries in one of the allowed directories above (typically the model folder).

Testing

  • CPU-only Release build (-DUSE_CUDA=OFF) on main: engine_unit_tests 929 passed, 0 failed, 2 skipped (including all 9 tests in CustomOpsLibrariesConfigTest, which load real test custom-op shared libraries to verify registration, ordering, and deduplication).
  • lintrunner, clang-format (20.1.8) and git diff --check are clean.

Motivation and Context

Found while hosting a model that uses seven custom-op libraries. Registering them through one custom_ops_library entry was not possible, and auxiliary sessions did not inherit the decoder's custom ops, so head graphs failed to load without repeating the whole session configuration.

This is the first PR of a stack that adds an Engine-hosted CUDA-graph MTP backend for Qwen3.8-Flash-Next (greedy only, one resident request, Linux/CUDA, no prefix cache). The follow-ups are drafts stacked on kvaishnavi/qwen-38-flash-run, so this commit is also carried as the first commit of the next PR (#2726) until this one merges. The stack: #2726 (CUDA data plane library) -> #2727 (model type and device engine) -> #2728 (Engine hosting) -> #2729 (qualification tools).

Checklist

  • Tests added/updated
  • No breaking changes
  • Documentation updated (the option is described in the PR; no dedicated config documentation exists for session_options yet)

…th auxiliary sessions

Models that combine several custom-op libraries (for example fused attention and
fused hyper-connection ops shipped next to a model package) could only name one
library through `session_options.custom_ops_library`.

- `session_options.custom_ops_libraries` is a list of additional custom-op
  libraries, registered in order after `custom_ops_library`. Every entry goes
  through the same path-traversal and allow-list checks as the single library,
  and all entries are validated before any library is registered.
- `custom_ops_libraries` is inherited together with the other session options.
- `InheritSessionOptionsFromParent` exposes the existing inheritance helper so
  components that create extra sessions (auxiliary heads) can inherit the
  decoder's providers, provider options, config entries and custom ops.
- Unit tests cover parsing, inheritance, and the allow-list for every entry.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI 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.

🟡 Changes recommended

Unresolved library names can bypass the intended directory allow-list.

1 open finding
What changed in this PR

Adds ordered multi-library custom-op configuration and session-option inheritance for auxiliary sessions.

Changes:

  • Parses and inherits custom_ops_libraries.
  • Validates and registers multiple libraries in order.
  • Adds configuration, inheritance, and allow-list tests.
File Description
src/​config.h Declares the new option and inheritance API.
src/​config.cpp Parses and inherits library lists.
src/​models/​model.cpp Validates and registers configured libraries.
test/​cpp/​engine/​custom_ops_libraries_tests.cpp Tests parsing, inheritance, and validation.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/models/model.cpp Resolved
- Reject custom ops library entries that cannot be resolved inside an allowed
  directory instead of handing the raw name to the platform loader.
- Build the allow-list directories once instead of per entry.
- Inherit custom_ops_library and custom_ops_libraries together, only when the
  child sets neither; register duplicate entries once.
- Make error messages generic and extend tests (unresolved entries, inheritance,
  non-vacuous out-of-allow-list case with RAII cleanup).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The approach looks good. I checked the latest commit and tested the config behavior. The earlier missing-library issue is fixed. Please fix the wrong-type check, explain the change to old library loading, and make the list rules clear. I also suggest a few tests that actually load libraries. Details are inline. I did not run the full engine test suite.

Comment thread src/config.cpp Resolved
Comment thread src/models/model.cpp Resolved
Comment thread src/config.cpp Resolved
Comment thread src/config.cpp Resolved
Comment thread src/models/model.cpp Resolved
…ary load tests

- Reject scalar values for `session_options.custom_ops_libraries` in
  `SessionOptions_Element::OnValue` instead of adding them to `config_entries`.
- Document overlay append behavior, empty-list inheritance semantics, allowed
  library directories, and two-phase path validation vs. sequential registration.
- Build two test custom-op shared libraries (`custom_ops_test_first` and
  `custom_ops_test_second`) and test actual loading, registration order
  (`custom_ops_library` before `custom_ops_libraries`), deduplication across
  relative/canonical paths, overlay rules, empty-list inheritance, and MTP
  `CreateMtpDecoderConfig` inheritance/override.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tianleiwu
Tianlei Wu (tianleiwu) enabled auto-merge (squash) October 14, 2026 07:02
@tianleiwu
Tianlei Wu (tianleiwu) merged commit bdfadcf into main Oct 14, 2026
63 of 66 checks passed
@tianleiwu
Tianlei Wu (tianleiwu) deleted the tlwu/20261013/ga-b1-custom-ops-libraries branch October 14, 2026 07:31
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.

3 participants