thanhnt-cf's picture
bring changes to demo app
e85027d
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