LittleMonkeyLab commited on
Commit
5a15d28
·
verified ·
1 Parent(s): b3f1cdd

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -704
app.py DELETED
@@ -1,704 +0,0 @@
1
- """
2
- Main Gradio application for the AI Trading Experiment.
3
- Combines trading game, chatbot, and experiment tracking.
4
- """
5
-
6
- import gradio as gr
7
- import uuid
8
- import time
9
- import random
10
- from datetime import datetime
11
- from typing import Optional, Tuple, List, Dict, Any
12
-
13
- from config import (
14
- ExperimentConfig, DEFAULT_CONFIG, SCENARIOS,
15
- ParticipantVisibleParams, ResearcherControlledParams,
16
- EXPERIMENT_CONDITIONS, get_condition
17
- )
18
- from trading import TradingEngine, format_currency, format_percentage
19
- from chatbot import TradingChatbot, ChatResponse
20
- from tracking import (
21
- ExperimentTracker, DecisionRecord, ChatInteraction,
22
- tracker
23
- )
24
-
25
-
26
- # Global state management
27
- class SessionState:
28
- """Manages session state for each participant."""
29
- def __init__(self):
30
- self.reset()
31
-
32
- def reset(self):
33
- self.participant_id: Optional[str] = None
34
- self.trading_engine: Optional[TradingEngine] = None
35
- self.chatbot: Optional[TradingChatbot] = None
36
- self.visible_params = ParticipantVisibleParams()
37
- self.hidden_params = ResearcherControlledParams()
38
- self.current_scenario = None
39
- self.scenario_start_time: float = 0
40
- self.ai_advice_shown_time: float = 0
41
- self.proactive_advice_shown: bool = False
42
- self.proactive_advice_engaged: bool = False
43
- self.chat_queries_this_scenario: int = 0
44
- self.pre_advice_confidence: int = 50
45
-
46
-
47
- # Initialize components
48
- session = SessionState()
49
-
50
-
51
- def get_random_condition() -> ResearcherControlledParams:
52
- """Get a random experimental condition for A/B testing."""
53
- condition_names = list(EXPERIMENT_CONDITIONS.keys())
54
- selected = random.choice(condition_names)
55
- return get_condition(selected)
56
-
57
-
58
- def start_experiment(condition_dropdown: str) -> Tuple:
59
- """Initialize a new experiment session."""
60
- session.reset()
61
-
62
- # Set experimental condition
63
- if condition_dropdown == "Random (A/B Testing)":
64
- session.hidden_params = get_random_condition()
65
- else:
66
- session.hidden_params = get_condition(condition_dropdown)
67
-
68
- # Create participant session
69
- session.participant_id = tracker.create_session(
70
- condition_name=session.hidden_params.condition_name,
71
- initial_portfolio=DEFAULT_CONFIG.initial_portfolio_value
72
- )
73
-
74
- # Initialize trading engine
75
- session.trading_engine = TradingEngine(DEFAULT_CONFIG)
76
- portfolio, first_scenario = session.trading_engine.start_new_game()
77
-
78
- # Initialize chatbot
79
- session.chatbot = TradingChatbot()
80
- session.chatbot.clear_history()
81
-
82
- # Set current scenario
83
- session.current_scenario = first_scenario
84
- session.scenario_start_time = time.time()
85
-
86
- # Generate proactive advice (maybe)
87
- proactive_message = ""
88
- session.proactive_advice_shown = False
89
-
90
- proactive_response = session.chatbot.generate_proactive_advice(
91
- first_scenario,
92
- session.visible_params,
93
- session.hidden_params
94
- )
95
-
96
- if proactive_response:
97
- proactive_message = f"**AI Advisor:** {proactive_response.message}"
98
- session.proactive_advice_shown = True
99
- session.ai_advice_shown_time = time.time()
100
-
101
- # Record proactive interaction
102
- tracker.record_chat_interaction(ChatInteraction(
103
- interaction_id=str(uuid.uuid4())[:12],
104
- participant_id=session.participant_id,
105
- timestamp=datetime.now().isoformat(),
106
- scenario_id=first_scenario.scenario_id,
107
- interaction_type="proactive",
108
- user_query=None,
109
- ai_response=proactive_response.message,
110
- explanation_depth=session.visible_params.explanation_depth,
111
- communication_style=session.visible_params.communication_style,
112
- confidence_framing=session.hidden_params.confidence_framing,
113
- risk_bias=session.hidden_params.risk_bias,
114
- response_time_ms=0,
115
- user_engaged=False,
116
- dismissed=False
117
- ))
118
-
119
- # Generate main AI recommendation
120
- ai_recommendation = session.chatbot.generate_ai_recommendation(
121
- first_scenario,
122
- session.visible_params,
123
- session.hidden_params
124
- )
125
-
126
- # Format scenario display
127
- scenario_text = format_scenario_display(first_scenario)
128
- progress = session.trading_engine.get_progress_info()
129
-
130
- return (
131
- gr.update(visible=False), # Hide welcome
132
- gr.update(visible=True), # Show game
133
- gr.update(visible=False), # Hide results
134
- f"Participant: {session.participant_id}",
135
- format_currency(portfolio.total_value),
136
- f"Scenario {progress['current_scenario']} of {progress['total_scenarios']}",
137
- scenario_text,
138
- f"**AI Recommendation:**\n\n{ai_recommendation.message}",
139
- proactive_message,
140
- [], # Clear chat history
141
- gr.update(value=50), # Reset confidence slider
142
- gr.update(value="HOLD"), # Reset decision
143
- )
144
-
145
-
146
- def format_scenario_display(scenario) -> str:
147
- """Format a scenario for display."""
148
- return f"""
149
- ## {scenario.company_name} ({scenario.company_symbol})
150
-
151
- **Sector:** {scenario.sector}
152
- **Country:** {scenario.country}
153
- **Current Price:** {scenario.current_price} credits
154
-
155
- ---
156
-
157
- ### Situation
158
-
159
- {scenario.situation_description}
160
- """
161
-
162
-
163
- def update_ai_params(explanation_depth: int, communication_style: int):
164
- """Update visible AI parameters and regenerate advice."""
165
- session.visible_params.explanation_depth = explanation_depth
166
- session.visible_params.communication_style = communication_style
167
-
168
- if session.current_scenario and session.chatbot:
169
- # Regenerate recommendation with new params
170
- ai_recommendation = session.chatbot.generate_ai_recommendation(
171
- session.current_scenario,
172
- session.visible_params,
173
- session.hidden_params
174
- )
175
- return f"**AI Recommendation:**\n\n{ai_recommendation.message}"
176
-
177
- return ""
178
-
179
-
180
- def handle_chat_query(
181
- message: str,
182
- chat_history: List[Tuple[str, str]]
183
- ) -> Tuple[List[Tuple[str, str]], str]:
184
- """Handle a user query to the chatbot."""
185
- if not message.strip() or not session.chatbot:
186
- return chat_history, ""
187
-
188
- query_start = time.time()
189
-
190
- response = session.chatbot.answer_query(
191
- message,
192
- session.current_scenario,
193
- session.visible_params,
194
- session.hidden_params
195
- )
196
-
197
- response_time_ms = int((time.time() - query_start) * 1000)
198
-
199
- # Record interaction
200
- if session.participant_id:
201
- tracker.record_chat_interaction(ChatInteraction(
202
- interaction_id=str(uuid.uuid4())[:12],
203
- participant_id=session.participant_id,
204
- timestamp=datetime.now().isoformat(),
205
- scenario_id=session.current_scenario.scenario_id if session.current_scenario else None,
206
- interaction_type="reactive_query",
207
- user_query=message,
208
- ai_response=response.message,
209
- explanation_depth=session.visible_params.explanation_depth,
210
- communication_style=session.visible_params.communication_style,
211
- confidence_framing=session.hidden_params.confidence_framing,
212
- risk_bias=session.hidden_params.risk_bias,
213
- response_time_ms=response_time_ms,
214
- user_engaged=True,
215
- dismissed=False
216
- ))
217
-
218
- session.chat_queries_this_scenario += 1
219
-
220
- chat_history.append((message, response.message))
221
- return chat_history, ""
222
-
223
-
224
- def engage_proactive_advice():
225
- """Mark that user engaged with proactive advice."""
226
- session.proactive_advice_engaged = True
227
- return "You engaged with the AI's initial observation."
228
-
229
-
230
- def dismiss_proactive_advice():
231
- """Mark that user dismissed proactive advice."""
232
- session.proactive_advice_engaged = False
233
- return gr.update(visible=False)
234
-
235
-
236
- def submit_decision(
237
- decision: str,
238
- confidence: int,
239
- trade_amount: float
240
- ) -> Tuple:
241
- """Process the participant's trading decision."""
242
- if not session.trading_engine or not session.current_scenario:
243
- return (gr.update(),) * 8
244
-
245
- # Calculate timing
246
- decision_time_ms = int((time.time() - session.scenario_start_time) * 1000)
247
- ai_viewing_time_ms = int((time.time() - session.ai_advice_shown_time) * 1000) if session.ai_advice_shown_time > 0 else 0
248
-
249
- # Process the decision
250
- outcome = session.trading_engine.process_decision(
251
- session.current_scenario,
252
- decision,
253
- trade_amount,
254
- session.current_scenario.ai_recommendation
255
- )
256
-
257
- # Record decision
258
- tracker.record_decision(DecisionRecord(
259
- decision_id=str(uuid.uuid4())[:12],
260
- participant_id=session.participant_id,
261
- timestamp=datetime.now().isoformat(),
262
- scenario_id=session.current_scenario.scenario_id,
263
- company_symbol=session.current_scenario.company_symbol,
264
- explanation_depth=session.visible_params.explanation_depth,
265
- communication_style=session.visible_params.communication_style,
266
- confidence_framing=session.hidden_params.confidence_framing,
267
- risk_bias=session.hidden_params.risk_bias,
268
- ai_recommendation=session.current_scenario.ai_recommendation,
269
- ai_was_correct=session.current_scenario.ai_is_correct,
270
- participant_decision=decision,
271
- followed_ai=outcome.followed_ai,
272
- decision_confidence=confidence,
273
- time_to_decision_ms=decision_time_ms,
274
- time_viewing_ai_advice_ms=ai_viewing_time_ms,
275
- outcome_percentage=outcome.outcome_percentage,
276
- portfolio_before=outcome.portfolio_before,
277
- portfolio_after=outcome.portfolio_after,
278
- trade_amount=trade_amount,
279
- proactive_advice_shown=session.proactive_advice_shown,
280
- proactive_advice_engaged=session.proactive_advice_engaged
281
- ))
282
-
283
- # Record trust metrics
284
- tracker.record_trust_metric(
285
- participant_id=session.participant_id,
286
- scenario_id=session.current_scenario.scenario_id,
287
- pre_confidence=session.pre_advice_confidence,
288
- post_confidence=confidence,
289
- advice_followed=outcome.followed_ai,
290
- time_deliberating_ms=decision_time_ms,
291
- queries_before_decision=session.chat_queries_this_scenario,
292
- outcome_positive=(outcome.outcome_percentage > 0)
293
- )
294
-
295
- # Format outcome message
296
- outcome_color = "green" if outcome.outcome_percentage > 0 else "red"
297
- outcome_message = f"""
298
- ### Decision Outcome
299
-
300
- You chose to **{decision}** with {trade_amount:,.0f} credits.
301
-
302
- **Result:** {format_percentage(outcome.outcome_percentage)} ({format_currency(outcome.outcome_amount)})
303
-
304
- **Portfolio:** {format_currency(outcome.portfolio_after)}
305
- """
306
-
307
- # Check if game is complete
308
- if session.trading_engine.is_game_complete():
309
- return show_results()
310
-
311
- # Move to next scenario
312
- next_scenario = session.trading_engine.get_next_scenario()
313
- session.current_scenario = next_scenario
314
- session.scenario_start_time = time.time()
315
- session.ai_advice_shown_time = 0
316
- session.proactive_advice_shown = False
317
- session.proactive_advice_engaged = False
318
- session.chat_queries_this_scenario = 0
319
- session.chatbot.clear_history()
320
-
321
- # Generate content for next scenario
322
- scenario_text = format_scenario_display(next_scenario)
323
-
324
- # Maybe show proactive advice
325
- proactive_message = ""
326
- proactive_response = session.chatbot.generate_proactive_advice(
327
- next_scenario,
328
- session.visible_params,
329
- session.hidden_params
330
- )
331
-
332
- if proactive_response:
333
- proactive_message = f"**AI Advisor:** {proactive_response.message}"
334
- session.proactive_advice_shown = True
335
- session.ai_advice_shown_time = time.time()
336
-
337
- tracker.record_chat_interaction(ChatInteraction(
338
- interaction_id=str(uuid.uuid4())[:12],
339
- participant_id=session.participant_id,
340
- timestamp=datetime.now().isoformat(),
341
- scenario_id=next_scenario.scenario_id,
342
- interaction_type="proactive",
343
- user_query=None,
344
- ai_response=proactive_response.message,
345
- explanation_depth=session.visible_params.explanation_depth,
346
- communication_style=session.visible_params.communication_style,
347
- confidence_framing=session.hidden_params.confidence_framing,
348
- risk_bias=session.hidden_params.risk_bias,
349
- response_time_ms=0,
350
- user_engaged=False,
351
- dismissed=False
352
- ))
353
-
354
- # Generate main recommendation
355
- ai_recommendation = session.chatbot.generate_ai_recommendation(
356
- next_scenario,
357
- session.visible_params,
358
- session.hidden_params
359
- )
360
- session.ai_advice_shown_time = time.time()
361
-
362
- progress = session.trading_engine.get_progress_info()
363
-
364
- return (
365
- gr.update(visible=True), # Keep game visible
366
- gr.update(visible=False), # Keep results hidden
367
- format_currency(session.trading_engine.portfolio.total_value),
368
- f"Scenario {progress['current_scenario']} of {progress['total_scenarios']}",
369
- scenario_text,
370
- f"**AI Recommendation:**\n\n{ai_recommendation.message}",
371
- proactive_message,
372
- [], # Clear chat
373
- gr.update(value=50),
374
- gr.update(value="HOLD"),
375
- outcome_message
376
- )
377
-
378
-
379
- def show_results() -> Tuple:
380
- """Show the final results screen."""
381
- if not session.trading_engine:
382
- return (gr.update(),) * 11
383
-
384
- # Complete the session
385
- summary = session.trading_engine.get_game_summary()
386
- tracker.complete_session(
387
- session.participant_id,
388
- summary["final_portfolio"]
389
- )
390
-
391
- # Get full session summary
392
- session_summary = tracker.get_session_summary(session.participant_id)
393
-
394
- results_text = f"""
395
- # Experiment Complete
396
-
397
- Thank you for participating!
398
-
399
- ---
400
-
401
- ## Your Results
402
-
403
- **Participant ID:** {session.participant_id}
404
- (Save this ID if you need to reference your data)
405
-
406
- ---
407
-
408
- ### Portfolio Performance
409
-
410
- | Metric | Value |
411
- |--------|-------|
412
- | Starting Portfolio | {format_currency(summary['initial_portfolio'])} |
413
- | Final Portfolio | {format_currency(summary['final_portfolio'])} |
414
- | Total Return | {format_currency(summary['total_return'])} |
415
- | Return Percentage | {summary['return_percentage']:.1f}% |
416
-
417
- ---
418
-
419
- ### Decision Analysis
420
-
421
- | Metric | Value |
422
- |--------|-------|
423
- | Total Decisions | {summary['total_decisions']} |
424
- | AI Follow Rate | {summary['ai_follow_rate']*100:.1f}% |
425
- | Optimal Decision Rate | {summary['optimal_decision_rate']*100:.1f}% |
426
-
427
- ---
428
-
429
- ### AI Interaction Summary
430
-
431
- | Metric | Value |
432
- |--------|-------|
433
- | Times Followed Correct AI | {summary['followed_correct_ai']} / {summary['ai_correct_scenarios']} |
434
- | Times Followed Incorrect AI | {summary['followed_incorrect_ai']} / {summary['ai_incorrect_scenarios']} |
435
- | Chat Queries Made | {session_summary.get('total_chat_queries', 0)} |
436
-
437
- ---
438
-
439
- ### Decision History
440
-
441
- """
442
-
443
- for d in summary['decisions']:
444
- followed = "Followed AI" if d['followed_ai'] else "Disagreed with AI"
445
- optimal = "Optimal" if d['was_optimal'] else "Suboptimal"
446
- results_text += f"- **{d['scenario']}**: {d['decision']} → {d['outcome']} ({followed}, {optimal})\n"
447
-
448
- return (
449
- gr.update(visible=False), # Hide game
450
- gr.update(visible=True), # Show results
451
- results_text,
452
- "", "", "", "", "", [], gr.update(), gr.update(), ""
453
- )
454
-
455
-
456
- # Build the Gradio interface
457
- def create_app():
458
- """Create and return the Gradio application."""
459
-
460
- with gr.Blocks(
461
- title="TradeVerse AI Experiment",
462
- theme=gr.themes.Soft(),
463
- css="""
464
- .container { max-width: 1200px; margin: auto; }
465
- .scenario-box { background: #f8f9fa; padding: 20px; border-radius: 10px; }
466
- .ai-advice { background: #e3f2fd; padding: 15px; border-radius: 8px; border-left: 4px solid #2196f3; }
467
- .proactive-advice { background: #fff3e0; padding: 15px; border-radius: 8px; border-left: 4px solid #ff9800; }
468
- .outcome-box { padding: 15px; border-radius: 8px; margin-top: 10px; }
469
- """
470
- ) as app:
471
-
472
- # ==================== WELCOME SCREEN ====================
473
- with gr.Column(visible=True) as welcome_section:
474
- gr.Markdown("""
475
- # TradeVerse AI Trading Experiment
476
-
477
- Welcome to this research study on AI-assisted decision making.
478
-
479
- ---
480
-
481
- ## About This Experiment
482
-
483
- You will participate in a simulated trading game set in the **TradeVerse**, a fictional
484
- financial universe. You will make trading decisions for several companies while receiving
485
- advice from an AI assistant.
486
-
487
- **Important:** All companies, markets, and situations are fictional. No real-world
488
- financial knowledge is required or applicable.
489
-
490
- ---
491
-
492
- ## What You'll Do
493
-
494
- 1. **Review Trading Scenarios** - Each scenario presents a company and market situation
495
- 2. **Consult the AI** - An AI advisor will offer recommendations and answer questions
496
- 3. **Make Decisions** - Choose to BUY, SELL, or HOLD for each scenario
497
- 4. **See Outcomes** - Learn the results of your decisions
498
-
499
- ---
500
-
501
- ## Data Collection
502
-
503
- This experiment collects:
504
- - Your trading decisions and confidence levels
505
- - Your interactions with the AI advisor
506
- - Timing information
507
-
508
- All data is anonymized. Your participant ID contains no personal information.
509
-
510
- ---
511
-
512
- ## Consent
513
-
514
- By clicking "Start Experiment", you consent to participate in this research study.
515
- You may stop at any time.
516
- """)
517
-
518
- with gr.Row():
519
- condition_dropdown = gr.Dropdown(
520
- choices=["Random (A/B Testing)"] + list(EXPERIMENT_CONDITIONS.keys()),
521
- value="Random (A/B Testing)",
522
- label="Experimental Condition (Researcher Use)",
523
- visible=True # Set to False in production
524
- )
525
-
526
- start_btn = gr.Button("Start Experiment", variant="primary", size="lg")
527
-
528
- # ==================== GAME SCREEN ====================
529
- with gr.Column(visible=False) as game_section:
530
-
531
- # Status bar
532
- with gr.Row():
533
- participant_display = gr.Markdown("Participant: ---")
534
- portfolio_display = gr.Markdown("Portfolio: ---")
535
- progress_display = gr.Markdown("Progress: ---")
536
-
537
- with gr.Row():
538
- # Left column: Scenario and Decision
539
- with gr.Column(scale=2):
540
- scenario_display = gr.Markdown(
541
- "Loading scenario...",
542
- elem_classes=["scenario-box"]
543
- )
544
-
545
- # AI Recommendation
546
- ai_recommendation_display = gr.Markdown(
547
- "",
548
- elem_classes=["ai-advice"]
549
- )
550
-
551
- # Proactive advice (may or may not show)
552
- proactive_display = gr.Markdown(
553
- "",
554
- elem_classes=["proactive-advice"]
555
- )
556
-
557
- # Decision controls
558
- gr.Markdown("### Your Decision")
559
-
560
- with gr.Row():
561
- decision_radio = gr.Radio(
562
- choices=["BUY", "HOLD", "SELL"],
563
- value="HOLD",
564
- label="Action"
565
- )
566
- trade_amount = gr.Slider(
567
- minimum=1000,
568
- maximum=50000,
569
- value=10000,
570
- step=1000,
571
- label="Trade Amount (credits)"
572
- )
573
-
574
- confidence_slider = gr.Slider(
575
- minimum=0,
576
- maximum=100,
577
- value=50,
578
- step=5,
579
- label="How confident are you in this decision?"
580
- )
581
-
582
- submit_btn = gr.Button("Submit Decision", variant="primary")
583
-
584
- outcome_display = gr.Markdown("")
585
-
586
- # Right column: AI Chat and Controls
587
- with gr.Column(scale=1):
588
- gr.Markdown("### AI Advisor Settings")
589
-
590
- explanation_slider = gr.Slider(
591
- minimum=0,
592
- maximum=100,
593
- value=50,
594
- step=10,
595
- label="Explanation Depth",
596
- info="Minimal ← → Detailed"
597
- )
598
-
599
- style_slider = gr.Slider(
600
- minimum=0,
601
- maximum=100,
602
- value=50,
603
- step=10,
604
- label="Communication Style",
605
- info="Formal ← → Casual"
606
- )
607
-
608
- update_params_btn = gr.Button("Update AI Settings", size="sm")
609
-
610
- gr.Markdown("### Ask the AI")
611
-
612
- chatbot_display = gr.Chatbot(
613
- label="Chat with AI Advisor",
614
- height=300
615
- )
616
-
617
- chat_input = gr.Textbox(
618
- placeholder="Ask a question about this scenario...",
619
- label="Your Question",
620
- lines=2
621
- )
622
-
623
- chat_btn = gr.Button("Send", size="sm")
624
-
625
- # ==================== RESULTS SCREEN ====================
626
- with gr.Column(visible=False) as results_section:
627
- results_display = gr.Markdown("Loading results...")
628
-
629
- restart_btn = gr.Button("Start New Session", variant="primary")
630
-
631
- # ==================== EVENT HANDLERS ====================
632
-
633
- # Start experiment
634
- start_btn.click(
635
- fn=start_experiment,
636
- inputs=[condition_dropdown],
637
- outputs=[
638
- welcome_section,
639
- game_section,
640
- results_section,
641
- participant_display,
642
- portfolio_display,
643
- progress_display,
644
- scenario_display,
645
- ai_recommendation_display,
646
- proactive_display,
647
- chatbot_display,
648
- confidence_slider,
649
- decision_radio
650
- ]
651
- )
652
-
653
- # Update AI parameters
654
- update_params_btn.click(
655
- fn=update_ai_params,
656
- inputs=[explanation_slider, style_slider],
657
- outputs=[ai_recommendation_display]
658
- )
659
-
660
- # Chat interaction
661
- chat_btn.click(
662
- fn=handle_chat_query,
663
- inputs=[chat_input, chatbot_display],
664
- outputs=[chatbot_display, chat_input]
665
- )
666
-
667
- chat_input.submit(
668
- fn=handle_chat_query,
669
- inputs=[chat_input, chatbot_display],
670
- outputs=[chatbot_display, chat_input]
671
- )
672
-
673
- # Submit decision
674
- submit_btn.click(
675
- fn=submit_decision,
676
- inputs=[decision_radio, confidence_slider, trade_amount],
677
- outputs=[
678
- game_section,
679
- results_section,
680
- portfolio_display,
681
- progress_display,
682
- scenario_display,
683
- ai_recommendation_display,
684
- proactive_display,
685
- chatbot_display,
686
- confidence_slider,
687
- decision_radio,
688
- outcome_display
689
- ]
690
- )
691
-
692
- # Restart
693
- restart_btn.click(
694
- fn=lambda: (gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)),
695
- outputs=[welcome_section, game_section, results_section]
696
- )
697
-
698
- return app
699
-
700
-
701
- # Launch the application
702
- if __name__ == "__main__":
703
- app = create_app()
704
- app.launch(debug=True)