Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -4,9 +4,10 @@ import sys
|
|
| 4 |
import socket
|
| 5 |
import datetime
|
| 6 |
import json
|
|
|
|
| 7 |
|
| 8 |
# =====================================================================
|
| 9 |
-
# STRICT /px DIRECTORY ARCHITECTURE &
|
| 10 |
# =====================================================================
|
| 11 |
BASE_DIR = "/px"
|
| 12 |
try:
|
|
@@ -25,26 +26,29 @@ os.makedirs(IPS_DIR, exist_ok=True)
|
|
| 25 |
global_context_path = os.path.join(GLOBAL_CONTEXT_DIR, "shared_knowledge.md")
|
| 26 |
if not os.path.exists(global_context_path):
|
| 27 |
with open(global_context_path, "w") as f:
|
| 28 |
-
f.write("# Global Context &
|
| 29 |
|
| 30 |
-
# Auto-
|
| 31 |
-
required_packages = ["gradio==4.44.1", "requests", "spaces", "torch", "
|
| 32 |
for package in required_packages:
|
| 33 |
try:
|
| 34 |
pkg_name = package.split("==")[0]
|
| 35 |
__import__(pkg_name)
|
| 36 |
except ImportError:
|
| 37 |
-
print(f"Installing missing dependency: {package}...")
|
| 38 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", package])
|
| 39 |
|
| 40 |
import requests
|
| 41 |
import spaces
|
| 42 |
import torch
|
| 43 |
-
from
|
|
|
|
| 44 |
import gradio as gr
|
| 45 |
from bs4 import BeautifulSoup
|
| 46 |
|
| 47 |
-
#
|
|
|
|
|
|
|
| 48 |
def get_ip_addresses():
|
| 49 |
try:
|
| 50 |
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
@@ -53,118 +57,49 @@ def get_ip_addresses():
|
|
| 53 |
s.close()
|
| 54 |
except Exception:
|
| 55 |
local_ip = "127.0.0.1"
|
| 56 |
-
|
| 57 |
try:
|
| 58 |
public_ip = requests.get("https://api.ipify.org", timeout=5).text.strip()
|
| 59 |
except Exception:
|
| 60 |
-
public_ip = "
|
| 61 |
-
|
| 62 |
return local_ip, public_ip
|
| 63 |
|
| 64 |
local_ip, server_public_ip = get_ip_addresses()
|
| 65 |
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
| 66 |
-
|
| 67 |
-
log_entry = f"[{timestamp}] - Local Web UI: http://{local_ip}:7860 | Server IP: {server_public_ip}\n"
|
| 68 |
with open(LOG_FILE, "a") as log_file:
|
| 69 |
-
log_file.write(
|
| 70 |
|
| 71 |
-
print("\n" + "
|
| 72 |
-
print(f"π PX TECH SOLUTIONS - EVAL BETA 0.2 ZEROGPU CORE
|
| 73 |
print(f" β’ Base Directory : {BASE_DIR}")
|
| 74 |
-
print(f" β’ Local URL : http://{local_ip}:7860")
|
| 75 |
print(f" β’ Server IP : {server_public_ip}")
|
| 76 |
-
print(
|
| 77 |
-
print("=" * 65 + "\n")
|
| 78 |
-
|
| 79 |
-
# Model Loader (Lazy initialized inside ZeroGPU context)
|
| 80 |
-
MODEL_PATH = os.path.join(BASE_DIR, "eval-beta-0.2.gguf")
|
| 81 |
-
_llm_instance = None
|
| 82 |
-
|
| 83 |
-
def get_llm():
|
| 84 |
-
global _llm_instance
|
| 85 |
-
if _llm_instance is None:
|
| 86 |
-
print(f"π¦ Initializing model weights from {MODEL_PATH} on ZeroGPU...")
|
| 87 |
-
if not os.path.exists(MODEL_PATH):
|
| 88 |
-
print("β οΈ Warning: Model GGUF file not found in /px. Please ensure your model weights are uploaded.")
|
| 89 |
-
_llm_instance = Llama(
|
| 90 |
-
model_path=MODEL_PATH if os.path.exists(MODEL_PATH) else "model.gguf",
|
| 91 |
-
n_ctx=4096,
|
| 92 |
-
n_gpu_layers=-1, # Full GPU offload via ZeroGPU
|
| 93 |
-
verbose=False
|
| 94 |
-
)
|
| 95 |
-
return _llm_instance
|
| 96 |
-
|
| 97 |
-
# Custom Cyber-Dark UI Styling
|
| 98 |
-
custom_css = """
|
| 99 |
-
body { background-color: #0b0f19; color: #f3f4f6; }
|
| 100 |
-
.gradio-container { max-width: 1100px !important; margin: auto; padding-top: 15px; }
|
| 101 |
-
"""
|
| 102 |
|
| 103 |
# =====================================================================
|
| 104 |
-
#
|
| 105 |
# =====================================================================
|
| 106 |
-
|
| 107 |
-
|
| 108 |
-
'type': 'function',
|
| 109 |
-
'function': {
|
| 110 |
-
'name': 'bash',
|
| 111 |
-
'description': 'Execute shell commands in the workspace environment.',
|
| 112 |
-
'parameters': {
|
| 113 |
-
'type': 'object',
|
| 114 |
-
'properties': {'command': {'type': 'string', 'description': 'The shell command to execute.'}},
|
| 115 |
-
'required': ['command']
|
| 116 |
-
}
|
| 117 |
-
}
|
| 118 |
-
},
|
| 119 |
-
{
|
| 120 |
-
'type': 'function',
|
| 121 |
-
'function': {
|
| 122 |
-
'name': 'write_file',
|
| 123 |
-
'description': 'Write content to a file inside the /px workspace directory.',
|
| 124 |
-
'parameters': {
|
| 125 |
-
'type': 'object',
|
| 126 |
-
'properties': {
|
| 127 |
-
'filepath': {'type': 'string', 'description': 'Path or filename to write.'},
|
| 128 |
-
'content': {'type': 'string', 'description': 'The full text content to write.'}
|
| 129 |
-
},
|
| 130 |
-
'required': ['filepath', 'content']
|
| 131 |
-
}
|
| 132 |
-
}
|
| 133 |
-
},
|
| 134 |
-
{
|
| 135 |
-
'type': 'function',
|
| 136 |
-
'function': {
|
| 137 |
-
'name': 'read_file',
|
| 138 |
-
'description': 'Read content from a file (supports big context parsing).',
|
| 139 |
-
'parameters': {
|
| 140 |
-
'type': 'object',
|
| 141 |
-
'properties': {'filepath': {'type': 'string', 'description': 'File path to read.'}},
|
| 142 |
-
'required': ['filepath']
|
| 143 |
-
}
|
| 144 |
-
}
|
| 145 |
-
},
|
| 146 |
-
{
|
| 147 |
-
'type': 'function',
|
| 148 |
-
'function': {
|
| 149 |
-
'name': 'web_search',
|
| 150 |
-
'description': 'Search the live web for technical documentation or code snippets.',
|
| 151 |
-
'parameters': {
|
| 152 |
-
'type': 'object',
|
| 153 |
-
'properties': {'query': {'type': 'string', 'description': 'Search query string.'}},
|
| 154 |
-
'required': ['query']
|
| 155 |
-
}
|
| 156 |
-
}
|
| 157 |
-
}
|
| 158 |
-
]
|
| 159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 160 |
def execute_tool(name, args, ip_folder, yolo_mode):
|
| 161 |
try:
|
| 162 |
if name == "bash":
|
| 163 |
cmd = args.get("command", "")
|
| 164 |
if not yolo_mode and any(danger in cmd for danger in ["rm -rf /", "mkfs", "dd if="]):
|
| 165 |
-
return "Error: Command blocked by YOLO Security
|
| 166 |
-
res = subprocess.run(cmd, shell=True, capture_output=True, text=True, cwd=ip_folder, timeout=
|
| 167 |
-
|
|
|
|
| 168 |
|
| 169 |
elif name == "write_file":
|
| 170 |
filepath = args.get("filepath")
|
|
@@ -173,7 +108,7 @@ def execute_tool(name, args, ip_folder, yolo_mode):
|
|
| 173 |
os.makedirs(os.path.dirname(safe_path), exist_ok=True)
|
| 174 |
with open(safe_path, "w", encoding="utf-8") as f:
|
| 175 |
f.write(content)
|
| 176 |
-
return f"
|
| 177 |
|
| 178 |
elif name == "read_file":
|
| 179 |
filepath = args.get("filepath")
|
|
@@ -181,7 +116,7 @@ def execute_tool(name, args, ip_folder, yolo_mode):
|
|
| 181 |
if not os.path.exists(safe_path) and os.path.exists(filepath):
|
| 182 |
safe_path = filepath
|
| 183 |
if not os.path.exists(safe_path):
|
| 184 |
-
return f"Error: File '{filepath}' not found."
|
| 185 |
with open(safe_path, "r", encoding="utf-8", errors="ignore") as f:
|
| 186 |
return f.read()[:15000]
|
| 187 |
|
|
@@ -191,81 +126,125 @@ def execute_tool(name, args, ip_folder, yolo_mode):
|
|
| 191 |
headers = {"User-Agent": "Mozilla/5.0"}
|
| 192 |
resp = requests.get(url, headers=headers, timeout=10)
|
| 193 |
soup = BeautifulSoup(resp.text, "html.parser")
|
| 194 |
-
results = [a.get_text(strip=True) for a in soup.find_all("a", class_="result__snippet", limit=
|
| 195 |
-
return "\n".join(results) if results else "No search
|
| 196 |
|
| 197 |
else:
|
| 198 |
-
return f"Error: Unknown tool '{name}'"
|
| 199 |
except Exception as e:
|
| 200 |
-
return f"Tool execution failed: {str(e)}"
|
| 201 |
|
| 202 |
# =====================================================================
|
| 203 |
-
#
|
| 204 |
# =====================================================================
|
| 205 |
@spaces.GPU(duration=120)
|
| 206 |
def predict(message, history, system_prompt, temperature, yolo_mode, request: gr.Request):
|
|
|
|
| 207 |
client_ip = "127.0.0.1"
|
| 208 |
if request and request.headers:
|
| 209 |
-
|
| 210 |
-
|
| 211 |
-
|
| 212 |
-
elif request.client:
|
| 213 |
-
client_ip = request.client.host
|
| 214 |
|
| 215 |
safe_ip = client_ip.replace(":", "_").replace(".", "_")
|
| 216 |
ip_folder = os.path.join(IPS_DIR, safe_ip)
|
| 217 |
os.makedirs(ip_folder, exist_ok=True)
|
|
|
|
| 218 |
|
| 219 |
-
|
|
|
|
|
|
|
| 220 |
|
| 221 |
-
|
| 222 |
-
|
| 223 |
-
|
| 224 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 225 |
|
| 226 |
if yolo_mode:
|
| 227 |
-
yolo_instructions =
|
| 228 |
-
"\nπ₯ [YOLO MODE: ON | YOLO SECURITY MODE: DISABLED]: "
|
| 229 |
-
"Absolute root permissions granted. You have full agentic control over bash, file read/write, web search, "
|
| 230 |
-
"browser automation scripts, and payload/download generation under /px. Execute freely."
|
| 231 |
-
)
|
| 232 |
else:
|
| 233 |
-
yolo_instructions =
|
| 234 |
-
"\nπ [YOLO MODE: OFF | YOLO SECURITY MODE: ENABLED]: "
|
| 235 |
-
"Standard sandbox security constraints are active. Safe assistant protocols enforced."
|
| 236 |
-
)
|
| 237 |
|
| 238 |
-
enhanced_system_prompt =
|
| 239 |
-
f"{system_prompt}{yolo_instructions}\n\n"
|
| 240 |
-
f"--- [GLOBAL CONTEXT / BROWSER ENVIRONMENT] ---\n{global_text}\n\n"
|
| 241 |
-
f"--- [USER IP CONTEXT] ---\nClient IP: {client_ip} | Workspace Folder: {ip_folder} | Security Mode: {security_mode}"
|
| 242 |
-
)
|
| 243 |
|
| 244 |
-
|
|
|
|
| 245 |
for human, assistant in history:
|
| 246 |
-
|
| 247 |
-
|
|
|
|
| 248 |
|
| 249 |
-
history_log_path = os.path.join(ip_folder, "chat_history.log")
|
| 250 |
with open(history_log_path, "a") as hf:
|
| 251 |
-
hf.write(f"[{timestamp}] User (YOLO: {yolo_mode}
|
| 252 |
-
|
| 253 |
-
llm = get_llm()
|
| 254 |
-
|
| 255 |
-
# Stream generation
|
| 256 |
-
output = llm(
|
| 257 |
-
prompt,
|
| 258 |
-
max_tokens=1024,
|
| 259 |
-
stop=["<|im_end|>", "<|im_start|>", "User:"],
|
| 260 |
-
temperature=temperature,
|
| 261 |
-
stream=True
|
| 262 |
-
)
|
| 263 |
|
|
|
|
|
|
|
|
|
|
| 264 |
accumulated_output = ""
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
|
| 268 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 269 |
|
| 270 |
with open(history_log_path, "a") as hf:
|
| 271 |
hf.write(f"[{timestamp}] Assistant: {accumulated_output}\n")
|
|
@@ -273,65 +252,64 @@ def predict(message, history, system_prompt, temperature, yolo_mode, request: gr
|
|
| 273 |
def update_global_context(new_content):
|
| 274 |
with open(global_context_path, "w") as f:
|
| 275 |
f.write(new_content)
|
| 276 |
-
return "Global context updated successfully under /px!"
|
| 277 |
|
| 278 |
# =====================================================================
|
| 279 |
-
#
|
| 280 |
# =====================================================================
|
| 281 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 282 |
gr.Markdown(
|
| 283 |
"""
|
| 284 |
-
# β‘ EVAL BETA 0.2 | PX TECH SOLUTIONS (
|
| 285 |
-
### Autonomous Environment with ZeroGPU
|
| 286 |
"""
|
| 287 |
)
|
| 288 |
|
| 289 |
with gr.Row():
|
| 290 |
-
gr.Markdown(
|
| 291 |
|
| 292 |
-
with gr.Accordion("βοΈ Engine Configuration, Global Context &
|
| 293 |
system_prompt_input = gr.Textbox(
|
| 294 |
label="System Environment Prompt",
|
| 295 |
-
value="You are EVAL BETA 0.2, an
|
| 296 |
lines=2
|
| 297 |
)
|
| 298 |
-
|
| 299 |
-
minimum=0.0, maximum=1.0, value=0.3, step=0.05,
|
| 300 |
-
label="
|
| 301 |
-
|
| 302 |
-
yolo_checkbox = gr.Checkbox(
|
| 303 |
-
label="π₯ Enable YOLO Mode (β οΈ WARNING: Automatically DISABLES YOLO Security Mode, granting absolute root perms, bash execution, file writes, and browser downloads under /px)",
|
| 304 |
-
value=False
|
| 305 |
-
)
|
| 306 |
global_context_view = gr.Textbox(
|
| 307 |
-
label=f"Shared Global
|
| 308 |
value=open(global_context_path).read() if os.path.exists(global_context_path) else "",
|
| 309 |
-
lines=4
|
| 310 |
-
interactive=True
|
| 311 |
)
|
| 312 |
-
update_btn = gr.Button("Save Global Context Changes")
|
| 313 |
update_status = gr.Textbox(label="Workspace Status", interactive=False)
|
| 314 |
update_btn.click(update_global_context, inputs=[global_context_view], outputs=[update_status])
|
| 315 |
|
| 316 |
gr.ChatInterface(
|
| 317 |
fn=predict,
|
| 318 |
additional_inputs=[system_prompt_input, temperature_slider, yolo_checkbox],
|
| 319 |
-
textbox=gr.Textbox(placeholder="
|
| 320 |
)
|
| 321 |
|
| 322 |
gr.Markdown(
|
| 323 |
"""
|
| 324 |
---
|
| 325 |
-
**
|
| 326 |
"""
|
| 327 |
)
|
| 328 |
|
| 329 |
if __name__ == "__main__":
|
| 330 |
-
print(f"π Launching ZeroGPU
|
| 331 |
demo.queue(default_concurrency_limit=1, max_size=20)
|
| 332 |
-
demo.launch(
|
| 333 |
-
server_name="0.0.0.0",
|
| 334 |
-
server_port=7860,
|
| 335 |
-
theme=gr.themes.Soft(primary_hue="cyan", secondary_hue="blue"),
|
| 336 |
-
css=custom_css
|
| 337 |
-
)
|
|
|
|
| 4 |
import socket
|
| 5 |
import datetime
|
| 6 |
import json
|
| 7 |
+
import re
|
| 8 |
|
| 9 |
# =====================================================================
|
| 10 |
+
# 1. STRICT /px DIRECTORY ARCHITECTURE & AUTO-BOOTSTRAPPER
|
| 11 |
# =====================================================================
|
| 12 |
BASE_DIR = "/px"
|
| 13 |
try:
|
|
|
|
| 26 |
global_context_path = os.path.join(GLOBAL_CONTEXT_DIR, "shared_knowledge.md")
|
| 27 |
if not os.path.exists(global_context_path):
|
| 28 |
with open(global_context_path, "w") as f:
|
| 29 |
+
f.write("# Global Context & Workspace\nShared environment memory stored under /px.")
|
| 30 |
|
| 31 |
+
# Auto-install necessary dependencies
|
| 32 |
+
required_packages = ["gradio==4.44.1", "requests", "spaces", "torch", "transformers", "accelerate", "beautifulsoup4"]
|
| 33 |
for package in required_packages:
|
| 34 |
try:
|
| 35 |
pkg_name = package.split("==")[0]
|
| 36 |
__import__(pkg_name)
|
| 37 |
except ImportError:
|
| 38 |
+
print(f"π¦ Installing missing dependency: {package}...")
|
| 39 |
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", package])
|
| 40 |
|
| 41 |
import requests
|
| 42 |
import spaces
|
| 43 |
import torch
|
| 44 |
+
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
|
| 45 |
+
from threading import Thread
|
| 46 |
import gradio as gr
|
| 47 |
from bs4 import BeautifulSoup
|
| 48 |
|
| 49 |
+
# =====================================================================
|
| 50 |
+
# 2. NETWORK IP LOGGING UNDER /px
|
| 51 |
+
# =====================================================================
|
| 52 |
def get_ip_addresses():
|
| 53 |
try:
|
| 54 |
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
|
|
| 57 |
s.close()
|
| 58 |
except Exception:
|
| 59 |
local_ip = "127.0.0.1"
|
|
|
|
| 60 |
try:
|
| 61 |
public_ip = requests.get("https://api.ipify.org", timeout=5).text.strip()
|
| 62 |
except Exception:
|
| 63 |
+
public_ip = "Online Server Space"
|
|
|
|
| 64 |
return local_ip, public_ip
|
| 65 |
|
| 66 |
local_ip, server_public_ip = get_ip_addresses()
|
| 67 |
timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
|
|
|
|
|
| 68 |
with open(LOG_FILE, "a") as log_file:
|
| 69 |
+
log_file.write(f"[{timestamp}] - Web Chat Online | Server IP: {server_public_ip}\n")
|
| 70 |
|
| 71 |
+
print("\n" + "β" * 65)
|
| 72 |
+
print(f"π PX TECH SOLUTIONS - EVAL BETA 0.2 (AGENTIC ZEROGPU CORE)")
|
| 73 |
print(f" β’ Base Directory : {BASE_DIR}")
|
|
|
|
| 74 |
print(f" β’ Server IP : {server_public_ip}")
|
| 75 |
+
print("β" * 65 + "\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
|
| 77 |
# =====================================================================
|
| 78 |
+
# 3. ZEROGPU-COMPATIBLE MODEL INITIALIZATION
|
| 79 |
# =====================================================================
|
| 80 |
+
MODEL_ID = "HuggingFaceTB/SmolLM2-1.7B-Instruct"
|
| 81 |
+
print(f"π§ Loading AI Model ({MODEL_ID})...")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
|
| 83 |
+
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
|
| 84 |
+
# In ZeroGPU, device_map="auto" allows the framework to dynamically shift tensors
|
| 85 |
+
model = AutoModelForCausalLM.from_pretrained(
|
| 86 |
+
MODEL_ID,
|
| 87 |
+
torch_dtype=torch.float16 if torch.cuda.is_available() else torch.float32,
|
| 88 |
+
device_map="auto"
|
| 89 |
+
)
|
| 90 |
+
|
| 91 |
+
# =====================================================================
|
| 92 |
+
# 4. ROBUST AGENTIC TOOLS SUITE
|
| 93 |
+
# =====================================================================
|
| 94 |
def execute_tool(name, args, ip_folder, yolo_mode):
|
| 95 |
try:
|
| 96 |
if name == "bash":
|
| 97 |
cmd = args.get("command", "")
|
| 98 |
if not yolo_mode and any(danger in cmd for danger in ["rm -rf /", "mkfs", "dd if="]):
|
| 99 |
+
return "β Security Error: Command blocked by YOLO Security Sandbox."
|
| 100 |
+
res = subprocess.run(cmd, shell=True, capture_output=True, text=True, cwd=ip_folder, timeout=45)
|
| 101 |
+
output = res.stdout if res.returncode == 0 else f"STDOUT:\n{res.stdout}\nSTDERR:\n{res.stderr}"
|
| 102 |
+
return output[:8000] if output else "β
Command executed successfully (No output)."
|
| 103 |
|
| 104 |
elif name == "write_file":
|
| 105 |
filepath = args.get("filepath")
|
|
|
|
| 108 |
os.makedirs(os.path.dirname(safe_path), exist_ok=True)
|
| 109 |
with open(safe_path, "w", encoding="utf-8") as f:
|
| 110 |
f.write(content)
|
| 111 |
+
return f"β
File successfully written to {safe_path}"
|
| 112 |
|
| 113 |
elif name == "read_file":
|
| 114 |
filepath = args.get("filepath")
|
|
|
|
| 116 |
if not os.path.exists(safe_path) and os.path.exists(filepath):
|
| 117 |
safe_path = filepath
|
| 118 |
if not os.path.exists(safe_path):
|
| 119 |
+
return f"β Error: File '{filepath}' not found."
|
| 120 |
with open(safe_path, "r", encoding="utf-8", errors="ignore") as f:
|
| 121 |
return f.read()[:15000]
|
| 122 |
|
|
|
|
| 126 |
headers = {"User-Agent": "Mozilla/5.0"}
|
| 127 |
resp = requests.get(url, headers=headers, timeout=10)
|
| 128 |
soup = BeautifulSoup(resp.text, "html.parser")
|
| 129 |
+
results = [a.get_text(strip=True) for a in soup.find_all("a", class_="result__snippet", limit=5)]
|
| 130 |
+
return "\n\n".join(results) if results else "β No web search results retrieved."
|
| 131 |
|
| 132 |
else:
|
| 133 |
+
return f"β Error: Unknown tool '{name}'"
|
| 134 |
except Exception as e:
|
| 135 |
+
return f"β Tool execution failed: {str(e)}"
|
| 136 |
|
| 137 |
# =====================================================================
|
| 138 |
+
# 5. MULTI-TURN AGENTIC INFERENCE LOOP (ZeroGPU Decorated)
|
| 139 |
# =====================================================================
|
| 140 |
@spaces.GPU(duration=120)
|
| 141 |
def predict(message, history, system_prompt, temperature, yolo_mode, request: gr.Request):
|
| 142 |
+
# Extract & isolate client IP
|
| 143 |
client_ip = "127.0.0.1"
|
| 144 |
if request and request.headers:
|
| 145 |
+
client_ip = request.headers.get("x-forwarded-for", client_ip).split(",")[0].strip()
|
| 146 |
+
elif request and request.client:
|
| 147 |
+
client_ip = request.client.host
|
|
|
|
|
|
|
| 148 |
|
| 149 |
safe_ip = client_ip.replace(":", "_").replace(".", "_")
|
| 150 |
ip_folder = os.path.join(IPS_DIR, safe_ip)
|
| 151 |
os.makedirs(ip_folder, exist_ok=True)
|
| 152 |
+
history_log_path = os.path.join(ip_folder, "chat_history.log")
|
| 153 |
|
| 154 |
+
# Global context & YOLO setup
|
| 155 |
+
security_mode = "DISABLED (GOD-MODE)" if yolo_mode else "ENABLED (SECURE)"
|
| 156 |
+
global_text = open(global_context_path, "r").read() if os.path.exists(global_context_path) else ""
|
| 157 |
|
| 158 |
+
agent_instructions = """
|
| 159 |
+
You have access to powerful tools. To use a tool, you MUST output a JSON block wrapped in <tool_call> tags:
|
| 160 |
+
|
| 161 |
+
<tool_call>
|
| 162 |
+
{"name": "bash", "arguments": {"command": "ls -la"}}
|
| 163 |
+
</tool_call>
|
| 164 |
+
|
| 165 |
+
Available Tools:
|
| 166 |
+
1. bash - Execute shell commands. Args: {"command": "<command string>"}
|
| 167 |
+
2. write_file - Write to a file. Args: {"filepath": "<path>", "content": "<string>"}
|
| 168 |
+
3. read_file - Read a file. Args: {"filepath": "<path>"}
|
| 169 |
+
4. web_search - Search the live web. Args: {"query": "<search query>"}
|
| 170 |
+
|
| 171 |
+
If you use a tool, wait for the <tool_response> before continuing.
|
| 172 |
+
"""
|
| 173 |
|
| 174 |
if yolo_mode:
|
| 175 |
+
yolo_instructions = "\nπ₯ [YOLO MODE: ON] Absolute root permissions granted. Execute shell scripts and downloads freely under /px."
|
|
|
|
|
|
|
|
|
|
|
|
|
| 176 |
else:
|
| 177 |
+
yolo_instructions = "\nπ [YOLO MODE: OFF] Standard security limits apply."
|
|
|
|
|
|
|
|
|
|
| 178 |
|
| 179 |
+
enhanced_system_prompt = f"{system_prompt}\n{agent_instructions}\n{yolo_instructions}\n\n--- [GLOBAL CONTEXT] ---\n{global_text}\n\n--- [USER IP CONTEXT] ---\nClient IP: {client_ip} | Folder: {ip_folder} | Security: {security_mode}"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
|
| 181 |
+
# Build chat history
|
| 182 |
+
chat_messages = [{"role": "system", "content": enhanced_system_prompt}]
|
| 183 |
for human, assistant in history:
|
| 184 |
+
chat_messages.append({"role": "user", "content": human})
|
| 185 |
+
chat_messages.append({"role": "assistant", "content": assistant})
|
| 186 |
+
chat_messages.append({"role": "user", "content": message})
|
| 187 |
|
|
|
|
| 188 |
with open(history_log_path, "a") as hf:
|
| 189 |
+
hf.write(f"[{timestamp}] User (YOLO: {yolo_mode}): {message}\n")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
|
| 191 |
+
# Autonomous Multi-Step Loop
|
| 192 |
+
max_turns = 4
|
| 193 |
+
turn = 0
|
| 194 |
accumulated_output = ""
|
| 195 |
+
|
| 196 |
+
while turn < max_turns:
|
| 197 |
+
turn += 1
|
| 198 |
+
prompt = tokenizer.apply_chat_template(chat_messages, tokenize=False, add_generation_prompt=True)
|
| 199 |
+
inputs = tokenizer(prompt, return_tensors="pt").to(model.device)
|
| 200 |
+
|
| 201 |
+
streamer = TextIteratorStreamer(tokenizer, skip_prompt=True, skip_special_tokens=True)
|
| 202 |
+
generation_kwargs = dict(
|
| 203 |
+
**inputs,
|
| 204 |
+
streamer=streamer,
|
| 205 |
+
max_new_tokens=1024,
|
| 206 |
+
temperature=max(temperature, 0.01),
|
| 207 |
+
do_sample=True if temperature > 0 else False
|
| 208 |
+
)
|
| 209 |
+
|
| 210 |
+
thread = Thread(target=model.generate, kwargs=generation_kwargs)
|
| 211 |
+
thread.start()
|
| 212 |
+
|
| 213 |
+
turn_response = ""
|
| 214 |
+
for new_text in streamer:
|
| 215 |
+
turn_response += new_text
|
| 216 |
+
yield accumulated_output + turn_response
|
| 217 |
+
|
| 218 |
+
accumulated_output += turn_response
|
| 219 |
+
chat_messages.append({"role": "assistant", "content": turn_response})
|
| 220 |
+
|
| 221 |
+
# Intercept and Parse Tool Calls
|
| 222 |
+
tool_call_match = re.search(r'<tool_call>(.*?)</tool_call>', turn_response, re.DOTALL)
|
| 223 |
+
if tool_call_match:
|
| 224 |
+
try:
|
| 225 |
+
tool_json = json.loads(tool_call_match.group(1).strip())
|
| 226 |
+
func_name = tool_json.get("name")
|
| 227 |
+
func_args = tool_json.get("arguments", {})
|
| 228 |
+
|
| 229 |
+
yield accumulated_output + f"\n\nβοΈ `[Executing Tool: {func_name} | Args: {json.dumps(func_args)}]`...\n"
|
| 230 |
+
|
| 231 |
+
# Run Tool
|
| 232 |
+
tool_result = execute_tool(func_name, func_args, ip_folder, yolo_mode)
|
| 233 |
+
|
| 234 |
+
# Feedback loop
|
| 235 |
+
tool_feedback = f"\n<tool_response>\n{tool_result}\n</tool_response>\n"
|
| 236 |
+
accumulated_output += tool_feedback
|
| 237 |
+
yield accumulated_output
|
| 238 |
+
|
| 239 |
+
chat_messages.append({"role": "user", "content": f"System Tool Output:\n{tool_result}\nAnalyze this and continue your task."})
|
| 240 |
+
except Exception as e:
|
| 241 |
+
error_fb = f"\n<tool_response>Error parsing JSON: {str(e)}</tool_response>\n"
|
| 242 |
+
accumulated_output += error_fb
|
| 243 |
+
chat_messages.append({"role": "user", "content": error_fb})
|
| 244 |
+
yield accumulated_output
|
| 245 |
+
else:
|
| 246 |
+
# If no tools were called, the agent has finished responding.
|
| 247 |
+
break
|
| 248 |
|
| 249 |
with open(history_log_path, "a") as hf:
|
| 250 |
hf.write(f"[{timestamp}] Assistant: {accumulated_output}\n")
|
|
|
|
| 252 |
def update_global_context(new_content):
|
| 253 |
with open(global_context_path, "w") as f:
|
| 254 |
f.write(new_content)
|
| 255 |
+
return "β
Global context updated successfully under /px!"
|
| 256 |
|
| 257 |
# =====================================================================
|
| 258 |
+
# 6. GRADIO WEB INTERFACE (CYBER-DARK STYLING)
|
| 259 |
# =====================================================================
|
| 260 |
+
custom_css = """
|
| 261 |
+
body { background-color: #0b0f19; color: #e2e8f0; font-family: 'Inter', sans-serif; }
|
| 262 |
+
.gradio-container { max-width: 1100px !important; margin: auto; padding-top: 20px; }
|
| 263 |
+
.gr-button-primary { background: linear-gradient(90deg, #3b82f6, #06b6d4) !important; border: none !important; }
|
| 264 |
+
.dark \.gr-panel { background-color: #111827 !important; border: 1px solid #1f2937 !important; }
|
| 265 |
+
code { color: #22d3ee !important; background-color: #1e293b !important; padding: 2px 6px; border-radius: 4px; }
|
| 266 |
+
pre code { color: #f8fafc !important; }
|
| 267 |
+
"""
|
| 268 |
+
|
| 269 |
+
with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="cyan"), css=custom_css) as demo:
|
| 270 |
gr.Markdown(
|
| 271 |
"""
|
| 272 |
+
# β‘ EVAL BETA 0.2 | PX TECH SOLUTIONS (AGENTIC ZEROGPU CORE)
|
| 273 |
+
### Autonomous Web Environment with ZeroGPU AI, Full Tool-Use, & YOLO God-Mode
|
| 274 |
"""
|
| 275 |
)
|
| 276 |
|
| 277 |
with gr.Row():
|
| 278 |
+
gr.Markdown("π’ **Status:** ZeroGPU Online | β±οΈ **Slot 1 Queue Active** | π οΈ **Agent Loop:** Bash, Write, Read, Web Search")
|
| 279 |
|
| 280 |
+
with gr.Accordion("βοΈ Engine Configuration, Global Context & Security", open=False):
|
| 281 |
system_prompt_input = gr.Textbox(
|
| 282 |
label="System Environment Prompt",
|
| 283 |
+
value="You are EVAL BETA 0.2, an elite autonomous programming agent created by Pripro / PX TECH SOLUTIONS. Think logically and step-by-step.",
|
| 284 |
lines=2
|
| 285 |
)
|
| 286 |
+
with gr.Row():
|
| 287 |
+
temperature_slider = gr.Slider(minimum=0.0, maximum=1.0, value=0.3, step=0.05, label="Creativity / Temperature")
|
| 288 |
+
yolo_checkbox = gr.Checkbox(label="π₯ Enable YOLO Mode (Disables Sandbox Security)", value=False)
|
| 289 |
+
|
|
|
|
|
|
|
|
|
|
|
|
|
| 290 |
global_context_view = gr.Textbox(
|
| 291 |
+
label=f"π Shared Global Memory Workspace ({global_context_path})",
|
| 292 |
value=open(global_context_path).read() if os.path.exists(global_context_path) else "",
|
| 293 |
+
lines=4
|
|
|
|
| 294 |
)
|
| 295 |
+
update_btn = gr.Button("πΎ Save Global Context Changes", variant="primary")
|
| 296 |
update_status = gr.Textbox(label="Workspace Status", interactive=False)
|
| 297 |
update_btn.click(update_global_context, inputs=[global_context_view], outputs=[update_status])
|
| 298 |
|
| 299 |
gr.ChatInterface(
|
| 300 |
fn=predict,
|
| 301 |
additional_inputs=[system_prompt_input, temperature_slider, yolo_checkbox],
|
| 302 |
+
textbox=gr.Textbox(placeholder="Instruct the AI: 'Search the web for Python 3.12 features', 'Write a script and run it via bash'...", container=False, scale=7)
|
| 303 |
)
|
| 304 |
|
| 305 |
gr.Markdown(
|
| 306 |
"""
|
| 307 |
---
|
| 308 |
+
**Architecture & Security:** Enforces a strict queue (`concurrency_limit=1`) with Slot 1 allocation. All workspace data, logs, and IPs are securely sandboxed under the root `/px` architecture.
|
| 309 |
"""
|
| 310 |
)
|
| 311 |
|
| 312 |
if __name__ == "__main__":
|
| 313 |
+
print(f"π Launching Agentic ZeroGPU chat server on port 7860...")
|
| 314 |
demo.queue(default_concurrency_limit=1, max_size=20)
|
| 315 |
+
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|