wuhp commited on
Commit
95584d3
·
verified ·
1 Parent(s): 5cac637

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +40 -45
app.py CHANGED
@@ -168,7 +168,7 @@ def add_bot_message(history: list[dict], bot_message: str) -> list[dict]:
168
 
169
  def ai_workflow_chat(
170
  message: str,
171
- history: list[dict], # Chatbot history format changed to list[dict]
172
  hf_profile: gr.OAuthProfile | None,
173
  hf_token: gr.OAuthToken | None,
174
  gemini_api_key: str | None,
@@ -184,16 +184,16 @@ def ai_workflow_chat(
184
  repo_name_state: str | None,
185
  generated_code_state: str | None,
186
  ) -> tuple[
187
- list[dict], # history
188
- str | None, # repo_id
189
- str, # workflow_state
190
- str, # preview_html
191
- str, # container_logs
192
- str, # build_logs
193
- int, # debug_attempts_state
194
- str | None, # app_description_state
195
- str | None, # repo_name_state
196
- str | None, # generated_code_state
197
  ]:
198
  # Unpack state variables
199
  repo_id = repo_id_state
@@ -214,7 +214,7 @@ def ai_workflow_chat(
214
  user_message_entry["name"] = hf_profile.username
215
  history.append(user_message_entry)
216
 
217
- # Yield immediately to show user message - this is the first yield
218
  yield history, repo_id, state, updated_preview, updated_run, updated_build, attempts, app_desc, repo_name, generated_code
219
 
220
 
@@ -272,7 +272,7 @@ def ai_workflow_chat(
272
 
273
  if state == STATE_AWAITING_REPO_NAME:
274
  new_repo_name = message.strip()
275
- if not new_repo_name or re.search(r'[^a-zA-Z0-9_-]', new_repo_name): # More robust validation
276
  history = add_bot_message(history, "Invalid name. Please provide a single word/slug for the Space name (letters, numbers, underscores, hyphens only).")
277
  yield history, repo_id, state, updated_preview, updated_run, updated_build, attempts, app_desc, repo_name, generated_code
278
  else:
@@ -364,15 +364,15 @@ Return **only** the python code block for app.py. Do not include any extra text,
364
  if "requests" in str(app_desc).lower():
365
  reqs_list.append("requests")
366
  reqs_list.append("huggingface_hub")
367
- if "image" in str(app_desc).lower() or "upload" in str(app_desc).lower() or "blur" in str(app_desc).lower() or "vision" in str(app_desc).lower(): # Added vision
368
  reqs_list.append("Pillow")
369
  if "numpy" in str(app_desc).lower(): reqs_list.append("numpy")
370
  if "pandas" in str(app_desc).lower(): reqs_list.append("pandas")
371
- if "scikit-image" in str(app_desc).lower() or "skimage" in str(app_desc).lower() or "cv2" in str(app_desc).lower() or "opencv-python" in str(app_desc).lower(): # Common image processing deps
372
- reqs_list.append("scikit-image") # skimage
373
- reqs_list.append("opencv-python") # cv2
374
 
375
- reqs_list = list(dict.fromkeys(reqs_list)) # Remove duplicates
376
 
377
  reqs_content = "\n".join(reqs_list) + "\n"
378
 
@@ -544,25 +544,15 @@ Return **only** the python code block for app.py. Do not include any extra text,
544
 
545
  elif state == STATE_COMPLETE:
546
  # Workflow finished. Stay in this state until reset.
547
- # The message is set in the state that transitioned to COMPLETE.
548
- pass # No further action needed in this state
549
 
550
 
551
  except Exception as e:
552
- # Catch-all for unexpected exceptions in any state
553
  error_message = f"Workflow step failed unexpectedly ({state}): {e}. Click 'Send' to re-attempt this step or 'reset'."
554
  history = add_bot_message(history, error_message)
555
  print(f"Critical Error in state {state}: {e}")
556
- # Transition to idle state on unexpected errors
557
  yield history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0, None, None, None
558
- return # End generator
559
-
560
-
561
- # Note: Each state block should end with a yield to update the UI/state.
562
- # If a state block finishes without yielding, the generator will stop until the next call.
563
- # By yielding the state variables *after* adding the user message, and then yielding
564
- # again after state transitions/actions *within* the state logic, we ensure updates.
565
- # The final yield after the try/except is removed as yields should happen within the state logic.
566
 
567
 
568
  # --- Build the Gradio UI ---
@@ -579,7 +569,7 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
579
  debug_attempts = gr.State(0)
580
  app_description = gr.State(None)
581
  repo_name_state = gr.State(None)
582
- generated_code_state = gr.State(None) # Reused
583
 
584
  with gr.Row():
585
  # Sidebar
@@ -592,14 +582,17 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
592
  # Removed _preprocess=False
593
  ai_builder_tab.load(show_profile, outputs=login_status)
594
  # Update status on login click
 
595
  login_btn.click(show_profile, outputs=login_status)
596
  # Store profile and token in state on login click
 
597
  login_btn.click(lambda x: x, inputs=[login_btn], outputs=[hf_profile, hf_token])
598
 
599
  gr.Markdown("## Google AI Studio API Key")
600
  gemini_input = gr.Textbox(label="API Key", type="password", interactive=True)
601
  gemini_status = gr.Markdown("")
602
 
 
603
  gemini_input.change(lambda k: k, inputs=gemini_input, outputs=gemini_key)
604
 
605
  gr.Markdown("## Gemini Model")
@@ -613,6 +606,7 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
613
  label="Select model",
614
  interactive=True
615
  )
 
616
  model_selector.change(lambda m: m, inputs=model_selector, outputs=gemini_model)
617
 
618
  # Configure Gemini status on load and when key/model changes
@@ -622,23 +616,23 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
622
  inputs=[gemini_key, gemini_model],
623
  outputs=[gemini_status]
624
  )
625
- # Keep _preprocess=False on change events as they have implicit outputs (the new value)
626
  gemini_input.change(
627
  configure_gemini,
628
  inputs=[gemini_key, gemini_model],
629
- outputs=[gemini_status],
630
- _preprocess=False
631
  )
 
632
  model_selector.change(
633
  configure_gemini,
634
  inputs=[gemini_key, gemini_model],
635
- outputs=[gemini_status],
636
- _preprocess=False
637
  )
638
 
639
 
640
  gr.Markdown("## Space SDK")
641
  sdk_selector = gr.Radio(choices=["gradio","streamlit"], value="gradio", label="Template SDK", interactive=True)
 
642
  sdk_selector.change(lambda s: s, inputs=sdk_selector, outputs=sdk_state)
643
 
644
  gr.Markdown("## Workflow Status")
@@ -663,24 +657,23 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
663
  inputs=[hf_profile, hf_token, gemini_key, gemini_model],
664
  outputs=[send_btn]
665
  )
666
- # Keep _preprocess=False on click/change events with explicit inputs
667
  login_btn.click(
668
  update_send_button_state,
669
  inputs=[hf_profile, hf_token, gemini_key, gemini_model],
670
- outputs=[send_btn],
671
- _preprocess=False
672
  )
 
673
  gemini_input.change(
674
  update_send_button_state,
675
  inputs=[hf_profile, hf_token, gemini_key, gemini_model],
676
- outputs=[send_btn],
677
- _preprocess=False
678
  )
 
679
  model_selector.change(
680
  update_send_button_state,
681
  inputs=[hf_profile, hf_token, gemini_key, gemini_model],
682
- outputs=[send_btn],
683
- _preprocess=False
684
  )
685
 
686
  iframe = gr.HTML("<p>No Space created yet.</p>")
@@ -688,6 +681,7 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
688
  run_txt = gr.Textbox(label="Container Logs", lines=10, interactive=False, value="")
689
 
690
  # The main event handler for the Send button
 
691
  send_btn.click(
692
  ai_workflow_chat,
693
  inputs=[
@@ -704,14 +698,16 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
704
  iframe, run_txt, build_txt,
705
  debug_attempts, app_description, repo_name_state, generated_code_state
706
  ]
707
- ).success( # Clear input after successful send
708
  lambda: gr.update(value=""),
709
  inputs=None,
710
  outputs=user_input
711
  )
712
 
713
  # Link state variables to UI status displays (reactive updates)
 
714
  workflow.change(lambda s: s, inputs=workflow, outputs=status_text)
 
715
  repo_id.change(lambda r: r if r else "None", inputs=repo_id, outputs=repo_id_text)
716
 
717
 
@@ -719,7 +715,6 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
719
  def greet():
720
  return [{"role": "assistant", "content": "Welcome! Please log in to Hugging Face and provide your Google AI Studio API key to start building Spaces. Once ready, type 'generate me a gradio app called myapp' or 'create' to begin."}]
721
 
722
- # THIS CALL IS INSIDE the with gr.Blocks() block
723
  ai_builder_tab.load(greet, outputs=chatbot)
724
 
725
 
 
168
 
169
  def ai_workflow_chat(
170
  message: str,
171
+ history: list[dict],
172
  hf_profile: gr.OAuthProfile | None,
173
  hf_token: gr.OAuthToken | None,
174
  gemini_api_key: str | None,
 
184
  repo_name_state: str | None,
185
  generated_code_state: str | None,
186
  ) -> tuple[
187
+ list[dict],
188
+ str | None,
189
+ str,
190
+ str,
191
+ str,
192
+ str,
193
+ int,
194
+ str | None,
195
+ str | None,
196
+ str | None,
197
  ]:
198
  # Unpack state variables
199
  repo_id = repo_id_state
 
214
  user_message_entry["name"] = hf_profile.username
215
  history.append(user_message_entry)
216
 
217
+ # Yield immediately to show user message
218
  yield history, repo_id, state, updated_preview, updated_run, updated_build, attempts, app_desc, repo_name, generated_code
219
 
220
 
 
272
 
273
  if state == STATE_AWAITING_REPO_NAME:
274
  new_repo_name = message.strip()
275
+ if not new_repo_name or re.search(r'[^a-zA-Z0-9_-]', new_repo_name):
276
  history = add_bot_message(history, "Invalid name. Please provide a single word/slug for the Space name (letters, numbers, underscores, hyphens only).")
277
  yield history, repo_id, state, updated_preview, updated_run, updated_build, attempts, app_desc, repo_name, generated_code
278
  else:
 
364
  if "requests" in str(app_desc).lower():
365
  reqs_list.append("requests")
366
  reqs_list.append("huggingface_hub")
367
+ if "image" in str(app_desc).lower() or "upload" in str(app_desc).lower() or "blur" in str(app_desc).lower() or "vision" in str(app_desc).lower():
368
  reqs_list.append("Pillow")
369
  if "numpy" in str(app_desc).lower(): reqs_list.append("numpy")
370
  if "pandas" in str(app_desc).lower(): reqs_list.append("pandas")
371
+ if "scikit-image" in str(app_desc).lower() or "skimage" in str(app_desc).lower() or "cv2" in str(app_desc).lower() or "opencv-python" in str(app_desc).lower():
372
+ reqs_list.append("scikit-image")
373
+ reqs_list.append("opencv-python")
374
 
375
+ reqs_list = list(dict.fromkeys(reqs_list))
376
 
377
  reqs_content = "\n".join(reqs_list) + "\n"
378
 
 
544
 
545
  elif state == STATE_COMPLETE:
546
  # Workflow finished. Stay in this state until reset.
547
+ pass
 
548
 
549
 
550
  except Exception as e:
 
551
  error_message = f"Workflow step failed unexpectedly ({state}): {e}. Click 'Send' to re-attempt this step or 'reset'."
552
  history = add_bot_message(history, error_message)
553
  print(f"Critical Error in state {state}: {e}")
 
554
  yield history, None, STATE_IDLE, updated_preview, updated_run, updated_build, 0, None, None, None
555
+ return
 
 
 
 
 
 
 
556
 
557
 
558
  # --- Build the Gradio UI ---
 
569
  debug_attempts = gr.State(0)
570
  app_description = gr.State(None)
571
  repo_name_state = gr.State(None)
572
+ generated_code_state = gr.State(None)
573
 
574
  with gr.Row():
575
  # Sidebar
 
582
  # Removed _preprocess=False
583
  ai_builder_tab.load(show_profile, outputs=login_status)
584
  # Update status on login click
585
+ # Removed _preprocess=False
586
  login_btn.click(show_profile, outputs=login_status)
587
  # Store profile and token in state on login click
588
+ # Removed _preprocess=False
589
  login_btn.click(lambda x: x, inputs=[login_btn], outputs=[hf_profile, hf_token])
590
 
591
  gr.Markdown("## Google AI Studio API Key")
592
  gemini_input = gr.Textbox(label="API Key", type="password", interactive=True)
593
  gemini_status = gr.Markdown("")
594
 
595
+ # Removed _preprocess=False
596
  gemini_input.change(lambda k: k, inputs=gemini_input, outputs=gemini_key)
597
 
598
  gr.Markdown("## Gemini Model")
 
606
  label="Select model",
607
  interactive=True
608
  )
609
+ # Removed _preprocess=False
610
  model_selector.change(lambda m: m, inputs=model_selector, outputs=gemini_model)
611
 
612
  # Configure Gemini status on load and when key/model changes
 
616
  inputs=[gemini_key, gemini_model],
617
  outputs=[gemini_status]
618
  )
619
+ # Removed _preprocess=False
620
  gemini_input.change(
621
  configure_gemini,
622
  inputs=[gemini_key, gemini_model],
623
+ outputs=[gemini_status]
 
624
  )
625
+ # Removed _preprocess=False
626
  model_selector.change(
627
  configure_gemini,
628
  inputs=[gemini_key, gemini_model],
629
+ outputs=[gemini_status]
 
630
  )
631
 
632
 
633
  gr.Markdown("## Space SDK")
634
  sdk_selector = gr.Radio(choices=["gradio","streamlit"], value="gradio", label="Template SDK", interactive=True)
635
+ # Removed _preprocess=False
636
  sdk_selector.change(lambda s: s, inputs=sdk_selector, outputs=sdk_state)
637
 
638
  gr.Markdown("## Workflow Status")
 
657
  inputs=[hf_profile, hf_token, gemini_key, gemini_model],
658
  outputs=[send_btn]
659
  )
660
+ # Removed _preprocess=False
661
  login_btn.click(
662
  update_send_button_state,
663
  inputs=[hf_profile, hf_token, gemini_key, gemini_model],
664
+ outputs=[send_btn]
 
665
  )
666
+ # Removed _preprocess=False
667
  gemini_input.change(
668
  update_send_button_state,
669
  inputs=[hf_profile, hf_token, gemini_key, gemini_model],
670
+ outputs=[send_btn]
 
671
  )
672
+ # Removed _preprocess=False
673
  model_selector.change(
674
  update_send_button_state,
675
  inputs=[hf_profile, hf_token, gemini_key, gemini_model],
676
+ outputs=[send_btn]
 
677
  )
678
 
679
  iframe = gr.HTML("<p>No Space created yet.</p>")
 
681
  run_txt = gr.Textbox(label="Container Logs", lines=10, interactive=False, value="")
682
 
683
  # The main event handler for the Send button
684
+ # Removed _preprocess=False (it wasn't on this one anyway)
685
  send_btn.click(
686
  ai_workflow_chat,
687
  inputs=[
 
698
  iframe, run_txt, build_txt,
699
  debug_attempts, app_description, repo_name_state, generated_code_state
700
  ]
701
+ ).success(
702
  lambda: gr.update(value=""),
703
  inputs=None,
704
  outputs=user_input
705
  )
706
 
707
  # Link state variables to UI status displays (reactive updates)
708
+ # Removed _preprocess=False
709
  workflow.change(lambda s: s, inputs=workflow, outputs=status_text)
710
+ # Removed _preprocess=False
711
  repo_id.change(lambda r: r if r else "None", inputs=repo_id, outputs=repo_id_text)
712
 
713
 
 
715
  def greet():
716
  return [{"role": "assistant", "content": "Welcome! Please log in to Hugging Face and provide your Google AI Studio API key to start building Spaces. Once ready, type 'generate me a gradio app called myapp' or 'create' to begin."}]
717
 
 
718
  ai_builder_tab.load(greet, outputs=chatbot)
719
 
720