thanhnt-cf's picture
bring changes to demo app
e85027d
Raw
History Blame Contribute Delete
4.81 kB
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