CORVO-AI commited on
Commit
fbc7990
·
verified ·
1 Parent(s): 0c626a7

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +15 -53
app.py CHANGED
@@ -3,15 +3,13 @@ import gradio as gr
3
  import subprocess, os, sys, time
4
  import urllib.request, urllib.error
5
  from fastapi import Request
6
- from fastapi.responses import Response, PlainTextResponse, HTMLResponse, StreamingResponse
7
 
8
  PORT = 9001
9
  FM_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "file-manager")
10
  MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct"
11
 
12
- # =================================================================
13
- # Launch the file manager as a background child process
14
- # =================================================================
15
  proc = {"p": None}
16
  def start_fm():
17
  if proc["p"] and proc["p"].poll() is None:
@@ -25,9 +23,7 @@ def start_fm():
25
 
26
  start_fm()
27
 
28
- # =================================================================
29
- # GPU info: runs nvidia-smi INSIDE the gate (GPU only attached here)
30
- # =================================================================
31
  @spaces.GPU
32
  def gpu_report():
33
  import torch
@@ -45,9 +41,7 @@ def gpu_report():
45
  lines.append(f"nvidia-smi error: {e}")
46
  return "\n".join(lines)
47
 
48
- # =================================================================
49
- # LLM inference: model loads + generates INSIDE the gate
50
- # =================================================================
51
  _state = {"model": None, "tok": None}
52
 
53
  @spaces.GPU
@@ -66,11 +60,9 @@ def run_llm(prompt: str):
66
  reply = tok.decode(out[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
67
  return f"[GPU: {torch.cuda.get_device_name(0)}]\n\n{reply}"
68
 
69
- # =================================================================
70
- # Gradio owns the ONLY public port 7860
71
- # =================================================================
72
  with gr.Blocks() as demo:
73
- gr.Markdown("Self-editing computer. File manager + terminal + Python REPL at /fm")
74
  with gr.Row():
75
  prompt = gr.Textbox(label="Ask the LLM")
76
  out = gr.Textbox(label="Reply")
@@ -82,36 +74,24 @@ demo.queue()
82
  demo.launch(server_name="0.0.0.0", server_port=7860,
83
  ssr_mode=False, prevent_thread_lock=True)
84
 
85
- app = demo.app # Gradio's FastAPI app on 7860
86
 
87
- # =================================================================
88
- # Hot-reload: respawn ONLY the file-manager process, no Space rebuild
89
- # =================================================================
90
  @app.get("/reload")
91
  def reload_fm():
92
  start_fm()
93
  time.sleep(1)
94
  return HTMLResponse('Reloaded file-manager process. <a href="/fm/">back to /fm</a>')
95
 
96
- # =================================================================
97
- # GPU info route
98
- # =================================================================
99
  @app.get("/gpuinfo")
100
  def gpuinfo():
101
  return PlainTextResponse(gpu_report())
102
 
103
- # =================================================================
104
- # LLM route
105
- # =================================================================
106
  @app.get("/llm")
107
  def llm(q: str = "Say hello and tell me which GPU you are running on."):
108
  return PlainTextResponse(run_llm(q))
109
 
110
- # =================================================================
111
- # Proxy: /fm/... -> 127.0.0.1:9001/fm/...
112
- # Streams text/plain (live shell) chunk by chunk; buffers everything else.
113
- # Forwards method + body so POST forms and the JSON REPL work.
114
- # =================================================================
115
  @app.api_route("/fm", methods=["GET", "POST"])
116
  @app.api_route("/fm/{path:path}", methods=["GET", "POST"])
117
  async def proxy(request: Request, path: str = ""):
@@ -122,33 +102,15 @@ async def proxy(request: Request, path: str = ""):
122
  fwd = {k: v for k, v in request.headers.items() if k.lower() != "host"}
123
  req = urllib.request.Request(url, data=body or None, method=request.method, headers=fwd)
124
  try:
125
- r = urllib.request.urlopen(req)
 
126
  except urllib.error.HTTPError as e:
127
- return Response(
128
- content=e.read(), status_code=e.code,
129
- headers={"content-type": e.headers.get("content-type", "text/plain")})
130
  except urllib.error.URLError:
131
  return Response(content=b"file-manager not up yet on 9001", status_code=502)
 
 
 
132
 
133
- ctype = r.headers.get("content-type", "text/html")
134
- # Stream the live shell output; buffer normal pages
135
- if ctype.startswith("text/plain"):
136
- def gen():
137
- while True:
138
- chunk = r.read(1024)
139
- if not chunk:
140
- break
141
- yield chunk
142
- return StreamingResponse(gen(), media_type="text/plain")
143
-
144
- out_headers = {"content-type": ctype}
145
- for k, v in r.headers.items():
146
- if k.lower() in ("set-cookie", "location"):
147
- out_headers[k] = v
148
- return Response(content=r.read(), status_code=r.status, headers=out_headers)
149
-
150
- # =================================================================
151
- # Keep the process alive (launch returned control)
152
- # =================================================================
153
  while True:
154
  time.sleep(3600)
 
3
  import subprocess, os, sys, time
4
  import urllib.request, urllib.error
5
  from fastapi import Request
6
+ from fastapi.responses import Response, PlainTextResponse, HTMLResponse
7
 
8
  PORT = 9001
9
  FM_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "file-manager")
10
  MODEL_ID = "Qwen/Qwen2.5-0.5B-Instruct"
11
 
12
+ # --- Launch the file manager as a background child process ---
 
 
13
  proc = {"p": None}
14
  def start_fm():
15
  if proc["p"] and proc["p"].poll() is None:
 
23
 
24
  start_fm()
25
 
26
+ # --- GPU info (runs INSIDE the gate) ---
 
 
27
  @spaces.GPU
28
  def gpu_report():
29
  import torch
 
41
  lines.append(f"nvidia-smi error: {e}")
42
  return "\n".join(lines)
43
 
44
+ # --- LLM (loads + generates INSIDE the gate) ---
 
 
45
  _state = {"model": None, "tok": None}
46
 
47
  @spaces.GPU
 
60
  reply = tok.decode(out[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
61
  return f"[GPU: {torch.cuda.get_device_name(0)}]\n\n{reply}"
62
 
63
+ # --- Gradio owns the ONLY public port 7860 ---
 
 
64
  with gr.Blocks() as demo:
65
+ gr.Markdown("Self-editing computer. Terminal + file manager at /fm")
66
  with gr.Row():
67
  prompt = gr.Textbox(label="Ask the LLM")
68
  out = gr.Textbox(label="Reply")
 
74
  demo.launch(server_name="0.0.0.0", server_port=7860,
75
  ssr_mode=False, prevent_thread_lock=True)
76
 
77
+ app = demo.app
78
 
79
+ # --- Hot-reload: respawn ONLY the file-manager process, no Space rebuild ---
 
 
80
  @app.get("/reload")
81
  def reload_fm():
82
  start_fm()
83
  time.sleep(1)
84
  return HTMLResponse('Reloaded file-manager process. <a href="/fm/">back to /fm</a>')
85
 
 
 
 
86
  @app.get("/gpuinfo")
87
  def gpuinfo():
88
  return PlainTextResponse(gpu_report())
89
 
 
 
 
90
  @app.get("/llm")
91
  def llm(q: str = "Say hello and tell me which GPU you are running on."):
92
  return PlainTextResponse(run_llm(q))
93
 
94
+ # --- Proxy: /fm/... -> 127.0.0.1:9001/fm/... (method + body forwarded) ---
 
 
 
 
95
  @app.api_route("/fm", methods=["GET", "POST"])
96
  @app.api_route("/fm/{path:path}", methods=["GET", "POST"])
97
  async def proxy(request: Request, path: str = ""):
 
102
  fwd = {k: v for k, v in request.headers.items() if k.lower() != "host"}
103
  req = urllib.request.Request(url, data=body or None, method=request.method, headers=fwd)
104
  try:
105
+ with urllib.request.urlopen(req) as r:
106
+ data, status, headers = r.read(), r.status, r.headers
107
  except urllib.error.HTTPError as e:
108
+ data, status, headers = e.read(), e.code, e.headers
 
 
109
  except urllib.error.URLError:
110
  return Response(content=b"file-manager not up yet on 9001", status_code=502)
111
+ out = {k: v for k, v in headers.items()
112
+ if k.lower() in ("set-cookie", "location", "content-type")}
113
+ return Response(content=data, status_code=status, headers=out)
114
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
115
  while True:
116
  time.sleep(3600)