Skip to content

Commit

Permalink
[OV JS] Enable CompiledModel set/get property() (openvinotoolkit#25808)
Browse files Browse the repository at this point in the history
### Details:
- add 2 methods: `CompiledModel::set_property()` and
`CompiledModel::get_property()`
 - create TypeScript definition for new created methods
- create unit tests for new functionalities (due to the issue that was
mentioned
[here](openvinotoolkit#24374 (comment)),
it's more of a mock now and should be altered as soon as the issue is
fixed)

### Tickets:
 - 134825
  • Loading branch information
hub-bla authored Aug 14, 2024
1 parent e0e5612 commit 98e4c36
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 2 deletions.
16 changes: 16 additions & 0 deletions src/bindings/js/node/include/compiled_model.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,22 @@ class CompiledModelWrap : public Napi::ObjectWrap<CompiledModelWrap> {
/** @brief Exports the compiled model to bytes/output stream. */
Napi::Value export_model(const Napi::CallbackInfo& info);

/**
* @brief Sets properties for current compiled model.
* @param info Contains information about the environment and passed arguments,
* this method accepts only one argument of type object.
* @return Napi::Undefined
*/
Napi::Value set_property(const Napi::CallbackInfo& info);

/**
* @brief Gets property for current compiled model.
* @param info Contains information about the environment and passed arguments,
* this method accepts only one argument of type string.
* @return A Napi::Value
*/
Napi::Value get_property(const Napi::CallbackInfo& info);

private:
/** @brief Gets node of a compiled model specified in CallbackInfo. */
Napi::Value get_node(const Napi::CallbackInfo& info,
Expand Down
16 changes: 15 additions & 1 deletion src/bindings/js/node/lib/addon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,12 @@ interface CompiledModel {
inputs: Output[];
/** It gets all outputs of a compiled model. */
outputs: Output[];
/**
* It gets the property for the current compiled model.
* @param propertyName A string to get the property value.
* @returns The property value.
*/
getProperty(propertyName: string): string | number | boolean;
/**
* It creates an inference request object used to infer the compiled model.
* @return {InferRequest}
Expand Down Expand Up @@ -353,7 +359,15 @@ interface CompiledModel {
* @returns {Output} A compiled model input.
*/
input(name: string): Output;

/**
* It sets properties for the current compiled model. Properties
* can be retrieved via {@link CompiledModel.getProperty}.
* @param property An object with the key-value pairs.
* (property name, property value)
*/
setProperty(properties: {
[propertyName: string]: string | number | boolean
}): void;
}

/**
Expand Down
39 changes: 38 additions & 1 deletion src/bindings/js/node/src/compiled_model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

#include "node/include/addon.hpp"
#include "node/include/errors.hpp"
#include "node/include/helper.hpp"
#include "node/include/infer_request.hpp"
#include "node/include/node_output.hpp"
#include "node/include/type_validation.hpp"

CompiledModelWrap::CompiledModelWrap(const Napi::CallbackInfo& info)
: Napi::ObjectWrap<CompiledModelWrap>(info),
Expand All @@ -20,7 +22,9 @@ Napi::Function CompiledModelWrap::get_class(Napi::Env env) {
InstanceAccessor<&CompiledModelWrap::get_inputs>("inputs"),
InstanceMethod("output", &CompiledModelWrap::get_output),
InstanceAccessor<&CompiledModelWrap::get_outputs>("outputs"),
InstanceMethod("exportModelSync", &CompiledModelWrap::export_model)});
InstanceMethod("exportModelSync", &CompiledModelWrap::export_model),
InstanceMethod("setProperty", &CompiledModelWrap::set_property),
InstanceMethod("getProperty", &CompiledModelWrap::get_property)});
}

Napi::Object CompiledModelWrap::wrap(Napi::Env env, ov::CompiledModel compiled_model) {
Expand Down Expand Up @@ -122,3 +126,36 @@ Napi::Value CompiledModelWrap::export_model(const Napi::CallbackInfo& info) {
const auto& exported = _stream.str();
return Napi::Buffer<const char>::Copy(info.Env(), exported.c_str(), exported.size());
}

Napi::Value CompiledModelWrap::set_property(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
std::vector<std::string> allowed_signatures;
try {
if (ov::js::validate<Napi::Object>(info, allowed_signatures)) {
const auto properties = to_anyMap(env, info[0]);
_compiled_model.set_property(properties);
} else {
OPENVINO_THROW("'setProperty'", ov::js::get_parameters_error_msg(info, allowed_signatures));
}
} catch (const std::exception& e) {
reportError(env, e.what());
}
return env.Undefined();
}

Napi::Value CompiledModelWrap::get_property(const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
std::vector<std::string> allowed_signatures;
try {
if (ov::js::validate<Napi::String>(info, allowed_signatures)) {
const auto property_name = info[0].As<Napi::String>().Utf8Value();
const auto property = _compiled_model.get_property(property_name);
return any_to_js(info, property);
} else {
OPENVINO_THROW("'getProperty'", ov::js::get_parameters_error_msg(info, allowed_signatures));
}
} catch (const std::exception& e) {
reportError(env, e.what());
}
return env.Undefined();
}
78 changes: 78 additions & 0 deletions src/bindings/js/node/tests/unit/compiled_model.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// -*- coding: utf-8 -*-
// Copyright (C) 2018-2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

const { addon: ov } = require('../..');
const assert = require('assert');
const { describe, it } = require('node:test');
const { getModelPath } = require('./utils.js');

const testXml = getModelPath().xml;
const core = new ov.Core();
const properties = {
"AUTO_BATCH_TIMEOUT": '1'
};
const compiledModel = core.compileModelSync(testXml, 'BATCH:CPU', properties);

describe('setProperty() / getProperty()', () => {

describe('getProperty()', () => {
it('returns the value of property from compiled model', () => {
assert.strictEqual(compiledModel.getProperty('AUTO_BATCH_TIMEOUT'), '1');
});
it('throws an error when called without arguments', () => {
assert.throws(
() => compiledModel.getProperty(),
/'getProperty' method called with incorrect parameters/
);
});
it('throws an error when called with property name that does not exists', ()=>{
assert.throws(
() => compiledModel.getProperty('PROPERTY_THAT_DOES_NOT_EXIST')
);
});
});

describe('setProperty()', () => {
it('sets a properties for compiled model', () => {
properties["AUTO_BATCH_TIMEOUT"] = '1000';
assert.doesNotThrow(() => compiledModel.setProperty(properties));
});

it('throws an error when called without an object argument', () => {
assert.throws(
() => compiledModel.setProperty(),
/'setProperty' method called with incorrect parameters/
);
});
it('throws an error when called with wrong argument', () => {
assert.throws(
() => compiledModel.setProperty(123),
/'setProperty' method called with incorrect parameters/
);
});

it('throws an error when called with multiple arguments', () => {
assert.throws(
() => compiledModel.setProperty({"PERFORMANCE_HINT": "THROUGHPUT"}, {"NUM_STREAMS": "AUTO"}),
/'setProperty' method called with incorrect parameters/
);
});

it('returns the set property of the compiled model', () => {
properties["AUTO_BATCH_TIMEOUT"] = '123';
compiledModel.setProperty(properties);
assert.strictEqual(compiledModel.getProperty('AUTO_BATCH_TIMEOUT'), 123);
});

it('retains the last set property when set multiple times', () => {
compiledModel.setProperty({"AUTO_BATCH_TIMEOUT": '321'});
compiledModel.setProperty({'AUTO_BATCH_TIMEOUT': '132'});
assert.strictEqual(compiledModel.getProperty('AUTO_BATCH_TIMEOUT'), 132);
});

it('allows to pass empty object', () => {
assert.doesNotThrow(() => compiledModel.setProperty({}));
});
});
});

0 comments on commit 98e4c36

Please sign in to comment.