Repository navigation
feat: InMemoryExactNNIndex pre filtering #1713
Changes from 4 commits
273e94e
c90b1ff
8df5bc6
e4dab39
e96a72d
47a8d9b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| import os | ||
| import sys | ||
| from collections import defaultdict | ||
| from dataclasses import dataclass, field | ||
| from typing import ( | ||
|
|
@@ -22,10 +23,7 @@ | |
| from docarray.array.any_array import AnyDocArray | ||
| from docarray.helper import _shallow_copy_doc | ||
| from docarray.index.abstract import BaseDocIndex, _raise_not_supported | ||
| from docarray.index.backends.helper import ( | ||
| _collect_query_args, | ||
| _execute_find_and_filter_query, | ||
| ) | ||
| from docarray.index.backends.helper import _collect_query_args | ||
| from docarray.typing import AnyTensor, NdArray | ||
| from docarray.typing.tensor.abstract_tensor import AbstractTensor | ||
| from docarray.utils._internal._typing import safe_issubclass | ||
|
|
@@ -293,12 +291,51 @@ def execute_query(self, query: List[Tuple[str, Dict]], *args, **kwargs) -> Any: | |
| raise ValueError( | ||
| f'args and kwargs not supported for `execute_query` on {type(self)}' | ||
| ) | ||
| find_res = _execute_find_and_filter_query( | ||
| doc_index=self, | ||
| query=query, | ||
| reverse_order=True, | ||
| ) | ||
| return find_res | ||
| return self._find_and_filter(query) | ||
|
|
||
| def _find_and_filter(self, query: List[Tuple[str, Dict]]) -> FindResult: | ||
| """ | ||
| Executes a hybrid search on documents based on the provided query. | ||
|
|
||
| The function performs search operations such as 'find' and 'filter' in the order | ||
| they appear in the query. The 'find' operation performs a vector similarity search. | ||
| The 'filter' operation filters out documents based on a filter query. | ||
| The documents are finally sorted based on their scores. | ||
|
|
||
| :param query: The query to execute. | ||
| :return: A tuple of retrieved documents and their scores. | ||
| """ | ||
| out_docs = self._docs | ||
| doc_to_score: Dict[BaseDoc, Any] = {} | ||
| limit = sys.maxsize | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why don't u just do
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I refactored limit logic, uses whatever is passed, and if nothing's passed goes with len(out_docs) |
||
| for op, op_kwargs in query: | ||
| limit = min(limit, op_kwargs['limit']) if op_kwargs.get('limit') else limit | ||
| if op == 'find': | ||
| out_docs, scores = find( | ||
| index=out_docs, | ||
| query=op_kwargs['query'], | ||
| search_field=op_kwargs['search_field'], | ||
| limit=len(out_docs), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think limit should be the limit obtained or the ln(out_docs) if no limit present
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. good point, I think I made it too complicated |
||
| metric=self._column_infos[op_kwargs['search_field']].config[ | ||
| 'space' | ||
| ], | ||
| ) | ||
| doc_to_score.update(zip(out_docs.id, scores)) | ||
| elif op == 'filter': | ||
| out_docs = filter_docs(out_docs, op_kwargs['filter_query']) | ||
| else: | ||
| raise ValueError(f'Query operation is not supported: {op}') | ||
|
|
||
| # if limit was not provided, use the default | ||
| if limit == sys.maxsize: | ||
| limit = 10 | ||
|
|
||
| out_docs = out_docs[:limit] | ||
| scores_and_docs = zip([doc_to_score[doc.id] for doc in out_docs], out_docs) | ||
| sorted_lists = sorted(scores_and_docs, reverse=True) | ||
| out_scores, out_docs = zip(*sorted_lists) | ||
|
|
||
| return FindResult(documents=out_docs, scores=out_scores) | ||
|
|
||
| def find( | ||
| self, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
change docstring as well pls
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should keep this term, we (and not only us) use it in docs and even though most ppl think of bm25 when talking about hybrid search, this is not wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we use find and filter which is what it is