File size: 4,805 Bytes
8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 e85027d 8ba64a4 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
from io import BytesIO
import requests
from fastapi import HTTPException
from PIL import Image
from app.config import get_settings
from app.core.errors import BadRequestError, VendorError
from app.schemas.requests import ExtractionRequest
from app.schemas.responses import APIResponse
from app.services.factory import AIServiceFactory
from app.utils.logger import exception_to_str, setup_logger
logger = setup_logger(__name__)
settings = get_settings()
async def handle_extract(request: ExtractionRequest):
request.max_attempts = max(request.max_attempts, 1)
request.max_attempts = min(request.max_attempts, 5)
for attempt in range(1, request.max_attempts + 1):
try:
logger.info(f"Attempt: {attempt}")
if request.ai_model in settings.OPENAI_MODELS:
ai_vendor = "openai"
elif request.ai_model in settings.ANTHROPIC_MODELS:
ai_vendor = "anthropic"
else:
raise ValueError(
f"Invalid AI model: {request.ai_model}, only support {settings.SUPPORTED_MODELS}"
)
service = AIServiceFactory.get_service(ai_vendor)
# pil_images = []
pil_images = None # temporarily removed to save cost
for url in request.img_urls:
try:
# response = requests.get(url)
# response.raise_for_status()
# image = Image.open(BytesIO(response.content))
# pil_images.append(image)
pass
except Exception as e:
# logger.error(f"Failed to download or process image from {url}: {exception_to_str(e)}")
raise HTTPException(
status_code=400,
detail=f"Failed to process image from {url}",
headers={"attempt": attempt},
)
json_attributes = await service.extract_attributes_with_validation(
request.attributes,
request.ai_model,
request.img_urls,
request.product_taxonomy,
request.product_data,
pil_images=pil_images,
)
break
except BadRequestError as e:
logger.error(
f"Bad request error: {exception_to_str(e)}",
)
raise HTTPException(
status_code=400,
detail=exception_to_str(e),
headers={"attempt": attempt},
)
except ValueError as e:
logger.error(f"Value error: {exception_to_str(e)}")
raise HTTPException(
status_code=400,
detail=exception_to_str(e),
headers={"attempt": attempt},
)
except VendorError as e:
logger.error(f"Vendor error: {exception_to_str(e)}")
if attempt == request.max_attempts:
raise HTTPException(
status_code=500,
detail=exception_to_str(e),
headers={"attempt": attempt},
)
else:
if request.ai_model in settings.ANTHROPIC_MODELS:
request.ai_model = settings.OPENAI_MODELS[
0
] # switch to OpenAI, and try again if max_attempts not reached
logger.info(
f"Switching from anthropic to {request.ai_model} for attempt {attempt + 1}"
)
elif request.ai_model in settings.OPENAI_MODELS:
request.ai_model = settings.ANTHROPIC_MODELS[
0
] # switch to anthropic, and try again if max_attempts not reached
logger.info(
f"Switching from OpenAI to {request.ai_model} for attempt {attempt + 1}"
)
except HTTPException as e:
logger.error(f"HTTP exception: {exception_to_str(e)}")
raise e
except Exception as e:
logger.error("Exception: ", exception_to_str(e))
if (
"overload" in str(e).lower()
and request.ai_model in settings.ANTHROPIC_MODELS
):
request.ai_model = settings.OPENAI_MODELS[
0
] # switch to OpenAI, and try again if max_attempts not reached
if attempt == request.max_attempts:
raise HTTPException(
status_code=500,
detail="Internal server error",
headers={"attempt": attempt},
)
return json_attributes, attempt
|