def bind_kv_io(self, io_binding: "IOBinding"):
        """Bind the cache tensors to the IO binding object.

        Past key-value tensors are bound as inputs and present key-value tensors are bound as outputs.
        During prompt processing, the past key-value tensors have length 0 and the present key-value tensors
            will be allocated dynamically by the session.
        During token generation, the past key-value tensors have length max_cache_len and the present key-value tensors
            have length max_cache_len + 1. Appropriate attention mask should be applied to the key-value tensors to mask
            out padded key-value tensors from previous steps and the unused slots.

        :param io_binding: IOBinding object to bind the cache tensors.
        """
        if self.seen_len == 0:
            # just use ort value since we don't need to access this after prompt processing
            for k in self.past_names:
                io_binding.bind_ortvalue_input(
                    k, self.get_empty_ortvalue(self.batch_size, self.num_kv_heads, 0, self.head_dim)
                )
            for k in self.present_names:
                io_binding.bind_output(k, self.device, self.device_id)
            return

        for k, v in self.cache.items():
            if self.backend == "torch":
                io_binding.bind_input(
                    name=k,
                    device_type=self.device,
                    device_id=self.device_id,
                    element_type=self.dtype,
                    shape=tuple(v.shape),
                    buffer_ptr=v.data_ptr(),
                )
            else:
                io_binding.bind_ortvalue_input(k, v)
        for k, v in self.output_cache.items():
            if self.backend == "torch":
                io_binding.bind_output(
                    name=k,
                    device_type=self.device,
                    device_id=self.device_id,
                    element_type=self.dtype,
                    shape=tuple(v.shape),
                    buffer_ptr=v.data_ptr(),
                )
            else:
                io_binding.bind_ortvalue_output(k, v)
Bind the cache tensors to the IO binding object.

        Past key-value tensors are bound as inputs and present key-value tensors are bound as outputs.
        During prompt processing, the past key-value tensors have length 0 and the present key-value tensors
            will be allocated dynamically by the session.
        During token generation, the past key-value tensors have length max_cache_len and the present key-value tensors
            have length max_cache_len + 1. Appropriate attention mask should be applied to the key-value tensors to mask
            out padded key-value tensors from previous steps and the unused slots.

        :param io_binding: IOBinding object to bind the cache tensors.
        
examples/utils/kv_cache_utils.py