diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 0cdbfd7114cf0..0289bca5c84d2 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -348,9 +348,6 @@ ORT_RUNTIME_CLASS(ExternalSemaphoreHandle); // EP-imported view of shared exte ORT_RUNTIME_CLASS(DeviceEpIncompatibilityDetails); ORT_RUNTIME_CLASS(EpAssignedSubgraph); ORT_RUNTIME_CLASS(EpAssignedNode); -ORT_RUNTIME_CLASS(ModelPackageOptions); -ORT_RUNTIME_CLASS(ModelPackageContext); -ORT_RUNTIME_CLASS(ModelPackageComponentContext); #ifdef _MSC_VER typedef _Return_type_success_(return == 0) OrtStatus* OrtStatusPtr; @@ -938,9 +935,6 @@ typedef struct OrtCompileApi OrtCompileApi; struct OrtInteropApi; typedef struct OrtInteropApi OrtInteropApi; -struct OrtModelPackageApi; -typedef struct OrtModelPackageApi OrtModelPackageApi; - struct OrtEpApi; typedef struct OrtEpApi OrtEpApi; @@ -7501,26 +7495,6 @@ struct OrtApi { */ ORT_API2_STATUS(SessionReleaseCapturedGraph, _In_ OrtSession* session, _In_ int graph_annotation_id); - /** \brief Get the model package API table. - * - * Returns a pointer to the ::OrtModelPackageApi function table, which provides APIs to: - * - create and release model package options and contexts, - * - inspect model package metadata (components/variants), - * - select a component/variant and query selected files/options, - * - create a session from model package selection results. - * - * The returned pointer is owned by ONNX Runtime and is valid for the process lifetime. - * Do not free it. - * - * \note May return NULL if model package support is not available in the current build - * (for example, minimal builds). - * - * \return Pointer to ::OrtModelPackageApi, or NULL if unsupported. - * - * \since Version 1.27. - */ - const OrtModelPackageApi*(ORT_API_CALL* GetModelPackageApi)(void); - /** \brief Retrieve an experimental function pointer by name. * * Experimental functions are not part of the stable ABI and may be added or removed between releases without notice. @@ -8645,250 +8619,6 @@ struct OrtInteropApi { /// @} }; -/** \brief API table for model package workflows. - * - * A model package is a directory containing one or more *components* (logical models). - * Each component has one or more *variants*, where each variant targets a single - * execution provider (EP). The package manifest declares the EP name, device type, - * and an optional compatibility string for every variant so that the runtime can - * automatically select the best variant for the hardware and EPs available in the - * caller's session options. - * - * Obtain this table from OrtApi::GetModelPackageApi(). The APIs support: - * - creating model package options that capture EP configuration from OrtSessionOptions, - * - loading a package context (manifest + metadata) from a package root path, - * - querying component/variant metadata including per-variant EP information, - * - selecting a component (which also resolves the best-matching variant), - * - querying the selected variant's name and folder path, - * - creating an OrtSession from the selected component context. - * - * Typical flow: - * 1) Create model package options: - * - CreateModelPackageOptionsFromSessionOptions() - * 2) Load package metadata: - * - CreateModelPackageContext() - * 3) Query metadata (optional): - * - ModelPackage_GetSchemaVersion() - * - ModelPackage_GetComponentCount() - * - ModelPackage_GetComponentNames() - * - ModelPackage_GetVariantCount() - * - ModelPackage_GetVariantNames() - * - ModelPackage_GetVariantEpName() - * 4) Select a component and resolve variant: - * - SelectComponent() - * 5) Query selected variant info (optional): - * - ModelPackageComponent_GetSelectedVariantName() - * - ModelPackageComponent_GetSelectedVariantFolderPath() - * 6) Create session: - * - CreateSession() - * - * Ownership: - * - Release objects created by this API with the corresponding release methods: - * ReleaseModelPackageOptions(), ReleaseModelPackageContext(), - * ReleaseModelPackageComponentContext(). - * - * \since Version 1.27. - */ -struct OrtModelPackageApi { - /// \name OrtModelPackageOptions - /// @{ - - /** \brief Create model package options from an existing OrtSessionOptions. - * - * Captures EP configuration (registered execution providers and their devices) from - * the session options for use during variant selection. The resulting OrtModelPackageOptions - * is passed to SelectComponent() to resolve the best variant for the available EPs. - * - * \param[in] env The ORT environment. - * \param[in] session_options Session options containing registered EPs. - * \param[out] out Receives the newly created OrtModelPackageOptions. Must be released - * with ReleaseModelPackageOptions(). - * - * \since Version 1.27. - */ - ORT_API2_STATUS(CreateModelPackageOptionsFromSessionOptions, - _In_ const OrtEnv* env, - _In_ const OrtSessionOptions* session_options, - _Outptr_ OrtModelPackageOptions** out); - - ORT_CLASS_RELEASE(ModelPackageOptions); - /// @} - /// \name OrtModelPackageContext - /// @{ - - /** \brief Create a model package context by parsing the package at the given root path. - * - * Parses the manifest.json and component metadata from the specified directory. - * The returned context provides read-only access to the package structure (components, - * variants, EP declarations). - * - * \param[in] package_root Path to the model package root directory (containing manifest.json). - * \param[out] out Receives the newly created OrtModelPackageContext. Must be released - * with ReleaseModelPackageContext(). - * - * \since Version 1.27. - */ - ORT_API2_STATUS(CreateModelPackageContext, - _In_ const ORTCHAR_T* package_root, - _Outptr_ OrtModelPackageContext** out); - - ORT_CLASS_RELEASE(ModelPackageContext); - - /** \brief Get the schema version declared in the model package manifest. - * - * \param[in] ctx The model package context. - * \param[out] out_version Receives the schema version number. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(ModelPackage_GetSchemaVersion, - _In_ const OrtModelPackageContext* ctx, - _Out_ int64_t* out_version); - - /** \brief Get the number of components in the model package. - * - * \param[in] ctx The model package context. - * \param[out] out_count Receives the component count. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(ModelPackage_GetComponentCount, - _In_ const OrtModelPackageContext* ctx, - _Out_ size_t* out_count); - - /** \brief Get the names of all components in the model package. - * - * Returns a pointer to an array of UTF-8 component name strings. The array and its - * strings are owned by `ctx` and remain valid until the context is released. - * - * \param[in] ctx The model package context. - * \param[out] out_names Receives a pointer to an array of component name strings. - * \param[out] out_count Receives the number of elements in the array. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(ModelPackage_GetComponentNames, - _In_ const OrtModelPackageContext* ctx, - _Outptr_result_buffer_maybenull_(*out_count) const char* const** out_names, - _Out_ size_t* out_count); - - /** \brief Get the number of variants for a given component. - * - * \param[in] ctx The model package context. - * \param[in] component_name Name of the component to query. - * \param[out] out_count Receives the variant count. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(ModelPackage_GetVariantCount, - _In_ const OrtModelPackageContext* ctx, - _In_ const char* component_name, - _Out_ size_t* out_count); - - /** \brief Get the names of all variants for a given component. - * - * Returns a pointer to an array of UTF-8 variant name strings. The array and its - * strings are owned by `ctx` and remain valid until the context is released. - * - * \param[in] ctx The model package context. - * \param[in] component_name Name of the component to query. - * \param[out] out_variant_names Receives a pointer to an array of variant name strings. - * \param[out] out_count Receives the number of elements in the array. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(ModelPackage_GetVariantNames, - _In_ const OrtModelPackageContext* ctx, - _In_ const char* component_name, - _Outptr_result_buffer_maybenull_(*out_count) const char* const** out_variant_names, - _Out_ size_t* out_count); - - /** \brief Get the EP name declared for a (component, variant) pair. - * - * Each variant targets a single EP. `out_ep` receives the EP name string. - * When the variant does not declare an EP, the returned pointer is NULL. - * String memory is owned by `ctx` and remains valid until the context is released. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(ModelPackage_GetVariantEpName, - _In_ const OrtModelPackageContext* ctx, - _In_ const char* component_name, - _In_ const char* variant_name, - _Outptr_result_maybenull_ const char** out_ep); - - /** \brief Select a component model and return an opaque component instance. - * - * The variant selection is also performed during this call based on the component metadata and the provided options. - * The returned `OrtModelPackgeComponentContext*` is independent of `context` lifetime and must be released via - * `ReleaseComponentInstance`. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(SelectComponent, - _In_ const OrtModelPackageContext* context, - _In_ const char* component_name, - _In_ const OrtModelPackageOptions* options, - _Outptr_ OrtModelPackageComponentContext** out); - - ORT_CLASS_RELEASE(ModelPackageComponentContext); - - /** \brief Get the name of the selected variant after SelectComponent has been called. - * - * String memory is owned by `ctx` and remains valid until the context is released. - * - * \param[in] ctx The component context returned by SelectComponent(). - * \param[out] out_name Receives the selected variant's name string. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(ModelPackageComponent_GetSelectedVariantName, - _In_ const OrtModelPackageComponentContext* ctx, - _Outptr_ const char** out_name); - - /** \brief Get the folder path of the selected variant. - * - * Returns the resolved absolute path to the variant's directory on disk. - * The string is owned by `ctx` and remains valid until the context is released. - * - * \param[in] ctx The component context returned by SelectComponent(). - * \param[out] folder_path Receives the variant folder path string. - * - * \since Version 1.27. - */ - ORT_API2_STATUS(ModelPackageComponent_GetSelectedVariantFolderPath, - _In_ const OrtModelPackageComponentContext* ctx, - _Outptr_ const ORTCHAR_T** folder_path); - - /// @} - /** \brief Create an OrtSession for a selected file within a component model variant. - * - * The chosen variant (and thus its EP selection) is determined by `context`, which - * was built from an OrtSessionOptions via CreateModelPackageOptionsFromSessionOptions. - * - * Session options precedence: - * 1. session_options == NULL (default path): - * ORT uses the OrtSessionOptions that was captured when `context` was created. - * Any variant-specific session and provider options declared in the package - * metadata are merged on top. - * - * 2. session_options != NULL (advanced path): - * ORT uses the caller-provided OrtSessionOptions as-is. Variant-specific - * session and provider options from the package metadata are NOT applied. - * Use this when custom EP setup is required (e.g., shared CUDA streams, - * shared QNN EP contexts, custom allocators). - * - * \since Version 1.27. - */ - ORT_API2_STATUS(CreateSession, - _In_ const OrtEnv* env, - _In_ OrtModelPackageComponentContext* context, - _In_opt_ const OrtSessionOptions* session_options, - _Outptr_ OrtSession** session); - - // End of Version 1.27 - DO NOT MODIFY ABOVE -}; - /* * This is the old way to add the CUDA provider to the session, please use SessionOptionsAppendExecutionProvider_CUDA above to access the latest functionality * This function always exists, but will only succeed if Onnxruntime was built with CUDA support and the CUDA provider shared library exists diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_api.h b/include/onnxruntime/core/session/onnxruntime_cxx_api.h index a999ef5e0faf4..4798d3d4ad1b8 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_api.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_api.h @@ -264,20 +264,6 @@ inline const OrtEpApi& GetEpApi() { return *api; } -/// -/// This returns a reference to the ORT C Model Package API. Used for loading models from model packages. -/// -/// ORT C Model Package API reference -inline const OrtModelPackageApi& GetModelPackageApi() { - auto* api = GetApi().GetModelPackageApi(); - if (api == nullptr) { - // minimal build - ORT_CXX_API_THROW("Model Package API is not available in this build", ORT_FAIL); - } - - return *api; -} - /** \brief IEEE 754 half-precision floating point data type * * \details This struct is used for converting float to float16 and back @@ -678,9 +664,6 @@ ORT_DEFINE_RELEASE_FROM_API_STRUCT(KernelDefBuilder, GetEpApi); ORT_DEFINE_RELEASE_FROM_API_STRUCT(KernelRegistry, GetEpApi); ORT_DEFINE_RELEASE_FROM_API_STRUCT(OpSchema, GetEpApi); ORT_DEFINE_RELEASE_FROM_API_STRUCT(ProfilingEvent, GetEpApi); -ORT_DEFINE_RELEASE_FROM_API_STRUCT(ModelPackageOptions, GetModelPackageApi); -ORT_DEFINE_RELEASE_FROM_API_STRUCT(ModelPackageContext, GetModelPackageApi); -ORT_DEFINE_RELEASE_FROM_API_STRUCT(ModelPackageComponentContext, GetModelPackageApi); // This is defined explicitly since OrtTensorRTProviderOptionsV2 is not a C API type, // but the struct has V2 in its name to indicate that it is the second version of the options. @@ -807,9 +790,6 @@ struct EpDevice; struct ExternalInitializerInfo; struct Graph; struct Model; -struct ModelPackageOptions; -struct ModelPackageContext; -struct ModelPackageComponentContext; struct Node; struct ModelMetadata; struct TypeInfo; @@ -1806,70 +1786,6 @@ struct ModelCompilationOptions : detail::Base { */ Status CompileModel(const Env& env, const ModelCompilationOptions& model_compilation_options); -/** \brief Options for selecting a component from a model package. - * - * Wraps ::OrtModelPackageOptions. Created from an Env and SessionOptions, which captures the - * EP configuration used for variant selection. - */ -struct ModelPackageOptions : detail::Base { - using Base = detail::Base; - using Base::Base; - - explicit ModelPackageOptions(std::nullptr_t) {} ///< Create an empty object, must be assigned a valid one to be used. - - ModelPackageOptions(const Env& env, const SessionOptions& session_options); ///< Wraps OrtModelPackageApi::CreateModelPackageOptionsFromSessionOptions - ModelPackageOptions(const Env& env, ConstSessionOptions session_options); ///< Wraps OrtModelPackageApi::CreateModelPackageOptionsFromSessionOptions -}; - -/** \brief Context for inspecting and selecting components from a model package. - * - * Wraps ::OrtModelPackageContext. Provides traversal APIs to enumerate components, variants, - * and EP compatibility, as well as component selection. - */ -struct ModelPackageContext : detail::Base { - using Base = detail::Base; - using Base::Base; - - explicit ModelPackageContext(std::nullptr_t) {} ///< Create an empty object, must be assigned a valid one to be used. - - explicit ModelPackageContext(const ORTCHAR_T* package_root); ///< Wraps OrtModelPackageApi::CreateModelPackageContext - - size_t GetComponentCount() const; ///< Wraps OrtModelPackageApi::ModelPackage_GetComponentCount - std::vector GetComponentNames() const; ///< Wraps OrtModelPackageApi::ModelPackage_GetComponentNames - size_t GetVariantCount(const char* component_name) const; ///< Wraps OrtModelPackageApi::ModelPackage_GetVariantCount - std::vector GetVariantNames(const char* component_name) const; ///< Wraps OrtModelPackageApi::ModelPackage_GetVariantNames - - /// Get the EP name for a variant. Returns nullptr if not declared. - /// Returned string is owned by this context and valid until it is released. - const char* GetVariantEpName(const char* component_name, - const char* variant_name) const; ///< Wraps OrtModelPackageApi::ModelPackage_GetVariantEpName - - int64_t GetSchemaVersion() const; ///< Wraps OrtModelPackageApi::ModelPackage_GetSchemaVersion - - ModelPackageComponentContext SelectComponent(const char* component_name, - const ModelPackageOptions& options) const; ///< Wraps OrtModelPackageApi::SelectComponent -}; - -/** \brief Context for a selected component within a model package. - * - * Wraps ::OrtModelPackageComponentContext. Provides accessors for the selected variant's - * folder path and variant name. - */ -struct ModelPackageComponentContext : detail::Base { - using Base = detail::Base; - using Base::Base; - - explicit ModelPackageComponentContext(std::nullptr_t) {} ///< Create an empty object, must be assigned a valid one to be used. - - std::basic_string GetSelectedVariantFolderPath() const; ///< Wraps OrtModelPackageApi::ModelPackageComponent_GetSelectedVariantFolderPath - - std::string GetSelectedVariantName() const; ///< Wraps OrtModelPackageApi::ModelPackageComponent_GetSelectedVariantName - - Session CreateSession(const Env& env); ///< Wraps OrtModelPackageApi::CreateSession (default path, NULL session_options) - Session CreateSession(const Env& env, const SessionOptions& session_options); ///< Wraps OrtModelPackageApi::CreateSession (advanced path) - Session CreateSession(const Env& env, ConstSessionOptions session_options); ///< Wraps OrtModelPackageApi::CreateSession (advanced path) -}; - /** \brief Wrapper around ::OrtModelMetadata * */ diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h index 51f99655121c6..d7439e7b356c6 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h @@ -1360,110 +1360,6 @@ inline ModelCompilationOptions& ModelCompilationOptions::SetInputModel(const Ort return *this; } -// ModelPackageOptions -inline ModelPackageOptions::ModelPackageOptions(const Env& env, const SessionOptions& session_options) { - ThrowOnError(GetModelPackageApi().CreateModelPackageOptionsFromSessionOptions(env, session_options, &this->p_)); -} - -inline ModelPackageOptions::ModelPackageOptions(const Env& env, ConstSessionOptions session_options) { - ThrowOnError(GetModelPackageApi().CreateModelPackageOptionsFromSessionOptions(env, session_options, &this->p_)); -} - -// ModelPackageContext -inline ModelPackageContext::ModelPackageContext(const ORTCHAR_T* package_root) { - ThrowOnError(GetModelPackageApi().CreateModelPackageContext(package_root, &this->p_)); -} - -inline size_t ModelPackageContext::GetComponentCount() const { - size_t count = 0; - ThrowOnError(GetModelPackageApi().ModelPackage_GetComponentCount(this->p_, &count)); - return count; -} - -inline std::vector ModelPackageContext::GetComponentNames() const { - const char* const* names = nullptr; - size_t count = 0; - ThrowOnError(GetModelPackageApi().ModelPackage_GetComponentNames(this->p_, &names, &count)); - std::vector result; - result.reserve(count); - for (size_t i = 0; i < count; ++i) { - result.emplace_back(names[i]); - } - return result; -} - -inline size_t ModelPackageContext::GetVariantCount(const char* component_name) const { - size_t count = 0; - ThrowOnError(GetModelPackageApi().ModelPackage_GetVariantCount(this->p_, component_name, &count)); - return count; -} - -inline std::vector ModelPackageContext::GetVariantNames(const char* component_name) const { - const char* const* names = nullptr; - size_t count = 0; - ThrowOnError(GetModelPackageApi().ModelPackage_GetVariantNames(this->p_, component_name, &names, &count)); - std::vector result; - result.reserve(count); - for (size_t i = 0; i < count; ++i) { - result.emplace_back(names[i]); - } - return result; -} - -inline const char* ModelPackageContext::GetVariantEpName(const char* component_name, - const char* variant_name) const { - const char* ep = nullptr; - ThrowOnError(GetModelPackageApi().ModelPackage_GetVariantEpName( - this->p_, component_name, variant_name, &ep)); - return ep; -} - -inline int64_t ModelPackageContext::GetSchemaVersion() const { - int64_t version = 0; - ThrowOnError(GetModelPackageApi().ModelPackage_GetSchemaVersion(this->p_, &version)); - return version; -} - -inline ModelPackageComponentContext ModelPackageContext::SelectComponent( - const char* component_name, const ModelPackageOptions& options) const { - OrtModelPackageComponentContext* out = nullptr; - ThrowOnError(GetModelPackageApi().SelectComponent(this->p_, component_name, options, &out)); - return ModelPackageComponentContext{out}; -} - -// ModelPackageComponentContext -inline std::basic_string ModelPackageComponentContext::GetSelectedVariantFolderPath() const { - const ORTCHAR_T* path = nullptr; - ThrowOnError(GetModelPackageApi().ModelPackageComponent_GetSelectedVariantFolderPath(this->p_, &path)); - return std::basic_string{path}; -} - -inline std::string ModelPackageComponentContext::GetSelectedVariantName() const { - const char* name = nullptr; - ThrowOnError(GetModelPackageApi().ModelPackageComponent_GetSelectedVariantName(this->p_, &name)); - return (name != nullptr) ? std::string{name} : std::string{}; -} - -inline Session ModelPackageComponentContext::CreateSession(const Env& env) { - OrtSession* out = nullptr; - ThrowOnError(GetModelPackageApi().CreateSession(env, this->p_, nullptr, &out)); - return Session{out}; -} - -inline Session ModelPackageComponentContext::CreateSession(const Env& env, - const SessionOptions& session_options) { - OrtSession* out = nullptr; - ThrowOnError(GetModelPackageApi().CreateSession(env, this->p_, session_options, &out)); - return Session{out}; -} - -inline Session ModelPackageComponentContext::CreateSession(const Env& env, - ConstSessionOptions session_options) { - OrtSession* out = nullptr; - ThrowOnError(GetModelPackageApi().CreateSession(env, this->p_, session_options, &out)); - return Session{out}; -} - namespace detail { template diff --git a/include/onnxruntime/core/session/onnxruntime_experimental_c_api.h b/include/onnxruntime/core/session/onnxruntime_experimental_c_api.h index e943a5cf65b11..0dd87c10776d3 100644 --- a/include/onnxruntime/core/session/onnxruntime_experimental_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_experimental_c_api.h @@ -39,6 +39,10 @@ // ORT_RUNTIME_CLASS(ExperimentalType); // +ORT_RUNTIME_CLASS(ModelPackageOptions); +ORT_RUNTIME_CLASS(ModelPackageContext); +ORT_RUNTIME_CLASS(ModelPackageComponentContext); + // // C: function pointer typedefs and name constants // diff --git a/include/onnxruntime/core/session/onnxruntime_experimental_c_api.inc b/include/onnxruntime/core/session/onnxruntime_experimental_c_api.inc index 0123b02818584..57a4e472b6f6d 100644 --- a/include/onnxruntime/core/session/onnxruntime_experimental_c_api.inc +++ b/include/onnxruntime/core/session/onnxruntime_experimental_c_api.inc @@ -35,3 +35,250 @@ * \snippet{doc} snippets.dox OrtStatus Return Value */ ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtApi_ExperimentalApiTest, _Out_ int64_t* out) + +// --------------------------------------------------------------------------- +// OrtModelPackageApi +// +// A model package is a directory containing one or more *components* (logical models). +// Each component has one or more *variants*, where each variant targets a single +// execution provider (EP). The package manifest declares the EP name, device type, +// and an optional compatibility string for every variant so that the runtime can +// automatically select the best variant for the hardware and EPs available in the +// caller's session options. +// +// The functions below support: +// - creating model package options that capture EP configuration from OrtSessionOptions, +// - loading a package context (manifest + metadata) from a package root path, +// - querying component/variant metadata including per-variant EP information, +// - selecting a component (which also resolves the best-matching variant), +// - querying the selected variant's name and folder path, +// - creating an OrtSession from the selected component context. +// +// Typical flow: +// 1) Create model package options: +// - OrtModelPackageApi_CreateModelPackageOptionsFromSessionOptions +// 2) Load package metadata: +// - OrtModelPackageApi_CreateModelPackageContext +// 3) Query metadata (optional): +// - OrtModelPackageApi_ModelPackage_GetSchemaVersion +// - OrtModelPackageApi_ModelPackage_GetComponentCount +// - OrtModelPackageApi_ModelPackage_GetComponentNames +// - OrtModelPackageApi_ModelPackage_GetVariantCount +// - OrtModelPackageApi_ModelPackage_GetVariantNames +// - OrtModelPackageApi_ModelPackage_GetVariantEpName +// 4) Select a component and resolve variant: +// - OrtModelPackageApi_SelectComponent +// 5) Query selected variant info (optional): +// - OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantName +// - OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantFolderPath +// 6) Create session: +// - OrtModelPackageApi_CreateSession +// +// Ownership: +// - Release objects created by this API with the corresponding release functions: +// OrtModelPackageApi_ReleaseModelPackageOptions, +// OrtModelPackageApi_ReleaseModelPackageContext, +// OrtModelPackageApi_ReleaseModelPackageComponentContext. +// +// Opaque handles (OrtModelPackageOptions, OrtModelPackageContext, OrtModelPackageComponentContext) +// are declared in onnxruntime_experimental_c_api.h. +// --------------------------------------------------------------------------- + +/** \brief Create model package options from an existing OrtSessionOptions. + * + * Captures EP configuration (registered execution providers and their devices) from + * the session options for use during variant selection. The resulting OrtModelPackageOptions + * is passed to OrtModelPackageApi_SelectComponent to resolve the best variant for the + * available EPs. + * + * \param[in] env The ORT environment. + * \param[in] session_options Session options containing registered EPs. + * \param[out] out Receives the newly created OrtModelPackageOptions. Must be released + * with OrtModelPackageApi_ReleaseModelPackageOptions. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_CreateModelPackageOptionsFromSessionOptions, + _In_ const OrtEnv* env, + _In_ const OrtSessionOptions* session_options, + _Outptr_ OrtModelPackageOptions** out) + +/** \brief Release an OrtModelPackageOptions created by + * OrtModelPackageApi_CreateModelPackageOptionsFromSessionOptions. + */ +ORT_EXPERIMENTAL_API(28, void, OrtModelPackageApi_ReleaseModelPackageOptions, + _Frees_ptr_opt_ OrtModelPackageOptions* options) + +/** \brief Create a model package context by parsing the package at the given root path. + * + * Parses the manifest.json and component metadata from the specified directory. + * The returned context provides read-only access to the package structure (components, + * variants, EP declarations). + * + * \param[in] package_root Path to the model package root directory (containing manifest.json). + * \param[out] out Receives the newly created OrtModelPackageContext. Must be released + * with OrtModelPackageApi_ReleaseModelPackageContext. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_CreateModelPackageContext, + _In_ const ORTCHAR_T* package_root, + _Outptr_ OrtModelPackageContext** out) + +/** \brief Release an OrtModelPackageContext created by OrtModelPackageApi_CreateModelPackageContext. */ +ORT_EXPERIMENTAL_API(28, void, OrtModelPackageApi_ReleaseModelPackageContext, + _Frees_ptr_opt_ OrtModelPackageContext* ctx) + +/** \brief Get the schema version declared in the model package manifest. + * + * \param[in] ctx The model package context. + * \param[out] out_version Receives the schema version number. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_ModelPackage_GetSchemaVersion, + _In_ const OrtModelPackageContext* ctx, + _Out_ int64_t* out_version) + +/** \brief Get the number of components in the model package. + * + * \param[in] ctx The model package context. + * \param[out] out_count Receives the component count. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_ModelPackage_GetComponentCount, + _In_ const OrtModelPackageContext* ctx, + _Out_ size_t* out_count) + +/** \brief Get the names of all components in the model package. + * + * Returns a pointer to an array of UTF-8 component name strings. The array and its + * strings are owned by `ctx` and remain valid until the context is released. + * + * \param[in] ctx The model package context. + * \param[out] out_names Receives a pointer to an array of component name strings. + * \param[out] out_count Receives the number of elements in the array. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_ModelPackage_GetComponentNames, + _In_ const OrtModelPackageContext* ctx, + _Outptr_result_buffer_maybenull_(*out_count) const char* const** out_names, + _Out_ size_t* out_count) + +/** \brief Get the number of variants for a given component. + * + * \param[in] ctx The model package context. + * \param[in] component_name Name of the component to query. + * \param[out] out_count Receives the variant count. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_ModelPackage_GetVariantCount, + _In_ const OrtModelPackageContext* ctx, + _In_ const char* component_name, + _Out_ size_t* out_count) + +/** \brief Get the names of all variants for a given component. + * + * Returns a pointer to an array of UTF-8 variant name strings. The array and its + * strings are owned by `ctx` and remain valid until the context is released. + * + * \param[in] ctx The model package context. + * \param[in] component_name Name of the component to query. + * \param[out] out_variant_names Receives a pointer to an array of variant name strings. + * \param[out] out_count Receives the number of elements in the array. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_ModelPackage_GetVariantNames, + _In_ const OrtModelPackageContext* ctx, + _In_ const char* component_name, + _Outptr_result_buffer_maybenull_(*out_count) const char* const** out_variant_names, + _Out_ size_t* out_count) + +/** \brief Get the EP name declared for a (component, variant) pair. + * + * Each variant targets a single EP. `out_ep` receives the EP name string. + * When the variant does not declare an EP, the returned pointer is NULL. + * String memory is owned by `ctx` and remains valid until the context is released. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_ModelPackage_GetVariantEpName, + _In_ const OrtModelPackageContext* ctx, + _In_ const char* component_name, + _In_ const char* variant_name, + _Outptr_result_maybenull_ const char** out_ep) + +/** \brief Select a component model and return an opaque component instance. + * + * The variant selection is also performed during this call based on the component + * metadata and the provided options. The returned `OrtModelPackageComponentContext*` is + * independent of `context` lifetime and must be released via + * OrtModelPackageApi_ReleaseModelPackageComponentContext. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_SelectComponent, + _In_ const OrtModelPackageContext* context, + _In_ const char* component_name, + _In_ const OrtModelPackageOptions* options, + _Outptr_ OrtModelPackageComponentContext** out) + +/** \brief Release an OrtModelPackageComponentContext created by OrtModelPackageApi_SelectComponent. */ +ORT_EXPERIMENTAL_API(28, void, OrtModelPackageApi_ReleaseModelPackageComponentContext, + _Frees_ptr_opt_ OrtModelPackageComponentContext* ctx) + +/** \brief Get the name of the selected variant after OrtModelPackageApi_SelectComponent has been called. + * + * String memory is owned by `ctx` and remains valid until the context is released. + * + * \param[in] ctx The component context returned by OrtModelPackageApi_SelectComponent. + * \param[out] out_name Receives the selected variant's name string. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantName, + _In_ const OrtModelPackageComponentContext* ctx, + _Outptr_ const char** out_name) + +/** \brief Get the folder path of the selected variant. + * + * Returns the resolved absolute path to the variant's directory on disk. + * The string is owned by `ctx` and remains valid until the context is released. + * + * \param[in] ctx The component context returned by OrtModelPackageApi_SelectComponent. + * \param[out] folder_path Receives the variant folder path string. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantFolderPath, + _In_ const OrtModelPackageComponentContext* ctx, + _Outptr_ const ORTCHAR_T** folder_path) + +/** \brief Create an OrtSession for a selected file within a component model variant. + * + * The chosen variant (and thus its EP selection) is determined by `context`, which + * was built from an OrtSessionOptions via OrtModelPackageApi_CreateModelPackageOptionsFromSessionOptions. + * + * Session options precedence: + * 1. session_options == NULL (default path): + * ORT uses the OrtSessionOptions that was captured when `context` was created. + * Any variant-specific session and provider options declared in the package + * metadata are merged on top. + * + * 2. session_options != NULL (advanced path): + * ORT uses the caller-provided OrtSessionOptions as-is. Variant-specific + * session and provider options from the package metadata are NOT applied. + * Use this when custom EP setup is required (e.g., shared CUDA streams, + * shared QNN EP contexts, custom allocators). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + */ +ORT_EXPERIMENTAL_API(28, OrtStatusPtr, OrtModelPackageApi_CreateSession, + _In_ const OrtEnv* env, + _In_ OrtModelPackageComponentContext* context, + _In_opt_ const OrtSessionOptions* session_options, + _Outptr_ OrtSession** session) diff --git a/onnxruntime/__init__.py b/onnxruntime/__init__.py index c26424a0ab9ec..df14bc8c57f24 100644 --- a/onnxruntime/__init__.py +++ b/onnxruntime/__init__.py @@ -29,9 +29,6 @@ GraphOptimizationLevel, # noqa: F401 LoraAdapter, # noqa: F401 ModelMetadata, # noqa: F401 - ModelPackageComponentContext, # noqa: F401 - ModelPackageContext, # noqa: F401 - ModelPackageOptions, # noqa: F401 NodeArg, # noqa: F401 OrtAllocatorType, # noqa: F401 OrtArenaCfg, # noqa: F401 diff --git a/onnxruntime/core/session/experimental_c_api.cc b/onnxruntime/core/session/experimental_c_api.cc index d030b68abdb99..458c47bcb58cd 100644 --- a/onnxruntime/core/session/experimental_c_api.cc +++ b/onnxruntime/core/session/experimental_c_api.cc @@ -18,6 +18,14 @@ namespace OrtExperimentalApis { +// Forward declarations driven by the .inc file so the registration table below +// can take the address of every entry, including those defined in other +// translation units linked into onnxruntime_session. +#define ORT_EXPERIMENTAL_API(VER, RET, NAME, ...) \ + RET ORT_API_CALL NAME##_SinceV##VER(__VA_ARGS__) NO_EXCEPTION; +#include "onnxruntime_experimental_c_api.inc" +#undef ORT_EXPERIMENTAL_API + // Test-only experimental function that writes a known sentinel value. // Exists to exercise the experimental API mechanism end-to-end and to serve as a template for future experimental // functions. diff --git a/onnxruntime/core/session/model_package_api.cc b/onnxruntime/core/session/model_package_api.cc index 27abb0f5f7a37..5fd25f9511eb9 100644 --- a/onnxruntime/core/session/model_package_api.cc +++ b/onnxruntime/core/session/model_package_api.cc @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -#include "core/session/model_package_api.h" +#include "core/session/onnxruntime_experimental_c_api.h" #include "core/common/common.h" #include "core/framework/error_code_helper.h" @@ -23,7 +23,9 @@ using namespace onnxruntime; return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, \ "Model package API is not supported in this build") -ORT_API(void, OrtModelPackageAPI::ReleaseModelPackageOptions, +namespace OrtExperimentalApis { + +ORT_API(void, OrtModelPackageApi_ReleaseModelPackageOptions_SinceV28, _Frees_ptr_opt_ OrtModelPackageOptions* options) { #if !defined(ORT_MINIMAL_BUILD) delete reinterpret_cast(options); @@ -32,7 +34,7 @@ ORT_API(void, OrtModelPackageAPI::ReleaseModelPackageOptions, #endif } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::CreateModelPackageOptionsFromSessionOptions, +ORT_API_STATUS_IMPL(OrtModelPackageApi_CreateModelPackageOptionsFromSessionOptions_SinceV28, _In_ const OrtEnv* env, _In_ const OrtSessionOptions* session_options, _Outptr_ OrtModelPackageOptions** out) { @@ -54,7 +56,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::CreateModelPackageOptionsFromSessionOpti API_IMPL_END } -ORT_API(void, OrtModelPackageAPI::ReleaseModelPackageContext, +ORT_API(void, OrtModelPackageApi_ReleaseModelPackageContext_SinceV28, _Frees_ptr_opt_ OrtModelPackageContext* ctx) { #if !defined(ORT_MINIMAL_BUILD) delete reinterpret_cast(ctx); @@ -63,7 +65,7 @@ ORT_API(void, OrtModelPackageAPI::ReleaseModelPackageContext, #endif } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::CreateModelPackageContext, +ORT_API_STATUS_IMPL(OrtModelPackageApi_CreateModelPackageContext_SinceV28, _In_ const ORTCHAR_T* package_root, _Outptr_ OrtModelPackageContext** out) { API_IMPL_BEGIN @@ -89,7 +91,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::CreateModelPackageContext, API_IMPL_END } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetComponentCount, +ORT_API_STATUS_IMPL(OrtModelPackageApi_ModelPackage_GetComponentCount_SinceV28, _In_ const OrtModelPackageContext* ctx, _Out_ size_t* out_count) { API_IMPL_BEGIN @@ -107,7 +109,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetComponentCount, API_IMPL_END } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetComponentNames, +ORT_API_STATUS_IMPL(OrtModelPackageApi_ModelPackage_GetComponentNames_SinceV28, _In_ const OrtModelPackageContext* ctx, _Outptr_result_buffer_maybenull_(*out_count) const char* const** out_names, _Out_ size_t* out_count) { @@ -136,7 +138,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetComponentNames, API_IMPL_END } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetVariantCount, +ORT_API_STATUS_IMPL(OrtModelPackageApi_ModelPackage_GetVariantCount_SinceV28, _In_ const OrtModelPackageContext* ctx, _In_ const char* component_name, _Out_ size_t* out_count) { @@ -158,7 +160,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetVariantCount, API_IMPL_END } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetVariantNames, +ORT_API_STATUS_IMPL(OrtModelPackageApi_ModelPackage_GetVariantNames_SinceV28, _In_ const OrtModelPackageContext* ctx, _In_ const char* component_name, _Outptr_result_buffer_maybenull_(*out_count) const char* const** out_variant_names, @@ -190,7 +192,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetVariantNames, API_IMPL_END } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::SelectComponent, +ORT_API_STATUS_IMPL(OrtModelPackageApi_SelectComponent_SinceV28, _In_ const OrtModelPackageContext* context, _In_ const char* component_name, _In_ const OrtModelPackageOptions* options, @@ -235,7 +237,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::SelectComponent, API_IMPL_END } -ORT_API(void, OrtModelPackageAPI::ReleaseModelPackageComponentContext, +ORT_API(void, OrtModelPackageApi_ReleaseModelPackageComponentContext_SinceV28, _Frees_ptr_opt_ OrtModelPackageComponentContext* cix) { #if !defined(ORT_MINIMAL_BUILD) delete reinterpret_cast(cix); @@ -244,7 +246,7 @@ ORT_API(void, OrtModelPackageAPI::ReleaseModelPackageComponentContext, #endif } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackageComponent_GetSelectedVariantFolderPath, +ORT_API_STATUS_IMPL(OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantFolderPath_SinceV28, _In_ const OrtModelPackageComponentContext* ctx, _Outptr_ const ORTCHAR_T** folder_path) { API_IMPL_BEGIN @@ -269,7 +271,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackageComponent_GetSelectedVariant API_IMPL_END } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::CreateSession, +ORT_API_STATUS_IMPL(OrtModelPackageApi_CreateSession_SinceV28, _In_ const OrtEnv* env, _In_ OrtModelPackageComponentContext* ctx, _In_opt_ const OrtSessionOptions* session_options, @@ -383,7 +385,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::CreateSession, // ---------- API table ------------------------------------------------------ -ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetVariantEpName, +ORT_API_STATUS_IMPL(OrtModelPackageApi_ModelPackage_GetVariantEpName_SinceV28, _In_ const OrtModelPackageContext* ctx, _In_ const char* component_name, _In_ const char* variant_name, @@ -417,7 +419,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetVariantEpName, API_IMPL_END } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetSchemaVersion, +ORT_API_STATUS_IMPL(OrtModelPackageApi_ModelPackage_GetSchemaVersion_SinceV28, _In_ const OrtModelPackageContext* ctx, _Out_ int64_t* out_version) { API_IMPL_BEGIN @@ -437,7 +439,7 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackage_GetSchemaVersion, API_IMPL_END } -ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackageComponent_GetSelectedVariantName, +ORT_API_STATUS_IMPL(OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantName_SinceV28, _In_ const OrtModelPackageComponentContext* ctx, _Outptr_ const char** out_name) { API_IMPL_BEGIN @@ -461,40 +463,4 @@ ORT_API_STATUS_IMPL(OrtModelPackageAPI::ModelPackageComponent_GetSelectedVariant API_IMPL_END } -// ---------- API table dispatch --------------------------------------------- - -static constexpr OrtModelPackageApi ort_model_package_api = { - // Options - &OrtModelPackageAPI::CreateModelPackageOptionsFromSessionOptions, - &OrtModelPackageAPI::ReleaseModelPackageOptions, - - // Context - &OrtModelPackageAPI::CreateModelPackageContext, - &OrtModelPackageAPI::ReleaseModelPackageContext, - - // Package-level queries - &OrtModelPackageAPI::ModelPackage_GetSchemaVersion, - &OrtModelPackageAPI::ModelPackage_GetComponentCount, - &OrtModelPackageAPI::ModelPackage_GetComponentNames, - &OrtModelPackageAPI::ModelPackage_GetVariantCount, - &OrtModelPackageAPI::ModelPackage_GetVariantNames, - &OrtModelPackageAPI::ModelPackage_GetVariantEpName, - - // Variant selection and component queries - &OrtModelPackageAPI::SelectComponent, - &OrtModelPackageAPI::ReleaseModelPackageComponentContext, - &OrtModelPackageAPI::ModelPackageComponent_GetSelectedVariantName, - &OrtModelPackageAPI::ModelPackageComponent_GetSelectedVariantFolderPath, - - // Session - &OrtModelPackageAPI::CreateSession, - - // End of Version 1.27 - DO NOT MODIFY ABOVE -}; - -static_assert(offsetof(OrtModelPackageApi, CreateSession) / sizeof(void*) == 14, - "Size of initial OrtModelPackageApi cannot change"); - -ORT_API(const OrtModelPackageApi*, OrtModelPackageAPI::GetModelPackageApi) { - return &ort_model_package_api; -} +} // namespace OrtExperimentalApis diff --git a/onnxruntime/core/session/model_package_api.h b/onnxruntime/core/session/model_package_api.h deleted file mode 100644 index 435e3a521c24c..0000000000000 --- a/onnxruntime/core/session/model_package_api.h +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#include "core/session/onnxruntime_c_api.h" - -namespace OrtModelPackageAPI { - -ORT_API(const OrtModelPackageApi*, GetModelPackageApi); - -ORT_API(void, ReleaseModelPackageOptions, _Frees_ptr_opt_ OrtModelPackageOptions*); -ORT_API_STATUS_IMPL(CreateModelPackageOptionsFromSessionOptions, - _In_ const OrtEnv* env, - _In_ const OrtSessionOptions* session_options, - _Outptr_ OrtModelPackageOptions** out); - -ORT_API(void, ReleaseModelPackageContext, _Frees_ptr_opt_ OrtModelPackageContext*); -ORT_API_STATUS_IMPL(CreateModelPackageContext, - _In_ const ORTCHAR_T* package_root, - _Outptr_ OrtModelPackageContext** out); - -ORT_API_STATUS_IMPL(ModelPackage_GetComponentCount, - _In_ const OrtModelPackageContext* ctx, - _Out_ size_t* out_count); - -ORT_API_STATUS_IMPL(ModelPackage_GetComponentNames, - _In_ const OrtModelPackageContext* ctx, - _Outptr_result_buffer_maybenull_(*out_count) const char* const** out_names, - _Out_ size_t* out_count); - -ORT_API_STATUS_IMPL(ModelPackage_GetVariantCount, - _In_ const OrtModelPackageContext* ctx, - _In_ const char* component_name, - _Out_ size_t* out_count); - -ORT_API_STATUS_IMPL(ModelPackage_GetVariantNames, - _In_ const OrtModelPackageContext* ctx, - _In_ const char* component_name, - _Outptr_result_buffer_maybenull_(*out_count) const char* const** out_variant_names, - _Out_ size_t* out_count); - -ORT_API_STATUS_IMPL(SelectComponent, - _In_ const OrtModelPackageContext* context, - _In_ const char* component_name, - _In_ const OrtModelPackageOptions* options, - _Outptr_ OrtModelPackageComponentContext** out); - -ORT_API(void, ReleaseModelPackageComponentContext, - _Frees_ptr_opt_ OrtModelPackageComponentContext* ctx); - -ORT_API_STATUS_IMPL(ModelPackageComponent_GetSelectedVariantFolderPath, - _In_ const OrtModelPackageComponentContext* ctx, - _Outptr_ const ORTCHAR_T** folder_path); - -ORT_API_STATUS_IMPL(CreateSession, - _In_ const OrtEnv* env, - _In_ OrtModelPackageComponentContext* ctx, - _In_opt_ const OrtSessionOptions* session_options, - _Outptr_ OrtSession** session); - -ORT_API_STATUS_IMPL(ModelPackage_GetVariantEpName, - _In_ const OrtModelPackageContext* ctx, - _In_ const char* component_name, - _In_ const char* variant_name, - _Outptr_result_maybenull_ const char** out_ep); - -ORT_API_STATUS_IMPL(ModelPackage_GetSchemaVersion, - _In_ const OrtModelPackageContext* ctx, - _Out_ int64_t* out_version); - -ORT_API_STATUS_IMPL(ModelPackageComponent_GetSelectedVariantName, - _In_ const OrtModelPackageComponentContext* ctx, - _Outptr_ const char** out_name); - -} // namespace OrtModelPackageAPI diff --git a/onnxruntime/core/session/onnxruntime_c_api.cc b/onnxruntime/core/session/onnxruntime_c_api.cc index 61a413d92e7fc..f451eaa401497 100644 --- a/onnxruntime/core/session/onnxruntime_c_api.cc +++ b/onnxruntime/core/session/onnxruntime_c_api.cc @@ -57,7 +57,6 @@ #include "core/session/ort_env.h" #include "core/session/ort_version_check.h" #include "core/session/utils.h" -#include "core/session/model_package_api.h" #if defined(USE_CUDA) || defined(USE_CUDA_PROVIDER_INTERFACE) #include "core/providers/cuda/cuda_provider_factory.h" @@ -3689,10 +3688,6 @@ ORT_API(const OrtCompileApi*, OrtApis::GetCompileApi) { return OrtCompileAPI::GetCompileApi(); } -ORT_API(const OrtModelPackageApi*, OrtApis::GetModelPackageApi) { - return OrtModelPackageAPI::GetModelPackageApi(); -} - ORT_API(void, OrtApis::CreateKeyValuePairs, _Outptr_ OrtKeyValuePairs** out) { auto kvps = std::make_unique(); *out = reinterpret_cast(kvps.release()); @@ -4911,7 +4906,6 @@ static constexpr OrtApi ort_api_1_to_28 = { &OrtApis::GetMemPatternEnabled, &OrtApis::GetSessionExecutionMode, &OrtApis::SessionReleaseCapturedGraph, - &OrtApis::GetModelPackageApi, // End of Version 27 - DO NOT MODIFY ABOVE (see above text for more information) &OrtApis::GetExperimentalFunction, diff --git a/onnxruntime/core/session/ort_apis.h b/onnxruntime/core/session/ort_apis.h index 250a2853a4777..61ece2dd9a682 100644 --- a/onnxruntime/core/session/ort_apis.h +++ b/onnxruntime/core/session/ort_apis.h @@ -825,9 +825,6 @@ ORT_API_STATUS_IMPL(GetTensorElementTypeAndShapeDataReference, _In_ const OrtVal _Outptr_result_maybenull_ const int64_t** shape_data, _Out_ size_t* shape_data_count); -// Model Package API -ORT_API(const OrtModelPackageApi*, GetModelPackageApi); - // Experimental API ORT_API(OrtExperimentalFnPtr, GetExperimentalFunction, _In_ const char* name); diff --git a/onnxruntime/python/onnxruntime_pybind_state.cc b/onnxruntime/python/onnxruntime_pybind_state.cc index 77200ea84778e..2044a128d9540 100644 --- a/onnxruntime/python/onnxruntime_pybind_state.cc +++ b/onnxruntime/python/onnxruntime_pybind_state.cc @@ -3247,195 +3247,6 @@ including arg name, arg type (contains both type and shape).)pbdoc") #endif }, R"pbdoc(Compile an ONNX model into an output stream using the provided write functor.)pbdoc"); - - // --- Model Package API --- -#if !defined(ORT_MINIMAL_BUILD) - // Helper to create a PyInferenceSession from a pre-initialized OrtSession* (C API handle). - // PyInferenceSession's owning ctor is protected; this subclass provides access. - struct PyModelPackageSession : PyInferenceSession { - PyModelPackageSession(std::unique_ptr sess) - : PyInferenceSession(std::move(sess)) {} - }; - - // Wrapper classes to manage opaque C handles with proper RAII - struct PyModelPackageContext { - OrtModelPackageContext* ctx_{nullptr}; - PyModelPackageContext(const std::string& package_path) { - auto path = ToPathString(package_path); - const auto* api = Ort::GetApi().GetModelPackageApi(); - Ort::ThrowOnError(api->CreateModelPackageContext(path.c_str(), &ctx_)); - } - ~PyModelPackageContext() { - if (ctx_) { - const auto* api = Ort::GetApi().GetModelPackageApi(); - api->ReleaseModelPackageContext(ctx_); - } - } - PyModelPackageContext(const PyModelPackageContext&) = delete; - PyModelPackageContext& operator=(const PyModelPackageContext&) = delete; - }; - - struct PyModelPackageComponentContext { - OrtModelPackageComponentContext* ctx_{nullptr}; - ~PyModelPackageComponentContext() { - if (ctx_) { - const auto* api = Ort::GetApi().GetModelPackageApi(); - api->ReleaseModelPackageComponentContext(ctx_); - } - } - PyModelPackageComponentContext(const PyModelPackageComponentContext&) = delete; - PyModelPackageComponentContext& operator=(const PyModelPackageComponentContext&) = delete; - PyModelPackageComponentContext() = default; - }; - - struct PyModelPackageOptions { - OrtModelPackageOptions* opts_{nullptr}; - ~PyModelPackageOptions() { - if (opts_) { - const auto* api = Ort::GetApi().GetModelPackageApi(); - api->ReleaseModelPackageOptions(opts_); - } - } - PyModelPackageOptions(const PyModelPackageOptions&) = delete; - PyModelPackageOptions& operator=(const PyModelPackageOptions&) = delete; - PyModelPackageOptions() = default; - }; - - py::class_(m, "ModelPackageContext", - R"pbdoc(Represents an opened model package for inspection and component selection.)pbdoc") - .def(py::init(), py::arg("package_path"), - R"pbdoc(Open a model package from the given directory path.)pbdoc") - .def( - "get_component_names", - [](PyModelPackageContext& self) -> std::vector { - const auto* api = Ort::GetApi().GetModelPackageApi(); - const char* const* names = nullptr; - size_t count = 0; - Ort::ThrowOnError(api->ModelPackage_GetComponentNames(self.ctx_, &names, &count)); - std::vector result; - result.reserve(count); - for (size_t i = 0; i < count; ++i) { - result.emplace_back(names[i]); - } - return result; - }, - R"pbdoc(Get the names of all components in the package.)pbdoc") - .def( - "get_variant_names", - [](PyModelPackageContext& self, const std::string& component_name) -> std::vector { - const auto* api = Ort::GetApi().GetModelPackageApi(); - const char* const* names = nullptr; - size_t count = 0; - Ort::ThrowOnError(api->ModelPackage_GetVariantNames( - self.ctx_, component_name.c_str(), &names, &count)); - std::vector result; - result.reserve(count); - for (size_t i = 0; i < count; ++i) { - result.emplace_back(names[i]); - } - return result; - }, - py::arg("component_name"), - R"pbdoc(Get the variant names for a given component.)pbdoc") - .def( - "get_variant_ep_name", - [](PyModelPackageContext& self, const std::string& component_name, - const std::string& variant_name) -> std::optional { - const auto* api = Ort::GetApi().GetModelPackageApi(); - const char* ep = nullptr; - Ort::ThrowOnError(api->ModelPackage_GetVariantEpName( - self.ctx_, component_name.c_str(), variant_name.c_str(), &ep)); - if (ep) return std::string(ep); - return std::nullopt; - }, - py::arg("component_name"), py::arg("variant_name"), - R"pbdoc(Get the EP name for a variant. Returns None if not declared.)pbdoc") - .def( - "get_schema_version", - [](PyModelPackageContext& self) -> int64_t { - const auto* api = Ort::GetApi().GetModelPackageApi(); - int64_t version = 0; - Ort::ThrowOnError(api->ModelPackage_GetSchemaVersion(self.ctx_, &version)); - return version; - }, - R"pbdoc(Get the schema version declared in the model package manifest.)pbdoc") - .def( - "select_component", - [](PyModelPackageContext& self, const std::string& component_name, - PyModelPackageOptions& options) -> std::unique_ptr { - const auto* api = Ort::GetApi().GetModelPackageApi(); - auto result = std::make_unique(); - Ort::ThrowOnError(api->SelectComponent( - self.ctx_, component_name.c_str(), options.opts_, &result->ctx_)); - return result; - }, - py::arg("component_name"), py::arg("options"), - R"pbdoc(Select a component and resolve its variant based on the provided options. -Returns a ModelPackageComponentContext for inspecting the selected variant.)pbdoc"); - - py::class_(m, "ModelPackageOptions", - R"pbdoc(Options used for variant selection in a model package. -Created from a SessionOptions to capture EP configuration for variant matching.)pbdoc") - .def(py::init([](PySessionOptions& session_options) { - const auto* api = Ort::GetApi().GetModelPackageApi(); - auto result = std::make_unique(); - Ort::ThrowOnError(api->CreateModelPackageOptionsFromSessionOptions( - GetOrtEnv(), &session_options, &result->opts_)); - return result; - }), - py::arg("session_options"), - R"pbdoc(Create model package options from a SessionOptions instance. -The EP configured on the session options is used for variant selection.)pbdoc"); - - py::class_(m, "ModelPackageComponentContext", - R"pbdoc(Represents a selected component within a model package. -Provides access to the resolved variant's files, session options, and metadata.)pbdoc") - .def( - "get_selected_variant_folder_path", - [](PyModelPackageComponentContext& self) -> std::string { - const auto* api = Ort::GetApi().GetModelPackageApi(); - const ORTCHAR_T* path = nullptr; - Ort::ThrowOnError(api->ModelPackageComponent_GetSelectedVariantFolderPath(self.ctx_, &path)); - return PathToUTF8String(PathString(path)); - }, - R"pbdoc(Get the folder path of the selected variant.)pbdoc") - .def( - "get_selected_variant_name", - [](PyModelPackageComponentContext& self) -> std::string { - const auto* api = Ort::GetApi().GetModelPackageApi(); - const char* name = nullptr; - Ort::ThrowOnError(api->ModelPackageComponent_GetSelectedVariantName( - self.ctx_, &name)); - return name ? std::string(name) : std::string(); - }, - R"pbdoc(Get the name of the selected variant.)pbdoc") - .def( - "create_session", - [](PyModelPackageComponentContext& self, py::object session_options_obj) -> std::unique_ptr { - const auto* api = Ort::GetApi().GetModelPackageApi(); - OrtSession* ort_session = nullptr; - if (session_options_obj.is_none()) { - Ort::ThrowOnError(api->CreateSession(GetOrtEnv(), self.ctx_, nullptr, &ort_session)); - } else { - auto& so = session_options_obj.cast(); - Ort::ThrowOnError(api->CreateSession(GetOrtEnv(), self.ctx_, &so, &ort_session)); - } - // OrtSession* is a reinterpret_cast of InferenceSession* - auto* inference_session = reinterpret_cast(ort_session); - std::unique_ptr session_ptr(inference_session); - return std::make_unique(std::move(session_ptr)); - }, - py::arg("session_options") = py::none(), - R"pbdoc(Create an InferenceSession from the selected component variant. - -Args: - session_options: Optional SessionOptions override. If None, uses the options - captured during variant selection with per-file options merged on top. - If provided, variant-specific options are NOT applied. - -Returns: - An InferenceSession ready for inference.)pbdoc"); -#endif // !defined(ORT_MINIMAL_BUILD) } bool InitArray() { diff --git a/onnxruntime/test/autoep/test_model_package.cc b/onnxruntime/test/autoep/test_model_package.cc index 6fb3f8e6ba82f..34f73eb69b149 100644 --- a/onnxruntime/test/autoep/test_model_package.cc +++ b/onnxruntime/test/autoep/test_model_package.cc @@ -12,6 +12,7 @@ #include "gtest/gtest.h" #include "core/session/model_package/model_package_context.h" +#include "core/session/onnxruntime_experimental_c_api.h" #include "core/session/abi_devices.h" #include "test/autoep/test_autoep_utils.h" #include "test/util/include/asserts.h" @@ -22,6 +23,90 @@ extern std::unique_ptr ort_env; namespace onnxruntime { namespace test { namespace { + +// Typed function pointers for every OrtModelPackageApi_* experimental entry, +// resolved once via the experimental name-based lookup. +struct ModelPackageFns { + OrtExperimental_OrtModelPackageApi_CreateModelPackageOptionsFromSessionOptions_SinceV28_Fn + CreateModelPackageOptionsFromSessionOptions{nullptr}; + OrtExperimental_OrtModelPackageApi_ReleaseModelPackageOptions_SinceV28_Fn + ReleaseModelPackageOptions{nullptr}; + OrtExperimental_OrtModelPackageApi_CreateModelPackageContext_SinceV28_Fn + CreateModelPackageContext{nullptr}; + OrtExperimental_OrtModelPackageApi_ReleaseModelPackageContext_SinceV28_Fn + ReleaseModelPackageContext{nullptr}; + OrtExperimental_OrtModelPackageApi_ModelPackage_GetSchemaVersion_SinceV28_Fn + ModelPackage_GetSchemaVersion{nullptr}; + OrtExperimental_OrtModelPackageApi_ModelPackage_GetComponentCount_SinceV28_Fn + ModelPackage_GetComponentCount{nullptr}; + OrtExperimental_OrtModelPackageApi_ModelPackage_GetComponentNames_SinceV28_Fn + ModelPackage_GetComponentNames{nullptr}; + OrtExperimental_OrtModelPackageApi_ModelPackage_GetVariantCount_SinceV28_Fn + ModelPackage_GetVariantCount{nullptr}; + OrtExperimental_OrtModelPackageApi_ModelPackage_GetVariantNames_SinceV28_Fn + ModelPackage_GetVariantNames{nullptr}; + OrtExperimental_OrtModelPackageApi_ModelPackage_GetVariantEpName_SinceV28_Fn + ModelPackage_GetVariantEpName{nullptr}; + OrtExperimental_OrtModelPackageApi_SelectComponent_SinceV28_Fn + SelectComponent{nullptr}; + OrtExperimental_OrtModelPackageApi_ReleaseModelPackageComponentContext_SinceV28_Fn + ReleaseModelPackageComponentContext{nullptr}; + OrtExperimental_OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantName_SinceV28_Fn + ModelPackageComponent_GetSelectedVariantName{nullptr}; + OrtExperimental_OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantFolderPath_SinceV28_Fn + ModelPackageComponent_GetSelectedVariantFolderPath{nullptr}; + OrtExperimental_OrtModelPackageApi_CreateSession_SinceV28_Fn + CreateSession{nullptr}; +}; + +inline const ModelPackageFns& GetModelPackageFns() { + static const ModelPackageFns fns = []() { + const OrtApi* api = &Ort::GetApi(); + ModelPackageFns f; +#define RESOLVE(member, getter) \ + do { \ + f.member = Ort::Experimental::getter(api); \ + if (f.member == nullptr) { \ + throw std::runtime_error(std::string("Failed to resolve experimental " \ + "OrtModelPackageApi_") + \ + #member "_SinceV28"); \ + } \ + } while (0) + RESOLVE(CreateModelPackageOptionsFromSessionOptions, + Get_OrtModelPackageApi_CreateModelPackageOptionsFromSessionOptions_SinceV28_Fn); + RESOLVE(ReleaseModelPackageOptions, + Get_OrtModelPackageApi_ReleaseModelPackageOptions_SinceV28_Fn); + RESOLVE(CreateModelPackageContext, + Get_OrtModelPackageApi_CreateModelPackageContext_SinceV28_Fn); + RESOLVE(ReleaseModelPackageContext, + Get_OrtModelPackageApi_ReleaseModelPackageContext_SinceV28_Fn); + RESOLVE(ModelPackage_GetSchemaVersion, + Get_OrtModelPackageApi_ModelPackage_GetSchemaVersion_SinceV28_Fn); + RESOLVE(ModelPackage_GetComponentCount, + Get_OrtModelPackageApi_ModelPackage_GetComponentCount_SinceV28_Fn); + RESOLVE(ModelPackage_GetComponentNames, + Get_OrtModelPackageApi_ModelPackage_GetComponentNames_SinceV28_Fn); + RESOLVE(ModelPackage_GetVariantCount, + Get_OrtModelPackageApi_ModelPackage_GetVariantCount_SinceV28_Fn); + RESOLVE(ModelPackage_GetVariantNames, + Get_OrtModelPackageApi_ModelPackage_GetVariantNames_SinceV28_Fn); + RESOLVE(ModelPackage_GetVariantEpName, + Get_OrtModelPackageApi_ModelPackage_GetVariantEpName_SinceV28_Fn); + RESOLVE(SelectComponent, + Get_OrtModelPackageApi_SelectComponent_SinceV28_Fn); + RESOLVE(ReleaseModelPackageComponentContext, + Get_OrtModelPackageApi_ReleaseModelPackageComponentContext_SinceV28_Fn); + RESOLVE(ModelPackageComponent_GetSelectedVariantName, + Get_OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantName_SinceV28_Fn); + RESOLVE(ModelPackageComponent_GetSelectedVariantFolderPath, + Get_OrtModelPackageApi_ModelPackageComponent_GetSelectedVariantFolderPath_SinceV28_Fn); + RESOLVE(CreateSession, + Get_OrtModelPackageApi_CreateSession_SinceV28_Fn); +#undef RESOLVE + return f; + }(); + return fns; +} // ------------------------------------------------------------------ // Helpers to build a test model package on disk // ------------------------------------------------------------------ @@ -233,26 +318,25 @@ std::filesystem::path CreateModelPackageApiTestPackage(bool multi_file_variant = TEST(ModelPackageApiTest, PackageContextQueries) { const auto package_root = CreateModelPackageApiTestPackage(); - const OrtModelPackageApi* pkg_api = Ort::GetApi().GetModelPackageApi(); - ASSERT_NE(pkg_api, nullptr); + const auto& pkg_api = GetModelPackageFns(); - auto context_deleter = [pkg_api](OrtModelPackageContext* p) { - if (p) pkg_api->ReleaseModelPackageContext(p); + auto context_deleter = [&pkg_api](OrtModelPackageContext* p) { + if (p) pkg_api.ReleaseModelPackageContext(p); }; std::unique_ptr model_pkg_context(nullptr, context_deleter); OrtModelPackageContext* raw_context = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageContext(package_root.c_str(), &raw_context)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageContext(package_root.c_str(), &raw_context)); model_pkg_context.reset(raw_context); // Query: component count + names size_t component_count = 0; - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackage_GetComponentCount(model_pkg_context.get(), &component_count)); + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackage_GetComponentCount(model_pkg_context.get(), &component_count)); ASSERT_EQ(component_count, 1u); const char* const* component_names = nullptr; size_t component_name_count = 0; - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackage_GetComponentNames( + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackage_GetComponentNames( model_pkg_context.get(), &component_names, &component_name_count)); ASSERT_EQ(component_name_count, 1u); ASSERT_NE(component_names, nullptr); @@ -261,13 +345,13 @@ TEST(ModelPackageApiTest, PackageContextQueries) { // Query: variant count + names size_t variant_count = 0; - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackage_GetVariantCount( + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackage_GetVariantCount( model_pkg_context.get(), "model_1", &variant_count)); ASSERT_EQ(variant_count, 2u); const char* const* variant_names = nullptr; size_t variant_name_count = 0; - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackage_GetVariantNames( + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackage_GetVariantNames( model_pkg_context.get(), "model_1", &variant_names, &variant_name_count)); ASSERT_EQ(variant_name_count, 2u); @@ -294,17 +378,16 @@ TEST(ModelPackageApiTest, SingleFileVariantInComponent_SelectComponentAndCreateS std::unordered_map ep_options; session_options.AppendExecutionProvider_V2(*ort_env, {plugin_ep_device}, ep_options); - const OrtModelPackageApi* pkg_api = Ort::GetApi().GetModelPackageApi(); - ASSERT_NE(pkg_api, nullptr); + const auto& pkg_api = GetModelPackageFns(); - auto options_deleter = [pkg_api](OrtModelPackageOptions* p) { - if (p) pkg_api->ReleaseModelPackageOptions(p); + auto options_deleter = [&pkg_api](OrtModelPackageOptions* p) { + if (p) pkg_api.ReleaseModelPackageOptions(p); }; - auto context_deleter = [pkg_api](OrtModelPackageContext* p) { - if (p) pkg_api->ReleaseModelPackageContext(p); + auto context_deleter = [&pkg_api](OrtModelPackageContext* p) { + if (p) pkg_api.ReleaseModelPackageContext(p); }; - auto component_context_deleter = [pkg_api](OrtModelPackageComponentContext* p) { - if (p) pkg_api->ReleaseModelPackageComponentContext(p); + auto component_context_deleter = [&pkg_api](OrtModelPackageComponentContext* p) { + if (p) pkg_api.ReleaseModelPackageComponentContext(p); }; std::unique_ptr model_pkg_options(nullptr, options_deleter); @@ -312,25 +395,25 @@ TEST(ModelPackageApiTest, SingleFileVariantInComponent_SelectComponentAndCreateS std::unique_ptr component_context(nullptr, component_context_deleter); OrtModelPackageOptions* raw_options = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageOptionsFromSessionOptions(*ort_env, session_options, &raw_options)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageOptionsFromSessionOptions(*ort_env, session_options, &raw_options)); model_pkg_options.reset(raw_options); OrtModelPackageContext* raw_context = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageContext(package_root.c_str(), &raw_context)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageContext(package_root.c_str(), &raw_context)); model_pkg_context.reset(raw_context); OrtModelPackageComponentContext* raw_component_context = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->SelectComponent(model_pkg_context.get(), - "model_1", - model_pkg_options.get(), - &raw_component_context)); + ASSERT_ORTSTATUS_OK(pkg_api.SelectComponent(model_pkg_context.get(), + "model_1", + model_pkg_options.get(), + &raw_component_context)); component_context.reset(raw_component_context); OrtSession* raw_session = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateSession(*ort_env, - component_context.get(), - session_options, - &raw_session)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateSession(*ort_env, + component_context.get(), + session_options, + &raw_session)); Ort::Session session(raw_session); Ort::MemoryInfo memory_info = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeCPU); @@ -921,33 +1004,32 @@ TEST(ModelPackageApiTest, GetVariantEpName_ReturnsSingleEp) { os << R"({"filename":"mul_1.onnx"})"; } - const OrtModelPackageApi* pkg_api = Ort::GetApi().GetModelPackageApi(); - ASSERT_NE(pkg_api, nullptr); + const auto& pkg_api = GetModelPackageFns(); - auto context_deleter = [pkg_api](OrtModelPackageContext* p) { - if (p) pkg_api->ReleaseModelPackageContext(p); + auto context_deleter = [&pkg_api](OrtModelPackageContext* p) { + if (p) pkg_api.ReleaseModelPackageContext(p); }; std::unique_ptr ctx(nullptr, context_deleter); OrtModelPackageContext* raw_ctx = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageContext(package_root.c_str(), &raw_ctx)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageContext(package_root.c_str(), &raw_ctx)); ctx.reset(raw_ctx); // variant_1 targets example_ep const char* ep1 = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackage_GetVariantEpName( + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackage_GetVariantEpName( ctx.get(), "model_1", "variant_1", &ep1)); ASSERT_NE(ep1, nullptr); EXPECT_STREQ(ep1, "example_ep"); // variant_2 targets other_ep const char* ep2 = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackage_GetVariantEpName( + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackage_GetVariantEpName( ctx.get(), "model_1", "variant_2", &ep2)); ASSERT_NE(ep2, nullptr); EXPECT_STREQ(ep2, "other_ep"); // Optional out-parameter: callers can pass NULL. - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackage_GetVariantEpName( + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackage_GetVariantEpName( ctx.get(), "model_1", "variant_1", nullptr)); std::filesystem::remove_all(package_root, ec); @@ -990,32 +1072,31 @@ TEST(ModelPackageTest, VariantSelector_TieBreakIsDeterministic) { std::unordered_map ep_options; session_options.AppendExecutionProvider_V2(*ort_env, {plugin_ep_device}, ep_options); - const OrtModelPackageApi* pkg_api = Ort::GetApi().GetModelPackageApi(); - ASSERT_NE(pkg_api, nullptr); + const auto& pkg_api = GetModelPackageFns(); - auto options_deleter = [pkg_api](OrtModelPackageOptions* p) { if (p) pkg_api->ReleaseModelPackageOptions(p); }; - auto context_deleter = [pkg_api](OrtModelPackageContext* p) { if (p) pkg_api->ReleaseModelPackageContext(p); }; - auto component_context_deleter = [pkg_api](OrtModelPackageComponentContext* p) { - if (p) pkg_api->ReleaseModelPackageComponentContext(p); + auto options_deleter = [&pkg_api](OrtModelPackageOptions* p) { if (p) pkg_api.ReleaseModelPackageOptions(p); }; + auto context_deleter = [&pkg_api](OrtModelPackageContext* p) { if (p) pkg_api.ReleaseModelPackageContext(p); }; + auto component_context_deleter = [&pkg_api](OrtModelPackageComponentContext* p) { + if (p) pkg_api.ReleaseModelPackageComponentContext(p); }; std::unique_ptr mp_opts(nullptr, options_deleter); std::unique_ptr ctx(nullptr, context_deleter); std::unique_ptr comp_ctx(nullptr, component_context_deleter); OrtModelPackageOptions* raw_mp_opts = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageOptionsFromSessionOptions(*ort_env, session_options, &raw_mp_opts)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageOptionsFromSessionOptions(*ort_env, session_options, &raw_mp_opts)); mp_opts.reset(raw_mp_opts); OrtModelPackageContext* raw_ctx = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageContext(package_root.c_str(), &raw_ctx)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageContext(package_root.c_str(), &raw_ctx)); ctx.reset(raw_ctx); OrtModelPackageComponentContext* raw_comp_ctx = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->SelectComponent(ctx.get(), "model_1", mp_opts.get(), &raw_comp_ctx)); + ASSERT_ORTSTATUS_OK(pkg_api.SelectComponent(ctx.get(), "model_1", mp_opts.get(), &raw_comp_ctx)); comp_ctx.reset(raw_comp_ctx); const ORTCHAR_T* selected_folder = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackageComponent_GetSelectedVariantFolderPath(comp_ctx.get(), &selected_folder)); + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackageComponent_GetSelectedVariantFolderPath(comp_ctx.get(), &selected_folder)); ASSERT_NE(selected_folder, nullptr); // Path looks like .../models/model_1/ -- the folder name is the variant. @@ -1082,28 +1163,27 @@ TEST(ModelPackageTest, VariantSessionOptions_DispatchedThroughAddSessionConfigEn std::unordered_map ep_options; session_options.AppendExecutionProvider_V2(*ort_env, {plugin_ep_device}, ep_options); - const OrtModelPackageApi* pkg_api = Ort::GetApi().GetModelPackageApi(); - ASSERT_NE(pkg_api, nullptr); + const auto& pkg_api = GetModelPackageFns(); - auto options_deleter = [pkg_api](OrtModelPackageOptions* p) { if (p) pkg_api->ReleaseModelPackageOptions(p); }; - auto context_deleter = [pkg_api](OrtModelPackageContext* p) { if (p) pkg_api->ReleaseModelPackageContext(p); }; - auto component_context_deleter = [pkg_api](OrtModelPackageComponentContext* p) { - if (p) pkg_api->ReleaseModelPackageComponentContext(p); + auto options_deleter = [&pkg_api](OrtModelPackageOptions* p) { if (p) pkg_api.ReleaseModelPackageOptions(p); }; + auto context_deleter = [&pkg_api](OrtModelPackageContext* p) { if (p) pkg_api.ReleaseModelPackageContext(p); }; + auto component_context_deleter = [&pkg_api](OrtModelPackageComponentContext* p) { + if (p) pkg_api.ReleaseModelPackageComponentContext(p); }; std::unique_ptr mp_opts(nullptr, options_deleter); std::unique_ptr ctx(nullptr, context_deleter); std::unique_ptr comp_ctx(nullptr, component_context_deleter); OrtModelPackageOptions* raw_mp_opts = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageOptionsFromSessionOptions(*ort_env, session_options, &raw_mp_opts)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageOptionsFromSessionOptions(*ort_env, session_options, &raw_mp_opts)); mp_opts.reset(raw_mp_opts); OrtModelPackageContext* raw_ctx = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageContext(package_root.c_str(), &raw_ctx)); + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageContext(package_root.c_str(), &raw_ctx)); ctx.reset(raw_ctx); OrtModelPackageComponentContext* raw_comp_ctx = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->SelectComponent(ctx.get(), "model_1", mp_opts.get(), &raw_comp_ctx)); + ASSERT_ORTSTATUS_OK(pkg_api.SelectComponent(ctx.get(), "model_1", mp_opts.get(), &raw_comp_ctx)); comp_ctx.reset(raw_comp_ctx); // CreateSession iterates the per-file session_options and dispatches each through OrtApis::AddSessionConfigEntry. @@ -1111,7 +1191,7 @@ TEST(ModelPackageTest, VariantSessionOptions_DispatchedThroughAddSessionConfigEn // Pass nullptr for session_options so the metadata-merge path runs (it is skipped when the caller // supplies their own session_options). OrtSession* raw_session = nullptr; - OrtStatus* st = pkg_api->CreateSession(*ort_env, comp_ctx.get(), /*session_options=*/nullptr, &raw_session); + OrtStatus* st = pkg_api.CreateSession(*ort_env, comp_ctx.get(), /*session_options=*/nullptr, &raw_session); // Clean up session first to avoid leaks if assertion fails. if (raw_session != nullptr) { Ort::GetApi().ReleaseSession(raw_session); @@ -1131,60 +1211,6 @@ TEST(ModelPackageTest, VariantSessionOptions_DispatchedThroughAddSessionConfigEn std::filesystem::remove_all(package_root, ec); } -// Test that the C++ RAII wrappers (Ort::ModelPackageContext, etc.) work correctly. -TEST(ModelPackageApiTest, CxxWrappers_PackageContextQueries) { - const auto package_root = CreateModelPackageApiTestPackage(); - - Ort::ModelPackageContext ctx(package_root.c_str()); - - // Component queries - EXPECT_EQ(ctx.GetComponentCount(), 1u); - auto component_names = ctx.GetComponentNames(); - ASSERT_EQ(component_names.size(), 1u); - EXPECT_EQ(component_names[0], "model_1"); - - // Variant queries - EXPECT_EQ(ctx.GetVariantCount("model_1"), 2u); - auto variant_names = ctx.GetVariantNames("model_1"); - ASSERT_EQ(variant_names.size(), 2u); - std::unordered_set variant_set(variant_names.begin(), variant_names.end()); - EXPECT_EQ(variant_set.count("variant_1"), 1u); - EXPECT_EQ(variant_set.count("variant_2"), 1u); - - std::error_code ec; - std::filesystem::remove_all(package_root, ec); -} - -TEST(ModelPackageApiTest, CxxWrappers_SelectComponentAndQueryFileAccessors) { - const auto package_root = CreateModelPackageApiTestPackage(); - - RegisteredEpDeviceUniquePtr example_ep; - ASSERT_NO_FATAL_FAILURE(Utils::RegisterAndGetExampleEp(*ort_env, Utils::example_ep_info, example_ep)); - Ort::ConstEpDevice plugin_ep_device(example_ep.get()); - - Ort::SessionOptions so; - std::unordered_map ep_options; - so.AppendExecutionProvider_V2(*ort_env, {plugin_ep_device}, ep_options); - Ort::ModelPackageOptions pkg_opts(*ort_env, so); - - Ort::ModelPackageContext ctx(package_root.c_str()); - auto cix = ctx.SelectComponent("model_1", pkg_opts); - - // Folder path should be non-empty - auto folder = cix.GetSelectedVariantFolderPath(); - EXPECT_FALSE(folder.empty()); - - // Selected variant name should not throw - auto variant_name = cix.GetSelectedVariantName(); - EXPECT_FALSE(variant_name.empty()); - - // CreateSession via C++ wrapper - auto session = cix.CreateSession(*ort_env, so); - - std::error_code ec; - std::filesystem::remove_all(package_root, ec); -} - // ------------------------------------------------------------------ // Test: GetSelectedVariantFolderPath returns correct path even when variant.json is absent. // ------------------------------------------------------------------ @@ -1221,31 +1247,29 @@ TEST(ModelPackageApiTest, FolderPath_ReturnsCorrectPath_WhenVariantJsonAbsent) { Ort::SessionOptions so; std::unordered_map ep_options; so.AppendExecutionProvider_V2(*ort_env, {plugin_ep_device}, ep_options); - Ort::ModelPackageOptions pkg_opts(*ort_env, so); - const OrtModelPackageApi* pkg_api = Ort::GetApi().GetModelPackageApi(); - ASSERT_NE(pkg_api, nullptr); + const auto& pkg_api = GetModelPackageFns(); OrtModelPackageOptions* raw_mp_opts = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageOptionsFromSessionOptions(*ort_env, so, &raw_mp_opts)); - auto options_deleter = [pkg_api](OrtModelPackageOptions* p) { if (p) pkg_api->ReleaseModelPackageOptions(p); }; + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageOptionsFromSessionOptions(*ort_env, so, &raw_mp_opts)); + auto options_deleter = [&pkg_api](OrtModelPackageOptions* p) { if (p) pkg_api.ReleaseModelPackageOptions(p); }; std::unique_ptr mp_opts(raw_mp_opts, options_deleter); OrtModelPackageContext* raw_ctx = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->CreateModelPackageContext(package_root.c_str(), &raw_ctx)); - auto context_deleter = [pkg_api](OrtModelPackageContext* p) { if (p) pkg_api->ReleaseModelPackageContext(p); }; + ASSERT_ORTSTATUS_OK(pkg_api.CreateModelPackageContext(package_root.c_str(), &raw_ctx)); + auto context_deleter = [&pkg_api](OrtModelPackageContext* p) { if (p) pkg_api.ReleaseModelPackageContext(p); }; std::unique_ptr ctx(raw_ctx, context_deleter); OrtModelPackageComponentContext* raw_comp_ctx = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->SelectComponent(ctx.get(), "model_1", mp_opts.get(), &raw_comp_ctx)); - auto component_context_deleter = [pkg_api](OrtModelPackageComponentContext* p) { - if (p) pkg_api->ReleaseModelPackageComponentContext(p); + ASSERT_ORTSTATUS_OK(pkg_api.SelectComponent(ctx.get(), "model_1", mp_opts.get(), &raw_comp_ctx)); + auto component_context_deleter = [&pkg_api](OrtModelPackageComponentContext* p) { + if (p) pkg_api.ReleaseModelPackageComponentContext(p); }; std::unique_ptr comp_ctx(raw_comp_ctx, component_context_deleter); // GetSelectedVariantFolderPath should return the variant directory even without variant.json. const ORTCHAR_T* selected_folder = nullptr; - ASSERT_ORTSTATUS_OK(pkg_api->ModelPackageComponent_GetSelectedVariantFolderPath(comp_ctx.get(), &selected_folder)); + ASSERT_ORTSTATUS_OK(pkg_api.ModelPackageComponent_GetSelectedVariantFolderPath(comp_ctx.get(), &selected_folder)); ASSERT_NE(selected_folder, nullptr); const auto result_path = std::filesystem::path(selected_folder);