gemini-code-assist[bot] commented on code in PR #19859:
URL: https://github.com/apache/tvm/pull/19859#discussion_r3449495811
##########
python/tvm/relax/frontend/tflite/tflite_frontend.py:
##########
@@ -6688,6 +6727,93 @@ def convert_embedding_lookup_sparse(self, op):
relax.op.greater(bucket_counts, relax.const(0.0, "float32")),
normalized, value_base
)
+ def convert_lsh_projection(self, op):
+ """Reject TFLite LSH_PROJECTION with a targeted diagnostic."""
+ from tflite.LSHProjectionOptions import LSHProjectionOptions
+ from tflite.LSHProjectionType import LSHProjectionType
+ from tflite.TensorType import TensorType
+
+ input_tensors = self.get_input_tensors(op)
+ output_tensors = self.get_output_tensors(op)
+ if len(input_tensors) not in (2, 3) or len(output_tensors) != 1:
+ raise tvm.error.OpNotImplemented(
+ "LSH_PROJECTION expects hash and input tensors, optional
weights, and one output"
+ )
+
+ hash_tensor, input_tensor = input_tensors[:2]
+ output_tensor = output_tensors[0]
+ hash_shape = to_int_list(self.get_tensor_shape(hash_tensor))
+ input_shape = to_int_list(self.get_tensor_shape(input_tensor))
+ output_shape = to_int_list(self.get_tensor_shape(output_tensor))
+ if hash_tensor.tensor.Type() != TensorType.FLOAT32:
+ raise tvm.error.OpNotImplemented("LSH_PROJECTION hash tensor must
be float32")
+ if len(hash_shape) != 2 or hash_shape[0] < 1 or hash_shape[1] > 32:
+ raise tvm.error.OpNotImplemented(
+ "LSH_PROJECTION hash tensor must be rank 2 with at most 32
bits"
+ )
+ if len(input_shape) < 1 or input_shape[0] < 1:
+ raise tvm.error.OpNotImplemented("LSH_PROJECTION input tensor must
be rank >= 1")
+ if len(input_tensors) == 3:
+ weight_tensor = input_tensors[2]
+ weight_shape = to_int_list(self.get_tensor_shape(weight_tensor))
+ if weight_tensor.tensor.Type() != TensorType.FLOAT32 or
weight_shape != [
+ input_shape[0]
+ ]:
+ raise tvm.error.OpNotImplemented(
+ "LSH_PROJECTION weights must be rank-1 float32 and match
input dimension 0"
+ )
Review Comment:

In TFLite, the third input tensor (weights) for `LSH_PROJECTION` is
optional. If it is omitted, `get_input_tensors` will return `None` for the
third element, resulting in `len(input_tensors) == 3` but `input_tensors[2] is
None`. Calling `self.get_tensor_shape(weight_tensor)` on `None` will raise an
`AttributeError` instead of handling it gracefully.
Additionally, to adhere to defensive programming practices, we should
explicitly check if the required `hash_tensor`, `input_tensor`, and
`output_tensor` are `None` before accessing their properties.
```python
hash_tensor, input_tensor = input_tensors[:2]
output_tensor = output_tensors[0]
if hash_tensor is None or input_tensor is None or output_tensor is
None:
raise tvm.error.OpNotImplemented(
"LSH_PROJECTION expects valid hash, input, and output
tensors"
)
hash_shape = to_int_list(self.get_tensor_shape(hash_tensor))
input_shape = to_int_list(self.get_tensor_shape(input_tensor))
output_shape = to_int_list(self.get_tensor_shape(output_tensor))
if hash_tensor.tensor.Type() != TensorType.FLOAT32:
raise tvm.error.OpNotImplemented("LSH_PROJECTION hash tensor
must be float32")
if len(hash_shape) != 2 or hash_shape[0] < 1 or hash_shape[1] > 32:
raise tvm.error.OpNotImplemented(
"LSH_PROJECTION hash tensor must be rank 2 with at most 32
bits"
)
if len(input_shape) < 1 or input_shape[0] < 1:
raise tvm.error.OpNotImplemented("LSH_PROJECTION input tensor
must be rank >= 1")
if len(input_tensors) == 3 and input_tensors[2] is not None:
weight_tensor = input_tensors[2]
weight_shape = to_int_list(self.get_tensor_shape(weight_tensor))
if weight_tensor.tensor.Type() != TensorType.FLOAT32 or
weight_shape != [
input_shape[0]
]:
raise tvm.error.OpNotImplemented(
"LSH_PROJECTION weights must be rank-1 float32 and match
input dimension 0"
)
```
##########
python/tvm/relax/frontend/tflite/tflite_frontend.py:
##########
@@ -6688,6 +6727,93 @@ def convert_embedding_lookup_sparse(self, op):
relax.op.greater(bucket_counts, relax.const(0.0, "float32")),
normalized, value_base
)
+ def convert_lsh_projection(self, op):
+ """Reject TFLite LSH_PROJECTION with a targeted diagnostic."""
+ from tflite.LSHProjectionOptions import LSHProjectionOptions
+ from tflite.LSHProjectionType import LSHProjectionType
+ from tflite.TensorType import TensorType
+
+ input_tensors = self.get_input_tensors(op)
+ output_tensors = self.get_output_tensors(op)
+ if len(input_tensors) not in (2, 3) or len(output_tensors) != 1:
+ raise tvm.error.OpNotImplemented(
+ "LSH_PROJECTION expects hash and input tensors, optional
weights, and one output"
+ )
+
+ hash_tensor, input_tensor = input_tensors[:2]
+ output_tensor = output_tensors[0]
+ hash_shape = to_int_list(self.get_tensor_shape(hash_tensor))
+ input_shape = to_int_list(self.get_tensor_shape(input_tensor))
+ output_shape = to_int_list(self.get_tensor_shape(output_tensor))
+ if hash_tensor.tensor.Type() != TensorType.FLOAT32:
+ raise tvm.error.OpNotImplemented("LSH_PROJECTION hash tensor must
be float32")
+ if len(hash_shape) != 2 or hash_shape[0] < 1 or hash_shape[1] > 32:
+ raise tvm.error.OpNotImplemented(
+ "LSH_PROJECTION hash tensor must be rank 2 with at most 32
bits"
+ )
+ if len(input_shape) < 1 or input_shape[0] < 1:
+ raise tvm.error.OpNotImplemented("LSH_PROJECTION input tensor must
be rank >= 1")
+ if len(input_tensors) == 3:
+ weight_tensor = input_tensors[2]
+ weight_shape = to_int_list(self.get_tensor_shape(weight_tensor))
+ if weight_tensor.tensor.Type() != TensorType.FLOAT32 or
weight_shape != [
+ input_shape[0]
+ ]:
+ raise tvm.error.OpNotImplemented(
+ "LSH_PROJECTION weights must be rank-1 float32 and match
input dimension 0"
+ )
+ if output_tensor.tensor.Type() != TensorType.INT32:
+ raise tvm.error.OpNotImplemented("LSH_PROJECTION output must be
int32")
+
+ op_options = op.BuiltinOptions()
+ if op_options is None:
+ raise tvm.error.OpNotImplemented("LSH_PROJECTION requires
LSHProjectionOptions")
+ lsh_options = LSHProjectionOptions()
+ lsh_options.Init(op_options.Bytes, op_options.Pos)
+ projection_type = lsh_options.Type()
+ if projection_type == LSHProjectionType.SPARSE:
+ expected_output_shape = [hash_shape[0]]
+ elif projection_type == LSHProjectionType.DENSE:
+ expected_output_shape = [hash_shape[0] * hash_shape[1]]
+ else:
+ raise tvm.error.OpNotImplemented("LSH_PROJECTION requires SPARSE
or DENSE type")
+ if output_shape != expected_output_shape:
+ raise tvm.error.OpNotImplemented(
+ "LSH_PROJECTION output shape must match the projection type"
+ )
+
+ raise tvm.error.OpNotImplemented(
+ "LSH_PROJECTION requires TFLite fingerprint hash semantics that
are not lowered "
+ "by the Relax TFLite frontend yet"
+ )
+
+ def convert_skip_gram(self, op):
+ """Reject TFLite SKIP_GRAM with a targeted diagnostic."""
+ from tflite.SkipGramOptions import SkipGramOptions
+
+ input_tensors = self.get_input_tensors(op)
+ output_tensors = self.get_output_tensors(op)
+ if len(input_tensors) != 1 or len(output_tensors) != 1:
+ raise tvm.error.OpNotImplemented("SKIP_GRAM expects one input and
one output")
+ if not self._is_tflite_string_type(input_tensors[0].tensor.Type()):
+ raise tvm.error.OpNotImplemented("SKIP_GRAM input must be
TensorType.STRING")
+ if not self._is_tflite_string_type(output_tensors[0].tensor.Type()):
+ raise tvm.error.OpNotImplemented("SKIP_GRAM output must be
TensorType.STRING")
Review Comment:

To adhere to defensive programming practices, we should explicitly check if
the required input and output tensors are `None` before accessing their
properties (e.g., `.tensor.Type()`).
```suggestion
if input_tensors[0] is None or output_tensors[0] is None:
raise tvm.error.OpNotImplemented("SKIP_GRAM expects valid input
and output tensors")
if not self._is_tflite_string_type(input_tensors[0].tensor.Type()):
raise tvm.error.OpNotImplemented("SKIP_GRAM input must be
TensorType.STRING")
if not self._is_tflite_string_type(output_tensors[0].tensor.Type()):
raise tvm.error.OpNotImplemented("SKIP_GRAM output must be
TensorType.STRING")
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]