VibecoderMcSwaggins commited on
Commit
581f7c0
Β·
unverified Β·
2 Parent(s): bb240a6 47528ca

Merge pull request #120 from The-Obstacle-Is-The-Way/dev

Browse files

fix(gradio): Prevent examples from auto-submitting on click

docs/bugs/ACTIVE_BUGS.md CHANGED
@@ -9,6 +9,29 @@
9
 
10
  ## Currently Active Bugs
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  ### P2 - 7B Model Produces Garbage Streaming Output
13
 
14
  **File:** `docs/bugs/P2_7B_MODEL_GARBAGE_OUTPUT.md`
 
9
 
10
  ## Currently Active Bugs
11
 
12
+ ### P1 - Gradio Example Click Auto-Submits Instead of Loading
13
+
14
+ **File:** `docs/bugs/P1_GRADIO_EXAMPLE_CLICK_AUTO_SUBMIT.md`
15
+ **Status:** OPEN - Simple Fix Available
16
+
17
+ **Problem:** Clicking on example questions immediately starts the research agent instead of loading the text into the input field. This breaks the BYOK (Bring Your Own Key) flow because:
18
+ 1. User clicks example β†’ chat starts with Free Tier
19
+ 2. User then tries to enter API key β†’ already too late
20
+ 3. Session state becomes confused
21
+
22
+ **Root Cause:**
23
+ 1. Missing `run_examples_on_click=False` in ChatInterface
24
+ 2. HuggingFace Spaces defaults `cache_examples=True`, which overrides `run_examples_on_click`
25
+ 3. Examples pass `None` for api_key, overwriting user settings
26
+
27
+ **Fix:** Add two parameters to `gr.ChatInterface()` in `src/app.py`:
28
+ ```python
29
+ cache_examples=False,
30
+ run_examples_on_click=False,
31
+ ```
32
+
33
+ ---
34
+
35
  ### P2 - 7B Model Produces Garbage Streaming Output
36
 
37
  **File:** `docs/bugs/P2_7B_MODEL_GARBAGE_OUTPUT.md`
docs/bugs/P1_GRADIO_EXAMPLE_CLICK_AUTO_SUBMIT.md ADDED
@@ -0,0 +1,273 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # P1: Gradio Example Click Auto-Submits Instead of Loading
2
+
3
+ **Status:** OPEN
4
+ **Priority:** P1 (High - UX breaks BYOK flow)
5
+ **Discovered:** 2025-12-03
6
+ **Component:** `src/app.py` (Gradio UI)
7
+
8
+ ---
9
+
10
+ ## Summary
11
+
12
+ Clicking on example questions in the Gradio ChatInterface immediately starts the research agent instead of just loading the text into the input field. This prevents users from:
13
+ 1. Entering their API key before starting the chat
14
+ 2. Modifying the example query before submission
15
+ 3. Understanding what's happening (chat starts without explicit action)
16
+
17
+ ---
18
+
19
+ ## Reproduction Steps
20
+
21
+ 1. Open DeepBoner Gradio UI
22
+ 2. **Before entering any API key**, click on an example like "What drugs improve female libido post-menopause?"
23
+ 3. Observe: Chat immediately starts with Free Tier
24
+ 4. Try to enter an OpenAI API key in the accordion
25
+ 5. Try to submit a new query
26
+ 6. **Result:** Confusing UX - the chat already ran, state is unclear
27
+
28
+ ### Expected Behavior
29
+
30
+ 1. Click example β†’ text loads into input field
31
+ 2. User can enter API key
32
+ 3. User clicks submit β†’ chat starts with their configured settings
33
+
34
+ ---
35
+
36
+ ## Root Cause Analysis
37
+
38
+ ### Problem 1: Missing `run_examples_on_click=False`
39
+
40
+ Gradio's `ChatInterface` has a parameter `run_examples_on_click` (added in [PR #10109](https://github.com/gradio-app/gradio/pull/10109), December 2024):
41
+
42
+ | Value | Behavior |
43
+ |-------|----------|
44
+ | `True` (default) | Clicking example immediately runs the function |
45
+ | `False` | Clicking example only populates the input field |
46
+
47
+ **Our code** in `src/app.py:279-325` does NOT set this parameter:
48
+
49
+ ```python
50
+ demo = gr.ChatInterface(
51
+ fn=research_agent,
52
+ examples=[...],
53
+ # run_examples_on_click=False ← MISSING!
54
+ )
55
+ ```
56
+
57
+ ### Problem 2: HuggingFace Spaces Default Overrides
58
+
59
+ From [Gradio docs](https://www.gradio.app/docs/gradio/chatinterface):
60
+
61
+ > `cache_examples`: The default option in HuggingFace Spaces is **True**.
62
+ > `run_examples_on_click` has **no effect** if `cache_examples` is True.
63
+
64
+ This means on HuggingFace Spaces:
65
+ - `cache_examples` defaults to `True`
66
+ - Even if we add `run_examples_on_click=False`, it would be **ignored**
67
+ - We MUST explicitly set `cache_examples=False`
68
+
69
+ ### ~~Problem 3: Example Data Overwrites User Settings~~ (CORRECTION: This is Actually Fine)
70
+
71
+ Looking at lines 283-304:
72
+
73
+ ```python
74
+ examples=[
75
+ [
76
+ "What drugs improve female libido post-menopause?",
77
+ "sexual_health",
78
+ None, # ← api_key set to None
79
+ None, # ← api_key_state set to None
80
+ ],
81
+ ...
82
+ ]
83
+ ```
84
+
85
+ **CORRECTION:** Per [Stack Overflow research](https://stackoverflow.com/questions/78584977/how-to-use-additional-inputs-and-examples-at-the-same-time):
86
+
87
+ > "If you set None for some input in all examples then it will not display this column in example and example will not change current value for this input."
88
+
89
+ Since ALL examples have `None` for api_key and api_key_state:
90
+ - Those columns won't display in the examples table
91
+ - **Clicking an example will NOT change the API key textbox**
92
+ - User's API key is PRESERVED!
93
+
94
+ The current example structure is actually **correct**. The only issue is auto-submit.
95
+
96
+ ### Dead Code: api_key_state Never Updated (Non-Blocking)
97
+
98
+ Line 258-259 has a comment suggesting a fix was attempted:
99
+
100
+ ```python
101
+ # BUG FIX: Add gr.State for API key persistence across example clicks
102
+ api_key_state = gr.State("")
103
+ ```
104
+
105
+ This code is **dead** because:
106
+ 1. The `gr.State` is initialized empty (`""`)
107
+ 2. There's NO event handler (`.change()`) to update the state when textbox changes
108
+ 3. The value passed to `research_agent` is always `""`
109
+ 4. In `_validate_inputs`: `(api_key or api_key_state or "")` - the State never contributes
110
+
111
+ **However**, this is NOT blocking the fix. The fix works regardless of this dead code.
112
+ We can clean it up in a separate PR after the fix is verified working.
113
+
114
+ ---
115
+
116
+ ## Architecture Implications
117
+
118
+ ### BYOK Flow Broken
119
+
120
+ The unified architecture (SPEC-16) relies on API key auto-detection:
121
+
122
+ ```text
123
+ User provides key?
124
+ β”œβ”€β”€ YES β†’ OpenAI backend (sk-...) or Anthropic backend (sk-ant-...)
125
+ └── NO β†’ HuggingFace Free Tier
126
+ ```
127
+
128
+ The example click bug forces users into Free Tier even if they intended to use their API key.
129
+
130
+ ### Session State Confusion
131
+
132
+ After an example auto-submits:
133
+ 1. Chat history has content
134
+ 2. User enters API key
135
+ 3. User submits new query
136
+ 4. **Question:** Does the new query use the new key? Is history preserved correctly?
137
+
138
+ This creates ambiguous state that could lead to:
139
+ - Inconsistent backend usage within a session
140
+ - Confusion about which tier was used for which response
141
+
142
+ ---
143
+
144
+ ## Fix Implementation
145
+
146
+ ### Required Changes to `src/app.py`
147
+
148
+ ```python
149
+ demo = gr.ChatInterface(
150
+ fn=research_agent,
151
+ title="πŸ† DeepBoner",
152
+ description=description,
153
+ examples=[...],
154
+ additional_inputs_accordion=additional_inputs_accordion,
155
+ additional_inputs=[...],
156
+ # === FIX: Prevent auto-submit on example click ===
157
+ cache_examples=False, # MUST be False for run_examples_on_click to work
158
+ run_examples_on_click=False, # Load into input, don't auto-run
159
+ )
160
+ ```
161
+
162
+ ### Why This Fix is Safe (No Optional Enhancements Needed)
163
+
164
+ The current example structure with `None` values is **correct**:
165
+ - API key textbox value is PRESERVED when clicking examples
166
+ - Only the message textbox is populated
167
+ - No restructuring of examples needed
168
+
169
+ **The fix is minimal and surgical:**
170
+ ```python
171
+ cache_examples=False,
172
+ run_examples_on_click=False,
173
+ ```
174
+
175
+ No other changes required.
176
+
177
+ ---
178
+
179
+ ## Testing
180
+
181
+ ### Manual Test Cases
182
+
183
+ 1. **Fresh load, click example:** Should only populate input, not start chat
184
+ 2. **Enter API key, click example:** Query loads, API key preserved
185
+ 3. **Click example, enter key, submit:** Should use the entered key
186
+ 4. **Multiple example clicks:** Each should just replace input text
187
+
188
+ ### Automated Test (if possible)
189
+
190
+ ```python
191
+ def test_example_click_does_not_auto_submit():
192
+ """Verify examples only populate input, not trigger function."""
193
+ # Would need Gradio testing utilities
194
+ pass
195
+ ```
196
+
197
+ ---
198
+
199
+ ## Related Issues
200
+
201
+ - [Gradio #10103](https://github.com/gradio-app/gradio/issues/10103): Original feature request for `run_examples_on_click`
202
+ - [Gradio #10109](https://github.com/gradio-app/gradio/pull/10109): PR that implemented the parameter
203
+ - SPEC-16: Unified Chat Client Architecture (relies on proper API key handling)
204
+ - P2_ARCHITECTURAL_BYOK_GAPS.md (archived) - Related BYOK issues now fixed
205
+
206
+ ---
207
+
208
+ ## Priority Justification
209
+
210
+ **P1 (High)** because:
211
+ 1. Breaks the BYOK (Bring Your Own Key) user flow
212
+ 2. Forces users into Free Tier unexpectedly
213
+ 3. Creates confusing UX that may prevent demo adoption
214
+ 4. Simple fix with clear solution path
215
+
216
+ ---
217
+
218
+ ## Files Affected
219
+
220
+ - `src/app.py:279-325` - ChatInterface configuration
221
+
222
+ ---
223
+
224
+ ## Senior Review: Risk Assessment
225
+
226
+ **Reviewed:** 2025-12-03
227
+
228
+ ### Verification Performed
229
+
230
+ 1. **Gradio Version Confirmed:** 6.0.1 (`uv pip show gradio`)
231
+ 2. **Parameters Exist:** Both `run_examples_on_click` and `cache_examples` verified in `ChatInterface.__init__` signature
232
+ 3. **No Hidden Gradio Usage:** Only `src/app.py` imports gradio (grep confirmed)
233
+ 4. **No Event Handlers:** No `.change()`, `.click()`, `.submit()` events in app.py that could conflict
234
+ 5. **Example Format Correct:** List-of-lists format matches `additional_inputs` order
235
+
236
+ ### Potential Regressions Checked
237
+
238
+ | Risk | Assessment | Mitigation |
239
+ |------|------------|------------|
240
+ | Cold start slower on HF Spaces | Low - examples aren't pre-cached, but they also don't run on click | None needed - acceptable tradeoff |
241
+ | Progress bar issues | None - `gr.Progress()` issues only affect cached examples, we're disabling caching | N/A |
242
+ | Example display changes | None - examples already appear below chatbot due to `additional_inputs` | N/A |
243
+ | API key cleared on example click | **Verified SAFE** - `None` in all examples means input is preserved | N/A |
244
+ | Dead State code causes issues | No - it's inert, just passes `""` always | Clean up in follow-up PR |
245
+
246
+ ### Gotchas Investigated
247
+
248
+ 1. **ViewFrame/hydration issues:** `ssr_mode=False` already set at line 339 - no conflict
249
+ 2. **MCP server interaction:** MCP server (`mcp_server=True`) operates independently of examples - no conflict
250
+ 3. **CSS injection:** Custom CSS only affects `.api-key-input` class - no conflict
251
+ 4. **Accordion state:** `additional_inputs_accordion` unaffected by example behavior
252
+
253
+ ### Confidence Level
254
+
255
+ **HIGH** - This is a two-line, surgical fix that:
256
+ - Uses documented, stable Gradio 6.0 parameters
257
+ - Has no side effects on other components
258
+ - Preserves existing example structure
259
+ - Was explicitly designed for this use case (PR #10109)
260
+
261
+ ### Recommended Approach
262
+
263
+ 1. **Phase 1:** Add the two params, test manually on HF Spaces
264
+ 2. **Phase 2:** (Optional) Clean up dead `api_key_state` code in follow-up PR
265
+
266
+ ---
267
+
268
+ ## References
269
+
270
+ - [Gradio ChatInterface Docs](https://www.gradio.app/docs/gradio/chatinterface)
271
+ - [Gradio Examples Behavior](https://www.gradio.app/guides/chatinterface-examples)
272
+ - [PR #10109: run_examples_on_click](https://github.com/gradio-app/gradio/pull/10109)
273
+ - [Stack Overflow: None values in examples](https://stackoverflow.com/questions/78584977/how-to-use-additional-inputs-and-examples-at-the-same-time)
src/app.py CHANGED
@@ -283,6 +283,7 @@ def create_demo() -> tuple[gr.ChatInterface, gr.Accordion]:
283
  examples=[
284
  # SPEC-16: Mode is always "advanced" (unified architecture)
285
  # Examples now only need: [question, domain, api_key, api_key_state]
 
286
  [
287
  "What drugs improve female libido post-menopause?",
288
  "sexual_health",
@@ -302,6 +303,10 @@ def create_demo() -> tuple[gr.ChatInterface, gr.Accordion]:
302
  None,
303
  ],
304
  ],
 
 
 
 
305
  additional_inputs_accordion=additional_inputs_accordion,
306
  additional_inputs=[
307
  # SPEC-16: Mode toggle removed - everyone gets Advanced Mode
 
283
  examples=[
284
  # SPEC-16: Mode is always "advanced" (unified architecture)
285
  # Examples now only need: [question, domain, api_key, api_key_state]
286
+ # NOTE: None values preserve user's current input (not overwritten)
287
  [
288
  "What drugs improve female libido post-menopause?",
289
  "sexual_health",
 
303
  None,
304
  ],
305
  ],
306
+ # FIX: Prevent examples from auto-submitting (P1_GRADIO_EXAMPLE_CLICK_AUTO_SUBMIT)
307
+ # cache_examples must be False for run_examples_on_click to take effect on HF Spaces
308
+ cache_examples=False,
309
+ run_examples_on_click=False,
310
  additional_inputs_accordion=additional_inputs_accordion,
311
  additional_inputs=[
312
  # SPEC-16: Mode toggle removed - everyone gets Advanced Mode