def torch_value(obs, weights):
    """
    ppo critic to predict value
    :params:
        obs: observation
        weights: weights
    :return:
        value: value predicted by critic
    """
    with torch.no_grad():  # Disable gradient computation
        obs = torch.from_numpy(obs).float().unsqueeze(0).to(device)  # Convert to tensor and move to device
        weights = _expert_weights
        x = torch.matmul(obs, weights["default_policy/fc_value_1/kernel"]) + weights["default_policy/fc_value_1/bias"]
        x = torch.tanh(x)
        x = torch.matmul(x, weights["default_policy/fc_value_2/kernel"]) + weights["default_policy/fc_value_2/bias"]
        x = torch.tanh(x)
        x = torch.matmul(x, weights["default_policy/value_out/kernel"]) + weights["default_policy/value_out/bias"]
        return x.squeeze(0).cpu().numpy()  # Move back to CPU and remove batch dimension

    ppo critic to predict value
    :params:
        obs: observation
        weights: weights
    :return:
        value: value predicted by critic
    
metadrive/examples/ppo_expert/torch_expert.py