Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,7 +1,6 @@
|
|
| 1 |
import warnings
|
| 2 |
-
warnings.filterwarnings("ignore"
|
| 3 |
import gradio as gr
|
| 4 |
-
import torch
|
| 5 |
import time
|
| 6 |
import sys
|
| 7 |
import subprocess
|
|
@@ -18,15 +17,14 @@ import ast
|
|
| 18 |
import json
|
| 19 |
import tempfile
|
| 20 |
from pathlib import Path
|
| 21 |
-
from
|
| 22 |
from typing import List, Dict
|
| 23 |
from functools import lru_cache
|
| 24 |
|
| 25 |
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
| 26 |
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
DTYPE = torch.float32
|
| 30 |
DISPLAY_NUM = ":99"
|
| 31 |
SCREEN_W, SCREEN_H = 800, 600
|
| 32 |
SNIPPETS_FILE = "/tmp/axon_snippets.json"
|
|
@@ -419,30 +417,62 @@ class PTYTerminal:
|
|
| 419 |
terminal = PTYTerminal()
|
| 420 |
|
| 421 |
# ═══════════════════════════════════════
|
| 422 |
-
# AI Model
|
| 423 |
# ═══════════════════════════════════════
|
| 424 |
-
|
|
|
|
|
|
|
| 425 |
def load_model():
|
| 426 |
-
|
| 427 |
-
|
| 428 |
-
|
| 429 |
-
|
| 430 |
-
|
| 431 |
-
|
| 432 |
-
|
| 433 |
-
|
| 434 |
-
print(f"
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 438 |
|
| 439 |
-
def ai_gen(system_prompt, code, max_tokens=256):
|
| 440 |
-
pipe = load_model()
|
| 441 |
-
if not pipe: return "Error: model failed to load"
|
| 442 |
-
prompt = f"<|system|>{system_prompt}</s><|user|>\n{code}\n</s><|assistant|>"
|
| 443 |
try:
|
| 444 |
-
|
| 445 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 446 |
except Exception as e:
|
| 447 |
return f"Error: {e}"
|
| 448 |
|
|
@@ -609,6 +639,11 @@ with gr.Blocks(title="Axon Pro") as demo:
|
|
| 609 |
|
| 610 |
with gr.Tabs() as bottom_tabs:
|
| 611 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 612 |
with gr.Tab("⌘ TERMINAL", id="term-tab"):
|
| 613 |
term_out = gr.Textbox(value=terminal.get_log(), lines=12, max_lines=25,
|
| 614 |
interactive=False, elem_classes="term-box",
|
|
@@ -661,7 +696,7 @@ with gr.Blocks(title="Axon Pro") as demo:
|
|
| 661 |
|
| 662 |
status_bar = gr.Markdown(
|
| 663 |
f"**AXON PRO v4.0** │ Python {sys.version.split()[0]} │ CPU │ "
|
| 664 |
-
f"
|
| 665 |
elem_classes="status-bar")
|
| 666 |
|
| 667 |
# State
|
|
@@ -695,7 +730,7 @@ with gr.Blocks(title="Axon Pro") as demo:
|
|
| 695 |
def on_save(code):
|
| 696 |
fs.save_file(code)
|
| 697 |
return (f"**AXON PRO v4.0** │ Python {sys.version.split()[0]} │ CPU │ "
|
| 698 |
-
f"
|
| 699 |
|
| 700 |
def on_delete():
|
| 701 |
name = fs.current_file
|
|
@@ -712,13 +747,9 @@ with gr.Blocks(title="Axon Pro") as demo:
|
|
| 712 |
if is_gui_code(code):
|
| 713 |
# GUI app — launch as background process, capture display
|
| 714 |
msg = gui_mgr.launch(code)
|
| 715 |
-
|
| 716 |
-
time.sleep(1.5)
|
| 717 |
-
ss = vdisplay.capture()
|
| 718 |
-
return terminal.get_log(), ss, f"<small>Xvfb: ● ON | {gui_mgr.get_status()}</small>"
|
| 719 |
|
| 720 |
-
# Normal script — run with subprocess,
|
| 721 |
-
terminal._append("$ python [editor]")
|
| 722 |
tmp = "/tmp/_axon_run.py"
|
| 723 |
with open(tmp, "w") as f: f.write(code)
|
| 724 |
try:
|
|
@@ -727,12 +758,17 @@ with gr.Blocks(title="Axon Pro") as demo:
|
|
| 727 |
env["PYTHONPATH"] = fs._sync_dir + ":" + env.get("PYTHONPATH", "")
|
| 728 |
r = subprocess.run([sys.executable, tmp], capture_output=True, text=True,
|
| 729 |
timeout=30, env=env, cwd=fs._sync_dir)
|
| 730 |
-
|
| 731 |
-
if r.
|
| 732 |
-
if
|
| 733 |
-
|
| 734 |
-
|
| 735 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 736 |
|
| 737 |
def on_stop():
|
| 738 |
msg = gui_mgr.stop(); terminal._append(msg)
|
|
@@ -834,7 +870,8 @@ with gr.Blocks(title="Axon Pro") as demo:
|
|
| 834 |
del_btn.click(on_delete, None, [file_list, editor, editor, structure_view])
|
| 835 |
|
| 836 |
# Run
|
| 837 |
-
run_btn.click(on_run, editor, [
|
|
|
|
| 838 |
stop_btn.click(on_stop, None, [term_out, gui_status])
|
| 839 |
|
| 840 |
# Terminal
|
|
|
|
| 1 |
import warnings
|
| 2 |
+
warnings.filterwarnings("ignore")
|
| 3 |
import gradio as gr
|
|
|
|
| 4 |
import time
|
| 5 |
import sys
|
| 6 |
import subprocess
|
|
|
|
| 17 |
import json
|
| 18 |
import tempfile
|
| 19 |
from pathlib import Path
|
| 20 |
+
from huggingface_hub import hf_hub_download
|
| 21 |
from typing import List, Dict
|
| 22 |
from functools import lru_cache
|
| 23 |
|
| 24 |
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
| 25 |
|
| 26 |
+
MODEL_REPO = "AIencoder/Qwen2.5CMR-Q4_K_M-GGUF"
|
| 27 |
+
MODEL_FILE = "qwen2.5cmr-q4_k_m.gguf"
|
|
|
|
| 28 |
DISPLAY_NUM = ":99"
|
| 29 |
SCREEN_W, SCREEN_H = 800, 600
|
| 30 |
SNIPPETS_FILE = "/tmp/axon_snippets.json"
|
|
|
|
| 417 |
terminal = PTYTerminal()
|
| 418 |
|
| 419 |
# ═══════════════════════════════════════
|
| 420 |
+
# AI Model — Qwen2.5CMR Q4_K_M GGUF
|
| 421 |
# ═══════════════════════════════════════
|
| 422 |
+
_llm_instance = None
|
| 423 |
+
_llm_lock = threading.Lock()
|
| 424 |
+
|
| 425 |
def load_model():
|
| 426 |
+
global _llm_instance
|
| 427 |
+
if _llm_instance is not None:
|
| 428 |
+
return _llm_instance
|
| 429 |
+
|
| 430 |
+
with _llm_lock:
|
| 431 |
+
if _llm_instance is not None:
|
| 432 |
+
return _llm_instance
|
| 433 |
+
|
| 434 |
+
print(f"Downloading {MODEL_REPO}/{MODEL_FILE}...")
|
| 435 |
+
t0 = time.time()
|
| 436 |
+
try:
|
| 437 |
+
model_path = hf_hub_download(
|
| 438 |
+
repo_id=MODEL_REPO,
|
| 439 |
+
filename=MODEL_FILE,
|
| 440 |
+
)
|
| 441 |
+
print(f"Downloaded in {time.time()-t0:.1f}s, loading...")
|
| 442 |
+
|
| 443 |
+
from llama_cpp import Llama
|
| 444 |
+
_llm_instance = Llama(
|
| 445 |
+
model_path=model_path,
|
| 446 |
+
n_ctx=4096,
|
| 447 |
+
n_threads=os.cpu_count() or 4,
|
| 448 |
+
n_gpu_layers=0, # CPU only
|
| 449 |
+
verbose=False,
|
| 450 |
+
)
|
| 451 |
+
print(f"Model ready in {time.time()-t0:.1f}s total")
|
| 452 |
+
return _llm_instance
|
| 453 |
+
except Exception as e:
|
| 454 |
+
print(f"Model error: {e}")
|
| 455 |
+
return None
|
| 456 |
+
|
| 457 |
+
def ai_gen(system_prompt, code, max_tokens=300):
|
| 458 |
+
llm = load_model()
|
| 459 |
+
if not llm: return "Error: model failed to load"
|
| 460 |
+
|
| 461 |
+
messages = [
|
| 462 |
+
{"role": "system", "content": system_prompt},
|
| 463 |
+
{"role": "user", "content": code},
|
| 464 |
+
]
|
| 465 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 466 |
try:
|
| 467 |
+
response = llm.create_chat_completion(
|
| 468 |
+
messages=messages,
|
| 469 |
+
max_tokens=max_tokens,
|
| 470 |
+
temperature=0.3,
|
| 471 |
+
top_p=0.9,
|
| 472 |
+
repeat_penalty=1.1,
|
| 473 |
+
)
|
| 474 |
+
text = response["choices"][0]["message"]["content"].strip()
|
| 475 |
+
return text if text else "(No output from model)"
|
| 476 |
except Exception as e:
|
| 477 |
return f"Error: {e}"
|
| 478 |
|
|
|
|
| 639 |
|
| 640 |
with gr.Tabs() as bottom_tabs:
|
| 641 |
|
| 642 |
+
with gr.Tab("▶ OUTPUT", id="output-tab"):
|
| 643 |
+
run_output = gr.Textbox(value="Run your code to see output here.",
|
| 644 |
+
lines=12, max_lines=25, interactive=False,
|
| 645 |
+
elem_classes="term-box", label="", show_label=False)
|
| 646 |
+
|
| 647 |
with gr.Tab("⌘ TERMINAL", id="term-tab"):
|
| 648 |
term_out = gr.Textbox(value=terminal.get_log(), lines=12, max_lines=25,
|
| 649 |
interactive=False, elem_classes="term-box",
|
|
|
|
| 696 |
|
| 697 |
status_bar = gr.Markdown(
|
| 698 |
f"**AXON PRO v4.0** │ Python {sys.version.split()[0]} │ CPU │ "
|
| 699 |
+
f"Qwen2.5CMR Q4_K_M │ PTY + Xvfb │ Snippets + Structure + Find",
|
| 700 |
elem_classes="status-bar")
|
| 701 |
|
| 702 |
# State
|
|
|
|
| 730 |
def on_save(code):
|
| 731 |
fs.save_file(code)
|
| 732 |
return (f"**AXON PRO v4.0** │ Python {sys.version.split()[0]} │ CPU │ "
|
| 733 |
+
f"Qwen2.5CMR Q4_K_M │ ✓ Saved {fs.current_file}")
|
| 734 |
|
| 735 |
def on_delete():
|
| 736 |
name = fs.current_file
|
|
|
|
| 747 |
if is_gui_code(code):
|
| 748 |
# GUI app — launch as background process, capture display
|
| 749 |
msg = gui_mgr.launch(code)
|
| 750 |
+
return msg, vdisplay.capture(), f"<small>Xvfb: ● ON | {gui_mgr.get_status()}</small>"
|
|
|
|
|
|
|
|
|
|
| 751 |
|
| 752 |
+
# Normal script — run with subprocess, output goes to OUTPUT tab
|
|
|
|
| 753 |
tmp = "/tmp/_axon_run.py"
|
| 754 |
with open(tmp, "w") as f: f.write(code)
|
| 755 |
try:
|
|
|
|
| 758 |
env["PYTHONPATH"] = fs._sync_dir + ":" + env.get("PYTHONPATH", "")
|
| 759 |
r = subprocess.run([sys.executable, tmp], capture_output=True, text=True,
|
| 760 |
timeout=30, env=env, cwd=fs._sync_dir)
|
| 761 |
+
output = ""
|
| 762 |
+
if r.stdout.strip(): output += r.stdout.rstrip()
|
| 763 |
+
if r.stderr.strip():
|
| 764 |
+
if output: output += "\n"
|
| 765 |
+
output += r.stderr.rstrip()
|
| 766 |
+
if not output: output = "(No output)"
|
| 767 |
+
except subprocess.TimeoutExpired:
|
| 768 |
+
output = "[Timed out after 30s]"
|
| 769 |
+
except Exception as e:
|
| 770 |
+
output = f"[Error] {e}"
|
| 771 |
+
return output, gr.update(), gr.update()
|
| 772 |
|
| 773 |
def on_stop():
|
| 774 |
msg = gui_mgr.stop(); terminal._append(msg)
|
|
|
|
| 870 |
del_btn.click(on_delete, None, [file_list, editor, editor, structure_view])
|
| 871 |
|
| 872 |
# Run
|
| 873 |
+
run_btn.click(on_run, editor, [run_output, display_image, gui_status]
|
| 874 |
+
).then(lambda: gr.Tabs(selected="output-tab"), None, bottom_tabs)
|
| 875 |
stop_btn.click(on_stop, None, [term_out, gui_status])
|
| 876 |
|
| 877 |
# Terminal
|