Spaces:
Running
Running
File size: 3,973 Bytes
824589c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | 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()
|