From 60103fc4a54b132a8aa3d11d5c19d9b08fdd121d Mon Sep 17 00:00:00 2001 From: Mathis Joffre <51022808+Joffref@users.noreply.github.com> Date: Mon, 24 Jun 2024 18:58:32 +0200 Subject: [PATCH] community: Fix OVHcloud 401 Unauthorized on embedding. (#23260) They are now rejecting with code 401 calls from users with expired or invalid tokens (while before they were being considered anonymous). Thus, the authorization header has to be removed when there is no token. Related to: #23178 --------- Signed-off-by: Joffref --- .../text_embedding/ovhcloud.ipynb | 18 ++++++++++++++- .../embeddings/ovhcloud.py | 19 +++++++--------- .../tests/integration_tests/test_ovhcloud.py | 8 ------- .../unit_tests/embeddings/test_ovhcloud.py | 22 ++++++++++++------- 4 files changed, 39 insertions(+), 28 deletions(-) delete mode 100644 libs/community/tests/integration_tests/test_ovhcloud.py diff --git a/docs/docs/integrations/text_embedding/ovhcloud.ipynb b/docs/docs/integrations/text_embedding/ovhcloud.ipynb index f60e328ef2..f79a022c69 100644 --- a/docs/docs/integrations/text_embedding/ovhcloud.ipynb +++ b/docs/docs/integrations/text_embedding/ovhcloud.ipynb @@ -7,12 +7,14 @@ "source": [ "# OVHcloud\n", "\n", + "> In order to use this model you need to create a new token on the AI Endpoints website: https://endpoints.ai.cloud.ovh.net/.\n", + "\n", "This notebook explains how to use OVHCloudEmbeddings, which is included in the langchain_community package, to embed texts in langchain." ] }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 4, "id": "3da0fce0", "metadata": {}, "outputs": [ @@ -35,6 +37,20 @@ "\"\"\" verify \"\"\"\n", "print(f\"Embedding generated by OVHCloudEmbeddings: {embed}\")" ] + }, + { + "cell_type": "markdown", + "id": "47c9af05-4d25-40f2-9305-7bccf1e14c64", + "metadata": {}, + "source": [ + "## Further reading\n", + "- [Enhance your applications with AI Endpoints](https://blog.ovhcloud.com/enhance-your-applications-with-ai-endpoints/)\n", + "- [How to use AI Endpoints and LangChain4j](https://blog.ovhcloud.com/how-to-use-ai-endpoints-and-langchain4j/)\n", + "- [LLMs streaming with AI Endpoints and LangChain4j](https://blog.ovhcloud.com/llms-streaming-with-ai-endpoints-and-langchain4j/)\n", + "- [How to use AI Endpoints and LangChain to create a chatbot](https://blog.ovhcloud.com/how-to-use-ai-endpoints-and-langchain-to-create-a-chatbot/)\n", + "- [How to use AI Endpoints, LangChain and Javascript to create a chatbot](https://blog.ovhcloud.com/how-to-use-ai-endpoints-langchain-and-javascript-to-create-a-chatbot/)\n", + "- [RAG chatbot using AI Endpoints and LangChain](https://blog.ovhcloud.com/rag-chatbot-using-ai-endpoints-and-langchain/)" + ] } ], "metadata": { diff --git a/libs/community/langchain_community/embeddings/ovhcloud.py b/libs/community/langchain_community/embeddings/ovhcloud.py index 7c90686246..7dde3810a2 100644 --- a/libs/community/langchain_community/embeddings/ovhcloud.py +++ b/libs/community/langchain_community/embeddings/ovhcloud.py @@ -1,6 +1,6 @@ import logging import time -from typing import Any, List, Optional +from typing import Any, List import requests from langchain_core.embeddings import Embeddings @@ -11,14 +11,11 @@ logger = logging.getLogger(__name__) class OVHCloudEmbeddings(BaseModel, Embeddings): """ - Usage: - OVH_AI_ENDPOINTS_ACCESS_TOKEN="your-token" python3 langchain_embedding.py - NB: Make sure you are using a valid token. - In the contrary, document indexing will be long due to rate-limiting. + OVHcloud AI Endpoints Embeddings. """ """ OVHcloud AI Endpoints Access Token""" - access_token: Optional[str] = None + access_token: str = "" """ OVHcloud AI Endpoints model name for embeddings generation""" model_name: str = "" @@ -33,10 +30,8 @@ class OVHCloudEmbeddings(BaseModel, Embeddings): def __init__(self, **kwargs: Any): super().__init__(**kwargs) - if self.access_token is None: - logger.warning( - "No access token provided indexing will be slow due to rate limiting." - ) + if self.access_token == "": + raise ValueError("Access token is required for OVHCloud embeddings.") if self.model_name == "": raise ValueError("Model name is required for OVHCloud embeddings.") if self.region == "": @@ -72,7 +67,9 @@ class OVHCloudEmbeddings(BaseModel, Embeddings): else: """Rate limit reset time has passed, retry immediately""" continue - + if response.status_code == 401: + """ Unauthorized, retry with new token """ + raise ValueError("Unauthorized, retry with new token") """ Handle other non-200 status codes """ raise ValueError( "Request failed with status code: {status_code}, {text}".format( diff --git a/libs/community/tests/integration_tests/test_ovhcloud.py b/libs/community/tests/integration_tests/test_ovhcloud.py deleted file mode 100644 index bbbaa9d721..0000000000 --- a/libs/community/tests/integration_tests/test_ovhcloud.py +++ /dev/null @@ -1,8 +0,0 @@ -from langchain_community.embeddings.ovhcloud import OVHCloudEmbeddings - - -def test_ovhcloud_embed_documents() -> None: - llm = OVHCloudEmbeddings(model_name="multilingual-e5-base") - docs = ["Hello", "World"] - output = llm.embed_documents(docs) - assert len(output) == len(docs) diff --git a/libs/community/tests/unit_tests/embeddings/test_ovhcloud.py b/libs/community/tests/unit_tests/embeddings/test_ovhcloud.py index caec981118..c06c1550e4 100644 --- a/libs/community/tests/unit_tests/embeddings/test_ovhcloud.py +++ b/libs/community/tests/unit_tests/embeddings/test_ovhcloud.py @@ -4,22 +4,28 @@ from langchain_community.embeddings.ovhcloud import OVHCloudEmbeddings def test_ovhcloud_correct_instantiation() -> None: - llm = OVHCloudEmbeddings(model_name="multilingual-e5-base") + llm = OVHCloudEmbeddings(model_name="multilingual-e5-base", access_token="token") + assert isinstance(llm, OVHCloudEmbeddings) + llm = OVHCloudEmbeddings( + model_name="multilingual-e5-base", region="kepler", access_token="token" + ) assert isinstance(llm, OVHCloudEmbeddings) def test_ovhcloud_empty_model_name_should_raise_error() -> None: with pytest.raises(ValueError): - OVHCloudEmbeddings(model_name="") + OVHCloudEmbeddings(model_name="", region="kepler", access_token="token") def test_ovhcloud_empty_region_should_raise_error() -> None: with pytest.raises(ValueError): - OVHCloudEmbeddings(model_name="multilingual-e5-base", region="") + OVHCloudEmbeddings( + model_name="multilingual-e5-base", region="", access_token="token" + ) -def test_ovhcloud_empty_access_token_should_not_raise_error() -> None: - llm = OVHCloudEmbeddings( - model_name="multilingual-e5-base", region="kepler", access_token="" - ) - assert isinstance(llm, OVHCloudEmbeddings) +def test_ovhcloud_empty_access_token_should_raise_error() -> None: + with pytest.raises(ValueError): + OVHCloudEmbeddings( + model_name="multilingual-e5-base", region="kepler", access_token="" + )