Spaces:
Running
Running
Update app.py
Browse filesadicionado a nova aba de chatbot e atualizado os textos de apoio
app.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
-
# GERADOR DE POSTS PARA REDES SOCIAIS
|
| 2 |
# Aula 9: Versão Web com Hugging Face Spaces + Gradio
|
| 3 |
# Versão com persistência de dados via Firebase Admin
|
|
|
|
| 4 |
|
| 5 |
import gradio as gr
|
| 6 |
import requests
|
|
@@ -27,7 +28,7 @@ if not HUGGINGFACE_API_KEY:
|
|
| 27 |
BASE_URL = "https://router.huggingface.co/v1"
|
| 28 |
MODELO_TEXTO = "meta-llama/Llama-3.1-8B-Instruct"
|
| 29 |
MODELO_IMAGEM = "black-forest-labs/FLUX.1-schnell"
|
| 30 |
-
MODELO_TRADUCA = "Helsinki-NLP/opus-mt-pt-en"
|
| 31 |
|
| 32 |
# Headers para requisições
|
| 33 |
headers = {
|
|
@@ -67,7 +68,7 @@ FORMATO_CONFIGS = {
|
|
| 67 |
# Variável global para armazenar o histórico de sessão (agora é um cache)
|
| 68 |
post_history = []
|
| 69 |
# Variável para a instância do Firestore
|
| 70 |
-
db = None
|
| 71 |
|
| 72 |
|
| 73 |
# ============================================
|
|
@@ -197,7 +198,7 @@ def _formatar_historico_para_df(history_list):
|
|
| 197 |
return formatted_list
|
| 198 |
|
| 199 |
# ============================================
|
| 200 |
-
# FUNÇÕES DE GERAÇÃO (
|
| 201 |
# ============================================
|
| 202 |
|
| 203 |
def gerar_texto(tema, nicho, estilo, formato):
|
|
@@ -247,7 +248,7 @@ Escreva apenas o conteúdo, sem introduções ou explicações."""
|
|
| 247 |
texto = resultado['choices'][0]['message']['content'].strip()
|
| 248 |
return texto
|
| 249 |
else:
|
| 250 |
-
|
| 251 |
else:
|
| 252 |
return f"❌ Erro ao gerar texto: {response.status_code}\n{response.text}"
|
| 253 |
|
|
@@ -307,13 +308,61 @@ def gerar_imagem(descricao):
|
|
| 307 |
print(f"Erro ao gerar imagem: {str(e)}")
|
| 308 |
return None
|
| 309 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 310 |
|
| 311 |
# ============================================
|
| 312 |
-
# FUNÇÃO PRINCIPAL PARA O
|
| 313 |
# ============================================
|
| 314 |
def gerar_post_interface(tema, nicho, estilo, formato, descricao_imagem, gerar_img, progress=gr.Progress()):
|
| 315 |
"""
|
| 316 |
-
Função principal que o Gradio chama
|
| 317 |
"""
|
| 318 |
progress(0, desc="Iniciando validação...")
|
| 319 |
|
|
@@ -382,7 +431,7 @@ def gerar_post_interface(tema, nicho, estilo, formato, descricao_imagem, gerar_i
|
|
| 382 |
|
| 383 |
|
| 384 |
# ============================================
|
| 385 |
-
# INTERFACE GRADIO (
|
| 386 |
# ============================================
|
| 387 |
|
| 388 |
custom_theme = gr.themes.Glass(
|
|
@@ -393,11 +442,11 @@ custom_theme = gr.themes.Glass(
|
|
| 393 |
)
|
| 394 |
|
| 395 |
|
| 396 |
-
with gr.Blocks(theme=custom_theme, title="Gerador de Posts") as demo:
|
| 397 |
|
| 398 |
gr.Markdown("""
|
| 399 |
-
# 🚀 Gerador de Posts
|
| 400 |
-
### Powered by Hugging Face
|
| 401 |
""")
|
| 402 |
|
| 403 |
theme_mode = gr.Radio(
|
|
@@ -554,15 +603,40 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts") as demo:
|
|
| 554 |
queue=True # Necessário para gr.Progress
|
| 555 |
)
|
| 556 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 557 |
# ABA 2: Histórico (Exibe o Dataframe)
|
| 558 |
-
with gr.TabItem("📚 Histórico"):
|
| 559 |
gr.Markdown("### Posts Gerados Recentemente")
|
| 560 |
|
| 561 |
# Dataframe de exibição que é atualizado pelo output do botão
|
| 562 |
historico_display = gr.Dataframe(
|
| 563 |
headers=["Data/Hora", "Tema", "Nicho", "Estilo", "Formato", "Texto (Preview)", "Status"],
|
| 564 |
interactive=False,
|
| 565 |
-
value=_formatar_historico_para_df(carregar_historico_inicial()), # Carrega histórico (DB ou vazio) E FORMATA
|
| 566 |
)
|
| 567 |
# Garantir que o historico_display seja atualizado sempre que o historico_dataframe (invisível) for atualizado
|
| 568 |
historico_dataframe.change(lambda x: x, historico_dataframe, historico_display)
|
|
@@ -571,29 +645,25 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts") as demo:
|
|
| 571 |
---
|
| 572 |
*Nota sobre Persistência:*
|
| 573 |
|
| 574 |
-
Esta aba agora exibe o histórico persistente salvo no Google Firestore.
|
| 575 |
O histórico é compartilhado entre todas as sessões e usuários.
|
| 576 |
""")
|
| 577 |
|
| 578 |
# ABA 3: Configurações
|
| 579 |
with gr.TabItem("⚙️ Configurações"):
|
| 580 |
gr.Markdown("### Configurações do Gerador")
|
| 581 |
-
gr.Markdown("**Modelo de Texto:** Llama 3.1 8B")
|
| 582 |
gr.Markdown("**Modelo de Imagem:** FLUX.1 Schnell")
|
| 583 |
gr.Markdown("**Modelo de Tradução (PT -> EN):** Helsinki-NLP/opus-mt-pt-en")
|
| 584 |
gr.Markdown("**API Provider:** Hugging Face Inference")
|
| 585 |
gr.Markdown("**Database:** Google Firestore (via Firebase Admin)")
|
| 586 |
gr.Markdown("---")
|
| 587 |
-
gr.Markdown("####
|
| 588 |
-
gr.Markdown("-
|
| 589 |
-
gr.Markdown("-
|
| 590 |
-
gr.Markdown("-
|
| 591 |
-
gr.Markdown("#### Estilos Adicionais:")
|
| 592 |
-
gr.Markdown("- Controverso e de Debate")
|
| 593 |
-
gr.Markdown("- Curiosidades (Fatos Rápidos)")
|
| 594 |
-
gr.Markdown("- Tutorial/Passo a Passo")
|
| 595 |
gr.Markdown("---")
|
| 596 |
-
gr.Markdown("#### Formatos de Saída:")
|
| 597 |
gr.Markdown("- Instagram (Post): 100-150 palavras")
|
| 598 |
gr.Markdown("- Twitter/X (Curto): Até 280 caracteres")
|
| 599 |
gr.Markdown("- LinkedIn (Artigo): 250-400 palavras")
|
|
@@ -609,16 +679,16 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts") as demo:
|
|
| 609 |
**Tecnologias:**
|
| 610 |
- Hugging Face Spaces (hospedagem)
|
| 611 |
- Gradio (interface web)
|
| 612 |
-
- Llama 3.1 8B (geração de texto)
|
| 613 |
- FLUX.1 (geração de imagens)
|
| 614 |
- Opus-MT (tradução)
|
| 615 |
- **Firebase Firestore (Banco de Dados)**
|
| 616 |
|
| 617 |
**Como funciona:**
|
| 618 |
-
1. Você escolhe nicho, tema e **formato de saída**.
|
| 619 |
-
2.
|
| 620 |
-
3. Se a imagem estiver marcada, a descrição é **automaticamente traduzida para Inglês**.
|
| 621 |
-
4. Os resultados são exibidos e o post é salvo permanentemente no **Firestore**, aparecendo na aba "Histórico".
|
| 622 |
|
| 623 |
**Desenvolvido por:** Wilder Paz
|
| 624 |
""")
|
|
@@ -626,11 +696,9 @@ with gr.Blocks(theme=custom_theme, title="Gerador de Posts") as demo:
|
|
| 626 |
# Footer
|
| 627 |
gr.Markdown("""
|
| 628 |
---
|
| 629 |
-
**Curso de Python com IA** | 🤖 Powered by Llama 3.1 & FLUX | ⚡ Hugging Face Spaces + Gradio
|
| 630 |
""")
|
| 631 |
|
| 632 |
# Lançar aplicação
|
| 633 |
if __name__ == "__main__":
|
| 634 |
demo.launch()
|
| 635 |
-
|
| 636 |
-
|
|
|
|
| 1 |
+
# CHATBOT E GERADOR DE POSTS PARA REDES SOCIAIS
|
| 2 |
# Aula 9: Versão Web com Hugging Face Spaces + Gradio
|
| 3 |
# Versão com persistência de dados via Firebase Admin
|
| 4 |
+
# ATUALIZADO: Adicionada funcionalidade de Chatbot
|
| 5 |
|
| 6 |
import gradio as gr
|
| 7 |
import requests
|
|
|
|
| 28 |
BASE_URL = "https://router.huggingface.co/v1"
|
| 29 |
MODELO_TEXTO = "meta-llama/Llama-3.1-8B-Instruct"
|
| 30 |
MODELO_IMAGEM = "black-forest-labs/FLUX.1-schnell"
|
| 31 |
+
MODELO_TRADUCA = "Helsinki-NLP/opus-mt-pt-en"
|
| 32 |
|
| 33 |
# Headers para requisições
|
| 34 |
headers = {
|
|
|
|
| 68 |
# Variável global para armazenar o histórico de sessão (agora é um cache)
|
| 69 |
post_history = []
|
| 70 |
# Variável para a instância do Firestore
|
| 71 |
+
db = None
|
| 72 |
|
| 73 |
|
| 74 |
# ============================================
|
|
|
|
| 198 |
return formatted_list
|
| 199 |
|
| 200 |
# ============================================
|
| 201 |
+
# FUNÇÕES DE GERAÇÃO (POSTS)
|
| 202 |
# ============================================
|
| 203 |
|
| 204 |
def gerar_texto(tema, nicho, estilo, formato):
|
|
|
|
| 248 |
texto = resultado['choices'][0]['message']['content'].strip()
|
| 249 |
return texto
|
| 250 |
else:
|
| 251 |
+
return f"❌ Erro na resposta da API: Resposta vazia ou inesperada.\n{resultado}"
|
| 252 |
else:
|
| 253 |
return f"❌ Erro ao gerar texto: {response.status_code}\n{response.text}"
|
| 254 |
|
|
|
|
| 308 |
print(f"Erro ao gerar imagem: {str(e)}")
|
| 309 |
return None
|
| 310 |
|
| 311 |
+
# ============================================
|
| 312 |
+
# NOVA FUNÇÃO DO CHATBOT
|
| 313 |
+
# ============================================
|
| 314 |
+
def responder_chat(message, chat_history):
|
| 315 |
+
"""
|
| 316 |
+
Processa uma mensagem do usuário e retorna uma resposta do LLM para o chatbot.
|
| 317 |
+
"""
|
| 318 |
+
if not HUGGINGFACE_API_KEY:
|
| 319 |
+
return "❌ Erro de Configuração: API Key não está definida."
|
| 320 |
+
|
| 321 |
+
url = f"{BASE_URL}/chat/completions"
|
| 322 |
+
|
| 323 |
+
# 1. Definir o System Prompt para o assistente
|
| 324 |
+
system_prompt = "Você é um assistente virtual prestativo e amigável, especializado em marketing de mídias sociais e criação de conteúdo, mas pode responder sobre qualquer tópico. Seja direto e útil."
|
| 325 |
+
|
| 326 |
+
# 2. Construir o histórico no formato da API
|
| 327 |
+
messages = [{"role": "system", "content": system_prompt}]
|
| 328 |
+
|
| 329 |
+
for user_msg, bot_msg in chat_history:
|
| 330 |
+
messages.append({"role": "user", "content": user_msg})
|
| 331 |
+
messages.append({"role": "assistant", "content": bot_msg})
|
| 332 |
+
|
| 333 |
+
# 3. Adicionar a nova mensagem do usuário
|
| 334 |
+
messages.append({"role": "user", "content": message})
|
| 335 |
+
|
| 336 |
+
payload = {
|
| 337 |
+
"model": MODELO_TEXTO, # Reutiliza o mesmo modelo
|
| 338 |
+
"messages": messages,
|
| 339 |
+
"max_tokens": 1500, # Mais espaço para uma conversa fluida
|
| 340 |
+
"temperature": 0.7,
|
| 341 |
+
"stream": False # ChatInterface do Gradio lida melhor com respostas completas
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
try:
|
| 345 |
+
response = requests.post(url, headers=headers, json=payload, timeout=60)
|
| 346 |
+
|
| 347 |
+
if response.status_code == 200:
|
| 348 |
+
resultado = response.json()
|
| 349 |
+
if 'choices' in resultado and resultado['choices']:
|
| 350 |
+
texto = resultado['choices'][0]['message']['content'].strip()
|
| 351 |
+
return texto
|
| 352 |
+
else:
|
| 353 |
+
return f"❌ Erro na resposta da API: Resposta vazia ou inesperada.\n{resultado}"
|
| 354 |
+
else:
|
| 355 |
+
return f"❌ Erro ao gerar resposta: {response.status_code}\n{response.text}"
|
| 356 |
+
|
| 357 |
+
except Exception as e:
|
| 358 |
+
return f"❌ Erro de Conexão: {str(e)}"
|
| 359 |
|
| 360 |
# ============================================
|
| 361 |
+
# FUNÇÃO PRINCIPAL PARA O GERADOR DE POSTS
|
| 362 |
# ============================================
|
| 363 |
def gerar_post_interface(tema, nicho, estilo, formato, descricao_imagem, gerar_img, progress=gr.Progress()):
|
| 364 |
"""
|
| 365 |
+
Função principal que o Gradio chama para GERAR POSTS, com barra de progresso e persistência.
|
| 366 |
"""
|
| 367 |
progress(0, desc="Iniciando validação...")
|
| 368 |
|
|
|
|
| 431 |
|
| 432 |
|
| 433 |
# ============================================
|
| 434 |
+
# INTERFACE GRADIO (Com Chatbot)
|
| 435 |
# ============================================
|
| 436 |
|
| 437 |
custom_theme = gr.themes.Glass(
|
|
|
|
| 442 |
)
|
| 443 |
|
| 444 |
|
| 445 |
+
with gr.Blocks(theme=custom_theme, title="Gerador de Posts e Chatbot") as demo:
|
| 446 |
|
| 447 |
gr.Markdown("""
|
| 448 |
+
# 🚀 Gerador de Posts e Assistente de Mídias Sociais
|
| 449 |
+
### Powered by Hugging Face, Gradio e Llama 3.1
|
| 450 |
""")
|
| 451 |
|
| 452 |
theme_mode = gr.Radio(
|
|
|
|
| 603 |
queue=True # Necessário para gr.Progress
|
| 604 |
)
|
| 605 |
|
| 606 |
+
# ============================================
|
| 607 |
+
# NOVA ABA: CHATBOT
|
| 608 |
+
# ============================================
|
| 609 |
+
with gr.TabItem("💬 Chatbot Assistente"):
|
| 610 |
+
gr.Markdown("### 🤖 Assistente Virtual")
|
| 611 |
+
gr.Markdown("Faça perguntas sobre mídias sociais, IA, peça ideias rápidas ou qualquer outro tópico.")
|
| 612 |
+
|
| 613 |
+
gr.ChatInterface(
|
| 614 |
+
fn=responder_chat,
|
| 615 |
+
title="Assistente Virtual",
|
| 616 |
+
description="Converse com o Llama 3.1 para obter ajuda e insights.",
|
| 617 |
+
examples=[
|
| 618 |
+
"O que é um 'gancho' para Instagram?",
|
| 619 |
+
"Me dê 3 ideias de post para um nicho de 'Fitness'",
|
| 620 |
+
"Como o Llama 3.1 funciona?",
|
| 621 |
+
"Qual a diferença entre um post para Instagram e um para LinkedIn?"
|
| 622 |
+
],
|
| 623 |
+
chatbot=gr.Chatbot(height=500), # Define uma altura
|
| 624 |
+
textbox=gr.Textbox(placeholder="Digite sua mensagem aqui...", scale=7),
|
| 625 |
+
submit_btn="Enviar",
|
| 626 |
+
clear_btn="Limpar Conversa",
|
| 627 |
+
retry_btn=None, # Oculta botões desnecessários
|
| 628 |
+
undo_btn=None,
|
| 629 |
+
)
|
| 630 |
+
|
| 631 |
# ABA 2: Histórico (Exibe o Dataframe)
|
| 632 |
+
with gr.TabItem("📚 Histórico de Posts"):
|
| 633 |
gr.Markdown("### Posts Gerados Recentemente")
|
| 634 |
|
| 635 |
# Dataframe de exibição que é atualizado pelo output do botão
|
| 636 |
historico_display = gr.Dataframe(
|
| 637 |
headers=["Data/Hora", "Tema", "Nicho", "Estilo", "Formato", "Texto (Preview)", "Status"],
|
| 638 |
interactive=False,
|
| 639 |
+
value=_formatar_historico_para_df(carregar_historico_inicial()), # Carrega histórico (DB ou vazio) E FORMATA
|
| 640 |
)
|
| 641 |
# Garantir que o historico_display seja atualizado sempre que o historico_dataframe (invisível) for atualizado
|
| 642 |
historico_dataframe.change(lambda x: x, historico_dataframe, historico_display)
|
|
|
|
| 645 |
---
|
| 646 |
*Nota sobre Persistência:*
|
| 647 |
|
| 648 |
+
Esta aba agora exibe o histórico persistente (dos **posts gerados**) salvo no Google Firestore.
|
| 649 |
O histórico é compartilhado entre todas as sessões e usuários.
|
| 650 |
""")
|
| 651 |
|
| 652 |
# ABA 3: Configurações
|
| 653 |
with gr.TabItem("⚙️ Configurações"):
|
| 654 |
gr.Markdown("### Configurações do Gerador")
|
| 655 |
+
gr.Markdown("**Modelo de Texto (LLM):** Llama 3.1 8B (Usado para Posts e Chatbot)")
|
| 656 |
gr.Markdown("**Modelo de Imagem:** FLUX.1 Schnell")
|
| 657 |
gr.Markdown("**Modelo de Tradução (PT -> EN):** Helsinki-NLP/opus-mt-pt-en")
|
| 658 |
gr.Markdown("**API Provider:** Hugging Face Inference")
|
| 659 |
gr.Markdown("**Database:** Google Firestore (via Firebase Admin)")
|
| 660 |
gr.Markdown("---")
|
| 661 |
+
gr.Markdown("#### Funcionalidades:")
|
| 662 |
+
gr.Markdown("- **Gerador de Posts:** Cria posts completos com texto e imagem.")
|
| 663 |
+
gr.Markdown("- **Chatbot Assistente:** Converse com a IA para ideias e perguntas rápidas.")
|
| 664 |
+
gr.Markdown("- **Histórico Persistente:** Salva os *posts gerados* no Firestore.")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 665 |
gr.Markdown("---")
|
| 666 |
+
gr.Markdown("#### Formatos de Saída (Gerador de Posts):")
|
| 667 |
gr.Markdown("- Instagram (Post): 100-150 palavras")
|
| 668 |
gr.Markdown("- Twitter/X (Curto): Até 280 caracteres")
|
| 669 |
gr.Markdown("- LinkedIn (Artigo): 250-400 palavras")
|
|
|
|
| 679 |
**Tecnologias:**
|
| 680 |
- Hugging Face Spaces (hospedagem)
|
| 681 |
- Gradio (interface web)
|
| 682 |
+
- **Llama 3.1 8B (geração de texto e chatbot)**
|
| 683 |
- FLUX.1 (geração de imagens)
|
| 684 |
- Opus-MT (tradução)
|
| 685 |
- **Firebase Firestore (Banco de Dados)**
|
| 686 |
|
| 687 |
**Como funciona:**
|
| 688 |
+
1. **Gerar Post:** Você escolhe nicho, tema e **formato de saída**.
|
| 689 |
+
2. **Chatbot:** Você pode conversar diretamente com a IA na aba 'Chatbot Assistente' para tirar dúvidas.
|
| 690 |
+
3. Se a imagem estiver marcada (no Gerador), a descrição é **automaticamente traduzida para Inglês**.
|
| 691 |
+
4. Os resultados são exibidos e o post é salvo permanentemente no **Firestore**, aparecendo na aba "Histórico de Posts".
|
| 692 |
|
| 693 |
**Desenvolvido por:** Wilder Paz
|
| 694 |
""")
|
|
|
|
| 696 |
# Footer
|
| 697 |
gr.Markdown("""
|
| 698 |
---
|
| 699 |
+
**Curso de Python com IA** | 🤖 Powered by Llama 3.1 & FLUX | ⚡ Hugging Face Spaces + Gradio + Firestore
|
| 700 |
""")
|
| 701 |
|
| 702 |
# Lançar aplicação
|
| 703 |
if __name__ == "__main__":
|
| 704 |
demo.launch()
|
|
|
|
|
|