diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 2aca35ae..4208b5cb 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.5.0" + ".": "0.6.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 71c5ffa2..c6e434cd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 49 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-82c2c1c322149cd73b2e8e45f475919b941752a89e74464ccecd1aee9352e9be.yml -openapi_spec_hash: 07482ed86f5ccf7b480c514d6d5ebb15 -config_hash: 167171738605c297aa5e8bc73abc66e3 +configured_endpoints: 48 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-a331b701867ba3d3dd907c8389fde663be4fda24c91e23f54f4dde8a6ade683f.yml +openapi_spec_hash: 95587d9746abb97d5b294bfedf86b782 +config_hash: 8545159b6ba2d638b8a2e7bbed6f04e7 diff --git a/CHANGELOG.md b/CHANGELOG.md index f4dee4fb..8a341037 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Changelog +## 0.6.0 (2025-06-13) + +Full Changelog: [v0.5.0...v0.6.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.5.0...v0.6.0) + +### Features + +* **api:** api update ([8ada0ea](https://github.com/mixedbread-ai/mixedbread-python/commit/8ada0eaeeed29b8ee2a08cf436077ee2f729794a)) +* **api:** api update ([22e5269](https://github.com/mixedbread-ai/mixedbread-python/commit/22e52693cb2f02fb20c0f7ca8f97d572a1091f6f)) +* **api:** api update ([eec921b](https://github.com/mixedbread-ai/mixedbread-python/commit/eec921b939205565f11790b08458f3e74df6e8a3)) +* **api:** api update ([0296d95](https://github.com/mixedbread-ai/mixedbread-python/commit/0296d958b5d8e82e2626fc04f9618a6423803515)) +* **api:** update via SDK Studio ([56f4e89](https://github.com/mixedbread-ai/mixedbread-python/commit/56f4e890d75c0cc54898f65f4087a828fe4bcc4e)) +* **api:** update via SDK Studio ([ed99b06](https://github.com/mixedbread-ai/mixedbread-python/commit/ed99b067eba308da0bb4ff24623d32b3339563a1)) +* **client:** add follow_redirects request option ([5f0a4ab](https://github.com/mixedbread-ai/mixedbread-python/commit/5f0a4abbecd635ad655480514685281891fd8699)) + + +### Bug Fixes + +* **client:** correctly parse binary response | stream ([786bd6a](https://github.com/mixedbread-ai/mixedbread-python/commit/786bd6aeeac6fb7af0ffb1f00b6485dd253bd8fa)) +* **docs/api:** remove references to nonexistent types ([43c342b](https://github.com/mixedbread-ai/mixedbread-python/commit/43c342bb106371ea6057969578dc55af713f225e)) + + +### Chores + +* **docs:** remove reference to rye shell ([c0c8bfd](https://github.com/mixedbread-ai/mixedbread-python/commit/c0c8bfdeac4c2ed4b7d381a9faef43485e5904de)) +* **docs:** remove unnecessary param examples ([54ef7c7](https://github.com/mixedbread-ai/mixedbread-python/commit/54ef7c77e392577a3038552a4a859b6351c6ddf4)) +* **tests:** run tests in parallel ([064a793](https://github.com/mixedbread-ai/mixedbread-python/commit/064a793c8269a6e3a30a1c84e6d7a3a783ffa31f)) + ## 0.5.0 (2025-05-26) Full Changelog: [v0.4.0...v0.5.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.4.0...v0.5.0) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e9ccd896..0b147f05 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -17,8 +17,7 @@ $ rye sync --all-features You can then run scripts using `rye run python script.py` or by activating the virtual environment: ```sh -$ rye shell -# or manually activate - https://docs.python.org/3/library/venv.html#how-venvs-work +# Activate the virtual environment - https://docs.python.org/3/library/venv.html#how-venvs-work $ source .venv/bin/activate # now you can omit the `rye run` prefix diff --git a/README.md b/README.md index 831cfdec..24d13985 100644 --- a/README.md +++ b/README.md @@ -152,10 +152,7 @@ from mixedbread import Mixedbread client = Mixedbread() vector_store = client.vector_stores.create( - expires_after={ - "anchor": "last_active_at", - "days": 0, - }, + expires_after={}, ) print(vector_store.expires_after) ``` diff --git a/api.md b/api.md index ff98c770..0008e67f 100644 --- a/api.md +++ b/api.md @@ -46,10 +46,10 @@ from mixedbread.types import ( Methods: - client.vector_stores.create(\*\*params) -> VectorStore -- client.vector_stores.retrieve(vector_store_id) -> VectorStore -- client.vector_stores.update(vector_store_id, \*\*params) -> VectorStore +- client.vector_stores.retrieve(vector_store_identifier) -> VectorStore +- client.vector_stores.update(vector_store_identifier, \*\*params) -> VectorStore - client.vector_stores.list(\*\*params) -> SyncLimitOffset[VectorStore] -- client.vector_stores.delete(vector_store_id) -> VectorStoreDeleteResponse +- client.vector_stores.delete(vector_store_identifier) -> VectorStoreDeleteResponse - client.vector_stores.question_answering(\*\*params) -> VectorStoreQuestionAnsweringResponse - client.vector_stores.search(\*\*params) -> VectorStoreSearchResponse @@ -68,10 +68,10 @@ from mixedbread.types.vector_stores import ( Methods: -- client.vector_stores.files.create(vector_store_id, \*\*params) -> VectorStoreFile -- client.vector_stores.files.retrieve(file_id, \*, vector_store_id) -> VectorStoreFile -- client.vector_stores.files.list(vector_store_id, \*\*params) -> SyncLimitOffset[VectorStoreFile] -- client.vector_stores.files.delete(file_id, \*, vector_store_id) -> FileDeleteResponse +- client.vector_stores.files.create(vector_store_identifier, \*\*params) -> VectorStoreFile +- client.vector_stores.files.retrieve(file_id, \*, vector_store_identifier) -> VectorStoreFile +- client.vector_stores.files.list(vector_store_identifier, \*\*params) -> SyncLimitOffset[VectorStoreFile] +- client.vector_stores.files.delete(file_id, \*, vector_store_identifier) -> FileDeleteResponse - client.vector_stores.files.search(\*\*params) -> FileSearchResponse # Parsing @@ -170,18 +170,6 @@ Methods: - client.embeddings.create(\*\*params) -> EmbeddingCreateResponse -# Chat - -Types: - -```python -from mixedbread.types import ChatCreateCompletionResponse -``` - -Methods: - -- client.chat.create_completion() -> object - # DataSources Types: diff --git a/pyproject.toml b/pyproject.toml index b6e83d86..6de28979 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mixedbread" -version = "0.5.0" +version = "0.6.0" description = "The official Python library for the Mixedbread API" dynamic = ["readme"] license = "Apache-2.0" @@ -54,6 +54,7 @@ dev-dependencies = [ "importlib-metadata>=6.7.0", "rich>=13.7.1", "nest_asyncio==1.6.0", + "pytest-xdist>=3.6.1", ] [tool.rye.scripts] @@ -125,7 +126,7 @@ replacement = '[\1](https://github.com/mixedbread-ai/mixedbread-python/tree/main [tool.pytest.ini_options] testpaths = ["tests"] -addopts = "--tb=short" +addopts = "--tb=short -n auto" xfail_strict = true asyncio_mode = "auto" asyncio_default_fixture_loop_scope = "session" diff --git a/requirements-dev.lock b/requirements-dev.lock index 4d2d4266..e4090452 100644 --- a/requirements-dev.lock +++ b/requirements-dev.lock @@ -30,6 +30,8 @@ distro==1.8.0 exceptiongroup==1.2.2 # via anyio # via pytest +execnet==2.1.1 + # via pytest-xdist filelock==3.12.4 # via virtualenv h11==0.14.0 @@ -72,7 +74,9 @@ pygments==2.18.0 pyright==1.1.399 pytest==8.3.3 # via pytest-asyncio + # via pytest-xdist pytest-asyncio==0.24.0 +pytest-xdist==3.7.0 python-dateutil==2.8.2 # via time-machine pytz==2023.3.post1 diff --git a/src/mixedbread/_base_client.py b/src/mixedbread/_base_client.py index 72f949dc..44036510 100644 --- a/src/mixedbread/_base_client.py +++ b/src/mixedbread/_base_client.py @@ -960,6 +960,9 @@ def request( if self.custom_auth is not None: kwargs["auth"] = self.custom_auth + if options.follow_redirects is not None: + kwargs["follow_redirects"] = options.follow_redirects + log.debug("Sending HTTP Request: %s %s", request.method, request.url) response = None @@ -1068,7 +1071,14 @@ def _process_response( ) -> ResponseT: origin = get_origin(cast_to) or cast_to - if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse): + if ( + inspect.isclass(origin) + and issubclass(origin, BaseAPIResponse) + # we only want to actually return the custom BaseAPIResponse class if we're + # returning the raw response, or if we're not streaming SSE, as if we're streaming + # SSE then `cast_to` doesn't actively reflect the type we need to parse into + and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER))) + ): if not issubclass(origin, APIResponse): raise TypeError(f"API Response types must subclass {APIResponse}; Received {origin}") @@ -1460,6 +1470,9 @@ async def request( if self.custom_auth is not None: kwargs["auth"] = self.custom_auth + if options.follow_redirects is not None: + kwargs["follow_redirects"] = options.follow_redirects + log.debug("Sending HTTP Request: %s %s", request.method, request.url) response = None @@ -1568,7 +1581,14 @@ async def _process_response( ) -> ResponseT: origin = get_origin(cast_to) or cast_to - if inspect.isclass(origin) and issubclass(origin, BaseAPIResponse): + if ( + inspect.isclass(origin) + and issubclass(origin, BaseAPIResponse) + # we only want to actually return the custom BaseAPIResponse class if we're + # returning the raw response, or if we're not streaming SSE, as if we're streaming + # SSE then `cast_to` doesn't actively reflect the type we need to parse into + and (not stream or bool(response.request.headers.get(RAW_RESPONSE_HEADER))) + ): if not issubclass(origin, AsyncAPIResponse): raise TypeError(f"API Response types must subclass {AsyncAPIResponse}; Received {origin}") diff --git a/src/mixedbread/_client.py b/src/mixedbread/_client.py index 87e724e0..f75adc2f 100644 --- a/src/mixedbread/_client.py +++ b/src/mixedbread/_client.py @@ -36,7 +36,7 @@ async_to_raw_response_wrapper, async_to_streamed_response_wrapper, ) -from .resources import chat, files, api_keys, embeddings +from .resources import files, api_keys, embeddings from ._streaming import Stream as Stream, AsyncStream as AsyncStream from ._exceptions import APIStatusError, MixedbreadError from ._base_client import ( @@ -78,7 +78,6 @@ class Mixedbread(SyncAPIClient): files: files.FilesResource extractions: extractions.ExtractionsResource embeddings: embeddings.EmbeddingsResource - chat: chat.ChatResource data_sources: data_sources.DataSourcesResource api_keys: api_keys.APIKeysResource with_raw_response: MixedbreadWithRawResponse @@ -167,7 +166,6 @@ def __init__( self.files = files.FilesResource(self) self.extractions = extractions.ExtractionsResource(self) self.embeddings = embeddings.EmbeddingsResource(self) - self.chat = chat.ChatResource(self) self.data_sources = data_sources.DataSourcesResource(self) self.api_keys = api_keys.APIKeysResource(self) self.with_raw_response = MixedbreadWithRawResponse(self) @@ -441,7 +439,6 @@ class AsyncMixedbread(AsyncAPIClient): files: files.AsyncFilesResource extractions: extractions.AsyncExtractionsResource embeddings: embeddings.AsyncEmbeddingsResource - chat: chat.AsyncChatResource data_sources: data_sources.AsyncDataSourcesResource api_keys: api_keys.AsyncAPIKeysResource with_raw_response: AsyncMixedbreadWithRawResponse @@ -530,7 +527,6 @@ def __init__( self.files = files.AsyncFilesResource(self) self.extractions = extractions.AsyncExtractionsResource(self) self.embeddings = embeddings.AsyncEmbeddingsResource(self) - self.chat = chat.AsyncChatResource(self) self.data_sources = data_sources.AsyncDataSourcesResource(self) self.api_keys = api_keys.AsyncAPIKeysResource(self) self.with_raw_response = AsyncMixedbreadWithRawResponse(self) @@ -805,7 +801,6 @@ def __init__(self, client: Mixedbread) -> None: self.files = files.FilesResourceWithRawResponse(client.files) self.extractions = extractions.ExtractionsResourceWithRawResponse(client.extractions) self.embeddings = embeddings.EmbeddingsResourceWithRawResponse(client.embeddings) - self.chat = chat.ChatResourceWithRawResponse(client.chat) self.data_sources = data_sources.DataSourcesResourceWithRawResponse(client.data_sources) self.api_keys = api_keys.APIKeysResourceWithRawResponse(client.api_keys) @@ -827,7 +822,6 @@ def __init__(self, client: AsyncMixedbread) -> None: self.files = files.AsyncFilesResourceWithRawResponse(client.files) self.extractions = extractions.AsyncExtractionsResourceWithRawResponse(client.extractions) self.embeddings = embeddings.AsyncEmbeddingsResourceWithRawResponse(client.embeddings) - self.chat = chat.AsyncChatResourceWithRawResponse(client.chat) self.data_sources = data_sources.AsyncDataSourcesResourceWithRawResponse(client.data_sources) self.api_keys = api_keys.AsyncAPIKeysResourceWithRawResponse(client.api_keys) @@ -849,7 +843,6 @@ def __init__(self, client: Mixedbread) -> None: self.files = files.FilesResourceWithStreamingResponse(client.files) self.extractions = extractions.ExtractionsResourceWithStreamingResponse(client.extractions) self.embeddings = embeddings.EmbeddingsResourceWithStreamingResponse(client.embeddings) - self.chat = chat.ChatResourceWithStreamingResponse(client.chat) self.data_sources = data_sources.DataSourcesResourceWithStreamingResponse(client.data_sources) self.api_keys = api_keys.APIKeysResourceWithStreamingResponse(client.api_keys) @@ -871,7 +864,6 @@ def __init__(self, client: AsyncMixedbread) -> None: self.files = files.AsyncFilesResourceWithStreamingResponse(client.files) self.extractions = extractions.AsyncExtractionsResourceWithStreamingResponse(client.extractions) self.embeddings = embeddings.AsyncEmbeddingsResourceWithStreamingResponse(client.embeddings) - self.chat = chat.AsyncChatResourceWithStreamingResponse(client.chat) self.data_sources = data_sources.AsyncDataSourcesResourceWithStreamingResponse(client.data_sources) self.api_keys = api_keys.AsyncAPIKeysResourceWithStreamingResponse(client.api_keys) diff --git a/src/mixedbread/_models.py b/src/mixedbread/_models.py index 798956f1..4f214980 100644 --- a/src/mixedbread/_models.py +++ b/src/mixedbread/_models.py @@ -737,6 +737,7 @@ class FinalRequestOptionsInput(TypedDict, total=False): idempotency_key: str json_data: Body extra_json: AnyMapping + follow_redirects: bool @final @@ -750,6 +751,7 @@ class FinalRequestOptions(pydantic.BaseModel): files: Union[HttpxRequestFiles, None] = None idempotency_key: Union[str, None] = None post_parser: Union[Callable[[Any], Any], NotGiven] = NotGiven() + follow_redirects: Union[bool, None] = None # It should be noted that we cannot use `json` here as that would override # a BaseModel method in an incompatible fashion. diff --git a/src/mixedbread/_types.py b/src/mixedbread/_types.py index b1e781f8..6fdd2f2b 100644 --- a/src/mixedbread/_types.py +++ b/src/mixedbread/_types.py @@ -100,6 +100,7 @@ class RequestOptions(TypedDict, total=False): params: Query extra_json: AnyMapping idempotency_key: str + follow_redirects: bool # Sentinel class used until PEP 0661 is accepted @@ -215,3 +216,4 @@ class _GenericAlias(Protocol): class HttpxSendArgs(TypedDict, total=False): auth: httpx.Auth + follow_redirects: bool diff --git a/src/mixedbread/_version.py b/src/mixedbread/_version.py index 7a42cf4e..6060c6be 100644 --- a/src/mixedbread/_version.py +++ b/src/mixedbread/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "mixedbread" -__version__ = "0.5.0" # x-release-please-version +__version__ = "0.6.0" # x-release-please-version diff --git a/src/mixedbread/resources/__init__.py b/src/mixedbread/resources/__init__.py index 241510a2..284cc1cb 100644 --- a/src/mixedbread/resources/__init__.py +++ b/src/mixedbread/resources/__init__.py @@ -1,13 +1,5 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from .chat import ( - ChatResource, - AsyncChatResource, - ChatResourceWithRawResponse, - AsyncChatResourceWithRawResponse, - ChatResourceWithStreamingResponse, - AsyncChatResourceWithStreamingResponse, -) from .files import ( FilesResource, AsyncFilesResource, @@ -96,12 +88,6 @@ "AsyncEmbeddingsResourceWithRawResponse", "EmbeddingsResourceWithStreamingResponse", "AsyncEmbeddingsResourceWithStreamingResponse", - "ChatResource", - "AsyncChatResource", - "ChatResourceWithRawResponse", - "AsyncChatResourceWithRawResponse", - "ChatResourceWithStreamingResponse", - "AsyncChatResourceWithStreamingResponse", "DataSourcesResource", "AsyncDataSourcesResource", "DataSourcesResourceWithRawResponse", diff --git a/src/mixedbread/resources/chat.py b/src/mixedbread/resources/chat.py deleted file mode 100644 index f9b1b0ce..00000000 --- a/src/mixedbread/resources/chat.py +++ /dev/null @@ -1,164 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import httpx - -from .._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from .._compat import cached_property -from .._resource import SyncAPIResource, AsyncAPIResource -from .._response import ( - to_raw_response_wrapper, - to_streamed_response_wrapper, - async_to_raw_response_wrapper, - async_to_streamed_response_wrapper, -) -from .._base_client import make_request_options - -__all__ = ["ChatResource", "AsyncChatResource"] - - -class ChatResource(SyncAPIResource): - @cached_property - def with_raw_response(self) -> ChatResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/mixedbread-ai/mixedbread-python#accessing-raw-response-data-eg-headers - """ - return ChatResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> ChatResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/mixedbread-ai/mixedbread-python#with_streaming_response - """ - return ChatResourceWithStreamingResponse(self) - - def create_completion( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: - """ - Create a chat completion using the provided parameters. - - Generates a completion response based on the chat messages and model parameters - provided. The response can be either a full completion or streamed chunks - depending on the request parameters. - - Args: params: Parameters for creating the chat completion including messages, - model selection, and generation settings user: The authenticated user making the - request - - Returns: Either a ChatCompletion containing the full response, or - ChatCompletionChunk for streaming - - Raises: HTTPException: If there is an error creating the completion (500) - """ - return self._post( - "/v1/chat/completions", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=object, - ) - - -class AsyncChatResource(AsyncAPIResource): - @cached_property - def with_raw_response(self) -> AsyncChatResourceWithRawResponse: - """ - This property can be used as a prefix for any HTTP method call to return - the raw response object instead of the parsed content. - - For more information, see https://www.github.com/mixedbread-ai/mixedbread-python#accessing-raw-response-data-eg-headers - """ - return AsyncChatResourceWithRawResponse(self) - - @cached_property - def with_streaming_response(self) -> AsyncChatResourceWithStreamingResponse: - """ - An alternative to `.with_raw_response` that doesn't eagerly read the response body. - - For more information, see https://www.github.com/mixedbread-ai/mixedbread-python#with_streaming_response - """ - return AsyncChatResourceWithStreamingResponse(self) - - async def create_completion( - self, - *, - # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. - # The extra values given here take precedence over values defined on the client or passed to this method. - extra_headers: Headers | None = None, - extra_query: Query | None = None, - extra_body: Body | None = None, - timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> object: - """ - Create a chat completion using the provided parameters. - - Generates a completion response based on the chat messages and model parameters - provided. The response can be either a full completion or streamed chunks - depending on the request parameters. - - Args: params: Parameters for creating the chat completion including messages, - model selection, and generation settings user: The authenticated user making the - request - - Returns: Either a ChatCompletion containing the full response, or - ChatCompletionChunk for streaming - - Raises: HTTPException: If there is an error creating the completion (500) - """ - return await self._post( - "/v1/chat/completions", - options=make_request_options( - extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout - ), - cast_to=object, - ) - - -class ChatResourceWithRawResponse: - def __init__(self, chat: ChatResource) -> None: - self._chat = chat - - self.create_completion = to_raw_response_wrapper( - chat.create_completion, - ) - - -class AsyncChatResourceWithRawResponse: - def __init__(self, chat: AsyncChatResource) -> None: - self._chat = chat - - self.create_completion = async_to_raw_response_wrapper( - chat.create_completion, - ) - - -class ChatResourceWithStreamingResponse: - def __init__(self, chat: ChatResource) -> None: - self._chat = chat - - self.create_completion = to_streamed_response_wrapper( - chat.create_completion, - ) - - -class AsyncChatResourceWithStreamingResponse: - def __init__(self, chat: AsyncChatResource) -> None: - self._chat = chat - - self.create_completion = async_to_streamed_response_wrapper( - chat.create_completion, - ) diff --git a/src/mixedbread/resources/data_sources/connectors.py b/src/mixedbread/resources/data_sources/connectors.py index 435ca0e1..c9ab8400 100644 --- a/src/mixedbread/resources/data_sources/connectors.py +++ b/src/mixedbread/resources/data_sources/connectors.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Dict, Union, Optional import httpx @@ -53,7 +53,7 @@ def create( name: str | NotGiven = NOT_GIVEN, trigger_sync: bool | NotGiven = NOT_GIVEN, metadata: object | NotGiven = NOT_GIVEN, - polling_interval: Optional[str] | NotGiven = NOT_GIVEN, + polling_interval: Union[int, str, None] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -80,7 +80,12 @@ def create( metadata: The metadata of the connector - polling_interval: The polling interval of the connector + polling_interval: Polling interval for the connector. Defaults to 30 minutes if not specified. Can + be provided as: + + - int: Number of seconds (e.g., 1800 for 30 minutes) + - str: Duration string (e.g., '30m', '1h', '2d') or ISO 8601 format (e.g., + 'PT30M', 'P1D') Valid range: 15 seconds to 30 days extra_headers: Send extra headers @@ -163,7 +168,7 @@ def update( name: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, trigger_sync: Optional[bool] | NotGiven = NOT_GIVEN, - polling_interval: Optional[str] | NotGiven = NOT_GIVEN, + polling_interval: Union[int, str, None] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -191,7 +196,12 @@ def update( trigger_sync: Whether the connector should be synced after update - polling_interval: The polling interval of the connector + polling_interval: Polling interval for the connector. Defaults to 30 minutes if not specified. Can + be provided as: + + - int: Number of seconds (e.g., 1800 for 30 minutes) + - str: Duration string (e.g., '30m', '1h', '2d') or ISO 8601 format (e.g., + 'PT30M', 'P1D') Valid range: 15 seconds to 30 days extra_headers: Send extra headers @@ -353,7 +363,7 @@ async def create( name: str | NotGiven = NOT_GIVEN, trigger_sync: bool | NotGiven = NOT_GIVEN, metadata: object | NotGiven = NOT_GIVEN, - polling_interval: Optional[str] | NotGiven = NOT_GIVEN, + polling_interval: Union[int, str, None] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -380,7 +390,12 @@ async def create( metadata: The metadata of the connector - polling_interval: The polling interval of the connector + polling_interval: Polling interval for the connector. Defaults to 30 minutes if not specified. Can + be provided as: + + - int: Number of seconds (e.g., 1800 for 30 minutes) + - str: Duration string (e.g., '30m', '1h', '2d') or ISO 8601 format (e.g., + 'PT30M', 'P1D') Valid range: 15 seconds to 30 days extra_headers: Send extra headers @@ -463,7 +478,7 @@ async def update( name: Optional[str] | NotGiven = NOT_GIVEN, metadata: Optional[Dict[str, object]] | NotGiven = NOT_GIVEN, trigger_sync: Optional[bool] | NotGiven = NOT_GIVEN, - polling_interval: Optional[str] | NotGiven = NOT_GIVEN, + polling_interval: Union[int, str, None] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -491,7 +506,12 @@ async def update( trigger_sync: Whether the connector should be synced after update - polling_interval: The polling interval of the connector + polling_interval: Polling interval for the connector. Defaults to 30 minutes if not specified. Can + be provided as: + + - int: Number of seconds (e.g., 1800 for 30 minutes) + - str: Duration string (e.g., '30m', '1h', '2d') or ISO 8601 format (e.g., + 'PT30M', 'P1D') Valid range: 15 seconds to 30 days extra_headers: Send extra headers diff --git a/src/mixedbread/resources/data_sources/data_sources.py b/src/mixedbread/resources/data_sources/data_sources.py index a579c6ac..1f3fc0f9 100644 --- a/src/mixedbread/resources/data_sources/data_sources.py +++ b/src/mixedbread/resources/data_sources/data_sources.py @@ -3,17 +3,13 @@ from __future__ import annotations from typing import Optional +from typing_extensions import overload import httpx -from ...types import ( - DataSourceType, - data_source_list_params, - data_source_create_params, - data_source_update_params, -) +from ...types import DataSourceType, data_source_list_params, data_source_create_params, data_source_update_params from ..._types import NOT_GIVEN, Body, Query, Headers, NotGiven -from ..._utils import maybe_transform, async_maybe_transform +from ..._utils import required_args, maybe_transform, async_maybe_transform from ..._compat import cached_property from .connectors import ( ConnectorsResource, @@ -35,7 +31,6 @@ from ...types.data_source import DataSource from ...types.data_source_type import DataSourceType from ...types.data_source_delete_response import DataSourceDeleteResponse -from ...types.data_source_oauth2_params_param import DataSourceOauth2ParamsParam __all__ = ["DataSourcesResource", "AsyncDataSourcesResource"] @@ -64,13 +59,15 @@ def with_streaming_response(self) -> DataSourcesResourceWithStreamingResponse: """ return DataSourcesResourceWithStreamingResponse(self) + @overload def create( self, *, - type: DataSourceType, + type: DataSourceType | NotGiven = NOT_GIVEN, name: str, metadata: object | NotGiven = NOT_GIVEN, - auth_params: Optional[DataSourceOauth2ParamsParam] | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_create_params.NotionDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -92,7 +89,8 @@ def create( metadata: The metadata of the data source - auth_params: Authentication parameters for a OAuth data source. + auth_params: The authentication parameters of the data source. Notion supports OAuth2 and API + key. extra_headers: Send extra headers @@ -102,6 +100,67 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + def create( + self, + *, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, + metadata: object | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_create_params.LinearDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DataSource: + """ + Create a new data source. + + Args: params: The data source to create. + + Returns: The created data source. + + Args: + type: The type of data source to create + + name: The name of the data source + + metadata: The metadata of the data source + + auth_params: Base class for OAuth2 create or update parameters. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["name"]) + def create( + self, + *, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, + metadata: object | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_create_params.NotionDataSourceCreateOrUpdateParamsAuthParams] + | Optional[data_source_create_params.LinearDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DataSource: return self._post( "/v1/data_sources/", body=maybe_transform( @@ -158,13 +217,16 @@ def retrieve( cast_to=DataSource, ) + @overload def update( self, data_source_id: str, *, - name: Optional[str] | NotGiven = NOT_GIVEN, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, metadata: object | NotGiven = NOT_GIVEN, - auth_params: Optional[DataSourceOauth2ParamsParam] | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_update_params.NotionDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -184,11 +246,14 @@ def update( Args: data_source_id: The ID of the data source to update + type: The type of data source to create + name: The name of the data source metadata: The metadata of the data source - auth_params: Authentication parameters for a OAuth data source. + auth_params: The authentication parameters of the data source. Notion supports OAuth2 and API + key. extra_headers: Send extra headers @@ -198,12 +263,80 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + def update( + self, + data_source_id: str, + *, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, + metadata: object | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_update_params.LinearDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DataSource: + """Update a data source. + + Args: data_source_id: The ID of the data source to update. + + params: The data + source to update. + + Returns: The updated data source. + + Args: + data_source_id: The ID of the data source to update + + type: The type of data source to create + + name: The name of the data source + + metadata: The metadata of the data source + + auth_params: Base class for OAuth2 create or update parameters. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["name"]) + def update( + self, + data_source_id: str, + *, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, + metadata: object | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_update_params.NotionDataSourceCreateOrUpdateParamsAuthParams] + | Optional[data_source_update_params.LinearDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DataSource: if not data_source_id: raise ValueError(f"Expected a non-empty value for `data_source_id` but received {data_source_id!r}") return self._put( f"/v1/data_sources/{data_source_id}", body=maybe_transform( { + "type": type, "name": name, "metadata": metadata, "auth_params": auth_params, @@ -327,13 +460,15 @@ def with_streaming_response(self) -> AsyncDataSourcesResourceWithStreamingRespon """ return AsyncDataSourcesResourceWithStreamingResponse(self) + @overload async def create( self, *, - type: DataSourceType, + type: DataSourceType | NotGiven = NOT_GIVEN, name: str, metadata: object | NotGiven = NOT_GIVEN, - auth_params: Optional[DataSourceOauth2ParamsParam] | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_create_params.NotionDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -355,7 +490,8 @@ async def create( metadata: The metadata of the data source - auth_params: Authentication parameters for a OAuth data source. + auth_params: The authentication parameters of the data source. Notion supports OAuth2 and API + key. extra_headers: Send extra headers @@ -365,6 +501,67 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @overload + async def create( + self, + *, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, + metadata: object | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_create_params.LinearDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DataSource: + """ + Create a new data source. + + Args: params: The data source to create. + + Returns: The created data source. + + Args: + type: The type of data source to create + + name: The name of the data source + + metadata: The metadata of the data source + + auth_params: Base class for OAuth2 create or update parameters. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @required_args(["name"]) + async def create( + self, + *, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, + metadata: object | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_create_params.NotionDataSourceCreateOrUpdateParamsAuthParams] + | Optional[data_source_create_params.LinearDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DataSource: return await self._post( "/v1/data_sources/", body=await async_maybe_transform( @@ -421,13 +618,64 @@ async def retrieve( cast_to=DataSource, ) + @overload + async def update( + self, + data_source_id: str, + *, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, + metadata: object | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_update_params.NotionDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DataSource: + """Update a data source. + + Args: data_source_id: The ID of the data source to update. + + params: The data + source to update. + + Returns: The updated data source. + + Args: + data_source_id: The ID of the data source to update + + type: The type of data source to create + + name: The name of the data source + + metadata: The metadata of the data source + + auth_params: The authentication parameters of the data source. Notion supports OAuth2 and API + key. + + extra_headers: Send extra headers + + extra_query: Add additional query parameters to the request + + extra_body: Add additional JSON properties to the request + + timeout: Override the client-level default timeout for this request, in seconds + """ + ... + + @overload async def update( self, data_source_id: str, *, - name: Optional[str] | NotGiven = NOT_GIVEN, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, metadata: object | NotGiven = NOT_GIVEN, - auth_params: Optional[DataSourceOauth2ParamsParam] | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_update_params.LinearDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -447,11 +695,13 @@ async def update( Args: data_source_id: The ID of the data source to update + type: The type of data source to create + name: The name of the data source metadata: The metadata of the data source - auth_params: Authentication parameters for a OAuth data source. + auth_params: Base class for OAuth2 create or update parameters. extra_headers: Send extra headers @@ -461,12 +711,33 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ + ... + + @required_args(["name"]) + async def update( + self, + data_source_id: str, + *, + type: DataSourceType | NotGiven = NOT_GIVEN, + name: str, + metadata: object | NotGiven = NOT_GIVEN, + auth_params: Optional[data_source_update_params.NotionDataSourceCreateOrUpdateParamsAuthParams] + | Optional[data_source_update_params.LinearDataSourceCreateOrUpdateParamsAuthParams] + | NotGiven = NOT_GIVEN, + # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. + # The extra values given here take precedence over values defined on the client or passed to this method. + extra_headers: Headers | None = None, + extra_query: Query | None = None, + extra_body: Body | None = None, + timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, + ) -> DataSource: if not data_source_id: raise ValueError(f"Expected a non-empty value for `data_source_id` but received {data_source_id!r}") return await self._put( f"/v1/data_sources/{data_source_id}", body=await async_maybe_transform( { + "type": type, "name": name, "metadata": metadata, "auth_params": auth_params, diff --git a/src/mixedbread/resources/vector_stores/files.py b/src/mixedbread/resources/vector_stores/files.py index 5022d024..76e599e5 100644 --- a/src/mixedbread/resources/vector_stores/files.py +++ b/src/mixedbread/resources/vector_stores/files.py @@ -3,7 +3,7 @@ from __future__ import annotations import functools -from typing import Any, List, Optional +from typing import Any, List, Union, Iterable, Optional import httpx @@ -50,7 +50,7 @@ def with_streaming_response(self) -> FilesResourceWithStreamingResponse: def create( self, - vector_store_id: str, + vector_store_identifier: str, *, file_id: str, metadata: object | NotGiven = NOT_GIVEN, @@ -65,13 +65,13 @@ def create( """ Upload a new file to a vector store for indexing. - Args: vector_store_id: The ID of the vector store to upload to file: The file to - upload and index + Args: vector_store_identifier: The ID or name of the vector store to upload to + file: The file to upload and index Returns: VectorStoreFile: Details of the uploaded and indexed file Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store file_id: ID of the file to add @@ -87,10 +87,12 @@ def create( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return self._post( - f"/v1/vector_stores/{vector_store_id}/files", + f"/v1/vector_stores/{vector_store_identifier}/files", body=maybe_transform( { "file_id": file_id, @@ -109,7 +111,7 @@ def retrieve( self, file_id: str, *, - vector_store_id: str, + vector_store_identifier: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -120,12 +122,13 @@ def retrieve( """ Get details of a specific file in a vector store. - Args: vector_store_id: The ID of the vector store file_id: The ID of the file + Args: vector_store_identifier: The ID or name of the vector store file_id: The + ID of the file Returns: VectorStoreFile: Details of the vector store file Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store file_id: The ID of the file @@ -137,12 +140,14 @@ def retrieve( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._get( - f"/v1/vector_stores/{vector_store_id}/files/{file_id}", + f"/v1/vector_stores/{vector_store_identifier}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -151,7 +156,7 @@ def retrieve( def list( self, - vector_store_id: str, + vector_store_identifier: str, *, limit: int | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, @@ -165,13 +170,13 @@ def list( """ List files indexed in a vector store with pagination. - Args: vector_store_id: The ID of the vector store pagination: Pagination - parameters + Args: vector_store_identifier: The ID or name of the vector store pagination: + Pagination parameters Returns: VectorStoreFileListResponse: Paginated list of vector store files Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store limit: Maximum number of items to return per page @@ -185,10 +190,12 @@ def list( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return self._get_api_list( - f"/v1/vector_stores/{vector_store_id}/files", + f"/v1/vector_stores/{vector_store_identifier}/files", page=SyncLimitOffset[VectorStoreFile], options=make_request_options( extra_headers=extra_headers, @@ -210,7 +217,7 @@ def delete( self, file_id: str, *, - vector_store_id: str, + vector_store_identifier: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -221,13 +228,13 @@ def delete( """ Delete a file from a vector store. - Args: vector_store_id: The ID of the vector store file_id: The ID of the file to - delete + Args: vector_store_identifier: The ID or name of the vector store file_id: The + ID of the file to delete Returns: VectorStoreFileDeleted: The deleted file Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store file_id: The ID of the file to delete @@ -239,12 +246,14 @@ def delete( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return self._delete( - f"/v1/vector_stores/{vector_store_id}/files/{file_id}", + f"/v1/vector_stores/{vector_store_identifier}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -255,9 +264,11 @@ def search( self, *, query: str, - vector_store_ids: List[str], + vector_store_identifiers: Optional[List[str]] | NotGiven = NOT_GIVEN, + vector_store_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, top_k: int | NotGiven = NOT_GIVEN, filters: Optional[file_search_params.Filters] | NotGiven = NOT_GIVEN, + file_ids: Union[Iterable[object], List[str], None] | NotGiven = NOT_GIVEN, search_options: file_search_params.SearchOptions | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -287,12 +298,14 @@ def search( Args: query: Search query text - vector_store_ids: IDs of vector stores to search + vector_store_identifiers: IDs or names of vector stores to search top_k: Number of results to return filters: Optional filter conditions + file_ids: Optional list of file IDs to filter chunks by (inclusion filter) + search_options: Search configuration options extra_headers: Send extra headers @@ -308,9 +321,11 @@ def search( body=maybe_transform( { "query": query, + "vector_store_identifiers": vector_store_identifiers, "vector_store_ids": vector_store_ids, "top_k": top_k, "filters": filters, + "file_ids": file_ids, "search_options": search_options, }, file_search_params.FileSearchParams, @@ -450,7 +465,7 @@ def with_streaming_response(self) -> AsyncFilesResourceWithStreamingResponse: async def create( self, - vector_store_id: str, + vector_store_identifier: str, *, file_id: str, metadata: object | NotGiven = NOT_GIVEN, @@ -465,13 +480,13 @@ async def create( """ Upload a new file to a vector store for indexing. - Args: vector_store_id: The ID of the vector store to upload to file: The file to - upload and index + Args: vector_store_identifier: The ID or name of the vector store to upload to + file: The file to upload and index Returns: VectorStoreFile: Details of the uploaded and indexed file Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store file_id: ID of the file to add @@ -487,10 +502,12 @@ async def create( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return await self._post( - f"/v1/vector_stores/{vector_store_id}/files", + f"/v1/vector_stores/{vector_store_identifier}/files", body=await async_maybe_transform( { "file_id": file_id, @@ -509,7 +526,7 @@ async def retrieve( self, file_id: str, *, - vector_store_id: str, + vector_store_identifier: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -520,12 +537,13 @@ async def retrieve( """ Get details of a specific file in a vector store. - Args: vector_store_id: The ID of the vector store file_id: The ID of the file + Args: vector_store_identifier: The ID or name of the vector store file_id: The + ID of the file Returns: VectorStoreFile: Details of the vector store file Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store file_id: The ID of the file @@ -537,12 +555,14 @@ async def retrieve( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._get( - f"/v1/vector_stores/{vector_store_id}/files/{file_id}", + f"/v1/vector_stores/{vector_store_identifier}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -551,7 +571,7 @@ async def retrieve( def list( self, - vector_store_id: str, + vector_store_identifier: str, *, limit: int | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, @@ -565,13 +585,13 @@ def list( """ List files indexed in a vector store with pagination. - Args: vector_store_id: The ID of the vector store pagination: Pagination - parameters + Args: vector_store_identifier: The ID or name of the vector store pagination: + Pagination parameters Returns: VectorStoreFileListResponse: Paginated list of vector store files Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store limit: Maximum number of items to return per page @@ -585,10 +605,12 @@ def list( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return self._get_api_list( - f"/v1/vector_stores/{vector_store_id}/files", + f"/v1/vector_stores/{vector_store_identifier}/files", page=AsyncLimitOffset[VectorStoreFile], options=make_request_options( extra_headers=extra_headers, @@ -610,7 +632,7 @@ async def delete( self, file_id: str, *, - vector_store_id: str, + vector_store_identifier: str, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -621,13 +643,13 @@ async def delete( """ Delete a file from a vector store. - Args: vector_store_id: The ID of the vector store file_id: The ID of the file to - delete + Args: vector_store_identifier: The ID or name of the vector store file_id: The + ID of the file to delete Returns: VectorStoreFileDeleted: The deleted file Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store file_id: The ID of the file to delete @@ -639,12 +661,14 @@ async def delete( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) if not file_id: raise ValueError(f"Expected a non-empty value for `file_id` but received {file_id!r}") return await self._delete( - f"/v1/vector_stores/{vector_store_id}/files/{file_id}", + f"/v1/vector_stores/{vector_store_identifier}/files/{file_id}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -655,9 +679,11 @@ async def search( self, *, query: str, - vector_store_ids: List[str], + vector_store_identifiers: Optional[List[str]] | NotGiven = NOT_GIVEN, + vector_store_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, top_k: int | NotGiven = NOT_GIVEN, filters: Optional[file_search_params.Filters] | NotGiven = NOT_GIVEN, + file_ids: Union[Iterable[object], List[str], None] | NotGiven = NOT_GIVEN, search_options: file_search_params.SearchOptions | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -687,12 +713,14 @@ async def search( Args: query: Search query text - vector_store_ids: IDs of vector stores to search + vector_store_identifiers: IDs or names of vector stores to search top_k: Number of results to return filters: Optional filter conditions + file_ids: Optional list of file IDs to filter chunks by (inclusion filter) + search_options: Search configuration options extra_headers: Send extra headers @@ -708,9 +736,11 @@ async def search( body=await async_maybe_transform( { "query": query, + "vector_store_identifiers": vector_store_identifiers, "vector_store_ids": vector_store_ids, "top_k": top_k, "filters": filters, + "file_ids": file_ids, "search_options": search_options, }, file_search_params.FileSearchParams, diff --git a/src/mixedbread/resources/vector_stores/vector_stores.py b/src/mixedbread/resources/vector_stores/vector_stores.py index 18b25941..2d476dac 100644 --- a/src/mixedbread/resources/vector_stores/vector_stores.py +++ b/src/mixedbread/resources/vector_stores/vector_stores.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import List, Optional +from typing import List, Union, Iterable, Optional import httpx @@ -129,7 +129,7 @@ def create( def retrieve( self, - vector_store_id: str, + vector_store_identifier: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -139,14 +139,14 @@ def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VectorStore: """ - Get a vector store by ID. + Get a vector store by ID or name. - Args: vector_store_id: The ID of the vector store to retrieve. + Args: vector_store_identifier: The ID or name of the vector store to retrieve. Returns: VectorStore: The response containing the vector store details. Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store extra_headers: Send extra headers @@ -156,10 +156,12 @@ def retrieve( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return self._get( - f"/v1/vector_stores/{vector_store_id}", + f"/v1/vector_stores/{vector_store_identifier}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -168,7 +170,7 @@ def retrieve( def update( self, - vector_store_id: str, + vector_store_identifier: str, *, name: Optional[str] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, @@ -182,16 +184,16 @@ def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VectorStore: """ - Update a vector store by ID. + Update a vector store by ID or name. - Args: vector_store_id: The ID of the vector store to update. + Args: vector_store_identifier: The ID or name of the vector store to update. vector_store_update: VectorStoreCreate object containing the name, description, and metadata. Returns: VectorStore: The response containing the updated vector store details. Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store name: New name for the vector store @@ -209,10 +211,12 @@ def update( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return self._put( - f"/v1/vector_stores/{vector_store_id}", + f"/v1/vector_stores/{vector_store_identifier}", body=maybe_transform( { "name": name, @@ -233,6 +237,7 @@ def list( *, limit: int | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, + q: Optional[str] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -241,9 +246,10 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> SyncLimitOffset[VectorStore]: """ - List all vector stores. + List all vector stores with optional search. - Args: pagination: The pagination options. + Args: pagination: The pagination options. q: Optional search query to filter + vector stores. Returns: VectorStoreListResponse: The list of vector stores. @@ -252,6 +258,8 @@ def list( offset: Offset of the first item to return + q: Search query for fuzzy matching over name and description fields + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -272,6 +280,7 @@ def list( { "limit": limit, "offset": offset, + "q": q, }, vector_store_list_params.VectorStoreListParams, ), @@ -281,7 +290,7 @@ def list( def delete( self, - vector_store_id: str, + vector_store_identifier: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -291,14 +300,14 @@ def delete( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VectorStoreDeleteResponse: """ - Delete a vector store by ID. + Delete a vector store by ID or name. - Args: vector_store_id: The ID of the vector store to delete. + Args: vector_store_identifier: The ID or name of the vector store to delete. Returns: VectorStore: The response containing the deleted vector store details. Args: - vector_store_id: The ID of the vector store to delete + vector_store_identifier: The ID or name of the vector store to delete extra_headers: Send extra headers @@ -308,10 +317,12 @@ def delete( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return self._delete( - f"/v1/vector_stores/{vector_store_id}", + f"/v1/vector_stores/{vector_store_identifier}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -322,9 +333,11 @@ def question_answering( self, *, query: str | NotGiven = NOT_GIVEN, - vector_store_ids: List[str], + vector_store_identifiers: Optional[List[str]] | NotGiven = NOT_GIVEN, + vector_store_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, top_k: int | NotGiven = NOT_GIVEN, filters: Optional[vector_store_question_answering_params.Filters] | NotGiven = NOT_GIVEN, + file_ids: Union[Iterable[object], List[str], None] | NotGiven = NOT_GIVEN, search_options: VectorStoreChunkSearchOptionsParam | NotGiven = NOT_GIVEN, stream: bool | NotGiven = NOT_GIVEN, qa_options: vector_store_question_answering_params.QaOptions | NotGiven = NOT_GIVEN, @@ -343,12 +356,14 @@ def question_answering( If not provided, the question will be extracted from the passed messages. - vector_store_ids: IDs of vector stores to search + vector_store_identifiers: IDs or names of vector stores to search top_k: Number of results to return filters: Optional filter conditions + file_ids: Optional list of file IDs to filter chunks by (inclusion filter) + search_options: Search configuration options stream: Whether to stream the answer @@ -368,9 +383,11 @@ def question_answering( body=maybe_transform( { "query": query, + "vector_store_identifiers": vector_store_identifiers, "vector_store_ids": vector_store_ids, "top_k": top_k, "filters": filters, + "file_ids": file_ids, "search_options": search_options, "stream": stream, "qa_options": qa_options, @@ -387,9 +404,11 @@ def search( self, *, query: str, - vector_store_ids: List[str], + vector_store_identifiers: Optional[List[str]] | NotGiven = NOT_GIVEN, + vector_store_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, top_k: int | NotGiven = NOT_GIVEN, filters: Optional[vector_store_search_params.Filters] | NotGiven = NOT_GIVEN, + file_ids: Union[Iterable[object], List[str], None] | NotGiven = NOT_GIVEN, search_options: VectorStoreChunkSearchOptionsParam | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -406,7 +425,9 @@ def search( relevance-scored results. Args: search_params: Search configuration including: - query text or - embeddings - metadata filters - pagination parameters - sorting preferences + embeddings - vector_store_ids: List of vector stores to search - file_ids: + Optional list of file IDs to filter chunks by (or tuple of list and condition + operator) - metadata filters - pagination parameters - sorting preferences \\__state: API state dependency \\__ctx: Service context dependency Returns: VectorStoreSearchChunkResponse containing: - List of matched chunks @@ -418,12 +439,14 @@ def search( Args: query: Search query text - vector_store_ids: IDs of vector stores to search + vector_store_identifiers: IDs or names of vector stores to search top_k: Number of results to return filters: Optional filter conditions + file_ids: Optional list of file IDs to filter chunks by (inclusion filter) + search_options: Search configuration options extra_headers: Send extra headers @@ -439,9 +462,11 @@ def search( body=maybe_transform( { "query": query, + "vector_store_identifiers": vector_store_identifiers, "vector_store_ids": vector_store_ids, "top_k": top_k, "filters": filters, + "file_ids": file_ids, "search_options": search_options, }, vector_store_search_params.VectorStoreSearchParams, @@ -539,7 +564,7 @@ async def create( async def retrieve( self, - vector_store_id: str, + vector_store_identifier: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -549,14 +574,14 @@ async def retrieve( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VectorStore: """ - Get a vector store by ID. + Get a vector store by ID or name. - Args: vector_store_id: The ID of the vector store to retrieve. + Args: vector_store_identifier: The ID or name of the vector store to retrieve. Returns: VectorStore: The response containing the vector store details. Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store extra_headers: Send extra headers @@ -566,10 +591,12 @@ async def retrieve( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return await self._get( - f"/v1/vector_stores/{vector_store_id}", + f"/v1/vector_stores/{vector_store_identifier}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -578,7 +605,7 @@ async def retrieve( async def update( self, - vector_store_id: str, + vector_store_identifier: str, *, name: Optional[str] | NotGiven = NOT_GIVEN, description: Optional[str] | NotGiven = NOT_GIVEN, @@ -592,16 +619,16 @@ async def update( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VectorStore: """ - Update a vector store by ID. + Update a vector store by ID or name. - Args: vector_store_id: The ID of the vector store to update. + Args: vector_store_identifier: The ID or name of the vector store to update. vector_store_update: VectorStoreCreate object containing the name, description, and metadata. Returns: VectorStore: The response containing the updated vector store details. Args: - vector_store_id: The ID of the vector store + vector_store_identifier: The ID or name of the vector store name: New name for the vector store @@ -619,10 +646,12 @@ async def update( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return await self._put( - f"/v1/vector_stores/{vector_store_id}", + f"/v1/vector_stores/{vector_store_identifier}", body=await async_maybe_transform( { "name": name, @@ -643,6 +672,7 @@ def list( *, limit: int | NotGiven = NOT_GIVEN, offset: int | NotGiven = NOT_GIVEN, + q: Optional[str] | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. extra_headers: Headers | None = None, @@ -651,9 +681,10 @@ def list( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> AsyncPaginator[VectorStore, AsyncLimitOffset[VectorStore]]: """ - List all vector stores. + List all vector stores with optional search. - Args: pagination: The pagination options. + Args: pagination: The pagination options. q: Optional search query to filter + vector stores. Returns: VectorStoreListResponse: The list of vector stores. @@ -662,6 +693,8 @@ def list( offset: Offset of the first item to return + q: Search query for fuzzy matching over name and description fields + extra_headers: Send extra headers extra_query: Add additional query parameters to the request @@ -682,6 +715,7 @@ def list( { "limit": limit, "offset": offset, + "q": q, }, vector_store_list_params.VectorStoreListParams, ), @@ -691,7 +725,7 @@ def list( async def delete( self, - vector_store_id: str, + vector_store_identifier: str, *, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -701,14 +735,14 @@ async def delete( timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, ) -> VectorStoreDeleteResponse: """ - Delete a vector store by ID. + Delete a vector store by ID or name. - Args: vector_store_id: The ID of the vector store to delete. + Args: vector_store_identifier: The ID or name of the vector store to delete. Returns: VectorStore: The response containing the deleted vector store details. Args: - vector_store_id: The ID of the vector store to delete + vector_store_identifier: The ID or name of the vector store to delete extra_headers: Send extra headers @@ -718,10 +752,12 @@ async def delete( timeout: Override the client-level default timeout for this request, in seconds """ - if not vector_store_id: - raise ValueError(f"Expected a non-empty value for `vector_store_id` but received {vector_store_id!r}") + if not vector_store_identifier: + raise ValueError( + f"Expected a non-empty value for `vector_store_identifier` but received {vector_store_identifier!r}" + ) return await self._delete( - f"/v1/vector_stores/{vector_store_id}", + f"/v1/vector_stores/{vector_store_identifier}", options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), @@ -732,9 +768,11 @@ async def question_answering( self, *, query: str | NotGiven = NOT_GIVEN, - vector_store_ids: List[str], + vector_store_identifiers: Optional[List[str]] | NotGiven = NOT_GIVEN, + vector_store_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, top_k: int | NotGiven = NOT_GIVEN, filters: Optional[vector_store_question_answering_params.Filters] | NotGiven = NOT_GIVEN, + file_ids: Union[Iterable[object], List[str], None] | NotGiven = NOT_GIVEN, search_options: VectorStoreChunkSearchOptionsParam | NotGiven = NOT_GIVEN, stream: bool | NotGiven = NOT_GIVEN, qa_options: vector_store_question_answering_params.QaOptions | NotGiven = NOT_GIVEN, @@ -753,12 +791,14 @@ async def question_answering( If not provided, the question will be extracted from the passed messages. - vector_store_ids: IDs of vector stores to search + vector_store_identifiers: IDs or names of vector stores to search top_k: Number of results to return filters: Optional filter conditions + file_ids: Optional list of file IDs to filter chunks by (inclusion filter) + search_options: Search configuration options stream: Whether to stream the answer @@ -778,9 +818,11 @@ async def question_answering( body=await async_maybe_transform( { "query": query, + "vector_store_identifiers": vector_store_identifiers, "vector_store_ids": vector_store_ids, "top_k": top_k, "filters": filters, + "file_ids": file_ids, "search_options": search_options, "stream": stream, "qa_options": qa_options, @@ -797,9 +839,11 @@ async def search( self, *, query: str, - vector_store_ids: List[str], + vector_store_identifiers: Optional[List[str]] | NotGiven = NOT_GIVEN, + vector_store_ids: Optional[List[str]] | NotGiven = NOT_GIVEN, top_k: int | NotGiven = NOT_GIVEN, filters: Optional[vector_store_search_params.Filters] | NotGiven = NOT_GIVEN, + file_ids: Union[Iterable[object], List[str], None] | NotGiven = NOT_GIVEN, search_options: VectorStoreChunkSearchOptionsParam | NotGiven = NOT_GIVEN, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -816,7 +860,9 @@ async def search( relevance-scored results. Args: search_params: Search configuration including: - query text or - embeddings - metadata filters - pagination parameters - sorting preferences + embeddings - vector_store_ids: List of vector stores to search - file_ids: + Optional list of file IDs to filter chunks by (or tuple of list and condition + operator) - metadata filters - pagination parameters - sorting preferences \\__state: API state dependency \\__ctx: Service context dependency Returns: VectorStoreSearchChunkResponse containing: - List of matched chunks @@ -828,12 +874,14 @@ async def search( Args: query: Search query text - vector_store_ids: IDs of vector stores to search + vector_store_identifiers: IDs or names of vector stores to search top_k: Number of results to return filters: Optional filter conditions + file_ids: Optional list of file IDs to filter chunks by (inclusion filter) + search_options: Search configuration options extra_headers: Send extra headers @@ -849,9 +897,11 @@ async def search( body=await async_maybe_transform( { "query": query, + "vector_store_identifiers": vector_store_identifiers, "vector_store_ids": vector_store_ids, "top_k": top_k, "filters": filters, + "file_ids": file_ids, "search_options": search_options, }, vector_store_search_params.VectorStoreSearchParams, diff --git a/src/mixedbread/types/__init__.py b/src/mixedbread/types/__init__.py index 56f206a5..4b299a86 100644 --- a/src/mixedbread/types/__init__.py +++ b/src/mixedbread/types/__init__.py @@ -44,7 +44,6 @@ from .scored_video_url_input_chunk import ScoredVideoURLInputChunk as ScoredVideoURLInputChunk from .vector_store_delete_response import VectorStoreDeleteResponse as VectorStoreDeleteResponse from .vector_store_search_response import VectorStoreSearchResponse as VectorStoreSearchResponse -from .data_source_oauth2_params_param import DataSourceOauth2ParamsParam as DataSourceOauth2ParamsParam from .vector_store_question_answering_params import ( VectorStoreQuestionAnsweringParams as VectorStoreQuestionAnsweringParams, ) diff --git a/src/mixedbread/types/data_source.py b/src/mixedbread/types/data_source.py index d02682e1..eefb4d3d 100644 --- a/src/mixedbread/types/data_source.py +++ b/src/mixedbread/types/data_source.py @@ -1,14 +1,27 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import Union, Optional from datetime import datetime -from typing_extensions import Literal +from typing_extensions import Literal, Annotated, TypeAlias +from .._utils import PropertyInfo from .._models import BaseModel from .data_source_type import DataSourceType from .data_source_oauth2_params import DataSourceOauth2Params -__all__ = ["DataSource"] +__all__ = ["DataSource", "AuthParams", "AuthParamsDataSourceAPIKeyParams"] + + +class AuthParamsDataSourceAPIKeyParams(BaseModel): + type: Optional[Literal["api_key"]] = None + + api_key: str + """The API key""" + + +AuthParams: TypeAlias = Annotated[ + Union[DataSourceOauth2Params, AuthParamsDataSourceAPIKeyParams, None], PropertyInfo(discriminator="type") +] class DataSource(BaseModel): @@ -30,8 +43,8 @@ class DataSource(BaseModel): metadata: object """The metadata of the data source""" - auth_params: Optional[DataSourceOauth2Params] = None - """Authentication parameters for a OAuth data source.""" + auth_params: Optional[AuthParams] = None + """Authentication parameters""" object: Optional[Literal["data_source"]] = None """The type of the object""" diff --git a/src/mixedbread/types/data_source_create_params.py b/src/mixedbread/types/data_source_create_params.py index af01ebdd..e9794cdb 100644 --- a/src/mixedbread/types/data_source_create_params.py +++ b/src/mixedbread/types/data_source_create_params.py @@ -2,17 +2,24 @@ from __future__ import annotations -from typing import Optional -from typing_extensions import Required, TypedDict +from typing import Union, Optional +from typing_extensions import Literal, Required, TypeAlias, TypedDict from .data_source_type import DataSourceType -from .data_source_oauth2_params_param import DataSourceOauth2ParamsParam -__all__ = ["DataSourceCreateParams"] +__all__ = [ + "DataSourceCreateParams", + "NotionDataSourceCreateOrUpdateParams", + "NotionDataSourceCreateOrUpdateParamsAuthParams", + "NotionDataSourceCreateOrUpdateParamsAuthParamsOAuth2CreateOrUpdateParams", + "NotionDataSourceCreateOrUpdateParamsAuthParamsAPIKeyCreateOrUpdateParams", + "LinearDataSourceCreateOrUpdateParams", + "LinearDataSourceCreateOrUpdateParamsAuthParams", +] -class DataSourceCreateParams(TypedDict, total=False): - type: Required[DataSourceType] +class NotionDataSourceCreateOrUpdateParams(TypedDict, total=False): + type: DataSourceType """The type of data source to create""" name: Required[str] @@ -21,5 +28,46 @@ class DataSourceCreateParams(TypedDict, total=False): metadata: object """The metadata of the data source""" - auth_params: Optional[DataSourceOauth2ParamsParam] - """Authentication parameters for a OAuth data source.""" + auth_params: Optional[NotionDataSourceCreateOrUpdateParamsAuthParams] + """The authentication parameters of the data source. + + Notion supports OAuth2 and API key. + """ + + +class NotionDataSourceCreateOrUpdateParamsAuthParamsOAuth2CreateOrUpdateParams(TypedDict, total=False): + type: Literal["oauth2"] + + +class NotionDataSourceCreateOrUpdateParamsAuthParamsAPIKeyCreateOrUpdateParams(TypedDict, total=False): + type: Literal["api_key"] + + api_key: Required[str] + """The API key""" + + +NotionDataSourceCreateOrUpdateParamsAuthParams: TypeAlias = Union[ + NotionDataSourceCreateOrUpdateParamsAuthParamsOAuth2CreateOrUpdateParams, + NotionDataSourceCreateOrUpdateParamsAuthParamsAPIKeyCreateOrUpdateParams, +] + + +class LinearDataSourceCreateOrUpdateParams(TypedDict, total=False): + type: DataSourceType + """The type of data source to create""" + + name: Required[str] + """The name of the data source""" + + metadata: object + """The metadata of the data source""" + + auth_params: Optional[LinearDataSourceCreateOrUpdateParamsAuthParams] + """Base class for OAuth2 create or update parameters.""" + + +class LinearDataSourceCreateOrUpdateParamsAuthParams(TypedDict, total=False): + type: Literal["oauth2"] + + +DataSourceCreateParams: TypeAlias = Union[NotionDataSourceCreateOrUpdateParams, LinearDataSourceCreateOrUpdateParams] diff --git a/src/mixedbread/types/data_source_oauth2_params.py b/src/mixedbread/types/data_source_oauth2_params.py index 5cda3db5..3e9c8a90 100644 --- a/src/mixedbread/types/data_source_oauth2_params.py +++ b/src/mixedbread/types/data_source_oauth2_params.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import Optional +from typing import Dict, Optional from datetime import datetime from typing_extensions import Literal @@ -15,16 +15,7 @@ class DataSourceOauth2Params(BaseModel): created_at: Optional[datetime] = None """The timestamp when the OAuth2 credentials were created""" - client_id: str - """The OAuth2 client ID""" - - client_secret: str - """The OAuth2 client secret""" - - redirect_uri: str - """The OAuth2 redirect URI""" - - scope: str + scope: Optional[str] = None """The OAuth2 scope""" access_token: Optional[str] = None @@ -38,3 +29,6 @@ class DataSourceOauth2Params(BaseModel): expires_on: Optional[datetime] = None """The OAuth2 token expiration timestamp""" + + additional_params: Optional[Dict[str, object]] = None + """Additional parameters for the OAuth2 flow""" diff --git a/src/mixedbread/types/data_source_oauth2_params_param.py b/src/mixedbread/types/data_source_oauth2_params_param.py deleted file mode 100644 index 72ff4b56..00000000 --- a/src/mixedbread/types/data_source_oauth2_params_param.py +++ /dev/null @@ -1,42 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -from typing import Union, Optional -from datetime import datetime -from typing_extensions import Literal, Required, Annotated, TypedDict - -from .._utils import PropertyInfo - -__all__ = ["DataSourceOauth2ParamsParam"] - - -class DataSourceOauth2ParamsParam(TypedDict, total=False): - type: Literal["oauth2"] - - created_at: Annotated[Union[str, datetime], PropertyInfo(format="iso8601")] - """The timestamp when the OAuth2 credentials were created""" - - client_id: Required[str] - """The OAuth2 client ID""" - - client_secret: Required[str] - """The OAuth2 client secret""" - - redirect_uri: Required[str] - """The OAuth2 redirect URI""" - - scope: Required[str] - """The OAuth2 scope""" - - access_token: Optional[str] - """The OAuth2 access token""" - - refresh_token: Optional[str] - """The OAuth2 refresh token""" - - token_type: Optional[str] - """The OAuth2 token type""" - - expires_on: Annotated[Union[str, datetime, None], PropertyInfo(format="iso8601")] - """The OAuth2 token expiration timestamp""" diff --git a/src/mixedbread/types/data_source_update_params.py b/src/mixedbread/types/data_source_update_params.py index 609704a0..23d34c4a 100644 --- a/src/mixedbread/types/data_source_update_params.py +++ b/src/mixedbread/types/data_source_update_params.py @@ -2,20 +2,72 @@ from __future__ import annotations -from typing import Optional -from typing_extensions import TypedDict +from typing import Union, Optional +from typing_extensions import Literal, Required, TypeAlias, TypedDict -from .data_source_oauth2_params_param import DataSourceOauth2ParamsParam +from .data_source_type import DataSourceType -__all__ = ["DataSourceUpdateParams"] +__all__ = [ + "DataSourceUpdateParams", + "NotionDataSourceCreateOrUpdateParams", + "NotionDataSourceCreateOrUpdateParamsAuthParams", + "NotionDataSourceCreateOrUpdateParamsAuthParamsOAuth2CreateOrUpdateParams", + "NotionDataSourceCreateOrUpdateParamsAuthParamsAPIKeyCreateOrUpdateParams", + "LinearDataSourceCreateOrUpdateParams", + "LinearDataSourceCreateOrUpdateParamsAuthParams", +] -class DataSourceUpdateParams(TypedDict, total=False): - name: Optional[str] +class NotionDataSourceCreateOrUpdateParams(TypedDict, total=False): + type: DataSourceType + """The type of data source to create""" + + name: Required[str] """The name of the data source""" metadata: object """The metadata of the data source""" - auth_params: Optional[DataSourceOauth2ParamsParam] - """Authentication parameters for a OAuth data source.""" + auth_params: Optional[NotionDataSourceCreateOrUpdateParamsAuthParams] + """The authentication parameters of the data source. + + Notion supports OAuth2 and API key. + """ + + +class NotionDataSourceCreateOrUpdateParamsAuthParamsOAuth2CreateOrUpdateParams(TypedDict, total=False): + type: Literal["oauth2"] + + +class NotionDataSourceCreateOrUpdateParamsAuthParamsAPIKeyCreateOrUpdateParams(TypedDict, total=False): + type: Literal["api_key"] + + api_key: Required[str] + """The API key""" + + +NotionDataSourceCreateOrUpdateParamsAuthParams: TypeAlias = Union[ + NotionDataSourceCreateOrUpdateParamsAuthParamsOAuth2CreateOrUpdateParams, + NotionDataSourceCreateOrUpdateParamsAuthParamsAPIKeyCreateOrUpdateParams, +] + + +class LinearDataSourceCreateOrUpdateParams(TypedDict, total=False): + type: DataSourceType + """The type of data source to create""" + + name: Required[str] + """The name of the data source""" + + metadata: object + """The metadata of the data source""" + + auth_params: Optional[LinearDataSourceCreateOrUpdateParamsAuthParams] + """Base class for OAuth2 create or update parameters.""" + + +class LinearDataSourceCreateOrUpdateParamsAuthParams(TypedDict, total=False): + type: Literal["oauth2"] + + +DataSourceUpdateParams: TypeAlias = Union[NotionDataSourceCreateOrUpdateParams, LinearDataSourceCreateOrUpdateParams] diff --git a/src/mixedbread/types/data_sources/connector_create_params.py b/src/mixedbread/types/data_sources/connector_create_params.py index 6b1f8ed4..43c23c67 100644 --- a/src/mixedbread/types/data_sources/connector_create_params.py +++ b/src/mixedbread/types/data_sources/connector_create_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Optional +from typing import Union from typing_extensions import Required, TypedDict __all__ = ["ConnectorCreateParams"] @@ -21,5 +21,12 @@ class ConnectorCreateParams(TypedDict, total=False): metadata: object """The metadata of the connector""" - polling_interval: Optional[str] - """The polling interval of the connector""" + polling_interval: Union[int, str, None] + """Polling interval for the connector. + + Defaults to 30 minutes if not specified. Can be provided as: + + - int: Number of seconds (e.g., 1800 for 30 minutes) + - str: Duration string (e.g., '30m', '1h', '2d') or ISO 8601 format (e.g., + 'PT30M', 'P1D') Valid range: 15 seconds to 30 days + """ diff --git a/src/mixedbread/types/data_sources/connector_update_params.py b/src/mixedbread/types/data_sources/connector_update_params.py index 80434be2..7e0d112b 100644 --- a/src/mixedbread/types/data_sources/connector_update_params.py +++ b/src/mixedbread/types/data_sources/connector_update_params.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Dict, Optional +from typing import Dict, Union, Optional from typing_extensions import Required, TypedDict __all__ = ["ConnectorUpdateParams"] @@ -21,5 +21,12 @@ class ConnectorUpdateParams(TypedDict, total=False): trigger_sync: Optional[bool] """Whether the connector should be synced after update""" - polling_interval: Optional[str] - """The polling interval of the connector""" + polling_interval: Union[int, str, None] + """Polling interval for the connector. + + Defaults to 30 minutes if not specified. Can be provided as: + + - int: Number of seconds (e.g., 1800 for 30 minutes) + - str: Duration string (e.g., '30m', '1h', '2d') or ISO 8601 format (e.g., + 'PT30M', 'P1D') Valid range: 15 seconds to 30 days + """ diff --git a/src/mixedbread/types/extractions/image_url_input_param.py b/src/mixedbread/types/extractions/image_url_input_param.py index 6c361176..a4480f76 100644 --- a/src/mixedbread/types/extractions/image_url_input_param.py +++ b/src/mixedbread/types/extractions/image_url_input_param.py @@ -11,6 +11,9 @@ class ImageURL(TypedDict, total=False): url: Required[str] """The image URL. Can be either a URL or a Data URI.""" + format: str + """The image format/mimetype""" + class ImageURLInputParam(TypedDict, total=False): type: Literal["image_url"] diff --git a/src/mixedbread/types/scored_image_url_input_chunk.py b/src/mixedbread/types/scored_image_url_input_chunk.py index ec6ba9dd..f160a46d 100644 --- a/src/mixedbread/types/scored_image_url_input_chunk.py +++ b/src/mixedbread/types/scored_image_url_input_chunk.py @@ -12,6 +12,9 @@ class ImageURL(BaseModel): url: str """The image URL. Can be either a URL or a Data URI.""" + format: Optional[str] = None + """The image format/mimetype""" + class ScoredImageURLInputChunk(BaseModel): chunk_index: int diff --git a/src/mixedbread/types/vector_store.py b/src/mixedbread/types/vector_store.py index 65cb0ede..c2ab8879 100644 --- a/src/mixedbread/types/vector_store.py +++ b/src/mixedbread/types/vector_store.py @@ -11,6 +11,9 @@ class FileCounts(BaseModel): + pending: Optional[int] = None + """Number of files waiting to be processed""" + in_progress: Optional[int] = None """Number of files currently being processed""" diff --git a/src/mixedbread/types/vector_store_chunk_search_options_param.py b/src/mixedbread/types/vector_store_chunk_search_options_param.py index a2396bec..f5fb8437 100644 --- a/src/mixedbread/types/vector_store_chunk_search_options_param.py +++ b/src/mixedbread/types/vector_store_chunk_search_options_param.py @@ -2,9 +2,27 @@ from __future__ import annotations -from typing_extensions import TypedDict +from typing import List, Union, Optional +from typing_extensions import TypeAlias, TypedDict -__all__ = ["VectorStoreChunkSearchOptionsParam"] +__all__ = ["VectorStoreChunkSearchOptionsParam", "Rerank", "RerankRerankConfig"] + + +class RerankRerankConfig(TypedDict, total=False): + model: str + """The name of the reranking model""" + + with_metadata: Union[bool, List[str]] + """Whether to include metadata in the reranked results""" + + top_k: Optional[int] + """Maximum number of results to return after reranking. + + If None, returns all reranked results. + """ + + +Rerank: TypeAlias = Union[bool, RerankRerankConfig] class VectorStoreChunkSearchOptionsParam(TypedDict, total=False): @@ -14,5 +32,8 @@ class VectorStoreChunkSearchOptionsParam(TypedDict, total=False): rewrite_query: bool """Whether to rewrite the query""" + rerank: Optional[Rerank] + """Whether to rerank results and optional reranking configuration""" + return_metadata: bool """Whether to return file metadata""" diff --git a/src/mixedbread/types/vector_store_list_params.py b/src/mixedbread/types/vector_store_list_params.py index 39225421..4f649424 100644 --- a/src/mixedbread/types/vector_store_list_params.py +++ b/src/mixedbread/types/vector_store_list_params.py @@ -2,6 +2,7 @@ from __future__ import annotations +from typing import Optional from typing_extensions import TypedDict __all__ = ["VectorStoreListParams"] @@ -13,3 +14,6 @@ class VectorStoreListParams(TypedDict, total=False): offset: int """Offset of the first item to return""" + + q: Optional[str] + """Search query for fuzzy matching over name and description fields""" diff --git a/src/mixedbread/types/vector_store_question_answering_params.py b/src/mixedbread/types/vector_store_question_answering_params.py index abb7919b..b34189b3 100644 --- a/src/mixedbread/types/vector_store_question_answering_params.py +++ b/src/mixedbread/types/vector_store_question_answering_params.py @@ -3,7 +3,7 @@ from __future__ import annotations from typing import List, Union, Iterable, Optional -from typing_extensions import Required, TypeAlias, TypedDict +from typing_extensions import TypeAlias, TypedDict from .shared_params.search_filter_condition import SearchFilterCondition from .vector_store_chunk_search_options_param import VectorStoreChunkSearchOptionsParam @@ -18,8 +18,10 @@ class VectorStoreQuestionAnsweringParams(TypedDict, total=False): If not provided, the question will be extracted from the passed messages. """ - vector_store_ids: Required[List[str]] - """IDs of vector stores to search""" + vector_store_identifiers: Optional[List[str]] + """IDs or names of vector stores to search""" + + vector_store_ids: Optional[List[str]] top_k: int """Number of results to return""" @@ -27,6 +29,9 @@ class VectorStoreQuestionAnsweringParams(TypedDict, total=False): filters: Optional[Filters] """Optional filter conditions""" + file_ids: Union[Iterable[object], List[str], None] + """Optional list of file IDs to filter chunks by (inclusion filter)""" + search_options: VectorStoreChunkSearchOptionsParam """Search configuration options""" diff --git a/src/mixedbread/types/vector_store_search_params.py b/src/mixedbread/types/vector_store_search_params.py index e0edc1bb..48fc21e1 100644 --- a/src/mixedbread/types/vector_store_search_params.py +++ b/src/mixedbread/types/vector_store_search_params.py @@ -15,8 +15,10 @@ class VectorStoreSearchParams(TypedDict, total=False): query: Required[str] """Search query text""" - vector_store_ids: Required[List[str]] - """IDs of vector stores to search""" + vector_store_identifiers: Optional[List[str]] + """IDs or names of vector stores to search""" + + vector_store_ids: Optional[List[str]] top_k: int """Number of results to return""" @@ -24,6 +26,9 @@ class VectorStoreSearchParams(TypedDict, total=False): filters: Optional[Filters] """Optional filter conditions""" + file_ids: Union[Iterable[object], List[str], None] + """Optional list of file IDs to filter chunks by (inclusion filter)""" + search_options: VectorStoreChunkSearchOptionsParam """Search configuration options""" diff --git a/src/mixedbread/types/vector_stores/file_search_params.py b/src/mixedbread/types/vector_stores/file_search_params.py index c34d7611..2844c28a 100644 --- a/src/mixedbread/types/vector_stores/file_search_params.py +++ b/src/mixedbread/types/vector_stores/file_search_params.py @@ -7,15 +7,24 @@ from ..shared_params.search_filter_condition import SearchFilterCondition -__all__ = ["FileSearchParams", "Filters", "FiltersUnionMember2", "SearchOptions"] +__all__ = [ + "FileSearchParams", + "Filters", + "FiltersUnionMember2", + "SearchOptions", + "SearchOptionsRerank", + "SearchOptionsRerankRerankConfig", +] class FileSearchParams(TypedDict, total=False): query: Required[str] """Search query text""" - vector_store_ids: Required[List[str]] - """IDs of vector stores to search""" + vector_store_identifiers: Optional[List[str]] + """IDs or names of vector stores to search""" + + vector_store_ids: Optional[List[str]] top_k: int """Number of results to return""" @@ -23,6 +32,9 @@ class FileSearchParams(TypedDict, total=False): filters: Optional[Filters] """Optional filter conditions""" + file_ids: Union[Iterable[object], List[str], None] + """Optional list of file IDs to filter chunks by (inclusion filter)""" + search_options: SearchOptions """Search configuration options""" @@ -32,6 +44,23 @@ class FileSearchParams(TypedDict, total=False): Filters: TypeAlias = Union["SearchFilter", SearchFilterCondition, Iterable[FiltersUnionMember2]] +class SearchOptionsRerankRerankConfig(TypedDict, total=False): + model: str + """The name of the reranking model""" + + with_metadata: Union[bool, List[str]] + """Whether to include metadata in the reranked results""" + + top_k: Optional[int] + """Maximum number of results to return after reranking. + + If None, returns all reranked results. + """ + + +SearchOptionsRerank: TypeAlias = Union[bool, SearchOptionsRerankRerankConfig] + + class SearchOptions(TypedDict, total=False): score_threshold: float """Minimum similarity score threshold""" @@ -39,6 +68,9 @@ class SearchOptions(TypedDict, total=False): rewrite_query: bool """Whether to rewrite the query""" + rerank: Optional[SearchOptionsRerank] + """Whether to rerank results and optional reranking configuration""" + return_metadata: bool """Whether to return file metadata""" diff --git a/src/mixedbread/types/vector_stores/scored_vector_store_file.py b/src/mixedbread/types/vector_stores/scored_vector_store_file.py index 7c702c1c..919dffec 100644 --- a/src/mixedbread/types/vector_stores/scored_vector_store_file.py +++ b/src/mixedbread/types/vector_stores/scored_vector_store_file.py @@ -29,7 +29,7 @@ class ScoredVectorStoreFile(BaseModel): metadata: Optional[object] = None """Optional file metadata""" - status: Optional[str] = None + status: Optional[Literal["pending", "in_progress", "cancelled", "completed", "failed"]] = None """Processing status of the file""" last_error: Optional[object] = None diff --git a/src/mixedbread/types/vector_stores/vector_store_file.py b/src/mixedbread/types/vector_stores/vector_store_file.py index 39bdb685..d6e5efda 100644 --- a/src/mixedbread/types/vector_stores/vector_store_file.py +++ b/src/mixedbread/types/vector_stores/vector_store_file.py @@ -19,7 +19,7 @@ class VectorStoreFile(BaseModel): metadata: Optional[object] = None """Optional file metadata""" - status: Optional[str] = None + status: Optional[Literal["pending", "in_progress", "cancelled", "completed", "failed"]] = None """Processing status of the file""" last_error: Optional[object] = None diff --git a/tests/api_resources/data_sources/test_connectors.py b/tests/api_resources/data_sources/test_connectors.py index f25e9ce0..fb95955d 100644 --- a/tests/api_resources/data_sources/test_connectors.py +++ b/tests/api_resources/data_sources/test_connectors.py @@ -37,7 +37,7 @@ def test_method_create_with_all_params(self, client: Mixedbread) -> None: name="name", trigger_sync=True, metadata={}, - polling_interval="polling_interval", + polling_interval=1800, ) assert_matches_type(DataSourceConnector, connector, path=["response"]) @@ -139,7 +139,7 @@ def test_method_update_with_all_params(self, client: Mixedbread) -> None: name="name", metadata={"foo": "bar"}, trigger_sync=True, - polling_interval="polling_interval", + polling_interval=1800, ) assert_matches_type(DataSourceConnector, connector, path=["response"]) @@ -298,7 +298,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncMixedbread name="name", trigger_sync=True, metadata={}, - polling_interval="polling_interval", + polling_interval=1800, ) assert_matches_type(DataSourceConnector, connector, path=["response"]) @@ -400,7 +400,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncMixedbread name="name", metadata={"foo": "bar"}, trigger_sync=True, - polling_interval="polling_interval", + polling_interval=1800, ) assert_matches_type(DataSourceConnector, connector, path=["response"]) diff --git a/tests/api_resources/test_chat.py b/tests/api_resources/test_chat.py deleted file mode 100644 index 65341369..00000000 --- a/tests/api_resources/test_chat.py +++ /dev/null @@ -1,71 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from __future__ import annotations - -import os -from typing import Any, cast - -import pytest - -from mixedbread import Mixedbread, AsyncMixedbread -from tests.utils import assert_matches_type - -base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") - - -class TestChat: - parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - def test_method_create_completion(self, client: Mixedbread) -> None: - chat = client.chat.create_completion() - assert_matches_type(object, chat, path=["response"]) - - @parametrize - def test_raw_response_create_completion(self, client: Mixedbread) -> None: - response = client.chat.with_raw_response.create_completion() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - chat = response.parse() - assert_matches_type(object, chat, path=["response"]) - - @parametrize - def test_streaming_response_create_completion(self, client: Mixedbread) -> None: - with client.chat.with_streaming_response.create_completion() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - chat = response.parse() - assert_matches_type(object, chat, path=["response"]) - - assert cast(Any, response.is_closed) is True - - -class TestAsyncChat: - parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) - - @parametrize - async def test_method_create_completion(self, async_client: AsyncMixedbread) -> None: - chat = await async_client.chat.create_completion() - assert_matches_type(object, chat, path=["response"]) - - @parametrize - async def test_raw_response_create_completion(self, async_client: AsyncMixedbread) -> None: - response = await async_client.chat.with_raw_response.create_completion() - - assert response.is_closed is True - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - chat = await response.parse() - assert_matches_type(object, chat, path=["response"]) - - @parametrize - async def test_streaming_response_create_completion(self, async_client: AsyncMixedbread) -> None: - async with async_client.chat.with_streaming_response.create_completion() as response: - assert not response.is_closed - assert response.http_request.headers.get("X-Stainless-Lang") == "python" - - chat = await response.parse() - assert_matches_type(object, chat, path=["response"]) - - assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_data_sources.py b/tests/api_resources/test_data_sources.py index be95dcb7..28f502e2 100644 --- a/tests/api_resources/test_data_sources.py +++ b/tests/api_resources/test_data_sources.py @@ -13,7 +13,6 @@ DataSource, DataSourceDeleteResponse, ) -from mixedbread._utils import parse_datetime from mixedbread.pagination import SyncLimitOffset, AsyncLimitOffset base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -23,38 +22,25 @@ class TestDataSources: parametrize = pytest.mark.parametrize("client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - def test_method_create(self, client: Mixedbread) -> None: + def test_method_create_overload_1(self, client: Mixedbread) -> None: data_source = client.data_sources.create( - type="notion", name="name", ) assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - def test_method_create_with_all_params(self, client: Mixedbread) -> None: + def test_method_create_with_all_params_overload_1(self, client: Mixedbread) -> None: data_source = client.data_sources.create( type="notion", name="name", metadata={}, - auth_params={ - "type": "oauth2", - "created_at": parse_datetime("2019-12-27T18:11:19.117Z"), - "client_id": "client_id", - "client_secret": "client_secret", - "redirect_uri": "redirect_uri", - "scope": "scope", - "access_token": "access_token", - "refresh_token": "refresh_token", - "token_type": "token_type", - "expires_on": parse_datetime("2019-12-27T18:11:19.117Z"), - }, + auth_params={"type": "oauth2"}, ) assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - def test_raw_response_create(self, client: Mixedbread) -> None: + def test_raw_response_create_overload_1(self, client: Mixedbread) -> None: response = client.data_sources.with_raw_response.create( - type="notion", name="name", ) @@ -64,10 +50,50 @@ def test_raw_response_create(self, client: Mixedbread) -> None: assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - def test_streaming_response_create(self, client: Mixedbread) -> None: + def test_streaming_response_create_overload_1(self, client: Mixedbread) -> None: with client.data_sources.with_streaming_response.create( + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + data_source = response.parse() + assert_matches_type(DataSource, data_source, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_method_create_overload_2(self, client: Mixedbread) -> None: + data_source = client.data_sources.create( + name="name", + ) + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + def test_method_create_with_all_params_overload_2(self, client: Mixedbread) -> None: + data_source = client.data_sources.create( type="notion", name="name", + metadata={}, + auth_params={"type": "oauth2"}, + ) + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + def test_raw_response_create_overload_2(self, client: Mixedbread) -> None: + response = client.data_sources.with_raw_response.create( + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + data_source = response.parse() + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + def test_streaming_response_create_overload_2(self, client: Mixedbread) -> None: + with client.data_sources.with_streaming_response.create( + name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -116,37 +142,29 @@ def test_path_params_retrieve(self, client: Mixedbread) -> None: ) @parametrize - def test_method_update(self, client: Mixedbread) -> None: + def test_method_update_overload_1(self, client: Mixedbread) -> None: data_source = client.data_sources.update( data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", ) assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - def test_method_update_with_all_params(self, client: Mixedbread) -> None: + def test_method_update_with_all_params_overload_1(self, client: Mixedbread) -> None: data_source = client.data_sources.update( data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + type="notion", name="name", metadata={}, - auth_params={ - "type": "oauth2", - "created_at": parse_datetime("2019-12-27T18:11:19.117Z"), - "client_id": "client_id", - "client_secret": "client_secret", - "redirect_uri": "redirect_uri", - "scope": "scope", - "access_token": "access_token", - "refresh_token": "refresh_token", - "token_type": "token_type", - "expires_on": parse_datetime("2019-12-27T18:11:19.117Z"), - }, + auth_params={"type": "oauth2"}, ) assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - def test_raw_response_update(self, client: Mixedbread) -> None: + def test_raw_response_update_overload_1(self, client: Mixedbread) -> None: response = client.data_sources.with_raw_response.update( data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", ) assert response.is_closed is True @@ -155,9 +173,63 @@ def test_raw_response_update(self, client: Mixedbread) -> None: assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - def test_streaming_response_update(self, client: Mixedbread) -> None: + def test_streaming_response_update_overload_1(self, client: Mixedbread) -> None: with client.data_sources.with_streaming_response.update( data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + data_source = response.parse() + assert_matches_type(DataSource, data_source, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + def test_path_params_update_overload_1(self, client: Mixedbread) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `data_source_id` but received ''"): + client.data_sources.with_raw_response.update( + data_source_id="", + name="name", + ) + + @parametrize + def test_method_update_overload_2(self, client: Mixedbread) -> None: + data_source = client.data_sources.update( + data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", + ) + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + def test_method_update_with_all_params_overload_2(self, client: Mixedbread) -> None: + data_source = client.data_sources.update( + data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + type="notion", + name="name", + metadata={}, + auth_params={"type": "oauth2"}, + ) + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + def test_raw_response_update_overload_2(self, client: Mixedbread) -> None: + response = client.data_sources.with_raw_response.update( + data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + data_source = response.parse() + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + def test_streaming_response_update_overload_2(self, client: Mixedbread) -> None: + with client.data_sources.with_streaming_response.update( + data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -168,10 +240,11 @@ def test_streaming_response_update(self, client: Mixedbread) -> None: assert cast(Any, response.is_closed) is True @parametrize - def test_path_params_update(self, client: Mixedbread) -> None: + def test_path_params_update_overload_2(self, client: Mixedbread) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `data_source_id` but received ''"): client.data_sources.with_raw_response.update( data_source_id="", + name="name", ) @parametrize @@ -250,38 +323,25 @@ class TestAsyncDataSources: parametrize = pytest.mark.parametrize("async_client", [False, True], indirect=True, ids=["loose", "strict"]) @parametrize - async def test_method_create(self, async_client: AsyncMixedbread) -> None: + async def test_method_create_overload_1(self, async_client: AsyncMixedbread) -> None: data_source = await async_client.data_sources.create( - type="notion", name="name", ) assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - async def test_method_create_with_all_params(self, async_client: AsyncMixedbread) -> None: + async def test_method_create_with_all_params_overload_1(self, async_client: AsyncMixedbread) -> None: data_source = await async_client.data_sources.create( type="notion", name="name", metadata={}, - auth_params={ - "type": "oauth2", - "created_at": parse_datetime("2019-12-27T18:11:19.117Z"), - "client_id": "client_id", - "client_secret": "client_secret", - "redirect_uri": "redirect_uri", - "scope": "scope", - "access_token": "access_token", - "refresh_token": "refresh_token", - "token_type": "token_type", - "expires_on": parse_datetime("2019-12-27T18:11:19.117Z"), - }, + auth_params={"type": "oauth2"}, ) assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - async def test_raw_response_create(self, async_client: AsyncMixedbread) -> None: + async def test_raw_response_create_overload_1(self, async_client: AsyncMixedbread) -> None: response = await async_client.data_sources.with_raw_response.create( - type="notion", name="name", ) @@ -291,10 +351,50 @@ async def test_raw_response_create(self, async_client: AsyncMixedbread) -> None: assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - async def test_streaming_response_create(self, async_client: AsyncMixedbread) -> None: + async def test_streaming_response_create_overload_1(self, async_client: AsyncMixedbread) -> None: async with async_client.data_sources.with_streaming_response.create( + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + data_source = await response.parse() + assert_matches_type(DataSource, data_source, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_method_create_overload_2(self, async_client: AsyncMixedbread) -> None: + data_source = await async_client.data_sources.create( + name="name", + ) + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + async def test_method_create_with_all_params_overload_2(self, async_client: AsyncMixedbread) -> None: + data_source = await async_client.data_sources.create( type="notion", name="name", + metadata={}, + auth_params={"type": "oauth2"}, + ) + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + async def test_raw_response_create_overload_2(self, async_client: AsyncMixedbread) -> None: + response = await async_client.data_sources.with_raw_response.create( + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + data_source = await response.parse() + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + async def test_streaming_response_create_overload_2(self, async_client: AsyncMixedbread) -> None: + async with async_client.data_sources.with_streaming_response.create( + name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -343,37 +443,29 @@ async def test_path_params_retrieve(self, async_client: AsyncMixedbread) -> None ) @parametrize - async def test_method_update(self, async_client: AsyncMixedbread) -> None: + async def test_method_update_overload_1(self, async_client: AsyncMixedbread) -> None: data_source = await async_client.data_sources.update( data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", ) assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - async def test_method_update_with_all_params(self, async_client: AsyncMixedbread) -> None: + async def test_method_update_with_all_params_overload_1(self, async_client: AsyncMixedbread) -> None: data_source = await async_client.data_sources.update( data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + type="notion", name="name", metadata={}, - auth_params={ - "type": "oauth2", - "created_at": parse_datetime("2019-12-27T18:11:19.117Z"), - "client_id": "client_id", - "client_secret": "client_secret", - "redirect_uri": "redirect_uri", - "scope": "scope", - "access_token": "access_token", - "refresh_token": "refresh_token", - "token_type": "token_type", - "expires_on": parse_datetime("2019-12-27T18:11:19.117Z"), - }, + auth_params={"type": "oauth2"}, ) assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - async def test_raw_response_update(self, async_client: AsyncMixedbread) -> None: + async def test_raw_response_update_overload_1(self, async_client: AsyncMixedbread) -> None: response = await async_client.data_sources.with_raw_response.update( data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", ) assert response.is_closed is True @@ -382,9 +474,63 @@ async def test_raw_response_update(self, async_client: AsyncMixedbread) -> None: assert_matches_type(DataSource, data_source, path=["response"]) @parametrize - async def test_streaming_response_update(self, async_client: AsyncMixedbread) -> None: + async def test_streaming_response_update_overload_1(self, async_client: AsyncMixedbread) -> None: async with async_client.data_sources.with_streaming_response.update( data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", + ) as response: + assert not response.is_closed + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + + data_source = await response.parse() + assert_matches_type(DataSource, data_source, path=["response"]) + + assert cast(Any, response.is_closed) is True + + @parametrize + async def test_path_params_update_overload_1(self, async_client: AsyncMixedbread) -> None: + with pytest.raises(ValueError, match=r"Expected a non-empty value for `data_source_id` but received ''"): + await async_client.data_sources.with_raw_response.update( + data_source_id="", + name="name", + ) + + @parametrize + async def test_method_update_overload_2(self, async_client: AsyncMixedbread) -> None: + data_source = await async_client.data_sources.update( + data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", + ) + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + async def test_method_update_with_all_params_overload_2(self, async_client: AsyncMixedbread) -> None: + data_source = await async_client.data_sources.update( + data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + type="notion", + name="name", + metadata={}, + auth_params={"type": "oauth2"}, + ) + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + async def test_raw_response_update_overload_2(self, async_client: AsyncMixedbread) -> None: + response = await async_client.data_sources.with_raw_response.update( + data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", + ) + + assert response.is_closed is True + assert response.http_request.headers.get("X-Stainless-Lang") == "python" + data_source = await response.parse() + assert_matches_type(DataSource, data_source, path=["response"]) + + @parametrize + async def test_streaming_response_update_overload_2(self, async_client: AsyncMixedbread) -> None: + async with async_client.data_sources.with_streaming_response.update( + data_source_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + name="name", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -395,10 +541,11 @@ async def test_streaming_response_update(self, async_client: AsyncMixedbread) -> assert cast(Any, response.is_closed) is True @parametrize - async def test_path_params_update(self, async_client: AsyncMixedbread) -> None: + async def test_path_params_update_overload_2(self, async_client: AsyncMixedbread) -> None: with pytest.raises(ValueError, match=r"Expected a non-empty value for `data_source_id` but received ''"): await async_client.data_sources.with_raw_response.update( data_source_id="", + name="name", ) @parametrize diff --git a/tests/api_resources/test_vector_stores.py b/tests/api_resources/test_vector_stores.py index 4cbe5b96..0dfbf64a 100644 --- a/tests/api_resources/test_vector_stores.py +++ b/tests/api_resources/test_vector_stores.py @@ -65,14 +65,14 @@ def test_streaming_response_create(self, client: Mixedbread) -> None: @parametrize def test_method_retrieve(self, client: Mixedbread) -> None: vector_store = client.vector_stores.retrieve( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_raw_response_retrieve(self, client: Mixedbread) -> None: response = client.vector_stores.with_raw_response.retrieve( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) assert response.is_closed is True @@ -83,7 +83,7 @@ def test_raw_response_retrieve(self, client: Mixedbread) -> None: @parametrize def test_streaming_response_retrieve(self, client: Mixedbread) -> None: with client.vector_stores.with_streaming_response.retrieve( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -95,7 +95,9 @@ def test_streaming_response_retrieve(self, client: Mixedbread) -> None: @parametrize def test_path_params_retrieve(self, client: Mixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): client.vector_stores.with_raw_response.retrieve( "", ) @@ -103,14 +105,14 @@ def test_path_params_retrieve(self, client: Mixedbread) -> None: @parametrize def test_method_update(self, client: Mixedbread) -> None: vector_store = client.vector_stores.update( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize def test_method_update_with_all_params(self, client: Mixedbread) -> None: vector_store = client.vector_stores.update( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", name="x", description="description", expires_after={ @@ -124,7 +126,7 @@ def test_method_update_with_all_params(self, client: Mixedbread) -> None: @parametrize def test_raw_response_update(self, client: Mixedbread) -> None: response = client.vector_stores.with_raw_response.update( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert response.is_closed is True @@ -135,7 +137,7 @@ def test_raw_response_update(self, client: Mixedbread) -> None: @parametrize def test_streaming_response_update(self, client: Mixedbread) -> None: with client.vector_stores.with_streaming_response.update( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -147,9 +149,11 @@ def test_streaming_response_update(self, client: Mixedbread) -> None: @parametrize def test_path_params_update(self, client: Mixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): client.vector_stores.with_raw_response.update( - vector_store_id="", + vector_store_identifier="", ) @parametrize @@ -162,6 +166,7 @@ def test_method_list_with_all_params(self, client: Mixedbread) -> None: vector_store = client.vector_stores.list( limit=1000, offset=0, + q="x", ) assert_matches_type(SyncLimitOffset[VectorStore], vector_store, path=["response"]) @@ -188,14 +193,14 @@ def test_streaming_response_list(self, client: Mixedbread) -> None: @parametrize def test_method_delete(self, client: Mixedbread) -> None: vector_store = client.vector_stores.delete( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) assert_matches_type(VectorStoreDeleteResponse, vector_store, path=["response"]) @parametrize def test_raw_response_delete(self, client: Mixedbread) -> None: response = client.vector_stores.with_raw_response.delete( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) assert response.is_closed is True @@ -206,7 +211,7 @@ def test_raw_response_delete(self, client: Mixedbread) -> None: @parametrize def test_streaming_response_delete(self, client: Mixedbread) -> None: with client.vector_stores.with_streaming_response.delete( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -218,23 +223,24 @@ def test_streaming_response_delete(self, client: Mixedbread) -> None: @parametrize def test_path_params_delete(self, client: Mixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): client.vector_stores.with_raw_response.delete( "", ) @parametrize def test_method_question_answering(self, client: Mixedbread) -> None: - vector_store = client.vector_stores.question_answering( - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - ) + vector_store = client.vector_stores.question_answering() assert_matches_type(VectorStoreQuestionAnsweringResponse, vector_store, path=["response"]) @parametrize def test_method_question_answering_with_all_params(self, client: Mixedbread) -> None: vector_store = client.vector_stores.question_answering( query="x", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + vector_store_identifiers=["string"], + vector_store_ids=["string"], top_k=1, filters={ "all": [ @@ -274,9 +280,11 @@ def test_method_question_answering_with_all_params(self, client: Mixedbread) -> }, ], }, + file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"], search_options={ "score_threshold": 0, "rewrite_query": True, + "rerank": True, "return_metadata": True, }, stream=True, @@ -289,9 +297,7 @@ def test_method_question_answering_with_all_params(self, client: Mixedbread) -> @parametrize def test_raw_response_question_answering(self, client: Mixedbread) -> None: - response = client.vector_stores.with_raw_response.question_answering( - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - ) + response = client.vector_stores.with_raw_response.question_answering() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -300,9 +306,7 @@ def test_raw_response_question_answering(self, client: Mixedbread) -> None: @parametrize def test_streaming_response_question_answering(self, client: Mixedbread) -> None: - with client.vector_stores.with_streaming_response.question_answering( - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - ) as response: + with client.vector_stores.with_streaming_response.question_answering() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -315,7 +319,6 @@ def test_streaming_response_question_answering(self, client: Mixedbread) -> None def test_method_search(self, client: Mixedbread) -> None: vector_store = client.vector_stores.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) @@ -323,7 +326,8 @@ def test_method_search(self, client: Mixedbread) -> None: def test_method_search_with_all_params(self, client: Mixedbread) -> None: vector_store = client.vector_stores.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + vector_store_identifiers=["string"], + vector_store_ids=["string"], top_k=1, filters={ "all": [ @@ -363,9 +367,11 @@ def test_method_search_with_all_params(self, client: Mixedbread) -> None: }, ], }, + file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"], search_options={ "score_threshold": 0, "rewrite_query": True, + "rerank": True, "return_metadata": True, }, ) @@ -375,7 +381,6 @@ def test_method_search_with_all_params(self, client: Mixedbread) -> None: def test_raw_response_search(self, client: Mixedbread) -> None: response = client.vector_stores.with_raw_response.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) assert response.is_closed is True @@ -387,7 +392,6 @@ def test_raw_response_search(self, client: Mixedbread) -> None: def test_streaming_response_search(self, client: Mixedbread) -> None: with client.vector_stores.with_streaming_response.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -443,14 +447,14 @@ async def test_streaming_response_create(self, async_client: AsyncMixedbread) -> @parametrize async def test_method_retrieve(self, async_client: AsyncMixedbread) -> None: vector_store = await async_client.vector_stores.retrieve( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_raw_response_retrieve(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.with_raw_response.retrieve( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) assert response.is_closed is True @@ -461,7 +465,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncMixedbread) -> Non @parametrize async def test_streaming_response_retrieve(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.with_streaming_response.retrieve( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -473,7 +477,9 @@ async def test_streaming_response_retrieve(self, async_client: AsyncMixedbread) @parametrize async def test_path_params_retrieve(self, async_client: AsyncMixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): await async_client.vector_stores.with_raw_response.retrieve( "", ) @@ -481,14 +487,14 @@ async def test_path_params_retrieve(self, async_client: AsyncMixedbread) -> None @parametrize async def test_method_update(self, async_client: AsyncMixedbread) -> None: vector_store = await async_client.vector_stores.update( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert_matches_type(VectorStore, vector_store, path=["response"]) @parametrize async def test_method_update_with_all_params(self, async_client: AsyncMixedbread) -> None: vector_store = await async_client.vector_stores.update( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", name="x", description="description", expires_after={ @@ -502,7 +508,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncMixedbread @parametrize async def test_raw_response_update(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.with_raw_response.update( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert response.is_closed is True @@ -513,7 +519,7 @@ async def test_raw_response_update(self, async_client: AsyncMixedbread) -> None: @parametrize async def test_streaming_response_update(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.with_streaming_response.update( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -525,9 +531,11 @@ async def test_streaming_response_update(self, async_client: AsyncMixedbread) -> @parametrize async def test_path_params_update(self, async_client: AsyncMixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): await async_client.vector_stores.with_raw_response.update( - vector_store_id="", + vector_store_identifier="", ) @parametrize @@ -540,6 +548,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncMixedbread) vector_store = await async_client.vector_stores.list( limit=1000, offset=0, + q="x", ) assert_matches_type(AsyncLimitOffset[VectorStore], vector_store, path=["response"]) @@ -566,14 +575,14 @@ async def test_streaming_response_list(self, async_client: AsyncMixedbread) -> N @parametrize async def test_method_delete(self, async_client: AsyncMixedbread) -> None: vector_store = await async_client.vector_stores.delete( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) assert_matches_type(VectorStoreDeleteResponse, vector_store, path=["response"]) @parametrize async def test_raw_response_delete(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.with_raw_response.delete( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) assert response.is_closed is True @@ -584,7 +593,7 @@ async def test_raw_response_delete(self, async_client: AsyncMixedbread) -> None: @parametrize async def test_streaming_response_delete(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.with_streaming_response.delete( - "182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + "vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -596,23 +605,24 @@ async def test_streaming_response_delete(self, async_client: AsyncMixedbread) -> @parametrize async def test_path_params_delete(self, async_client: AsyncMixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): await async_client.vector_stores.with_raw_response.delete( "", ) @parametrize async def test_method_question_answering(self, async_client: AsyncMixedbread) -> None: - vector_store = await async_client.vector_stores.question_answering( - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - ) + vector_store = await async_client.vector_stores.question_answering() assert_matches_type(VectorStoreQuestionAnsweringResponse, vector_store, path=["response"]) @parametrize async def test_method_question_answering_with_all_params(self, async_client: AsyncMixedbread) -> None: vector_store = await async_client.vector_stores.question_answering( query="x", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + vector_store_identifiers=["string"], + vector_store_ids=["string"], top_k=1, filters={ "all": [ @@ -652,9 +662,11 @@ async def test_method_question_answering_with_all_params(self, async_client: Asy }, ], }, + file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"], search_options={ "score_threshold": 0, "rewrite_query": True, + "rerank": True, "return_metadata": True, }, stream=True, @@ -667,9 +679,7 @@ async def test_method_question_answering_with_all_params(self, async_client: Asy @parametrize async def test_raw_response_question_answering(self, async_client: AsyncMixedbread) -> None: - response = await async_client.vector_stores.with_raw_response.question_answering( - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - ) + response = await async_client.vector_stores.with_raw_response.question_answering() assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -678,9 +688,7 @@ async def test_raw_response_question_answering(self, async_client: AsyncMixedbre @parametrize async def test_streaming_response_question_answering(self, async_client: AsyncMixedbread) -> None: - async with async_client.vector_stores.with_streaming_response.question_answering( - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - ) as response: + async with async_client.vector_stores.with_streaming_response.question_answering() as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -693,7 +701,6 @@ async def test_streaming_response_question_answering(self, async_client: AsyncMi async def test_method_search(self, async_client: AsyncMixedbread) -> None: vector_store = await async_client.vector_stores.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) assert_matches_type(VectorStoreSearchResponse, vector_store, path=["response"]) @@ -701,7 +708,8 @@ async def test_method_search(self, async_client: AsyncMixedbread) -> None: async def test_method_search_with_all_params(self, async_client: AsyncMixedbread) -> None: vector_store = await async_client.vector_stores.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + vector_store_identifiers=["string"], + vector_store_ids=["string"], top_k=1, filters={ "all": [ @@ -741,9 +749,11 @@ async def test_method_search_with_all_params(self, async_client: AsyncMixedbread }, ], }, + file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"], search_options={ "score_threshold": 0, "rewrite_query": True, + "rerank": True, "return_metadata": True, }, ) @@ -753,7 +763,6 @@ async def test_method_search_with_all_params(self, async_client: AsyncMixedbread async def test_raw_response_search(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.with_raw_response.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) assert response.is_closed is True @@ -765,7 +774,6 @@ async def test_raw_response_search(self, async_client: AsyncMixedbread) -> None: async def test_streaming_response_search(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.with_streaming_response.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/api_resources/vector_stores/test_files.py b/tests/api_resources/vector_stores/test_files.py index e089a591..6a4128de 100644 --- a/tests/api_resources/vector_stores/test_files.py +++ b/tests/api_resources/vector_stores/test_files.py @@ -25,7 +25,7 @@ class TestFiles: @parametrize def test_method_create(self, client: Mixedbread) -> None: file = client.vector_stores.files.create( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(VectorStoreFile, file, path=["response"]) @@ -33,7 +33,7 @@ def test_method_create(self, client: Mixedbread) -> None: @parametrize def test_method_create_with_all_params(self, client: Mixedbread) -> None: file = client.vector_stores.files.create( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", metadata={}, experimental={ @@ -46,7 +46,7 @@ def test_method_create_with_all_params(self, client: Mixedbread) -> None: @parametrize def test_raw_response_create(self, client: Mixedbread) -> None: response = client.vector_stores.files.with_raw_response.create( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) @@ -58,7 +58,7 @@ def test_raw_response_create(self, client: Mixedbread) -> None: @parametrize def test_streaming_response_create(self, client: Mixedbread) -> None: with client.vector_stores.files.with_streaming_response.create( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed @@ -71,9 +71,11 @@ def test_streaming_response_create(self, client: Mixedbread) -> None: @parametrize def test_path_params_create(self, client: Mixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): client.vector_stores.files.with_raw_response.create( - vector_store_id="", + vector_store_identifier="", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) @@ -81,7 +83,7 @@ def test_path_params_create(self, client: Mixedbread) -> None: def test_method_retrieve(self, client: Mixedbread) -> None: file = client.vector_stores.files.retrieve( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert_matches_type(VectorStoreFile, file, path=["response"]) @@ -89,7 +91,7 @@ def test_method_retrieve(self, client: Mixedbread) -> None: def test_raw_response_retrieve(self, client: Mixedbread) -> None: response = client.vector_stores.files.with_raw_response.retrieve( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert response.is_closed is True @@ -101,7 +103,7 @@ def test_raw_response_retrieve(self, client: Mixedbread) -> None: def test_streaming_response_retrieve(self, client: Mixedbread) -> None: with client.vector_stores.files.with_streaming_response.retrieve( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -113,29 +115,31 @@ def test_streaming_response_retrieve(self, client: Mixedbread) -> None: @parametrize def test_path_params_retrieve(self, client: Mixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): client.vector_stores.files.with_raw_response.retrieve( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="", + vector_store_identifier="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.vector_stores.files.with_raw_response.retrieve( file_id="", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) @parametrize def test_method_list(self, client: Mixedbread) -> None: file = client.vector_stores.files.list( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert_matches_type(SyncLimitOffset[VectorStoreFile], file, path=["response"]) @parametrize def test_method_list_with_all_params(self, client: Mixedbread) -> None: file = client.vector_stores.files.list( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", limit=1000, offset=0, ) @@ -144,7 +148,7 @@ def test_method_list_with_all_params(self, client: Mixedbread) -> None: @parametrize def test_raw_response_list(self, client: Mixedbread) -> None: response = client.vector_stores.files.with_raw_response.list( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert response.is_closed is True @@ -155,7 +159,7 @@ def test_raw_response_list(self, client: Mixedbread) -> None: @parametrize def test_streaming_response_list(self, client: Mixedbread) -> None: with client.vector_stores.files.with_streaming_response.list( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -167,16 +171,18 @@ def test_streaming_response_list(self, client: Mixedbread) -> None: @parametrize def test_path_params_list(self, client: Mixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): client.vector_stores.files.with_raw_response.list( - vector_store_id="", + vector_store_identifier="", ) @parametrize def test_method_delete(self, client: Mixedbread) -> None: file = client.vector_stores.files.delete( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert_matches_type(FileDeleteResponse, file, path=["response"]) @@ -184,7 +190,7 @@ def test_method_delete(self, client: Mixedbread) -> None: def test_raw_response_delete(self, client: Mixedbread) -> None: response = client.vector_stores.files.with_raw_response.delete( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert response.is_closed is True @@ -196,7 +202,7 @@ def test_raw_response_delete(self, client: Mixedbread) -> None: def test_streaming_response_delete(self, client: Mixedbread) -> None: with client.vector_stores.files.with_streaming_response.delete( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -208,23 +214,24 @@ def test_streaming_response_delete(self, client: Mixedbread) -> None: @parametrize def test_path_params_delete(self, client: Mixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): client.vector_stores.files.with_raw_response.delete( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="", + vector_store_identifier="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): client.vector_stores.files.with_raw_response.delete( file_id="", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) @parametrize def test_method_search(self, client: Mixedbread) -> None: file = client.vector_stores.files.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) assert_matches_type(FileSearchResponse, file, path=["response"]) @@ -232,7 +239,8 @@ def test_method_search(self, client: Mixedbread) -> None: def test_method_search_with_all_params(self, client: Mixedbread) -> None: file = client.vector_stores.files.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + vector_store_identifiers=["string"], + vector_store_ids=["string"], top_k=1, filters={ "all": [ @@ -272,9 +280,11 @@ def test_method_search_with_all_params(self, client: Mixedbread) -> None: }, ], }, + file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"], search_options={ "score_threshold": 0, "rewrite_query": True, + "rerank": True, "return_metadata": True, "return_chunks": True, "chunks_per_file": 0, @@ -286,7 +296,6 @@ def test_method_search_with_all_params(self, client: Mixedbread) -> None: def test_raw_response_search(self, client: Mixedbread) -> None: response = client.vector_stores.files.with_raw_response.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) assert response.is_closed is True @@ -298,7 +307,6 @@ def test_raw_response_search(self, client: Mixedbread) -> None: def test_streaming_response_search(self, client: Mixedbread) -> None: with client.vector_stores.files.with_streaming_response.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -315,7 +323,7 @@ class TestAsyncFiles: @parametrize async def test_method_create(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.create( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) assert_matches_type(VectorStoreFile, file, path=["response"]) @@ -323,7 +331,7 @@ async def test_method_create(self, async_client: AsyncMixedbread) -> None: @parametrize async def test_method_create_with_all_params(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.create( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", metadata={}, experimental={ @@ -336,7 +344,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncMixedbread @parametrize async def test_raw_response_create(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.files.with_raw_response.create( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) @@ -348,7 +356,7 @@ async def test_raw_response_create(self, async_client: AsyncMixedbread) -> None: @parametrize async def test_streaming_response_create(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.files.with_streaming_response.create( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) as response: assert not response.is_closed @@ -361,9 +369,11 @@ async def test_streaming_response_create(self, async_client: AsyncMixedbread) -> @parametrize async def test_path_params_create(self, async_client: AsyncMixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): await async_client.vector_stores.files.with_raw_response.create( - vector_store_id="", + vector_store_identifier="", file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) @@ -371,7 +381,7 @@ async def test_path_params_create(self, async_client: AsyncMixedbread) -> None: async def test_method_retrieve(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.retrieve( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert_matches_type(VectorStoreFile, file, path=["response"]) @@ -379,7 +389,7 @@ async def test_method_retrieve(self, async_client: AsyncMixedbread) -> None: async def test_raw_response_retrieve(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.files.with_raw_response.retrieve( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert response.is_closed is True @@ -391,7 +401,7 @@ async def test_raw_response_retrieve(self, async_client: AsyncMixedbread) -> Non async def test_streaming_response_retrieve(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.files.with_streaming_response.retrieve( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -403,29 +413,31 @@ async def test_streaming_response_retrieve(self, async_client: AsyncMixedbread) @parametrize async def test_path_params_retrieve(self, async_client: AsyncMixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): await async_client.vector_stores.files.with_raw_response.retrieve( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="", + vector_store_identifier="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.vector_stores.files.with_raw_response.retrieve( file_id="", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) @parametrize async def test_method_list(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.list( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert_matches_type(AsyncLimitOffset[VectorStoreFile], file, path=["response"]) @parametrize async def test_method_list_with_all_params(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.list( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", limit=1000, offset=0, ) @@ -434,7 +446,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncMixedbread) @parametrize async def test_raw_response_list(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.files.with_raw_response.list( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert response.is_closed is True @@ -445,7 +457,7 @@ async def test_raw_response_list(self, async_client: AsyncMixedbread) -> None: @parametrize async def test_streaming_response_list(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.files.with_streaming_response.list( - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -457,16 +469,18 @@ async def test_streaming_response_list(self, async_client: AsyncMixedbread) -> N @parametrize async def test_path_params_list(self, async_client: AsyncMixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): await async_client.vector_stores.files.with_raw_response.list( - vector_store_id="", + vector_store_identifier="", ) @parametrize async def test_method_delete(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.delete( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert_matches_type(FileDeleteResponse, file, path=["response"]) @@ -474,7 +488,7 @@ async def test_method_delete(self, async_client: AsyncMixedbread) -> None: async def test_raw_response_delete(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.files.with_raw_response.delete( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) assert response.is_closed is True @@ -486,7 +500,7 @@ async def test_raw_response_delete(self, async_client: AsyncMixedbread) -> None: async def test_streaming_response_delete(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.files.with_streaming_response.delete( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" @@ -498,23 +512,24 @@ async def test_streaming_response_delete(self, async_client: AsyncMixedbread) -> @parametrize async def test_path_params_delete(self, async_client: AsyncMixedbread) -> None: - with pytest.raises(ValueError, match=r"Expected a non-empty value for `vector_store_id` but received ''"): + with pytest.raises( + ValueError, match=r"Expected a non-empty value for `vector_store_identifier` but received ''" + ): await async_client.vector_stores.files.with_raw_response.delete( file_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", - vector_store_id="", + vector_store_identifier="", ) with pytest.raises(ValueError, match=r"Expected a non-empty value for `file_id` but received ''"): await async_client.vector_stores.files.with_raw_response.delete( file_id="", - vector_store_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", + vector_store_identifier="vector_store_identifier", ) @parametrize async def test_method_search(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) assert_matches_type(FileSearchResponse, file, path=["response"]) @@ -522,7 +537,8 @@ async def test_method_search(self, async_client: AsyncMixedbread) -> None: async def test_method_search_with_all_params(self, async_client: AsyncMixedbread) -> None: file = await async_client.vector_stores.files.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], + vector_store_identifiers=["string"], + vector_store_ids=["string"], top_k=1, filters={ "all": [ @@ -562,9 +578,11 @@ async def test_method_search_with_all_params(self, async_client: AsyncMixedbread }, ], }, + file_ids=["123e4567-e89b-12d3-a456-426614174000", "123e4567-e89b-12d3-a456-426614174001"], search_options={ "score_threshold": 0, "rewrite_query": True, + "rerank": True, "return_metadata": True, "return_chunks": True, "chunks_per_file": 0, @@ -576,7 +594,6 @@ async def test_method_search_with_all_params(self, async_client: AsyncMixedbread async def test_raw_response_search(self, async_client: AsyncMixedbread) -> None: response = await async_client.vector_stores.files.with_raw_response.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) assert response.is_closed is True @@ -588,7 +605,6 @@ async def test_raw_response_search(self, async_client: AsyncMixedbread) -> None: async def test_streaming_response_search(self, async_client: AsyncMixedbread) -> None: async with async_client.vector_stores.files.with_streaming_response.search( query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], ) as response: assert not response.is_closed assert response.http_request.headers.get("X-Stainless-Lang") == "python" diff --git a/tests/test_client.py b/tests/test_client.py index 4d16384d..61377980 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -836,6 +836,33 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: assert response.http_request.headers.get("x-stainless-retry-count") == "42" + @pytest.mark.respx(base_url=base_url) + def test_follow_redirects(self, respx_mock: MockRouter) -> None: + # Test that the default follow_redirects=True allows following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) + + response = self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + assert response.status_code == 200 + assert response.json() == {"status": "ok"} + + @pytest.mark.respx(base_url=base_url) + def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + # Test that follow_redirects=False prevents following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + + with pytest.raises(APIStatusError) as exc_info: + self.client.post( + "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response + ) + + assert exc_info.value.response.status_code == 302 + assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected" + class TestAsyncMixedbread: client = AsyncMixedbread(base_url=base_url, api_key=api_key, _strict_response_validation=True) @@ -1671,3 +1698,30 @@ async def test_main() -> None: raise AssertionError("calling get_platform using asyncify resulted in a hung process") time.sleep(0.1) + + @pytest.mark.respx(base_url=base_url) + async def test_follow_redirects(self, respx_mock: MockRouter) -> None: + # Test that the default follow_redirects=True allows following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + respx_mock.get("/redirected").mock(return_value=httpx.Response(200, json={"status": "ok"})) + + response = await self.client.post("/redirect", body={"key": "value"}, cast_to=httpx.Response) + assert response.status_code == 200 + assert response.json() == {"status": "ok"} + + @pytest.mark.respx(base_url=base_url) + async def test_follow_redirects_disabled(self, respx_mock: MockRouter) -> None: + # Test that follow_redirects=False prevents following redirects + respx_mock.post("/redirect").mock( + return_value=httpx.Response(302, headers={"Location": f"{base_url}/redirected"}) + ) + + with pytest.raises(APIStatusError) as exc_info: + await self.client.post( + "/redirect", body={"key": "value"}, options={"follow_redirects": False}, cast_to=httpx.Response + ) + + assert exc_info.value.response.status_code == 302 + assert exc_info.value.response.headers["Location"] == f"{base_url}/redirected"