wuhp commited on
Commit
8e77934
·
verified ·
1 Parent(s): ceffe86

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -44
app.py CHANGED
@@ -1,5 +1,3 @@
1
- # main.py
2
-
3
  import os
4
  import json
5
  import uuid
@@ -24,20 +22,24 @@ SYSTEM_INSTRUCTION = (
24
  )
25
 
26
  # In-memory session store: maps session IDs to state dicts
27
- state_store = {}
28
 
29
 
30
- def start_app(gemini_key, hf_token, hf_username, repo_name):
 
31
  os.makedirs(WORKSPACE_DIR, exist_ok=True)
 
 
32
  client = genai.Client(api_key=gemini_key)
33
  config = types.GenerateContentConfig(system_instruction=SYSTEM_INSTRUCTION)
34
  tools = [Tool(google_search=GoogleSearch())]
35
  chat = client.chats.create(model=MODEL_ID, config=config, tools=tools)
36
 
 
37
  local_path = os.path.join(WORKSPACE_DIR, repo_name)
38
  os.makedirs(local_path, exist_ok=True)
39
 
40
- state = {
41
  "chat": chat,
42
  "hf_token": hf_token,
43
  "hf_username": hf_username,
@@ -45,68 +47,81 @@ def start_app(gemini_key, hf_token, hf_username, repo_name):
45
  "created": False,
46
  "repo_id": None,
47
  "local_path": local_path,
 
48
  "logs": [f"Initialized workspace at {WORKSPACE_DIR}/{repo_name}."],
49
  }
50
- return state
51
 
52
 
53
- def handle_message(user_msg, state):
 
 
54
  chat = state["chat"]
55
- logs = state.get("logs", [])
56
- logs.append(f"> User: {user_msg}")
57
 
 
58
  resp = chat.send_message(user_msg)
59
  logs.append("Received response from Gemini.")
60
- text = resp.text
61
 
62
  try:
63
- data = json.loads(text)
64
- framework = data["framework"]
65
- files = data.get("files", {})
66
- reply_msg = data.get("message", "")
67
  except Exception:
68
- logs.append("⚠️ Failed to parse assistant JSON.\n" + text)
69
- state["logs"] = logs
70
  return "⚠️ Parsing error. Check logs.", state
71
 
 
 
 
72
  if not state["created"]:
73
  full_repo = f"{state['hf_username']}/{state['repo_name']}"
74
- logs.append(f"Creating HF Space '{full_repo}' with template '{framework}'.")
75
  create_repo(
76
  repo_id=full_repo,
77
  token=state["hf_token"],
78
  exist_ok=True,
79
  repo_type="space",
80
- space_sdk=framework
81
  )
82
- state["created"] = True
83
- state["repo_id"] = full_repo
84
- state["embed_url"] = f"https://huggingface.co/spaces/{full_repo}"
85
-
 
 
 
 
 
86
  if files:
87
- logs.append(f"Writing {len(files)} file(s): {list(files.keys())}")
88
  for relpath, content in files.items():
89
  dest = os.path.join(state["local_path"], relpath)
90
  os.makedirs(os.path.dirname(dest), exist_ok=True)
91
  with open(dest, "w", encoding="utf-8") as f:
92
  f.write(content)
93
 
94
- logs.append("Uploading snapshot to Hugging Face...")
 
 
 
95
  api = HfApi(token=state["hf_token"])
96
  api.upload_folder(
97
  folder_path=state["local_path"],
98
  repo_id=state["repo_id"],
99
- repo_type="space"
100
  )
101
  logs.append("Snapshot upload complete.")
102
 
103
- state["logs"] = logs
104
  return reply_msg, state
105
 
106
 
107
  # ——— Gradio UI ———
108
- with gr.Blocks() as demo:
109
  with gr.Row():
 
 
 
110
  with gr.Column(scale=1):
111
  gemini_key = gr.Textbox(label="Gemini API Key", type="password")
112
  hf_token = gr.Textbox(label="Hugging Face Token", type="password")
@@ -115,50 +130,65 @@ with gr.Blocks() as demo:
115
  session_id = gr.Textbox(value="", visible=False)
116
  start_btn = gr.Button("Start a new app")
117
 
 
 
 
118
  with gr.Column(scale=3):
119
- chatbot = gr.Chatbot(type="messages")
120
  logs_display = gr.Textbox(label="Operation Logs", interactive=False, lines=8)
121
  preview_iframe = gr.HTML("<p>No deployed app yet.</p>")
122
 
123
  user_msg = gr.Textbox(label="Your message")
124
- send_btn = gr.Button("Send")
125
 
 
126
  def on_start(g_key, h_token, h_user, r_name):
127
  new_id = str(uuid.uuid4())
128
- state = start_app(g_key, h_token, h_user, r_name)
129
- state_store[new_id] = state
130
- logs = "\n".join(state["logs"])
131
- return new_id, logs, "<p>Awaiting first instruction...</p>"
 
 
 
 
132
 
133
  start_btn.click(
134
  on_start,
135
  inputs=[gemini_key, hf_token, hf_user, repo_name],
136
- outputs=[session_id, logs_display, preview_iframe]
137
  )
138
 
139
  def on_send(msg, chat_history, sess_id):
140
  if not sess_id or sess_id not in state_store:
141
- err = "Error: No API found. Please start a new app."
142
  return chat_history + [("", err)], sess_id, "", ""
143
- state = state_store[sess_id]
144
- reply, new_state = handle_message(msg, state)
145
  state_store[sess_id] = new_state
146
- chat_history = chat_history + [(msg, reply)]
147
- logs = "\n".join(new_state.get("logs", []))
148
- embed = ""
149
- if new_state.get("embed_url"):
150
- embed = f'<iframe src="{new_state["embed_url"]}" width="100%" height="500px"></iframe>'
 
 
 
151
  return chat_history, sess_id, logs, embed
152
 
153
  send_btn.click(
154
  on_send,
155
  inputs=[user_msg, chatbot, session_id],
156
- outputs=[chatbot, session_id, logs_display, preview_iframe]
157
  )
158
  user_msg.submit(
159
  on_send,
160
  inputs=[user_msg, chatbot, session_id],
161
- outputs=[chatbot, session_id, logs_display, preview_iframe]
162
  )
163
 
 
 
 
 
164
  demo.launch()
 
 
 
1
  import os
2
  import json
3
  import uuid
 
22
  )
23
 
24
  # In-memory session store: maps session IDs to state dicts
25
+ state_store: dict[str, dict] = {}
26
 
27
 
28
+ def start_app(gemini_key: str, hf_token: str, hf_username: str, repo_name: str) -> dict:
29
+ """Initialises a new chat session + local workspace."""
30
  os.makedirs(WORKSPACE_DIR, exist_ok=True)
31
+
32
+ # Gemini chat client
33
  client = genai.Client(api_key=gemini_key)
34
  config = types.GenerateContentConfig(system_instruction=SYSTEM_INSTRUCTION)
35
  tools = [Tool(google_search=GoogleSearch())]
36
  chat = client.chats.create(model=MODEL_ID, config=config, tools=tools)
37
 
38
+ # per‑project workspace (persisted so we can push snapshots)
39
  local_path = os.path.join(WORKSPACE_DIR, repo_name)
40
  os.makedirs(local_path, exist_ok=True)
41
 
42
+ return {
43
  "chat": chat,
44
  "hf_token": hf_token,
45
  "hf_username": hf_username,
 
47
  "created": False,
48
  "repo_id": None,
49
  "local_path": local_path,
50
+ "embed_url": None,
51
  "logs": [f"Initialized workspace at {WORKSPACE_DIR}/{repo_name}."],
52
  }
 
53
 
54
 
55
+ def handle_message(user_msg: str, state: dict):
56
+ """Send user message to Gemini, scaffold / update the Space and return reply text."""
57
+
58
  chat = state["chat"]
59
+ logs = state.setdefault("logs", [])
 
60
 
61
+ logs.append(f"> User: {user_msg}")
62
  resp = chat.send_message(user_msg)
63
  logs.append("Received response from Gemini.")
 
64
 
65
  try:
66
+ data = json.loads(resp.text)
67
+ framework: str = data["framework"]
68
+ files: dict[str, str] = data.get("files", {})
69
+ reply_msg: str = data.get("message", "")
70
  except Exception:
71
+ logs.append("⚠️ Failed to parse assistant JSON." + "\n" + resp.text)
 
72
  return "⚠️ Parsing error. Check logs.", state
73
 
74
+ # ---------------------------------------------------------------------
75
+ # Create the Space on first run
76
+ # ---------------------------------------------------------------------
77
  if not state["created"]:
78
  full_repo = f"{state['hf_username']}/{state['repo_name']}"
79
+ logs.append(f"Creating HF Space '{full_repo}' (template '{framework}') …")
80
  create_repo(
81
  repo_id=full_repo,
82
  token=state["hf_token"],
83
  exist_ok=True,
84
  repo_type="space",
85
+ space_sdk=framework,
86
  )
87
+ state.update({
88
+ "created": True,
89
+ "repo_id": full_repo,
90
+ "embed_url": f"https://huggingface.co/spaces/{full_repo}",
91
+ })
92
+
93
+ # ---------------------------------------------------------------------
94
+ # Write/overwrite files returned by Gemini
95
+ # ---------------------------------------------------------------------
96
  if files:
97
+ logs.append(f"Writing {len(files)} file(s): {list(files)}")
98
  for relpath, content in files.items():
99
  dest = os.path.join(state["local_path"], relpath)
100
  os.makedirs(os.path.dirname(dest), exist_ok=True)
101
  with open(dest, "w", encoding="utf-8") as f:
102
  f.write(content)
103
 
104
+ # ---------------------------------------------------------------------
105
+ # Commit the snapshot to the Space
106
+ # ---------------------------------------------------------------------
107
+ logs.append("Uploading snapshot to Hugging Face …")
108
  api = HfApi(token=state["hf_token"])
109
  api.upload_folder(
110
  folder_path=state["local_path"],
111
  repo_id=state["repo_id"],
112
+ repo_type="space",
113
  )
114
  logs.append("Snapshot upload complete.")
115
 
 
116
  return reply_msg, state
117
 
118
 
119
  # ——— Gradio UI ———
120
+ with gr.Blocks(title="Gemini → HF Space scaffolder") as demo:
121
  with gr.Row():
122
+ # -----------------------------------------------------------------
123
+ # Left column – credentials & new‑app form
124
+ # -----------------------------------------------------------------
125
  with gr.Column(scale=1):
126
  gemini_key = gr.Textbox(label="Gemini API Key", type="password")
127
  hf_token = gr.Textbox(label="Hugging Face Token", type="password")
 
130
  session_id = gr.Textbox(value="", visible=False)
131
  start_btn = gr.Button("Start a new app")
132
 
133
+ # -----------------------------------------------------------------
134
+ # Right column – chat & live preview
135
+ # -----------------------------------------------------------------
136
  with gr.Column(scale=3):
137
+ chatbot = gr.Chatbot(type="messages")
138
  logs_display = gr.Textbox(label="Operation Logs", interactive=False, lines=8)
139
  preview_iframe = gr.HTML("<p>No deployed app yet.</p>")
140
 
141
  user_msg = gr.Textbox(label="Your message")
142
+ send_btn = gr.Button("Send", interactive=False) # <— disabled until a session exists
143
 
144
+ # --------------- Callbacks ---------------
145
  def on_start(g_key, h_token, h_user, r_name):
146
  new_id = str(uuid.uuid4())
147
+ state_store[new_id] = start_app(g_key, h_token, h_user, r_name)
148
+ logs = "\n".join(state_store[new_id]["logs"])
149
+ return (
150
+ new_id, # session_id (hidden)
151
+ logs, # logs_display
152
+ "<p>Awaiting first instruction…</p>", # preview_iframe
153
+ gr.update(interactive=True), # enable send button
154
+ )
155
 
156
  start_btn.click(
157
  on_start,
158
  inputs=[gemini_key, hf_token, hf_user, repo_name],
159
+ outputs=[session_id, logs_display, preview_iframe, send_btn],
160
  )
161
 
162
  def on_send(msg, chat_history, sess_id):
163
  if not sess_id or sess_id not in state_store:
164
+ err = "Error: No session found. Please start a new app first."
165
  return chat_history + [("", err)], sess_id, "", ""
166
+
167
+ reply, new_state = handle_message(msg, state_store[sess_id])
168
  state_store[sess_id] = new_state
169
+
170
+ chat_history.append((msg, reply))
171
+ logs = "\n".join(new_state["logs"])
172
+ embed = (
173
+ f'<iframe src="{new_state["embed_url"]}" width="100%" height="500px"></iframe>'
174
+ if new_state.get("embed_url")
175
+ else ""
176
+ )
177
  return chat_history, sess_id, logs, embed
178
 
179
  send_btn.click(
180
  on_send,
181
  inputs=[user_msg, chatbot, session_id],
182
+ outputs=[chatbot, session_id, logs_display, preview_iframe],
183
  )
184
  user_msg.submit(
185
  on_send,
186
  inputs=[user_msg, chatbot, session_id],
187
+ outputs=[chatbot, session_id, logs_display, preview_iframe],
188
  )
189
 
190
+ # -------------------------------------------------------------------------
191
+ # Run the Gradio app – expose on default 7860 unless HF Space overrides it
192
+ # -------------------------------------------------------------------------
193
+ if __name__ == "__main__":
194
  demo.launch()