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"

Cena {i}

" html_content += f"

{sc['text']}

" html_content += f"cena {i}" html_content += "
" return html_content import gradio as gr with gr.Blocks() as demo: gr.Markdown("# IAFlix: Exemplo em Gradio\nInsira a chave Groq, gere sugestões e expanda em cenas + imagens.") with gr.Row(): groq_key_box = gr.Textbox(label="Sua Groq API Key", type="password", value="") btn_save_key = gr.Button("Salvar Chave") key_status = gr.Textbox(label="Status da Chave", interactive=False) with gr.Accordion("Passo 1: Gerar sugestões", open=True): style_dd = gr.Dropdown( label="Estilo/Gênero", choices=["Fantasia", "Ficção Científica", "Surreal", "Romance", "Tema Personalizado"], value="Fantasia" ) custom_theme_box = gr.Textbox(label="Tema Personalizado (se selecionado)") btn_suggs = gr.Button("Gerar Sugestões") suggestions_output = gr.State() # armazena array de sugestões suggestions_display = gr.Radio( label="Sugestões Geradas", choices=[], # será populado dinâmicamente interactive=True ) with gr.Accordion("Passo 2: Expandir e gerar cenas", open=False): btn_run_story = gr.Button("Iniciar História da Sugestão Selecionada") story_html = gr.HTML(label="Resultado das Cenas") # Lógica de Botões btn_save_key.click(fn=ui_set_key, inputs=[groq_key_box], outputs=[key_status]) btn_suggs.click(fn=ui_generate_suggs, inputs=[style_dd, custom_theme_box], outputs=[suggestions_output]) # array de strings # Quando suggestions_output mudar, atualizamos o Radio suggestions_output.change( fn=lambda arr: gr.update(choices=arr), inputs=[suggestions_output], outputs=[suggestions_display] ) # Ao clicar em "Iniciar História", chamamos run_story com a ideia selecionada btn_run_story.click(fn=ui_run_story, inputs=[suggestions_display], outputs=[story_html]) demo.launch(server_name="0.0.0.0", server_port=7860)