From 030c22e221fcd15be076a8d81f45cd0374c7bbab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ianar=C3=A9=20S=C3=A9vi?= Date: Fri, 11 Sep 2026 15:27:53 +0200 Subject: [PATCH] :memo: update docs for RAG search --- docs/client_mixin.rst | 7 ---- mindee/client_mixin.py | 23 ------------ mindee/client_options/polling_options.py | 20 +++++++++++ mindee/v1/client.py | 10 ++++-- mindee/v2/client.py | 9 ++--- .../rag_document_search_parameters.py | 13 +++++-- .../search/test_model_search_integration.py | 4 +-- .../test_rag_document_search_integration.py | 36 +++++++++++++++---- 8 files changed, 71 insertions(+), 51 deletions(-) delete mode 100644 docs/client_mixin.rst delete mode 100644 mindee/client_mixin.py diff --git a/docs/client_mixin.rst b/docs/client_mixin.rst deleted file mode 100644 index d8a9d424..00000000 --- a/docs/client_mixin.rst +++ /dev/null @@ -1,7 +0,0 @@ ------------- -Client Mixin ------------- - -.. autoclass:: mindee.client_mixin - :members: - :inherited-members: diff --git a/mindee/client_mixin.py b/mindee/client_mixin.py deleted file mode 100644 index 8a4c5753..00000000 --- a/mindee/client_mixin.py +++ /dev/null @@ -1,23 +0,0 @@ -from mindee.error import MindeeClientError - - -class ClientMixin: - """Mixin for clients V1 & V2 common static methods.""" - - @staticmethod - def _validate_async_params( - initial_delay_sec: float, delay_sec: float, max_retries: int - ) -> None: - min_delay = 1 - min_initial_delay = 1 - min_retries = 1 - if delay_sec < min_delay: - raise MindeeClientError( - f"Cannot set auto-parsing delay to less than {min_delay} second(s)." - ) - if initial_delay_sec < min_initial_delay: - raise MindeeClientError( - f"Cannot set initial parsing delay to less than {min_initial_delay} second(s)." - ) - if max_retries < min_retries: - raise MindeeClientError(f"Cannot set retries to less than {min_retries}.") diff --git a/mindee/client_options/polling_options.py b/mindee/client_options/polling_options.py index 9da22362..4fab1edc 100644 --- a/mindee/client_options/polling_options.py +++ b/mindee/client_options/polling_options.py @@ -1,3 +1,6 @@ +from mindee.error import MindeeClientError + + class PollingOptions: """Options for asynchronous polling.""" @@ -17,3 +20,20 @@ def __init__( self.initial_delay_sec = initial_delay_sec self.delay_sec = delay_sec self.max_retries = max_retries + + def validate_settings(self) -> None: + """Validates polling options against minimum accepted values.""" + + min_delay = 1 + min_initial_delay = 1 + min_retries = 1 + if self.delay_sec < min_delay: + raise MindeeClientError( + f"Cannot set auto-parsing delay to less than {min_delay} second(s)." + ) + if self.initial_delay_sec < min_initial_delay: + raise MindeeClientError( + f"Cannot set initial parsing delay to less than {min_initial_delay} second(s)." + ) + if self.max_retries < min_retries: + raise MindeeClientError(f"Cannot set retries to less than {min_retries}.") diff --git a/mindee/v1/client.py b/mindee/v1/client.py index a6ff7b51..f19ee451 100644 --- a/mindee/v1/client.py +++ b/mindee/v1/client.py @@ -2,7 +2,7 @@ import httpx -from mindee.client_mixin import ClientMixin +from mindee.client_options.polling_options import PollingOptions from mindee.error.mindee_error import MindeeClientError, MindeeError from mindee.error.mindee_http_error import handle_error from mindee.input.local_input_source import LocalInputSource @@ -53,7 +53,7 @@ def _clean_account_name(account_name: str) -> str: return account_name -class Client(ClientMixin): +class Client: """ Mindee API Client. @@ -353,7 +353,11 @@ def enqueue_and_parse( # pylint: disable=too-many-locals :param rag: If set, will enable Retrieval-Augmented Generation. Only works if a valid ``workflow_id`` is set. """ - self._validate_async_params(initial_delay_sec, delay_sec, max_retries) + PollingOptions( + initial_delay_sec=initial_delay_sec, + delay_sec=delay_sec, + max_retries=max_retries, + ).validate_settings() if not endpoint: endpoint = self._initialize_ots_endpoint(product_class=product_class) queue_result = self.enqueue( diff --git a/mindee/v2/client.py b/mindee/v2/client.py index 9fc6bebd..b5b89fc1 100644 --- a/mindee/v2/client.py +++ b/mindee/v2/client.py @@ -4,7 +4,6 @@ import httpx -from mindee.client_mixin import ClientMixin from mindee.client_options.polling_options import PollingOptions from mindee.error.mindee_error import MindeeError from mindee.input import URLInputSource @@ -27,7 +26,7 @@ ) -class Client(ClientMixin): +class Client: """ Mindee API Client. @@ -127,11 +126,7 @@ def enqueue_and_get_result( """ if not params.polling_options: params.polling_options = PollingOptions() - self._validate_async_params( - params.polling_options.initial_delay_sec, - params.polling_options.delay_sec, - params.polling_options.max_retries, - ) + params.polling_options.validate_settings() enqueue_response = self.enqueue(input_source, params) logger.debug( "Successfully enqueued document with job ID: %s", enqueue_response.job.id diff --git a/mindee/v2/search/rag_documents/rag_document_search_parameters.py b/mindee/v2/search/rag_documents/rag_document_search_parameters.py index 351e3ff4..16327d01 100644 --- a/mindee/v2/search/rag_documents/rag_document_search_parameters.py +++ b/mindee/v2/search/rag_documents/rag_document_search_parameters.py @@ -9,13 +9,20 @@ @dataclass(kw_only=True) class RagDocumentSearchParameters(BaseSearchParameters[RagDocumentSearchResponse]): - """Search parameters for RAG Documents.""" + """ + Search for RAG documents within the organization linked to the API key. + + The model ID is required, search filters are optional. + If no search filters are given, all documents linked to the model are returned. + + Results are paginated. + """ model_id: str - """Model identifier to search in.""" + """The exact Model UUID the document is linked to.""" filename: str | None = None - """Case-insensitive substring search on filename.""" + """Filter documents by partial filename match, case-insensitive.""" _slug: ClassVar[str] = "rag-documents" _response_class: type[RagDocumentSearchResponse] = RagDocumentSearchResponse diff --git a/tests/v2/search/test_model_search_integration.py b/tests/v2/search/test_model_search_integration.py index 53b4dc31..dd6e9275 100644 --- a/tests/v2/search/test_model_search_integration.py +++ b/tests/v2/search/test_model_search_integration.py @@ -11,7 +11,7 @@ def v2_client() -> Client: @pytest.mark.integration @pytest.mark.v2 -def test_must_have_results(v2_client: Client): +def test_search_must_have_results(v2_client: Client): response = v2_client.search(ModelSearchParameters()) assert response is not None @@ -27,7 +27,7 @@ def test_must_have_results(v2_client: Client): @pytest.mark.integration @pytest.mark.v2 -def test_must_return_empty(v2_client: Client): +def test_search_must_return_empty(v2_client: Client): response = v2_client.search(ModelSearchParameters(name="je n'existe pas tralala")) assert response is not None diff --git a/tests/v2/search/test_rag_document_search_integration.py b/tests/v2/search/test_rag_document_search_integration.py index 5783527c..5b17e653 100644 --- a/tests/v2/search/test_rag_document_search_integration.py +++ b/tests/v2/search/test_rag_document_search_integration.py @@ -3,9 +3,7 @@ import pytest from mindee.v2.client import Client -from mindee.v2.search.rag_documents.rag_document_search_parameters import ( - RagDocumentSearchParameters, -) +from mindee.v2.search.rag_documents import RagDocumentSearchParameters @pytest.fixture(scope="session") @@ -13,15 +11,41 @@ def v2_client() -> Client: return Client() -@pytest.mark.integration -@pytest.mark.v2 -def test_must_have_results(v2_client: Client): +@pytest.fixture(scope="session") +def findoc_model_id() -> str: findoc_model_id = os.getenv("MINDEE_V2_SE_TESTS_FINDOC_MODEL_ID") assert findoc_model_id, "MINDEE_V2_SE_TESTS_FINDOC_MODEL_ID must be set" + return findoc_model_id + + +@pytest.mark.integration +@pytest.mark.v2 +def test_search_must_have_results(v2_client: Client, findoc_model_id: str): response = v2_client.search(RagDocumentSearchParameters(model_id=findoc_model_id)) assert response is not None assert len(response.rag_documents) > 0 + for rag_doc in response.rag_documents: + assert rag_doc.id + assert rag_doc.created_at + assert rag_doc.filename + assert rag_doc.total_matches >= 0 assert response.pagination is not None assert response.pagination.total_items >= 1 assert response.pagination.page == 1 + + +@pytest.mark.integration +@pytest.mark.v2 +def test_search_must_return_empty(v2_client: Client, findoc_model_id: str): + response = v2_client.search( + RagDocumentSearchParameters( + model_id=findoc_model_id, filename="invoice_32GB-RAM_450k-USD.pdf" + ) + ) + + assert response is not None + assert len(response.rag_documents) == 0 + assert response.pagination is not None + assert response.pagination.total_items == 0 + assert response.pagination.page == 1