From 312a603bb67da9ff8409b1e0950a0dee03200636 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 21:09:41 +0000 Subject: [PATCH 1/5] feat(api): update via SDK Studio (#180) --- .stats.yml | 2 +- api.md | 18 +++++- src/mixedbread/_client.py | 10 ++-- src/mixedbread/resources/embeddings.py | 10 ++-- src/mixedbread/types/__init__.py | 3 +- .../types/{em.py => embed_response.py} | 4 +- .../types/embedding_create_response.py | 60 +++++++++++++++++++ tests/api_resources/test_client.py | 18 +++--- tests/api_resources/test_embeddings.py | 18 +++--- 9 files changed, 108 insertions(+), 35 deletions(-) rename src/mixedbread/types/{em.py => embed_response.py} (95%) create mode 100644 src/mixedbread/types/embedding_create_response.py diff --git a/.stats.yml b/.stats.yml index 00db8629..c0a3743f 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 32 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-82c2c1c322149cd73b2e8e45f475919b941752a89e74464ccecd1aee9352e9be.yml openapi_spec_hash: dbd7616a32c90fd25b32994830fb12f6 -config_hash: 2a44785dc321bd6e458c4e767035de1b +config_hash: 404d016390359897b6f1ea74357b2ace diff --git a/api.md b/api.md index 556c3a91..2c0954d6 100644 --- a/api.md +++ b/api.md @@ -9,12 +9,18 @@ from mixedbread.types import SearchFilter, SearchFilterCondition Types: ```python -from mixedbread.types import Em, Embedding, MultiEncodingEmbedding, InfoResponse, RerankResponse +from mixedbread.types import ( + Embedding, + MultiEncodingEmbedding, + EmbedResponse, + InfoResponse, + RerankResponse, +) ``` Methods: -- client.embed(\*\*params) -> Em +- client.embed(\*\*params) -> EmbedResponse - client.info() -> InfoResponse - client.rerank(\*\*params) -> RerankResponse @@ -145,6 +151,12 @@ Methods: # Embeddings +Types: + +```python +from mixedbread.types import EmbeddingCreateResponse +``` + Methods: -- client.embeddings.create(\*\*params) -> Em +- client.embeddings.create(\*\*params) -> EmbeddingCreateResponse diff --git a/src/mixedbread/_client.py b/src/mixedbread/_client.py index 29b4d595..b9996076 100644 --- a/src/mixedbread/_client.py +++ b/src/mixedbread/_client.py @@ -30,7 +30,6 @@ async_maybe_transform, ) from ._version import __version__ -from .types.em import Em from ._response import ( to_raw_response_wrapper, to_streamed_response_wrapper, @@ -48,6 +47,7 @@ ) from .resources.parsing import parsing from .types.info_response import InfoResponse +from .types.embed_response import EmbedResponse from .resources.extractions import extractions from .types.rerank_response import RerankResponse from .resources.vector_stores import vector_stores @@ -257,7 +257,7 @@ def embed( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Em: + ) -> EmbedResponse: """ Create embeddings for text or images using the specified model, encoding format, and normalization. @@ -304,7 +304,7 @@ def embed( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=Em, + cast_to=EmbedResponse, ) def info( @@ -614,7 +614,7 @@ async def embed( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Em: + ) -> EmbedResponse: """ Create embeddings for text or images using the specified model, encoding format, and normalization. @@ -661,7 +661,7 @@ async def embed( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=Em, + cast_to=EmbedResponse, ) async def info( diff --git a/src/mixedbread/resources/embeddings.py b/src/mixedbread/resources/embeddings.py index f2adc49c..d7390eda 100644 --- a/src/mixedbread/resources/embeddings.py +++ b/src/mixedbread/resources/embeddings.py @@ -14,7 +14,6 @@ async_maybe_transform, ) from .._compat import cached_property -from ..types.em import Em from .._resource import SyncAPIResource, AsyncAPIResource from .._response import ( to_raw_response_wrapper, @@ -23,6 +22,7 @@ async_to_streamed_response_wrapper, ) from .._base_client import make_request_options +from ..types.embedding_create_response import EmbeddingCreateResponse __all__ = ["EmbeddingsResource", "AsyncEmbeddingsResource"] @@ -66,7 +66,7 @@ def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Em: + ) -> EmbeddingCreateResponse: """ Create embeddings for text or images using the specified model, encoding format, and normalization. @@ -113,7 +113,7 @@ def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=Em, + cast_to=EmbeddingCreateResponse, ) @@ -156,7 +156,7 @@ async def create( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> Em: + ) -> EmbeddingCreateResponse: """ Create embeddings for text or images using the specified model, encoding format, and normalization. @@ -203,7 +203,7 @@ async def create( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=Em, + cast_to=EmbeddingCreateResponse, ) diff --git a/src/mixedbread/types/__init__.py b/src/mixedbread/types/__init__.py index c48a74b0..ee8d1032 100644 --- a/src/mixedbread/types/__init__.py +++ b/src/mixedbread/types/__init__.py @@ -2,7 +2,6 @@ from __future__ import annotations -from .em import Em as Em from .shared import SearchFilter as SearchFilter, SearchFilterCondition as SearchFilterCondition from .embedding import Embedding as Embedding from .file_counts import FileCounts as FileCounts @@ -10,6 +9,7 @@ from .vector_store import VectorStore as VectorStore from .expires_after import ExpiresAfter as ExpiresAfter from .info_response import InfoResponse as InfoResponse +from .embed_response import EmbedResponse as EmbedResponse from .rerank_response import RerankResponse as RerankResponse from .file_list_params import FileListParams as FileListParams from .file_create_params import FileCreateParams as FileCreateParams @@ -21,6 +21,7 @@ from .embedding_create_params import EmbeddingCreateParams as EmbeddingCreateParams from .multi_encoding_embedding import MultiEncodingEmbedding as MultiEncodingEmbedding from .vector_store_list_params import VectorStoreListParams as VectorStoreListParams +from .embedding_create_response import EmbeddingCreateResponse as EmbeddingCreateResponse from .scored_vector_store_chunk import ScoredVectorStoreChunk as ScoredVectorStoreChunk from .vector_store_create_params import VectorStoreCreateParams as VectorStoreCreateParams from .vector_store_search_params import VectorStoreSearchParams as VectorStoreSearchParams diff --git a/src/mixedbread/types/em.py b/src/mixedbread/types/embed_response.py similarity index 95% rename from src/mixedbread/types/em.py rename to src/mixedbread/types/embed_response.py index 12277e0a..fb9c8803 100644 --- a/src/mixedbread/types/em.py +++ b/src/mixedbread/types/embed_response.py @@ -7,7 +7,7 @@ from .embedding import Embedding from .multi_encoding_embedding import MultiEncodingEmbedding -__all__ = ["Em", "Usage"] +__all__ = ["EmbedResponse", "Usage"] class Usage(BaseModel): @@ -21,7 +21,7 @@ class Usage(BaseModel): """The number of tokens used for the completion""" -class Em(BaseModel): +class EmbedResponse(BaseModel): usage: Usage """The usage of the model""" diff --git a/src/mixedbread/types/embedding_create_response.py b/src/mixedbread/types/embedding_create_response.py new file mode 100644 index 00000000..8f3605cb --- /dev/null +++ b/src/mixedbread/types/embedding_create_response.py @@ -0,0 +1,60 @@ +# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +from typing import List, Union, Optional +from typing_extensions import Literal + +from .._models import BaseModel +from .embedding import Embedding +from .multi_encoding_embedding import MultiEncodingEmbedding + +__all__ = ["EmbeddingCreateResponse", "Usage"] + + +class Usage(BaseModel): + prompt_tokens: int + """The number of tokens used for the prompt""" + + total_tokens: int + """The total number of tokens used""" + + completion_tokens: Optional[int] = None + """The number of tokens used for the completion""" + + +class EmbeddingCreateResponse(BaseModel): + usage: Usage + """The usage of the model""" + + model: str + """The model used""" + + data: Union[List[Embedding], List[MultiEncodingEmbedding]] + """The created embeddings.""" + + object: Optional[ + Literal[ + "list", + "parsing_job", + "job", + "embedding", + "embedding_dict", + "rank_result", + "file", + "vector_store", + "vector_store.file", + "api_key", + ] + ] = None + """The object type of the response""" + + normalized: bool + """Whether the embeddings are normalized.""" + + encoding_format: Union[ + Literal["float", "float16", "base64", "binary", "ubinary", "int8", "uint8"], + List[Literal["float", "float16", "base64", "binary", "ubinary", "int8", "uint8"]], + ] + """The encoding formats of the embeddings.""" + + dimensions: Optional[int] = None + """The number of dimensions used for the embeddings.""" diff --git a/tests/api_resources/test_client.py b/tests/api_resources/test_client.py index dc3ed1d8..1d143378 100644 --- a/tests/api_resources/test_client.py +++ b/tests/api_resources/test_client.py @@ -9,7 +9,7 @@ from mixedbread import Mixedbread, AsyncMixedbread from tests.utils import assert_matches_type -from mixedbread.types import Em, InfoResponse, RerankResponse +from mixedbread.types import InfoResponse, EmbedResponse, RerankResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -23,7 +23,7 @@ def test_method_embed(self, client: Mixedbread) -> None: model="mixedbread-ai/mxbai-embed-large-v1", input=["string"], ) - assert_matches_type(Em, client_, path=["response"]) + assert_matches_type(EmbedResponse, client_, path=["response"]) @parametrize def test_method_embed_with_all_params(self, client: Mixedbread) -> None: @@ -35,7 +35,7 @@ def test_method_embed_with_all_params(self, client: Mixedbread) -> None: normalized=True, encoding_format="float", ) - assert_matches_type(Em, client_, path=["response"]) + assert_matches_type(EmbedResponse, client_, path=["response"]) @parametrize def test_raw_response_embed(self, client: Mixedbread) -> None: @@ -47,7 +47,7 @@ def test_raw_response_embed(self, client: Mixedbread) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" client_ = response.parse() - assert_matches_type(Em, client_, path=["response"]) + assert_matches_type(EmbedResponse, client_, path=["response"]) @parametrize def test_streaming_response_embed(self, client: Mixedbread) -> None: @@ -59,7 +59,7 @@ def test_streaming_response_embed(self, client: Mixedbread) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" client_ = response.parse() - assert_matches_type(Em, client_, path=["response"]) + assert_matches_type(EmbedResponse, client_, path=["response"]) assert cast(Any, response.is_closed) is True @@ -144,7 +144,7 @@ async def test_method_embed(self, async_client: AsyncMixedbread) -> None: model="mixedbread-ai/mxbai-embed-large-v1", input=["string"], ) - assert_matches_type(Em, client, path=["response"]) + assert_matches_type(EmbedResponse, client, path=["response"]) @parametrize async def test_method_embed_with_all_params(self, async_client: AsyncMixedbread) -> None: @@ -156,7 +156,7 @@ async def test_method_embed_with_all_params(self, async_client: AsyncMixedbread) normalized=True, encoding_format="float", ) - assert_matches_type(Em, client, path=["response"]) + assert_matches_type(EmbedResponse, client, path=["response"]) @parametrize async def test_raw_response_embed(self, async_client: AsyncMixedbread) -> None: @@ -168,7 +168,7 @@ async def test_raw_response_embed(self, async_client: AsyncMixedbread) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" client = await response.parse() - assert_matches_type(Em, client, path=["response"]) + assert_matches_type(EmbedResponse, client, path=["response"]) @parametrize async def test_streaming_response_embed(self, async_client: AsyncMixedbread) -> None: @@ -180,7 +180,7 @@ async def test_streaming_response_embed(self, async_client: AsyncMixedbread) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" client = await response.parse() - assert_matches_type(Em, client, path=["response"]) + assert_matches_type(EmbedResponse, client, path=["response"]) assert cast(Any, response.is_closed) is True diff --git a/tests/api_resources/test_embeddings.py b/tests/api_resources/test_embeddings.py index 610022ee..ffe758eb 100644 --- a/tests/api_resources/test_embeddings.py +++ b/tests/api_resources/test_embeddings.py @@ -9,7 +9,7 @@ from mixedbread import Mixedbread, AsyncMixedbread from tests.utils import assert_matches_type -from mixedbread.types import Em +from mixedbread.types import EmbeddingCreateResponse base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -23,7 +23,7 @@ def test_method_create(self, client: Mixedbread) -> None: model="mixedbread-ai/mxbai-embed-large-v1", input=["string"], ) - assert_matches_type(Em, embedding, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, embedding, path=["response"]) @parametrize def test_method_create_with_all_params(self, client: Mixedbread) -> None: @@ -35,7 +35,7 @@ def test_method_create_with_all_params(self, client: Mixedbread) -> None: normalized=True, encoding_format="float", ) - assert_matches_type(Em, embedding, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, embedding, path=["response"]) @parametrize def test_raw_response_create(self, client: Mixedbread) -> None: @@ -47,7 +47,7 @@ def test_raw_response_create(self, client: Mixedbread) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" embedding = response.parse() - assert_matches_type(Em, embedding, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, embedding, path=["response"]) @parametrize def test_streaming_response_create(self, client: Mixedbread) -> None: @@ -59,7 +59,7 @@ def test_streaming_response_create(self, client: Mixedbread) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" embedding = response.parse() - assert_matches_type(Em, embedding, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, embedding, path=["response"]) assert cast(Any, response.is_closed) is True @@ -73,7 +73,7 @@ async def test_method_create(self, async_client: AsyncMixedbread) -> None: model="mixedbread-ai/mxbai-embed-large-v1", input=["string"], ) - assert_matches_type(Em, embedding, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, embedding, path=["response"]) @parametrize async def test_method_create_with_all_params(self, async_client: AsyncMixedbread) -> None: @@ -85,7 +85,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncMixedbread normalized=True, encoding_format="float", ) - assert_matches_type(Em, embedding, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, embedding, path=["response"]) @parametrize async def test_raw_response_create(self, async_client: AsyncMixedbread) -> None: @@ -97,7 +97,7 @@ async def test_raw_response_create(self, async_client: AsyncMixedbread) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" embedding = await response.parse() - assert_matches_type(Em, embedding, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, embedding, path=["response"]) @parametrize async def test_streaming_response_create(self, async_client: AsyncMixedbread) -> None: @@ -109,6 +109,6 @@ async def test_streaming_response_create(self, async_client: AsyncMixedbread) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" embedding = await response.parse() - assert_matches_type(Em, embedding, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, embedding, path=["response"]) assert cast(Any, response.is_closed) is True From 33480fca59f6b3f67ad5acee09781ef22e240600 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 21:16:40 +0000 Subject: [PATCH 2/5] feat(api): update via SDK Studio (#182) --- .stats.yml | 2 +- api.md | 10 +---- src/mixedbread/_client.py | 10 ++--- src/mixedbread/types/__init__.py | 1 - src/mixedbread/types/embed_response.py | 60 -------------------------- tests/api_resources/test_client.py | 22 ++++++---- 6 files changed, 21 insertions(+), 84 deletions(-) delete mode 100644 src/mixedbread/types/embed_response.py diff --git a/.stats.yml b/.stats.yml index c0a3743f..ffb38610 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 32 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-82c2c1c322149cd73b2e8e45f475919b941752a89e74464ccecd1aee9352e9be.yml openapi_spec_hash: dbd7616a32c90fd25b32994830fb12f6 -config_hash: 404d016390359897b6f1ea74357b2ace +config_hash: bed309dda44f5c585068c1fa50ccc7ca diff --git a/api.md b/api.md index 2c0954d6..a7d820d8 100644 --- a/api.md +++ b/api.md @@ -11,8 +11,8 @@ Types: ```python from mixedbread.types import ( Embedding, + EmbeddingCreateResponse, MultiEncodingEmbedding, - EmbedResponse, InfoResponse, RerankResponse, ) @@ -20,7 +20,7 @@ from mixedbread.types import ( Methods: -- client.embed(\*\*params) -> EmbedResponse +- client.embed(\*\*params) -> EmbeddingCreateResponse - client.info() -> InfoResponse - client.rerank(\*\*params) -> RerankResponse @@ -151,12 +151,6 @@ Methods: # Embeddings -Types: - -```python -from mixedbread.types import EmbeddingCreateResponse -``` - Methods: - client.embeddings.create(\*\*params) -> EmbeddingCreateResponse diff --git a/src/mixedbread/_client.py b/src/mixedbread/_client.py index b9996076..30ff9cca 100644 --- a/src/mixedbread/_client.py +++ b/src/mixedbread/_client.py @@ -47,10 +47,10 @@ ) from .resources.parsing import parsing from .types.info_response import InfoResponse -from .types.embed_response import EmbedResponse from .resources.extractions import extractions from .types.rerank_response import RerankResponse from .resources.vector_stores import vector_stores +from .types.embedding_create_response import EmbeddingCreateResponse __all__ = [ "ENVIRONMENTS", @@ -257,7 +257,7 @@ def embed( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> EmbedResponse: + ) -> EmbeddingCreateResponse: """ Create embeddings for text or images using the specified model, encoding format, and normalization. @@ -304,7 +304,7 @@ def embed( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=EmbedResponse, + cast_to=EmbeddingCreateResponse, ) def info( @@ -614,7 +614,7 @@ async def embed( extra_query: Query | None = None, extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = NOT_GIVEN, - ) -> EmbedResponse: + ) -> EmbeddingCreateResponse: """ Create embeddings for text or images using the specified model, encoding format, and normalization. @@ -661,7 +661,7 @@ async def embed( options=make_request_options( extra_headers=extra_headers, extra_query=extra_query, extra_body=extra_body, timeout=timeout ), - cast_to=EmbedResponse, + cast_to=EmbeddingCreateResponse, ) async def info( diff --git a/src/mixedbread/types/__init__.py b/src/mixedbread/types/__init__.py index ee8d1032..ae8ce3a4 100644 --- a/src/mixedbread/types/__init__.py +++ b/src/mixedbread/types/__init__.py @@ -9,7 +9,6 @@ from .vector_store import VectorStore as VectorStore from .expires_after import ExpiresAfter as ExpiresAfter from .info_response import InfoResponse as InfoResponse -from .embed_response import EmbedResponse as EmbedResponse from .rerank_response import RerankResponse as RerankResponse from .file_list_params import FileListParams as FileListParams from .file_create_params import FileCreateParams as FileCreateParams diff --git a/src/mixedbread/types/embed_response.py b/src/mixedbread/types/embed_response.py deleted file mode 100644 index fb9c8803..00000000 --- a/src/mixedbread/types/embed_response.py +++ /dev/null @@ -1,60 +0,0 @@ -# File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. - -from typing import List, Union, Optional -from typing_extensions import Literal - -from .._models import BaseModel -from .embedding import Embedding -from .multi_encoding_embedding import MultiEncodingEmbedding - -__all__ = ["EmbedResponse", "Usage"] - - -class Usage(BaseModel): - prompt_tokens: int - """The number of tokens used for the prompt""" - - total_tokens: int - """The total number of tokens used""" - - completion_tokens: Optional[int] = None - """The number of tokens used for the completion""" - - -class EmbedResponse(BaseModel): - usage: Usage - """The usage of the model""" - - model: str - """The model used""" - - data: Union[List[Embedding], List[MultiEncodingEmbedding]] - """The created embeddings.""" - - object: Optional[ - Literal[ - "list", - "parsing_job", - "job", - "embedding", - "embedding_dict", - "rank_result", - "file", - "vector_store", - "vector_store.file", - "api_key", - ] - ] = None - """The object type of the response""" - - normalized: bool - """Whether the embeddings are normalized.""" - - encoding_format: Union[ - Literal["float", "float16", "base64", "binary", "ubinary", "int8", "uint8"], - List[Literal["float", "float16", "base64", "binary", "ubinary", "int8", "uint8"]], - ] - """The encoding formats of the embeddings.""" - - dimensions: Optional[int] = None - """The number of dimensions used for the embeddings.""" diff --git a/tests/api_resources/test_client.py b/tests/api_resources/test_client.py index 1d143378..1c38d8ba 100644 --- a/tests/api_resources/test_client.py +++ b/tests/api_resources/test_client.py @@ -9,7 +9,11 @@ from mixedbread import Mixedbread, AsyncMixedbread from tests.utils import assert_matches_type -from mixedbread.types import InfoResponse, EmbedResponse, RerankResponse +from mixedbread.types import ( + InfoResponse, + RerankResponse, + EmbeddingCreateResponse, +) base_url = os.environ.get("TEST_API_BASE_URL", "http://127.0.0.1:4010") @@ -23,7 +27,7 @@ def test_method_embed(self, client: Mixedbread) -> None: model="mixedbread-ai/mxbai-embed-large-v1", input=["string"], ) - assert_matches_type(EmbedResponse, client_, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, client_, path=["response"]) @parametrize def test_method_embed_with_all_params(self, client: Mixedbread) -> None: @@ -35,7 +39,7 @@ def test_method_embed_with_all_params(self, client: Mixedbread) -> None: normalized=True, encoding_format="float", ) - assert_matches_type(EmbedResponse, client_, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, client_, path=["response"]) @parametrize def test_raw_response_embed(self, client: Mixedbread) -> None: @@ -47,7 +51,7 @@ def test_raw_response_embed(self, client: Mixedbread) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" client_ = response.parse() - assert_matches_type(EmbedResponse, client_, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, client_, path=["response"]) @parametrize def test_streaming_response_embed(self, client: Mixedbread) -> None: @@ -59,7 +63,7 @@ def test_streaming_response_embed(self, client: Mixedbread) -> None: assert response.http_request.headers.get("X-Stainless-Lang") == "python" client_ = response.parse() - assert_matches_type(EmbedResponse, client_, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, client_, path=["response"]) assert cast(Any, response.is_closed) is True @@ -144,7 +148,7 @@ async def test_method_embed(self, async_client: AsyncMixedbread) -> None: model="mixedbread-ai/mxbai-embed-large-v1", input=["string"], ) - assert_matches_type(EmbedResponse, client, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, client, path=["response"]) @parametrize async def test_method_embed_with_all_params(self, async_client: AsyncMixedbread) -> None: @@ -156,7 +160,7 @@ async def test_method_embed_with_all_params(self, async_client: AsyncMixedbread) normalized=True, encoding_format="float", ) - assert_matches_type(EmbedResponse, client, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, client, path=["response"]) @parametrize async def test_raw_response_embed(self, async_client: AsyncMixedbread) -> None: @@ -168,7 +172,7 @@ async def test_raw_response_embed(self, async_client: AsyncMixedbread) -> None: assert response.is_closed is True assert response.http_request.headers.get("X-Stainless-Lang") == "python" client = await response.parse() - assert_matches_type(EmbedResponse, client, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, client, path=["response"]) @parametrize async def test_streaming_response_embed(self, async_client: AsyncMixedbread) -> None: @@ -180,7 +184,7 @@ async def test_streaming_response_embed(self, async_client: AsyncMixedbread) -> assert response.http_request.headers.get("X-Stainless-Lang") == "python" client = await response.parse() - assert_matches_type(EmbedResponse, client, path=["response"]) + assert_matches_type(EmbeddingCreateResponse, client, path=["response"]) assert cast(Any, response.is_closed) is True From c6ff6bf3a4c0e0434b9ab051b927566b880737cf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 21:21:13 +0000 Subject: [PATCH 3/5] codegen metadata --- .stats.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index ffb38610..5bff61e7 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 32 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-82c2c1c322149cd73b2e8e45f475919b941752a89e74464ccecd1aee9352e9be.yml openapi_spec_hash: dbd7616a32c90fd25b32994830fb12f6 -config_hash: bed309dda44f5c585068c1fa50ccc7ca +config_hash: 1abee5c9ed042aec152177e571d391e1 From 651e0923c62e32345dfc39d67e38ef41dcc22028 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 21:23:37 +0000 Subject: [PATCH 4/5] feat(api): update via SDK Studio (#184) --- .stats.yml | 2 +- README.md | 108 ++++++++++++++++++++++++++++++------------- tests/test_client.py | 94 +++++++++++-------------------------- 3 files changed, 103 insertions(+), 101 deletions(-) diff --git a/.stats.yml b/.stats.yml index 5bff61e7..85523261 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 32 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/mixedbread%2Fmixedbread-82c2c1c322149cd73b2e8e45f475919b941752a89e74464ccecd1aee9352e9be.yml openapi_spec_hash: dbd7616a32c90fd25b32994830fb12f6 -config_hash: 1abee5c9ed042aec152177e571d391e1 +config_hash: daf46fcf1979db0bfe4221c9a4197cd1 diff --git a/README.md b/README.md index 3d966cc2..5d3e4084 100644 --- a/README.md +++ b/README.md @@ -33,11 +33,8 @@ client = Mixedbread( environment="local", ) -response = client.vector_stores.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], -) -print(response.object) +vector_store = client.vector_stores.create() +print(vector_store.id) ``` While you can provide an `api_key` keyword argument, @@ -62,11 +59,8 @@ client = AsyncMixedbread( async def main() -> None: - response = await client.vector_stores.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - ) - print(response.object) + vector_store = await client.vector_stores.create() + print(vector_store.id) asyncio.run(main()) @@ -83,6 +77,71 @@ Nested request parameters are [TypedDicts](https://docs.python.org/3/library/typ Typed requests and responses provide autocomplete and documentation within your editor. If you would like to see type errors in VS Code to help catch bugs earlier, set `python.analysis.typeCheckingMode` to `basic`. +## Pagination + +List methods in the Mixedbread API are paginated. + +This library provides auto-paginating iterators with each list response, so you do not have to request successive pages manually: + +```python +from mixedbread import Mixedbread + +client = Mixedbread() + +all_vector_stores = [] +# Automatically fetches more pages as needed. +for vector_store in client.vector_stores.list(): + # Do something with vector_store here + all_vector_stores.append(vector_store) +print(all_vector_stores) +``` + +Or, asynchronously: + +```python +import asyncio +from mixedbread import AsyncMixedbread + +client = AsyncMixedbread() + + +async def main() -> None: + all_vector_stores = [] + # Iterate through items across all pages, issuing requests as needed. + async for vector_store in client.vector_stores.list(): + all_vector_stores.append(vector_store) + print(all_vector_stores) + + +asyncio.run(main()) +``` + +Alternatively, you can use the `.has_next_page()`, `.next_page_info()`, or `.get_next_page()` methods for more granular control working with pages: + +```python +first_page = await client.vector_stores.list() +if first_page.has_next_page(): + print(f"will fetch next page using these details: {first_page.next_page_info()}") + next_page = await first_page.get_next_page() + print(f"number of items we just fetched: {len(next_page.data)}") + +# Remove `await` for non-async usage. +``` + +Or just work directly with the returned data: + +```python +first_page = await client.vector_stores.list() + +print( + f"the current start offset for this page: {first_page.pagination.offset}" +) # => "the current start offset for this page: 1" +for vector_store in first_page.data: + print(vector_store.id) + +# Remove `await` for non-async usage. +``` + ## Nested params Nested parameters are dictionaries, typed using `TypedDict`, for example: @@ -134,10 +193,7 @@ from mixedbread import Mixedbread client = Mixedbread() try: - client.vector_stores.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - ) + client.vector_stores.create() except mixedbread.APIConnectionError as e: print("The server could not be reached") print(e.__cause__) # an underlying Exception, likely raised within httpx. @@ -180,10 +236,7 @@ client = Mixedbread( ) # Or, configure per-request: -client.with_options(max_retries=5).vector_stores.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], -) +client.with_options(max_retries=5).vector_stores.create() ``` ### Timeouts @@ -206,10 +259,7 @@ client = Mixedbread( ) # Override per-request: -client.with_options(timeout=5.0).vector_stores.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], -) +client.with_options(timeout=5.0).vector_stores.create() ``` On timeout, an `APITimeoutError` is thrown. @@ -250,14 +300,11 @@ The "raw" Response object can be accessed by prefixing `.with_raw_response.` to from mixedbread import Mixedbread client = Mixedbread() -response = client.vector_stores.with_raw_response.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], -) +response = client.vector_stores.with_raw_response.create() print(response.headers.get('X-My-Header')) -vector_store = response.parse() # get the object that `vector_stores.search()` would have returned -print(vector_store.object) +vector_store = response.parse() # get the object that `vector_stores.create()` would have returned +print(vector_store.id) ``` These methods return an [`APIResponse`](https://github.com/mixedbread-ai/mixedbread-python/tree/main/src/mixedbread/_response.py) object. @@ -271,10 +318,7 @@ The above interface eagerly reads the full response body when you make the reque To stream the response body, use `.with_streaming_response` instead, which requires a context manager and only reads the response body once you call `.read()`, `.text()`, `.json()`, `.iter_bytes()`, `.iter_text()`, `.iter_lines()` or `.parse()`. In the async client, these are async methods. ```python -with client.vector_stores.with_streaming_response.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], -) as response: +with client.vector_stores.with_streaming_response.create() as response: print(response.headers.get("X-My-Header")) for line in response.iter_lines(): diff --git a/tests/test_client.py b/tests/test_client.py index 450bfe0b..9a2b23af 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -33,7 +33,7 @@ BaseClient, make_request_options, ) -from mixedbread.types.vector_store_search_params import VectorStoreSearchParams +from mixedbread.types.vector_store_create_params import VectorStoreCreateParams from .utils import update_env @@ -732,18 +732,12 @@ def test_parse_retry_after_header(self, remaining_retries: int, retry_after: str @mock.patch("mixedbread._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: - respx_mock.post("/v1/vector_stores/search").mock(side_effect=httpx.TimeoutException("Test timeout error")) + respx_mock.post("/v1/vector_stores").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): self.client.post( - "/v1/vector_stores/search", - body=cast( - object, - maybe_transform( - dict(query="how to configure SSL", vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"]), - VectorStoreSearchParams, - ), - ), + "/v1/vector_stores", + body=cast(object, maybe_transform({}, VectorStoreCreateParams)), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -753,18 +747,12 @@ def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> No @mock.patch("mixedbread._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: - respx_mock.post("/v1/vector_stores/search").mock(return_value=httpx.Response(500)) + respx_mock.post("/v1/vector_stores").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): self.client.post( - "/v1/vector_stores/search", - body=cast( - object, - maybe_transform( - dict(query="how to configure SSL", vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"]), - VectorStoreSearchParams, - ), - ), + "/v1/vector_stores", + body=cast(object, maybe_transform({}, VectorStoreCreateParams)), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -795,11 +783,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/vector_stores/search").mock(side_effect=retry_handler) + respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler) - response = client.vector_stores.with_raw_response.search( - query="how to configure SSL", vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"] - ) + response = client.vector_stores.with_raw_response.create() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -821,13 +807,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/vector_stores/search").mock(side_effect=retry_handler) + respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler) - response = client.vector_stores.with_raw_response.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - extra_headers={"x-stainless-retry-count": Omit()}, - ) + response = client.vector_stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": Omit()}) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -848,13 +830,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/vector_stores/search").mock(side_effect=retry_handler) + respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler) - response = client.vector_stores.with_raw_response.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - extra_headers={"x-stainless-retry-count": "42"}, - ) + response = client.vector_stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" @@ -1540,18 +1518,12 @@ async def test_parse_retry_after_header(self, remaining_retries: int, retry_afte @mock.patch("mixedbread._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: - respx_mock.post("/v1/vector_stores/search").mock(side_effect=httpx.TimeoutException("Test timeout error")) + respx_mock.post("/v1/vector_stores").mock(side_effect=httpx.TimeoutException("Test timeout error")) with pytest.raises(APITimeoutError): await self.client.post( - "/v1/vector_stores/search", - body=cast( - object, - maybe_transform( - dict(query="how to configure SSL", vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"]), - VectorStoreSearchParams, - ), - ), + "/v1/vector_stores", + body=cast(object, maybe_transform({}, VectorStoreCreateParams)), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -1561,18 +1533,12 @@ async def test_retrying_timeout_errors_doesnt_leak(self, respx_mock: MockRouter) @mock.patch("mixedbread._base_client.BaseClient._calculate_retry_timeout", _low_retry_timeout) @pytest.mark.respx(base_url=base_url) async def test_retrying_status_errors_doesnt_leak(self, respx_mock: MockRouter) -> None: - respx_mock.post("/v1/vector_stores/search").mock(return_value=httpx.Response(500)) + respx_mock.post("/v1/vector_stores").mock(return_value=httpx.Response(500)) with pytest.raises(APIStatusError): await self.client.post( - "/v1/vector_stores/search", - body=cast( - object, - maybe_transform( - dict(query="how to configure SSL", vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"]), - VectorStoreSearchParams, - ), - ), + "/v1/vector_stores", + body=cast(object, maybe_transform({}, VectorStoreCreateParams)), cast_to=httpx.Response, options={"headers": {RAW_RESPONSE_HEADER: "stream"}}, ) @@ -1604,11 +1570,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/vector_stores/search").mock(side_effect=retry_handler) + respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler) - response = await client.vector_stores.with_raw_response.search( - query="how to configure SSL", vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"] - ) + response = await client.vector_stores.with_raw_response.create() assert response.retries_taken == failures_before_success assert int(response.http_request.headers.get("x-stainless-retry-count")) == failures_before_success @@ -1631,12 +1595,10 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/vector_stores/search").mock(side_effect=retry_handler) + respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler) - response = await client.vector_stores.with_raw_response.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - extra_headers={"x-stainless-retry-count": Omit()}, + response = await client.vector_stores.with_raw_response.create( + extra_headers={"x-stainless-retry-count": Omit()} ) assert len(response.http_request.headers.get_list("x-stainless-retry-count")) == 0 @@ -1659,13 +1621,9 @@ def retry_handler(_request: httpx.Request) -> httpx.Response: return httpx.Response(500) return httpx.Response(200) - respx_mock.post("/v1/vector_stores/search").mock(side_effect=retry_handler) + respx_mock.post("/v1/vector_stores").mock(side_effect=retry_handler) - response = await client.vector_stores.with_raw_response.search( - query="how to configure SSL", - vector_store_ids=["182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e"], - extra_headers={"x-stainless-retry-count": "42"}, - ) + response = await client.vector_stores.with_raw_response.create(extra_headers={"x-stainless-retry-count": "42"}) assert response.http_request.headers.get("x-stainless-retry-count") == "42" From 92279cc834a6deba02d1b128473366352a01dbaf Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 3 Apr 2025 21:33:00 +0000 Subject: [PATCH 5/5] release: 1.0.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 10 ++++++++++ README.md | 2 +- pyproject.toml | 2 +- src/mixedbread/_version.py | 2 +- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 9c28aaea..fea34540 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.41" + ".": "1.0.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d22e525..fc5e8693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # Changelog +## 1.0.0 (2025-04-03) + +Full Changelog: [v0.1.0-alpha.41...v1.0.0](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.1.0-alpha.41...v1.0.0) + +### Features + +* **api:** update via SDK Studio ([#180](https://github.com/mixedbread-ai/mixedbread-python/issues/180)) ([312a603](https://github.com/mixedbread-ai/mixedbread-python/commit/312a603bb67da9ff8409b1e0950a0dee03200636)) +* **api:** update via SDK Studio ([#182](https://github.com/mixedbread-ai/mixedbread-python/issues/182)) ([33480fc](https://github.com/mixedbread-ai/mixedbread-python/commit/33480fca59f6b3f67ad5acee09781ef22e240600)) +* **api:** update via SDK Studio ([#184](https://github.com/mixedbread-ai/mixedbread-python/issues/184)) ([651e092](https://github.com/mixedbread-ai/mixedbread-python/commit/651e0923c62e32345dfc39d67e38ef41dcc22028)) + ## 0.1.0-alpha.41 (2025-04-03) Full Changelog: [v0.1.0-alpha.40...v0.1.0-alpha.41](https://github.com/mixedbread-ai/mixedbread-python/compare/v0.1.0-alpha.40...v0.1.0-alpha.41) diff --git a/README.md b/README.md index 5d3e4084..dfea616f 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ The REST API documentation can be found on [mixedbread.com](https://mixedbread.c ```sh # install from PyPI -pip install --pre mixedbread +pip install mixedbread ``` ## Usage diff --git a/pyproject.toml b/pyproject.toml index 8871ff50..8c70343e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mixedbread" -version = "0.1.0-alpha.41" +version = "1.0.0" description = "The official Python library for the Mixedbread API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/mixedbread/_version.py b/src/mixedbread/_version.py index 18d791e8..a6b0880b 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.1.0-alpha.41" # x-release-please-version +__version__ = "1.0.0" # x-release-please-version