Skip to content

Commit 66f530f

Browse files
author
Aditya Rastogi
committed
Initial draft
1 parent de99059 commit 66f530f

File tree

6 files changed

+491
-1
lines changed

6 files changed

+491
-1
lines changed

include/onnxruntime/core/session/onnxruntime_c_api.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6912,6 +6912,77 @@ struct OrtApi {
69126912
ORT_CLASS_RELEASE(DeviceEpIncompatibilityDetails);
69136913

69146914
/// @}
6915+
6916+
/// \name Model Compatibility APIs
6917+
/// @{
6918+
6919+
/** \brief Extract EP compatibility info from a precompiled model file.
6920+
*
6921+
* Parses the model file to extract the compatibility info string for a specific execution provider
6922+
* from the model's metadata properties. This is only applicable to models that have been precompiled
6923+
* for an EP (e.g., via OrtCompileApi). Standard ONNX models do not contain this information.
6924+
*
6925+
* The compatibility info string must be valid UTF-8 without embedded NUL characters.
6926+
*
6927+
* \note This API performs standalone model parsing, separate from session creation. This means
6928+
* the protobuf parsing cost is incurred here and again during session creation. It is intended
6929+
* for scenarios where applications need to check compatibility before deciding whether to proceed
6930+
* with session creation, such as providing early user feedback.
6931+
*
6932+
* \note This operation parses the full ONNX ModelProto from disk. For very large models, consider
6933+
* using GetCompatibilityInfoFromModelBytes with a pre-loaded buffer if the model is already in memory.
6934+
*
6935+
* The compatibility info can then be passed to GetModelCompatibilityForEpDevices to check if a
6936+
* precompiled model is compatible with the current system.
6937+
*
6938+
* \param[in] model_path Path to the ONNX model file.
6939+
* \param[in] ep_type The execution provider type string. Must be non-empty.
6940+
* Use OrtApi::EpDevice_EpName to get this value from an OrtEpDevice.
6941+
* \param[in] allocator Allocator to use for the output string. Use OrtApi::GetAllocatorWithDefaultOptions.
6942+
* \param[out] compatibility_info Output pointer to the compatibility info string.
6943+
* Returns nullptr if no compatibility info exists for the specified EP.
6944+
* Caller must free with OrtApi::AllocatorFree when non-null.
6945+
*
6946+
* \snippet{doc} snippets.dox OrtStatus Return Value
6947+
*
6948+
* \since Version 1.24.
6949+
*/
6950+
ORT_API2_STATUS(GetCompatibilityInfoFromModel,
6951+
_In_ const ORTCHAR_T* model_path,
6952+
_In_ const char* ep_type,
6953+
_Inout_ OrtAllocator* allocator,
6954+
_Outptr_result_maybenull_ char** compatibility_info);
6955+
6956+
/** \brief Extract EP compatibility info from precompiled model bytes in memory.
6957+
*
6958+
* Same as GetCompatibilityInfoFromModel but reads from a memory buffer instead of a file.
6959+
* Useful when precompiled models are loaded from encrypted storage, network, or other non-file sources.
6960+
*
6961+
* \note This API performs standalone model parsing, separate from session creation. This means
6962+
* the protobuf parsing cost is incurred here and again during session creation. It is intended
6963+
* for scenarios where applications need to check compatibility before deciding whether to proceed
6964+
* with session creation, such as providing early user feedback.
6965+
*
6966+
* \param[in] model_data Pointer to the model data in memory.
6967+
* \param[in] model_data_length Size of the model data in bytes.
6968+
* \param[in] ep_type The execution provider type string. Must be non-empty.
6969+
* \param[in] allocator Allocator to use for the output string. Use OrtApi::GetAllocatorWithDefaultOptions.
6970+
* \param[out] compatibility_info Output pointer to the compatibility info string.
6971+
* Returns nullptr if no compatibility info exists for the specified EP.
6972+
* Caller must free with OrtApi::AllocatorFree when non-null.
6973+
*
6974+
* \snippet{doc} snippets.dox OrtStatus Return Value
6975+
*
6976+
* \since Version 1.24.
6977+
*/
6978+
ORT_API2_STATUS(GetCompatibilityInfoFromModelBytes,
6979+
_In_reads_(model_data_length) const void* model_data,
6980+
_In_ size_t model_data_length,
6981+
_In_ const char* ep_type,
6982+
_Inout_ OrtAllocator* allocator,
6983+
_Outptr_result_maybenull_ char** compatibility_info);
6984+
6985+
/// @}
69156986
};
69166987

69176988
/*

include/onnxruntime/core/session/onnxruntime_cxx_api.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,39 @@ OrtCompiledModelCompatibility GetModelCompatibilityForEpDevices(
11641164
const std::vector<ConstEpDevice>& ep_devices,
11651165
const char* compatibility_info);
11661166

1167+
/** \\brief Extract EP compatibility info from a precompiled model file.
1168+
*
1169+
* Parses the model file to extract the compatibility info string for a specific execution provider
1170+
* from the model's metadata properties. This is only applicable to models that have been precompiled
1171+
* for an EP. Standard ONNX models do not contain this information.
1172+
*
1173+
* \\note This operation parses the full ONNX ModelProto from disk.
1174+
*
1175+
* \\param model_path Path to the ONNX model file.
1176+
* \\param ep_type The execution provider type string. Must be non-empty.
1177+
* Use ConstEpDevice::EpName() to get this value.
1178+
* \\param allocator Allocator to use for the output string.
1179+
* \\return The compatibility info string, or nullptr if not found for this EP. Caller must free via allocator.
1180+
* \\throws Ort::Exception on error.
1181+
*/
1182+
AllocatedStringPtr GetCompatibilityInfoFromModelAllocated(const ORTCHAR_T* model_path, const char* ep_type,
1183+
OrtAllocator* allocator);
1184+
1185+
/** \\brief Extract EP compatibility info from precompiled model bytes in memory.
1186+
*
1187+
* Same as GetCompatibilityInfoFromModelAllocated but reads from a memory buffer.
1188+
* Useful when precompiled models are loaded from encrypted storage, network, or other non-file sources.
1189+
*
1190+
* \\param model_data Pointer to the model data in memory.
1191+
* \\param model_data_length Size of the model data in bytes.
1192+
* \\param ep_type The execution provider type string. Must be non-empty.
1193+
* \\param allocator Allocator to use for the output string.
1194+
* \\return The compatibility info string, or nullptr if not found for this EP. Caller must free via allocator.
1195+
* \\throws Ort::Exception on error.
1196+
*/
1197+
AllocatedStringPtr GetCompatibilityInfoFromModelBytesAllocated(const void* model_data, size_t model_data_length,
1198+
const char* ep_type, OrtAllocator* allocator);
1199+
11671200
/** \brief The Env (Environment)
11681201
*
11691202
* The Env holds the logging state used by all other objects.

include/onnxruntime/core/session/onnxruntime_cxx_inline.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -919,6 +919,20 @@ inline OrtCompiledModelCompatibility GetModelCompatibilityForEpDevices(
919919
return status;
920920
}
921921

922+
inline AllocatedStringPtr GetCompatibilityInfoFromModelAllocated(const ORTCHAR_T* model_path, const char* ep_type,
923+
OrtAllocator* allocator) {
924+
char* compat_info = nullptr;
925+
ThrowOnError(GetApi().GetCompatibilityInfoFromModel(model_path, ep_type, allocator, &compat_info));
926+
return AllocatedStringPtr(compat_info, detail::AllocatedFree(allocator));
927+
}
928+
929+
inline AllocatedStringPtr GetCompatibilityInfoFromModelBytesAllocated(const void* model_data, size_t model_data_length,
930+
const char* ep_type, OrtAllocator* allocator) {
931+
char* compat_info = nullptr;
932+
ThrowOnError(GetApi().GetCompatibilityInfoFromModelBytes(model_data, model_data_length, ep_type, allocator, &compat_info));
933+
return AllocatedStringPtr(compat_info, detail::AllocatedFree(allocator));
934+
}
935+
922936
inline LoraAdapter LoraAdapter::CreateLoraAdapter(const std::basic_string<ORTCHAR_T>& adapter_path,
923937
OrtAllocator* allocator) {
924938
OrtLoraAdapter* p;

onnxruntime/core/session/onnxruntime_c_api.cc

Lines changed: 117 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@
33

44
#include <algorithm>
55
#include <cassert>
6+
#include <climits>
67
#include <cstring>
78
#include <functional>
89
#include <mutex>
9-
#include <vector>
1010
#include <sstream>
11+
#include <vector>
1112

1213
#include "core/common/common.h"
1314
#include "core/common/logging/logging.h"
@@ -30,15 +31,18 @@
3031
#include "core/framework/utils.h"
3132
#include "core/graph/constants.h"
3233
#include "core/graph/graph.h"
34+
#include "core/graph/model.h"
3335
#include "core/graph/model_editor_api_types.h"
3436
#include "core/graph/ep_api_types.h"
37+
#include "core/graph/onnx_protobuf.h"
3538
#include "core/providers/get_execution_providers.h"
3639
#include "core/session/abi_devices.h"
3740
#include "core/session/abi_session_options_impl.h"
3841
#include "core/session/allocator_adapters.h"
3942
#include "core/session/compile_api.h"
4043
#include "core/session/environment.h"
4144
#include "core/session/interop_api.h"
45+
#include "core/session/onnxruntime_ep_device_ep_metadata_keys.h"
4246
#include "core/session/plugin_ep/ep_api.h"
4347
#include "core/session/plugin_ep/ep_library_internal.h"
4448
#include "core/session/inference_session.h"
@@ -3565,6 +3569,93 @@ ORT_API_STATUS_IMPL(OrtApis::GetModelCompatibilityForEpDevices,
35653569
API_IMPL_END
35663570
}
35673571

3572+
// Helper function to extract compatibility info from model metadata
3573+
static OrtStatus* ExtractCompatibilityInfoFromModelProto(
3574+
const ONNX_NAMESPACE::ModelProto& model_proto,
3575+
const char* ep_type,
3576+
OrtAllocator* allocator,
3577+
char** compatibility_info) {
3578+
// Build the key we're looking for
3579+
std::string target_key = std::string(kOrtModelMetadata_EpCompatibilityInfoPrefix) + ep_type;
3580+
3581+
// Search through metadata_props for the matching key
3582+
for (const auto& prop : model_proto.metadata_props()) {
3583+
if (prop.key() == target_key) {
3584+
// Found it - allocate and copy the value using the provided allocator
3585+
*compatibility_info = onnxruntime::StrDup(prop.value(), allocator);
3586+
if (*compatibility_info == nullptr) {
3587+
return OrtApis::CreateStatus(ORT_FAIL, "Failed to allocate memory for compatibility info.");
3588+
}
3589+
return nullptr;
3590+
}
3591+
}
3592+
3593+
// Key not found - return nullptr (not an error, just means no compat info for this EP)
3594+
*compatibility_info = nullptr;
3595+
return nullptr;
3596+
}
3597+
3598+
// Extract EP compatibility info from a model file
3599+
ORT_API_STATUS_IMPL(OrtApis::GetCompatibilityInfoFromModel,
3600+
_In_ const ORTCHAR_T* model_path,
3601+
_In_ const char* ep_type,
3602+
_Inout_ OrtAllocator* allocator,
3603+
_Outptr_result_maybenull_ char** compatibility_info) {
3604+
API_IMPL_BEGIN
3605+
if (model_path == nullptr || ep_type == nullptr || ep_type[0] == '\0' ||
3606+
allocator == nullptr || compatibility_info == nullptr) {
3607+
return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT,
3608+
"Invalid argument provided to GetCompatibilityInfoFromModel.");
3609+
}
3610+
3611+
*compatibility_info = nullptr;
3612+
3613+
// Use Model::Load for proper cross-platform path handling via file descriptor
3614+
ONNX_NAMESPACE::ModelProto model_proto;
3615+
auto status = Model::Load(PathString(model_path), model_proto);
3616+
if (!status.IsOK()) {
3617+
if (status.Code() == common::NO_SUCHFILE) {
3618+
return OrtApis::CreateStatus(ORT_NO_SUCHFILE, status.ErrorMessage().c_str());
3619+
}
3620+
return OrtApis::CreateStatus(ORT_INVALID_GRAPH, status.ErrorMessage().c_str());
3621+
}
3622+
3623+
return ExtractCompatibilityInfoFromModelProto(model_proto, ep_type, allocator, compatibility_info);
3624+
API_IMPL_END
3625+
}
3626+
3627+
// Extract EP compatibility info from model bytes in memory
3628+
ORT_API_STATUS_IMPL(OrtApis::GetCompatibilityInfoFromModelBytes,
3629+
_In_reads_(model_data_length) const void* model_data,
3630+
_In_ size_t model_data_length,
3631+
_In_ const char* ep_type,
3632+
_Inout_ OrtAllocator* allocator,
3633+
_Outptr_result_maybenull_ char** compatibility_info) {
3634+
API_IMPL_BEGIN
3635+
if (model_data == nullptr || model_data_length == 0 || ep_type == nullptr || ep_type[0] == '\0' ||
3636+
allocator == nullptr || compatibility_info == nullptr) {
3637+
return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT,
3638+
"Invalid argument provided to GetCompatibilityInfoFromModelBytes.");
3639+
}
3640+
3641+
*compatibility_info = nullptr;
3642+
3643+
// Explicit check for size limit - Model::LoadFromBytes uses int for size due to protobuf API
3644+
if (model_data_length > static_cast<size_t>(INT_MAX)) {
3645+
return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT,
3646+
"Model data size exceeds maximum supported size (2GB). Use GetCompatibilityInfoFromModel with a file path instead.");
3647+
}
3648+
3649+
ONNX_NAMESPACE::ModelProto model_proto;
3650+
auto status = Model::LoadFromBytes(static_cast<int>(model_data_length), model_data, model_proto);
3651+
if (!status.IsOK()) {
3652+
return OrtApis::CreateStatus(ORT_INVALID_GRAPH, status.ErrorMessage().c_str());
3653+
}
3654+
3655+
return ExtractCompatibilityInfoFromModelProto(model_proto, ep_type, allocator, compatibility_info);
3656+
API_IMPL_END
3657+
}
3658+
35683659
// GetInteropApi - returns the Interop API struct
35693660
ORT_API(const OrtInteropApi*, OrtApis::GetInteropApi) {
35703661
return OrtInteropAPI::GetInteropApi();
@@ -3603,6 +3694,29 @@ ORT_API_STATUS_IMPL(OrtApis::GetModelCompatibilityForEpDevices,
36033694
API_IMPL_END
36043695
}
36053696

3697+
// Minimal build stub for GetCompatibilityInfoFromModel
3698+
ORT_API_STATUS_IMPL(OrtApis::GetCompatibilityInfoFromModel,
3699+
_In_ const ORTCHAR_T* /*model_path*/,
3700+
_In_ const char* /*ep_type*/,
3701+
_Inout_ OrtAllocator* /*allocator*/,
3702+
_Outptr_result_maybenull_ char** /*compatibility_info*/) {
3703+
API_IMPL_BEGIN
3704+
return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, "GetCompatibilityInfoFromModel is not supported in a minimal build.");
3705+
API_IMPL_END
3706+
}
3707+
3708+
// Minimal build stub for GetCompatibilityInfoFromModelBytes
3709+
ORT_API_STATUS_IMPL(OrtApis::GetCompatibilityInfoFromModelBytes,
3710+
_In_reads_(model_data_length) const void* /*model_data*/,
3711+
_In_ size_t /*model_data_length*/,
3712+
_In_ const char* /*ep_type*/,
3713+
_Inout_ OrtAllocator* /*allocator*/,
3714+
_Outptr_result_maybenull_ char** /*compatibility_info*/) {
3715+
API_IMPL_BEGIN
3716+
return OrtApis::CreateStatus(ORT_NOT_IMPLEMENTED, "GetCompatibilityInfoFromModelBytes is not supported in a minimal build.");
3717+
API_IMPL_END
3718+
}
3719+
36063720
ORT_API_STATUS_IMPL(OrtApis::SessionOptionsAppendExecutionProvider_V2, _In_ OrtSessionOptions* /*session_options*/,
36073721
_In_ OrtEnv* /*env*/,
36083722
_In_reads_(num_ep_devices) const OrtEpDevice* const* /*ep_devices*/,
@@ -4298,6 +4412,8 @@ static constexpr OrtApi ort_api_1_to_24 = {
42984412
&OrtApis::DeviceEpIncompatibilityDetails_GetNotes,
42994413
&OrtApis::DeviceEpIncompatibilityDetails_GetErrorCode,
43004414
&OrtApis::ReleaseDeviceEpIncompatibilityDetails,
4415+
&OrtApis::GetCompatibilityInfoFromModel,
4416+
&OrtApis::GetCompatibilityInfoFromModelBytes,
43014417
};
43024418

43034419
// OrtApiBase can never change as there is no way to know what version of OrtApiBase is returned by OrtGetApiBase.

onnxruntime/core/session/ort_apis.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,6 +659,17 @@ ORT_API_STATUS_IMPL(GetModelCompatibilityForEpDevices,
659659
_In_ size_t num_ep_devices,
660660
_In_ const char* compatibility_info,
661661
_Out_ OrtCompiledModelCompatibility* out_status);
662+
ORT_API_STATUS_IMPL(GetCompatibilityInfoFromModel,
663+
_In_ const ORTCHAR_T* model_path,
664+
_In_ const char* ep_type,
665+
_Inout_ OrtAllocator* allocator,
666+
_Outptr_result_maybenull_ char** compatibility_info);
667+
ORT_API_STATUS_IMPL(GetCompatibilityInfoFromModelBytes,
668+
_In_reads_(model_data_length) const void* model_data,
669+
_In_ size_t model_data_length,
670+
_In_ const char* ep_type,
671+
_Inout_ OrtAllocator* allocator,
672+
_Outptr_result_maybenull_ char** compatibility_info);
662673
ORT_API_STATUS_IMPL(Graph_GetModelPath, _In_ const OrtGraph* graph, _Outptr_ const ORTCHAR_T** model_path);
663674
ORT_API_STATUS_IMPL(Graph_GetOnnxIRVersion, _In_ const OrtGraph* graph, _Out_ int64_t* onnx_ir_version);
664675
ORT_API_STATUS_IMPL(Graph_GetNumOperatorSets, _In_ const OrtGraph* graph, _Out_ size_t* num_operator_sets);

0 commit comments

Comments
 (0)