caarleexx commited on
Commit
e1c686a
·
verified ·
1 Parent(s): 851808a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -46
app.py CHANGED
@@ -1,81 +1,88 @@
1
- # --- INÍCIO DO CÓDIGO CORRIGIDO E FINAL ---
2
 
3
  import gradio as gr
4
  import os
5
  import google.generativeai as genai
6
  import json
7
 
8
- # --- CONFIGURAÇÃO DA API GEMINI ---
 
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-2.5-pro')
16
 
17
- # --- PROMPT DE SISTEMA MESTRE ---
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', 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', 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`.
 
 
 
 
 
55
  - **Decisão:**
56
- - Se a coerência for 'baixa', formule uma pergunta para resolver a incerteza e defina `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 adaptada. 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.",
70
  "proximo_passo": "string",
71
  "pergunta_para_usuario": "string | null",
72
- "estado_pipeline_atualizado": { ... },
 
 
 
 
 
 
 
 
73
  "resposta_final": "string | null"
74
  }
75
  """
76
 
77
- # --- GERENCIAMENTO DE ESTADO ---
78
  def resetar_estado():
 
79
  print("Resetando o estado da pipeline para uma nova conversa.")
80
  return {
81
  "passo_atual": "passo_1_clareza",
@@ -83,19 +90,23 @@ def resetar_estado():
83
  "clareza": {"confianca": "baixa"},
84
  "proposito": {"valor": None, "confianca": "baixa"},
85
  "motivacao": {"valor": None, "confianca": "baixa"},
86
- "coerencia": {"confianca": "baixa"}
 
87
  }
88
 
 
89
  estado_pipeline_global = resetar_estado()
90
  historico_conversa_llm = []
91
 
92
- # --- FUNÇÃO PRINCIPAL DO CHATBOT ---
93
  def handle_chat(mensagem, historico_chat_gradio):
 
 
 
 
94
  global estado_pipeline_global, historico_conversa_llm
95
 
96
- # CORREÇÃO PRINCIPAL: Detecta se é o início de uma conversa.
97
- # O histórico do Gradio estar vazio significa que o usuário acabou de abrir
98
- # a página ou clicou em "Clear".
99
  if not historico_chat_gradio:
100
  estado_pipeline_global = resetar_estado()
101
  historico_conversa_llm = []
@@ -105,6 +116,7 @@ def handle_chat(mensagem, historico_chat_gradio):
105
  if estado_pipeline_global["duvida_inicial"] is None:
106
  estado_pipeline_global["duvida_inicial"] = mensagem
107
 
 
108
  prompt_completo = f"""
109
  {PROMPT_SISTEMA}
110
  ---
@@ -117,14 +129,18 @@ def handle_chat(mensagem, historico_chat_gradio):
117
  **Instrução Final:** Baseado no estado e no histórico, execute o próximo passo do protocolo e gere o JSON de saída.
118
  """
119
 
120
- if True:
121
-
122
  response = model.generate_content(prompt_completo)
 
 
123
  resposta_texto = response.text.strip().replace("```json", "").replace("```", "")
124
  decisao_json = json.loads(resposta_texto)
125
 
 
126
  estado_pipeline_global = decisao_json.get("estado_pipeline_atualizado", estado_pipeline_global)
127
 
 
128
  if decisao_json.get("resposta_final"):
129
  resposta_para_usuario = decisao_json["resposta_final"]
130
  historico_conversa_llm.append({"role": "model", "parts": [resposta_para_usuario]})
@@ -136,20 +152,30 @@ def handle_chat(mensagem, historico_chat_gradio):
136
  return resposta_para_usuario
137
 
138
  else:
 
139
  return "Ocorreu um erro no meu raciocínio. Poderia tentar reformular?"
140
 
141
-
142
- # --- INTERFACE GRADIO ---
143
- # REMOVIDO: A função on_clear_chat e a linha iface.clear_btn.click não são mais necessárias.
 
 
 
 
 
 
144
  iface = gr.ChatInterface(
145
  fn=handle_chat,
146
- title="🤖 Protótipo de IA com Protocolo de Raciocínio",
147
- 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.",
148
- chatbot=gr.Chatbot(height=500),
149
  textbox=gr.Textbox(placeholder="Qual é a sua dúvida?", container=False, scale=7),
 
 
150
  )
151
 
 
152
  if __name__ == "__main__":
153
  iface.launch()
154
 
155
- # --- FIM DO CÓDIGO CORRIGIDO E FINAL ---
 
1
+ # --- INÍCIO DO CÓDIGO COMPLETO E FINAL ---
2
 
3
  import gradio as gr
4
  import os
5
  import google.generativeai as genai
6
  import json
7
 
8
+ # --- 1. CONFIGURAÇÃO DA API GEMINI ---
9
+ # É mais seguro usar variáveis de ambiente, mas para testes, você pode inserir a chave aqui.
10
  api_key = os.getenv("GOOGLE_API_KEY")
11
  if not api_key:
12
+ # ⚠️ SUBSTITUA "SUA_API_KEY_AQUI" PELA SUA CHAVE REAL ANTES DE EXECUTAR
13
  api_key = "SUA_API_KEY_AQUI"
14
 
15
  genai.configure(api_key=api_key)
16
+ model = genai.GenerativeModel('gemini-2.0-pro')
17
 
18
+ # --- 2. PROMPT DE SISTEMA MESTRE (O "CÉREBRO" DO PROTOCOLO) ---
19
  PROMPT_SISTEMA = """
20
+ Você é um especialista em análise de intenções que opera sob um protocolo de 6 passos.
21
+ Sua função é conduzir uma conversa para entender 100% da dúvida de um usuário ANTES de respondê-la.
22
+ Sua SAÍDA DEVE SER SEMPRE E SOMENTE um objeto JSON válido, sem nenhum texto adicional.
23
 
24
  **PROTOCOLO DE EXECUÇÃO OBRIGATÓRIO:**
25
 
26
+ Analise o `estado_pipeline` atual e o `historico_conversa`. Decida qual passo executar. Sua resposta em JSON deve conter o estado COMPLETAMENTE ATUALIZADO da pipeline.
27
 
28
  ---
29
  **Passo 1: Análise Primária (Clareza)**
30
  - **Meta:** A dúvida é compreensível?
31
+ - **Decisão:** Se a clareza for 'baixa', pergunte por mais contexto. Senão, defina `proximo_passo` como `"passo_2_proposito"`.
 
 
 
32
 
33
  ---
34
  **Passo 2: Análise de Propósito (Para Que)**
35
  - **Meta:** Para qual fim a resposta servirá?
36
+ - **Decisão:** Se a confiança no propósito for 'baixa', pergunte sobre o objetivo. Senão, defina `proximo_passo` como `"passo_3_motivacao"`.
 
 
 
37
 
38
  ---
39
  **Passo 3: Análise de Motivação (Porquê) e Interesses**
40
  - **Meta:** Por que o usuário precisa da resposta agora?
41
+ - **Decisão:** Se a confiança na motivação for 'baixa', pergunte sobre o que despertou o interesse. Senão, defina `proximo_passo` como `"passo_4_coerencia"`.
 
 
 
42
 
43
  ---
44
  **Passo 4: Análise de Coerência**
45
  - **Meta:** As informações coletadas fazem sentido juntas?
46
+ - **Decisão:** Se a coerência for 'baixa', pergunte para resolver a contradição. Senão, defina `proximo_passo` como `"passo_5_ambiguidade"`.
47
+
48
+ ---
49
+ **Passo 5: Análise de Ambiguidade de Cenário (Validação de Perspectiva)**
50
+ - **Meta:** A dúvida pode ter múltiplas respostas válidas dependendo de uma perspectiva oculta?
51
+ - **Ação:** Revise o contexto completo. Pense se a resposta muda se o usuário for um estudante, um profissional, um entusiasta, etc.
52
  - **Decisão:**
53
+ - Se existem vários cenários de resposta válidos (confiança 'baixa'), formule uma pergunta que force o usuário a escolher uma perspectiva. Defina `proximo_passo` como `"aguardando_usuario"`.
54
+ - **Exemplo:** Se a dúvida é "Como otimizar um banco de dados?", pergunte: "Você está focando em otimização para velocidade de leitura, redução de custos de armazenamento, ou para escalabilidade?"
55
+ - Se o cenário de resposta é único e claro (confiança 'alta'), defina `proximo_passo` como `"passo_6_resposta_final"`.
56
 
57
  ---
58
+ **Passo 6: Geração da Resposta Final**
59
+ - **Meta:** Tenho 100% de clareza para dar uma resposta definitiva e sem subjetividade.
60
+ - **Ação:** Verifique se TODOS os passos anteriores têm confiança 'alta'.
61
  - **Decisão:**
62
+ - Se sim, construa a resposta final, objetiva e completa, adaptada a todo o contexto coletado. Coloque-a em `"resposta_final"`. Defina `"proximo_passo"` como `"concluido"`.
63
+ - Se não, volte ao passo com a confiança mais baixa e reformule a pergunta.
64
 
65
  **ESTRUTURA JSON DE SAÍDA OBRIGATÓRIA:**
66
  {
67
+ "raciocinio_do_passo": "Sua breve justificativa interna para a decisão tomada.",
68
  "proximo_passo": "string",
69
  "pergunta_para_usuario": "string | null",
70
+ "estado_pipeline_atualizado": {
71
+ "passo_atual": "string",
72
+ "duvida_inicial": "string | null",
73
+ "clareza": {"confianca": "baixa|media|alta"},
74
+ "proposito": {"valor": "string | null", "confianca": "baixa|media|alta"},
75
+ "motivacao": {"valor": "string | null", "confianca": "baixa|media|alta"},
76
+ "coerencia": {"confianca": "baixa|media|alta"},
77
+ "ambiguidade": {"confianca": "baixa|media|alta"}
78
+ },
79
  "resposta_final": "string | null"
80
  }
81
  """
82
 
83
+ # --- 3. GERENCIAMENTO DE ESTADO ---
84
  def resetar_estado():
85
+ """Inicializa ou reseta o dicionário de estado da pipeline."""
86
  print("Resetando o estado da pipeline para uma nova conversa.")
87
  return {
88
  "passo_atual": "passo_1_clareza",
 
90
  "clareza": {"confianca": "baixa"},
91
  "proposito": {"valor": None, "confianca": "baixa"},
92
  "motivacao": {"valor": None, "confianca": "baixa"},
93
+ "coerencia": {"confianca": "baixa"},
94
+ "ambiguidade": {"confianca": "baixa"}
95
  }
96
 
97
+ # Variáveis globais para manter o estado e o histórico durante a sessão
98
  estado_pipeline_global = resetar_estado()
99
  historico_conversa_llm = []
100
 
101
+ # --- 4. FUNÇÃO PRINCIPAL DO CHATBOT ---
102
  def handle_chat(mensagem, historico_chat_gradio):
103
+ """
104
+ Esta função é chamada a cada mensagem do usuário.
105
+ Ela gerencia o estado, constrói o prompt, chama a API e retorna a resposta.
106
+ """
107
  global estado_pipeline_global, historico_conversa_llm
108
 
109
+ # Detecta o início de uma nova conversa (quando a UI é limpa) e reseta o estado interno.
 
 
110
  if not historico_chat_gradio:
111
  estado_pipeline_global = resetar_estado()
112
  historico_conversa_llm = []
 
116
  if estado_pipeline_global["duvida_inicial"] is None:
117
  estado_pipeline_global["duvida_inicial"] = mensagem
118
 
119
+ # Monta o super-prompt com todas as instruções, o histórico e o estado atual.
120
  prompt_completo = f"""
121
  {PROMPT_SISTEMA}
122
  ---
 
129
  **Instrução Final:** Baseado no estado e no histórico, execute o próximo passo do protocolo e gere o JSON de saída.
130
  """
131
 
132
+ try:
133
+ # Envia a requisição para a API do Gemini
134
  response = model.generate_content(prompt_completo)
135
+
136
+ # Limpa e decodifica a resposta JSON do modelo
137
  resposta_texto = response.text.strip().replace("```json", "").replace("```", "")
138
  decisao_json = json.loads(resposta_texto)
139
 
140
+ # O LLM é a fonte da verdade: o estado local é substituído pelo estado retornado pela API.
141
  estado_pipeline_global = decisao_json.get("estado_pipeline_atualizado", estado_pipeline_global)
142
 
143
+ # Decide o que mostrar ao usuário
144
  if decisao_json.get("resposta_final"):
145
  resposta_para_usuario = decisao_json["resposta_final"]
146
  historico_conversa_llm.append({"role": "model", "parts": [resposta_para_usuario]})
 
152
  return resposta_para_usuario
153
 
154
  else:
155
+ # Fallback para caso o JSON seja válido mas não tenha uma ação clara
156
  return "Ocorreu um erro no meu raciocínio. Poderia tentar reformular?"
157
 
158
+ except (json.JSONDecodeError, AttributeError, Exception) as e:
159
+ print(f"Erro ao processar resposta da API: {e}")
160
+ try:
161
+ print(f"Resposta recebida (pode ter causado o erro): {response.text}")
162
+ except:
163
+ print("Não foi possível extrair o texto da resposta do erro.")
164
+ return "Desculpe, tive um problema técnico. Por favor, clique no botão 'Limpar' e tente novamente."
165
+
166
+ # --- 5. INTERFACE GRÁFICA COM GRADIO ---
167
  iface = gr.ChatInterface(
168
  fn=handle_chat,
169
+ title="🤖 Protótipo de IA com Protocolo de Raciocínio v2",
170
+ description="Este chatbot segue um protocolo de 6 passos para eliminar todas as ambiguidades antes de fornecer uma resposta 100% contextualizada.",
171
+ chatbot=gr.Chatbot(height=600),
172
  textbox=gr.Textbox(placeholder="Qual é a sua dúvida?", container=False, scale=7),
173
+ theme="soft",
174
+ examples=[["O que é um buraco negro?"], ["Como posso investir meu dinheiro?"], ["Me explique a computação quântica."]],
175
  )
176
 
177
+ # --- 6. EXECUÇÃO DA APLICAÇÃO ---
178
  if __name__ == "__main__":
179
  iface.launch()
180
 
181
+ # --- FIM DO CÓDIGO ---```