"""Main entrypoint for the app.""" import base64 from io import BytesIO import os from numpy import ndarray import requests from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from urllib.parse import urlparse import gradio as gr from style_master.LLMRecommender import LLMRecommender, make_request_with_retry from PIL import Image static_dir = os.environ.get("STATIC_FILES_PATH") or "data/Assets" def ndarray_to_base64(image): # Convert ndarray image to PIL image pil_image = Image.fromarray(image) # Create a BytesIO object buffered = BytesIO() # Save PIL image to buffer pil_image.save(buffered, format="PNG") # Get image bytes img_bytes = buffered.getvalue() # Encode bytes to base64 and decode to string img_base64 = base64.b64encode(img_bytes).decode() return img_base64 # Function to encode the image def encode_image(image_path_or_url_or_ndarray): if isinstance(image_path_or_url_or_ndarray, ndarray): image_base64 = ndarray_to_base64(image_path_or_url_or_ndarray) elif image_path_or_url_or_ndarray.startswith("http"): response = requests.get(image_path_or_url_or_ndarray) buffered = BytesIO(response.content) image_base64 = base64.b64encode(buffered.getvalue()).decode("utf-8") else: with open(image_path_or_url_or_ndarray, "rb") as image_file: image_base64 = base64.b64encode(image_file.read()).decode("utf-8") return image_base64 mock_ootd_api_responses = { "sessions": { "profile": { "id": "123", "name": "Sam", } }, "try-ons": {"try_on_images": []}, } def call_ootd_api(name, data): print(f"Calling {name} with data: {data if name != 'sessions' else '***'}") return mock_ootd_api_responses.get(name, {}) # url = f"{ootd_server_url}/{name}" # headers = {"Content-Type": "application/json"} # response = make_request_with_retry( # url, headers, data, suppress_data=name == "sessions" # ) # response_json = response.json() # return response_json llmr = LLMRecommender() def call_try_on_api(garment_ids): data = {"session_id": f"{profile['id']}", "garment_ids": garment_ids} response = call_ootd_api("try-ons", data) # if len(garment_ids) == 2: # products = [llmr.get_garment(id) for id in garment_ids] # if products[0]["category"] != products[1]["category"]: # data2 = { # "session_id": f"{profile['id']}", # "model_filename": response["try_on_images"][0]["filename"], # "garment_ids": [garment_ids[1]], # } # response2 = call_ootd_api("try-ons", data2) # response["try_on_images"] += response2["try_on_images"] # response["try_on_images"][-1]["extra_garment_id"] = garment_ids[0] return response def login(image_file_or_ndarray): print("login:", type(image_file_or_ndarray)) data = {"encodedData": encode_image(image_file_or_ndarray)} response = call_ootd_api("sessions", data) profile = response["profile"] print(response) profile["gender"] = llmr.login(profile["name"], data["encodedData"]) try_on_images_folder = f"{static_dir}/try-ons/{profile['id']}" os.makedirs(try_on_images_folder, exist_ok=True) return profile, try_on_images_folder share_gradio_app = os.environ.get("SHARE_GRADIO_APP") == "true" ootd_server_url = os.environ.get("OOTD_SERVER_URL") def predict(message, history): print("predict:", message) response = llmr.invoke(message) print(response) if response["intent"] in ["unknown", "checkout"]: partial_message = f"{response['message']}" elif response["intent"] == "recommendation": partial_message = f"Here are {len(response['products'])} recommendation{'s' if len(response['products']) > 1 else ''} for you:" elif response["intent"] == "try-on": partial_message = f"For {len(response['products'])} garment{'s' if len(response['products']) > 1 else ''} you've selected:" elif response["intent"] == "add-to-cart": partial_message = f"Added {len(response['products'])} item{'s' if len(response['products']) > 1 else ''} into your cart:" elif response["intent"] == "view-cart": partial_message = f"There {'are' if len(response['products']) > 1 else 'is'} {len(response['products'])} item{'s' if len(response['products']) > 1 else ''} in your cart{':' if len(response['products']) > 0 else '.'}" else: partial_message = f"{response}" if "products" in response and response["products"]: partial_message += "\n\n" for id in response["products"]: product = llmr.get_garment(id) url = product["image"] parsed_url = urlparse(url) title = f"#{product['id']} {product['name']}: ${product['price']}" partial_message += f"1. [{title}]({url})\n" partial_message += f"\n" if response["intent"] == "try-on": response = call_try_on_api(response["products"]) print(response) partial_message += f"\n\nwe have created {len(response['try_on_images'])} try-on image{'s:' if len(response['try_on_images']) > 1 else '.'}" partial_message += "\n\n" for try_on_image in response["try_on_images"]: url = try_on_image["url"] file_name = try_on_image["filename"] file_path = f"{try_on_images_folder}/{file_name}" response = make_request_with_retry(url) with open(file_path, "wb") as f: f.write(response.content) title = f"{profile['name']} wearing " extra_garment_id = try_on_image.get("extra_garment_id") if extra_garment_id: extra_product = llmr.get_garment(extra_garment_id) title += f"{extra_product['name']} and " id = try_on_image["garment_id"] product = llmr.get_garment(id) title += f"{product['name']}" partial_message += f"1. [{title}]({url})\n" parsed_url = urlparse(url) partial_message += f"\n" yield partial_message app = FastAPI() model = os.environ.get("OPENAI_MODEL_NAME") href = "https://platform.openai.com/docs/models" title = "Style Master" questions_file_path = os.environ.get("QUESTIONS_FILE_PATH") # Open the file for reading with open(questions_file_path, "r") as file: examples = file.readlines() examples = [example.strip() for example in examples] description = f"""\
Powered by: {model}