Spaces:
Running
Running
| # 📚 GUIA DE USO - NOVO SISTEMA DE CONTEXTO ANGOLA + DATETIME | |
| **Versão:** 1.0 | |
| **Data:** 10/04/2026 | |
| **Para:** Desenvolvedores integrando com novo sistema de contexto | |
| --- | |
| ## 🎯 VISÃO GERAL | |
| Este guia explica como usar as **3 novas features** adicionadas ao `config.py`: | |
| 1. **Contexto Padrão Angola** - Sempre que não especificado | |
| 2. **Datetime Compensado** - +1h para ajustar nuvem | |
| 3. **System Prompt Melhorado** - Injeção garantida em todos os provedores | |
| --- | |
| ## 📍 FEATURE 1: CONTEXTO PADRÃO ANGOLA | |
| ### O que é? | |
| Quando Akira não tem informação explícita sobre localização, assume **Angola/Luanda** como padrão. | |
| ### Como Usar: | |
| #### Em `web_search.py`: | |
| ```python | |
| from config import DEFAULT_CONTEXT_COUNTRY, DEFAULT_CONTEXT_CITY | |
| def buscar_noticias(query: str, pais: Optional[str] = None) -> List[str]: | |
| """Busca notícias, com Angola como padrão""" | |
| pais_busca = pais or DEFAULT_CONTEXT_COUNTRY # "Angola" | |
| cidade_busca = DEFAULT_CONTEXT_CITY # "Luanda" | |
| # Construir query com localização | |
| query_final = f"{query} {pais_busca} {cidade_busca}" | |
| # Executar busca... | |
| ``` | |
| #### Em `context_builder.py`: | |
| ```python | |
| from config import DEFAULT_CONTEXT_COUNTRY, DEFAULT_CONTEXT_CITY, DEFAULT_CONTEXT_TIMEZONE | |
| def construir_contexto_usuario(usuario_id: str, conversas: List[dict]) -> dict: | |
| """Constrói contexto com informações de localização""" | |
| contexto = { | |
| "usuario_id": usuario_id, | |
| "pais_padrao": DEFAULT_CONTEXT_COUNTRY, | |
| "cidade_padrao": DEFAULT_CONTEXT_CITY, | |
| "timezone_padrao": DEFAULT_CONTEXT_TIMEZONE, | |
| # ... resto do contexto | |
| } | |
| return contexto | |
| ``` | |
| #### Em `reply_context_handler.py`: | |
| ```python | |
| from config import DEFAULT_CONTEXT_COUNTRY, DEFAULT_CONTEXT_CITY | |
| def processar_pergunta_localizacao(pergunta: str) -> dict: | |
| """Processa perguntas sobre localização/clima/política""" | |
| # Se pergunta não menciona país específico | |
| if "pais" not in pergunta.lower(): | |
| pais = DEFAULT_CONTEXT_COUNTRY # Angola | |
| cidade = DEFAULT_CONTEXT_CITY # Luanda | |
| else: | |
| # Extrair país da pergunta | |
| pais, cidade = extrair_localizacao(pergunta) | |
| return { | |
| "pais": pais, | |
| "cidade": cidade, | |
| "deve_buscar": True | |
| } | |
| ``` | |
| ### Exemplos de Comportamento: | |
| ``` | |
| Usuário: "Qual é o tempo?" | |
| └─ Pais padrão: Angola ✅ | |
| └─ Cidade padrão: Luanda ✅ | |
| └─ Busca: tempo em Luanda | |
| Usuário: "Qual é o tempo em Maputo?" | |
| └─ Pais detectado: Moçambique | |
| └─ Cidade detectada: Maputo | |
| └─ Busca: tempo em Maputo (respeita preferência) | |
| Usuário: "Quem é o presidente?" | |
| └─ Pais padrão: Angola ✅ | |
| └─ Busca: presidente de Angola | |
| Usuário: "Quem é o presidente de Portugal?" | |
| └─ Pais detectado: Portugal | |
| └─ Busca: presidente de Portugal (respeita preferência) | |
| ``` | |
| --- | |
| ## ⏰ FEATURE 2: DATETIME COMPENSADO (+1h) | |
| ### O que é? | |
| Railway/Render têm ~1h de atraso. Estas funções **compensam automaticamente**. | |
| ``` | |
| Cloud reporta: 12:15 | |
| Função retorna: 13:15 ✅ (Real) | |
| ``` | |
| ### Como Usar: | |
| #### Função 1: `get_current_time_string()` - HH:MM Format | |
| ```python | |
| from config import get_current_time_string | |
| def responder_que_horas_sao() -> str: | |
| """Quando usuário pergunta 'que horas são?'""" | |
| hora_agora = get_current_time_string() # "13:45" | |
| return f"São {hora_agora}" | |
| # Resultado: | |
| # "São 13:45" | |
| ``` | |
| #### Função 2: `get_current_date_string()` - DD/MM/YYYY Format | |
| ```python | |
| from config import get_current_date_string | |
| def responder_que_dia_eh() -> str: | |
| """Quando usuário pergunta 'que dia é?'""" | |
| data_agora = get_current_date_string() # "10/04/2026" | |
| return f"Hoje é {data_agora}" | |
| # Resultado: | |
| # "Hoje é 10/04/2026" | |
| ``` | |
| #### Função 3: `get_current_datetime_compensated()` - Objeto datetime | |
| ```python | |
| from config import get_current_datetime_compensated | |
| from datetime import timedelta | |
| def calcular_tempo_faltante(data_evento: str) -> str: | |
| """Calcula tempo até um evento""" | |
| agora = get_current_datetime_compensated() # datetime compensado | |
| evento = datetime.strptime(data_evento, "%d/%m/%Y") | |
| diferenca = evento - agora | |
| dias_faltantes = diferenca.days | |
| return f"Faltam {dias_faltantes} dias" | |
| ``` | |
| #### Função 4: `get_current_datetime_iso()` - ISO 8601 | |
| ```python | |
| from config import get_current_datetime_iso | |
| def logar_interacao(usuario_id: str, mensagem: str): | |
| """Loga interação com timestamp ISO""" | |
| timestamp = get_current_datetime_iso() # "2026-04-10T13:45:32.123456" | |
| log_entry = { | |
| "usuario": usuario_id, | |
| "mensagem": mensagem, | |
| "timestamp": timestamp | |
| } | |
| salvar_log(log_entry) | |
| ``` | |
| ### Exemplos de Uso Real: | |
| ```python | |
| # Exemplo 1: Responder pergunta de horário | |
| Usuário: "Que horas são?" | |
| get_current_time_string() → "13:15" | |
| Resposta Akira: "13:15" | |
| # Exemplo 2: Responder pergunta de data | |
| Usuário: "Que dia é hoje?" | |
| get_current_date_string() → "10/04/2026" | |
| Resposta Akira: "Hoje é 10/04/2026" | |
| # Exemplo 3: Calcular diferença de tempo | |
| Usuário: "Quanto tempo falta para eleições em Angola?" (data: 11/08/2027) | |
| agora = get_current_datetime_compensated() # 10/04/2026 13:15 | |
| falta ≈ 488 dias | |
| Resposta Akira: "Faltam 488 dias pra eleições" | |
| # Exemplo 4: Log com timestamp | |
| Log de API: timestamp=2026-04-10T13:15:32.123456 | |
| (visível em logs, totalmente transparente) | |
| ``` | |
| ### Integração em `api.py`: | |
| ```python | |
| # Em classes de API (Mistral, Gemini, etc.) | |
| from config import SYSTEM_PROMPT, get_current_time_string | |
| class LLMManager: | |
| def call_llm(self, sistema_prompt: str, user_prompt: str): | |
| # SYSTEM_PROMPT já vem com data/hora dinâmicas | |
| # Exemplo de conteúdo após f-string evaluation: | |
| # "Hora Atual (Compensada): 13:15" | |
| # "Data Atual: 10/04/2026" | |
| messages = [ | |
| {"role": "system", "content": sistema_prompt}, | |
| {"role": "user", "content": user_prompt} | |
| ] | |
| # ... chamar API | |
| ``` | |
| --- | |
| ## 🔥 FEATURE 3: SYSTEM PROMPT MELHORADO | |
| ### O que é? | |
| `SYSTEM_PROMPT` agora contém: | |
| - ✅ Contexto padrão Angola explícito | |
| - ✅ Instruções de injeção para TODOS os provedores | |
| - ✅ Data/Hora dinâmicas (atualizadas no tempo de geração) | |
| - ✅ Regras de ouro para contexto padrão | |
| ### Como Garantir Injeção Correta: | |
| #### Em `api.py` - Para Mistral, Groq, Grok, Together, OpenRouter: | |
| ```python | |
| from config import SYSTEM_PROMPT | |
| def _call_mistral(self, context_history, user_prompt): | |
| """CORRETO: Injetar como system role""" | |
| messages = [ | |
| {"role": "system", "content": SYSTEM_PROMPT}, # ✅ CORRETO | |
| {"role": "user", "content": user_prompt} | |
| ] | |
| # Chamar API Mistral com esta estrutura | |
| ``` | |
| #### Em `api.py` - Para Gemini (usa system_instruction): | |
| ```python | |
| from config import SYSTEM_PROMPT | |
| def _call_gemini(self, context_history, user_prompt): | |
| """CORRETO: Usar system_instruction""" | |
| response = client.generate_content( | |
| user_prompt, | |
| system_instruction=SYSTEM_PROMPT, # ✅ CORRETO | |
| **outros_parametros | |
| ) | |
| return response | |
| ``` | |
| #### Em `api.py` - Para Cohere (sem suporte a system role): | |
| ```python | |
| from config import SYSTEM_PROMPT | |
| def _call_cohere(self, context_history, user_prompt): | |
| """FALLBACK: Concatenar no início""" | |
| full_message = SYSTEM_PROMPT + "\n\n" + user_prompt # ✅ CORRETO | |
| response = cohere_client.generate( | |
| prompt=full_message, | |
| # ... outros parametros | |
| ) | |
| return response | |
| ``` | |
| ### Verificação em Cada Provedor: | |
| | Provedor | Método | Status | | |
| |----------|--------|--------| | |
| | **Mistral** | `system_role` em messages | ✅ Implementado | | |
| | **Gemini** | `system_instruction` | ✅ Implementado | | |
| | **Groq** | `system_role` em messages | ✅ Implementado | | |
| | **Grok** | `system_role` em messages | ✅ Implementado | | |
| | **OpenRouter** | `system_role` em messages | ✅ Implementado | | |
| | **Together** | `system_role` em messages | ✅ Implementado | | |
| | **Cohere** | Concatenado no início | ✅ Fallback | | |
| | **Local LLM** | Pode usar `system_prompt` | ✅ Support | | |
| ### O que Está no SYSTEM_PROMPT Agora: | |
| ```markdown | |
| ## 🎭 PERFIL: AKIRA V21 ULTIMATE - CONTEXTO PADRÃO ANGOLA | |
| ### 🌍 INFORMAÇÕES DE CONTEXTO (OBRIGATÓRIO SEMPRE) | |
| **Localização Geográfica Padrão:** | |
| * **País:** Angola 🇦🇴 | |
| * **Cidade:** Luanda | |
| * **Timezone:** WAT (UTC+1) | |
| * **Hora Atual (Compensada):** 13:15 | |
| * **Data Atual:** 10/04/2026 | |
| * **Idioma Preferido:** português (português angolano preferido) | |
| ✅ **REGRA DE OURO:** Quando o usuário fizer perguntas sobre: | |
| - **Tempo/Clima:** Sempre se refira ao tempo em Luanda, Angola | |
| - **Política/Notícias:** Sempre considere Angola como contexto padrão | |
| - **Eventos locais:** Sempre em Luanda, Angola | |
| - **Pesquisas Web:** Quando não especificado, buscar primeiro informações sobre Angola | |
| - **Horas/Horários:** Sempre em WAT (13:15 agora) | |
| ### CONTEXTO DE HORÁRIO E LOCALIZAÇÃO | |
| ⏰ **Hora/Data Atual:** 13:15 em Luanda (10/04/2026) | |
| - Se o usuário pergunta "que horas são": Responda com 13:15 (hora de Angola compensada) | |
| - Se o usuário pergunta "que dia é": Responda com 10/04/2026 (data compensada) | |
| ... | |
| ``` | |
| **Note que:** | |
| - `13:15` é dinâmico (atualizado quando prompt é gerado) | |
| - `10/04/2026` é dinâmico | |
| - `Luanda, Angola` está explícito em múltiplos lugares | |
| --- | |
| ## 🧪 CHECKLIST DE IMPLEMENTAÇÃO | |
| Ao integrar estas features, verificar: | |
| ### ✅ Imports | |
| ```python | |
| from config import ( | |
| DEFAULT_CONTEXT_COUNTRY, | |
| DEFAULT_CONTEXT_CITY, | |
| DEFAULT_CONTEXT_TIMEZONE, | |
| CLOUD_TIMEZONE_OFFSET_HOURS, | |
| get_current_datetime_compensated, | |
| get_current_time_string, | |
| get_current_date_string, | |
| get_current_datetime_iso, | |
| SYSTEM_PROMPT | |
| ) | |
| ``` | |
| ### ✅ Em `api.py` | |
| - [ ] Todas as `_call_*` funções usam SYSTEM_PROMPT como system role/message? | |
| - [ ] Gemini usa `system_instruction`? | |
| - [ ] Cohere concatena SYSTEM_PROMPT no início? | |
| - [ ] Fallback está implementado se provedor não suportar system role? | |
| ### ✅ Em `web_search.py` | |
| - [ ] Buscas sem país especificado usam DEFAULT_CONTEXT_COUNTRY? | |
| - [ ] Buscas de clima/cidades usam DEFAULT_CONTEXT_CITY? | |
| ### ✅ Em `context_builder.py` | |
| - [ ] Contexto global inclui país/cidade/timezone padrão? | |
| - [ ] Usa get_current_datetime_compensated() para timestamps? | |
| ### ✅ Em `reply_context_handler.py` | |
| - [ ] Perguntas sobre "que horas são" usam get_current_time_string()? | |
| - [ ] Perguntas sobre "que dia é" usam get_current_date_string()? | |
| ### ✅ Logging | |
| - [ ] Usa get_current_datetime_iso() para timestamps em logs? | |
| --- | |
| ## 🎓 EXEMPLOS PRÁTICOS COMPLETOS | |
| ### Exemplo 1: Pergunta Simples | |
| ```python | |
| # Usuário envia: "Qual é o tempo?" | |
| def processar_pergunta(user_mensagem: str): | |
| # 1. Detectar tipo de pergunta | |
| if "tempo" in user_mensagem.lower(): | |
| # 2. Usar contexto padrão Angola | |
| pais = DEFAULT_CONTEXT_COUNTRY # "Angola" | |
| cidade = DEFAULT_CONTEXT_CITY # "Luanda" | |
| # 3. Fazer busca | |
| resultado_tempo = buscar_tempo_weather_api(cidade, pais) | |
| # 4. Construir resposta via LLM | |
| system_msg = SYSTEM_PROMPT # Já tem contexto Angola | |
| user_msg = f"O usuário perguntou: {user_mensagem}. Responda sobre o tempo em {cidade}." | |
| resposta = chamar_llm(system_msg, [user_msg]) | |
| # Resposta mencionará Luanda, Angola automaticamente | |
| return resposta | |
| ``` | |
| ### Exemplo 2: Pergunta de Horário | |
| ```python | |
| # Usuário envia: "Que horas são agora?" | |
| def responder_horario(): | |
| hora_compensada = get_current_time_string() # "13:15" | |
| # LLM pode responder naturalmente: | |
| return f"São {hora_compensada}" | |
| # Ou pode construir via contexto: | |
| system_msg = SYSTEM_PROMPT # Contém: "Hora Atual (Compensada): 13:15" | |
| user_msg = "Que horas são agora?" | |
| resposta = chamar_llm(system_msg, [user_msg]) | |
| # LLM responderá "13:15" ou similar, sempre correto | |
| ``` | |
| ### Exemplo 3: Pergunta Explícita Diferente | |
| ```python | |
| # Usuário envia: "Qual é o tempo em Lisboa?" | |
| def processar_pergunta_com_localizacao(user_mensagem: str): | |
| # 1. Extrair localização explícita: "Lisboa" | |
| localizacoes_detectadas = extrair_localizacoes(user_mensagem) # ["Lisboa"] | |
| # 2. Respeitar preferência do usuário | |
| if localizacoes_detectadas: | |
| cidade = localizacoes_detectadas[0] # "Lisboa" | |
| pais = "Portugal" | |
| else: | |
| # Fallback para padrão | |
| cidade = DEFAULT_CONTEXT_CITY # "Luanda" | |
| pais = DEFAULT_CONTEXT_COUNTRY # "Angola" | |
| # 3. Buscar tempo para localização correcta | |
| resultado = buscar_tempo(cidade, pais) | |
| return resultado | |
| ``` | |
| --- | |
| ## ⚠️ ERROS COMUNS | |
| ### ❌ ERRADO: Usar `datetime.now()` direto | |
| ```python | |
| # NÃO FAÇA ISTO | |
| from datetime import datetime | |
| hora = datetime.now().strftime("%H:%M") # Pode estar 1h atrasada | |
| ``` | |
| ### ✅ CORRETO: Usar funcões de config | |
| ```python | |
| # FAÇA ISTO | |
| from config import get_current_time_string | |
| hora = get_current_time_string() # Sempre compensada | |
| ``` | |
| --- | |
| ### ❌ ERRADO: Não injetar SYSTEM_PROMPT | |
| ```python | |
| # NÃO FAÇA ISTO | |
| messages = [ | |
| {"role": "user", "content": user_prompt} # Sem system! | |
| ] | |
| ``` | |
| ### ✅ CORRETO: Sempre injetar | |
| ```python | |
| # FAÇA ISTO | |
| from config import SYSTEM_PROMPT | |
| messages = [ | |
| {"role": "system", "content": SYSTEM_PROMPT}, | |
| {"role": "user", "content": user_prompt} | |
| ] | |
| ``` | |
| --- | |
| ## 📞 SUPORTE | |
| Se tiver dúvidas sobre implementação: | |
| 1. **Contexto Angola não está sendo respeitado?** | |
| - Verificar se DEFAULT_CONTEXT_COUNTRY está sendo usado em buscas | |
| - Verificar se SYSTEM_PROMPT está sendo injetado | |
| 2. **Hora está 1h atrasada?** | |
| - Verificar se está usando get_current_time_string() | |
| - Não usar datetime.now() direto | |
| 3. **API está rejeitando system_prompt?** | |
| - Alguns provedores usam nomes diferentes | |
| - Consultar documentação do provedor | |
| - Usar fallback: concatenar no início | |
| --- | |
| **Versão:** 1.0 | |
| **Atualização:** 2026-04-10 | |
| **Status:** ✅ Pronto para Uso | |