We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Feature Request] More general metrics
I find the metrics to be a bit limited as one might want to pass additional options (even tensors) to the loss.
For instance in recurrent models with different sequence lengths, one would use a mask to avoid counting errors on padded time steps.
The mask is necessary in the loss to know which outputs to use in the final averaging/ loss.
[Feature Request] More general metrics
I find the metrics to be a bit limited as one might want to pass additional options (even tensors) to the loss.
For instance in recurrent models with different sequence lengths, one would use a mask to avoid counting errors on padded time steps.
The mask is necessary in the loss to know which outputs to use in the final averaging/ loss.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ignite/metrics/loss.py`
Content:
```
1 from __future__ import division
2 
3 from ignite.exceptions import NotComputableError
4 from ignite.metrics.metric import Metric
5 
6 
7 class Loss(Metric):
8     """
9     Calculates the average loss according to the passed loss_fn.
10 
11     - `loss_fn` must return the average loss over all observations in the batch.
12     - `update` must receive output of the form `(y_pred, y)`.
13     """
14     def __init__(self, loss_fn, output_transform=lambda x: x):
15         super(Loss, self).__init__(output_transform)
16         self._loss_fn = loss_fn
17 
18     def reset(self):
19         self._sum = 0
20         self._num_examples = 0
21 
22     def update(self, output):
23         y_pred, y = output
24         average_loss = self._loss_fn(y_pred, y)
25         assert len(average_loss.shape) == 0, '`loss_fn` did not return the average loss'
26         self._sum += average_loss.item() * y.shape[0]
27         self._num_examples += y.shape[0]
28 
29     def compute(self):
30         if self._num_examples == 0:
31             raise NotComputableError(
32                 'Loss must have at least one example before it can be computed')
33         return self._sum / self._num_examples
34
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/ignite/metrics/loss.py b/ignite/metrics/loss.py
--- a/ignite/metrics/loss.py
+++ b/ignite/metrics/loss.py
@@ -8,9 +8,21 @@
     """
     Calculates the average loss according to the passed loss_fn.
 
-    - `loss_fn` must return the average loss over all observations in the batch.
-    - `update` must receive output of the form `(y_pred, y)`.
+    Args:
+        loss_fn (callable): a callable taking a prediction tensor, a target
+            tensor, optionally other arguments, and returns the average loss
+            over all observations in the batch.
+        output_transform (callable): a callable that is used to transform the
+            :class:`ignite.engine.Engine`'s `process_function`'s output into the
+            form expected by the metric.
+            This can be useful if, for example, you have a multi-output model and
+            you want to compute the metric with respect to one of the outputs.
+            The output is is expected to be a tuple (prediction, target) or
+            (prediction, target, kwargs) where kwargs is a dictionary of extra
+            keywords arguments.
+
     """
+
     def __init__(self, loss_fn, output_transform=lambda x: x):
         super(Loss, self).__init__(output_transform)
         self._loss_fn = loss_fn
@@ -20,8 +32,12 @@
         self._num_examples = 0
 
     def update(self, output):
-        y_pred, y = output
-        average_loss = self._loss_fn(y_pred, y)
+        if len(output) == 2:
+            y_pred, y = output
+            kwargs = {}
+        else:
+            y_pred, y, kwargs = output
+        average_loss = self._loss_fn(y_pred, y, **kwargs)
         assert len(average_loss.shape) == 0, '`loss_fn` did not return the average loss'
         self._sum += average_loss.item() * y.shape[0]
         self._num_examples += y.shape[0]

{"golden_diff": "diff --git a/ignite/metrics/loss.py b/ignite/metrics/loss.py\n--- a/ignite/metrics/loss.py\n+++ b/ignite/metrics/loss.py\n@@ -8,9 +8,21 @@\n     \"\"\"\n     Calculates the average loss according to the passed loss_fn.\n \n-    - `loss_fn` must return the average loss over all observations in the batch.\n-    - `update` must receive output of the form `(y_pred, y)`.\n+    Args:\n+        loss_fn (callable): a callable taking a prediction tensor, a target\n+            tensor, optionally other arguments, and returns the average loss\n+            over all observations in the batch.\n+        output_transform (callable): a callable that is used to transform the\n+            :class:`ignite.engine.Engine`'s `process_function`'s output into the\n+            form expected by the metric.\n+            This can be useful if, for example, you have a multi-output model and\n+            you want to compute the metric with respect to one of the outputs.\n+            The output is is expected to be a tuple (prediction, target) or\n+            (prediction, target, kwargs) where kwargs is a dictionary of extra\n+            keywords arguments.\n+\n     \"\"\"\n+\n     def __init__(self, loss_fn, output_transform=lambda x: x):\n         super(Loss, self).__init__(output_transform)\n         self._loss_fn = loss_fn\n@@ -20,8 +32,12 @@\n         self._num_examples = 0\n \n     def update(self, output):\n-        y_pred, y = output\n-        average_loss = self._loss_fn(y_pred, y)\n+        if len(output) == 2:\n+            y_pred, y = output\n+            kwargs = {}\n+        else:\n+            y_pred, y, kwargs = output\n+        average_loss = self._loss_fn(y_pred, y, **kwargs)\n         assert len(average_loss.shape) == 0, '`loss_fn` did not return the average loss'\n         self._sum += average_loss.item() * y.shape[0]\n         self._num_examples += y.shape[0]\n", "issue": "[Feature Request] More general metrics\nI find the metrics to be a bit limited as one might want to pass additional options (even tensors) to the loss.\r\nFor instance in recurrent models with different sequence lengths, one would use a mask to avoid counting errors on padded time steps.\r\nThe mask is necessary in the loss to know which outputs to use in the final averaging/ loss.\n[Feature Request] More general metrics\nI find the metrics to be a bit limited as one might want to pass additional options (even tensors) to the loss.\r\nFor instance in recurrent models with different sequence lengths, one would use a mask to avoid counting errors on padded time steps.\r\nThe mask is necessary in the loss to know which outputs to use in the final averaging/ loss.\n", "before_files": [{"content": "from __future__ import division\n\nfrom ignite.exceptions import NotComputableError\nfrom ignite.metrics.metric import Metric\n\n\nclass Loss(Metric):\n    \"\"\"\n    Calculates the average loss according to the passed loss_fn.\n\n    - `loss_fn` must return the average loss over all observations in the batch.\n    - `update` must receive output of the form `(y_pred, y)`.\n    \"\"\"\n    def __init__(self, loss_fn, output_transform=lambda x: x):\n        super(Loss, self).__init__(output_transform)\n        self._loss_fn = loss_fn\n\n    def reset(self):\n        self._sum = 0\n        self._num_examples = 0\n\n    def update(self, output):\n        y_pred, y = output\n        average_loss = self._loss_fn(y_pred, y)\n        assert len(average_loss.shape) == 0, '`loss_fn` did not return the average loss'\n        self._sum += average_loss.item() * y.shape[0]\n        self._num_examples += y.shape[0]\n\n    def compute(self):\n        if self._num_examples == 0:\n            raise NotComputableError(\n                'Loss must have at least one example before it can be computed')\n        return self._sum / self._num_examples\n", "path": "ignite/metrics/loss.py"}], "after_files": [{"content": "from __future__ import division\n\nfrom ignite.exceptions import NotComputableError\nfrom ignite.metrics.metric import Metric\n\n\nclass Loss(Metric):\n    \"\"\"\n    Calculates the average loss according to the passed loss_fn.\n\n    Args:\n        loss_fn (callable): a callable taking a prediction tensor, a target\n            tensor, optionally other arguments, and returns the average loss\n            over all observations in the batch.\n        output_transform (callable): a callable that is used to transform the\n            :class:`ignite.engine.Engine`'s `process_function`'s output into the\n            form expected by the metric.\n            This can be useful if, for example, you have a multi-output model and\n            you want to compute the metric with respect to one of the outputs.\n            The output is is expected to be a tuple (prediction, target) or\n            (prediction, target, kwargs) where kwargs is a dictionary of extra\n            keywords arguments.\n\n    \"\"\"\n\n    def __init__(self, loss_fn, output_transform=lambda x: x):\n        super(Loss, self).__init__(output_transform)\n        self._loss_fn = loss_fn\n\n    def reset(self):\n        self._sum = 0\n        self._num_examples = 0\n\n    def update(self, output):\n        if len(output) == 2:\n            y_pred, y = output\n            kwargs = {}\n        else:\n            y_pred, y, kwargs = output\n        average_loss = self._loss_fn(y_pred, y, **kwargs)\n        assert len(average_loss.shape) == 0, '`loss_fn` did not return the average loss'\n        self._sum += average_loss.item() * y.shape[0]\n        self._num_examples += y.shape[0]\n\n    def compute(self):\n        if self._num_examples == 0:\n            raise NotComputableError(\n                'Loss must have at least one example before it can be computed')\n        return self._sum / self._num_examples\n", "path": "ignite/metrics/loss.py"}]}