From 61dbfa867b3656f671d30a17e51113eba041cc02 Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Thu, 22 May 2025 14:02:23 +0000 Subject: [PATCH 1/2] ci: regenerated with OpenAPI Doc , Speakeasy CLI 1.517.3 --- .speakeasy/gen.lock | 8 +++--- .speakeasy/gen.yaml | 2 +- .speakeasy/workflow.lock | 11 +++---- RELEASES.md | 12 +++++++- docs/models/ocrimageobject.md | 3 +- docs/models/ocrrequest.md | 20 +++++++------ docs/models/ocrresponse.md | 11 +++---- docs/sdks/ocr/README.md | 22 +++++++------- pyproject.toml | 2 +- src/mistralai/_version.py | 6 ++-- src/mistralai/models/ocrimageobject.py | 8 +++++- src/mistralai/models/ocrrequest.py | 15 ++++++++++ src/mistralai/models/ocrresponse.py | 40 ++++++++++++++++++++++++-- src/mistralai/ocr.py | 28 ++++++++++++++++++ 14 files changed, 145 insertions(+), 43 deletions(-) diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index bc731e9a..1a9287fc 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: 2d045ec7-2ebb-4f4d-ad25-40953b132161 management: - docChecksum: 63f1a973632e9afab0da3d2498994c1b - docVersion: 0.0.2 + docChecksum: 3589e9f1ea5775264c5c8e0887b4ea0e + docVersion: 1.0.0 speakeasyVersion: 1.517.3 generationVersion: 2.548.6 - releaseVersion: 1.7.0 - configChecksum: d52ab0a71ab9e0798da08262c59bf31d + releaseVersion: 1.7.1 + configChecksum: d35541d61057b11258d7d56bbc5c5260 repoURL: https://github.com/mistralai/client-python.git installationURL: https://github.com/mistralai/client-python.git published: true diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 4bf0297c..35d79fdf 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -15,7 +15,7 @@ generation: oAuth2ClientCredentialsEnabled: true oAuth2PasswordEnabled: false python: - version: 1.7.0 + version: 1.7.1 additionalDependencies: dev: pytest: ^8.2.2 diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 5c57d996..eaadc1d2 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -14,10 +14,11 @@ sources: - latest mistral-openapi: sourceNamespace: mistral-openapi - sourceRevisionDigest: sha256:e7953d0c99d1c036d6bfe223052f231a89626f7007a105a96258dad2eedab39e - sourceBlobDigest: sha256:66ed2d18b563f3350de4ab16c9e2ca6ce425c6376feb5fcf1511d5d074908091 + sourceRevisionDigest: sha256:14f5a88b723582e80ead33d129f287568eed05815a9437b7ff5c890ca4c93318 + sourceBlobDigest: sha256:230b4f22197e202aebd70f8628844a27fe70b9b27569dbc3338d3e7d5442cb88 tags: - latest + - speakeasy-sdk-regen-1747922489 targets: mistralai-azure-sdk: source: mistral-azure-source @@ -36,10 +37,10 @@ targets: mistralai-sdk: source: mistral-openapi sourceNamespace: mistral-openapi - sourceRevisionDigest: sha256:e7953d0c99d1c036d6bfe223052f231a89626f7007a105a96258dad2eedab39e - sourceBlobDigest: sha256:66ed2d18b563f3350de4ab16c9e2ca6ce425c6376feb5fcf1511d5d074908091 + sourceRevisionDigest: sha256:14f5a88b723582e80ead33d129f287568eed05815a9437b7ff5c890ca4c93318 + sourceBlobDigest: sha256:230b4f22197e202aebd70f8628844a27fe70b9b27569dbc3338d3e7d5442cb88 codeSamplesNamespace: mistral-openapi-code-samples - codeSamplesRevisionDigest: sha256:7c657301f482932fca0a3e914d3c25820ebb7e535e1887daea3cd9240eca0444 + codeSamplesRevisionDigest: sha256:d75cede62f03f1040732d65da392f66fe75c725dab04cdfba5498ad334652c1e workflow: workflowVersion: 1.0.0 speakeasyVersion: 1.517.3 diff --git a/RELEASES.md b/RELEASES.md index 629e92d9..78b5b585 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -198,4 +198,14 @@ Based on: ### Generated - [python v1.7.0] . ### Releases -- [PyPI v1.7.0] https://pypi.org/project/mistralai/1.7.0 - . \ No newline at end of file +- [PyPI v1.7.0] https://pypi.org/project/mistralai/1.7.0 - . + +## 2025-05-22 14:01:13 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.517.3 (2.548.6) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.7.1] . +### Releases +- [PyPI v1.7.1] https://pypi.org/project/mistralai/1.7.1 - . \ No newline at end of file diff --git a/docs/models/ocrimageobject.md b/docs/models/ocrimageobject.md index 273cfa9a..3c0d5544 100644 --- a/docs/models/ocrimageobject.md +++ b/docs/models/ocrimageobject.md @@ -10,4 +10,5 @@ | `top_left_y` | *Nullable[int]* | :heavy_check_mark: | Y coordinate of top-left corner of the extracted image | | `bottom_right_x` | *Nullable[int]* | :heavy_check_mark: | X coordinate of bottom-right corner of the extracted image | | `bottom_right_y` | *Nullable[int]* | :heavy_check_mark: | Y coordinate of bottom-right corner of the extracted image | -| `image_base64` | *OptionalNullable[str]* | :heavy_minus_sign: | Base64 string of the extracted image | \ No newline at end of file +| `image_base64` | *OptionalNullable[str]* | :heavy_minus_sign: | Base64 string of the extracted image | +| `image_annotation` | *OptionalNullable[str]* | :heavy_minus_sign: | Annotation of the extracted image in json str | \ No newline at end of file diff --git a/docs/models/ocrrequest.md b/docs/models/ocrrequest.md index dbc4dc80..0c8954a5 100644 --- a/docs/models/ocrrequest.md +++ b/docs/models/ocrrequest.md @@ -3,12 +3,14 @@ ## Fields -| Field | Type | Required | Description | -| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -| `model` | *Nullable[str]* | :heavy_check_mark: | N/A | -| `document` | [models.Document](../models/document.md) | :heavy_check_mark: | Document to run OCR on | -| `id` | *Optional[str]* | :heavy_minus_sign: | N/A | -| `pages` | List[*int*] | :heavy_minus_sign: | Specific pages user wants to process in various formats: single number, range, or list of both. Starts from 0 | -| `include_image_base64` | *OptionalNullable[bool]* | :heavy_minus_sign: | Include image URLs in response | -| `image_limit` | *OptionalNullable[int]* | :heavy_minus_sign: | Max images to extract | -| `image_min_size` | *OptionalNullable[int]* | :heavy_minus_sign: | Minimum height and width of image to extract | \ No newline at end of file +| Field | Type | Required | Description | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `model` | *Nullable[str]* | :heavy_check_mark: | N/A | +| `document` | [models.Document](../models/document.md) | :heavy_check_mark: | Document to run OCR on | +| `id` | *Optional[str]* | :heavy_minus_sign: | N/A | +| `pages` | List[*int*] | :heavy_minus_sign: | Specific pages user wants to process in various formats: single number, range, or list of both. Starts from 0 | +| `include_image_base64` | *OptionalNullable[bool]* | :heavy_minus_sign: | Include image URLs in response | +| `image_limit` | *OptionalNullable[int]* | :heavy_minus_sign: | Max images to extract | +| `image_min_size` | *OptionalNullable[int]* | :heavy_minus_sign: | Minimum height and width of image to extract | +| `bbox_annotation_format` | [OptionalNullable[models.ResponseFormat]](../models/responseformat.md) | :heavy_minus_sign: | Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field | +| `document_annotation_format` | [OptionalNullable[models.ResponseFormat]](../models/responseformat.md) | :heavy_minus_sign: | Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field | \ No newline at end of file diff --git a/docs/models/ocrresponse.md b/docs/models/ocrresponse.md index 690d992d..7d6a58ae 100644 --- a/docs/models/ocrresponse.md +++ b/docs/models/ocrresponse.md @@ -3,8 +3,9 @@ ## Fields -| Field | Type | Required | Description | -| -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -| `pages` | List[[models.OCRPageObject](../models/ocrpageobject.md)] | :heavy_check_mark: | List of OCR info for pages. | -| `model` | *str* | :heavy_check_mark: | The model used to generate the OCR. | -| `usage_info` | [models.OCRUsageInfo](../models/ocrusageinfo.md) | :heavy_check_mark: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| ---------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------- | +| `pages` | List[[models.OCRPageObject](../models/ocrpageobject.md)] | :heavy_check_mark: | List of OCR info for pages. | +| `model` | *str* | :heavy_check_mark: | The model used to generate the OCR. | +| `usage_info` | [models.OCRUsageInfo](../models/ocrusageinfo.md) | :heavy_check_mark: | N/A | +| `document_annotation` | *OptionalNullable[str]* | :heavy_minus_sign: | Formatted response in the request_format if provided in json str | \ No newline at end of file diff --git a/docs/sdks/ocr/README.md b/docs/sdks/ocr/README.md index 61988ea6..60d987b4 100644 --- a/docs/sdks/ocr/README.md +++ b/docs/sdks/ocr/README.md @@ -36,16 +36,18 @@ with Mistral( ### Parameters -| Parameter | Type | Required | Description | -| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | -| `model` | *Nullable[str]* | :heavy_check_mark: | N/A | -| `document` | [models.Document](../../models/document.md) | :heavy_check_mark: | Document to run OCR on | -| `id` | *Optional[str]* | :heavy_minus_sign: | N/A | -| `pages` | List[*int*] | :heavy_minus_sign: | Specific pages user wants to process in various formats: single number, range, or list of both. Starts from 0 | -| `include_image_base64` | *OptionalNullable[bool]* | :heavy_minus_sign: | Include image URLs in response | -| `image_limit` | *OptionalNullable[int]* | :heavy_minus_sign: | Max images to extract | -| `image_min_size` | *OptionalNullable[int]* | :heavy_minus_sign: | Minimum height and width of image to extract | -| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | +| Parameter | Type | Required | Description | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `model` | *Nullable[str]* | :heavy_check_mark: | N/A | +| `document` | [models.Document](../../models/document.md) | :heavy_check_mark: | Document to run OCR on | +| `id` | *Optional[str]* | :heavy_minus_sign: | N/A | +| `pages` | List[*int*] | :heavy_minus_sign: | Specific pages user wants to process in various formats: single number, range, or list of both. Starts from 0 | +| `include_image_base64` | *OptionalNullable[bool]* | :heavy_minus_sign: | Include image URLs in response | +| `image_limit` | *OptionalNullable[int]* | :heavy_minus_sign: | Max images to extract | +| `image_min_size` | *OptionalNullable[int]* | :heavy_minus_sign: | Minimum height and width of image to extract | +| `bbox_annotation_format` | [OptionalNullable[models.ResponseFormat]](../../models/responseformat.md) | :heavy_minus_sign: | Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field | +| `document_annotation_format` | [OptionalNullable[models.ResponseFormat]](../../models/responseformat.md) | :heavy_minus_sign: | Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | ### Response diff --git a/pyproject.toml b/pyproject.toml index 2da8b5ea..1d7bd53d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "mistralai" -version = "1.7.0" +version = "1.7.1" description = "Python Client SDK for the Mistral AI API." authors = [{ name = "Mistral" },] readme = "README-PYPI.md" diff --git a/src/mistralai/_version.py b/src/mistralai/_version.py index 7b151c78..ade7e11c 100644 --- a/src/mistralai/_version.py +++ b/src/mistralai/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "mistralai" -__version__: str = "1.7.0" -__openapi_doc_version__: str = "0.0.2" +__version__: str = "1.7.1" +__openapi_doc_version__: str = "1.0.0" __gen_version__: str = "2.548.6" -__user_agent__: str = "speakeasy-sdk/python 1.7.0 2.548.6 0.0.2 mistralai" +__user_agent__: str = "speakeasy-sdk/python 1.7.1 2.548.6 1.0.0 mistralai" try: if __package__ is not None: diff --git a/src/mistralai/models/ocrimageobject.py b/src/mistralai/models/ocrimageobject.py index 16b41e6c..78e37c1f 100644 --- a/src/mistralai/models/ocrimageobject.py +++ b/src/mistralai/models/ocrimageobject.py @@ -19,6 +19,8 @@ class OCRImageObjectTypedDict(TypedDict): r"""Y coordinate of bottom-right corner of the extracted image""" image_base64: NotRequired[Nullable[str]] r"""Base64 string of the extracted image""" + image_annotation: NotRequired[Nullable[str]] + r"""Annotation of the extracted image in json str""" class OCRImageObject(BaseModel): @@ -40,15 +42,19 @@ class OCRImageObject(BaseModel): image_base64: OptionalNullable[str] = UNSET r"""Base64 string of the extracted image""" + image_annotation: OptionalNullable[str] = UNSET + r"""Annotation of the extracted image in json str""" + @model_serializer(mode="wrap") def serialize_model(self, handler): - optional_fields = ["image_base64"] + optional_fields = ["image_base64", "image_annotation"] nullable_fields = [ "top_left_x", "top_left_y", "bottom_right_x", "bottom_right_y", "image_base64", + "image_annotation", ] null_default_fields = [] diff --git a/src/mistralai/models/ocrrequest.py b/src/mistralai/models/ocrrequest.py index 54339e9e..4f9dfd47 100644 --- a/src/mistralai/models/ocrrequest.py +++ b/src/mistralai/models/ocrrequest.py @@ -3,6 +3,7 @@ from __future__ import annotations from .documenturlchunk import DocumentURLChunk, DocumentURLChunkTypedDict from .imageurlchunk import ImageURLChunk, ImageURLChunkTypedDict +from .responseformat import ResponseFormat, ResponseFormatTypedDict from mistralai.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL from pydantic import model_serializer from typing import List, Optional, Union @@ -32,6 +33,10 @@ class OCRRequestTypedDict(TypedDict): r"""Max images to extract""" image_min_size: NotRequired[Nullable[int]] r"""Minimum height and width of image to extract""" + bbox_annotation_format: NotRequired[Nullable[ResponseFormatTypedDict]] + r"""Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field""" + document_annotation_format: NotRequired[Nullable[ResponseFormatTypedDict]] + r"""Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field""" class OCRRequest(BaseModel): @@ -54,6 +59,12 @@ class OCRRequest(BaseModel): image_min_size: OptionalNullable[int] = UNSET r"""Minimum height and width of image to extract""" + bbox_annotation_format: OptionalNullable[ResponseFormat] = UNSET + r"""Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field""" + + document_annotation_format: OptionalNullable[ResponseFormat] = UNSET + r"""Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field""" + @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = [ @@ -62,6 +73,8 @@ def serialize_model(self, handler): "include_image_base64", "image_limit", "image_min_size", + "bbox_annotation_format", + "document_annotation_format", ] nullable_fields = [ "model", @@ -69,6 +82,8 @@ def serialize_model(self, handler): "include_image_base64", "image_limit", "image_min_size", + "bbox_annotation_format", + "document_annotation_format", ] null_default_fields = [] diff --git a/src/mistralai/models/ocrresponse.py b/src/mistralai/models/ocrresponse.py index 45fb06e3..df3b7d18 100644 --- a/src/mistralai/models/ocrresponse.py +++ b/src/mistralai/models/ocrresponse.py @@ -3,9 +3,10 @@ from __future__ import annotations from .ocrpageobject import OCRPageObject, OCRPageObjectTypedDict from .ocrusageinfo import OCRUsageInfo, OCRUsageInfoTypedDict -from mistralai.types import BaseModel +from mistralai.types import BaseModel, Nullable, OptionalNullable, UNSET, UNSET_SENTINEL +from pydantic import model_serializer from typing import List -from typing_extensions import TypedDict +from typing_extensions import NotRequired, TypedDict class OCRResponseTypedDict(TypedDict): @@ -14,6 +15,8 @@ class OCRResponseTypedDict(TypedDict): model: str r"""The model used to generate the OCR.""" usage_info: OCRUsageInfoTypedDict + document_annotation: NotRequired[Nullable[str]] + r"""Formatted response in the request_format if provided in json str""" class OCRResponse(BaseModel): @@ -24,3 +27,36 @@ class OCRResponse(BaseModel): r"""The model used to generate the OCR.""" usage_info: OCRUsageInfo + + document_annotation: OptionalNullable[str] = UNSET + r"""Formatted response in the request_format if provided in json str""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = ["document_annotation"] + nullable_fields = ["document_annotation"] + null_default_fields = [] + + serialized = handler(self) + + m = {} + + for n, f in self.model_fields.items(): + k = f.alias or n + val = serialized.get(k) + serialized.pop(k, None) + + optional_nullable = k in optional_fields and k in nullable_fields + is_set = ( + self.__pydantic_fields_set__.intersection({n}) + or k in null_default_fields + ) # pylint: disable=no-member + + if val is not None and val != UNSET_SENTINEL: + m[k] = val + elif val != UNSET_SENTINEL and ( + not k in optional_fields or (optional_nullable and is_set) + ): + m[k] = val + + return m diff --git a/src/mistralai/ocr.py b/src/mistralai/ocr.py index 5d0e2414..cdc56ae8 100644 --- a/src/mistralai/ocr.py +++ b/src/mistralai/ocr.py @@ -21,6 +21,12 @@ def process( include_image_base64: OptionalNullable[bool] = UNSET, image_limit: OptionalNullable[int] = UNSET, image_min_size: OptionalNullable[int] = UNSET, + bbox_annotation_format: OptionalNullable[ + Union[models.ResponseFormat, models.ResponseFormatTypedDict] + ] = UNSET, + document_annotation_format: OptionalNullable[ + Union[models.ResponseFormat, models.ResponseFormatTypedDict] + ] = UNSET, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -35,6 +41,8 @@ def process( :param include_image_base64: Include image URLs in response :param image_limit: Max images to extract :param image_min_size: Minimum height and width of image to extract + :param bbox_annotation_format: Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field + :param document_annotation_format: Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field :param retries: Override the default retry configuration for this method :param server_url: Override the default server URL for this method :param timeout_ms: Override the default request timeout configuration for this method in milliseconds @@ -58,6 +66,12 @@ def process( include_image_base64=include_image_base64, image_limit=image_limit, image_min_size=image_min_size, + bbox_annotation_format=utils.get_pydantic_model( + bbox_annotation_format, OptionalNullable[models.ResponseFormat] + ), + document_annotation_format=utils.get_pydantic_model( + document_annotation_format, OptionalNullable[models.ResponseFormat] + ), ) req = self._build_request( @@ -139,6 +153,12 @@ async def process_async( include_image_base64: OptionalNullable[bool] = UNSET, image_limit: OptionalNullable[int] = UNSET, image_min_size: OptionalNullable[int] = UNSET, + bbox_annotation_format: OptionalNullable[ + Union[models.ResponseFormat, models.ResponseFormatTypedDict] + ] = UNSET, + document_annotation_format: OptionalNullable[ + Union[models.ResponseFormat, models.ResponseFormatTypedDict] + ] = UNSET, retries: OptionalNullable[utils.RetryConfig] = UNSET, server_url: Optional[str] = None, timeout_ms: Optional[int] = None, @@ -153,6 +173,8 @@ async def process_async( :param include_image_base64: Include image URLs in response :param image_limit: Max images to extract :param image_min_size: Minimum height and width of image to extract + :param bbox_annotation_format: Structured output class for extracting useful information from each extracted bounding box / image from document. Only json_schema is valid for this field + :param document_annotation_format: Structured output class for extracting useful information from the entire document. Only json_schema is valid for this field :param retries: Override the default retry configuration for this method :param server_url: Override the default server URL for this method :param timeout_ms: Override the default request timeout configuration for this method in milliseconds @@ -176,6 +198,12 @@ async def process_async( include_image_base64=include_image_base64, image_limit=image_limit, image_min_size=image_min_size, + bbox_annotation_format=utils.get_pydantic_model( + bbox_annotation_format, OptionalNullable[models.ResponseFormat] + ), + document_annotation_format=utils.get_pydantic_model( + document_annotation_format, OptionalNullable[models.ResponseFormat] + ), ) req = self._build_request_async( From e46bd0780c8aad1e96f55aae200d1c185cc627fa Mon Sep 17 00:00:00 2001 From: Jean-Malo Delignon <56539593+jean-malo@users.noreply.github.com> Date: Thu, 22 May 2025 16:08:10 +0200 Subject: [PATCH 2/2] Update RELEASES.md --- RELEASES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 78b5b585..791fb70b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -202,10 +202,12 @@ Based on: ## 2025-05-22 14:01:13 ### Changes +- Added support for `document_annotation_format` and `bbox_annotation_format` in `client.ocr.process` + Based on: - OpenAPI Doc - Speakeasy CLI 1.517.3 (2.548.6) https://github.com/speakeasy-api/speakeasy ### Generated - [python v1.7.1] . ### Releases -- [PyPI v1.7.1] https://pypi.org/project/mistralai/1.7.1 - . \ No newline at end of file +- [PyPI v1.7.1] https://pypi.org/project/mistralai/1.7.1 - .