From a20b32b70bd9d0ae3106e7e2049cab29336fedde Mon Sep 17 00:00:00 2001 From: Marcos Date: Sun, 22 Mar 2026 13:16:39 -0300 Subject: [PATCH] Performance: Implemented Turbo Lite mode for Ollama local --- ai_agent.py | 75 ++++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 53 deletions(-) diff --git a/ai_agent.py b/ai_agent.py index b108dd6..8b1e1dc 100644 --- a/ai_agent.py +++ b/ai_agent.py @@ -5,7 +5,7 @@ import json from tools import AVAILABLE_TOOLS from config import get_config -def get_llm_response(prompt: str, provider: str, cfg: dict) -> str: +def get_llm_response(prompt: str, provider: str, cfg: dict, temp: float = 0.7, ctx: int = 4096) -> str: """Invoca o provedor de LLM configurado.""" if provider == "gemini": api_key = cfg.get("gemini_api_key") or os.getenv("GEMINI_API_KEY") @@ -23,8 +23,8 @@ def get_llm_response(prompt: str, provider: str, cfg: dict) -> str: "prompt": prompt, "stream": False, "options": { - "temperature": 0.1, - "num_ctx": 4096 + "temperature": temp, + "num_ctx": ctx } }) if res.status_code == 200: @@ -37,57 +37,23 @@ def query_agent(prompt: str, override_provider: str = None, chat_history: list = """ Motor Agente em Loop (ReAct): Pensamento -> Ação -> Observação -> Resposta Final. """ + # Ajuste de Provedor e Contexto cfg = get_config() provider = override_provider or cfg.get("active_provider", "gemini") - # Contexto de Ferramentas para a IA - tools_desc = "\n".join([f"- {k}: {v['description']}" for k,v in AVAILABLE_TOOLS.items()]) - - # Prompt especializado reformulado para evitar alucinações - system_prompt_base = """Você é o [Antigravity VPS Agent], o SysAdmin de elite do Marcos. -Você tem acesso root completo à VPS e deve agir de forma profissional e precisa. - -### REGRAS DE OURO: -1. Responda em PORTUGUÊS (Brasil). -2. Se o usuário pedir o status da VPS, SEMPRE use a ferramenta 'get_system_health'. -3. Se o usuário pedir algo sobre containers, use 'get_docker_stats'. -4. Antes de decidir que um arquivo não existe, use 'run_bash_command' com 'ls' para verificar o diretório. -5. NUNCA invente que buscou por arquivos (como syslog.conf) se o usuário não pediu especificamente por eles. -6. A seção deve conter apenas as informações solicitadas. Se não houver imagem relevante, não inclua tags de imagem. -7. O disco da VPS está montado em `/host_root`. Os arquivos do Marcos ficam principalmente em `/host_root/root/VPS_Sync`. Use este caminho como ponto de partida se o `find` na raiz falhar ou demorar demais. - -### FORMATO DE AÇÃO: -Use: [TOOL:nome_da_ferramenta] argumento [/TOOL] -Rode UMA ferramenta por vez. Aguarde a saída do SISTEMA antes de concluir. - -### RESPOSTA FINAL: -Sua resposta terminada deve ter: -- Um resumo técnico. -- Uma seção ... com Markdown limpo. -- **DICA**: Só use imagens em se o usuário pediu para ver um arquivo de imagem específico que você localizou. Use o caminho absoluto encontrado. - -### FERRAMENTAS DISPONÍVEIS: -{TOOLS_LIST} - -### EXEMPLO DE SUCESSO: -Usuário: qual o uso de ram agora? -Agente: [TOOL:get_system_health] [/TOOL] -SISTEMA: CPU: 5% | RAM Usada: 20% | Disco Usado: 40% -Resposta: A memória RAM está operando com 20% de uso. - -### 📊 Memória e CPU -- **RAM Utilizada**: 20% -- **CPU**: 5% - -""" - system_prompt = system_prompt_base.replace("{TOOLS_LIST}", tools_desc) + # Prompt otimizado para ser curto se for Ollama (evita CPU 90% em conversas simples) + if provider == "ollama": + system_prompt = "Você é o [BotVPS] do Marcos. Seja técnico e breve. Use [TOOL:nome] arg [/TOOL] apenas se for necessário agir na VPS. Responda em Português." + num_context = 2048 + else: + system_prompt = system_prompt_base.replace("{TOOLS_LIST}", tools_desc) + num_context = 4096 # Preparação de Histórico Limpa - hist_list = chat_history[-5:] if chat_history else [] + hist_list = chat_history[-3:] if chat_history else [] # Apenas as últimas 3 para o Ollama voar hist_txt = "\n".join([f"Usuário: {m['user']}\nAgente: {m['bot']}" for m in hist_list]) - # Cabeçalho de Execução - execution_context = f"\n--- HISTÓRICO RECENTE ---\n{hist_txt}\n------------------------\n\nORDEM ATUAL: {prompt}\n" + execution_context = f"\nHistorico: {hist_txt}\nORDEM: {prompt}\n" current_reasoning = "" max_loops = 12 @@ -96,15 +62,20 @@ Resposta: A memória RAM está operando com 20% de uso. for i in range(max_loops): print(f"\n[LOOP {i+1}/{max_loops}]") - # Constrói o Prompt Final separando REGRAS, PASSADO e PENSAMENTO ATUAL - full_prompt = f"{system_prompt}\n{execution_context}\n\nSEU PENSAMENTO ATUAL (Ações e Observações):\n{current_reasoning}\n" + full_prompt = f"{system_prompt}\n{execution_context}\n{current_reasoning}\n" - response = get_llm_response(full_prompt, provider, cfg) + # Injeta o num_ctx dinâmico no payload + if provider == "ollama": + response = get_llm_response(full_prompt, provider, cfg, temp=0.1, ctx=num_context) + else: + response = get_llm_response(full_prompt, provider, cfg) + print(f"PENSAMENTO:\n{response}") match = re.search(r"\[TOOL:(.*?)\](.*?)\[/TOOL\]", response, re.IGNORECASE | re.DOTALL) if match: + # ... (lógica de ferramenta existente) ... tool_name = match.group(1).strip() arg = match.group(2).strip() print(f"EXECUTANDO: {tool_name}") @@ -112,12 +83,10 @@ Resposta: A memória RAM está operando com 20% de uso. if tool_name in AVAILABLE_TOOLS: func = AVAILABLE_TOOLS[tool_name]["func"] observation = func() if tool_name in ["get_system_health", "get_docker_stats"] else func(arg) - print(f"OBSERVAÇÃO (suprimida): {str(observation)[:150]}...") else: observation = f"Erro: Ferramenta '{tool_name}' não encontrada." - # Adiciona ao PENSAMENTO ATUAL apenas, sem sujar o histórico original - current_reasoning += f"\nAgente (Ação): {response}\nSISTEMA (Saída): {observation}\n" + current_reasoning += f"\nAção: {response}\nSISTEMA: {observation}\n" else: print("--- RESPOSTA FINAL ENCONTRADA ---") return response