Skip to content

Commit 08bb74f

Browse files
authored
fix(mistralai): handle HTTP errors in async embed documents (#33187)
The async embed function does not properly handle HTTP errors. For instance with large batches, Mistral AI returns `Too many inputs in request, split into more batches.` in a 400 error. This leads to a KeyError in `response.json()["data"]` l.288 This PR fixes the issue by: - calling `response.raise_for_status()` before returning - adding a retry similarly to what is done in the synchronous counterpart `embed_documents` I also added an integration test, but willing to move it to unit tests if more relevant.
1 parent 7d78ed9 commit 08bb74f

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

libs/partners/mistralai/langchain_mistralai/embeddings.py

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -267,20 +267,29 @@ async def aembed_documents(self, texts: list[str]) -> list[list[float]]:
267267
268268
Returns:
269269
List of embeddings, one for each text.
270-
271270
"""
272271
try:
272+
273+
@retry(
274+
retry=retry_if_exception_type(
275+
(httpx.TimeoutException, httpx.HTTPStatusError)
276+
),
277+
wait=wait_fixed(self.wait_time),
278+
stop=stop_after_attempt(self.max_retries),
279+
)
280+
async def _aembed_batch(batch: list[str]) -> Response:
281+
response = await self.async_client.post(
282+
url="/embeddings",
283+
json={
284+
"model": self.model,
285+
"input": batch,
286+
},
287+
)
288+
response.raise_for_status()
289+
return response
290+
273291
batch_responses = await asyncio.gather(
274-
*[
275-
self.async_client.post(
276-
url="/embeddings",
277-
json={
278-
"model": self.model,
279-
"input": batch,
280-
},
281-
)
282-
for batch in self._get_batches(texts)
283-
]
292+
*[_aembed_batch(batch) for batch in self._get_batches(texts)]
284293
)
285294
return [
286295
list(map(float, embedding_obj["embedding"]))

libs/partners/mistralai/tests/integration_tests/test_embeddings.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
"""Test MistralAI Embedding."""
22

3+
from unittest.mock import patch
4+
5+
import httpx
6+
import pytest
7+
import tenacity
8+
39
from langchain_mistralai import MistralAIEmbeddings
410

511

@@ -29,6 +35,21 @@ async def test_mistralai_embedding_documents_async() -> None:
2935
assert len(output[0]) == 1024
3036

3137

38+
async def test_mistralai_embedding_documents_http_error_async() -> None:
39+
"""Test MistralAI embeddings for documents."""
40+
documents = ["foo bar", "test document"]
41+
embedding = MistralAIEmbeddings(max_retries=0)
42+
mock_response = httpx.Response(
43+
status_code=400,
44+
request=httpx.Request("POST", url=embedding.async_client.base_url),
45+
)
46+
with (
47+
patch.object(embedding.async_client, "post", return_value=mock_response),
48+
pytest.raises(tenacity.RetryError),
49+
):
50+
await embedding.aembed_documents(documents)
51+
52+
3253
async def test_mistralai_embedding_query_async() -> None:
3354
"""Test MistralAI embeddings for query."""
3455
document = "foo bar"

0 commit comments

Comments
 (0)