Skip to content

Commit

Permalink
Merge pull request openvinotoolkit#16 from mvafin/mvafin/pt_fe/str_attrs
Browse files Browse the repository at this point in the history
Support string constants as attributes
  • Loading branch information
slyalin authored Oct 6, 2022
2 parents 89281ad + ca66dc2 commit d5db627
Show file tree
Hide file tree
Showing 28 changed files with 398 additions and 377 deletions.
9 changes: 9 additions & 0 deletions src/bindings/python/src/openvino/frontend/pytorch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,15 @@ def as_constant (self):

return None

def as_string (self):
if not self.get_op_type() == 'prim::Constant':
return None
pt_value = self._raw_output(0)

if str(pt_value.type()) in ['torch.StringType', 'str']:
return pt_value.toIValue()
return None

def as_constant_tensor (self, pt_value):
# Constant interpretation doesn't respect new-full type of PT
# It recognizes only tensors, and give lists as 1D tensors, and scalars as Tensor scalars
Expand Down
14 changes: 7 additions & 7 deletions src/bindings/python/src/pyopenvino/frontend/frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
#include <pybind11/stl.h>
#include <pybind11/stl_bind.h>

#include "./pytorch/decoder.hpp"
#include "openvino/frontend/exception.hpp"
#include "openvino/frontend/extension/telemetry.hpp"
#include "openvino/frontend/manager.hpp"
#include "openvino/frontend/pytorch/decoder.hpp"
#include "pyopenvino/graph/model.hpp"
#include "pyopenvino/utils/utils.hpp"
#include "./pytorch/decoder.hpp"

namespace py = pybind11;

Expand All @@ -29,18 +29,18 @@ void regclass_frontend_FrontEnd(py::module m) {
[](FrontEnd& self, const py::object& path) {
// TODO: Extend to arbitrary number of any parameters, this code shouldn't gate FE universal load function
try {
//std::cout << "----------- trying to cast to path ------------ \n";
// std::cout << "----------- trying to cast to path ------------ \n";
std::string model_path = Common::utils::convert_path_to_string(path);
return self.load(model_path);
} catch (...) {
// Extended for one argument only for this time
// TODO: Remove this excplicit dependency on specific Pytorch FE dependent type
//std::cout << "++++++++++ trying to cast to Decoder+++++++++++\n";
//std::cout << path.get_type() << '\n';
if(py::isinstance<pytorch::Decoder>(path)) {
//std::cout << "********* bingo ************\n";
// std::cout << "++++++++++ trying to cast to Decoder+++++++++++\n";
// std::cout << path.get_type() << '\n';
if (py::isinstance<pytorch::Decoder>(path)) {
// std::cout << "********* bingo ************\n";
auto decoder = path.cast<std::shared_ptr<pytorch::Decoder>>();
//std::cout << "Decoder: " << decoder << "\n";
// std::cout << "Decoder: " << decoder << "\n";
return self.load({Any(decoder)});
}
// no idea what this object is, let it throw
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ namespace py = pybind11;
OutputVector as_constant () override
{ PYBIND11_OVERRIDE_PURE(OutputVector, Decoder, as_constant); }

std::string as_string () override
{ PYBIND11_OVERRIDE_PURE(std::string, Decoder, as_string); }

std::string get_op_type() const override
{ PYBIND11_OVERRIDE_PURE(std::string, Decoder, get_op_type); }

Expand Down
31 changes: 14 additions & 17 deletions src/bindings/python/src/pyopenvino/utils/utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#include "pyopenvino/utils/utils.hpp"

#include "openvino/frontend/pytorch/decoder.hpp"

#include <pybind11/stl.h>

#include <map>
Expand All @@ -14,6 +12,7 @@
#include <vector>

#include "Python.h"
#include "openvino/frontend/pytorch/decoder.hpp"

namespace Common {
namespace utils {
Expand Down Expand Up @@ -140,13 +139,11 @@ std::string convert_path_to_string(const py::object& path) {
}; // namespace Common

ov::Any py_object_to_any(const py::object& py_obj) {

// TODO: Investigate if there is a better alternative for converting any registered pybind11 type
// Just listing all known types here looks a double work as we have already registed a lot of OV types
// in other pybind11 definitions.
// Another option is to not unpack pybind object until ov::Any is casted.


// Python types
if (py::isinstance<py::str>(py_obj)) {
return py_obj.cast<std::string>();
Expand Down Expand Up @@ -180,18 +177,18 @@ ov::Any py_object_to_any(const py::object& py_obj) {
}

switch (detected_type) {
case PY_TYPE::STR:
return _list.cast<std::vector<std::string>>();
case PY_TYPE::FLOAT:
return _list.cast<std::vector<double>>();
case PY_TYPE::INT:
return _list.cast<std::vector<int64_t>>();
case PY_TYPE::BOOL:
return _list.cast<std::vector<bool>>();
default:
OPENVINO_ASSERT(false, "Unsupported attribute type.");
case PY_TYPE::STR:
return _list.cast<std::vector<std::string>>();
case PY_TYPE::FLOAT:
return _list.cast<std::vector<double>>();
case PY_TYPE::INT:
return _list.cast<std::vector<int64_t>>();
case PY_TYPE::BOOL:
return _list.cast<std::vector<bool>>();
default:
OPENVINO_ASSERT(false, "Unsupported attribute type.");
}
// OV types
// OV types
} else if (py::isinstance<ov::Any>(py_obj)) {
return py::cast<ov::Any>(py_obj);
} else if (py::isinstance<ov::element::Type>(py_obj)) {
Expand All @@ -208,14 +205,14 @@ ov::Any py_object_to_any(const py::object& py_obj) {
return py::cast<ov::streams::Num>(py_obj);
} else if (py::isinstance<ov::Affinity>(py_obj)) {
return py::cast<ov::Affinity>(py_obj);
// Custom PT FE Types
// Custom PT FE Types
} else if (py::isinstance<ov::frontend::pytorch::Type::Tensor>(py_obj)) {
std::cout << "[ ANY PYBIND ] Detected Tensor\n";
return py::cast<ov::frontend::pytorch::Type::Tensor>(py_obj);
} else if (py::isinstance<ov::frontend::pytorch::Type::List>(py_obj)) {
std::cout << "[ ANY PYBIND ] Detected List\n";
return py::cast<ov::frontend::pytorch::Type::List>(py_obj);
// If there is no match fallback to py::object
// If there is no match fallback to py::object
} else if (py::isinstance<py::object>(py_obj)) {
return py_obj;
}
Expand Down
5 changes: 3 additions & 2 deletions src/core/include/openvino/core/descriptor/tensor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,11 @@ class OPENVINO_API Tensor {
}
/// \brief Returns custom description of element type if element type is set to ov::element::custom
const ov::Any get_custom_element_type() const {
if(get_element_type() == ov::element::custom) {
if (get_element_type() == ov::element::custom) {
return m_custom_element_type;
} else {
throw std::runtime_error("Attempt to query custom data type description for description::Tensor which doesn't have a custom element type");
throw std::runtime_error("Attempt to query custom data type description for description::Tensor which "
"doesn't have a custom element type");
}
}
const Shape& get_shape() const;
Expand Down
3 changes: 2 additions & 1 deletion src/core/include/openvino/core/node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ class OPENVINO_API Node : public std::enable_shared_from_this<Node> {
void set_output_type(size_t i, const element::Type& element_type, const PartialShape& pshape);

/// Set custom output type, usually it is not a tensor, so pshape is set as for a scalar by default
// TODO: prefer using set_output_type but it conflicts with original function apparently because ov::Any has too generic ctor
// TODO: prefer using set_output_type but it conflicts with original function apparently because ov::Any has too
// generic ctor
void set_custom_output_type(size_t i, ov::Any custom_element_type, const PartialShape& pshape = PartialShape());

/// Sets the number of outputs
Expand Down
4 changes: 2 additions & 2 deletions src/core/include/openvino/core/type/element_type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class OPENVINO_API Type {
Type(const Type&) = default;
constexpr Type(const Type_t t) : m_type{t} {}
Type(size_t bitwidth, bool is_real, bool is_signed, bool is_quantized, const std::string& cname);
//explicit Type(const Any& custom_type);
// explicit Type(const Any& custom_type);
Type& operator=(const Type&) = default;
std::string c_type_string() const;
size_t size() const;
Expand Down Expand Up @@ -119,7 +119,7 @@ class OPENVINO_API Type {

private:
Type_t m_type{Type_t::undefined};
//Any m_custom_type;
// Any m_custom_type;
};

using TypeVector = std::vector<Type>;
Expand Down
2 changes: 1 addition & 1 deletion src/core/include/openvino/op/parameter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class OPENVINO_API Parameter : public op::Op {
Parameter(const ov::element::Type& element_type, const PartialShape& pshape);

Parameter(const ov::element::Type& element_type, const ov::Any& element_custom_type, const PartialShape& pshape);

bool visit_attributes(AttributeVisitor& visitor) override;

void validate_and_infer_types() override;
Expand Down
13 changes: 8 additions & 5 deletions src/core/src/descriptor/tensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ ov::descriptor::Tensor::Tensor(const element::Type& element_type, const PartialS

ov::descriptor::Tensor::Tensor(const ov::Any& custom_element_type, const PartialShape& pshape, const std::string& name)
: ov::descriptor::Tensor::Tensor(ov::element::custom, pshape, name) {
this->m_custom_element_type = custom_element_type;
}
this->m_custom_element_type = custom_element_type;
}

ov::descriptor::Tensor::Tensor(const ov::element::Type& element_type,
const PartialShape& pshape,
Expand All @@ -27,10 +27,13 @@ ov::descriptor::Tensor::Tensor(const ov::element::Type& element_type,
m_partial_shape(pshape),
m_shape_changed(true) {}

ov::descriptor::Tensor::Tensor(const ov::Any& custom_element_type, const PartialShape& pshape, Node* node, size_t node_output_number)
ov::descriptor::Tensor::Tensor(const ov::Any& custom_element_type,
const PartialShape& pshape,
Node* node,
size_t node_output_number)
: ov::descriptor::Tensor::Tensor(element::custom, pshape, node, node_output_number) {
this->m_custom_element_type = custom_element_type;
}
this->m_custom_element_type = custom_element_type;
}

OPENVINO_SUPPRESS_DEPRECATED_START
void ov::descriptor::Tensor::set_tensor_type(const element::Type& element_type, const PartialShape& pshape) {
Expand Down
17 changes: 10 additions & 7 deletions src/core/src/op/parameter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,18 @@ op::Parameter::Parameter(const element::Type& element_type, const ov::PartialSha
constructor_validate_and_infer_types();
}


op::Parameter::Parameter(const element::Type& element_type, const ov::Any& element_custom_type, const ov::PartialShape& pshape)
op::Parameter::Parameter(const element::Type& element_type,
const ov::Any& element_custom_type,
const ov::PartialShape& pshape)
: m_partial_shape(pshape),
m_is_relevant_to_shapes(false) {
OPENVINO_ASSERT(element_type == element::custom, "Parameter ctor with 3 arguments accept element_type = element::custom only");
// If element_type is custom, it doesn't mean that it is really custom, it may be just a way to hide normal type under Any
// In some circumstances it is simpler to wrap a regular type in Any and then pass through multi-layer API that works with Any only
OPENVINO_ASSERT(element_type == element::custom,
"Parameter ctor with 3 arguments accept element_type = element::custom only");
// If element_type is custom, it doesn't mean that it is really custom, it may be just a way to hide normal type
// under Any In some circumstances it is simpler to wrap a regular type in Any and then pass through multi-layer API
// that works with Any only
std::cout << "Parameter of custom type: attempt to detect simple type\n";
if(element_custom_type.is<element::Type>()) {
if (element_custom_type.is<element::Type>()) {
std::cout << "Parameter of custom type is simple type: " << element_custom_type.as<element::Type>() << "\n";
m_element_type = element_custom_type.as<element::Type>();
} else {
Expand All @@ -50,7 +53,7 @@ bool op::Parameter::visit_attributes(AttributeVisitor& visitor) {
void op::Parameter::validate_and_infer_types() {
NGRAPH_OP_SCOPE(v0_Parameter_validate_and_infer_types);
Op::validate_and_infer_types();
if(m_element_type == element::custom) {
if (m_element_type == element::custom) {
set_custom_output_type(0, m_element_custom_type, m_partial_shape);
} else {
set_output_type(0, m_element_type, m_partial_shape);
Expand Down
2 changes: 1 addition & 1 deletion src/core/src/op/util/framework_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

#include "openvino/op/util/framework_node.hpp"

#include "ngraph/graph_util.hpp"
#include "itt.hpp"
#include "ngraph/graph_util.hpp"

BWDCMP_RTTI_DEFINITION(ov::op::util::FrameworkNode);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
namespace ov {
namespace frontend {


class FRONTEND_API NodeContext {
public:
// TODO: Why this ctor is explicit when get_op_type is virtual so m_op_type looks to be a custom implementation
Expand Down
Loading

0 comments on commit d5db627

Please sign in to comment.