|
4 | 4 |
|
5 | 5 | from collections import defaultdict |
6 | 6 |
|
7 | | -from haystack import Document, component |
| 7 | +from haystack import Document, component, logging |
8 | 8 | from haystack.utils.misc import _deduplicate_documents |
9 | 9 |
|
| 10 | +logger = logging.getLogger(__name__) |
| 11 | + |
10 | 12 |
|
11 | 13 | @component |
12 | 14 | class MetaFieldGroupingRanker: |
@@ -117,9 +119,21 @@ def run(self, documents: list[Document]) -> dict[str, list[Document]]: |
117 | 119 | for docs in subgroups.values(): |
118 | 120 | if sort_field: |
119 | 121 | # Sort by the field value, placing documents with a missing value last. |
120 | | - # The (is_missing, value) tuple ensures that only actual field values are |
121 | | - # compared, making the sort work for numbers, strings, and other types. |
122 | | - docs.sort(key=lambda d: (d.meta.get(sort_field) is None, d.meta.get(sort_field))) |
| 122 | + # The (is_missing, value) tuple keeps documents with a missing value out of the |
| 123 | + # value comparison, but two present values of mutually non-comparable types |
| 124 | + # (e.g. an int and a str) would still raise a TypeError. In that case we keep the |
| 125 | + # group's insertion order instead of crashing, mirroring MetaFieldRanker. |
| 126 | + try: |
| 127 | + docs.sort(key=lambda d: (d.meta.get(sort_field) is None, d.meta.get(sort_field))) |
| 128 | + except TypeError as error: |
| 129 | + logger.warning( |
| 130 | + "Tried to sort Documents with IDs {document_ids}, but got TypeError with the " |
| 131 | + "message: {error}\nKeeping the original order of the Documents in this group " |
| 132 | + "since sorting by '{sort_field}' is not possible.", |
| 133 | + document_ids=",".join([doc.id for doc in docs]), |
| 134 | + error=error, |
| 135 | + sort_field=sort_field, |
| 136 | + ) |
123 | 137 | ordered_docs.extend(docs) |
124 | 138 |
|
125 | 139 | ordered_docs.extend(no_group_docs) |
|
0 commit comments