caarleexx commited on
Commit
08eed8d
·
verified ·
1 Parent(s): d13c759

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -52
app.py CHANGED
@@ -1,4 +1,4 @@
1
- # --- INÍCIO DO CÓDIGO FINAL CORRIGIDO ---
2
 
3
  import gradio as gr
4
  import os
@@ -9,94 +9,138 @@ import json
9
  api_key = os.getenv("GOOGLE_API_KEY")
10
  if not api_key:
11
  # ⚠️ SUBSTITUA PELA SUA CHAVE REAL ANTES DE EXECUTAR
12
- api_key = "AIzaSyBedFD-iX0G6_DODAnjKZNEJbe6mjyHiR0"
13
 
14
  genai.configure(api_key=api_key)
 
15
 
16
- # CORREÇÃO 1: Usando o nome do modelo mais recente e recomendado.
17
- model = genai.GenerativeModel('gemini-2.5-pro')
18
-
19
- # --- PROMPT DE SISTEMA ---
20
  PROMPT_SISTEMA = """
21
- Você é um assistente de raciocínio estruturado. Sua função é executar um protocolo de análise de 5 passos antes de fornecer uma resposta final.
22
- Sua saída DEVE SER SEMPRE um objeto JSON válido, sem nenhum outro texto antes ou depois.
23
-
24
- O protocolo funciona da seguinte forma:
25
- 1. **Passo 1 (Análise Primária):** Receba a dúvida inicial do usuário. Avalie a clareza.
26
- 2. **Passo 2 (Análise de Propósito):** Infira 'para que' o usuário quer a resposta (estudo, curiosidade, etc.). Se a confiança for baixa, formule uma pergunta para esclarecer.
27
- 3. **Passo 3 (Análise de Motivação):** Infira 'por que' o usuário quer a resposta (medo, interesse súbito, etc.). Se a confiança for baixa, formule uma pergunta.
28
- 4. **Passo 4 (Coerência):** Verifique se todas as informações são coerentes.
29
- 5. **Passo 5 (Resposta Final):** Quando tiver confiança média ou alta em todos os passos, gere a resposta completa para o usuário.
30
-
31
- **Estrutura do JSON de Saída:**
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  {
33
- "proximo_passo": "string",
34
- "justificativa_raciocinio": "string",
35
- "pergunta_para_usuario": "string | null",
36
- "dados_coletados": {
37
- "duvida_inicial": "string",
38
- "para_que": {"valor": "string | null", "confianca": "baixa|media|alta"},
39
- "porque": {"valor": "string | null", "confianca": "baixa|media|alta"}
40
- },
41
- "resposta_final": "string | null"
42
  }
43
-
44
- **Instrução:**
45
- Analise o 'Estado Atual da Pipeline' e o 'Histórico da Conversa' fornecidos. Retorne o objeto JSON que representa a próxima ação a ser tomada.
46
- NÃO responda diretamente ao usuário no histórico. Seu único trabalho é gerar o JSON para a aplicação.
47
  """
48
 
49
  # --- GERENCIAMENTO DE ESTADO ---
50
  def resetar_estado():
51
  return {
52
- "passo_atual": "passo_1_analise_primaria",
53
- "dados_coletados": {
54
- "duvida_inicial": None,
55
- "para_que": {"valor": None, "confianca": "baixa"},
56
- "porque": {"valor": None, "confianca": "baixa"}
57
- },
58
- "historico_conversa_gemini": []
59
  }
60
 
61
- estado_pipeline = resetar_estado()
 
62
 
63
  # --- FUNÇÃO PRINCIPAL DO CHATBOT ---
64
  def handle_chat(mensagem, historico_chat_gradio):
65
- global estado_pipeline
66
 
67
- estado_pipeline["historico_conversa_gemini"].append({"role": "user", "parts": [mensagem]})
 
68
 
69
- if estado_pipeline["passo_atual"] == "passo_1_analise_primaria":
70
- estado_pipeline["dados_coletados"]["duvida_inicial"] = mensagem
 
71
 
 
72
  prompt_completo = f"""
73
  {PROMPT_SISTEMA}
 
74
  ---
75
- **Estado Atual da Pipeline:**
76
- {json.dumps(estado_pipeline, indent=2)}
 
 
 
 
77
  ---
78
- **Instrução Final:** Baseado no estado e no histórico, gere o próximo JSON de ação.
 
79
  """
80
 
81
  try:
82
  response = model.generate_content(prompt_completo)
83
 
 
84
  resposta_texto = response.text.strip().replace("```json", "").replace("```", "")
85
  decisao_json = json.loads(resposta_texto)
86
 
87
- estado_pipeline["passo_atual"] = decisao_json.get("proximo_passo")
88
- estado_pipeline["dados_coletados"] = decisao_json.get("dados_coletados", estado_pipeline["dados_coletados"])
89
 
 
90
  if decisao_json.get("resposta_final"):
91
  resposta_para_usuario = decisao_json["resposta_final"]
92
- estado_pipeline = resetar_estado()
 
 
 
93
  return resposta_para_usuario
94
 
95
  elif decisao_json.get("pergunta_para_usuario"):
96
  resposta_para_usuario = decisao_json["pergunta_para_usuario"]
 
97
  return resposta_para_usuario
98
 
99
  else:
 
100
  return "Ocorreu um erro no meu raciocínio. Poderia tentar reformular sua pergunta?"
101
 
102
  except (json.JSONDecodeError, AttributeError, Exception) as e:
@@ -105,19 +149,27 @@ def handle_chat(mensagem, historico_chat_gradio):
105
  print(f"Resposta recebida: {response.text}")
106
  except:
107
  print("Não foi possível extrair o texto da resposta.")
108
- return "Desculpe, tive um problema ao processar sua solicitação. Vamos tentar novamente."
109
 
110
 
111
  # --- INTERFACE GRADIO ---
 
 
 
 
 
 
 
112
  iface = gr.ChatInterface(
113
  fn=handle_chat,
114
- title="🤖 Protótipo de IA com Raciocínio Estruturado",
115
- description="Este chatbot segue um protocolo interno de 5 passos para analisar sua dúvida antes de responder. A conversa é guiada por um modelo Gemini que gera instruções em JSON.",
116
  chatbot=gr.Chatbot(height=500),
117
  textbox=gr.Textbox(placeholder="Qual é a sua dúvida?", container=False, scale=7),
118
  )
 
119
 
120
  if __name__ == "__main__":
121
  iface.launch()
122
 
123
- # --- FIM DO CÓDIGO FINAL CORRIGIDO ---
 
1
+ # --- INÍCIO DO CÓDIGO FINAL ---
2
 
3
  import gradio as gr
4
  import os
 
9
  api_key = os.getenv("GOOGLE_API_KEY")
10
  if not api_key:
11
  # ⚠️ SUBSTITUA PELA SUA CHAVE REAL ANTES DE EXECUTAR
12
+ api_key = "SUA_API_KEY_AQUI"
13
 
14
  genai.configure(api_key=api_key)
15
+ model = genai.GenerativeModel('gemini-1.5-pro-latest')
16
 
17
+ # --- PROMPT DE SISTEMA MESTRE (SEGUINDO SEU PROTOCOLO) ---
 
 
 
18
  PROMPT_SISTEMA = """
19
+ Você é um especialista em análise de intenções que opera sob um protocolo de 5 passos.
20
+ Sua função é conduzir uma conversa para entender completamente a dúvida de um usuário ANTES de respondê-la.
21
+ Sua SAÍDA DEVE SER SEMPRE E SOMENTE um objeto JSON válido.
22
+
23
+ **PROTOCOLO DE EXECUÇÃO OBRIGATÓRIO:**
24
+
25
+ Analise o `estado_pipeline` atual e o `historico_conversa`. Decida qual passo executar. Sua resposta em JSON deve conter o estado COMPLETAMENTE ATUALIZADO.
26
+
27
+ ---
28
+ **Passo 1: Análise Primária (Clareza)**
29
+ - **Meta:** A dúvida é compreensível?
30
+ - **Ação:** Analise o `duvida_inicial`.
31
+ - **Decisão:**
32
+ - Se a clareza for 'baixa' (ex: "flibbertigibbet quântico"), sua resposta JSON DEVE conter: `{"proximo_passo": "aguardando_usuario", "pergunta_para_usuario": "Interessante! O termo que você usou não é padrão. Poderia me dar mais contexto?", ...}`.
33
+ - Se a clareza for 'media' ou 'alta', atualize `estado.clareza.confianca` para 'alta' e defina `proximo_passo` como `"passo_2_proposito"`.
34
+
35
+ ---
36
+ **Passo 2: Análise de Propósito (Para Que)**
37
+ - **Meta:** Para qual fim a resposta servirá?
38
+ - **Ação:** Analise o histórico para inferir o objetivo prático (`para_que`).
39
+ - **Decisão:**
40
+ - Se a confiança for 'baixa' (ex: uma pergunta ampla como "o que é asteroide?"), sua resposta JSON DEVE conter: `{"proximo_passo": "aguardando_usuario", "pergunta_para_usuario": "Claro! Para te dar a melhor resposta, qual o seu objetivo? Você está estudando, curioso, escrevendo uma história...?", ...}`.
41
+ - Se a confiança for 'media' ou 'alta', preencha `estado.proposito.valor` e `estado.proposito.confianca`, e defina `proximo_passo` como `"passo_3_motivacao"`.
42
+
43
+ ---
44
+ **Passo 3: Análise de Motivação (Porquê) e Interesses**
45
+ - **Meta:** Por que o usuário precisa da resposta agora?
46
+ - **Ação:** Analise o histórico para inferir a motivação (`porque`).
47
+ - **Decisão:**
48
+ - Se a confiança for 'baixa', sua resposta JSON DEVE conter: `{"proximo_passo": "aguardando_usuario", "pergunta_para_usuario": "Entendi. E o que te despertou esse interesse agora? Algo específico que você viu ou ouviu?", ...}`.
49
+ - Se a confiança for 'media' ou 'alta', preencha `estado.motivacao.valor` e `estado.motivacao.confianca`, e defina `proximo_passo` como `"passo_4_coerencia"`.
50
+
51
+ ---
52
+ **Passo 4: Análise de Coerência**
53
+ - **Meta:** As informações coletadas fazem sentido juntas?
54
+ - **Ação:** Revise `clareza`, `proposito` e `motivacao` em busca de contradições ou lacunas.
55
+ - **Decisão:**
56
+ - Se a coerência for 'baixa' (ex: propósito é 'estudo', motivação é 'medo de impacto'), formule uma pergunta para resolver a incerteza. Ex: `{"pergunta_para_usuario": "Ok, entendi que é para estudo, mas notei uma preocupação. Você gostaria de focar nos aspectos científicos ou também nos riscos de impacto?", ...}` e `proximo_passo` como `aguardando_usuario`.
57
+ - Se a coerência for 'alta', atualize `estado.coerencia.confianca` e defina `proximo_passo` como `"passo_5_resposta_final"`.
58
+
59
+ ---
60
+ **Passo 5: Geração da Resposta Final**
61
+ - **Meta:** Tenho tudo para dar uma resposta completa e personalizada.
62
+ - **Ação:** Verifique se todos os passos anteriores têm confiança 'media' ou 'alta'.
63
+ - **Decisão:**
64
+ - Se sim, construa uma resposta final detalhada, adaptada ao propósito e motivação do usuário. Coloque essa resposta no campo `"resposta_final"` do JSON. Defina `"proximo_passo"` como `"concluido"`.
65
+ - Se não, volte ao passo com a confiança mais baixa e formule uma nova pergunta.
66
+
67
+ **ESTRUTURA JSON DE SAÍDA OBRIGATÓRIA:**
68
  {
69
+ "raciocinio_do_passo": "Sua breve justificativa interna para a decisão tomada.",
70
+ "proximo_passo": "string", // "passo_2_proposito", "passo_3_motivacao", "aguardando_usuario", "concluido", etc.
71
+ "pergunta_para_usuario": "string | null", // A pergunta exata a ser feita ao usuário, se houver.
72
+ "estado_pipeline_atualizado": { ... }, // O objeto de estado completo e atualizado.
73
+ "resposta_final": "string | null" // A resposta final, apenas no Passo 5.
 
 
 
 
74
  }
 
 
 
 
75
  """
76
 
77
  # --- GERENCIAMENTO DE ESTADO ---
78
  def resetar_estado():
79
  return {
80
+ "passo_atual": "passo_1_clareza",
81
+ "duvida_inicial": None,
82
+ "clareza": {"confianca": "baixa"},
83
+ "proposito": {"valor": None, "confianca": "baixa"},
84
+ "motivacao": {"valor": None, "confianca": "baixa"},
85
+ "coerencia": {"confianca": "baixa"}
 
86
  }
87
 
88
+ estado_pipeline_global = resetar_estado()
89
+ historico_conversa_global = []
90
 
91
  # --- FUNÇÃO PRINCIPAL DO CHATBOT ---
92
  def handle_chat(mensagem, historico_chat_gradio):
93
+ global estado_pipeline_global, historico_conversa_global
94
 
95
+ # Adiciona a mensagem atual ao histórico da conversa
96
+ historico_conversa_global.append({"role": "user", "content": mensagem})
97
 
98
+ # Se for a primeira mensagem, define a dúvida inicial no estado
99
+ if estado_pipeline_global["duvida_inicial"] is None:
100
+ estado_pipeline_global["duvida_inicial"] = mensagem
101
 
102
+ # Constrói o prompt para o Gemini
103
  prompt_completo = f"""
104
  {PROMPT_SISTEMA}
105
+
106
  ---
107
+ **HISTÓRICO DA CONVERSA ATÉ AGORA:**
108
+ {json.dumps(historico_conversa_global, indent=2)}
109
+
110
+ ---
111
+ **ESTADO ATUAL DA PIPELINE:**
112
+ {json.dumps(estado_pipeline_global, indent=2)}
113
  ---
114
+
115
+ **Instrução Final:** Baseado no estado e no histórico, execute o próximo passo do protocolo e gere o JSON de saída correspondente.
116
  """
117
 
118
  try:
119
  response = model.generate_content(prompt_completo)
120
 
121
+ # Limpa e extrai o JSON da resposta
122
  resposta_texto = response.text.strip().replace("```json", "").replace("```", "")
123
  decisao_json = json.loads(resposta_texto)
124
 
125
+ # O LLM é a fonte da verdade: atualiza o estado global com o que foi retornado
126
+ estado_pipeline_global = decisao_json.get("estado_pipeline_atualizado", estado_pipeline_global)
127
 
128
+ # Decide o que mostrar ao usuário
129
  if decisao_json.get("resposta_final"):
130
  resposta_para_usuario = decisao_json["resposta_final"]
131
+ historico_conversa_global.append({"role": "model", "content": resposta_para_usuario})
132
+ # Reseta tudo para a próxima conversa
133
+ estado_pipeline_global = resetar_estado()
134
+ historico_conversa_global = []
135
  return resposta_para_usuario
136
 
137
  elif decisao_json.get("pergunta_para_usuario"):
138
  resposta_para_usuario = decisao_json["pergunta_para_usuario"]
139
+ historico_conversa_global.append({"role": "model", "content": resposta_para_usuario})
140
  return resposta_para_usuario
141
 
142
  else:
143
+ # Caso de erro onde o JSON é válido mas não tem ação para o usuário
144
  return "Ocorreu um erro no meu raciocínio. Poderia tentar reformular sua pergunta?"
145
 
146
  except (json.JSONDecodeError, AttributeError, Exception) as e:
 
149
  print(f"Resposta recebida: {response.text}")
150
  except:
151
  print("Não foi possível extrair o texto da resposta.")
152
+ return "Desculpe, tive um problema técnico ao processar sua solicitação. Por favor, tente novamente."
153
 
154
 
155
  # --- INTERFACE GRADIO ---
156
+ def on_clear_chat():
157
+ """Função para ser chamada quando o botão 'Clear' do Gradio é pressionado."""
158
+ global estado_pipeline_global, historico_conversa_global
159
+ estado_pipeline_global = resetar_estado()
160
+ historico_conversa_global = []
161
+ print("Chat e estado resetados.")
162
+
163
  iface = gr.ChatInterface(
164
  fn=handle_chat,
165
+ title="🤖 Protótipo de IA com Protocolo de Raciocínio",
166
+ description="Este chatbot segue um protocolo rigoroso para entender sua dúvida antes de responder. A conversa é guiada por um LLM que gerencia o estado do fluxo.",
167
  chatbot=gr.Chatbot(height=500),
168
  textbox=gr.Textbox(placeholder="Qual é a sua dúvida?", container=False, scale=7),
169
  )
170
+ iface.clear_btn.click(on_clear_chat) # Garante que o estado interno seja limpo junto com o chat
171
 
172
  if __name__ == "__main__":
173
  iface.launch()
174
 
175
+ # --- FIM DO CÓDIGO FINAL ---