Skip to content

Commit 9de375b

Browse files
authored
Merge pull request #39 from cloudera/dev
Refactor and Path management
2 parents 6e4a8d7 + d9ab279 commit 9de375b

File tree

10 files changed

+804
-613
lines changed

10 files changed

+804
-613
lines changed

app/core/config.py

Lines changed: 98 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from enum import Enum
22
from typing import Dict, List, Optional
33
from pydantic import BaseModel
4+
from fastapi import FastAPI, HTTPException, Request, status
5+
import requests
6+
import json
7+
from fastapi.responses import JSONResponse
48

59
class UseCase(str, Enum):
610
CODE_GENERATION = "code_generation"
@@ -58,7 +62,11 @@ class UseCaseMetadata(BaseModel):
5862
budget DECIMAL(15,2)
5963
);
6064
"""
61-
65+
bedrock_list = ['us.anthropic.claude-3-5-haiku-20241022-v1:0', 'us.anthropic.claude-3-5-sonnet-20241022-v2:0',
66+
'us.anthropic.claude-3-opus-20240229-v1:0','anthropic.claude-instant-v1',
67+
'us.meta.llama3-2-11b-instruct-v1:0','us.meta.llama3-2-90b-instruct-v1:0', 'us.meta.llama3-1-70b-instruct-v1:0',
68+
'mistral.mixtral-8x7b-instruct-v0:1', 'mistral.mistral-large-2402-v1:0',
69+
'mistral.mistral-small-2402-v1:0' ]
6270

6371
# Detailed use case configurations with examples
6472
USE_CASE_CONFIGS = {
@@ -198,4 +206,92 @@ def get_examples_for_topic(use_case: UseCase, topic: str) -> List[Dict[str, str]
198206
if not topic_metadata:
199207
return use_case_config.default_examples
200208

201-
return topic_metadata.example_questions
209+
return topic_metadata.example_questions
210+
211+
212+
responses = {
213+
# 4XX Client Errors
214+
status.HTTP_400_BAD_REQUEST: {
215+
"description": "Bad Request - Invalid input parameters",
216+
"content": {
217+
"application/json": {
218+
"example": {
219+
"status": "failed",
220+
"error": "Invalid input: No topics provided"
221+
}
222+
}
223+
}
224+
},
225+
status.HTTP_404_NOT_FOUND: {
226+
"description": "Resource not found",
227+
"content": {
228+
"application/json": {
229+
"example": {
230+
"status": "failed",
231+
"error": "Requested resource not found"
232+
}
233+
}
234+
}
235+
},
236+
status.HTTP_422_UNPROCESSABLE_ENTITY: {
237+
"description": "Validation Error",
238+
"content": {
239+
"application/json": {
240+
"example": {
241+
"status": "failed",
242+
"error": "Invalid request parameters"
243+
}
244+
}
245+
}
246+
},
247+
248+
# 5XX Server Errors
249+
status.HTTP_500_INTERNAL_SERVER_ERROR: {
250+
"description": "Internal server error",
251+
"content": {
252+
"application/json": {
253+
"example": {
254+
"status": "failed",
255+
"error": "Internal server error occurred"
256+
}
257+
}
258+
}
259+
},
260+
status.HTTP_503_SERVICE_UNAVAILABLE: {
261+
"description": "Service temporarily unavailable",
262+
"content": {
263+
"application/json": {
264+
"example": {
265+
"status": "failed",
266+
"error": "The CAII endpoint is downscaled, please try after >15 minutes"
267+
}
268+
}
269+
}
270+
},
271+
status.HTTP_504_GATEWAY_TIMEOUT: {
272+
"description": "Request timed out",
273+
"content": {
274+
"application/json": {
275+
"example": {
276+
"status": "failed",
277+
"error": "Operation timed out after specified seconds"
278+
}
279+
}
280+
}
281+
}
282+
}
283+
284+
285+
def caii_check(caii_endpoint):
286+
API_KEY = json.load(open("/tmp/jwt"))["access_token"]
287+
headers = {
288+
"Authorization": f"Bearer {API_KEY}"
289+
}
290+
291+
292+
if caii_endpoint:
293+
caii_endpoint = caii_endpoint.removesuffix('/chat/completions')
294+
caii_endpoint = caii_endpoint + "/models"
295+
response = requests.get(caii_endpoint, headers=headers, timeout=3) # Will raise RequestException if fails
296+
297+
return response

app/core/exceptions.py

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,64 @@
1+
from typing import Optional, Dict, Any
2+
13
class APIError(Exception):
2-
def __init__(self, message: str, status_code: int = 400):
4+
"""Base exception for API errors"""
5+
def __init__(self, message: str, status_code: int = 400, details: Optional[Dict[str, Any]] = None):
36
self.message = message
47
self.status_code = status_code
8+
self.details = details or {}
59
super().__init__(message)
6-
10+
711
class ModelHandlerError(APIError):
12+
"""Errors related to model handling"""
813
pass
914

1015
class InvalidModelError(ModelHandlerError):
11-
def __init__(self, model_id: str):
16+
"""Invalid model configuration or access errors
17+
18+
Status code 404 (Not Found) is used because:
19+
- The requested model resource cannot be found or accessed
20+
- This includes cases where the model exists but cannot be accessed due to configuration
21+
- Follows REST principles for resource not found scenarios
22+
"""
23+
def __init__(self, model_id: str, error: str):
24+
# Extract specific error conditions from AWS error messages
25+
details = {
26+
"model_id": model_id,
27+
"error_type": "invalid_model_error"
28+
}
29+
30+
if "on-demand throughput isn't supported" in error:
31+
details["error_subtype"] = "throughput_configuration_error"
32+
message = (f"Model {model_id} requires an inference profile configuration. "
33+
"Please use a model with on-demand throughput support or configure an inference profile.")
34+
elif "model identifier is invalid" in error:
35+
details["error_subtype"] = "invalid_identifier_error"
36+
message = f"Model {model_id} is not a valid model identifier."
37+
else:
38+
details["error_subtype"] = "general_model_error"
39+
message = f"Invalid model configuration for {model_id}: {error}"
40+
41+
super().__init__(
42+
message=message,
43+
status_code=404,
44+
details=details
45+
)
46+
47+
class JSONParsingError(APIError):
48+
"""Specific exception for JSON parsing failures
49+
50+
Status code 422 (Unprocessable Entity) is used because:
51+
- The request syntax is valid (unlike 400 Bad Request)
52+
- The server understands the content type (unlike 415 Unsupported Media Type)
53+
- But the server cannot process the contained instructions/content
54+
"""
55+
def __init__(self, message: str, raw_text: str, parsing_context: str = ""):
1256
super().__init__(
13-
message=f"Invalid model identifier: {model_id}",
14-
status_code=400
57+
message=f"JSON parsing error: {message}",
58+
status_code=422, # Unprocessable Entity
59+
details={
60+
"parsing_context": parsing_context,
61+
"raw_text_sample": raw_text[:500] if raw_text else "No text provided",
62+
"error_type": "json_parsing_error"
63+
}
1564
)

0 commit comments

Comments
 (0)