Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -3,6 +3,7 @@ import json
|
|
3 |
import os
|
4 |
|
5 |
import gradio as gr
|
|
|
6 |
from huggingface_hub import (
|
7 |
create_repo, list_models, upload_file, list_repo_files, constants
|
8 |
)
|
@@ -38,7 +39,7 @@ def enable_repo_actions(repo_id, profile, token):
|
|
38 |
def create_space(repo_name, sdk, profile, token):
|
39 |
if not (profile and token):
|
40 |
return "", "⚠️ Please log in first.", "<p>No Space created yet.</p>"
|
41 |
-
rid = f"{profile.username}/{repo_name}"
|
42 |
create_repo(
|
43 |
repo_id=rid,
|
44 |
token=token.token,
|
@@ -110,9 +111,7 @@ def get_container_logs(repo_id, profile, token):
|
|
110 |
return "⚠️ Please log in and create a Space first."
|
111 |
return _fetch_space_logs_level(repo_id, "run")
|
112 |
|
113 |
-
|
114 |
-
# — FUNCTION DECLARATIONS & TOOL —
|
115 |
-
# Build a single Tool containing all function declarations.
|
116 |
|
117 |
func_decls = [
|
118 |
types.FunctionDeclaration(
|
@@ -169,16 +168,16 @@ func_decls = [
|
|
169 |
]
|
170 |
tool = types.Tool(function_declarations=func_decls)
|
171 |
|
172 |
-
|
173 |
-
# — CHAT HANDLER —
|
174 |
|
175 |
def execute_function_by_name(name, args, profile, token, session):
|
176 |
-
"""Dispatch to the right function and return a raw dict result."""
|
177 |
if name == "create_space":
|
178 |
rid, log, iframe = create_space(
|
179 |
args["repo_name"], session["sdk"], profile, token
|
180 |
)
|
181 |
session["repo_id"] = rid
|
|
|
|
|
182 |
return {"log": log, "iframe": iframe}
|
183 |
if name == "write_file":
|
184 |
status = write_file(
|
@@ -201,18 +200,15 @@ def execute_function_by_name(name, args, profile, token, session):
|
|
201 |
)}
|
202 |
return {"error": f"Unknown function {name}"}
|
203 |
|
204 |
-
|
205 |
def process_message(
|
206 |
profile, token, user_msg,
|
207 |
gemini_key, sidebar_repo, sidebar_sdk,
|
208 |
chat_history, session
|
209 |
):
|
210 |
-
# Initialize chat once
|
211 |
if session.get("chat") is None:
|
212 |
client = genai.Client(api_key=gemini_key)
|
213 |
-
# Pass the Tool object, not a list of dicts
|
214 |
model = client.chats.create(
|
215 |
-
model="gemini-2.
|
216 |
config=types.GenerateContentConfig(
|
217 |
system_instruction=(
|
218 |
"You are a HF Spaces admin. You can create spaces, "
|
@@ -228,150 +224,97 @@ def process_message(
|
|
228 |
"sdk": sidebar_sdk,
|
229 |
"messages": []
|
230 |
})
|
231 |
-
|
232 |
-
# Remember current SDK choice
|
233 |
session["sdk"] = sidebar_sdk
|
234 |
-
|
235 |
-
# Pre-chat “call it X” handler
|
236 |
if session["repo_id"] is None:
|
237 |
-
m = re.search(r"call
|
238 |
if m:
|
239 |
args = {"repo_name": m.group(1), "sdk": sidebar_sdk}
|
240 |
result = execute_function_by_name("create_space", args, profile, token, session)
|
241 |
session["messages"].append({"role": "assistant", "content": result["log"]})
|
242 |
-
return session["messages"],
|
243 |
-
|
244 |
-
# Append user message
|
245 |
session["messages"].append({"role": "user", "content": user_msg})
|
246 |
response = session["chat"].send_message(user_msg)
|
247 |
-
|
248 |
-
# Handle function-calling loop
|
249 |
while True:
|
250 |
part = response.candidates[0].content.parts[0]
|
251 |
if not part.function_call:
|
252 |
-
break
|
253 |
fname = part.function_call.name
|
254 |
fargs = part.function_call.args or {}
|
255 |
-
# Run the tool
|
256 |
result = execute_function_by_name(fname, fargs, profile, token, session)
|
257 |
-
# Send function result back to model
|
258 |
resp_part = types.Part.from_function_response(name=fname, response=result)
|
259 |
-
response = session["chat"].send_message(
|
260 |
-
|
261 |
-
# Final assistant text
|
262 |
assistant_text = response.text
|
263 |
session["messages"].append({"role": "assistant", "content": assistant_text})
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
# — MANUAL SYNC —
|
273 |
|
274 |
def sync_manual(profile, token, session):
|
275 |
if not (profile and token and session.get("repo_id")):
|
276 |
return "", "⚠️ Cannot sync manual changes.", "", session
|
277 |
files = list_repo_files(session["repo_id"], token=token.token, repo_type="space")
|
278 |
log = "🔄 Manual changes synced."
|
279 |
-
return session.get("iframe",""), log, "\n".join(files), session
|
280 |
-
|
281 |
-
|
282 |
-
# — GRADIO UI —
|
283 |
|
284 |
with gr.Blocks(css="""
|
285 |
#sidebar { background:#f2f2f2; padding:1rem; border-right:1px solid #ccc; }
|
286 |
#main { padding:1rem; }
|
287 |
""") as demo:
|
288 |
-
|
289 |
-
# Sidebar
|
290 |
with gr.Column(elem_id="sidebar", scale=1):
|
291 |
gr.Markdown("### 🔑 HF Login & Config")
|
292 |
login_btn = gr.LoginButton(variant="huggingface", size="sm")
|
293 |
profile_state = gr.State(None)
|
294 |
token_state = gr.State(None)
|
295 |
login_btn.click(None, [], [profile_state, token_state])
|
296 |
-
|
297 |
status_md = gr.Markdown("*Not logged in.*")
|
298 |
profile_state.change(show_profile, [profile_state], [status_md])
|
299 |
-
|
300 |
models_md = gr.Markdown()
|
301 |
-
profile_state.change(list_private_models,
|
302 |
-
[profile_state, token_state], [models_md])
|
303 |
-
|
304 |
gemini_key = gr.Textbox(label="Gemini API Key", type="password")
|
305 |
sidebar_repo = gr.Textbox(label="Space name", placeholder="blurrtest")
|
306 |
-
sidebar_sdk = gr.Radio(["gradio","streamlit"],
|
307 |
-
value="gradio", label="SDK")
|
308 |
-
|
309 |
gr.Markdown("---")
|
310 |
confirm_btn = gr.Button("🔄 Sync Manual Changes")
|
311 |
-
|
312 |
-
# Main area
|
313 |
with gr.Column(elem_id="main", scale=3):
|
314 |
tabs = gr.Tabs()
|
315 |
with tabs:
|
316 |
with gr.TabItem("💬 Chat"):
|
317 |
-
chatbox
|
318 |
-
user_input = gr.Textbox(show_label=False,
|
319 |
-
|
320 |
-
send_btn = gr.Button("Send")
|
321 |
with gr.TabItem("🛠️ Manual"):
|
322 |
gr.Markdown("#### Create / Rename Space")
|
323 |
-
repo_m
|
324 |
-
sdk_m
|
325 |
-
value="gradio", label="SDK")
|
326 |
create_btn = gr.Button("Create Space")
|
327 |
-
sess_id
|
328 |
-
log_c
|
329 |
-
preview
|
330 |
-
|
331 |
-
create_btn.click(create_space,
|
332 |
-
[repo_m, sdk_m, profile_state, token_state],
|
333 |
-
[sess_id, log_c, preview])
|
334 |
-
|
335 |
gr.Markdown("#### Upload File")
|
336 |
-
path
|
337 |
-
file_u
|
338 |
-
upload_btn
|
339 |
-
log_u
|
340 |
-
|
341 |
-
|
342 |
-
upload_btn.click(upload_file_to_space,
|
343 |
-
[file_u, path, sess_id, profile_state, token_state],
|
344 |
-
[log_u])
|
345 |
-
|
346 |
gr.Markdown("#### Fetch Logs")
|
347 |
b_btn = gr.Button("Build Logs")
|
348 |
r_btn = gr.Button("Run Logs")
|
349 |
-
log_b = gr.Textbox(label="Build",
|
350 |
-
log_r = gr.Textbox(label="Run",
|
351 |
-
|
352 |
-
|
353 |
-
[sess_id, profile_state, token_state],
|
354 |
-
[log_b])
|
355 |
-
r_btn.click(get_container_logs,
|
356 |
-
[sess_id, profile_state, token_state],
|
357 |
-
[log_r])
|
358 |
-
|
359 |
gr.Markdown("---")
|
360 |
iframe_out = gr.HTML(label="🖼️ Preview")
|
361 |
-
log_out
|
362 |
-
files_out
|
363 |
-
|
364 |
state = gr.State({})
|
365 |
-
send_btn.click(process_message,
|
366 |
-
|
367 |
-
user_input, gemini_key,
|
368 |
-
sidebar_repo, sidebar_sdk,
|
369 |
-
chatbox, state],
|
370 |
-
[chatbox, iframe_out, log_out, files_out, state])
|
371 |
-
|
372 |
-
confirm_btn.click(sync_manual,
|
373 |
-
[profile_state, token_state, state],
|
374 |
-
[iframe_out, log_out, files_out, state])
|
375 |
|
376 |
if __name__ == "__main__":
|
377 |
demo.launch()
|
|
|
3 |
import os
|
4 |
|
5 |
import gradio as gr
|
6 |
+
from PIL import Image, ImageFilter
|
7 |
from huggingface_hub import (
|
8 |
create_repo, list_models, upload_file, list_repo_files, constants
|
9 |
)
|
|
|
39 |
def create_space(repo_name, sdk, profile, token):
|
40 |
if not (profile and token):
|
41 |
return "", "⚠️ Please log in first.", "<p>No Space created yet.</p>"
|
42 |
+
rid = f"{profile.username}/{repo_name.replace(' ', '-') }"
|
43 |
create_repo(
|
44 |
repo_id=rid,
|
45 |
token=token.token,
|
|
|
111 |
return "⚠️ Please log in and create a Space first."
|
112 |
return _fetch_space_logs_level(repo_id, "run")
|
113 |
|
114 |
+
# — FUNCTION DECLARATIONS & TOOL —
|
|
|
|
|
115 |
|
116 |
func_decls = [
|
117 |
types.FunctionDeclaration(
|
|
|
168 |
]
|
169 |
tool = types.Tool(function_declarations=func_decls)
|
170 |
|
171 |
+
# — CHAT HANDLER —
|
|
|
172 |
|
173 |
def execute_function_by_name(name, args, profile, token, session):
|
|
|
174 |
if name == "create_space":
|
175 |
rid, log, iframe = create_space(
|
176 |
args["repo_name"], session["sdk"], profile, token
|
177 |
)
|
178 |
session["repo_id"] = rid
|
179 |
+
session["iframe"] = iframe
|
180 |
+
session["log"] = log
|
181 |
return {"log": log, "iframe": iframe}
|
182 |
if name == "write_file":
|
183 |
status = write_file(
|
|
|
200 |
)}
|
201 |
return {"error": f"Unknown function {name}"}
|
202 |
|
|
|
203 |
def process_message(
|
204 |
profile, token, user_msg,
|
205 |
gemini_key, sidebar_repo, sidebar_sdk,
|
206 |
chat_history, session
|
207 |
):
|
|
|
208 |
if session.get("chat") is None:
|
209 |
client = genai.Client(api_key=gemini_key)
|
|
|
210 |
model = client.chats.create(
|
211 |
+
model="gemini-2.5-flash-preview-04-17",
|
212 |
config=types.GenerateContentConfig(
|
213 |
system_instruction=(
|
214 |
"You are a HF Spaces admin. You can create spaces, "
|
|
|
224 |
"sdk": sidebar_sdk,
|
225 |
"messages": []
|
226 |
})
|
|
|
|
|
227 |
session["sdk"] = sidebar_sdk
|
|
|
|
|
228 |
if session["repo_id"] is None:
|
229 |
+
m = re.search(r"(?:call it|called)\s+([\w- ]+)", user_msg, re.IGNORECASE)
|
230 |
if m:
|
231 |
args = {"repo_name": m.group(1), "sdk": sidebar_sdk}
|
232 |
result = execute_function_by_name("create_space", args, profile, token, session)
|
233 |
session["messages"].append({"role": "assistant", "content": result["log"]})
|
234 |
+
return session["messages"], session["iframe"], session["log"], "", session
|
|
|
|
|
235 |
session["messages"].append({"role": "user", "content": user_msg})
|
236 |
response = session["chat"].send_message(user_msg)
|
|
|
|
|
237 |
while True:
|
238 |
part = response.candidates[0].content.parts[0]
|
239 |
if not part.function_call:
|
240 |
+
break
|
241 |
fname = part.function_call.name
|
242 |
fargs = part.function_call.args or {}
|
|
|
243 |
result = execute_function_by_name(fname, fargs, profile, token, session)
|
|
|
244 |
resp_part = types.Part.from_function_response(name=fname, response=result)
|
245 |
+
response = session["chat"].send_message(resp_part)
|
|
|
|
|
246 |
assistant_text = response.text
|
247 |
session["messages"].append({"role": "assistant", "content": assistant_text})
|
248 |
+
return (
|
249 |
+
session["messages"],
|
250 |
+
session.get("iframe", ""),
|
251 |
+
session.get("log", ""),
|
252 |
+
session.get("files", ""),
|
253 |
+
session
|
254 |
+
)
|
|
|
|
|
255 |
|
256 |
def sync_manual(profile, token, session):
|
257 |
if not (profile and token and session.get("repo_id")):
|
258 |
return "", "⚠️ Cannot sync manual changes.", "", session
|
259 |
files = list_repo_files(session["repo_id"], token=token.token, repo_type="space")
|
260 |
log = "🔄 Manual changes synced."
|
261 |
+
return session.get("iframe", ""), log, "\n".join(files), session
|
|
|
|
|
|
|
262 |
|
263 |
with gr.Blocks(css="""
|
264 |
#sidebar { background:#f2f2f2; padding:1rem; border-right:1px solid #ccc; }
|
265 |
#main { padding:1rem; }
|
266 |
""") as demo:
|
|
|
|
|
267 |
with gr.Column(elem_id="sidebar", scale=1):
|
268 |
gr.Markdown("### 🔑 HF Login & Config")
|
269 |
login_btn = gr.LoginButton(variant="huggingface", size="sm")
|
270 |
profile_state = gr.State(None)
|
271 |
token_state = gr.State(None)
|
272 |
login_btn.click(None, [], [profile_state, token_state])
|
|
|
273 |
status_md = gr.Markdown("*Not logged in.*")
|
274 |
profile_state.change(show_profile, [profile_state], [status_md])
|
|
|
275 |
models_md = gr.Markdown()
|
276 |
+
profile_state.change(list_private_models,[profile_state, token_state],[models_md])
|
|
|
|
|
277 |
gemini_key = gr.Textbox(label="Gemini API Key", type="password")
|
278 |
sidebar_repo = gr.Textbox(label="Space name", placeholder="blurrtest")
|
279 |
+
sidebar_sdk = gr.Radio(["gradio","streamlit"],value="gradio",label="SDK")
|
|
|
|
|
280 |
gr.Markdown("---")
|
281 |
confirm_btn = gr.Button("🔄 Sync Manual Changes")
|
|
|
|
|
282 |
with gr.Column(elem_id="main", scale=3):
|
283 |
tabs = gr.Tabs()
|
284 |
with tabs:
|
285 |
with gr.TabItem("💬 Chat"):
|
286 |
+
chatbox = gr.Chatbot(type="messages")
|
287 |
+
user_input = gr.Textbox(show_label=False, placeholder="Generate code…")
|
288 |
+
send_btn = gr.Button("Send")
|
|
|
289 |
with gr.TabItem("🛠️ Manual"):
|
290 |
gr.Markdown("#### Create / Rename Space")
|
291 |
+
repo_m = gr.Textbox(label="Name", value="")
|
292 |
+
sdk_m = gr.Radio(["gradio","streamlit"],value="gradio",label="SDK")
|
|
|
293 |
create_btn = gr.Button("Create Space")
|
294 |
+
sess_id = gr.Textbox(visible=False)
|
295 |
+
log_c = gr.Textbox(label="Log",interactive=False,lines=2)
|
296 |
+
preview = gr.HTML("<p>No Space yet.</p>")
|
297 |
+
create_btn.click(create_space,[repo_m,sdk_m,profile_state,token_state],[sess_id,log_c,preview])
|
|
|
|
|
|
|
|
|
298 |
gr.Markdown("#### Upload File")
|
299 |
+
path = gr.Textbox(label="Path",value="app.py")
|
300 |
+
file_u = gr.File()
|
301 |
+
upload_btn = gr.Button("Upload File")
|
302 |
+
log_u = gr.Textbox(label="Upload Log",interactive=False,lines=2)
|
303 |
+
upload_btn.click(upload_file_to_space,[file_u,path,sess_id,profile_state,token_state],[log_u])
|
|
|
|
|
|
|
|
|
|
|
304 |
gr.Markdown("#### Fetch Logs")
|
305 |
b_btn = gr.Button("Build Logs")
|
306 |
r_btn = gr.Button("Run Logs")
|
307 |
+
log_b = gr.Textbox(label="Build",interactive=False,lines=5)
|
308 |
+
log_r = gr.Textbox(label="Run",interactive=False,lines=5)
|
309 |
+
b_btn.click(get_build_logs,[sess_id,profile_state,token_state],[log_b])
|
310 |
+
r_btn.click(get_container_logs,[sess_id,profile_state,token_state],[log_r])
|
|
|
|
|
|
|
|
|
|
|
|
|
311 |
gr.Markdown("---")
|
312 |
iframe_out = gr.HTML(label="🖼️ Preview")
|
313 |
+
log_out = gr.Textbox(label="📋 Latest Log",lines=4)
|
314 |
+
files_out = gr.Textbox(label="📚 Files",lines=4)
|
|
|
315 |
state = gr.State({})
|
316 |
+
send_btn.click(process_message,[profile_state,token_state,user_input,gemini_key,sidebar_repo,sidebar_sdk,chatbox,state],[chatbox,iframe_out,log_out,files_out,state])
|
317 |
+
confirm_btn.click(sync_manual,[profile_state,token_state,state],[iframe_out,log_out,files_out,state])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
318 |
|
319 |
if __name__ == "__main__":
|
320 |
demo.launch()
|