A variety of keras ops have paths that return objects of type OpenVINOKerasTensor
. For example
import keras.ops as ops
from typing import reveal_type
result = keras.ops.concatenate(...)
reveal_type(result) # OpenVINOKerasTensor
This is because the paths of this op route to backend.numpy.concatenate(...)
And backend.numpy.concatenate
has the following implementation:
def concatenate(xs, axis=0):
assert isinstance(xs, list), "`concatenate` is supported only for `x` list"
elems = []
for elem in xs:
elem = get_ov_output(elem)
elems.append(elem)
res = ov_opset.concat(elems, axis).output(0)
return OpenVINOKerasTensor(res)
However, when inspecting the definition of OpenVINOKerasTensor
here, it doesn't implement a variety of the __dunder__
methods expected (we see KerasTensor and frameworks like PyTorch, Jax, Numpy, and TFs objects all implement a much larger superset). Furthermore, it is missing an __array__
implementation, which is surprising of the return of any op coming from backend.numpy.some_operation
.
When working with framework code that is supposed to cleanly be interoperable with other frameworks, which is a large selling point of Keras 3.x, the minimum expectation should be to abide by the same interface defined by KerasTensor
, including overloads that are expected from non-symbolic tensors like __array__
with errors just like KerasTensor
has. The reason for this is that it makes it much easier to write properly typed downstream code with Protocol
s for things like ArrayLike
and TensorLike
. Right now, all such code will get typing errors for any ops
that have implementations through backend.numpy
, which is not ideal.