Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1 |
-
import
|
2 |
import gradio as gr
|
3 |
from huggingface_hub import (
|
4 |
-
create_repo, list_models, upload_file, constants
|
5 |
)
|
6 |
from huggingface_hub.utils import build_hf_headers, get_session, hf_raise_for_status
|
7 |
from google import genai
|
@@ -35,13 +35,7 @@ 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(
|
39 |
-
repo_id=rid,
|
40 |
-
token=token.token,
|
41 |
-
exist_ok=True,
|
42 |
-
repo_type="space",
|
43 |
-
space_sdk=sdk
|
44 |
-
)
|
45 |
url = f"https://huggingface.co/spaces/{rid}"
|
46 |
return rid, f"โ
Space ready: {url}", f'<iframe src="{url}" width="100%" height="400px"></iframe>'
|
47 |
|
@@ -52,18 +46,11 @@ def upload_file_to_space(file, path, repo_id, profile, token):
|
|
52 |
return "โ ๏ธ Please create a Space first."
|
53 |
if not file:
|
54 |
return "โ ๏ธ No file selected."
|
55 |
-
upload_file(
|
56 |
-
path_or_fileobj=file.name,
|
57 |
-
path_in_repo=path,
|
58 |
-
repo_id=repo_id,
|
59 |
-
token=token.token,
|
60 |
-
repo_type="space"
|
61 |
-
)
|
62 |
return f"โ
Uploaded `{path}` to `{repo_id}`"
|
63 |
|
64 |
def _fetch_space_logs_level(repo_id, level):
|
65 |
-
|
66 |
-
r = get_session().get(jwt_url, headers=build_hf_headers())
|
67 |
hf_raise_for_status(r)
|
68 |
jwt = r.json()["token"]
|
69 |
url = f"https://api.hf.space/v1/{repo_id}/logs/{level}"
|
@@ -86,12 +73,11 @@ def get_container_logs(repo_id, profile, token):
|
|
86 |
return "โ ๏ธ Please log in and create a Space first."
|
87 |
return _fetch_space_logs_level(repo_id, "run")
|
88 |
|
89 |
-
|
90 |
# โ GEMINI FUNCTION DECLARATIONS โ
|
91 |
|
92 |
func_decls = [
|
93 |
{
|
94 |
-
"name":"create_space","description":"Create
|
95 |
"parameters":{
|
96 |
"type":"object",
|
97 |
"properties":{
|
@@ -102,7 +88,7 @@ func_decls = [
|
|
102 |
}
|
103 |
},
|
104 |
{
|
105 |
-
"name":"list_files","description":"List files in
|
106 |
"parameters":{
|
107 |
"type":"object",
|
108 |
"properties":{"repo_id":{"type":"string"}},
|
@@ -136,8 +122,8 @@ def process_message(profile, token, user_msg,
|
|
136 |
client = genai.Client(api_key=gemini_key)
|
137 |
cfg = types.GenerateContentConfig(
|
138 |
system_instruction=(
|
139 |
-
"You are a HF Spaces admin. "
|
140 |
-
"
|
141 |
),
|
142 |
temperature=0,
|
143 |
tools=[ types.Tool(function_declarations=func_decls) ]
|
@@ -154,20 +140,18 @@ def process_message(profile, token, user_msg,
|
|
154 |
if part.function_call:
|
155 |
name = part.function_call.name
|
156 |
args = json.loads(part.function_call.args)
|
157 |
-
if name=="create_space":
|
158 |
rid, log, iframe = create_space(
|
159 |
args["repo_name"], args["sdk"], profile, token
|
160 |
)
|
161 |
session["repo_id"] = rid
|
162 |
result = {"log": log, "iframe": iframe}
|
163 |
-
elif name=="list_files":
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
result = {"files": "\n".join(files)}
|
168 |
-
elif name=="get_build_logs":
|
169 |
result = {"log": get_build_logs(session["repo_id"], profile, token)}
|
170 |
-
elif name=="get_run_logs":
|
171 |
result = {"log": get_container_logs(session["repo_id"], profile, token)}
|
172 |
else:
|
173 |
result = {"log": f"โ ๏ธ Unknown function {name}"}
|
@@ -185,7 +169,6 @@ def process_message(profile, token, user_msg,
|
|
185 |
else:
|
186 |
final = part.text
|
187 |
|
188 |
-
# update panels
|
189 |
if "iframe" in result: session["iframe"] = result["iframe"]
|
190 |
if "log" in result: session["log"] = result["log"]
|
191 |
if "files" in result: session["files"] = result["files"]
|
@@ -203,25 +186,19 @@ def sync_manual(profile, token, session):
|
|
203 |
"โ ๏ธ Cannot sync manual changes.",
|
204 |
session.get("files",""),
|
205 |
session)
|
206 |
-
|
207 |
-
|
208 |
-
)
|
209 |
-
session["files"] = "\n".join(files)
|
210 |
session["log"] = "๐ Manual changes synced."
|
211 |
return (session.get("iframe",""),
|
212 |
session["log"],
|
213 |
session["files"],
|
214 |
session)
|
215 |
|
216 |
-
|
217 |
-
return profile, oauth_token
|
218 |
-
|
219 |
-
|
220 |
-
# โ BUILD THE UI โ
|
221 |
|
222 |
with gr.Blocks(css="""
|
223 |
-
#sidebar {background
|
224 |
-
#main {padding:1rem;}
|
225 |
""") as demo:
|
226 |
|
227 |
with gr.Row():
|
@@ -229,17 +206,14 @@ with gr.Blocks(css="""
|
|
229 |
with gr.Column(elem_id="sidebar", scale=1):
|
230 |
gr.Markdown("### ๐ HF Login & Config")
|
231 |
login_btn = gr.LoginButton(variant="huggingface", size="sm")
|
232 |
-
profile_state = gr.State()
|
233 |
-
token_state = gr.State()
|
234 |
|
235 |
-
|
236 |
-
|
237 |
-
outputs=[profile_state, token_state])
|
238 |
|
239 |
status_md = gr.Markdown("*Not logged in.*")
|
240 |
-
profile_state.change(show_profile,
|
241 |
-
inputs=[profile_state],
|
242 |
-
outputs=[status_md])
|
243 |
|
244 |
models_md = gr.Markdown()
|
245 |
profile_state.change(list_private_models,
|
@@ -248,8 +222,7 @@ with gr.Blocks(css="""
|
|
248 |
|
249 |
gemini_key = gr.Textbox(label="Gemini API Key", type="password")
|
250 |
sidebar_repo = gr.Textbox(label="Space name", placeholder="my-space")
|
251 |
-
sidebar_sdk = gr.Radio(["gradio","streamlit"],
|
252 |
-
value="gradio", label="SDK")
|
253 |
|
254 |
gr.Markdown("---")
|
255 |
confirm_btn = gr.Button("๐ Confirm Manual Changes")
|
@@ -259,19 +232,16 @@ with gr.Blocks(css="""
|
|
259 |
tabs = gr.Tabs()
|
260 |
with tabs:
|
261 |
with gr.TabItem("๐ฌ Chat"):
|
262 |
-
chatbox = gr.Chatbot(type="
|
263 |
-
user_input = gr.Textbox(show_label=False,
|
264 |
-
placeholder="Ask the LLMโฆ")
|
265 |
send_btn = gr.Button("Send")
|
266 |
with gr.TabItem("๐ ๏ธ Manual"):
|
267 |
gr.Markdown("#### Create a Space")
|
268 |
-
repo_m
|
269 |
-
sdk_m
|
270 |
-
value="gradio", label="SDK")
|
271 |
create_btn = gr.Button("Create Space")
|
272 |
sess_id = gr.Textbox(visible=False)
|
273 |
-
log_c = gr.Textbox(label="Log",
|
274 |
-
interactive=False, lines=2)
|
275 |
preview = gr.HTML("<p>No Space yet.</p>")
|
276 |
|
277 |
create_btn.click(create_space,
|
@@ -280,37 +250,30 @@ with gr.Blocks(css="""
|
|
280 |
outputs=[sess_id, log_c, preview])
|
281 |
|
282 |
gr.Markdown("#### Upload File")
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
sess_id,
|
293 |
-
profile_state, token_state],
|
294 |
-
outputs=[log_u])
|
295 |
|
296 |
gr.Markdown("#### Fetch Logs")
|
297 |
b_btn = gr.Button("Build Logs")
|
298 |
r_btn = gr.Button("Run Logs")
|
299 |
-
log_b = gr.Textbox(label="Build",
|
300 |
-
|
301 |
-
log_r = gr.Textbox(label="Run",
|
302 |
-
interactive=False, lines=5)
|
303 |
|
304 |
b_btn.click(get_build_logs,
|
305 |
-
inputs=[sess_id,
|
306 |
-
profile_state, token_state],
|
307 |
outputs=[log_b])
|
308 |
r_btn.click(get_container_logs,
|
309 |
-
inputs=[sess_id,
|
310 |
-
profile_state, token_state],
|
311 |
outputs=[log_r])
|
312 |
|
313 |
-
#
|
314 |
gr.Markdown("---")
|
315 |
iframe_out = gr.HTML(label="๐ผ๏ธ Preview")
|
316 |
log_out = gr.Textbox(label="๐ Latest Log", lines=4)
|
|
|
1 |
+
import json, os
|
2 |
import gradio as gr
|
3 |
from huggingface_hub import (
|
4 |
+
create_repo, list_models, upload_file, list_repo_files, constants
|
5 |
)
|
6 |
from huggingface_hub.utils import build_hf_headers, get_session, hf_raise_for_status
|
7 |
from google import genai
|
|
|
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 |
|
|
|
46 |
return "โ ๏ธ Please create a Space first."
|
47 |
if not file:
|
48 |
return "โ ๏ธ No file selected."
|
49 |
+
upload_file(file.name, path, repo_id, token=token.token, repo_type="space")
|
|
|
|
|
|
|
|
|
|
|
|
|
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}"
|
|
|
73 |
return "โ ๏ธ Please log in and create a Space first."
|
74 |
return _fetch_space_logs_level(repo_id, "run")
|
75 |
|
|
|
76 |
# โ GEMINI FUNCTION DECLARATIONS โ
|
77 |
|
78 |
func_decls = [
|
79 |
{
|
80 |
+
"name":"create_space","description":"Create/get a HF Space",
|
81 |
"parameters":{
|
82 |
"type":"object",
|
83 |
"properties":{
|
|
|
88 |
}
|
89 |
},
|
90 |
{
|
91 |
+
"name":"list_files","description":"List files in Space",
|
92 |
"parameters":{
|
93 |
"type":"object",
|
94 |
"properties":{"repo_id":{"type":"string"}},
|
|
|
122 |
client = genai.Client(api_key=gemini_key)
|
123 |
cfg = types.GenerateContentConfig(
|
124 |
system_instruction=(
|
125 |
+
"You are a HF Spaces admin. Use functions to create spaces, "
|
126 |
+
"list files, and fetch logs."
|
127 |
),
|
128 |
temperature=0,
|
129 |
tools=[ types.Tool(function_declarations=func_decls) ]
|
|
|
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
|
146 |
)
|
147 |
session["repo_id"] = rid
|
148 |
result = {"log": log, "iframe": iframe}
|
149 |
+
elif name == "list_files":
|
150 |
+
fl = list_repo_files(session["repo_id"], token=token.token, repo_type="space")
|
151 |
+
result = {"files": "\n".join(fl)}
|
152 |
+
elif name == "get_build_logs":
|
|
|
|
|
153 |
result = {"log": get_build_logs(session["repo_id"], profile, token)}
|
154 |
+
elif name == "get_run_logs":
|
155 |
result = {"log": get_container_logs(session["repo_id"], profile, token)}
|
156 |
else:
|
157 |
result = {"log": f"โ ๏ธ Unknown function {name}"}
|
|
|
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"]
|
|
|
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():
|
|
|
206 |
with gr.Column(elem_id="sidebar", scale=1):
|
207 |
gr.Markdown("### ๐ HF Login & Config")
|
208 |
login_btn = gr.LoginButton(variant="huggingface", size="sm")
|
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 |
|
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 |
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,
|
|
|
250 |
outputs=[sess_id, log_c, preview])
|
251 |
|
252 |
gr.Markdown("#### Upload File")
|
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,
|
260 |
+
profile_state, token_state],
|
261 |
+
outputs=[log_u])
|
|
|
|
|
|
|
262 |
|
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],
|
|
|
271 |
outputs=[log_b])
|
272 |
r_btn.click(get_container_logs,
|
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)
|