dev-agent / dev-agent.py
Luis-Filipe's picture
Update dev-agent.py
824589c verified
import os
import sys
import json
import textwrap
from pathlib import Path
# Detectar ambiente
def is_huggingface():
return "SPACE_ID" in os.environ or "HF_HOME" in os.environ
RUNNING_IN_HF = is_huggingface()
# ==========================
# MODELOS
# ==========================
LOCAL_MODEL = "qwen3.5:latest"
HF_MODEL = "google/gemma-2-2b-it"
# ==========================
# MODELO LOCAL (OLLAMA)
# ==========================
def call_ollama(prompt):
import requests
try:
resp = requests.post(
"http://localhost:11434/api/generate",
json={"model": LOCAL_MODEL, "prompt": prompt, "stream": False},
timeout=30
)
return resp.json().get("response", "")
except:
return None
# ==========================
# MODELO HUGGING FACE (TRANSFORMERS)
# ==========================
hf_pipeline = None
def load_hf_model():
global hf_pipeline
if hf_pipeline is None:
from transformers import AutoTokenizer, AutoModelForCausalLM, pipeline
tok = AutoTokenizer.from_pretrained(HF_MODEL)
model = AutoModelForCausalLM.from_pretrained(HF_MODEL)
hf_pipeline = pipeline("text-generation", model=model, tokenizer=tok)
return hf_pipeline
def call_hf_transformers(prompt):
pipe = load_hf_model()
out = pipe(prompt, max_new_tokens=256)
return out[0]["generated_text"]
# ==========================
# FALLBACK
# ==========================
def call_model(prompt):
# 1) Tentar Ollama local
if not RUNNING_IN_HF:
r = call_ollama(prompt)
if r:
return r
# 2) Tentar Gemma local (Transformers)
try:
return call_hf_transformers(prompt)
except:
pass
# 3) Fallback interno
return "Não consegui usar nenhum modelo. Resposta fallback."
# ==========================
# AGENTE
# ==========================
SYSTEM_PROMPT = """
És um agente de desenvolvimento híbrido.
Cria ficheiros, lê ficheiros e corrige código.
No Hugging Face não usas subprocessos.
Responde sempre em JSON com:
{
"thoughts": "...",
"steps": [
{"tool": "...", "args": {...}, "comment": "..."}
]
}
"""
def build_prompt(user):
return SYSTEM_PROMPT + "\nUtilizador:\n" + user + "\nJSON:"
# Ferramentas
def tool_read(path):
p = Path(path)
if not p.exists():
return "[ERRO] ficheiro não existe"
return p.read_text()
def tool_write(path, content):
p = Path(path)
p.parent.mkdir(parents=True, exist_ok=True)
p.write_text(content)
return "[OK] escrito"
def tool_run(cmd):
if RUNNING_IN_HF:
return "[BLOQUEADO] subprocessos não são permitidos no Hugging Face."
import subprocess
r = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return r.stdout + "\n" + r.stderr
# Execução dos passos
def execute_steps(steps):
outputs = []
for s in steps:
tool = s.get("tool")
args = s.get("args", {})
if tool == "read_file":
outputs.append(tool_read(args["path"]))
elif tool == "write_file":
outputs.append(tool_write(args["path"], args["content"]))
elif tool == "run_command":
outputs.append(tool_run(args["command"]))
else:
outputs.append("[ERRO] ferramenta desconhecida")
return "\n".join(outputs)
# ==========================
# INTERFACE GRADIO
# ==========================
import gradio as gr
def agent_chat(user_input):
prompt = build_prompt(user_input)
raw = call_model(prompt)
try:
data = json.loads(raw)
except:
return "Modelo não devolveu JSON válido:\n" + raw
steps = data.get("steps", [])
out = execute_steps(steps)
return out
with gr.Blocks() as demo:
gr.Markdown("# Dev Agent Híbrido (Local + Hugging Face)")
inp = gr.Textbox(label="Comando")
out = gr.Textbox(label="Output")
btn = gr.Button("Executar")
btn.click(agent_chat, inp, out)
demo.launch()