Skip to content

Commit d548463

Browse files
gustavocidornelaswhoseoyster
authored andcommitted
Completes OPEN-4865 Raise custom Openlayer errors for well-known user errors for LLMs
1 parent fb9952c commit d548463

File tree

5 files changed

+62
-20
lines changed

5 files changed

+62
-20
lines changed

openlayer/api.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
from tqdm import tqdm
3030
from tqdm.utils import CallbackIOWrapper
3131

32+
from . import constants
3233
from .exceptions import ExceptionMap, OpenlayerException
3334
from .version import __version__
3435

@@ -39,7 +40,6 @@
3940
HTTP_RETRY_ALLOWED_METHODS = frozenset({"GET", "PUT", "POST"})
4041

4142
CLIENT_METADATA = {"version": __version__}
42-
REQUESTS_TIMEOUT = 60 * 60 * 3 # 3 hours
4343

4444

4545
class StorageType(Enum):
@@ -230,7 +230,7 @@ def upload_blob_s3(
230230
data=m,
231231
headers=headers,
232232
verify=VERIFY_REQUESTS,
233-
timeout=REQUESTS_TIMEOUT,
233+
timeout=constants.REQUESTS_TIMEOUT,
234234
)
235235

236236
if res.ok:
@@ -260,7 +260,7 @@ def upload_blob_gcs(
260260
data=wrapped_file,
261261
headers={"Content-Type": "application/x-gzip"},
262262
verify=VERIFY_REQUESTS,
263-
timeout=REQUESTS_TIMEOUT,
263+
timeout=constants.REQUESTS_TIMEOUT,
264264
)
265265
if res.ok:
266266
body["storageUri"] = presigned_json["storageUri"]
@@ -292,7 +292,7 @@ def upload_blob_azure(
292292
"x-ms-blob-type": "BlockBlob",
293293
},
294294
verify=VERIFY_REQUESTS,
295-
timeout=REQUESTS_TIMEOUT,
295+
timeout=constants.REQUESTS_TIMEOUT,
296296
)
297297
if res.ok:
298298
body["storageUri"] = presigned_json["storageUri"]

openlayer/constants.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,6 @@
99
# -------------------------------- Size limits ------------------------------- #
1010
MAXIMUM_CHARACTER_LIMIT = 10000
1111
MAXIMUM_TAR_FILE_SIZE = 25 # MB
12+
13+
# ----------------------------------- APIs ----------------------------------- #
14+
REQUESTS_TIMEOUT = 60 * 60 * 3 # 3 hours

openlayer/exceptions.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,38 @@ class OpenlayerTimeoutError(OpenlayerException):
107107
code = 504
108108

109109

110+
# -------------------------- LLM-specific exceptions ------------------------- #
111+
class OpenlayerLlmException(OpenlayerException):
112+
"""Generic LLM exception class"""
113+
114+
def __init__(self, message):
115+
super().__init__(message)
116+
117+
118+
class OpenlayerUnsupportedLlmProvider(OpenlayerLlmException):
119+
"""Unsupported provider exception class"""
120+
121+
def __init__(self, message, provider):
122+
message = f"Unsupported LLM provider '{provider}'. " + message
123+
super().__init__(message)
124+
125+
126+
class OpenlayerMissingLlmApiKey(OpenlayerLlmException):
127+
"""Missing LLM API key exception class"""
128+
129+
def __init__(self, message):
130+
message = "Missing API key for the LLM provider. " + message
131+
super().__init__(message)
132+
133+
134+
class OpenlayerInvalidLlmApiKey(OpenlayerLlmException):
135+
"""Invalid LLM API key exception class"""
136+
137+
def __init__(self, message):
138+
message = "Invalid API key for the LLM provider. " + message
139+
super().__init__(message)
140+
141+
110142
ExceptionMap: Dict[int, OpenlayerException] = {
111143
OpenlayerInvalidRequest.code: OpenlayerInvalidRequest,
112144
OpenlayerUnauthorized.code: OpenlayerUnauthorized,

openlayer/model_runners/ll_model_runners.py

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
import requests
1818
from tqdm import tqdm
1919

20+
from .. import constants
21+
from .. import exceptions as openlayer_exceptions
2022
from . import base_model_runner
2123

2224

@@ -287,8 +289,8 @@ def __init__(
287289
):
288290
super().__init__(logger, **kwargs)
289291
if kwargs.get("anthropic_api_key") is None:
290-
raise ValueError(
291-
"Anthropic API key must be provided. Please pass it as the "
292+
raise openlayer_exceptions.OpenlayerMissingLlmApiKey(
293+
"Please pass your Anthropic API key as the "
292294
"keyword argument 'anthropic_api_key'"
293295
)
294296

@@ -358,8 +360,8 @@ def __init__(
358360
):
359361
super().__init__(logger, **kwargs)
360362
if kwargs.get("cohere_api_key") is None:
361-
raise ValueError(
362-
"Cohere API key must be provided. Please pass it as the "
363+
raise openlayer_exceptions.OpenlayerMissingLlmApiKey(
364+
"Please pass your Cohere API key as the "
363365
"keyword argument 'cohere_api_key'"
364366
)
365367

@@ -374,8 +376,8 @@ def _initialize_llm(self):
374376
api_key=self.cohere_api_key, check_api_key=True
375377
)
376378
except Exception as e:
377-
raise ValueError(
378-
"Cohere API key is invalid. Please pass a valid API key as the "
379+
raise openlayer_exceptions.OpenlayerInvalidLlmApiKey(
380+
"Please pass a valid Cohere API key as the "
379381
f"keyword argument 'cohere_api_key' \n Error message: {e}"
380382
) from e
381383
if self.model_config.get("model") is None:
@@ -441,8 +443,8 @@ def __init__(
441443
):
442444
super().__init__(logger, **kwargs)
443445
if kwargs.get("openai_api_key") is None:
444-
raise ValueError(
445-
"OpenAI API key must be provided. Please pass it as the "
446+
raise openlayer_exceptions.OpenlayerMissingLlmApiKey(
447+
"Please pass your OpenAI API key as the "
446448
"keyword argument 'openai_api_key'"
447449
)
448450

@@ -459,8 +461,8 @@ def _initialize_llm(self):
459461
try:
460462
openai.Model.list()
461463
except Exception as e:
462-
raise ValueError(
463-
"OpenAI API key is invalid. Please pass a valid API key as the "
464+
raise openlayer_exceptions.OpenlayerInvalidLlmApiKey(
465+
"Please pass a valid OpenAI API key as the "
464466
f"keyword argument 'openai_api_key' \n Error message: {e}"
465467
) from e
466468
if self.model_config.get("model") is None:
@@ -540,8 +542,7 @@ def _initialize_llm(self):
540542
"""Initializes the self-hosted LL model."""
541543
# Check if API key is valid
542544
try:
543-
# TODO: move request timeout to constants.py
544-
requests.get(self.url, timeout=10800)
545+
requests.get(self.url, timeout=constants.REQUESTS_TIMEOUT)
545546
except Exception as e:
546547
raise ValueError(
547548
"URL is invalid. Please pass a valid URL as the "
@@ -574,8 +575,9 @@ def _make_request(self, llm_input: str) -> Dict[str, Any]:
574575
"Content-Type": "application/json",
575576
}
576577
data = {self.input_key: llm_input}
577-
# TODO: move request timeout to constants.py
578-
response = requests.post(self.url, headers=headers, json=data, timeout=10800)
578+
response = requests.post(
579+
self.url, headers=headers, json=data, timeout=constants.REQUESTS_TIMEOUT
580+
)
579581
if response.status_code == 200:
580582
response_data = response.json()[0]
581583
return response_data

openlayer/models.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from enum import Enum
1010
from typing import Any, Dict
1111

12-
from . import tasks, utils
12+
from . import exceptions, tasks, utils
1313
from .model_runners import (
1414
base_model_runner,
1515
ll_model_runners,
@@ -172,7 +172,12 @@ def _create_ll_model_runner(
172172
raise ValueError("Model provider is required for LLM task types.")
173173

174174
if model_provider not in ModelRunnerFactory._LLM_PROVIDERS:
175-
raise ValueError(f"Model provider `{model_provider}` is not supported.")
175+
raise exceptions.OpenlayerUnsupportedLlmProvider(
176+
provider=model_provider,
177+
message="\nCurrently, the supported providers are: 'OpenAI', 'Cohere',"
178+
" 'Anthropic', 'SelfHosted', 'HuggingFace'. Reach out if you'd like us"
179+
" to support your use case.",
180+
)
176181

177182
model_runner_class = ModelRunnerFactory._LL_MODEL_RUNNERS[task_type.value][
178183
model_provider

0 commit comments

Comments
 (0)