Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PyOV] Add more ov.Model constructors #25635

Merged
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 95 additions & 4 deletions src/bindings/python/src/pyopenvino/graph/model.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,22 @@ static void set_tensor_names(const ov::ParameterVector& parameters) {
}
}

static ov::SinkVector cast_to_sink_vector(const std::vector<std::shared_ptr<ov::Node>>& nodes) {
static std::shared_ptr<ov::Node> get_node_ptr(std::shared_ptr<ov::Node> node) {
return node;
}

static std::shared_ptr<ov::Node> get_node_ptr(const ov::Output<ov::Node>& output) {
return output.get_node_shared_ptr();
}

template <typename T>
ov::SinkVector cast_to_sink_vector(const std::vector<T>& items) {
ov::SinkVector sinks;
for (const auto& node : nodes) {
auto sink = std::dynamic_pointer_cast<ov::op::Sink>(node);
sinks.reserve(items.size());
for (const auto& item : items) {
auto sink = std::dynamic_pointer_cast<ov::op::Sink>(get_node_ptr(item));
OPENVINO_ASSERT(sink != nullptr, "Node {} is not instance of Sink");
sinks.push_back(sink);
sinks.push_back(std::move(sink));
}
return sinks;
}
Expand Down Expand Up @@ -256,9 +266,90 @@ void regclass_graph_Model(py::module m) {
:type results: List[openvino.runtime.Output]
:param sinks: List of Nodes to be used as Sinks (e.g. Assign ops).
:type sinks: List[openvino.runtime.Node]
:param parameters: List of parameters.
:type parameters: List[op.Parameter]
:param name: String to set as model's friendly name.
:type name: str
)");

model.def(py::init([](const ov::OutputVector& results,
const ov::OutputVector& nodes,
const ov::ParameterVector& parameters,
py::object& variables,
const std::string& name) {
set_tensor_names(parameters);
const auto sinks = cast_to_sink_vector(nodes);
if (py::isinstance<py::none>(variables)) {
auto model = std::make_shared<ov::Model>(results, sinks, parameters, name);
set_correct_variables_for_assign_ops(model, sinks);
return model;
} else {
return std::make_shared<ov::Model>(results,
sinks,
parameters,
variables.cast<ov::op::util::VariableVector>(),
name);
}
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("variables") = py::none(),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model

:param results: List of outputs.
:type results: List[openvino.runtime.Output]
:param sinks: List of Output sink node handles.
:type sinks: List[openvino.runtime.Output]
:param parameters: List of parameters.
:type parameters: List[op.Parameter]
:param variables: List of variables.
:type variables: List[op.util.Variable]
:param name: String to set as model's friendly name.
:type name: str
)");

model.def(py::init([](const ov::ResultVector& results,
const ov::OutputVector& nodes,
const ov::ParameterVector& parameters,
const py::object& variables,
const std::string& name) {
set_tensor_names(parameters);
const auto sinks = cast_to_sink_vector(nodes);
if (py::isinstance<py::none>(variables)) {
auto model = std::make_shared<ov::Model>(results, sinks, parameters, name);
set_correct_variables_for_assign_ops(model, sinks);
return model;
} else {
return std::make_shared<ov::Model>(results,
sinks,
parameters,
variables.cast<ov::op::util::VariableVector>(),
name);
}
}),
py::arg("results"),
py::arg("sinks"),
py::arg("parameters"),
py::arg("variables") = py::none(),
py::arg("name") = "",
R"(
Create user-defined Model which is a representation of a model

:param results: List of results.
:type results: List[op.Result]
:param sinks: List of Output sink node handles.
:type sinks: List[openvino.runtime.Output]
:param parameters: List of parameters.
:type parameters: List[op.Parameter]
:param variables: List of variables.
:type variables: List[op.util.Variable]
:param name: String to set as model's friendly name.
:type name: str
)");

model.def(py::init([](const ov::ResultVector& results,
const std::vector<std::shared_ptr<ov::Node>>& nodes,
const ov::ParameterVector& parameters,
Expand Down
47 changes: 47 additions & 0 deletions src/bindings/python/tests/test_runtime/test_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,53 @@ def test_get_sink_index(device):
)


def test_model_sink_ctors():
input_data = ops.parameter([2, 2], name="input_data", dtype=np.float32)
rv = ops.read_value("var_id_667", np.float32, [2, 2])
add = ops.add(rv, input_data, name="MemoryAdd")
node = ops.assign(add, "var_id_667")
res = ops.result(add, "res")

# Model(List[openvino._pyopenvino.op.Result], List[ov::Output<ov::Node>],
# List[openvino._pyopenvino.op.Parameter], str = '')
model = Model(results=[res], sinks=[node.output(0)], parameters=[input_data], name="TestModel")
model.validate_nodes_and_infer_types()
sinks = ["Assign"]
assert sinks == [sink.get_type_name() for sink in model.get_sinks()]
assert model.sinks[0].get_output_shape(0) == Shape([2, 2])

# Model(List[ov::Output<ov::Node>, List[ov::Output<ov::Node>],
# List[openvino._pyopenvino.op.Parameter], str = '')
model = Model(results=[model.output(0)], sinks=[node.output(0)], parameters=[input_data], name="TestModel")
model.validate_nodes_and_infer_types()
assert model.sinks[0].get_output_shape(0) == Shape([2, 2])
assert sinks == [sink.get_type_name() for sink in model.get_sinks()]

var_info = VariableInfo()
var_info.data_shape = PartialShape([2, 2])
var_info.data_type = Type.f32
var_info.variable_id = "v1"
variable_1 = Variable(var_info)
rv = ops.read_value(variable_1)
add = ops.add(rv, input_data, name="MemoryAdd")
assign = ops.assign(add, variable_1)
res = ops.result(add, "res")

# Model(List[openvino._pyopenvino.op.Result], List[ov::Output<ov::Node>],
# List[openvino._pyopenvino.op.Parameter], List[openvino._pyopenvino.op.util.Variable], str = '')
model = Model(results=[res], sinks=[assign.output(0)], parameters=[input_data], variables=[variable_1], name="TestModel")
model.validate_nodes_and_infer_types()
assert model.sinks[0].get_output_shape(0) == Shape([2, 2])
assert sinks == [sink.get_type_name() for sink in model.get_sinks()]

# Model(List[ov::Output<ov::Node>, List[ov::Output<ov::Node>],
# List[openvino._pyopenvino.op.Parameter], List[openvino._pyopenvino.op.util.Variable], str = '')
model = Model(results=[model.output(0)], sinks=[assign.output(0)], parameters=[input_data], variables=[variable_1], name="TestModel")
model.validate_nodes_and_infer_types()
assert model.sinks[0].get_output_shape(0) == Shape([2, 2])
assert sinks == [sink.get_type_name() for sink in model.get_sinks()]


@pytest.mark.parametrize(("args1", "args2", "expectation", "raise_msg"), [
(Tensor("float32", Shape([2, 1])),
[Tensor(np.array([2, 1], dtype=np.float32).reshape(2, 1)),
Expand Down
Loading