from PIL import Image from io import BytesIO import base64 import os import re from groq import Groq import gradio as gr # Read key from Hugging Face secrets or default fallback api_key = os.getenv("GROQ_API_KEY", "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") client = Groq(api_key=api_key) def encode_image(image_input): """Encode image (path, dict, or base64 data URI) to base64 string.""" try: # If Gradio passes a FileData dictionary if isinstance(image_input, dict): image_input = image_input.get("path", "") # If already a base64 Data URI string if isinstance(image_input, str) and image_input.startswith("data:image"): return image_input.split(",")[1] # Otherwise treat as a local file path and open via PIL image = Image.open(image_input).convert("RGB") base_height = 512 h_percent = (base_height / float(image.size[1])) w_size = int((float(image.size[0]) * float(h_percent))) image = image.resize((w_size, base_height), Image.LANCZOS) buffered = BytesIO() image.save(buffered, format="JPEG") return base64.b64encode(buffered.getvalue()).decode("utf-8") except Exception as e: print(f"Error encoding image: {e}") return None def feifeichat(image): try: if image is None: return "Please upload a photo" base64_image = encode_image(image) if not base64_image: return "Error processing image" messages = [ { "role": "user", "content": [ { "type": "text", "text": "Analyze the image and return strictly valid JSON format with keys 'title', 'description', 'meta_title' (max 60 chars), 'meta_description' (max 155 chars), 'tags' (array of 5-8 strings), 'style_breakdown' (object with keys: aesthetic, top, bottom, legwear, accessories), and 'faqs' (array of two objects with 'q' and 'a'). Follow these strict copywriting guidelines: 1. Description must be an elegant, descriptive paragraph (3-4 sentences) written like an alternative fashion lookbook. 2. Focus on physical aesthetics: mention terms like 'slender body', 'petite frame', 'youthful appeal', 'cute vibe', and 'sexy style' naturally. 3. Avoid literal camera actions: DO NOT say 'taking a selfie', 'mirror picture', or 'holding a phone'. Describe the pose as casual, relaxed, or playful. 4. Tags must be individual aesthetic search terms (e.g., ['egirl-aesthetic', 'thigh-highs', 'white-tights', 'alternative-fashion'])." }, { "type": "image_url", "image_url": { "url": f"data:image/jpeg;base64,{base64_image}" } } ] } ] response = client.chat.completions.create( model="qwen/qwen3.6-27b", messages=messages, response_format={"type": "json_object"}, temperature=0.7, stream=False ) raw_content = response.choices[0].message.content or "" # Strip Qwen reasoning/thinking blocks (...) cleaned = re.sub(r'.*?', '', raw_content, flags=re.DOTALL).strip() # Strip markdown fences if present cleaned = re.sub(r'^```(?:json)?\s*', '', cleaned) cleaned = re.sub(r'\s*```$', '', cleaned) return cleaned.strip() except Exception as e: print(f"Error: {e}") return f"An error occurred while processing your request: {e}" with gr.Blocks() as demo: gr.Markdown("Image To Flux Prompt") with gr.Tab(label="Image To Flux Prompt"): input_img = gr.Image(label="Input Picture", height=320, type="filepath") output_text = gr.Textbox(label="Flux Prompt") submit_btn = gr.Button(value="Submit") submit_btn.click( fn=feifeichat, inputs=input_img, outputs=output_text, api_name="feifeichat" ) # Disabling SSR mode resolves SvelteKit 405 Method Not Allowed errors on Gradio 5 demo.launch(ssr_mode=False)