wuhp commited on
Commit
4e8c436
·
verified ·
1 Parent(s): 1c7f8b9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +46 -81
app.py CHANGED
@@ -1,11 +1,10 @@
1
  import re
2
  import json
3
  import time
4
- import os
5
  import importlib.metadata
6
 
7
  import gradio as gr
8
- from huggingface_hub import create_repo, upload_file, list_models, constants, Repository
9
  from huggingface_hub.utils import build_hf_headers, get_session, hf_raise_for_status
10
  from google import genai
11
  from google.genai.types import Tool, GenerateContentConfig, GoogleSearch
@@ -40,9 +39,13 @@ def get_sdk_version(sdk_choice: str) -> str:
40
 
41
  def extract_code(text: str) -> str:
42
  """
43
- Extract the last ```…``` block. If none, return whole text.
 
 
44
  """
45
- blocks = re.findall(r"```(?:\w*\n)?([\s\S]*?)```", text)
 
 
46
  return blocks[-1].strip() if blocks else text.strip()
47
 
48
  # — HF SPACE LOGGING —
@@ -63,36 +66,13 @@ def fetch_logs(repo_id: str, level: str) -> str:
63
  if raw.startswith(b"data: "):
64
  try:
65
  ev = json.loads(raw[len(b"data: "):].decode())
66
- ts = ev.get("timestamp", "")
67
- txt = ev.get("data", "")
68
  lines.append(f"[{ts}] {txt}")
69
  except:
70
  continue
71
  return "\n".join(lines)
72
 
73
- def fetch_all_logs(repo_id: str) -> str:
74
- """Return combined build + run logs."""
75
- build = fetch_logs(repo_id, "build")
76
- run = fetch_logs(repo_id, "run")
77
- return f"--- BUILD ---\n{build}\n\n--- RUN ---\n{run}"
78
-
79
- # — SYNC MANUAL EDITS —
80
-
81
- def sync_and_read_code(username: str, repo_name: str, token: str, code_filename: str) -> str:
82
- """Clone or pull the HF Space repo locally and return the latest code."""
83
- local_dir = f"./{repo_name}"
84
- repo_url = f"https://huggingface.co/spaces/{username}/{repo_name}"
85
- repo = Repository(
86
- local_dir,
87
- clone_from=repo_url,
88
- use_auth_token=token,
89
- repo_type="space"
90
- )
91
- repo.git_pull()
92
- path = os.path.join(local_dir, code_filename)
93
- with open(path, "r") as f:
94
- return f.read()
95
-
96
  # — CORE LOOP —
97
 
98
  def handle_user_message(
@@ -107,41 +87,26 @@ def handle_user_message(
107
  if profile is None or oauth_token is None:
108
  return (
109
  history + [{"role":"assistant","content":"⚠️ Please log in first."}],
110
- "", "", "<p>No Space yet.</p>"
 
 
111
  )
112
 
113
- username = profile.username
114
- repo_name = f"{username}-{space_suffix}"
115
- repo_id = f"{username}/{repo_name}"
116
- code_fn = "app.py" if sdk_choice == "gradio" else "streamlit_app.py"
117
-
118
- # Sync manual edits into history before LLM generation
119
- try:
120
- latest_code = sync_and_read_code(username, repo_name, oauth_token.token, code_fn)
121
- history.append({
122
- "role": "assistant",
123
- "content": (
124
- f"🔄 Synced latest `{code_fn}` from the Space:\n"
125
- "```python\n"
126
- f"{latest_code}\n"
127
- "```"
128
- )
129
- })
130
- except Exception:
131
- # If repo doesn't exist yet, skip sync
132
- pass
133
 
134
- # Build chat context
135
  client = genai.Client(api_key=gemini_api_key)
136
  system_msg = {
137
- "role": "system",
138
- "content": (
139
- f"You are an AI assistant writing a HuggingFace Space using the {sdk_choice} SDK. "
140
- "After producing code, wait for logs; if errors appear, fix them."
141
  )
142
  }
143
  chat = [system_msg] + history
144
 
 
145
  readme_fn = "README.md"
146
  reqs_fn = "requirements.txt"
147
 
@@ -157,7 +122,7 @@ def handle_user_message(
157
  )
158
 
159
  raw_code = resp.text
160
- code = extract_code(raw_code)
161
  chat.append({"role":"assistant","content":code})
162
 
163
  # Write code file
@@ -184,7 +149,7 @@ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-
184
 
185
  # Write requirements
186
  base_reqs = "pandas\n"
187
- extra = "streamlit\n" if sdk_choice == "streamlit" else "gradio\n"
188
  with open(reqs_fn, "w") as f:
189
  f.write(base_reqs + extra)
190
 
@@ -205,30 +170,31 @@ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-
205
  repo_type="space"
206
  )
207
 
208
- # Fetch logs and break if no errors
209
  build = fetch_logs(repo_id, "build")
210
  run = fetch_logs(repo_id, "run")
211
  if "ERROR" not in build.upper() and "ERROR" not in run.upper():
212
  break
213
 
214
- # Feed errors back to LLM
215
  chat.append({
216
  "role":"user",
217
  "content":(
218
- f"Build logs:\n{build}\n\nRun logs:\n{run}\n\nPlease fix the code."
 
 
219
  )
220
  })
221
  time.sleep(2)
222
 
223
- # Prepare messages + iframe preview
224
- messages = [{"role":m["role"],"content":m["content"]} for m in chat if m["role"] != "system"]
225
- preview_url = f"https://huggingface.co/spaces/{username}/{repo_name}"
226
  iframe = (
227
  f'<iframe src="{preview_url}" '
228
  f'width="100%" height="500px" frameborder="0"></iframe>'
229
  )
230
 
231
- placeholder = "✅ Space created! Click “Refresh Logs” to pull logs."
232
  return messages, placeholder, placeholder, iframe
233
 
234
  # — REFRESH LOGS —
@@ -239,12 +205,11 @@ def refresh_logs(
239
  oauth_token: gr.OAuthToken | None
240
  ):
241
  if profile is None or oauth_token is None:
242
- return "⚠️ Please log in.", ""
243
  repo_id = f"{profile.username}/{profile.username}-{space_suffix}"
244
- combined = fetch_all_logs(repo_id)
245
- return combined, ""
246
 
247
- # — BUILD THE UI —
248
 
249
  with gr.Blocks(title="HF Space Auto‑Builder") as demo:
250
  gr.Markdown("## Sign in + Auto‑Build Spaces\n\n"
@@ -260,19 +225,19 @@ with gr.Blocks(title="HF Space Auto‑Builder") as demo:
260
  login_btn.click(list_private_models, inputs=None, outputs=models_md)
261
 
262
  # SETTINGS
263
- sdk_choice = gr.Radio(["gradio","streamlit"], value="gradio", label="SDK template")
264
- api_key = gr.Textbox(label="Gemini API Key", type="password")
265
- grounding = gr.Checkbox(label="Enable grounding", value=False)
266
- space_suffix = gr.Textbox(label="Space suffix", value="auto-space",
267
- info="E.g. 'auto-space', 'auto-space2', etc.")
268
 
269
  # CHAT + OUTPUTS
270
- chatbot = gr.Chatbot(type="messages")
271
- user_in = gr.Textbox(placeholder="Your prompt…", label="Prompt")
272
- send_btn = gr.Button("Send")
273
- build_box = gr.Textbox(label="Build logs", lines=10, interactive=False)
274
- run_box = gr.Textbox(label="Run logs", lines=1, interactive=False)
275
- preview = gr.HTML("<p>No Space yet.</p>")
276
 
277
  send_btn.click(
278
  fn=handle_user_message,
@@ -284,8 +249,8 @@ with gr.Blocks(title="HF Space Auto‑Builder") as demo:
284
  refresh_btn = gr.Button("Refresh Logs")
285
  refresh_btn.click(
286
  fn=refresh_logs,
287
- inputs=[space_suffix, status_md, api_key],
288
  outputs=[build_box, run_box]
289
  )
290
 
291
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
1
  import re
2
  import json
3
  import time
 
4
  import importlib.metadata
5
 
6
  import gradio as gr
7
+ from huggingface_hub import create_repo, upload_file, list_models, constants
8
  from huggingface_hub.utils import build_hf_headers, get_session, hf_raise_for_status
9
  from google import genai
10
  from google.genai.types import Tool, GenerateContentConfig, GoogleSearch
 
39
 
40
  def extract_code(text: str) -> str:
41
  """
42
+ Extract the last
43
+
44
+ block. If none, return whole text.
45
  """
46
+ blocks = re.findall(r"
47
+ (?:\w*\n)?([\s\S]*?)
48
+ ", text)
49
  return blocks[-1].strip() if blocks else text.strip()
50
 
51
  # — HF SPACE LOGGING —
 
66
  if raw.startswith(b"data: "):
67
  try:
68
  ev = json.loads(raw[len(b"data: "):].decode())
69
+ ts = ev.get("timestamp","")
70
+ txt = ev.get("data","")
71
  lines.append(f"[{ts}] {txt}")
72
  except:
73
  continue
74
  return "\n".join(lines)
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  # — CORE LOOP —
77
 
78
  def handle_user_message(
 
87
  if profile is None or oauth_token is None:
88
  return (
89
  history + [{"role":"assistant","content":"⚠️ Please log in first."}],
90
+ "",
91
+ "",
92
+ "<p>No Space yet.</p>"
93
  )
94
 
95
+ username = profile.username
96
+ repo_name = f"{username}-{space_suffix}"
97
+ repo_id = f"{username}/{repo_name}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
 
 
99
  client = genai.Client(api_key=gemini_api_key)
100
  system_msg = {
101
+ "role":"system",
102
+ "content":(
103
+ f"You are an AI assistant writing a HuggingFace Space using the "
104
+ f"{sdk_choice} SDK. After producing code, wait for logs; if errors appear, fix them."
105
  )
106
  }
107
  chat = [system_msg] + history
108
 
109
+ code_fn = "app.py" if sdk_choice=="gradio" else "streamlit_app.py"
110
  readme_fn = "README.md"
111
  reqs_fn = "requirements.txt"
112
 
 
122
  )
123
 
124
  raw_code = resp.text
125
+ code = extract_code(raw_code)
126
  chat.append({"role":"assistant","content":code})
127
 
128
  # Write code file
 
149
 
150
  # Write requirements
151
  base_reqs = "pandas\n"
152
+ extra = "streamlit\n" if sdk_choice=="streamlit" else "gradio\n"
153
  with open(reqs_fn, "w") as f:
154
  f.write(base_reqs + extra)
155
 
 
170
  repo_type="space"
171
  )
172
 
173
+ # If build succeeds without errors, break; otherwise feed logs back to LLM
174
  build = fetch_logs(repo_id, "build")
175
  run = fetch_logs(repo_id, "run")
176
  if "ERROR" not in build.upper() and "ERROR" not in run.upper():
177
  break
178
 
 
179
  chat.append({
180
  "role":"user",
181
  "content":(
182
+ f"Build logs:\n{build}\n\n"
183
+ f"Run logs:\n{run}\n\n"
184
+ "Please fix the code."
185
  )
186
  })
187
  time.sleep(2)
188
 
189
+ # Prepare messages + immediate iframe preview
190
+ messages = [{"role":m["role"],"content":m["content"]} for m in chat if m["role"]!="system"]
191
+ preview_url = f"https://huggingface.co/spaces/{repo_id}"
192
  iframe = (
193
  f'<iframe src="{preview_url}" '
194
  f'width="100%" height="500px" frameborder="0"></iframe>'
195
  )
196
 
197
+ placeholder = "✅ Space created! Click “Refresh Logs” to pull build/run logs."
198
  return messages, placeholder, placeholder, iframe
199
 
200
  # — REFRESH LOGS —
 
205
  oauth_token: gr.OAuthToken | None
206
  ):
207
  if profile is None or oauth_token is None:
208
+ return "⚠️ Please log in.", "⚠️ Please log in."
209
  repo_id = f"{profile.username}/{profile.username}-{space_suffix}"
210
+ return fetch_logs(repo_id, "build"), fetch_logs(repo_id, "run")
 
211
 
212
+ # — BUILD THE UI —
213
 
214
  with gr.Blocks(title="HF Space Auto‑Builder") as demo:
215
  gr.Markdown("## Sign in + Auto‑Build Spaces\n\n"
 
225
  login_btn.click(list_private_models, inputs=None, outputs=models_md)
226
 
227
  # SETTINGS
228
+ sdk_choice = gr.Radio(["gradio","streamlit"], value="gradio", label="SDK template")
229
+ api_key = gr.Textbox(label="Gemini API Key", type="password")
230
+ grounding = gr.Checkbox(label="Enable grounding", value=False)
231
+ space_suffix= gr.Textbox(label="Space suffix", value="auto-space",
232
+ info="E.g. 'auto-space', 'auto-space2', etc.")
233
 
234
  # CHAT + OUTPUTS
235
+ chatbot = gr.Chatbot(type="messages")
236
+ user_in = gr.Textbox(placeholder="Your prompt…", label="Prompt")
237
+ send_btn = gr.Button("Send")
238
+ build_box = gr.Textbox(label="Build logs", lines=5, interactive=False)
239
+ run_box = gr.Textbox(label="Run logs", lines=5, interactive=False)
240
+ preview = gr.HTML("<p>No Space yet.</p>")
241
 
242
  send_btn.click(
243
  fn=handle_user_message,
 
249
  refresh_btn = gr.Button("Refresh Logs")
250
  refresh_btn.click(
251
  fn=refresh_logs,
252
+ inputs=[space_suffix],
253
  outputs=[build_box, run_box]
254
  )
255
 
256
+ demo.launch(server_name="0.0.0.0", server_port=7860)