Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions docs/client_mixin.rst

This file was deleted.

23 changes: 0 additions & 23 deletions mindee/client_mixin.py

This file was deleted.

20 changes: 20 additions & 0 deletions mindee/client_options/polling_options.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from mindee.error import MindeeClientError


class PollingOptions:
"""Options for asynchronous polling."""

Expand All @@ -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}.")
10 changes: 7 additions & 3 deletions mindee/v1/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -53,7 +53,7 @@ def _clean_account_name(account_name: str) -> str:
return account_name


class Client(ClientMixin):
class Client:
"""
Mindee API Client.

Expand Down Expand Up @@ -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(
Expand Down
9 changes: 2 additions & 7 deletions mindee/v2/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -27,7 +26,7 @@
)


class Client(ClientMixin):
class Client:
"""
Mindee API Client.

Expand Down Expand Up @@ -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
Expand Down
13 changes: 10 additions & 3 deletions mindee/v2/search/rag_documents/rag_document_search_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions tests/v2/search/test_model_search_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
36 changes: 30 additions & 6 deletions tests/v2/search/test_rag_document_search_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,49 @@
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")
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