def _make_autoencoder_latent_grad_wrt_input_scalar_deriver_helper(
    dst_config: DstConfig,
    output_dst: DerivedScalarType,
    node_type: NodeType | None = None,
) -> ScalarDeriver:
    """Compute the gradient from a particular autoencoder latent, with respect to the
    autoencoder input directions.

    Requires:
    >>> dst_config.layer_indices = [layer_index]
    >>> dst_config.trace_config.tensor_indices = ("All", latent_index)
    """
    # import here to avoid circular import
    from neuron_explainer.activations.derived_scalars.make_scalar_derivers import (
        make_scalar_deriver,
    )

    trace_config = dst_config.trace_config
    assert trace_config is not None
    assert trace_config.node_type in [
        NodeType.AUTOENCODER_LATENT,
        NodeType.MLP_AUTOENCODER_LATENT,
        NodeType.ATTENTION_AUTOENCODER_LATENT,
        NodeType.AUTOENCODER_LATENT_BY_TOKEN_PAIR,
    ]
    assert trace_config.tensor_indices[0] == "All"
    assert isinstance(trace_config.tensor_indices[1], int)
    latent_index_for_grad = trace_config.tensor_indices[1]
    layer_index = trace_config.layer_index
    assert layer_index is not None
    if dst_config.layer_indices is not None:
        assert [layer_index] == dst_config.layer_indices

    autoencoder_context = dst_config.get_autoencoder_context(node_type)
    assert autoencoder_context is not None
    autoencoder_dst = autoencoder_context.dst
    autoencoder_dst = maybe_convert_autoencoder_dst(autoencoder_dst)
    scalar_deriver = make_scalar_deriver(autoencoder_dst, dst_config)
    apply_autoencoder = make_apply_autoencoder(autoencoder_context, use_no_grad=False)

    def new_tensor_calculate_derived_scalar_fn(
        derived_scalar_tensor: torch.Tensor,
    ) -> torch.Tensor:
        derived_scalar_tensor = detach_and_clone(derived_scalar_tensor, requires_grad=True)
        latents = apply_autoencoder(derived_scalar_tensor, layer_index)
        latents[:, latent_index_for_grad].sum(dim=0).backward()  # sum over tokens
        assert derived_scalar_tensor.grad is not None
        return derived_scalar_tensor.grad

    new_scalar_deriver = scalar_deriver.apply_transform_fn_to_output(
        transform_fn=new_tensor_calculate_derived_scalar_fn,
        pass_type_to_transform=PassType.FORWARD,
        output_dst=output_dst,
    )
    return new_scalar_deriver
Compute the gradient from a particular autoencoder latent, with respect to the
    autoencoder input directions.

    Requires:
    >>> dst_config.layer_indices = [layer_index]
    >>> dst_config.trace_config.tensor_indices = ("All", latent_index)
    
neuron_explainer/activations/derived_scalars/autoencoder.py