Spaces:
Sleeping
Sleeping
| # --- INÍCIO DO CÓDIGO COMPLETO E FINAL --- | |
| import gradio as gr | |
| import os | |
| import google.generativeai as genai | |
| import json | |
| # --- 1. CARREGAMENTO DO CONTEXTO FILOSÓFICO IMUTÁVEL --- | |
| def carregar_contexto_filosofico(caminho_arquivo="epct0.md"): | |
| """Lê o arquivo .md e o retorna como uma string de contexto.""" | |
| try: | |
| with open(caminho_arquivo, 'r', encoding='utf-8') as f: | |
| print(f"Contexto filosófico '{caminho_arquivo}' carregado com sucesso.") | |
| return f.read() | |
| except FileNotFoundError: | |
| print(f"AVISO CRÍTICO: O arquivo de contexto '{caminho_arquivo}' não foi encontrado.") | |
| print("O 'Modo Amigo Sábio' ficará indisponível até que o arquivo seja colocado no mesmo diretório que o script.") | |
| return None | |
| CONTEXTO_EPICTETO = carregar_contexto_filosofico() | |
| # --- 2. CONFIGURAÇÃO DAS APIS GEMINI --- | |
| api_key = os.getenv("GOOGLE_API_KEY") | |
| if not api_key: | |
| # ⚠️ SUBSTITUA "SUA_API_KEY_AQUI" PELA SUA CHAVE REAL ANTES DE EXECUTAR | |
| api_key = "SUA_API_KEY_AQUI" | |
| genai.configure(api_key=api_key) | |
| # Inicializa os dois modelos separadamente | |
| counselor_model = genai.GenerativeModel('gemini-flash-latest') | |
| supervisor_model = genai.GenerativeModel('gemini-flash-latest') | |
| # --- 3. DEFINIÇÃO DOS PROMPTS --- | |
| # A NOVA DIRETIVA, FOCADA NA PERSONA | |
| DIRETIVA_AMIGO_SABIO = """ | |
| **AVISO: MODO AMIGO SÁBIO ATIVADO.** | |
| Sua identidade mudou. Você não é um oráculo ou um professor de filosofia. Você é um **amigo**. Un amigo que por acaso tem uma bússola interna muito bem calibrada, baseada nos princípios do `epct0.md`. Sua meta é conversar, não lecionar. | |
| **SUA NOVA PERSONALIDADE E MODO DE OPERAR:** | |
| 1. **Tom Conversacional, Não de Oráculo:** Sua linguagem deve ser natural, calorosa e acessível. Use "a gente", "nós", "vamos pensar nisso juntos". Mostre empatia primeiro ("Nossa, isso parece muito frustrante..." ou "Eu imagino como isso deve ser complicado..."). | |
| 2. **Seja um Parceiro de Reflexão:** Não dê respostas prontas. Em vez disso, faça perguntas que guiem a reflexão. Sua função é ajudar o usuário a encontrar as próprias respostas. Mostre vulnerabilidade e dúvida quando apropriado ("Sabe, essa é uma pergunta difícil..." ou "Por um lado, eu penso que..., mas por outro... o que você acha?"). | |
| 3. **Filosofia como Bússola, Não como Manual:** Os princípios do `epct0.md` são sua bússola interna secreta. Eles guiam a *direção* das suas perguntas, mas **NUNCA DEVEM SER MENCIONADOS OU CITADOS DIRETAMENTE.** | |
| - **Em vez de dizer:** "Você precisa focar no que controla (Dicotomia do Controle)." | |
| - **Diga (como um amigo):** "Ok, essa situação toda parece um emaranhado gigante. Que tal a gente tentar separar as coisas? Quais pedacinhos disso aqui a gente consegue de fato mudar, e quais são aqueles que, por mais que a gente se irrite, estão fora do nosso alcance agora?" | |
| 4. **Use Humor e Leveza (Quando Apropriado):** Um amigo sabe quando quebrar a tensão. Se o assunto não for pesado demais, uma observação leve ou uma analogia divertida pode ser mais útil que um conselho solene. | |
| 5. **Foco no Empoderamento:** Seu objetivo final é fazer o usuário sentir que ele tem o poder de lidar com a situação. Toda a conversa deve convergir para a agência e a capacidade de escolha do usuário. | |
| **REGRA DE OURO:** Se sua resposta soa como algo que um professor diria em uma palestra, apague e reescreva. Sua resposta deve soar como algo que um amigo diria enquanto toma um café com você. O protocolo de 6 passos é sua ferramenta para entender o problema, mas esta persona é quem conduz a conversa. | |
| """ | |
| PROMPT_SISTEMA_METODOLOGICO = """ | |
| Você é um especialista em análise de intenções que opera sob um protocolo de 6 passos. | |
| Sua função é conduzir uma conversa para entender 100% da dúvida de um usuário ANTES de respondê-la. | |
| Sua SAÍDA DEVE SER SEMPRE E SOMENTE um objeto JSON válido. | |
| **PROTOCOLO DE EXECUÇÃO OBRIGATÓRIO:** | |
| Analise o `estado_pipeline` atual e o `historico_conversa`. Decida qual passo executar. Sua resposta em JSON deve conter o estado COMPLETAMENTE ATUALIZADO. | |
| --- | |
| **Passo 1: Análise Primária (Clareza)** | |
| - **Decisão:** Se a clareza for 'baixa', pergunte. Senão, `proximo_passo` = `"passo_2_proposito"`. | |
| --- | |
| **Passo 2: Análise de Propósito (Para Que)** | |
| - **Decisão:** Se a confiança for 'baixa', formule uma pergunta de esclarecimento conversacional, mostrando que entendeu o tópico geral. Senão, `proximo_passo` = `"passo_3_motivacao"`. | |
| --- | |
| **Passo 3: Análise de Motivação (Porquê)** | |
| - **Decisão:** Se a confiança for 'baixa', formule uma pergunta de esclarecimento conversacional. Senão, `proximo_passo` = `"passo_4_coerencia"`. | |
| --- | |
| **Passo 4: Análise de Coerência** | |
| - **Decisão:** Se a coerência for 'baixa', pergunte para resolver a contradição. Senão, `proximo_passo` = `"passo_5_ambiguidade"`. | |
| --- | |
| **Passo 5: Análise de Ambiguidade de Cenário (Validação de Perspectiva)** | |
| - **Meta:** A dúvida pode ter múltiplas respostas válidas dependendo de uma perspectiva oculta? | |
| - **Decisão:** | |
| - Se existem vários cenários válidos, sua tarefa é **formular uma pergunta de esclarecimento conversacional e aberta.** | |
| - **REGRA DE OURO PARA PERGUNTAS:** Suas perguntas NÃO devem ser menus ou listas fechadas (ex: "A ou B?"). Elas DEVEM ser humanizadas seguindo esta estrutura: | |
| 1. **Afirmação de Engajamento:** Comece com uma frase curta que valide o interesse do usuário (ex: "Entendido, esse é um tema fascinante!"). | |
| 2. **Ponte de Entendimento:** Demonstre que você entendeu o que foi dito, apresentando os cenários como uma exploração conjunta. | |
| 3. **Pergunta Aberta:** Termine com uma pergunta que convide o usuário a escolher um caminho de forma natural. | |
| - **Exemplo de Pergunta Conversacional Perfeita:** | |
| Dúvida: "Me fale sobre carros". A pergunta no campo `pergunta_para_usuario` DEVE ser algo como: | |
| *"Sério, interessante, eu acho esse mundo fascinante! Os detalhes da engenharia são curiosos. Veja, podemos explorar isso por um lado, analisando o chassi, que é como o esqueleto que dá estrutura e segurança. E também do outro, o motor, que é o coração que dá potência ao carro. Qual desses detalhes da engenharia te desperta mais curiosidade agora?"* | |
| - Defina `proximo_passo` como `"aguardando_usuario"`. | |
| - Se a confiança em um único cenário for 'alta', defina `proximo_passo` como `"passo_6_resposta_final"`. | |
| --- | |
| **Passo 6: Geração da Resposta Final** | |
| - **Meta:** Tenho 100% de clareza para dar uma resposta definitiva. | |
| - **Decisão:** Se todos os passos têm confiança 'alta', construa a resposta final. Coloque-a em `"resposta_final"`. Defina `proximo_passo` como `"concluido"`. | |
| --- | |
| **ESTRUTURA JSON DE SAÍDA OBRIGATÓRIA:** | |
| { | |
| "raciocinio_do_passo": "Sua breve justificativa interna.", "proximo_passo": "string", | |
| "pergunta_para_usuario": "string | null", | |
| "estado_pipeline_atualizado": { | |
| "passo_atual": "string", "duvida_inicial": "string | null", "clareza": {"confianca": "baixa|media|alta"}, | |
| "proposito": {"valor": "string | null", "confianca": "baixa|media|alta"}, "motivacao": {"valor": "string | null", "confianca": "baixa|media|alta"}, | |
| "coerencia": {"confianca": "baixa|media|alta"}, "ambiguidade": {"confianca": "baixa|media|alta"} | |
| }, | |
| "resposta_final": "string | null" | |
| } | |
| """ | |
| PROMPT_SUPERVISOR = """ | |
| Você é um Supervisor de IA, um fact-checker rigoroso e objetivo. Sua única tarefa é analisar o texto fornecido abaixo em busca de incorreções factuais. | |
| - **Use sua ferramenta de busca (`GoogleSearch`)** para verificar nomes, datas, estatísticas, conceitos científicos e outras alegações factuais. | |
| - Você NÃO analisa opiniões, conselhos filosóficos ou a estrutura da resposta. Apenas fatos. | |
| - Se você encontrar uma ou mais divergências factuais com confiança média ou alta, forneça uma correção clara e concisa em formato de lista. | |
| - **Se você NÃO encontrar nenhuma divergência factual, você DEVE responder com a string exata `NO_DIVERGENCE` e absolutamente mais nada.** | |
| """ | |
| # --- 4. GERENCIAMENTO DE ESTADO E FUNÇÕES AUXILIARES --- | |
| def resetar_estado(): | |
| """Inicializa ou reseta o dicionário de estado da pipeline.""" | |
| print("Resetando o estado da pipeline para uma nova conversa.") | |
| return { | |
| "passo_atual": "passo_1_clareza", "duvida_inicial": None, | |
| "clareza": {"confianca": "baixa"}, "proposito": {"valor": None, "confianca": "baixa"}, | |
| "motivacao": {"valor": None, "confianca": "baixa"}, "coerencia": {"confianca": "baixa"}, | |
| "ambiguidade": {"confianca": "baixa"} | |
| } | |
| estado_pipeline_global = resetar_estado() | |
| historico_conversa_llm = [] | |
| def run_supervisor(text_to_check): | |
| """Aciona o modelo Supervisor para verificar os fatos de um texto.""" | |
| print("--- Acionando o Supervisor para verificação de fatos ---") | |
| try: | |
| full_prompt = f"{PROMPT_SUPERVISOR}\n\n--- TEXTO PARA ANÁLISE ---\n{text_to_check}" | |
| response = supervisor_model.generate_content(full_prompt) | |
| if "NO_DIVERGENCE" in response.text: | |
| print("Supervisor não encontrou divergências factuais.") | |
| return None | |
| else: | |
| print(f"Supervisor encontrou uma divergência: {response.text}") | |
| return response.text | |
| except Exception as e: | |
| print(f"Erro durante a execução do Supervisor: {e}") | |
| return None | |
| # --- 5. FUNÇÃO PRINCIPAL DO CHATBOT --- | |
| def handle_chat(mensagem, historico_chat_gradio, modo_sabio, modo_supervisor): | |
| global estado_pipeline_global, historico_conversa_llm | |
| if not historico_chat_gradio: | |
| estado_pipeline_global = resetar_estado() | |
| historico_conversa_llm = [] | |
| historico_conversa_llm.append({"role": "user", "parts": [mensagem]}) | |
| if estado_pipeline_global["duvida_inicial"] is None: | |
| estado_pipeline_global["duvida_inicial"] = mensagem | |
| prompt_base = PROMPT_SISTEMA_METODOLOGICO | |
| if modo_sabio and CONTEXTO_EPICTETO: | |
| prompt_base = f"""{DIRETIVA_AMIGO_SABIO} | |
| --- CONTEXTO FILOSÓFICO PARA SUA REFLEXÃO INTERNA --- | |
| {CONTEXTO_EPICTETO} | |
| --- | |
| Agora, aplique esta persona e seus princípios ao executar a seguinte metodologia de análise: | |
| {PROMPT_SISTEMA_METODOLOGICO} | |
| """ | |
| elif modo_sabio and not CONTEXTO_EPICTETO: | |
| return "O 'Modo Amigo Sábio' não pôde ser ativado porque o arquivo `epct0.md` não foi encontrado. Operando no modo padrão." | |
| prompt_completo = f""" | |
| {prompt_base} | |
| --- | |
| **HISTÓRICO DA CONVERSA:** | |
| {json.dumps(historico_conversa_llm, indent=2)} | |
| --- | |
| **ESTADO ATUAL DA ANÁLISE:** | |
| {json.dumps(estado_pipeline_global, indent=2)} | |
| --- | |
| **Instrução:** Aplique suas diretrizes ao estado e histórico atuais e gere o próximo JSON de ação. | |
| """ | |
| try: | |
| response_counselor = counselor_model.generate_content(prompt_completo) | |
| resposta_texto = response_counselor.text.strip().replace("```json", "").replace("```", "") | |
| decisao_json = json.loads(resposta_texto) | |
| estado_pipeline_global = decisao_json.get("estado_pipeline_atualizado", estado_pipeline_global) | |
| resposta_para_usuario = None | |
| if decisao_json.get("resposta_final"): | |
| resposta_para_usuario = decisao_json["resposta_final"] | |
| elif decisao_json.get("pergunta_para_usuario"): | |
| resposta_para_usuario = decisao_json["pergunta_para_usuario"] | |
| else: | |
| resposta_para_usuario = "Ocorreu um erro no meu raciocínio. Poderia tentar reformular?" | |
| historico_conversa_llm.append({"role": "model", "parts": [resposta_para_usuario]}) | |
| if modo_supervisor and decisao_json.get("resposta_final"): | |
| feedback_supervisor = run_supervisor(resposta_para_usuario) | |
| if feedback_supervisor: | |
| resposta_para_usuario += f"\n\n---\n\n**🔍 Análise do Supervisor:**\n{feedback_supervisor}" | |
| return resposta_para_usuario | |
| except (json.JSONDecodeError, AttributeError, Exception) as e: | |
| print(f"Erro ao processar resposta da API: {e}") | |
| try: | |
| print(f"Resposta recebida (pode ter causado o erro): {response_counselor.text}") | |
| except: | |
| print("Não foi possível extrair o texto da resposta do erro.") | |
| return "Desculpe, tive um problema técnico. Por favor, clique no botão 'Limpar' e tente novamente." | |
| # --- 6. INTERFACE GRÁFICA COM GRADIO --- | |
| iface = gr.ChatInterface( | |
| fn=handle_chat, | |
| title="🤖 Parceiro de Raciocínio v8 (Amigo Sábio)", | |
| description="Vamos conversar. Me conte o que está na sua cabeça. Se quiser uma perspectiva diferente para refletir, ative o 'Modo Amigo Sábio'.", | |
| chatbot=gr.Chatbot(height=600, label="Diálogo"), | |
| textbox=gr.Textbox(placeholder="E aí, como você está?", container=False, scale=7), | |
| additional_inputs=[ | |
| gr.Checkbox(label="🧘 Ativar Modo Amigo Sábio", value=True), | |
| gr.Checkbox(label="🔍 Ativar Modo Supervisor (Verificação de Fatos)", value=True) | |
| ], | |
| theme="soft", | |
| examples=[ | |
| ["o que é violência domestica?"], | |
| ["Estou me sentindo totalmente desmotivado."], | |
| ["Como posso parar de me preocupar com o que os outros pensam?"] | |
| ], | |
| cache_examples=False | |
| ) | |
| # --- 7. EXECUÇÃO DA APLICAÇÃO --- | |
| if __name__ == "__main__": | |
| iface.launch() | |
| # --- FIM DO CÓDIGO --- |