wuhp commited on
Commit
a28d73c
·
verified ·
1 Parent(s): 5a807ae

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +71 -93
app.py CHANGED
@@ -5,6 +5,13 @@ from huggingface_hub.utils import build_hf_headers, get_session, hf_raise_for_st
5
  from google import genai # Gemini Python SDK
6
  from google.genai.types import Tool, GenerateContentConfig, GoogleSearch
7
 
 
 
 
 
 
 
 
8
  # — HELPERS FOR HF SPACE LOGS —
9
 
10
  def _get_space_jwt(repo_id: str):
@@ -30,37 +37,24 @@ def fetch_logs(repo_id: str, level: str):
30
  continue
31
  return "\n".join(lines)
32
 
33
- # — UTILS —
34
-
35
- def normalize_history(history):
36
- """
37
- Take Chatbot 'messages' history (list of ChatMessage or dict)
38
- and return list of dicts: {'role': ..., 'content': ...}
39
- """
40
- out = []
41
- for msg in history:
42
- if isinstance(msg, dict):
43
- out.append({"role": msg["role"], "content": msg["content"]})
44
- else:
45
- # ChatMessage namedtuple
46
- out.append({"role": msg.role, "content": msg.content})
47
- return out
48
-
49
  # — CORE LOOP: send prompt & (iteratively) deploy —
50
 
51
  def handle_user_message(
52
- history,
53
- hf_profile, hf_token,
54
  sdk_choice: str,
55
- gemini_api_key, grounding_enabled
 
 
 
56
  ):
57
- # must be logged in
58
- if hf_profile is None or hf_token is None:
59
  return history + [{"role":"assistant","content":"⚠️ Please log in first."}], "", "", "<p>No Space yet.</p>"
60
 
 
61
  genai_client = genai.Client(api_key=gemini_api_key)
62
 
63
- # build system + user chat
64
  chat = [{
65
  "role":"system",
66
  "content":(
@@ -68,36 +62,39 @@ def handle_user_message(
68
  f"{sdk_choice} SDK. After producing code, wait for logs. "
69
  "If errors appear, fix them and return the full updated code."
70
  )
71
- }]
72
- chat += normalize_history(history)
73
 
74
  filename = "app.py" if sdk_choice=="gradio" else "streamlit_app.py"
75
  build_logs = run_logs = ""
76
 
77
  for _ in range(5):
78
- # setup tools for grounding
79
  tools = []
80
  if grounding_enabled:
81
  tools.append(Tool(google_search=GoogleSearch()))
82
- config = GenerateContentConfig(tools=tools, response_modalities=["TEXT"])
 
 
 
 
83
 
84
  # call Gemini
85
- resp = genai_client.models.generate_content(
86
  model="gemini-2.5-flash-preview-04-17",
87
- contents=[c["content"] for c in chat],
88
  config=config
89
  )
90
- ai_code = resp.text
91
  chat.append({"role":"assistant", "content": ai_code})
92
 
93
  # write & deploy
94
  with open(filename, "w") as f:
95
  f.write(ai_code)
96
 
97
- repo_id = f"{hf_profile.username}/{hf_profile.username}-auto-space"
98
  create_repo(
99
  repo_id=repo_id,
100
- token=hf_token.token,
101
  exist_ok=True,
102
  repo_type="space",
103
  space_sdk=sdk_choice
@@ -106,19 +103,19 @@ def handle_user_message(
106
  path_or_fileobj=filename,
107
  path_in_repo=filename,
108
  repo_id=repo_id,
109
- token=hf_token.token,
110
  repo_type="space"
111
  )
112
 
113
- # fetch logs
114
  build_logs = fetch_logs(repo_id, "build")
115
  run_logs = fetch_logs(repo_id, "run")
116
 
117
- # done if no errors
118
  if "ERROR" not in build_logs.upper() and "ERROR" not in run_logs.upper():
119
  break
120
 
121
- # else feed back
122
  chat.append({
123
  "role":"user",
124
  "content":(
@@ -129,67 +126,48 @@ def handle_user_message(
129
  })
130
  time.sleep(2)
131
 
132
- # prepare return: a list of dicts for Chatbot(type="messages")
133
- return (
134
- [{"role":m["role"], "content":m["content"]} for m in chat if m["role"]!="system"],
135
- build_logs,
136
- run_logs,
137
- f'<iframe src="https://huggingface.co/spaces/{repo_id}" width="100%" height="500px"></iframe>'
138
- )
139
 
140
- # — GRADIO UI —
141
 
142
  with gr.Blocks(title="HF Space Auto‑Builder (Gradio & Streamlit)") as demo:
143
- with gr.Row():
144
- with gr.Column(scale=1):
145
- gr.Markdown("### Sidebar")
146
-
147
- profile_state = gr.State()
148
- token_state = gr.State()
149
-
150
- login_btn = gr.LoginButton("huggingface", size="sm")
151
- login_status = gr.Markdown("*Not logged in.*")
152
-
153
- # capture the profile/token from the LoginButton
154
- login_btn.click(
155
- fn=lambda profile, oauth_token: (profile, oauth_token),
156
- inputs=None,
157
- outputs=[profile_state, token_state]
158
- )
159
- # update the status text once those states are set
160
- login_btn.click(
161
- fn=lambda profile, oauth_token: f"Logged in as **{profile.username}**"
162
- if profile else "*Not logged in.*",
163
- inputs=[profile_state, token_state],
164
- outputs=login_status
165
- )
166
-
167
- sdk_choice = gr.Radio(
168
- ["gradio","streamlit"],
169
- value="gradio",
170
- label="SDK Template"
171
- )
172
- api_key = gr.Textbox(label="Gemini API Key", type="password")
173
- grounding = gr.Checkbox(label="Enable grounding", value=False)
174
-
175
- with gr.Column(scale=3):
176
- chatbot = gr.Chatbot(type="messages")
177
- user_in = gr.Textbox(placeholder="Your prompt …", label="Prompt")
178
- send_btn = gr.Button("Send")
179
-
180
- build_box = gr.Textbox(label="Build logs", lines=5, interactive=False)
181
- run_box = gr.Textbox(label="Run logs", lines=5, interactive=False)
182
- preview = gr.HTML("<p>No Space yet.</p>")
183
-
184
- send_btn.click(
185
- fn=handle_user_message,
186
- inputs=[
187
- chatbot,
188
- profile_state, token_state,
189
- sdk_choice, api_key, grounding
190
- ],
191
- outputs=[chatbot, build_box, run_box, preview]
192
- )
193
 
194
  if __name__=="__main__":
195
  demo.launch()
 
5
  from google import genai # Gemini Python SDK
6
  from google.genai.types import Tool, GenerateContentConfig, GoogleSearch
7
 
8
+ # — USER INFO & MODEL LISTING (from your reference) —
9
+
10
+ def show_profile(profile: gr.OAuthProfile | None) -> str:
11
+ if profile is None:
12
+ return "*Not logged in.*"
13
+ return f"✅ Logged in as **{profile.username}**"
14
+
15
  # — HELPERS FOR HF SPACE LOGS —
16
 
17
  def _get_space_jwt(repo_id: str):
 
37
  continue
38
  return "\n".join(lines)
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  # — CORE LOOP: send prompt & (iteratively) deploy —
41
 
42
  def handle_user_message(
43
+ history, # list of {"role","content"} dicts
 
44
  sdk_choice: str,
45
+ gemini_api_key: str,
46
+ grounding_enabled: bool,
47
+ profile: gr.OAuthProfile | None,
48
+ oauth_token: gr.OAuthToken | None
49
  ):
50
+ # require login
51
+ if profile is None or oauth_token is None:
52
  return history + [{"role":"assistant","content":"⚠️ Please log in first."}], "", "", "<p>No Space yet.</p>"
53
 
54
+ # initialize Gemini
55
  genai_client = genai.Client(api_key=gemini_api_key)
56
 
57
+ # build the prompt history (including a system instruction)
58
  chat = [{
59
  "role":"system",
60
  "content":(
 
62
  f"{sdk_choice} SDK. After producing code, wait for logs. "
63
  "If errors appear, fix them and return the full updated code."
64
  )
65
+ }] + history
 
66
 
67
  filename = "app.py" if sdk_choice=="gradio" else "streamlit_app.py"
68
  build_logs = run_logs = ""
69
 
70
  for _ in range(5):
71
+ # assemble tools
72
  tools = []
73
  if grounding_enabled:
74
  tools.append(Tool(google_search=GoogleSearch()))
75
+
76
+ config = GenerateContentConfig(
77
+ tools=tools,
78
+ response_modalities=["TEXT"],
79
+ )
80
 
81
  # call Gemini
82
+ response = genai_client.models.generate_content(
83
  model="gemini-2.5-flash-preview-04-17",
84
+ contents=[m["content"] for m in chat],
85
  config=config
86
  )
87
+ ai_code = response.text
88
  chat.append({"role":"assistant", "content": ai_code})
89
 
90
  # write & deploy
91
  with open(filename, "w") as f:
92
  f.write(ai_code)
93
 
94
+ repo_id = f"{profile.username}/{profile.username}-auto-space"
95
  create_repo(
96
  repo_id=repo_id,
97
+ token=oauth_token.token,
98
  exist_ok=True,
99
  repo_type="space",
100
  space_sdk=sdk_choice
 
103
  path_or_fileobj=filename,
104
  path_in_repo=filename,
105
  repo_id=repo_id,
106
+ token=oauth_token.token,
107
  repo_type="space"
108
  )
109
 
110
+ # fetch build & run logs
111
  build_logs = fetch_logs(repo_id, "build")
112
  run_logs = fetch_logs(repo_id, "run")
113
 
114
+ # if no errors, stop looping
115
  if "ERROR" not in build_logs.upper() and "ERROR" not in run_logs.upper():
116
  break
117
 
118
+ # otherwise feed logs back to Gemini
119
  chat.append({
120
  "role":"user",
121
  "content":(
 
126
  })
127
  time.sleep(2)
128
 
129
+ # prepare outputs for gr.Chatbot(type="messages")
130
+ messages = [{"role":m["role"], "content":m["content"]} for m in chat if m["role"]!="system"]
131
+ iframe = f'<iframe src="https://huggingface.co/spaces/{repo_id}" width="100%" height="500px"></iframe>'
132
+ return messages, build_logs, run_logs, iframe
 
 
 
133
 
134
+ # — BUILD THE UI —
135
 
136
  with gr.Blocks(title="HF Space Auto‑Builder (Gradio & Streamlit)") as demo:
137
+ gr.Markdown("## Sign in with Hugging Face + Auto‑Build Spaces\n\n"
138
+ "1. Sign in\n2. Enter your prompt\n3. Watch the code deploy & debug itself\n\n---")
139
+
140
+ # — LOGIN —
141
+ login_btn = gr.LoginButton(variant="huggingface", size="lg")
142
+ status_md = gr.Markdown("*Not logged in.*")
143
+ # automatically show profile on load & login
144
+ demo.load(show_profile, inputs=None, outputs=status_md)
145
+ login_btn.click(show_profile, inputs=None, outputs=status_md)
146
+
147
+ # SIDEBAR CONTROLS
148
+ sdk_choice = gr.Radio(
149
+ choices=["gradio","streamlit"],
150
+ value="gradio",
151
+ label="SDK template"
152
+ )
153
+ api_key = gr.Textbox(label="Gemini API Key", type="password")
154
+ grounding = gr.Checkbox(label="Enable grounding", value=False)
155
+
156
+ # CHAT INTERFACE & OUTPUTS —
157
+ chatbot = gr.Chatbot(type="messages")
158
+ user_in = gr.Textbox(placeholder="e.g. Generate me a blurtest app…", label="Prompt")
159
+ send_btn = gr.Button("Send")
160
+
161
+ build_box = gr.Textbox(label="Build logs", lines=5, interactive=False)
162
+ run_box = gr.Textbox(label="Run logs", lines=5, interactive=False)
163
+ preview = gr.HTML("<p>No Space yet.</p>")
164
+
165
+ # wire up the Send button
166
+ send_btn.click(
167
+ fn=handle_user_message,
168
+ inputs=[chatbot, sdk_choice, api_key, grounding],
169
+ outputs=[chatbot, build_box, run_box, preview]
170
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
  if __name__=="__main__":
173
  demo.launch()