103 lines
4.4 KiB
Python
103 lines
4.4 KiB
Python
import os
|
|
import re
|
|
import requests
|
|
import json
|
|
from tools import AVAILABLE_TOOLS
|
|
from config import get_config
|
|
|
|
def get_llm_response(prompt: str, provider: str, cfg: dict) -> str:
|
|
"""Invoca o provedor de LLM configurado."""
|
|
if provider == "gemini":
|
|
api_key = cfg.get("gemini_api_key")
|
|
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={api_key}"
|
|
payload = {"contents": [{"parts": [{"text": prompt}]}]}
|
|
res = requests.post(url, json=payload)
|
|
if res.status_code == 200:
|
|
return res.json()["candidates"][0]["content"]["parts"][0]["text"]
|
|
return f"Erro Gemini: {res.text}"
|
|
|
|
elif provider == "ollama":
|
|
ollama_host = os.getenv("OLLAMA_HOST", "http://ollama-lw4s8g4gc8gss4gkc4gg0wk4:11434")
|
|
res = requests.post(f"{ollama_host}/api/generate", json={
|
|
"model": os.getenv("OLLAMA_MODEL", "qwen2.5-coder:1.5b"),
|
|
"prompt": prompt,
|
|
"stream": False
|
|
})
|
|
if res.status_code == 200:
|
|
return res.json().get("response", "")
|
|
return f"Erro Ollama: {res.text}"
|
|
|
|
return "Provedor desconhecido."
|
|
|
|
def query_agent(prompt: str, override_provider: str = None) -> str:
|
|
"""
|
|
Motor Agente em Loop (ReAct): Pensamento -> Ação -> Observação -> Resposta Final.
|
|
"""
|
|
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 (sem chaves complexas)
|
|
system_prompt_base = """Você é o [Antigravity VPS Agent].
|
|
Sua missão é ser o SysAdmin de elite do Marcos. Você tem acesso root.
|
|
|
|
### REGRAS:
|
|
1. Responda em PORTUGUÊS (Brasil).
|
|
2. Para agir, use o formato: [TOOL:nome_da_ferramenta] argumento [/TOOL]. Rode UMA ferramenta por vez.
|
|
3. Para comandos de terminal, use a ferramenta 'run_bash_command'. Exemplo: [TOOL:run_bash_command] ls -la [/TOOL].
|
|
4. Para ler arquivos do host, use 'read_vps_file'. Exemplo: [TOOL:read_vps_file] /etc/hosts [/TOOL].
|
|
5. Após usar a ferramenta, você receberá a saída. O seu objetivo é resolver a solicitação do usuário.
|
|
6. Quando terminar, sua resposta FINAL deve ter:
|
|
- Um resumo técnico rápido.
|
|
- Uma seção entre tags <REFINED> ... </REFINED> com uma tabela Markdown limpa ou resumo em tópicos (Nome: Valor) para o usuário leigo.
|
|
7. Se for solicitado exibir uma imagem (ex: um logo, foto) que você achou no host, **exiba-a dentro da tag <REFINED>** usando markdown de imagem com o endpoint `/api/host_file?path=`. Exemplo: ``
|
|
|
|
### FERRAMENTAS DISPONÍVEIS:
|
|
{TOOLS_LIST}
|
|
|
|
### EXEMPLO DE REFINAMENTO VISUAL:
|
|
Relatório: Coletei os dados solicitados.
|
|
<REFINED>
|
|
### 📊 Status Global
|
|
- **CPU**: 10%
|
|
- **RAM**: 500MB livre
|
|
|
|

|
|
</REFINED>
|
|
"""
|
|
system_prompt = system_prompt_base.replace("{TOOLS_LIST}", tools_desc)
|
|
|
|
history = f"\nUsuário: {prompt}\n"
|
|
max_loops = 10
|
|
|
|
for _ in range(max_loops):
|
|
full_prompt = system_prompt + history
|
|
response = get_llm_response(full_prompt, provider, cfg)
|
|
|
|
# Procura por chamadas de ferramentas na resposta
|
|
match = re.search(r"\[TOOL:(.*?)\](.*?)\[/TOOL\]", response, re.IGNORECASE | re.DOTALL)
|
|
|
|
if match:
|
|
tool_name = match.group(1).strip()
|
|
arg = match.group(2).strip()
|
|
|
|
print(f"Agente usando ferramenta: {tool_name} -> {arg}")
|
|
|
|
if tool_name in AVAILABLE_TOOLS:
|
|
if tool_name in ["get_system_health", "get_docker_stats"]:
|
|
observation = AVAILABLE_TOOLS[tool_name]["func"]()
|
|
else:
|
|
observation = AVAILABLE_TOOLS[tool_name]["func"](arg)
|
|
else:
|
|
observation = f"Erro: Ferramenta '{tool_name}' não encontrada. Use as ferramentas listadas ou 'run_bash_command'."
|
|
|
|
# Adiciona ao histórico para a IA ler na próxima rodada
|
|
history += f"\nAgente (Ação): {response}\nSISTEMA (Saída de {tool_name}): {observation}\n"
|
|
else:
|
|
# Se não tem comando, é a resposta final
|
|
return response
|
|
|
|
return "O agente atingiu o limite de tentativas para esta tarefa."
|