wuhp commited on
Commit
e5dc606
·
verified ·
1 Parent(s): cb1b9d8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +66 -60
app.py CHANGED
@@ -230,7 +230,8 @@ def greet():
230
 
231
  # Helper function to update send button interactivity based on prereqs
232
  # Now takes explicit arguments, intended to be called with all necessary states.
233
- def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAuthToken | None, gemini_key: str | None, gemini_model: str | None) -> gr.update:
 
234
  """Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
235
  # --- START ENHANCED DEBUGGING LOGS ---
236
  print("\n--- check_send_button_ready START ---")
@@ -240,6 +241,8 @@ def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAu
240
  api_key_display = gemini_key[:5] if isinstance(gemini_key, str) and gemini_key else ('Empty String' if isinstance(gemini_key, str) and gemini_key == "" else 'None')
241
  print(f" Received gemini_key: Value starts with '{api_key_display}'")
242
  print(f" Received gemini_model: {gemini_model}")
 
 
243
  # --- END ENHANCED DEBUGGING LOGS ---
244
 
245
  is_logged_in = hf_profile is not None and hf_token is not None
@@ -252,6 +255,16 @@ def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAu
252
 
253
  return gr.update(interactive=is_ready)
254
 
 
 
 
 
 
 
 
 
 
 
255
 
256
  # This is the main generator function for the workflow, triggered by the 'Send' button
257
  # NOTE: This function MUST accept ALL state variables as inputs that it might need to modify or pass through.
@@ -278,7 +291,7 @@ def ai_workflow_chat(
278
  repo_name_state: str | None,
279
  generated_code_state: str | None,
280
  use_grounding_state: bool, # Value from use_grounding_checkbox
281
- # Absorb potential extra args passed by Gradio event listeners
282
  *args,
283
  **kwargs
284
  ) -> tuple[
@@ -979,59 +992,54 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
979
 
980
  # Trigger check_send_button_ready whenever any prerequisite state changes
981
  # Bind the check function directly. The inputs list passes the required state values.
 
982
  hf_profile.change(
983
- check_send_button_ready, # Call the core check function directly
984
- inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
985
- outputs=send_button_update_output, # Update only the send button
986
  )
987
  hf_token.change(
988
- check_send_button_ready, # Call the core check function directly
989
- inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
990
- outputs=send_button_update_output, # Update only the send button
991
- )
992
- # gemini_input.change updates gemini_api_key_state, which triggers gemini_api_key_state.change
993
- gemini_api_key_state.change(
994
- check_send_button_ready, # Call the core check function directly
995
- inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
996
- outputs=send_button_update_output, # Update only the send button
997
- )
998
- # model_selector.change updates gemini_model_state, which triggers gemini_model_state.change
999
- gemini_model_state.change(
1000
- check_send_button_ready, # Call the core check function directly
1001
- inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
1002
- outputs=send_button_update_output, # Update only the send button
1003
- )
1004
-
1005
-
1006
- # Handle login button click: Update profile/token state -> Their .change handlers trigger check_send_button_ready
1007
- login_btn.click(
1008
- lambda x: (x[0], x[1]), # Lambda takes the LoginButton output (profile, token tuple) and returns it
1009
- inputs=[login_btn],
1010
- outputs=[hf_profile, hf_token] # Update state variables
1011
  )
1012
-
1013
- # Handle Gemini Key Input change: Update key state -> Configure Gemini status -> State .change handler triggers check_send_button_ready
 
 
1014
  gemini_input.change(
1015
- lambda k: k, # Lambda takes the textbox value and returns it
1016
  inputs=[gemini_input],
1017
- outputs=[gemini_api_key_state] # Update state variable
1018
  ).then(
1019
- # Configure Gemini using the updated state variables
1020
- configure_gemini,
1021
- inputs=[gemini_api_key_state, gemini_model_state],
1022
  outputs=[gemini_status] # Update Gemini status display
 
 
 
 
 
 
1023
  )
1024
 
1025
- # Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> State .change handler triggers check_send_button_ready
1026
  model_selector.change(
1027
- lambda m: m, # Lambda takes the radio value and returns it
1028
  inputs=[model_selector],
1029
- outputs=[gemini_model_state] # Update state variable
1030
  ).then(
1031
- # Configure Gemini using the updated state variables
1032
- configure_gemini,
1033
- inputs=[gemini_api_key_state, gemini_model_state],
1034
  outputs=[gemini_status] # Update Gemini status display
 
 
 
 
 
 
1035
  )
1036
 
1037
 
@@ -1049,18 +1057,14 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1049
  workflow.change(lambda s: s, inputs=workflow, outputs=status_text)
1050
 
1051
  # Link Repo ID State variable change to UI status display
1052
- # This binding seems correct and should update the Textbox with the value of repo_id state.
1053
- # The API key appearing here means the API key value is somehow ending up *in* the repo_id state.
1054
- repo_id.change(lambda r: r if r else "None", inputs=repo_id, outputs=repo_id_text)
1055
 
1056
 
1057
- # The main event handler for the Send button
1058
- # This .click() event triggers the ai_workflow_chat generator function
1059
- # Inputs are read from UI components AND State variables
1060
- # Outputs are updated by the values yielded from the generator
1061
- # Ensure inputs and outputs match the ai_workflow_chat signature and yield tuple EXACTLY.
1062
  send_btn.click(
1063
- ai_workflow_chat, # The generator function to run
1064
  inputs=[
1065
  user_input, chatbot, # UI component inputs (message, current chat history)
1066
  hf_profile, hf_token, # HF State variables
@@ -1090,24 +1094,26 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1090
  # This chain runs once when the app loads
1091
  ai_builder_tab.load(
1092
  # Action 1: Show profile (loads cached login if available)
1093
- show_profile,
1094
  inputs=None,
1095
- outputs=login_status # Updates UI
1096
  ).then(
1097
- # Action 2: Configure Gemini using initial state (gemini_api_key_state is "", model_state is default)
1098
- configure_gemini,
1099
- inputs=[gemini_api_key_state, gemini_model_state],
1100
- outputs=[gemini_status] # Update Gemini status display
 
1101
  ).then(
1102
  # Action 3: After initial load checks, update the button state based on initial states
1103
- # Call check_send_button_ready directly on load with initial state values
1104
  check_send_button_ready,
1105
  inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
1106
- outputs=send_button_update_output, # Update the send button
1107
  ).then(
1108
  # Action 4: Add the initial welcome message to the chat history
1109
- greet,
1110
- inputs=None,
 
1111
  outputs=chatbot # Updates the chatbot display
1112
  )
1113
 
 
230
 
231
  # Helper function to update send button interactivity based on prereqs
232
  # Now takes explicit arguments, intended to be called with all necessary states.
233
+ # Modified to accept extra positional and keyword arguments passed by Gradio event chains
234
+ def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAuthToken | None, gemini_key: str | None, gemini_model: str | None, *args, **kwargs) -> gr.update:
235
  """Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
236
  # --- START ENHANCED DEBUGGING LOGS ---
237
  print("\n--- check_send_button_ready START ---")
 
241
  api_key_display = gemini_key[:5] if isinstance(gemini_key, str) and gemini_key else ('Empty String' if isinstance(gemini_key, str) and gemini_key == "" else 'None')
242
  print(f" Received gemini_key: Value starts with '{api_key_display}'")
243
  print(f" Received gemini_model: {gemini_model}")
244
+ print(f" Received extra args: {args}") # Added debug for extra args
245
+ print(f" Received extra kwargs: {kwargs}") # Added debug for extra kwargs
246
  # --- END ENHANCED DEBUGGING LOGS ---
247
 
248
  is_logged_in = hf_profile is not None and hf_token is not None
 
255
 
256
  return gr.update(interactive=is_ready)
257
 
258
+ # Wrapper function for configure_gemini when called in a .then() chain
259
+ # It accepts the output of the previous function as the first arg and discards it.
260
+ def wrapper_configure_gemini(prev_output, api_key: str | None, model_name: str | None) -> str:
261
+ return configure_gemini(api_key, model_name)
262
+
263
+ # Wrapper function for greet when called in a .then() chain
264
+ # It accepts the output of the previous function as the first arg and discards it.
265
+ def wrapper_greet(prev_output):
266
+ return greet()
267
+
268
 
269
  # This is the main generator function for the workflow, triggered by the 'Send' button
270
  # NOTE: This function MUST accept ALL state variables as inputs that it might need to modify or pass through.
 
291
  repo_name_state: str | None,
292
  generated_code_state: str | None,
293
  use_grounding_state: bool, # Value from use_grounding_checkbox
294
+ # Absorb potential extra args passed by Gradio event listeners (important for generators)
295
  *args,
296
  **kwargs
297
  ) -> tuple[
 
992
 
993
  # Trigger check_send_button_ready whenever any prerequisite state changes
994
  # Bind the check function directly. The inputs list passes the required state values.
995
+ # The check_send_button_ready function signature now handles the implicit first argument.
996
  hf_profile.change(
997
+ check_send_button_ready,
998
+ inputs=send_button_interactive_binding_inputs,
999
+ outputs=send_button_update_output,
1000
  )
1001
  hf_token.change(
1002
+ check_send_button_ready,
1003
+ inputs=send_button_interactive_binding_inputs,
1004
+ outputs=send_button_update_output,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1005
  )
1006
+ # gemini_input.change updates gemini_api_key_state (in the first lambda).
1007
+ # The .then() chain attached to gemini_input.change will then trigger.
1008
+ # The function in the first .then() will receive the *output* of the previous lambda + its inputs.
1009
+ # This requires the wrapper for configure_gemini.
1010
  gemini_input.change(
1011
+ lambda k: k, # Updates gemini_api_key_state
1012
  inputs=[gemini_input],
1013
+ outputs=[gemini_api_key_state] # This output becomes the implicit first arg for the .then() chain
1014
  ).then(
1015
+ # Wrap configure_gemini because it's in a .then() chain and receives the output of the prior step
1016
+ wrapper_configure_gemini, # Use the wrapper
1017
+ inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1018
  outputs=[gemini_status] # Update Gemini status display
1019
+ ).then(
1020
+ # Trigger check_send_button_ready after status update
1021
+ # check_send_button_ready signature now handles the implicit previous output + explicit inputs
1022
+ check_send_button_ready,
1023
+ inputs=send_button_interactive_binding_inputs,
1024
+ outputs=send_button_update_output
1025
  )
1026
 
1027
+ # Handle Gemini Model Selector change: Update model state -> Configure Gemini status -> Update send button state
1028
  model_selector.change(
1029
+ lambda m: m, # Updates gemini_model_state
1030
  inputs=[model_selector],
1031
+ outputs=[gemini_model_state] # This output becomes the implicit first arg for the .then() chain
1032
  ).then(
1033
+ # Wrap configure_gemini because it's in a .then() chain
1034
+ wrapper_configure_gemini, # Use the wrapper
1035
+ inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1036
  outputs=[gemini_status] # Update Gemini status display
1037
+ ).then(
1038
+ # Trigger check_send_button_ready after status update
1039
+ # check_send_button_ready signature now handles the implicit previous output + explicit inputs
1040
+ check_send_button_ready,
1041
+ inputs=send_button_interactive_binding_inputs,
1042
+ outputs=send_button_update_output
1043
  )
1044
 
1045
 
 
1057
  workflow.change(lambda s: s, inputs=workflow, outputs=status_text)
1058
 
1059
  # Link Repo ID State variable change to UI status display
1060
+ # Fix: The lambda here only needs the implicit new value of repo_id, remove inputs=[repo_id]
1061
+ repo_id.change(lambda r: r if r else "None", inputs=None, outputs=repo_id_text)
 
1062
 
1063
 
1064
+ # The main event handler for the Send button (generator)
1065
+ # This call is direct, not in a .then() chain, so no implicit previous output is passed
 
 
 
1066
  send_btn.click(
1067
+ ai_workflow_chat, # The generator function to run (signature now handles potential args)
1068
  inputs=[
1069
  user_input, chatbot, # UI component inputs (message, current chat history)
1070
  hf_profile, hf_token, # HF State variables
 
1094
  # This chain runs once when the app loads
1095
  ai_builder_tab.load(
1096
  # Action 1: Show profile (loads cached login if available)
1097
+ show_profile, # Called directly by load, expects one arg (profile), should handle None initially
1098
  inputs=None,
1099
+ outputs=login_status # Updates UI. This output becomes the implicit first arg for the next .then()
1100
  ).then(
1101
+ # Action 2: Configure Gemini using initial state
1102
+ # Wrap configure_gemini because it's in a .then() chain and receives the output of the prior step (show_profile)
1103
+ wrapper_configure_gemini, # Use the wrapper
1104
+ inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1105
+ outputs=[gemini_status] # Update Gemini status display. This output becomes the implicit first arg for the next .then()
1106
  ).then(
1107
  # Action 3: After initial load checks, update the button state based on initial states
1108
+ # check_send_button_ready signature now handles the implicit previous output + explicit inputs
1109
  check_send_button_ready,
1110
  inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
1111
+ outputs=send_button_update_output, # Update the send button. This output becomes implicit first arg for next .then()
1112
  ).then(
1113
  # Action 4: Add the initial welcome message to the chat history
1114
+ # Wrap greet because it's in a .then() chain and receives the output of the prior step (check_send_button_ready)
1115
+ wrapper_greet, # Use the wrapper
1116
+ inputs=None, # Greet takes no explicit inputs
1117
  outputs=chatbot # Updates the chatbot display
1118
  )
1119