code: def test_qconv1d_gradient(tokens, embeddings, device):
      # We use a batch size of 1 to simplify gradient manual calculations
      batch_size = 1
      conv = Conv1D(embeddings, embeddings).to(device)
      qconv = QConv1D.from_module(conv)
      assert qconv.weight.requires_grad is True
      assert qconv.bias.requires_grad is True
      qinputs = random_qtensor(
          (batch_size,) + (tokens, embeddings), dtype=torch.float32
      ).to(device)
      qout = qconv(qinputs)
      gradient = torch.randn(qout.size()).to(device)
      qout.backward(gradient)
      # Compute gradients manually and compare
      bias_gradient = torch.sum(gradient, axis=[0, 1])
      assert torch.allclose(qconv.bias.grad, bias_gradient)
      # FIXME: gradient calculation is wrong because of the transposed weights
      weight_gradient = torch.matmul(
          gradient.squeeze().t(), qinputs.dequantize().squeeze()
      )
      assert torch.allclose(qconv.weight.grad, weight_gradient)
  
file_path: quanto/test/nn/test_custom_qmodule.py
imports: import os
  from tempfile import TemporaryDirectory
  import pytest
  import torch
  from helpers import q_assert_close, random_qtensor
  from quanto import Calibration, QModuleMixin, QTensor, freeze, register_qmodule
label_desc: Use image node_id 3 for calling a global function with example usage: test_qconv1d_gradient(tokens, embeddings, device) without return types