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:
   ![high](https://www.gstatic.com/codereviewagent/high-priority.svg)
   
   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:
   ![medium](https://www.gstatic.com/codereviewagent/medium-priority.svg)
   
   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]

Reply via email to