wuhp commited on
Commit
52ae72e
·
verified ·
1 Parent(s): 06f3bae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +83 -44
app.py CHANGED
@@ -35,9 +35,14 @@ def create_space(repo_name, sdk, profile, token):
35
  if not (profile and token):
36
  return "", "⚠️ Please log in first.", "<p>No Space created yet.</p>"
37
  rid = f"{profile.username}/{repo_name}"
38
- create_repo(rid, token=token.token, exist_ok=True, repo_type="space", space_sdk=sdk)
 
39
  url = f"https://huggingface.co/spaces/{rid}"
40
- return rid, f"✅ Space ready: {url}", f'<iframe src="{url}" width="100%" height="400px"></iframe>'
 
 
 
 
41
 
42
  def upload_file_to_space(file, path, repo_id, profile, token):
43
  if not (profile and token):
@@ -50,7 +55,10 @@ def upload_file_to_space(file, path, repo_id, profile, token):
50
  return f"✅ Uploaded `{path}` to `{repo_id}`"
51
 
52
  def _fetch_space_logs_level(repo_id, level):
53
- r = get_session().get(f"{constants.ENDPOINT}/api/spaces/{repo_id}/jwt", headers=build_hf_headers())
 
 
 
54
  hf_raise_for_status(r)
55
  jwt = r.json()["token"]
56
  url = f"https://api.hf.space/v1/{repo_id}/logs/{level}"
@@ -77,8 +85,9 @@ def get_container_logs(repo_id, profile, token):
77
 
78
  func_decls = [
79
  {
80
- "name":"create_space","description":"Create/get a HF Space",
81
- "parameters":{
 
82
  "type":"object",
83
  "properties":{
84
  "repo_name":{"type":"string"},
@@ -88,24 +97,27 @@ func_decls = [
88
  }
89
  },
90
  {
91
- "name":"list_files","description":"List files in Space",
92
- "parameters":{
 
93
  "type":"object",
94
  "properties":{"repo_id":{"type":"string"}},
95
  "required":["repo_id"]
96
  }
97
  },
98
  {
99
- "name":"get_build_logs","description":"Fetch build logs",
100
- "parameters":{
 
101
  "type":"object",
102
  "properties":{"repo_id":{"type":"string"}},
103
  "required":["repo_id"]
104
  }
105
  },
106
  {
107
- "name":"get_run_logs","description":"Fetch run logs",
108
- "parameters":{
 
109
  "type":"object",
110
  "properties":{"repo_id":{"type":"string"}},
111
  "required":["repo_id"]
@@ -118,6 +130,7 @@ func_decls = [
118
  def process_message(profile, token, user_msg,
119
  gemini_key, sidebar_repo, sidebar_sdk,
120
  chat_history, session):
 
121
  if session.get("chat") is None:
122
  client = genai.Client(api_key=gemini_key)
123
  cfg = types.GenerateContentConfig(
@@ -130,16 +143,23 @@ def process_message(profile, token, user_msg,
130
  )
131
  session["chat"] = client.chats.create(model="gemini-2.0-flash", config=cfg)
132
  session["repo_id"] = None
 
133
 
134
- chat = session["chat"]
135
- chat_history.append((user_msg, None))
136
- resp = chat.send_message(user_msg)
 
137
  part = resp.candidates[0].content.parts[0]
138
 
139
  result = {}
 
140
  if part.function_call:
 
 
 
 
 
141
  name = part.function_call.name
142
- args = json.loads(part.function_call.args)
143
  if name == "create_space":
144
  rid, log, iframe = create_space(
145
  args["repo_name"], args["sdk"], profile, token
@@ -156,7 +176,8 @@ def process_message(profile, token, user_msg,
156
  else:
157
  result = {"log": f"⚠️ Unknown function {name}"}
158
 
159
- chat.send_message(
 
160
  types.Content(
161
  role="function",
162
  parts=[ types.Part(
@@ -165,40 +186,50 @@ def process_message(profile, token, user_msg,
165
  )]
166
  )
167
  )
168
- final = chat.get_history()[-1].parts[0].text
 
169
  else:
170
- final = part.text
171
 
 
 
 
 
172
  if "iframe" in result: session["iframe"] = result["iframe"]
173
  if "log" in result: session["log"] = result["log"]
174
  if "files" in result: session["files"] = result["files"]
175
 
176
- chat_history[-1] = (user_msg, final)
177
- return (chat_history,
178
- session.get("iframe",""),
179
- session.get("log",""),
180
- session.get("files",""),
181
- session)
 
182
 
183
  def sync_manual(profile, token, session):
184
  if not (profile and token and session.get("repo_id")):
185
- return (session.get("iframe",""),
186
- "⚠️ Cannot sync manual changes.",
187
- session.get("files",""),
188
- session)
 
 
189
  fl = list_repo_files(session["repo_id"], token=token.token, repo_type="space")
190
  session["files"] = "\n".join(fl)
191
  session["log"] = "🔄 Manual changes synced."
192
- return (session.get("iframe",""),
193
- session["log"],
194
- session["files"],
195
- session)
 
 
196
 
197
  # — BUILD UI —
198
 
199
  with gr.Blocks(css="""
200
- #sidebar { background: #f2f2f2; padding: 1rem; border-right:1px solid #ccc; }
201
- #main { padding: 1rem; }
202
  """) as demo:
203
 
204
  with gr.Row():
@@ -209,11 +240,13 @@ with gr.Blocks(css="""
209
  profile_state = gr.State(None)
210
  token_state = gr.State(None)
211
 
212
- # capture both outputs
213
  login_btn.click(None, [], [profile_state, token_state])
214
 
215
  status_md = gr.Markdown("*Not logged in.*")
216
- profile_state.change(show_profile, inputs=[profile_state], outputs=[status_md])
 
 
217
 
218
  models_md = gr.Markdown()
219
  profile_state.change(list_private_models,
@@ -222,7 +255,8 @@ with gr.Blocks(css="""
222
 
223
  gemini_key = gr.Textbox(label="Gemini API Key", type="password")
224
  sidebar_repo = gr.Textbox(label="Space name", placeholder="my-space")
225
- sidebar_sdk = gr.Radio(["gradio","streamlit"], value="gradio", label="SDK")
 
226
 
227
  gr.Markdown("---")
228
  confirm_btn = gr.Button("🔄 Confirm Manual Changes")
@@ -232,16 +266,18 @@ with gr.Blocks(css="""
232
  tabs = gr.Tabs()
233
  with tabs:
234
  with gr.TabItem("💬 Chat"):
235
- chatbox = gr.Chatbot(type="tuples")
236
  user_input = gr.Textbox(show_label=False, placeholder="Ask the LLM…")
237
  send_btn = gr.Button("Send")
238
  with gr.TabItem("🛠️ Manual"):
239
  gr.Markdown("#### Create a Space")
240
  repo_m = gr.Textbox(label="Name")
241
- sdk_m = gr.Radio(["gradio","streamlit"], value="gradio", label="SDK")
 
242
  create_btn = gr.Button("Create Space")
243
  sess_id = gr.Textbox(visible=False)
244
- log_c = gr.Textbox(label="Log", interactive=False, lines=2)
 
245
  preview = gr.HTML("<p>No Space yet.</p>")
246
 
247
  create_btn.click(create_space,
@@ -253,7 +289,8 @@ with gr.Blocks(css="""
253
  path = gr.Textbox(label="Path", value="app.py")
254
  file_u = gr.File()
255
  upload_btn = gr.Button("Upload File")
256
- log_u = gr.Textbox(label="Log", interactive=False, lines=2)
 
257
 
258
  upload_btn.click(upload_file_to_space,
259
  inputs=[file_u, path, sess_id,
@@ -263,8 +300,10 @@ with gr.Blocks(css="""
263
  gr.Markdown("#### Fetch Logs")
264
  b_btn = gr.Button("Build Logs")
265
  r_btn = gr.Button("Run Logs")
266
- log_b = gr.Textbox(label="Build", interactive=False, lines=5)
267
- log_r = gr.Textbox(label="Run", interactive=False, lines=5)
 
 
268
 
269
  b_btn.click(get_build_logs,
270
  inputs=[sess_id, profile_state, token_state],
@@ -273,7 +312,7 @@ with gr.Blocks(css="""
273
  inputs=[sess_id, profile_state, token_state],
274
  outputs=[log_r])
275
 
276
- # persistent panels
277
  gr.Markdown("---")
278
  iframe_out = gr.HTML(label="🖼️ Preview")
279
  log_out = gr.Textbox(label="📋 Latest Log", lines=4)
 
35
  if not (profile and token):
36
  return "", "⚠️ Please log in first.", "<p>No Space created yet.</p>"
37
  rid = f"{profile.username}/{repo_name}"
38
+ create_repo(rid, token=token.token, exist_ok=True,
39
+ repo_type="space", space_sdk=sdk)
40
  url = f"https://huggingface.co/spaces/{rid}"
41
+ return (
42
+ rid,
43
+ f"✅ Space ready: {url} (SDK: {sdk})",
44
+ f'<iframe src="{url}" width="100%" height="400px"></iframe>'
45
+ )
46
 
47
  def upload_file_to_space(file, path, repo_id, profile, token):
48
  if not (profile and token):
 
55
  return f"✅ Uploaded `{path}` to `{repo_id}`"
56
 
57
  def _fetch_space_logs_level(repo_id, level):
58
+ r = get_session().get(
59
+ f"{constants.ENDPOINT}/api/spaces/{repo_id}/jwt",
60
+ headers=build_hf_headers()
61
+ )
62
  hf_raise_for_status(r)
63
  jwt = r.json()["token"]
64
  url = f"https://api.hf.space/v1/{repo_id}/logs/{level}"
 
85
 
86
  func_decls = [
87
  {
88
+ "name": "create_space",
89
+ "description": "Create/get a HF Space",
90
+ "parameters": {
91
  "type":"object",
92
  "properties":{
93
  "repo_name":{"type":"string"},
 
97
  }
98
  },
99
  {
100
+ "name": "list_files",
101
+ "description": "List files in Space",
102
+ "parameters": {
103
  "type":"object",
104
  "properties":{"repo_id":{"type":"string"}},
105
  "required":["repo_id"]
106
  }
107
  },
108
  {
109
+ "name": "get_build_logs",
110
+ "description": "Fetch build logs",
111
+ "parameters": {
112
  "type":"object",
113
  "properties":{"repo_id":{"type":"string"}},
114
  "required":["repo_id"]
115
  }
116
  },
117
  {
118
+ "name": "get_run_logs",
119
+ "description": "Fetch run logs",
120
+ "parameters": {
121
  "type":"object",
122
  "properties":{"repo_id":{"type":"string"}},
123
  "required":["repo_id"]
 
130
  def process_message(profile, token, user_msg,
131
  gemini_key, sidebar_repo, sidebar_sdk,
132
  chat_history, session):
133
+ # Initialize on first call
134
  if session.get("chat") is None:
135
  client = genai.Client(api_key=gemini_key)
136
  cfg = types.GenerateContentConfig(
 
143
  )
144
  session["chat"] = client.chats.create(model="gemini-2.0-flash", config=cfg)
145
  session["repo_id"] = None
146
+ session["messages"] = []
147
 
148
+ # Record user message
149
+ session["messages"].append({"role":"user","content":user_msg})
150
+
151
+ resp = session["chat"].send_message(user_msg)
152
  part = resp.candidates[0].content.parts[0]
153
 
154
  result = {}
155
+ # If the model wants to call a function
156
  if part.function_call:
157
+ # args may already be dict
158
+ args = part.function_call.args
159
+ if isinstance(args, str):
160
+ args = json.loads(args)
161
+
162
  name = part.function_call.name
 
163
  if name == "create_space":
164
  rid, log, iframe = create_space(
165
  args["repo_name"], args["sdk"], profile, token
 
176
  else:
177
  result = {"log": f"⚠️ Unknown function {name}"}
178
 
179
+ # Send the function result back into the chat
180
+ session["chat"].send_message(
181
  types.Content(
182
  role="function",
183
  parts=[ types.Part(
 
186
  )]
187
  )
188
  )
189
+ # The assistant’s final message
190
+ assistant_text = session["chat"].get_history()[-1].parts[0].text
191
  else:
192
+ assistant_text = part.text
193
 
194
+ # Record assistant message
195
+ session["messages"].append({"role":"assistant","content":assistant_text})
196
+
197
+ # Update the panels
198
  if "iframe" in result: session["iframe"] = result["iframe"]
199
  if "log" in result: session["log"] = result["log"]
200
  if "files" in result: session["files"] = result["files"]
201
 
202
+ return (
203
+ session["messages"],
204
+ session.get("iframe",""),
205
+ session.get("log",""),
206
+ session.get("files",""),
207
+ session
208
+ )
209
 
210
  def sync_manual(profile, token, session):
211
  if not (profile and token and session.get("repo_id")):
212
+ return (
213
+ session.get("iframe",""),
214
+ "⚠️ Cannot sync manual changes.",
215
+ session.get("files",""),
216
+ session
217
+ )
218
  fl = list_repo_files(session["repo_id"], token=token.token, repo_type="space")
219
  session["files"] = "\n".join(fl)
220
  session["log"] = "🔄 Manual changes synced."
221
+ return (
222
+ session.get("iframe",""),
223
+ session["log"],
224
+ session["files"],
225
+ session
226
+ )
227
 
228
  # — BUILD UI —
229
 
230
  with gr.Blocks(css="""
231
+ #sidebar { background:#f2f2f2; padding:1rem; border-right:1px solid #ccc; }
232
+ #main { padding:1rem; }
233
  """) as demo:
234
 
235
  with gr.Row():
 
240
  profile_state = gr.State(None)
241
  token_state = gr.State(None)
242
 
243
+ # Capture both profile and token from the login button
244
  login_btn.click(None, [], [profile_state, token_state])
245
 
246
  status_md = gr.Markdown("*Not logged in.*")
247
+ profile_state.change(show_profile,
248
+ inputs=[profile_state],
249
+ outputs=[status_md])
250
 
251
  models_md = gr.Markdown()
252
  profile_state.change(list_private_models,
 
255
 
256
  gemini_key = gr.Textbox(label="Gemini API Key", type="password")
257
  sidebar_repo = gr.Textbox(label="Space name", placeholder="my-space")
258
+ sidebar_sdk = gr.Radio(["gradio","streamlit"],
259
+ value="gradio", label="SDK")
260
 
261
  gr.Markdown("---")
262
  confirm_btn = gr.Button("🔄 Confirm Manual Changes")
 
266
  tabs = gr.Tabs()
267
  with tabs:
268
  with gr.TabItem("💬 Chat"):
269
+ chatbox = gr.Chatbot(type="messages")
270
  user_input = gr.Textbox(show_label=False, placeholder="Ask the LLM…")
271
  send_btn = gr.Button("Send")
272
  with gr.TabItem("🛠️ Manual"):
273
  gr.Markdown("#### Create a Space")
274
  repo_m = gr.Textbox(label="Name")
275
+ sdk_m = gr.Radio(["gradio","streamlit"],
276
+ value="gradio", label="SDK")
277
  create_btn = gr.Button("Create Space")
278
  sess_id = gr.Textbox(visible=False)
279
+ log_c = gr.Textbox(label="Log",
280
+ interactive=False, lines=2)
281
  preview = gr.HTML("<p>No Space yet.</p>")
282
 
283
  create_btn.click(create_space,
 
289
  path = gr.Textbox(label="Path", value="app.py")
290
  file_u = gr.File()
291
  upload_btn = gr.Button("Upload File")
292
+ log_u = gr.Textbox(label="Log",
293
+ interactive=False, lines=2)
294
 
295
  upload_btn.click(upload_file_to_space,
296
  inputs=[file_u, path, sess_id,
 
300
  gr.Markdown("#### Fetch Logs")
301
  b_btn = gr.Button("Build Logs")
302
  r_btn = gr.Button("Run Logs")
303
+ log_b = gr.Textbox(label="Build",
304
+ interactive=False, lines=5)
305
+ log_r = gr.Textbox(label="Run",
306
+ interactive=False, lines=5)
307
 
308
  b_btn.click(get_build_logs,
309
  inputs=[sess_id, profile_state, token_state],
 
312
  inputs=[sess_id, profile_state, token_state],
313
  outputs=[log_r])
314
 
315
+ # Persistent panels
316
  gr.Markdown("---")
317
  iframe_out = gr.HTML(label="🖼️ Preview")
318
  log_out = gr.Textbox(label="📋 Latest Log", lines=4)