import gradio as gr import requests import re # -------------------------------------------- # Variáveis globais (poderíamos usar State) # -------------------------------------------- groq_api_key = "" # será preenchido ao usuário inserir groq_model = "llama3-groq-70b-8192-tool-use-preview" huggingface_ti_endpoint = "https://huggingface.co/spaces/USER/YOUR_TEXT_TO_IMAGE/queue/predict" # ^ Ajuste conforme seu Space de Text-to-Image. # -------------------------------------------- # Funções auxiliares # -------------------------------------------- def set_groq_key(key): """ Salva a chave do Groq informada pelo usuário. """ global groq_api_key groq_api_key = key.strip() return f"Chave Groq salva: {groq_api_key[:6]}******" def ask_groq(prompt): """ Faz chamada à API Groq, retornando string com a resposta. Necessita de groq_api_key global. """ if not groq_api_key: return "ERRO: sem chave Groq. Insira primeiro." # Monta body: payload = { "messages": [{"role": "user", "content": prompt}], "model": groq_model, "temperature": 1, "max_tokens": 1024, "top_p": 1, "stream": False, } headers = { "Content-Type": "application/json", "Authorization": f"Bearer {groq_api_key}" } try: resp = requests.post("https://api.groq.com/openai/v1/chat/completions", json=payload, headers=headers, timeout=60) resp.raise_for_status() data = resp.json() content = data.get("choices",[{}])[0].get("message",{}).get("content","") return content except Exception as e: return f"Erro ao chamar Groq: {e}" def generate_suggestions(style, custom_theme): """ Gera 3 sugestões de histórias no estilo/style, usando Groq. """ if style == "Tema Personalizado": if not custom_theme.strip(): return ["Digite algo em 'Tema Personalizado'..."] tema = custom_theme else: tema = style prompt = f""" Gere 3 ideias de histórias no gênero/tema: '{tema}'. Responda no formato: 1) ... 2) ... 3) ... """ resp = ask_groq(prompt) # Faz parse simples para separar 3 linhas # Caso a Groq retorne outro formato, ajuste aqui lines = re.split(r"\d\)|\d\.", resp) ideas = [] for line in lines: line = line.strip() if len(line) > 5: ideas.append(line) if not ideas: ideas = [resp] # fallback: mostra a string toda return ideas def call_text_to_image_api(description): """ Chama seu endpoint Hugging Face (exemplo 'queue/predict') para gerar imagem com base no `description`. Ajuste conforme a doc do seu Space. """ try: # Exemplo de payload que alguns Spaces usam: payload = {"data": [description]} r = requests.post(huggingface_ti_endpoint, json=payload, timeout=120) r.raise_for_status() data = r.json() # Exemplo: supor que a imagem retorne em data["data"][0] (base64) # Precisaria ver doc exata do Space base64_img = data["data"][0] return f"data:image/png;base64,{base64_img}" except Exception as e: return None def expand_story(idea): """ Gera uma história com várias cenas (CENA 1:, CENA 2:, etc.) dada uma ideia curta. """ if not idea or len(idea) < 5: return "Nenhuma ideia selecionada." prompt = f""" Crie uma história detalhada a partir da seguinte ideia: '{idea}' Separe cada cena como 'CENA X:' e descreva cada cena em poucas frases. """ story_text = ask_groq(prompt) # Quebrar a string pelas cenas splitted = re.split(r"(CENA\s*\d+:)", story_text, flags=re.IGNORECASE) # splitted vira algo como ["", "CENA 1:", "texto da cena1", "CENA 2:", "texto da cena2", ...] # Precisamos remontar pares scenes = [] buffer_title = "" buffer_text = "" for chunk in splitted: chunk = chunk.strip() if re.match(r"(?i)cena\s*\d+:", chunk): # se já houver buffer_text e buffer_title, finaliza if buffer_title and buffer_text: scenes.append(f"{buffer_title}\n{buffer_text}") buffer_title = chunk buffer_text = "" else: # é corpo da cena if buffer_text: buffer_text += " " + chunk else: buffer_text = chunk # Adiciona o último if buffer_title and buffer_text: scenes.append(f"{buffer_title}\n{buffer_text}") if not scenes: # fallback: sem 'CENA x:' => 1 bloco só scenes = [story_text] return scenes def run_story(idea): """ Gera as cenas da história e para cada cena gera a imagem e retorna tudo. Retorna uma lista de dicts: [{image, text}, ...]. """ scenes = expand_story(idea) output = [] for scene in scenes: # Chama text2img img_data = call_text_to_image_api(scene) if not img_data: # se falhar, placeholder img_data = "https://via.placeholder.com/600x400?text=Falha+Gerar+Imagem" output.append({"text": scene, "image": img_data}) return output # -------------------------------------------- # Montando interface com Gradio # -------------------------------------------- def ui_set_key(key): return set_groq_key(key) def ui_generate_suggs(style, custom_theme): return generate_suggestions(style, custom_theme) def ui_run_story(idea): # Gera as cenas e retorna a lista all_scenes = run_story(idea) # Queremos exibir "carousel"? Ou gerar uma lista? # No Gradio, podemos retornar algo como (list of images, ou HTML). # Exemplo simples: retornamos uma tupla (primeira imagem, e todo o texto). # Mas se quisermos exibir cada cena isoladamente, podemos usar "Gallery" etc. # Para simplicidade, vamos juntar tudo em HTML: html_content = "" for i, sc in enumerate(all_scenes, start=1): html_content += f"
{sc['text']}
" html_content += f"