wuhp commited on
Commit
bca1246
·
verified ·
1 Parent(s): ce8cbe4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +63 -114
app.py CHANGED
@@ -256,7 +256,7 @@ def greet():
256
  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."}]
257
 
258
  # Helper function to update send button interactivity based on prereqs
259
- # This function has the clean signature it expects. Wrappers handle Gradio's argument passing.
260
  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:
261
  """Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
262
  # --- START ENHANCED DEBUGGING LOGS ---
@@ -279,84 +279,6 @@ def check_send_button_ready(hf_profile: gr.OAuthProfile | None, hf_token: gr.OAu
279
 
280
  return gr.update(interactive=is_ready)
281
 
282
- # --- Wrappers to handle Gradio's argument passing in event chains ---
283
- # These wrappers accept whatever Gradio passes (*args, **kwargs) and call the target function
284
- # with the specific arguments it expects, extracted from *args based on the expected call signature.
285
-
286
- # Wrapper for functions called in .then() chains with specific inputs list: expects (prev_output, *input_values)
287
- # e.g., .then(wrapper, inputs=[s1, s2]) -> wrapper receives (prev_out, s1_val, s2_val)
288
- def wrapper_from_then_inputs(func, num_inputs):
289
- def wrapped(*args, **kwargs):
290
- # We expect num_inputs values at the end of *args, after prev_output (index 0)
291
- if len(args) > num_inputs:
292
- required_args = args[-num_inputs:]
293
- try:
294
- return func(*required_args)
295
- except Exception as e:
296
- print(f"Error calling wrapped function {func.__name__} with args {required_args}: {e}")
297
- # Provide a fallback or re-raise depending on context
298
- if func == configure_gemini: return f"❌ Error configuring Gemini: {e}"
299
- if func == get_model_description: return f"Error getting description: {e}"
300
- if func == check_send_button_ready: return gr.update(interactive=False)
301
- raise # Re-raise if no specific fallback
302
- else:
303
- print(f"Warning: wrapper_from_then_inputs for {func.__name__} received unexpected args (expecting at least {num_inputs+1}): {args}")
304
- # Provide a fallback or re-raise
305
- if func == configure_gemini: return "❌ Error configuring Gemini: unexpected arguments received."
306
- if func == get_model_description: return "No description available (unexpected arguments received)."
307
- if func == check_send_button_ready: return gr.update(interactive=False)
308
- raise ValueError(f"Unexpected args received for {func.__name__}: {args}")
309
- return wrapped
310
-
311
- # Wrapper for functions called by .change() trigger with specific inputs list: expects (changed_value, *input_values)
312
- # e.g., component.change(wrapper, inputs=[s1, s2]) -> wrapper receives (changed_val, s1_val, s2_val)
313
- def wrapper_from_change_inputs(func, num_inputs):
314
- def wrapped(*args, **kwargs):
315
- # We expect num_inputs values at the end of *args, after the changed_value (index 0)
316
- if len(args) > num_inputs:
317
- required_args = args[-num_inputs:]
318
- try:
319
- return func(*required_args)
320
- except Exception as e:
321
- print(f"Error calling wrapped function {func.__name__} with args {required_args}: {e}")
322
- if func == check_send_button_ready: return gr.update(interactive=False)
323
- raise # Re-raise if no specific fallback
324
- else:
325
- print(f"Warning: wrapper_from_change_inputs for {func.__name__} received unexpected args (expecting at least {num_inputs+1}): {args}")
326
- if func == check_send_button_ready: return gr.update(interactive=False)
327
- raise ValueError(f"Unexpected args received for {func.__name__}: {args}")
328
- return wrapped
329
-
330
-
331
- # Wrapper for functions called in .then() chains with inputs=None: expects (prev_output,)
332
- # e.g., .then(wrapper, inputs=None) -> wrapper receives (prev_out,)
333
- def wrapper_from_prev_output(func):
334
- def wrapped(*args, **kwargs):
335
- # We expect only prev_output, or sometimes nothing if the chain starts
336
- if len(args) >= 0: # Just accept anything here
337
- try:
338
- # The target function expects 0 args, so call it with no args
339
- return func()
340
- except Exception as e:
341
- print(f"Error calling wrapped function {func.__name__} with args {args}: {e}")
342
- # Provide a fallback or re-raise
343
- if func == greet: return [{"role": "assistant", "content": f"❌ Error loading initial message: {e}"}]
344
- raise # Re-raise if no specific fallback
345
- else:
346
- print(f"Warning: wrapper_from_prev_output for {func.__name__} received unexpected args: {args}")
347
- if func == greet: return [{"role": "assistant", "content": "❌ Error loading initial message: unexpected arguments received."}]
348
- raise ValueError(f"Unexpected args received for {func.__name__}: {args}")
349
- return wrapped
350
-
351
- # Instantiate specific wrappers using the generic ones
352
- wrapper_check_button_change = wrapper_from_change_inputs(check_send_button_ready, 4) # Expects (changed, s1, s2, s3, s4)
353
- wrapper_check_button_then = wrapper_from_then_inputs(check_send_button_ready, 4) # Expects (prev_out, s1, s2, s3, s4)
354
-
355
- wrapper_configure_gemini_then = wrapper_from_then_inputs(configure_gemini, 2) # Expects (prev_out, s1, s2) -> api_key, model_name
356
- wrapper_get_model_description_then = wrapper_from_then_inputs(get_model_description, 1) # Expects (prev_out, s1) -> model_name
357
-
358
- wrapper_greet_then = wrapper_from_prev_output(greet) # Expects (prev_out,), needs 0 args
359
-
360
 
361
  # This is the main generator function for the workflow, triggered by the 'Send' button
362
  # Inputs and Outputs list must match exactly. The generator receives values from the inputs list.
@@ -380,9 +302,9 @@ def ai_workflow_chat(
380
  repo_name_state: str | None,
381
  generated_code_state: str | None,
382
  use_grounding_state: bool, # Value from use_grounding_checkbox
383
- # Absorb potential extra args passed by Gradio event listeners (important for generators)
384
- *args, # Generators might receive extra args, need to accept them but don't need to yield unless they are state
385
- **kwargs # Generators might receive extra kwargs
386
  ) -> tuple[
387
  list[dict], # 0: Updated chat history (for chatbot)
388
  str | None, # 1: Updated repo_id (for repo_id state)
@@ -918,6 +840,9 @@ Return **only** the python code block for app.py. Do not include any extra text,
918
  attempts, app_desc, repo_name, generated_code, use_grounding,
919
  current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
920
 
 
 
 
921
  except Exception as e:
922
  history = add_bot_message(history, f"❌ Error generating debug code: {e}. Click 'reset'.")
923
  # Yield error message and reset state on failure
@@ -1079,28 +1004,39 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1079
  # Define the output for updating the send button interactivity
1080
  send_button_update_output = [send_btn]
1081
 
 
 
 
 
 
 
 
 
1082
 
1083
  # Trigger check_send_button_ready whenever any prerequisite state changes
1084
- # Use the specific change wrapper which expects (changed_value, *input_values)
1085
  hf_profile.change(
1086
- wrapper_check_button_change,
1087
  inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
1088
  outputs=send_button_update_output, # Update only the send button
1089
  )
1090
  hf_token.change(
1091
- wrapper_check_button_change,
1092
  inputs=send_button_interactive_binding_inputs,
1093
  outputs=send_button_update_output,
1094
  )
1095
  # When gemini_api_key_state changes (updated by gemini_input.change), check button readiness
 
 
1096
  gemini_api_key_state.change(
1097
- wrapper_check_button_change,
1098
  inputs=send_button_interactive_binding_inputs,
1099
  outputs=send_button_update_output,
1100
  )
1101
  # When gemini_model_state changes (updated by model_selector.change), check button readiness
 
1102
  gemini_model_state.change(
1103
- wrapper_check_button_change,
1104
  inputs=send_button_interactive_binding_inputs,
1105
  outputs=send_button_update_output,
1106
  )
@@ -1108,12 +1044,13 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1108
 
1109
  # Handle login button click: Update profile/token state -> Their .change handlers trigger check_send_button_ready
1110
  login_btn.click(
1111
- lambda x: (x[0], x[1]), # Lambda takes the LoginButton output (profile, token tuple) and returns it
1112
- inputs=[login_btn], # Pass the LoginButton itself to get its output
 
1113
  outputs=[hf_profile, hf_token] # Update state variables
1114
  )
1115
 
1116
- # Handle Gemini Key Input change: Update key state -> Configure Gemini status -> Update send button state
1117
  gemini_input.change(
1118
  # Lambda receives the new value of gemini_input (1 arg) because inputs=None (implied)
1119
  lambda new_key_value: new_key_value,
@@ -1121,14 +1058,20 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1121
  outputs=[gemini_api_key_state] # This output becomes the implicit first arg for the next .then() in this chain
1122
  ).then(
1123
  # Configure Gemini using the updated state variables
1124
- # Use the then_inputs wrapper which expects (prev_output, api_key_val, model_name_val)
1125
- wrapper_configure_gemini_then,
 
 
 
 
1126
  inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1127
- outputs=[gemini_status] # Update Gemini status display. This output becomes the implicit first arg for the next .then()
1128
  )
1129
- # The .then chain continues from the outputs of the configure_gemini call, handled by gemini_api_key_state.change handler above
 
 
1130
 
1131
- # Handle Gemini Model Selector change: Update model state -> Update description -> Configure Gemini status -> Update send button state
1132
  model_selector.change(
1133
  # Lambda receives the new value of model_selector (1 arg)
1134
  lambda new_model_name: new_model_name,
@@ -1136,16 +1079,19 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1136
  outputs=[gemini_model_state] # This output becomes the implicit first arg for the next .then()
1137
  ).then(
1138
  # Update the model description display
1139
- # Use the then_inputs wrapper which expects (prev_output, model_name_val)
1140
- wrapper_get_model_description_then,
 
 
1141
  inputs=[gemini_model_state], # Get the new state value
1142
- outputs=[model_description_text] # Update description UI. This output becomes implicit first arg for next .then()
1143
  ).then(
1144
  # Configure Gemini using the updated state variables
1145
- # Use the then_inputs wrapper which expects (prev_output, api_key_val, model_name_val)
1146
- wrapper_configure_gemini_then,
 
1147
  inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1148
- outputs=[gemini_status] # Update Gemini status display. This output becomes the implicit first arg for the next .then()
1149
  )
1150
  # The .then chain continues from the outputs of the configure_gemini call, handled by gemini_model_state.change handler above
1151
 
@@ -1166,7 +1112,6 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1166
 
1167
  # Link Repo ID State variable change to UI status display
1168
  # Lambda receives the new state value (1 arg) because inputs=None
1169
- # The warning about receiving 0 args persists, likely ignorable for this lambda
1170
  repo_id.change(lambda new_repo_id_value: new_repo_id_value if new_repo_id_value else "None", inputs=None, outputs=repo_id_text)
1171
 
1172
 
@@ -1178,7 +1123,7 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1178
  # This call is direct, not in a .then() chain, so it does NOT receive a prev_output arg.
1179
  # It receives args only from the inputs list.
1180
  send_btn.click(
1181
- ai_workflow_chat, # The generator function to run (signature handles potential extra args, just in case)
1182
  inputs=[
1183
  user_input, chatbot, # UI component inputs (message, current chat history)
1184
  hf_profile, hf_token, # HF State variables
@@ -1208,32 +1153,36 @@ with gr.Blocks(title="AI-Powered HF Space App Builder") as ai_builder_tab:
1208
  # This chain runs once when the app loads
1209
  ai_builder_tab.load(
1210
  # Action 1: Show profile (loads cached login if available)
1211
- # show_profile expects 1 arg (profile) or None. It receives 1 from load. Correct.
1212
- show_profile,
1213
- inputs=None,
 
 
 
 
1214
  outputs=login_status # Updates UI. This output becomes the implicit first arg for the next .then()
1215
  ).then(
1216
  # Action 2: Configure Gemini using initial state
1217
- # Use the then_inputs wrapper which expects (prev_output, api_key_val, model_name_val)
1218
- wrapper_configure_gemini_then,
1219
  inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1220
  outputs=[gemini_status] # Update Gemini status display. This output becomes the implicit first arg for the next .then()
1221
  ).then(
1222
  # Action 3: After initial load checks, update the button state based on initial states
1223
- # Use the then_inputs wrapper which expects (prev_output, *prereq_state_values)
1224
- wrapper_check_button_then,
1225
  inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
1226
  outputs=send_button_update_output, # Update the send button. This output becomes implicit first arg for next .then()
1227
  ).then(
1228
  # Action 4: Update the model description text based on the default selected model
1229
- # Use the then_inputs wrapper which expects (prev_output, model_name_val)
1230
- wrapper_get_model_description_then,
1231
  inputs=[gemini_model_state], # Get the default model name from state
1232
  outputs=[model_description_text] # Update description UI. This output becomes implicit first arg for next .then()
1233
  ).then(
1234
  # Action 5: Add the initial welcome message to the chat history
1235
- # Use the prev_output wrapper which expects (prev_output,)
1236
- wrapper_greet_then,
1237
  inputs=None, # Greet takes no explicit inputs
1238
  outputs=chatbot # Updates the chatbot display
1239
  )
 
256
  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."}]
257
 
258
  # Helper function to update send button interactivity based on prereqs
259
+ # This function has the clean signature it expects. Lambdas handle Gradio's argument passing.
260
  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:
261
  """Checks if HF login and Gemini configuration are complete and returns update for button interactivity."""
262
  # --- START ENHANCED DEBUGGING LOGS ---
 
279
 
280
  return gr.update(interactive=is_ready)
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
 
283
  # This is the main generator function for the workflow, triggered by the 'Send' button
284
  # Inputs and Outputs list must match exactly. The generator receives values from the inputs list.
 
302
  repo_name_state: str | None,
303
  generated_code_state: str | None,
304
  use_grounding_state: bool, # Value from use_grounding_checkbox
305
+ # Accept any extra args/kwargs passed by Gradio, common for generators
306
+ *args,
307
+ **kwargs
308
  ) -> tuple[
309
  list[dict], # 0: Updated chat history (for chatbot)
310
  str | None, # 1: Updated repo_id (for repo_id state)
 
840
  attempts, app_desc, repo_name, generated_code, use_grounding,
841
  current_gemini_key, current_gemini_model) # Correctly yielding back the received Gemini states
842
 
843
+ # After uploading a fix, we usually go back to checking logs
844
+ state = STATE_CHECKING_LOGS_RUN # Correct transition after upload fix
845
+
846
  except Exception as e:
847
  history = add_bot_message(history, f"❌ Error generating debug code: {e}. Click 'reset'.")
848
  # Yield error message and reset state on failure
 
1004
  # Define the output for updating the send button interactivity
1005
  send_button_update_output = [send_btn]
1006
 
1007
+ # Lambda to pass only the required 4 state inputs to check_send_button_ready,
1008
+ # ignoring the first argument (the changed value) passed by state.change
1009
+ lambda_check_button_from_state_change = lambda changed_value, s1, s2, s3, s4: check_send_button_ready(s1, s2, s3, s4)
1010
+
1011
+ # Lambda to pass only the required 4 state inputs to check_send_button_ready,
1012
+ # ignoring the previous step's output passed by .then
1013
+ lambda_check_button_from_then = lambda prev_output, s1, s2, s3, s4: check_send_button_ready(s1, s2, s3, s4)
1014
+
1015
 
1016
  # Trigger check_send_button_ready whenever any prerequisite state changes
1017
+ # Use the specific lambda which expects (changed_value, *input_values)
1018
  hf_profile.change(
1019
+ lambda_check_button_from_state_change,
1020
  inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
1021
  outputs=send_button_update_output, # Update only the send button
1022
  )
1023
  hf_token.change(
1024
+ lambda_check_button_from_state_change,
1025
  inputs=send_button_interactive_binding_inputs,
1026
  outputs=send_button_update_output,
1027
  )
1028
  # When gemini_api_key_state changes (updated by gemini_input.change), check button readiness
1029
+ # The .then() chain attached to gemini_input.change updates the state *first*, then triggers this change handler.
1030
+ # This change handler receives (new_state_value, *inputs_values).
1031
  gemini_api_key_state.change(
1032
+ lambda_check_button_from_state_change,
1033
  inputs=send_button_interactive_binding_inputs,
1034
  outputs=send_button_update_output,
1035
  )
1036
  # When gemini_model_state changes (updated by model_selector.change), check button readiness
1037
+ # This change handler receives (new_state_value, *inputs_values).
1038
  gemini_model_state.change(
1039
+ lambda_check_button_from_state_change,
1040
  inputs=send_button_interactive_binding_inputs,
1041
  outputs=send_button_update_output,
1042
  )
 
1044
 
1045
  # Handle login button click: Update profile/token state -> Their .change handlers trigger check_send_button_ready
1046
  login_btn.click(
1047
+ # Lambda takes the LoginButton output (profile, token tuple) which is 2 args: (profile, token)
1048
+ lambda profile, token: (profile, token),
1049
+ inputs=[login_btn], # Pass the LoginButton itself to get its output (its output is a tuple of profile, token)
1050
  outputs=[hf_profile, hf_token] # Update state variables
1051
  )
1052
 
1053
+ # Handle Gemini Key Input change: Update key state -> Configure Gemini status
1054
  gemini_input.change(
1055
  # Lambda receives the new value of gemini_input (1 arg) because inputs=None (implied)
1056
  lambda new_key_value: new_key_value,
 
1058
  outputs=[gemini_api_key_state] # This output becomes the implicit first arg for the next .then() in this chain
1059
  ).then(
1060
  # Configure Gemini using the updated state variables
1061
+ # Lambda receives (prev_output, api_key_val, model_name_val) where prev_output is the new key value
1062
+ # It needs to pass api_key_val and model_name_val to configure_gemini.
1063
+ # Note: In this specific chain, prev_output IS the new key value, so we pass args[0] and args[2].
1064
+ # This is fragile! A better approach is to rely *only* on explicit inputs in .then.
1065
+ # Let's use the values from the *states* directly in the .then inputs.
1066
+ lambda prev_output, api_key_val_from_state, model_name_val_from_state: configure_gemini(api_key_val_from_state, model_name_val_from_state),
1067
  inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1068
+ outputs=[gemini_status] # Update Gemini status display.
1069
  )
1070
+ # The .then chain continues from the outputs of the configure_gemini call, but no further .then is attached here.
1071
+ # The gemini_api_key_state.change handler (defined above) will pick up the state change.
1072
+
1073
 
1074
+ # Handle Gemini Model Selector change: Update model state -> Update description -> Configure Gemini status
1075
  model_selector.change(
1076
  # Lambda receives the new value of model_selector (1 arg)
1077
  lambda new_model_name: new_model_name,
 
1079
  outputs=[gemini_model_state] # This output becomes the implicit first arg for the next .then()
1080
  ).then(
1081
  # Update the model description display
1082
+ # Lambda receives (prev_output, model_name_val) where prev_output is the new model name
1083
+ # It needs to pass model_name_val to get_model_description.
1084
+ # Again, fragile. Rely on explicit inputs.
1085
+ lambda prev_output, model_name_val_from_state: get_model_description(model_name_val_from_state),
1086
  inputs=[gemini_model_state], # Get the new state value
1087
+ outputs=[model_description_text] # Update description UI.
1088
  ).then(
1089
  # Configure Gemini using the updated state variables
1090
+ # Lambda receives (prev_output, api_key_val, model_name_val) where prev_output is the description text
1091
+ # It needs to pass api_key_val and model_name_val to configure_gemini.
1092
+ lambda prev_output, api_key_val_from_state, model_name_val_from_state: configure_gemini(api_key_val_from_state, model_name_val_from_state),
1093
  inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1094
+ outputs=[gemini_status] # Update Gemini status display.
1095
  )
1096
  # The .then chain continues from the outputs of the configure_gemini call, handled by gemini_model_state.change handler above
1097
 
 
1112
 
1113
  # Link Repo ID State variable change to UI status display
1114
  # Lambda receives the new state value (1 arg) because inputs=None
 
1115
  repo_id.change(lambda new_repo_id_value: new_repo_id_value if new_repo_id_value else "None", inputs=None, outputs=repo_id_text)
1116
 
1117
 
 
1123
  # This call is direct, not in a .then() chain, so it does NOT receive a prev_output arg.
1124
  # It receives args only from the inputs list.
1125
  send_btn.click(
1126
+ ai_workflow_chat, # The generator function to run
1127
  inputs=[
1128
  user_input, chatbot, # UI component inputs (message, current chat history)
1129
  hf_profile, hf_token, # HF State variables
 
1153
  # This chain runs once when the app loads
1154
  ai_builder_tab.load(
1155
  # Action 1: Show profile (loads cached login if available)
1156
+ # show_profile receives no implicit args from load when inputs=None is used for load itself
1157
+ # (If inputs was not None for load, it would receive those input values first).
1158
+ # Let's use inputs=None for load for simplicity. show_profile expects 1 arg (profile).
1159
+ # How does Gradio handle this for load? The load *function* takes no inputs, but the *event* passes the initial state values.
1160
+ # Let's add a lambda wrapper to be safe.
1161
+ lambda *args: show_profile(args[0] if args else None), # Expects 0 or 1 args, needs 1 for show_profile
1162
+ inputs=[hf_profile], # Pass the initial profile state value
1163
  outputs=login_status # Updates UI. This output becomes the implicit first arg for the next .then()
1164
  ).then(
1165
  # Action 2: Configure Gemini using initial state
1166
+ # Lambda receives (prev_output, api_key_val, model_name_val)
1167
+ lambda prev_output, api_key_val_from_state, model_name_val_from_state: configure_gemini(api_key_val_from_state, model_name_val_from_state),
1168
  inputs=[gemini_api_key_state, gemini_model_state], # Explicitly pass the required states
1169
  outputs=[gemini_status] # Update Gemini status display. This output becomes the implicit first arg for the next .then()
1170
  ).then(
1171
  # Action 3: After initial load checks, update the button state based on initial states
1172
+ # Lambda receives (prev_output, *prereq_state_values)
1173
+ lambda prev_output, s1, s2, s3, s4: check_send_button_ready(s1, s2, s3, s4),
1174
  inputs=send_button_interactive_binding_inputs, # Pass all 4 prerequisite states
1175
  outputs=send_button_update_output, # Update the send button. This output becomes implicit first arg for next .then()
1176
  ).then(
1177
  # Action 4: Update the model description text based on the default selected model
1178
+ # Lambda receives (prev_output, model_name_val)
1179
+ lambda prev_output, model_name_val_from_state: get_model_description(model_name_val_from_state),
1180
  inputs=[gemini_model_state], # Get the default model name from state
1181
  outputs=[model_description_text] # Update description UI. This output becomes implicit first arg for next .then()
1182
  ).then(
1183
  # Action 5: Add the initial welcome message to the chat history
1184
+ # Lambda receives (prev_output)
1185
+ lambda prev_output: greet(),
1186
  inputs=None, # Greet takes no explicit inputs
1187
  outputs=chatbot # Updates the chatbot display
1188
  )