Claude Claude commited on
Commit
76b0f88
Β·
unverified Β·
1 Parent(s): 76c6f71

Add interactive demo scripts for exploring persona responses

Browse files

New Features:
- demo_interactive.py: Full-featured interactive demo with multiple modes
* Quick demo (1 question, all personas)
* Full demo (4 preset questions)
* Custom questions (user input)
* Compare mode (2 personas side-by-side)
- quick_demo.py: Simple script for rapid testing with any question

Both scripts demonstrate the system's ability to generate diverse
stakeholder perspectives on urban planning issues.

Usage:
python demo_interactive.py # Interactive menu-driven experience
python quick_demo.py # Simple question prompt

Tested successfully with questions about food trucks, community gardens,
and other urban planning scenarios. Shows authentic persona responses
with clear value differences across stakeholders.

πŸ€– Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

Files changed (2) hide show
  1. demo_interactive.py +221 -0
  2. quick_demo.py +49 -0
demo_interactive.py ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Interactive Demo: AI Personas for Urban Planning
3
+
4
+ This script demonstrates the system with interesting questions
5
+ and shows how different stakeholders respond.
6
+ """
7
+
8
+ import sys
9
+ from pathlib import Path
10
+ sys.path.insert(0, str(Path(__file__).parent))
11
+
12
+ from src.pipeline.query_engine import QueryEngine
13
+ from rich.console import Console
14
+ from rich.panel import Panel
15
+ from rich.prompt import Prompt, Confirm
16
+ from rich.table import Table
17
+
18
+ console = Console()
19
+
20
+
21
+ def show_personas(engine):
22
+ """Display available personas in a nice table"""
23
+ personas = engine.list_available_personas()
24
+
25
+ table = Table(title="πŸ™οΈ Your Urban Planning Stakeholders", show_header=True, header_style="bold cyan")
26
+ table.add_column("#", style="dim", width=3)
27
+ table.add_column("Name", style="green", width=20)
28
+ table.add_column("Role", style="yellow", width=25)
29
+ table.add_column("Perspective", style="white")
30
+
31
+ descriptions = [
32
+ "Progressive, sustainability-focused",
33
+ "Pragmatic, economy-focused",
34
+ "Data-driven, safety-first",
35
+ "Traditional, community-protective",
36
+ "Activist, equity-focused",
37
+ "Market-driven, growth-oriented"
38
+ ]
39
+
40
+ for i, (persona_id, name, role) in enumerate(personas, 1):
41
+ table.add_row(str(i), name, role, descriptions[i-1])
42
+
43
+ console.print("\n")
44
+ console.print(table)
45
+ console.print("\n")
46
+
47
+
48
+ def ask_question(engine, question, persona_ids=None):
49
+ """Ask a question to one or more personas"""
50
+ console.print(Panel(
51
+ f"[bold cyan]Question:[/bold cyan]\n{question}",
52
+ border_style="cyan"
53
+ ))
54
+ console.print()
55
+
56
+ if persona_ids is None:
57
+ # Ask all personas
58
+ persona_ids = [p[0] for p in engine.list_available_personas()]
59
+
60
+ console.print(f"[dim]Querying {len(persona_ids)} persona(s)...[/dim]\n")
61
+
62
+ responses = engine.query_multiple(
63
+ persona_ids=persona_ids,
64
+ question=question,
65
+ context_id="downtown_district"
66
+ )
67
+
68
+ for i, response in enumerate(responses, 1):
69
+ console.print(f"[bold green]━━━ {i}. {response.persona_name}[/bold green] [dim]({response.persona_role})[/dim] [bold green]━━━[/bold green]")
70
+ console.print()
71
+ console.print(response.response)
72
+ console.print("\n")
73
+
74
+ return responses
75
+
76
+
77
+ def main():
78
+ console.print("\n")
79
+ console.print("╔═══════════════════════════════════════════════════════════════════╗", style="bold cyan")
80
+ console.print("β•‘ πŸ™οΈ AI Personas for Urban Planning - Demo Session β•‘", style="bold cyan")
81
+ console.print("β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•", style="bold cyan")
82
+ console.print()
83
+
84
+ # Initialize
85
+ console.print("[dim]Initializing system...[/dim]")
86
+ engine = QueryEngine()
87
+
88
+ if not engine.test_system():
89
+ console.print("[red]System initialization failed![/red]")
90
+ return
91
+
92
+ console.print("[green]βœ“ System ready![/green]")
93
+
94
+ # Show personas
95
+ show_personas(engine)
96
+
97
+ # Demo questions
98
+ questions = [
99
+ {
100
+ "q": "Should we allow food trucks in the downtown plaza?",
101
+ "desc": "A simple yes/no question with complex stakeholder implications"
102
+ },
103
+ {
104
+ "q": "The city is considering a $100M affordable housing bond. What's your opinion?",
105
+ "desc": "A major policy decision with fiscal and social dimensions"
106
+ },
107
+ {
108
+ "q": "What's the most important issue facing our downtown right now?",
109
+ "desc": "An open-ended question showing different priorities"
110
+ },
111
+ {
112
+ "q": "How would you improve public transit in the city?",
113
+ "desc": "Solution-oriented question revealing different approaches"
114
+ },
115
+ ]
116
+
117
+ console.print("[bold]Choose your adventure:[/bold]")
118
+ console.print()
119
+ console.print(" [cyan]1[/cyan] - Quick demo (1 question, all stakeholders)")
120
+ console.print(" [cyan]2[/cyan] - Full demo (4 questions, showing diverse perspectives)")
121
+ console.print(" [cyan]3[/cyan] - Custom question (you choose)")
122
+ console.print(" [cyan]4[/cyan] - Compare two personas (see contrasting views)")
123
+ console.print()
124
+
125
+ choice = Prompt.ask("Your choice", choices=["1", "2", "3", "4"], default="1")
126
+ console.print()
127
+
128
+ if choice == "1":
129
+ # Quick demo
130
+ console.print("[bold cyan]═══ QUICK DEMO ═══[/bold cyan]\n")
131
+ ask_question(engine, questions[0]["q"])
132
+
133
+ elif choice == "2":
134
+ # Full demo
135
+ console.print("[bold cyan]═══ FULL DEMO ═══[/bold cyan]\n")
136
+ for i, q_info in enumerate(questions, 1):
137
+ console.print(f"\n[bold yellow]Question {i}/4:[/bold yellow] [dim]{q_info['desc']}[/dim]\n")
138
+ ask_question(engine, q_info["q"])
139
+
140
+ if i < len(questions):
141
+ if not Confirm.ask("\n[cyan]Continue to next question?[/cyan]", default=True):
142
+ break
143
+ console.print("\n" + "─" * 70 + "\n")
144
+
145
+ elif choice == "3":
146
+ # Custom question
147
+ console.print("[bold cyan]═══ CUSTOM QUESTION ═══[/bold cyan]\n")
148
+ console.print("[dim]Ask the personas anything about urban planning![/dim]")
149
+ console.print("[dim]Examples: parking policies, green spaces, housing, transit, development, etc.[/dim]\n")
150
+
151
+ question = Prompt.ask("[cyan]Your question[/cyan]")
152
+ console.print()
153
+
154
+ ask_all = Confirm.ask("Ask all 6 personas?", default=True)
155
+
156
+ if ask_all:
157
+ ask_question(engine, question)
158
+ else:
159
+ show_personas(engine)
160
+ persona_choice = Prompt.ask("Which persona? (1-6)", choices=["1","2","3","4","5","6"])
161
+ persona_map = {
162
+ "1": "sarah_chen",
163
+ "2": "marcus_thompson",
164
+ "3": "elena_rodriguez",
165
+ "4": "james_obrien",
166
+ "5": "priya_patel",
167
+ "6": "david_kim"
168
+ }
169
+ ask_question(engine, question, [persona_map[persona_choice]])
170
+
171
+ elif choice == "4":
172
+ # Compare two personas
173
+ console.print("[bold cyan]═══ COMPARE TWO PERSPECTIVES ═══[/bold cyan]\n")
174
+ console.print("[dim]See how two different stakeholders view the same issue[/dim]\n")
175
+
176
+ question = Prompt.ask(
177
+ "[cyan]Question[/cyan]",
178
+ default="Should we prioritize affordable housing or economic development?"
179
+ )
180
+ console.print()
181
+
182
+ console.print("[yellow]Pick first persona:[/yellow]")
183
+ show_personas(engine)
184
+ p1 = Prompt.ask("Persona 1 (1-6)", choices=["1","2","3","4","5","6"])
185
+
186
+ console.print("\n[yellow]Pick second persona:[/yellow]")
187
+ p2 = Prompt.ask("Persona 2 (1-6)", choices=["1","2","3","4","5","6"])
188
+
189
+ persona_map = {
190
+ "1": "sarah_chen",
191
+ "2": "marcus_thompson",
192
+ "3": "elena_rodriguez",
193
+ "4": "james_obrien",
194
+ "5": "priya_patel",
195
+ "6": "david_kim"
196
+ }
197
+
198
+ console.print()
199
+ ask_question(engine, question, [persona_map[p1], persona_map[p2]])
200
+
201
+ # Wrap up
202
+ console.print("\n" + "═" * 70)
203
+ console.print("\n[bold green]βœ“ Demo complete![/bold green]")
204
+ console.print("\n[dim]This demonstrates how the AI Personas system helps explore")
205
+ console.print("diverse stakeholder perspectives on urban planning issues.[/dim]\n")
206
+ console.print("[cyan]Next steps:[/cyan]")
207
+ console.print(" β€’ Customize personas in [yellow]data/personas/[/yellow]")
208
+ console.print(" β€’ Add your own contexts in [yellow]data/contexts/[/yellow]")
209
+ console.print(" β€’ Use [yellow]python -m src.cli[/yellow] for full interactive mode")
210
+ console.print(" β€’ Build Phase 2 for population distributions\n")
211
+
212
+
213
+ if __name__ == "__main__":
214
+ try:
215
+ main()
216
+ except KeyboardInterrupt:
217
+ console.print("\n\n[yellow]Demo interrupted. Goodbye![/yellow]\n")
218
+ except Exception as e:
219
+ console.print(f"\n[red]Error: {e}[/red]\n")
220
+ import traceback
221
+ traceback.print_exc()
quick_demo.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Quick Demo - Ask the personas anything!
3
+
4
+ Usage: python quick_demo.py
5
+ """
6
+
7
+ import sys
8
+ from pathlib import Path
9
+ sys.path.insert(0, str(Path(__file__).parent))
10
+
11
+ from src.pipeline.query_engine import QueryEngine
12
+
13
+ print("\n" + "="*70)
14
+ print(" AI Personas for Urban Planning - Quick Demo")
15
+ print("="*70 + "\n")
16
+
17
+ # Initialize
18
+ print("Initializing...")
19
+ engine = QueryEngine()
20
+ engine.test_system()
21
+
22
+ print("\n" + "="*70)
23
+ print("\nAvailable Personas:")
24
+ for i, (pid, name, role) in enumerate(engine.list_available_personas(), 1):
25
+ print(f" {i}. {name} - {role}")
26
+
27
+ print("\n" + "="*70)
28
+
29
+ # Ask your question here!
30
+ question = input("\nYour question: ")
31
+
32
+ print(f"\nAsking all 6 personas: '{question}'\n")
33
+ print("="*70 + "\n")
34
+
35
+ responses = engine.query_multiple(
36
+ persona_ids=[p[0] for p in engine.list_available_personas()],
37
+ question=question,
38
+ context_id="downtown_district"
39
+ )
40
+
41
+ for i, response in enumerate(responses, 1):
42
+ print(f"\n{'='*70}")
43
+ print(f"{i}. {response.persona_name} ({response.persona_role})")
44
+ print('='*70)
45
+ print(f"\n{response.response}\n")
46
+
47
+ print("\n" + "="*70)
48
+ print(f"βœ“ Got {len(responses)} responses!")
49
+ print("="*70 + "\n")