Spaces:
Sleeping
Sleeping
Update app.py
Browse filesnova lista de estilos criativos (Studio Ghibli, Pixar, etc. e tradutor de erros da API para que as mensagens de falha (como 402, 503, etc.
app.py
CHANGED
|
@@ -84,24 +84,26 @@ ESTILOS_DISPONIVEIS = [
|
|
| 84 |
"Tutorial/Passo a Passo",
|
| 85 |
]
|
| 86 |
|
| 87 |
-
# NOVO: Dicionário de estilos de imagem (
|
| 88 |
-
|
| 89 |
-
"Nenhum (Automático)": "standard photography, high quality",
|
| 90 |
-
"
|
| 91 |
-
"
|
| 92 |
-
"
|
| 93 |
-
"
|
| 94 |
-
"
|
| 95 |
-
"
|
| 96 |
-
"
|
| 97 |
-
"
|
| 98 |
-
"
|
|
|
|
|
|
|
| 99 |
"Arte Digital (Cinemático)": "cinematic, dramatic lighting, fantasy art, concept art",
|
| 100 |
"Arte Digital (Neon)": "neonoir, cyberpunk, glowing lights, futuristic city",
|
| 101 |
"Minimalista": "minimalist, clean background, simple, elegant",
|
| 102 |
-
"Fotografia Vintage": "vintage photography, retro style, film grain, analog"
|
| 103 |
}
|
| 104 |
|
|
|
|
| 105 |
# NOVO: Dicionário de filtros de imagem
|
| 106 |
FILTROS_IMAGEM = {
|
| 107 |
"Nenhum": "",
|
|
@@ -114,6 +116,7 @@ FILTROS_IMAGEM = {
|
|
| 114 |
|
| 115 |
|
| 116 |
# CORRIGIDO: O dicionário do LinkedIn estava quebrado
|
|
|
|
| 117 |
FORMATO_CONFIGS = {
|
| 118 |
"Instagram (Post)": {"tamanho": "100-150 palavras", "estrutura": "gancho inicial + desenvolvimento + call-to-action", "tom_adicional": "próximo, empático e motivador", "max_tokens": 350, "limite_palavras_ia": "150 palavras", "hashtags": "Incluir 4-5 hashtags relevantes no final. Incluir no máximo 3 emojis relevantes no texto."},
|
| 119 |
"Twitter/X (Curto)": {"tamanho": "Até 280 caracteres", "estrutura": "frase de impacto + link/hashtag", "tom_adicional": "direto e conciso, ideal para tweets", "max_tokens": 150, "limite_palavras_ia": "280 caracteres", "hashtags": "Incluir no máximo 2 hashtags."},
|
|
@@ -284,7 +287,7 @@ def copiar_feedback(texto):
|
|
| 284 |
return criar_alerta('warning', '⚠️ Nada para copiar')
|
| 285 |
|
| 286 |
def limpar_tudo():
|
| 287 |
-
# Retorna
|
| 288 |
return (
|
| 289 |
"", # texto_output
|
| 290 |
None, # imagem_output
|
|
@@ -292,6 +295,7 @@ def limpar_tudo():
|
|
| 292 |
0, # palavras_output
|
| 293 |
0, # caracteres_output
|
| 294 |
0, # hashtags_output
|
|
|
|
| 295 |
"Nenhum (Automático)", # estilo_img_input
|
| 296 |
"Balanceada", # qualidade_img_input
|
| 297 |
"Nenhum", # filtro_img_input
|
|
@@ -305,19 +309,47 @@ def recarregar_e_formatar_historico():
|
|
| 305 |
# através da chamada a 'atualizar_historico'
|
| 306 |
return _formatar_historico_para_df(post_history)
|
| 307 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 308 |
|
| 309 |
# ============================================
|
| 310 |
# FUNÇÕES DE GERAÇÃO (POSTS)
|
| 311 |
# ============================================
|
| 312 |
|
| 313 |
-
def gerar_texto(tema, nicho, estilo):
|
| 314 |
"""
|
| 315 |
Gera texto usando API do Hugging Face com base no formato escolhido.
|
| 316 |
-
NOTA: 'formato' foi hardcoded para "Instagram (Post)" para
|
| 317 |
-
suportar a nova função gerar_post_interface.
|
| 318 |
"""
|
| 319 |
|
| 320 |
-
|
|
|
|
| 321 |
|
| 322 |
if not HUGGINGFACE_API_KEY:
|
| 323 |
return "❌ Erro de Configuração: API Key não está definida."
|
|
@@ -363,10 +395,12 @@ Escreva apenas o conteúdo, sem introduções ou explicações."""
|
|
| 363 |
else:
|
| 364 |
return f"❌ Erro na resposta da API: Resposta vazia ou inesperada.\n{resultado}"
|
| 365 |
else:
|
| 366 |
-
|
|
|
|
| 367 |
|
| 368 |
except Exception as e:
|
| 369 |
-
|
|
|
|
| 370 |
|
| 371 |
def traduzir_texto(texto_pt):
|
| 372 |
"""Traduz texto de Português (PT) para Inglês (EN) usando API do Hugging Face.
|
|
@@ -395,6 +429,7 @@ def traduzir_texto(texto_pt):
|
|
| 395 |
return texto_pt # Fallback
|
| 396 |
|
| 397 |
except Exception as e:
|
|
|
|
| 398 |
return texto_pt # Fallback
|
| 399 |
|
| 400 |
# ============================================
|
|
@@ -405,8 +440,8 @@ def otimizar_prompt_imagem(descricao_pt, estilo_escolhido, filtro_escolhido):
|
|
| 405 |
"""Combina as escolhas do usuário em um prompt otimizado (em Português)."""
|
| 406 |
|
| 407 |
# 1. Obter estilo
|
| 408 |
-
#
|
| 409 |
-
estilo =
|
| 410 |
|
| 411 |
# 2. Obter filtro
|
| 412 |
filtro = FILTROS_IMAGEM.get(filtro_escolhido, FILTROS_IMAGEM["Nenhum"])
|
|
@@ -486,7 +521,8 @@ def gerar_imagem_robusta(descricao_pt, estilo_escolhido, qualidade, filtro_escol
|
|
| 486 |
continue
|
| 487 |
else:
|
| 488 |
# Último modelo falhou, retornar erro
|
| 489 |
-
|
|
|
|
| 490 |
return (None, mensagem)
|
| 491 |
|
| 492 |
# Se chegou aqui, algo deu errado
|
|
@@ -537,10 +573,12 @@ def responder_chat(message, chat_history):
|
|
| 537 |
else:
|
| 538 |
return f"❌ Erro na resposta da API: Resposta vazia ou inesperada.\n{resultado}"
|
| 539 |
else:
|
| 540 |
-
|
|
|
|
| 541 |
|
| 542 |
except Exception as e:
|
| 543 |
-
|
|
|
|
| 544 |
|
| 545 |
# ============================================
|
| 546 |
# NOVAS FUNÇÕES DE DOWNLOAD
|
|
@@ -647,7 +685,8 @@ def preparar_download(texto, imagem_pil, tema):
|
|
| 647 |
# FUNÇÃO PRINCIPAL COM PROGRESSO (ATUALIZADA)
|
| 648 |
# ============================================
|
| 649 |
|
| 650 |
-
def gerar_post_interface(tema, nicho, estilo,
|
|
|
|
| 651 |
estilo_img_input, qualidade_img_input, filtro_img_input,
|
| 652 |
progress=gr.Progress()):
|
| 653 |
"""Gera post completo com feedback e lógica de imagem avançada"""
|
|
@@ -670,10 +709,11 @@ def gerar_post_interface(tema, nicho, estilo, descricao_imagem, gerar_img,
|
|
| 670 |
|
| 671 |
# Gerando texto
|
| 672 |
progress(0.3, desc="🤖 Gerando texto (Llama 3.1)...")
|
| 673 |
-
|
|
|
|
| 674 |
|
| 675 |
-
if texto.startswith("❌")
|
| 676 |
-
status_final = criar_alerta('error', f'
|
| 677 |
return (texto, None, status_final, 0, 0, 0)
|
| 678 |
|
| 679 |
progress(0.5, desc="✅ Texto pronto!")
|
|
@@ -699,6 +739,7 @@ def gerar_post_interface(tema, nicho, estilo, descricao_imagem, gerar_img,
|
|
| 699 |
status_final = criar_alerta('success', f'🎉 Post completo gerado! ({status_imagem})')
|
| 700 |
else:
|
| 701 |
# status_imagem conterá a mensagem de erro (ex: "Todos os modelos falharam")
|
|
|
|
| 702 |
status_final = criar_alerta('warning', f'✅ Texto OK, mas imagem falhou: {status_imagem}')
|
| 703 |
else:
|
| 704 |
progress(0.7, desc="⏭️ Pulando geração de imagem...")
|
|
@@ -720,9 +761,8 @@ def gerar_post_interface(tema, nicho, estilo, descricao_imagem, gerar_img,
|
|
| 720 |
# INÍCIO DA CORREÇÃO: Re-adicionando salvamento no histórico
|
| 721 |
# ==================================================
|
| 722 |
|
| 723 |
-
#
|
| 724 |
-
|
| 725 |
-
formato_usado = "Instagram (Post)"
|
| 726 |
|
| 727 |
# Usar a variável 'status' que já foi definida
|
| 728 |
status_final_historico = status_final # Usar o status HTML (o Firestore lida bem com strings)
|
|
@@ -735,7 +775,7 @@ def gerar_post_interface(tema, nicho, estilo, descricao_imagem, gerar_img,
|
|
| 735 |
"Tema": tema,
|
| 736 |
"Nicho": nicho,
|
| 737 |
"Estilo": estilo,
|
| 738 |
-
"Formato": formato_usado,
|
| 739 |
"Texto (Preview)": texto_preview,
|
| 740 |
"Status": status_imagem or "Texto Gerado", # Salva o status da imagem (ex: "Gerada com FLUX")
|
| 741 |
}
|
|
@@ -796,13 +836,13 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
|
| 796 |
placeholder="Ex: Transforme seu corpo, transforme sua vida"
|
| 797 |
)
|
| 798 |
|
| 799 |
-
#
|
| 800 |
formato_input = gr.Radio(
|
| 801 |
choices=list(FORMATO_CONFIGS.keys()),
|
| 802 |
-
label="Escolha o Formato de Saída
|
| 803 |
value=list(FORMATO_CONFIGS.keys())[0],
|
| 804 |
-
interactive=
|
| 805 |
-
visible=
|
| 806 |
)
|
| 807 |
|
| 808 |
gr.Markdown("### 🎨 2. Configurações da Imagem (Opcional)")
|
|
@@ -819,9 +859,10 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
|
| 819 |
visible=False
|
| 820 |
)
|
| 821 |
|
|
|
|
| 822 |
estilo_img_input = gr.Dropdown(
|
| 823 |
label="Estilo da Imagem",
|
| 824 |
-
choices=list(
|
| 825 |
value="Nenhum (Automático)",
|
| 826 |
visible=False,
|
| 827 |
interactive=True
|
|
@@ -909,14 +950,15 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
|
| 909 |
|
| 910 |
gr.Markdown("### 💡 Experimente estes exemplos:")
|
| 911 |
|
|
|
|
| 912 |
gr.Examples(
|
| 913 |
examples=[
|
| 914 |
-
[NICHOS_DISPONIVEIS[2], ESTILOS_DISPONIVEIS[0], "Frases marcantes de pessoas importantes"],
|
| 915 |
-
[NICHOS_DISPONIVEIS[1], ESTILOS_DISPONIVEIS[2], "Receita rápida de smoothie verde"],
|
| 916 |
-
[NICHOS_DISPONIVEIS[5], ESTILOS_DISPONIVEIS[3], "O futuro da IA em 2025"],
|
| 917 |
-
[NICHOS_DISPONIVEIS[4], ESTILOS_DISPONIVEIS[1], "Melhores destinos para lua de mel na Europa"],
|
| 918 |
],
|
| 919 |
-
inputs=[nicho_input, estilo_input, tema_input],
|
| 920 |
outputs=[texto_output, imagem_output, status_output]
|
| 921 |
)
|
| 922 |
|
|
@@ -930,6 +972,7 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
|
| 930 |
fn=gerar_post_interface,
|
| 931 |
inputs=[
|
| 932 |
tema_input, nicho_input, estilo_input,
|
|
|
|
| 933 |
descricao_img_input, gerar_img_checkbox,
|
| 934 |
estilo_img_input, qualidade_img_input, filtro_img_input # Novos inputs
|
| 935 |
],
|
|
@@ -954,6 +997,7 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
|
| 954 |
outputs=[
|
| 955 |
texto_output, imagem_output, status_output,
|
| 956 |
palavras_output, caracteres_output, hashtags_output,
|
|
|
|
| 957 |
estilo_img_input, qualidade_img_input, filtro_img_input, # Limpa novos inputs
|
| 958 |
download_output # Limpa o arquivo de download
|
| 959 |
]
|
|
@@ -992,7 +1036,11 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
|
| 992 |
],
|
| 993 |
chatbot=chatbot_para_interface, # Passando o componente chatbot customizado
|
| 994 |
textbox=gr.Textbox(placeholder="Digite sua mensagem aqui...", scale=7),
|
| 995 |
-
submit_btn="Enviar"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 996 |
)
|
| 997 |
|
| 998 |
# ABA 2: Histórico (Exibe o Dataframe)
|
|
@@ -1036,6 +1084,7 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
|
| 1036 |
gr.Markdown("---")
|
| 1037 |
gr.Markdown("#### Funcionalidades:")
|
| 1038 |
gr.Markdown("- **Gerador de Posts:** Cria posts completos com texto e imagem.")
|
|
|
|
| 1039 |
gr.Markdown("- **Controles Avançados:** Permite seleção de Estilo, Qualidade e Filtros para a imagem.")
|
| 1040 |
gr.Markdown("- **Download de Post:** Combina texto e imagem em um único arquivo PNG para download.")
|
| 1041 |
gr.Markdown("- **Chatbot Assistente:** Converse com a IA para ideias e perguntas rápidas.")
|
|
@@ -1059,7 +1108,7 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
|
| 1059 |
- **PIL (Python Imaging Library) (para composição de posts)**
|
| 1060 |
|
| 1061 |
**Como funciona:**
|
| 1062 |
-
1. **Gerar Post:** Você define o tema, nicho e
|
| 1063 |
2. **Imagem (Opcional):** Você ativa, descreve a imagem e seleciona *Estilo*, *Qualidade* e *Filtro*.
|
| 1064 |
3. O sistema otimiza o prompt, traduz para inglês e usa o sistema de *fallback* de modelos (baseado na *Qualidade*) para gerar a imagem.
|
| 1065 |
4. **Download:** Após a geração, você pode clicar em "Baixar Post Completo" para salvar um PNG com a imagem e o texto formatado.
|
|
|
|
| 84 |
"Tutorial/Passo a Passo",
|
| 85 |
]
|
| 86 |
|
| 87 |
+
# NOVO: Dicionário de estilos de imagem (baseado na Solicitação 2)
|
| 88 |
+
ESTILOS_DE_IMAGEM = {
|
| 89 |
+
"Nenhum (Automático)": "standard photography, high quality, 4k",
|
| 90 |
+
"Fotografia Vintage": "vintage photography, retro style, film grain, analog",
|
| 91 |
+
"Quente (Vintage)": "warm tones, vintage filter, retro, analog film look",
|
| 92 |
+
"Frio (Moderno)": "cool tones, modern aesthetic, clean, desaturated blues",
|
| 93 |
+
"Estilo Studio Ghibli": "Studio Ghibli style, poetic, soft, pastel colors, magical atmosphere, nostalgic portrait, fantasy scene",
|
| 94 |
+
"Estilo Simpsons": "Simpsons style, iconic visual, strong black outlines, solid colors, humorous daily scene",
|
| 95 |
+
"Estilo Pixar": "Pixar style, 3D digital animation, striking expressions, friendly characters",
|
| 96 |
+
"Estilo Tim Burton": "Tim Burton style, dark aesthetic, thin lines, gothic environment, mysterious characters",
|
| 97 |
+
"Estilo Attack on Titan": "Attack on Titan anime style, intense and dark lines, action scene",
|
| 98 |
+
"Estilo RPG Clássico": "Classic RPG style, epic aesthetic, fantasy book cover",
|
| 99 |
+
"Estilo 8-bit e 16-bit": "8-bit and 16-bit retro visual, nostalgic games",
|
| 100 |
+
"Estilo Animação Anos 2000": "2000s animation style (Samurai Jack inspired), modern and stylized",
|
| 101 |
"Arte Digital (Cinemático)": "cinematic, dramatic lighting, fantasy art, concept art",
|
| 102 |
"Arte Digital (Neon)": "neonoir, cyberpunk, glowing lights, futuristic city",
|
| 103 |
"Minimalista": "minimalist, clean background, simple, elegant",
|
|
|
|
| 104 |
}
|
| 105 |
|
| 106 |
+
|
| 107 |
# NOVO: Dicionário de filtros de imagem
|
| 108 |
FILTROS_IMAGEM = {
|
| 109 |
"Nenhum": "",
|
|
|
|
| 116 |
|
| 117 |
|
| 118 |
# CORRIGIDO: O dicionário do LinkedIn estava quebrado
|
| 119 |
+
# ATUALIZADO: Funcionalidade de formato reativada (Solicitação 1)
|
| 120 |
FORMATO_CONFIGS = {
|
| 121 |
"Instagram (Post)": {"tamanho": "100-150 palavras", "estrutura": "gancho inicial + desenvolvimento + call-to-action", "tom_adicional": "próximo, empático e motivador", "max_tokens": 350, "limite_palavras_ia": "150 palavras", "hashtags": "Incluir 4-5 hashtags relevantes no final. Incluir no máximo 3 emojis relevantes no texto."},
|
| 122 |
"Twitter/X (Curto)": {"tamanho": "Até 280 caracteres", "estrutura": "frase de impacto + link/hashtag", "tom_adicional": "direto e conciso, ideal para tweets", "max_tokens": 150, "limite_palavras_ia": "280 caracteres", "hashtags": "Incluir no máximo 2 hashtags."},
|
|
|
|
| 287 |
return criar_alerta('warning', '⚠️ Nada para copiar')
|
| 288 |
|
| 289 |
def limpar_tudo():
|
| 290 |
+
# Retorna 11 valores para limpar todos os campos
|
| 291 |
return (
|
| 292 |
"", # texto_output
|
| 293 |
None, # imagem_output
|
|
|
|
| 295 |
0, # palavras_output
|
| 296 |
0, # caracteres_output
|
| 297 |
0, # hashtags_output
|
| 298 |
+
list(FORMATO_CONFIGS.keys())[0], # formato_input (Solicitação 1)
|
| 299 |
"Nenhum (Automático)", # estilo_img_input
|
| 300 |
"Balanceada", # qualidade_img_input
|
| 301 |
"Nenhum", # filtro_img_input
|
|
|
|
| 309 |
# através da chamada a 'atualizar_historico'
|
| 310 |
return _formatar_historico_para_df(post_history)
|
| 311 |
|
| 312 |
+
# ============================================
|
| 313 |
+
# NOVA FUNÇÃO: INTERPRETAR ERROS (Solicitação 3)
|
| 314 |
+
# ============================================
|
| 315 |
+
def interpretar_erro_api(erro_str):
|
| 316 |
+
"""Interpreta erros comuns da API para o usuário em Português."""
|
| 317 |
+
erro_str_lower = erro_str.lower()
|
| 318 |
+
print(f"Interpretando erro: {erro_str}")
|
| 319 |
+
|
| 320 |
+
if "402" in erro_str_lower or "payment required" in erro_str_lower or "exceeded your monthly included credits" in erro_str_lower:
|
| 321 |
+
return ("Erro 402: Limite de créditos excedido. Você excedeu seus créditos mensais da API do Hugging Face. "
|
| 322 |
+
"Considere assinar o plano PRO para mais créditos.")
|
| 323 |
+
|
| 324 |
+
if "503" in erro_str_lower or "model is loading" in erro_str_lower or "service temporarily unavailable" in erro_str_lower:
|
| 325 |
+
return ("Erro 503: Modelo indisponível. O modelo está carregando ou temporariamente indisponível. "
|
| 326 |
+
"Por favor, tente novamente em alguns segundos.")
|
| 327 |
+
|
| 328 |
+
if "429" in erro_str_lower or "too many requests" in erro_str_lower:
|
| 329 |
+
return ("Erro 429: Muitas requisições. O limite de taxa foi atingido. "
|
| 330 |
+
"Por favor, aguarde um momento e tente novamente.")
|
| 331 |
+
|
| 332 |
+
if "timeout" in erro_str_lower or "timed out" in erro_str_lower:
|
| 333 |
+
return ("Erro de Timeout: A conexão expirou. O modelo demorou muito para responder. "
|
| 334 |
+
"Tente novamente.")
|
| 335 |
+
|
| 336 |
+
if "authorization" in erro_str_lower or "401" in erro_str_lower:
|
| 337 |
+
return ("Erro 401: Autenticação falhou. A Chave da API (Secret 'Capoeira') pode estar inválida ou ausente.")
|
| 338 |
+
|
| 339 |
+
# Fallback para erros genéricos
|
| 340 |
+
return f"Erro inesperado: {erro_str[:200]}..." # Trunca o erro
|
| 341 |
|
| 342 |
# ============================================
|
| 343 |
# FUNÇÕES DE GERAÇÃO (POSTS)
|
| 344 |
# ============================================
|
| 345 |
|
| 346 |
+
def gerar_texto(tema, nicho, estilo, formato): # ATUALIZADO: 'formato' re-adicionado
|
| 347 |
"""
|
| 348 |
Gera texto usando API do Hugging Face com base no formato escolhido.
|
|
|
|
|
|
|
| 349 |
"""
|
| 350 |
|
| 351 |
+
# ATUALIZADO: Linha hardcoded removida
|
| 352 |
+
# formato = "Instagram (Post)"
|
| 353 |
|
| 354 |
if not HUGGINGFACE_API_KEY:
|
| 355 |
return "❌ Erro de Configuração: API Key não está definida."
|
|
|
|
| 395 |
else:
|
| 396 |
return f"❌ Erro na resposta da API: Resposta vazia ou inesperada.\n{resultado}"
|
| 397 |
else:
|
| 398 |
+
# ATUALIZADO: Interpretar erro
|
| 399 |
+
return f"❌ {interpretar_erro_api(f'Erro {response.status_code}: {response.text}')}"
|
| 400 |
|
| 401 |
except Exception as e:
|
| 402 |
+
# ATUALIZADO: Interpretar erro
|
| 403 |
+
return f"❌ {interpretar_erro_api(str(e))}"
|
| 404 |
|
| 405 |
def traduzir_texto(texto_pt):
|
| 406 |
"""Traduz texto de Português (PT) para Inglês (EN) usando API do Hugging Face.
|
|
|
|
| 429 |
return texto_pt # Fallback
|
| 430 |
|
| 431 |
except Exception as e:
|
| 432 |
+
print(f"Falha na tradução (fallback para PT): {e}")
|
| 433 |
return texto_pt # Fallback
|
| 434 |
|
| 435 |
# ============================================
|
|
|
|
| 440 |
"""Combina as escolhas do usuário em um prompt otimizado (em Português)."""
|
| 441 |
|
| 442 |
# 1. Obter estilo
|
| 443 |
+
# ATUALIZADO: Usar o novo dicionário ESTILOS_DE_IMAGEM (Solicitação 2)
|
| 444 |
+
estilo = ESTILOS_DE_IMAGEM.get(estilo_escolhido, ESTILOS_DE_IMAGEM["Nenhum (Automático)"])
|
| 445 |
|
| 446 |
# 2. Obter filtro
|
| 447 |
filtro = FILTROS_IMAGEM.get(filtro_escolhido, FILTROS_IMAGEM["Nenhum"])
|
|
|
|
| 521 |
continue
|
| 522 |
else:
|
| 523 |
# Último modelo falhou, retornar erro
|
| 524 |
+
# ATUALIZADO: Interpretar erro
|
| 525 |
+
mensagem = f"❌ {interpretar_erro_api(str(e))}"
|
| 526 |
return (None, mensagem)
|
| 527 |
|
| 528 |
# Se chegou aqui, algo deu errado
|
|
|
|
| 573 |
else:
|
| 574 |
return f"❌ Erro na resposta da API: Resposta vazia ou inesperada.\n{resultado}"
|
| 575 |
else:
|
| 576 |
+
# ATUALIZADO: Interpretar erro
|
| 577 |
+
return f"❌ {interpretar_erro_api(f'Erro {response.status_code}: {response.text}')}"
|
| 578 |
|
| 579 |
except Exception as e:
|
| 580 |
+
# ATUALIZADO: Interpretar erro
|
| 581 |
+
return f"❌ {interpretar_erro_api(str(e))}"
|
| 582 |
|
| 583 |
# ============================================
|
| 584 |
# NOVAS FUNÇÕES DE DOWNLOAD
|
|
|
|
| 685 |
# FUNÇÃO PRINCIPAL COM PROGRESSO (ATUALIZADA)
|
| 686 |
# ============================================
|
| 687 |
|
| 688 |
+
def gerar_post_interface(tema, nicho, estilo, formato, # ATUALIZADO: 'formato' adicionado
|
| 689 |
+
descricao_imagem, gerar_img,
|
| 690 |
estilo_img_input, qualidade_img_input, filtro_img_input,
|
| 691 |
progress=gr.Progress()):
|
| 692 |
"""Gera post completo com feedback e lógica de imagem avançada"""
|
|
|
|
| 709 |
|
| 710 |
# Gerando texto
|
| 711 |
progress(0.3, desc="🤖 Gerando texto (Llama 3.1)...")
|
| 712 |
+
# ATUALIZADO: 'formato' passado para gerar_texto
|
| 713 |
+
texto = gerar_texto(tema, nicho, estilo, formato)
|
| 714 |
|
| 715 |
+
if texto.startswith("❌"): # Erro já vem formatado
|
| 716 |
+
status_final = criar_alerta('error', f'{texto}')
|
| 717 |
return (texto, None, status_final, 0, 0, 0)
|
| 718 |
|
| 719 |
progress(0.5, desc="✅ Texto pronto!")
|
|
|
|
| 739 |
status_final = criar_alerta('success', f'🎉 Post completo gerado! ({status_imagem})')
|
| 740 |
else:
|
| 741 |
# status_imagem conterá a mensagem de erro (ex: "Todos os modelos falharam")
|
| 742 |
+
# ATUALIZADO: status_imagem já vem formatado com o erro
|
| 743 |
status_final = criar_alerta('warning', f'✅ Texto OK, mas imagem falhou: {status_imagem}')
|
| 744 |
else:
|
| 745 |
progress(0.7, desc="⏭️ Pulando geração de imagem...")
|
|
|
|
| 761 |
# INÍCIO DA CORREÇÃO: Re-adicionando salvamento no histórico
|
| 762 |
# ==================================================
|
| 763 |
|
| 764 |
+
# ATUALIZADO: Usar o 'formato' vindo do input
|
| 765 |
+
formato_usado = formato
|
|
|
|
| 766 |
|
| 767 |
# Usar a variável 'status' que já foi definida
|
| 768 |
status_final_historico = status_final # Usar o status HTML (o Firestore lida bem com strings)
|
|
|
|
| 775 |
"Tema": tema,
|
| 776 |
"Nicho": nicho,
|
| 777 |
"Estilo": estilo,
|
| 778 |
+
"Formato": formato_usado, # Atualizado
|
| 779 |
"Texto (Preview)": texto_preview,
|
| 780 |
"Status": status_imagem or "Texto Gerado", # Salva o status da imagem (ex: "Gerada com FLUX")
|
| 781 |
}
|
|
|
|
| 836 |
placeholder="Ex: Transforme seu corpo, transforme sua vida"
|
| 837 |
)
|
| 838 |
|
| 839 |
+
# ATUALIZADO: Reativado (Solicitação 1)
|
| 840 |
formato_input = gr.Radio(
|
| 841 |
choices=list(FORMATO_CONFIGS.keys()),
|
| 842 |
+
label="Escolha o Formato de Saída",
|
| 843 |
value=list(FORMATO_CONFIGS.keys())[0],
|
| 844 |
+
interactive=True,
|
| 845 |
+
visible=True
|
| 846 |
)
|
| 847 |
|
| 848 |
gr.Markdown("### 🎨 2. Configurações da Imagem (Opcional)")
|
|
|
|
| 859 |
visible=False
|
| 860 |
)
|
| 861 |
|
| 862 |
+
# ATUALIZADO: Usando ESTILOS_DE_IMAGEM (Solicitação 2)
|
| 863 |
estilo_img_input = gr.Dropdown(
|
| 864 |
label="Estilo da Imagem",
|
| 865 |
+
choices=list(ESTILOS_DE_IMAGEM.keys()),
|
| 866 |
value="Nenhum (Automático)",
|
| 867 |
visible=False,
|
| 868 |
interactive=True
|
|
|
|
| 950 |
|
| 951 |
gr.Markdown("### 💡 Experimente estes exemplos:")
|
| 952 |
|
| 953 |
+
# ATUALIZADO: Exemplos agora incluem o formato
|
| 954 |
gr.Examples(
|
| 955 |
examples=[
|
| 956 |
+
[NICHOS_DISPONIVEIS[2], ESTILOS_DISPONIVEIS[0], "Frases marcantes de pessoas importantes", "Instagram (Post)"],
|
| 957 |
+
[NICHOS_DISPONIVEIS[1], ESTILOS_DISPONIVEIS[2], "Receita rápida de smoothie verde", "Instagram (Post)"],
|
| 958 |
+
[NICHOS_DISPONIVEIS[5], ESTILOS_DISPONIVEIS[3], "O futuro da IA em 2025", "LinkedIn (Artigo)"],
|
| 959 |
+
[NICHOS_DISPONIVEIS[4], ESTILOS_DISPONIVEIS[1], "Melhores destinos para lua de mel na Europa", "Twitter/X (Curto)"],
|
| 960 |
],
|
| 961 |
+
inputs=[nicho_input, estilo_input, tema_input, formato_input], # 'formato_input' adicionado
|
| 962 |
outputs=[texto_output, imagem_output, status_output]
|
| 963 |
)
|
| 964 |
|
|
|
|
| 972 |
fn=gerar_post_interface,
|
| 973 |
inputs=[
|
| 974 |
tema_input, nicho_input, estilo_input,
|
| 975 |
+
formato_input, # ATUALIZADO: 'formato_input' adicionado
|
| 976 |
descricao_img_input, gerar_img_checkbox,
|
| 977 |
estilo_img_input, qualidade_img_input, filtro_img_input # Novos inputs
|
| 978 |
],
|
|
|
|
| 997 |
outputs=[
|
| 998 |
texto_output, imagem_output, status_output,
|
| 999 |
palavras_output, caracteres_output, hashtags_output,
|
| 1000 |
+
formato_input, # ATUALIZADO: 'formato_input' adicionado
|
| 1001 |
estilo_img_input, qualidade_img_input, filtro_img_input, # Limpa novos inputs
|
| 1002 |
download_output # Limpa o arquivo de download
|
| 1003 |
]
|
|
|
|
| 1036 |
],
|
| 1037 |
chatbot=chatbot_para_interface, # Passando o componente chatbot customizado
|
| 1038 |
textbox=gr.Textbox(placeholder="Digite sua mensagem aqui...", scale=7),
|
| 1039 |
+
submit_btn="Enviar",
|
| 1040 |
+
# CORREÇÃO: Botões removidos conforme solicitado (Solicitação 7)
|
| 1041 |
+
clear_btn=None,
|
| 1042 |
+
retry_btn=None,
|
| 1043 |
+
undo_btn=None,
|
| 1044 |
)
|
| 1045 |
|
| 1046 |
# ABA 2: Histórico (Exibe o Dataframe)
|
|
|
|
| 1084 |
gr.Markdown("---")
|
| 1085 |
gr.Markdown("#### Funcionalidades:")
|
| 1086 |
gr.Markdown("- **Gerador de Posts:** Cria posts completos com texto e imagem.")
|
| 1087 |
+
gr.Markdown("- **Seleção de Formato:** Permite escolher o formato do texto (Instagram, Twitter, LinkedIn).")
|
| 1088 |
gr.Markdown("- **Controles Avançados:** Permite seleção de Estilo, Qualidade e Filtros para a imagem.")
|
| 1089 |
gr.Markdown("- **Download de Post:** Combina texto e imagem em um único arquivo PNG para download.")
|
| 1090 |
gr.Markdown("- **Chatbot Assistente:** Converse com a IA para ideias e perguntas rápidas.")
|
|
|
|
| 1108 |
- **PIL (Python Imaging Library) (para composição de posts)**
|
| 1109 |
|
| 1110 |
**Como funciona:**
|
| 1111 |
+
1. **Gerar Post:** Você define o tema, nicho, estilo e **formato** do *texto*.
|
| 1112 |
2. **Imagem (Opcional):** Você ativa, descreve a imagem e seleciona *Estilo*, *Qualidade* e *Filtro*.
|
| 1113 |
3. O sistema otimiza o prompt, traduz para inglês e usa o sistema de *fallback* de modelos (baseado na *Qualidade*) para gerar a imagem.
|
| 1114 |
4. **Download:** Após a geração, você pode clicar em "Baixar Post Completo" para salvar um PNG com a imagem e o texto formatado.
|