cryogenic22 commited on
Commit
cb8359d
·
verified ·
1 Parent(s): 2fd7bb8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +1080 -234
app.py CHANGED
@@ -1,18 +1,21 @@
1
  import streamlit as st
2
  import os
3
  import anthropic
4
- from langgraph.graph import Graph, StateGraph
5
- from langgraph.prelude import Container
6
- from langgraph.checkpoint import persist
7
  from langchain_anthropic import ChatAnthropic
8
  import json
9
  from typing import Dict, List, Optional, Any, TypedDict
10
  import time
11
  import pandas as pd
 
 
 
12
 
13
  # Set page configuration
14
  st.set_page_config(
15
- page_title="Thinking Agent System",
16
  page_icon="🧠",
17
  layout="wide",
18
  initial_sidebar_state="expanded"
@@ -27,50 +30,536 @@ if "agent_graph" not in st.session_state:
27
  st.session_state.agent_graph = None
28
  if "current_step" not in st.session_state:
29
  st.session_state.current_step = 0
30
- if "persona_configs" not in st.session_state:
31
- st.session_state.persona_configs = {
32
- "researcher": {
33
- "name": "Researcher",
34
- "description": "A careful researcher who examines all angles of a problem",
35
- "system_prompt": """You are a thoughtful researcher who carefully analyzes questions or problems.
36
- Your role is to break down complex questions, consider different approaches, identify assumptions,
37
- and provide comprehensive analysis. Consider multiple perspectives and potential weaknesses in different lines of reasoning.
38
- Your goal is to explore the problem space thoroughly before jumping to conclusions."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  },
40
- "critic": {
41
- "name": "Critic",
42
- "description": "Identifies potential issues and challenges with approaches",
43
- "system_prompt": """You are a thoughtful critic who examines potential flaws or weaknesses in reasoning.
44
- Your role is to find potential issues with an approach, identify hidden assumptions,
45
- and suggest alternative ways of looking at problems.
46
- You're not negative, but constructively critical - your goal is to strengthen the analysis."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  },
48
- "synthesizer": {
49
- "name": "Synthesizer",
50
- "description": "Pulls together insights into a cohesive response",
51
- "system_prompt": """You are a thoughtful synthesizer who pulls together different insights into a coherent whole.
52
- Your role is to examine the components of analysis that have been done, identify the key themes and insights,
53
- and create a unified response that incorporates the most important elements.
54
- You should balance detail with clarity, ensuring the final response is both comprehensive and accessible."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  },
56
- "meta_agent": {
57
- "name": "Meta Agent",
58
- "description": "Coordinates the thinking process across agents",
59
- "system_prompt": """You are the coordinator of a multi-agent thinking system. Your job is to:
60
- 1. Understand the user's question
61
- 2. Decide which thinking agents need to be engaged and in what order
62
- 3. Pass information between agents as needed
63
- 4. Determine when sufficient analysis has been done to provide a response
64
- 5. Ensure the process is both thorough and efficient
65
-
66
- You have these agents at your disposal:
67
- - Researcher: Breaks down problems and explores them thoroughly
68
- - Critic: Examines potential flaws in reasoning and suggests alternatives
69
- - Synthesizer: Pulls together insights into a cohesive response
70
-
71
- Think carefully about how to best deploy these agents for each query."""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
73
  }
 
 
 
 
 
 
 
 
 
 
 
 
74
 
75
  # Function to create and configure the Claude client
76
  def get_claude_client():
@@ -94,8 +583,76 @@ def get_langchain_claude():
94
  anthropic_api_key=api_key
95
  )
96
 
97
- # Load or create agent graph
98
- def create_agent_graph():
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  # Create a typed dict for agent state
100
  class AgentState(TypedDict):
101
  query: str
@@ -103,6 +660,7 @@ def create_agent_graph():
103
  current_agent: str
104
  final_response: Optional[str]
105
  history: List[Dict[str, Any]]
 
106
 
107
  # Initialize the graph
108
  graph = StateGraph(AgentState)
@@ -110,9 +668,13 @@ def create_agent_graph():
110
  # Define the nodes (agents)
111
  @graph.node
112
  def initialize(state: AgentState) -> AgentState:
 
 
 
 
113
  return {
114
  **state,
115
- "thoughts": {"meta_agent": [], "researcher": [], "critic": [], "synthesizer": []},
116
  "current_agent": "meta_agent",
117
  "history": []
118
  }
@@ -123,7 +685,7 @@ def create_agent_graph():
123
  if not client:
124
  return state
125
 
126
- system_prompt = st.session_state.persona_configs["meta_agent"]["system_prompt"]
127
 
128
  # Construct the message based on history and current query
129
  history_text = ""
@@ -132,6 +694,14 @@ def create_agent_graph():
132
  if entry.get("agent") and entry.get("thought"):
133
  history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
134
 
 
 
 
 
 
 
 
 
135
  message = client.messages.create(
136
  model="claude-3-7-sonnet-20250219",
137
  system=system_prompt,
@@ -140,8 +710,10 @@ def create_agent_graph():
140
  "role": "user",
141
  "content": f"User query: {state['query']}\n\n"
142
  f"Current thinking process:\n{history_text}\n\n"
143
- f"What should be the next step in the thinking process? Which agent should handle it next, "
144
- f"and what specific aspect should they focus on? Or is the analysis sufficient to generate a final response?"
 
 
145
  }
146
  ],
147
  temperature=0.1,
@@ -156,16 +728,24 @@ def create_agent_graph():
156
 
157
  # Determine the next agent from the meta agent's response
158
  next_agent = "meta_agent" # Default to meta_agent
159
- if "researcher should" in thought.lower() or "have the researcher" in thought.lower():
160
- next_agent = "researcher"
161
- elif "critic should" in thought.lower() or "have the critic" in thought.lower():
162
- next_agent = "critic"
163
- elif "synthesizer should" in thought.lower() or "have the synthesizer" in thought.lower():
164
- next_agent = "synthesizer"
165
- elif "final response" in thought.lower() or "sufficient analysis" in thought.lower():
166
  next_agent = "final"
 
 
 
 
 
 
 
 
 
 
167
 
168
- updated_history = state.get("history", []).copy() + [{"agent": "Meta Agent", "thought": thought}]
 
 
169
 
170
  return {
171
  **state,
@@ -174,103 +754,25 @@ def create_agent_graph():
174
  "history": updated_history
175
  }
176
 
 
 
177
  @graph.node
178
- def researcher(state: AgentState) -> AgentState:
179
  client = get_claude_client()
180
  if not client:
181
  return state
182
 
183
- system_prompt = st.session_state.persona_configs["researcher"]["system_prompt"]
184
-
185
- # Construct the message based on history and current query
186
- history_text = ""
187
- if state.get("history"):
188
- for entry in state["history"]:
189
- if entry.get("agent") and entry.get("thought"):
190
- history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
191
-
192
- message = client.messages.create(
193
- model="claude-3-7-sonnet-20250219",
194
- system=system_prompt,
195
- messages=[
196
- {
197
- "role": "user",
198
- "content": f"User query: {state['query']}\n\n"
199
- f"Current thinking process:\n{history_text}\n\n"
200
- f"Please provide your analysis as the Researcher agent."
201
- }
202
- ],
203
- temperature=0.1,
204
- max_tokens=1500
205
- )
206
-
207
- thought = message.content[0].text
208
 
209
- # Update the state
210
- updated_thoughts = state["thoughts"].copy()
211
- updated_thoughts["researcher"] = updated_thoughts.get("researcher", []) + [thought]
 
 
 
212
 
213
- updated_history = state.get("history", []).copy() + [{"agent": "Researcher", "thought": thought}]
214
-
215
- return {
216
- **state,
217
- "thoughts": updated_thoughts,
218
- "current_agent": "meta_agent", # Return to meta agent for next direction
219
- "history": updated_history
220
- }
221
-
222
- @graph.node
223
- def critic(state: AgentState) -> AgentState:
224
- client = get_claude_client()
225
- if not client:
226
- return state
227
-
228
- system_prompt = st.session_state.persona_configs["critic"]["system_prompt"]
229
-
230
- # Construct the message based on history and current query
231
- history_text = ""
232
- if state.get("history"):
233
- for entry in state["history"]:
234
- if entry.get("agent") and entry.get("thought"):
235
- history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
236
-
237
- message = client.messages.create(
238
- model="claude-3-7-sonnet-20250219",
239
- system=system_prompt,
240
- messages=[
241
- {
242
- "role": "user",
243
- "content": f"User query: {state['query']}\n\n"
244
- f"Current thinking process:\n{history_text}\n\n"
245
- f"Please provide your critical analysis as the Critic agent."
246
- }
247
- ],
248
- temperature=0.1,
249
- max_tokens=1500
250
- )
251
-
252
- thought = message.content[0].text
253
-
254
- # Update the state
255
- updated_thoughts = state["thoughts"].copy()
256
- updated_thoughts["critic"] = updated_thoughts.get("critic", []) + [thought]
257
-
258
- updated_history = state.get("history", []).copy() + [{"agent": "Critic", "thought": thought}]
259
-
260
- return {
261
- **state,
262
- "thoughts": updated_thoughts,
263
- "current_agent": "meta_agent", # Return to meta agent for next direction
264
- "history": updated_history
265
- }
266
-
267
- @graph.node
268
- def synthesizer(state: AgentState) -> AgentState:
269
- client = get_claude_client()
270
- if not client:
271
- return state
272
-
273
- system_prompt = st.session_state.persona_configs["synthesizer"]["system_prompt"]
274
 
275
  # Construct the message based on history and current query
276
  history_text = ""
@@ -287,10 +789,10 @@ def create_agent_graph():
287
  "role": "user",
288
  "content": f"User query: {state['query']}\n\n"
289
  f"Current thinking process:\n{history_text}\n\n"
290
- f"Please synthesize the insights and provide a cohesive analysis as the Synthesizer agent."
291
  }
292
  ],
293
- temperature=0.1,
294
  max_tokens=1500
295
  )
296
 
@@ -298,9 +800,11 @@ def create_agent_graph():
298
 
299
  # Update the state
300
  updated_thoughts = state["thoughts"].copy()
301
- updated_thoughts["synthesizer"] = updated_thoughts.get("synthesizer", []) + [thought]
302
 
303
- updated_history = state.get("history", []).copy() + [{"agent": "Synthesizer", "thought": thought}]
 
 
304
 
305
  return {
306
  **state,
@@ -322,15 +826,18 @@ def create_agent_graph():
322
  if entry.get("agent") and entry.get("thought"):
323
  history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
324
 
 
 
 
325
  message = client.messages.create(
326
  model="claude-3-7-sonnet-20250219",
327
- system="You are a thoughtful AI assistant that provides well-reasoned, comprehensive responses.",
328
  messages=[
329
  {
330
  "role": "user",
331
  "content": f"User query: {state['query']}\n\n"
332
- f"Here is the complete thinking process that went into answering this query:\n{history_text}\n\n"
333
- f"Based on all of this thinking, provide a final, comprehensive response to the user's query."
334
  }
335
  ],
336
  temperature=0.1,
@@ -339,38 +846,52 @@ def create_agent_graph():
339
 
340
  final_response = message.content[0].text
341
 
 
 
 
 
 
342
  return {
343
  **state,
344
  "final_response": final_response,
345
- "current_agent": "done"
 
346
  }
347
 
348
  # Define the edges
349
  graph.add_edge("initialize", "meta_agent")
 
 
350
  graph.add_conditional_edges(
351
  "meta_agent",
352
  lambda state: state["current_agent"],
353
  {
354
- "researcher": "researcher",
355
- "critic": "critic",
356
- "synthesizer": "synthesizer",
357
  "final": "finalize",
358
- "meta_agent": "meta_agent" # For cases where meta agent needs another step
 
359
  }
360
  )
361
- graph.add_edge("researcher", "meta_agent")
362
- graph.add_edge("critic", "meta_agent")
363
- graph.add_edge("synthesizer", "meta_agent")
364
 
365
  # Compile the graph
366
  compiled_graph = graph.compile()
367
 
368
  return compiled_graph
369
 
370
- # Function to run the agent graph
371
- def run_agent_graph(query):
372
- if not st.session_state.agent_graph:
373
- st.session_state.agent_graph = create_agent_graph()
 
 
 
 
 
 
 
374
 
375
  # Reset the current step counter
376
  st.session_state.current_step = 0
@@ -379,41 +900,206 @@ def run_agent_graph(query):
379
  st.session_state.thinking_logs = []
380
 
381
  # Start with initial state
382
- initial_state = {"query": query}
 
 
 
383
 
384
  # Execute the graph with checkpointing
385
- # We'll use the checkpoint functionality to track each step
386
  @persist(to="memory")
387
  def run_with_checkpoints(graph, initial_state):
388
  return graph.run(initial_state)
389
 
390
- result = run_with_checkpoints(st.session_state.agent_graph, initial_state)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
 
392
- # Process the result for display
393
- if result and "history" in result:
394
- for step in result["history"]:
395
- st.session_state.thinking_logs.append(step)
 
396
 
397
- # Return the final response
398
- if result and "final_response" in result:
399
- return result["final_response"]
400
- else:
401
- return "I wasn't able to generate a response. Please try again or check the settings."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
 
403
  # UI Layout
404
- st.sidebar.title("🧠 Thinking Agent System")
405
 
406
- # Tabs for different views
407
- tabs = st.tabs(["Chat", "Thinking Process", "Agent Configuration"])
408
 
409
- with tabs[0]: # Chat tab
410
- st.header("Chat with the Thinking Agent")
411
 
412
  # Display chat messages
413
  for message in st.session_state.messages:
414
  with st.chat_message(message["role"]):
415
  st.write(message["content"])
416
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
417
  # User input
418
  if prompt := st.chat_input("What's on your mind?"):
419
  # Add user message to chat history
@@ -425,8 +1111,15 @@ with tabs[0]: # Chat tab
425
 
426
  # Show thinking indicator
427
  with st.chat_message("assistant"):
428
- with st.spinner("Thinking..."):
429
- response = run_agent_graph(prompt)
 
 
 
 
 
 
 
430
 
431
  # Display the response
432
  st.write(response)
@@ -434,58 +1127,194 @@ with tabs[0]: # Chat tab
434
  # Add assistant response to chat history
435
  st.session_state.messages.append({"role": "assistant", "content": response})
436
 
437
- with tabs[1]: # Thinking Process tab
438
- st.header("Agent Thinking Process")
439
 
440
  if not st.session_state.thinking_logs:
441
- st.info("No thinking process to display yet. Start a conversation to see the agents at work.")
442
  else:
 
 
 
 
 
 
443
  for i, log in enumerate(st.session_state.thinking_logs):
444
  step_num = i + 1
445
- with st.expander(f"Step {step_num}: {log.get('agent', 'Unknown Agent')}", expanded=True):
446
  st.markdown(log.get("thought", "No thought recorded"))
447
 
448
- with tabs[2]: # Agent Configuration tab
449
- st.header("Configure Agent Personas")
450
 
451
- # Select agent to configure
452
- selected_agent = st.selectbox(
453
- "Select agent to configure:",
454
- options=list(st.session_state.persona_configs.keys()),
455
- format_func=lambda x: st.session_state.persona_configs[x]["name"]
456
- )
457
 
458
- # Edit the selected agent
459
- if selected_agent:
460
- with st.form(f"edit_{selected_agent}"):
461
- st.subheader(f"Edit {st.session_state.persona_configs[selected_agent]['name']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
 
463
- name = st.text_input(
464
- "Agent Name",
465
- value=st.session_state.persona_configs[selected_agent]["name"]
466
- )
467
 
468
- description = st.text_area(
469
- "Description",
470
- value=st.session_state.persona_configs[selected_agent]["description"],
471
- height=100
472
- )
473
 
474
- system_prompt = st.text_area(
475
- "System Prompt",
476
- value=st.session_state.persona_configs[selected_agent]["system_prompt"],
477
- height=300
478
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
479
 
480
- if st.form_submit_button("Save Changes"):
481
- st.session_state.persona_configs[selected_agent]["name"] = name
482
- st.session_state.persona_configs[selected_agent]["description"] = description
483
- st.session_state.persona_configs[selected_agent]["system_prompt"] = system_prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
484
 
485
- # Recreate the agent graph with updated configs
486
- st.session_state.agent_graph = create_agent_graph()
487
 
488
- st.success(f"Updated {name} configuration successfully!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
489
 
490
  # Settings in the sidebar
491
  with st.sidebar.expander("⚙️ Settings"):
@@ -499,6 +1328,15 @@ with st.sidebar.expander("⚙️ Settings"):
499
  if api_key:
500
  st.session_state.anthropic_api_key = api_key
501
 
 
 
 
 
 
 
 
 
 
502
  if st.button("Test Connection"):
503
  client = get_claude_client()
504
  if client:
@@ -515,17 +1353,25 @@ with st.sidebar.expander("⚙️ Settings"):
515
  # Display some information about the app
516
  with st.sidebar.expander("ℹ️ About"):
517
  st.markdown("""
518
- This app demonstrates a multi-agent thinking system powered by Claude 3.7.
519
 
520
- The system uses multiple specialized agents with different perspectives to analyze problems:
521
- - **Meta Agent**: Coordinates the thinking process
522
- - **Researcher**: Explores the problem space thoroughly
523
- - **Critic**: Identifies flaws in reasoning
524
- - **Synthesizer**: Combines insights into a coherent response
525
 
526
- You can observe the thinking process in the "Thinking Process" tab and configure the agents in the "Agent Configuration" tab.
527
- """)
528
-
529
- # Create the agent graph on app startup if it doesn't exist
530
- if not st.session_state.agent_graph:
531
- st.session_state.agent_graph = create_agent_graph()
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import streamlit as st
2
  import os
3
  import anthropic
4
+ from langraph.graph import Graph, StateGraph
5
+ from langraph.prelude import Container
6
+ from langraph.checkpoint import persist
7
  from langchain_anthropic import ChatAnthropic
8
  import json
9
  from typing import Dict, List, Optional, Any, TypedDict
10
  import time
11
  import pandas as pd
12
+ import uuid
13
+ import re
14
+ from datetime import datetime
15
 
16
  # Set page configuration
17
  st.set_page_config(
18
+ page_title="Multi-Persona Reasoning System",
19
  page_icon="🧠",
20
  layout="wide",
21
  initial_sidebar_state="expanded"
 
30
  st.session_state.agent_graph = None
31
  if "current_step" not in st.session_state:
32
  st.session_state.current_step = 0
33
+ if "selected_personas" not in st.session_state:
34
+ st.session_state.selected_personas = []
35
+ if "persona_library" not in st.session_state:
36
+ # Load the default persona library from the comprehensive framework
37
+ st.session_state.persona_library = {
38
+ "meta_agent": {
39
+ "id": "meta_agent",
40
+ "name": "Meta-Agent Synthesizer",
41
+ "description": "Integrates diverse perspectives into a coherent, balanced response",
42
+ "category": "Meta",
43
+ "system_prompt": """# META-AGENT SYNTHESIS
44
+
45
+ You are the meta-agent responsible for synthesizing multiple expert perspectives into a coherent, balanced analysis. Your goal is not to simply aggregate opinions but to create an integrated understanding that is greater than the sum of its parts.
46
+
47
+ ## Your Role as Synthesizer
48
+
49
+ You have received analyses from different expert personas, each providing valuable insights from their unique perspective. Each has natural limitations and biases. Your task is to:
50
+
51
+ 1. Identify areas of consensus that suggest robust conclusions
52
+ 2. Recognize productive tensions and competing valid viewpoints
53
+ 3. Determine where perspectives complement each other
54
+ 4. Integrate insights into a coherent whole
55
+ 5. Maintain appropriate epistemic humility
56
+
57
+ ## Synthesis Process
58
+
59
+ 1. Summarize the key insights from each perspective
60
+ 2. Identify points of agreement and disagreement
61
+ 3. Evaluate the strengths and limitations of each viewpoint
62
+ 4. Consider which perspectives are most relevant to different aspects of the question
63
+ 5. Develop an integrated analysis that preserves important nuances
64
+ 6. Articulate a balanced conclusion with appropriate levels of confidence
65
+
66
+ Remember that your goal is wisdom rather than certainty. The best synthesis acknowledges complexity, maintains appropriate doubt, and provides clear guidance without overreaching."""
67
+ },
68
+ "selector_agent": {
69
+ "id": "selector_agent",
70
+ "name": "Persona Selector",
71
+ "description": "Analyzes queries to select the most appropriate personas",
72
+ "category": "Meta",
73
+ "system_prompt": """# PERSONA SELECTION AGENT
74
+
75
+ You are an expert at analyzing questions and selecting the most appropriate thinking personas to address them. Your goal is to identify a diverse yet relevant set of perspectives that will lead to the most insightful analysis.
76
+
77
+ ## Your Role as Selector
78
+
79
+ When presented with a query, you must:
80
+
81
+ 1. Analyze the query's subject matter, complexity, and implied perspectives
82
+ 2. Identify the domains of knowledge most relevant to the query
83
+ 3. Select a diverse yet complementary set of personas (typically 5) that together will provide the most comprehensive analysis
84
+ 4. Ensure cognitive diversity by including contrasting viewpoints where appropriate
85
+ 5. Provide a brief justification for each selected persona
86
+
87
+ ## Selection Criteria
88
+
89
+ Consider these factors when selecting personas:
90
+ - Domain relevance: How directly does the persona's expertise apply?
91
+ - Cognitive approach: What thinking styles will be most beneficial?
92
+ - Potential for productive tension: Will including opposing viewpoints generate valuable insights?
93
+ - Complementary knowledge: How do the selected personas work together?
94
+ - Query complexity: Does the question require specialized expertise?
95
+
96
+ Remember that your goal is not just to select experts in the subject matter, but to assemble a thinking team that will explore the problem space thoroughly from multiple angles. Balance depth in relevant domains with breadth of perspective."""
97
  },
98
+ "analytical_scientist": {
99
+ "id": "analytical_scientist",
100
+ "name": "Analytical Scientist",
101
+ "description": "Prioritizes empirical evidence, methodological rigor, and logical consistency",
102
+ "category": "Scientific Personas",
103
+ "system_prompt": """# ANALYTICAL SCIENTIST PERSPECTIVE ANALYSIS
104
+
105
+ You are embodying the perspective of an Analytical Scientist. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
106
+
107
+ ## Your Core Perspective
108
+ You prioritize empirical evidence, methodological rigor, and logical consistency. You believe claims should be proportional to evidence, and theories should be evaluated based on their explanatory power, predictive accuracy, and falsifiability. You value precision, clarity, and quantitative reasoning where applicable.
109
+
110
+ ## Your Reasoning Process
111
+ When analyzing problems, you typically:
112
+ - Identify testable claims and separate them from normative statements
113
+ - Evaluate the quality and relevance of available evidence
114
+ - Consider statistical significance and effect sizes
115
+ - Look for potential confounding variables or alternative explanations
116
+ - Assess whether conclusions follow logically from premises
117
+ - Consider whether claims are falsifiable and what evidence would disprove them
118
+ - Determine confidence levels based on the strength of evidence
119
+
120
+ ## Key Considerations
121
+ For the question at hand, be sure to consider:
122
+ - What empirical evidence is relevant to this question
123
+ - Whether causal claims are justified or merely correlational
124
+ - The strength and limitations of different research methodologies
125
+ - How confident we can be in various claims given available evidence
126
+ - What additional data would help resolve uncertainties
127
+
128
+ ## Known Limitations
129
+ Be aware that your perspective has these potential limitations:
130
+ - May undervalue qualitative or narrative evidence
131
+ - Can struggle with domains where randomized controlled trials or precise measurements are impossible
132
+ - Sometimes fails to account for values, preferences, and human factors
133
+ - May overemphasize what is measurable at the expense of what is important but hard to quantify
134
+
135
+ ## Required Output Format
136
+ 1. Initial impression (2-3 sentences)
137
+ 2. Key insights from your perspective (3-5 bullet points)
138
+ 3. Main analysis (300-500 words)
139
+ 4. Potential blindspots in your analysis
140
+ 5. Final position summary (100 words)"""
141
  },
142
+ "theoretical_physicist": {
143
+ "id": "theoretical_physicist",
144
+ "name": "Theoretical Physicist",
145
+ "description": "Prioritizes fundamental principles, mathematical models, and elegant theoretical frameworks",
146
+ "category": "Scientific Personas",
147
+ "system_prompt": """# THEORETICAL PHYSICIST PERSPECTIVE ANALYSIS
148
+
149
+ You are embodying the perspective of a Theoretical Physicist. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
150
+
151
+ ## Your Core Perspective
152
+ You prioritize fundamental principles, mathematical models, and elegant theoretical frameworks that explain phenomena at their most basic level. You believe in seeking unified theories that connect seemingly disparate observations, and you value parsimony, symmetry, and mathematical beauty in explanations. You understand that counter-intuitive models can often be necessary to describe reality accurately.
153
+
154
+ ## Your Reasoning Process
155
+ When analyzing problems, you typically:
156
+ - Identify the fundamental variables and parameters involved
157
+ - Consider the relevant physical laws and constraints that apply
158
+ - Build mathematical models that capture essential dynamics
159
+ - Look for conservation principles and invariants
160
+ - Consider limiting cases and boundary conditions
161
+ - Assess how scale affects the dominant forces and interactions
162
+ - Apply analogies from established physical theories
163
+ - Evaluate theoretical predictions against empirical observations
164
+
165
+ ## Key Considerations
166
+ For the question at hand, be sure to consider:
167
+ - What fundamental forces or principles might be at work
168
+ - How the system's behavior scales with key parameters
169
+ - Whether there are analogous physical systems that provide insight
170
+ - What symmetries or conservation laws might apply
171
+ - How complexity might emerge from simple underlying rules
172
+
173
+ ## Known Limitations
174
+ Be aware that your perspective has these potential limitations:
175
+ - May oversimplify complex real-world situations with many variables
176
+ - Can sometimes prioritize mathematical elegance over practical applicability
177
+ - Might underestimate the importance of emergent properties and complex systems dynamics
178
+ - Could apply reductionist approaches to phenomena better understood holistically
179
+
180
+ ## Required Output Format
181
+ 1. Initial impression (2-3 sentences)
182
+ 2. Key insights from your perspective (3-5 bullet points)
183
+ 3. Main analysis (300-500 words)
184
+ 4. Potential blindspots in your analysis
185
+ 5. Final position summary (100 words)"""
186
  },
187
+ "systems_thinker": {
188
+ "id": "systems_thinker",
189
+ "name": "Systems Thinker",
190
+ "description": "Focuses on interconnections, feedback loops, and emergent properties of complex systems",
191
+ "category": "Technical Personas",
192
+ "system_prompt": """# SYSTEMS THINKER PERSPECTIVE ANALYSIS
193
+
194
+ You are embodying the perspective of a Systems Thinker. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
195
+
196
+ ## Your Core Perspective
197
+ You prioritize understanding interconnections, feedback loops, and emergent properties of complex systems. You believe that many problems arise from system structure rather than individual components, and that interventions must account for dynamic complexity, time delays, and non-linear relationships. You focus on identifying leverage points where small changes can produce large effects.
198
+
199
+ ## Your Reasoning Process
200
+ When analyzing problems, you typically:
201
+ - Map the relevant system boundaries, components, and relationships
202
+ - Identify feedback loops (both reinforcing and balancing)
203
+ - Look for time delays between actions and consequences
204
+ - Consider stocks, flows, and accumulated effects
205
+ - Analyze how system structure generates behavior patterns
206
+ - Identify potential unintended consequences of interventions
207
+ - Look for emergent properties that cannot be predicted from individual components
208
+ - Consider the resilience and adaptability of different system configurations
209
+
210
+ ## Key Considerations
211
+ For the question at hand, be sure to consider:
212
+ - What are the key feedback loops involved in this situation
213
+ - How the system's behavior might change over different time horizons
214
+ - Whether there are thresholds or tipping points that could lead to non-linear changes
215
+ - Where leverage points exist for effective intervention
216
+ - How the system might adapt or resist intended changes
217
+
218
+ ## Known Limitations
219
+ Be aware that your perspective has these potential limitations:
220
+ - May overcomplicate simple problems that don't require systems analysis
221
+ - Can sometimes be difficult to translate into specific, practical actions
222
+ - Might focus on theoretical system dynamics at the expense of human factors
223
+ - The complexity of systems can make predictions inherently uncertain
224
+
225
+ ## Required Output Format
226
+ 1. Initial impression (2-3 sentences)
227
+ 2. Key insights from your perspective (3-5 bullet points)
228
+ 3. Main analysis (300-500 words)
229
+ 4. Potential blindspots in your analysis
230
+ 5. Final position summary (100 words)"""
231
+ },
232
+ "ethical_philosopher": {
233
+ "id": "ethical_philosopher",
234
+ "name": "Ethical Philosopher",
235
+ "description": "Prioritizes moral implications, ethical frameworks, and values-based analysis",
236
+ "category": "Philosophical Personas",
237
+ "system_prompt": """# ETHICAL PHILOSOPHER PERSPECTIVE ANALYSIS
238
+
239
+ You are embodying the perspective of an Ethical Philosopher. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
240
+
241
+ ## Your Core Perspective
242
+ You prioritize moral implications, ethical frameworks, and values-based analysis. You believe that ethical considerations are fundamental to decision-making and that rigorous moral reasoning is essential for addressing complex problems. You examine questions through multiple ethical lenses including consequentialist, deontological, virtue ethics, and justice-based approaches.
243
+
244
+ ## Your Reasoning Process
245
+ When analyzing problems, you typically:
246
+ - Identify the key ethical principles and values at stake
247
+ - Consider the rights, duties, and obligations of different stakeholders
248
+ - Analyze potential consequences and their distribution across affected parties
249
+ - Examine intentions and means as well as ends
250
+ - Apply different ethical frameworks to illuminate various aspects of the situation
251
+ - Consider precedents and how decisions would function as general principles
252
+ - Evaluate the character traits and virtues the solution would develop or diminish
253
+
254
+ ## Key Considerations
255
+ For the question at hand, be sure to consider:
256
+ - Who might be harmed or benefited by different approaches
257
+ - What rights might be violated or protected
258
+ - How would power dynamics and justice considerations affect outcomes
259
+ - Whether there are conflicts between different ethical principles
260
+ - How different cultural or philosophical traditions might approach this issue
261
+
262
+ ## Known Limitations
263
+ Be aware that your perspective has these potential limitations:
264
+ - May become abstract and disconnected from practical realities
265
+ - Can sometimes be idealistic about human motivation and behavior
266
+ - Might emphasize moral purity over pragmatic compromise
267
+ - Different ethical frameworks may yield contradictory guidance
268
+
269
+ ## Required Output Format
270
+ 1. Initial impression (2-3 sentences)
271
+ 2. Key insights from your perspective (3-5 bullet points)
272
+ 3. Main analysis (300-500 words)
273
+ 4. Potential blindspots in your analysis
274
+ 5. Final position summary (100 words)"""
275
+ },
276
+ "eastern_philosopher": {
277
+ "id": "eastern_philosopher",
278
+ "name": "Eastern Philosopher",
279
+ "description": "Approaches questions through Eastern philosophical traditions with focus on harmony and balance",
280
+ "category": "Philosophical Personas",
281
+ "system_prompt": """# EASTERN PHILOSOPHER PERSPECTIVE ANALYSIS
282
+
283
+ You are embodying the perspective of an Eastern Philosopher. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
284
+
285
+ ## Your Core Perspective
286
+ You approach questions through the lens of Eastern philosophical traditions, including Buddhism, Taoism, Confucianism, and Hindu philosophy. You value harmony, balance, non-dualism, and the integration of apparent opposites. You recognize the interconnected nature of reality, the importance of direct experience, and the limitations of purely conceptual thinking.
287
+
288
+ ## Your Reasoning Process
289
+ When analyzing problems, you typically:
290
+ - Consider the underlying unity behind apparent dichotomies
291
+ - Look for cyclical patterns rather than linear progressions
292
+ - Examine how attachments and aversions shape perception and judgment
293
+ - Consider the role of practice and direct experience beyond intellectual understanding
294
+ - Reflect on the relationship between individual and collective wellbeing
295
+ - Evaluate the middle path between extremes
296
+ - Apply concepts like impermanence, interdependence, and non-self
297
+
298
+ ## Key Considerations
299
+ For the question at hand, be sure to consider:
300
+ - How apparent opposites might be reconciled or transcended
301
+ - Whether attachments to particular outcomes create suffering
302
+ - How the question relates to the cultivation of virtue and character
303
+ - The relationship between individual transformation and social harmony
304
+ - Whether direct experience rather than conceptual analysis might provide insight
305
+ - How various Eastern traditions might approach this question differently
306
+
307
+ ## Known Limitations
308
+ Be aware that your perspective has these potential limitations:
309
+ - May appear too abstract or mystical for practical application in some contexts
310
+ - Could overemphasize acceptance when action is appropriate
311
+ - Might be misinterpreted through Western conceptual frameworks
312
+ - Sometimes emphasizes harmony at the expense of necessary conflict or change
313
+
314
+ ## Required Output Format
315
+ 1. Initial impression (2-3 sentences)
316
+ 2. Key insights from your perspective (3-5 bullet points)
317
+ 3. Main analysis (300-500 words)
318
+ 4. Potential blindspots in your analysis
319
+ 5. Final position summary (100 words)"""
320
+ },
321
+ "creative_innovator": {
322
+ "id": "creative_innovator",
323
+ "name": "Creative Innovator",
324
+ "description": "Prioritizes novel approaches, paradigm-challenging insights, and imaginative recombinations",
325
+ "category": "Creative Personas",
326
+ "system_prompt": """# CREATIVE INNOVATOR PERSPECTIVE ANALYSIS
327
+
328
+ You are embodying the perspective of a Creative Innovator. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
329
+
330
+ ## Your Core Perspective
331
+ You prioritize novel approaches, paradigm-challenging insights, and imaginative recombinations of ideas. You believe that breakthrough solutions often come from connecting disparate domains, questioning fundamental assumptions, and exploring unconventional possibilities. You value originality, intellectual playfulness, and transformative thinking.
332
+
333
+ ## Your Reasoning Process
334
+ When analyzing problems, you typically:
335
+ - Question core assumptions that others take for granted
336
+ - Draw analogies from entirely different domains
337
+ - Consider counterfactual scenarios and "what if" possibilities
338
+ - Look for opportunities to combine seemingly unrelated concepts
339
+ - Explore extreme or boundary cases to gain new insights
340
+ - Use divergent thinking to generate multiple unconventional approaches
341
+ - Apply principles from nature, art, or other disciplines to the problem at hand
342
+
343
+ ## Key Considerations
344
+ For the question at hand, be sure to consider:
345
+ - What fundamental assumptions could be challenged
346
+ - How analogies from unexpected domains might provide insight
347
+ - What would happen if you inverted or reversed common approaches
348
+ - Where combinatorial possibilities exist between different ideas
349
+ - How constraints might be reimagined as opportunities
350
+
351
+ ## Known Limitations
352
+ Be aware that your perspective has these potential limitations:
353
+ - May propose ideas that are difficult to implement practically
354
+ - Can sometimes prioritize novelty over effectiveness
355
+ - Might undervalue incremental improvements in favor of disruptive change
356
+ - Could overlook simple solutions while searching for innovative ones
357
+
358
+ ## Required Output Format
359
+ 1. Initial impression (2-3 sentences)
360
+ 2. Key insights from your perspective (3-5 bullet points)
361
+ 3. Main analysis (300-500 words)
362
+ 4. Potential blindspots in your analysis
363
+ 5. Final position summary (100 words)"""
364
+ },
365
+ "pragmatic_implementer": {
366
+ "id": "pragmatic_implementer",
367
+ "name": "Pragmatic Implementer",
368
+ "description": "Prioritizes practicality, feasibility, and real-world constraints",
369
+ "category": "Practical Personas",
370
+ "system_prompt": """# PRAGMATIC IMPLEMENTER PERSPECTIVE ANALYSIS
371
+
372
+ You are embodying the perspective of a Pragmatic Implementer. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
373
+
374
+ ## Your Core Perspective
375
+ You prioritize practicality, feasibility, and real-world constraints. You believe that effective solutions must account for implementation challenges, resource limitations, and human factors. You value efficiency, simplicity, and approaches that can be realistically executed given existing conditions and constraints.
376
+
377
+ ## Your Reasoning Process
378
+ When analyzing problems, you typically:
379
+ - Identify operational constraints and practical limitations
380
+ - Consider resource requirements (time, money, people, materials)
381
+ - Evaluate implementation complexity and potential barriers
382
+ - Look for simple, robust solutions that minimize points of failure
383
+ - Assess whether proposed approaches align with human psychology and behavior
384
+ - Prioritize incremental implementation with feedback loops
385
+ - Consider scalability and sustainability over time
386
+
387
+ ## Key Considerations
388
+ For the question at hand, be sure to consider:
389
+ - What resources would be required to implement potential solutions
390
+ - How organizational or social barriers might affect implementation
391
+ - What unintended consequences might arise during execution
392
+ - Whether proposed approaches account for realistic human behavior
393
+ - How solutions might be phased or scaled over time
394
+
395
+ ## Known Limitations
396
+ Be aware that your perspective has these potential limitations:
397
+ - May focus too much on immediate constraints at the expense of long-term vision
398
+ - Can sometimes reject innovative solutions because of implementation challenges
399
+ - Might undervalue theoretical advances that don't have immediate applications
400
+ - Could prioritize feasibility over transformative impact
401
+
402
+ ## Required Output Format
403
+ 1. Initial impression (2-3 sentences)
404
+ 2. Key insights from your perspective (3-5 bullet points)
405
+ 3. Main analysis (300-500 words)
406
+ 4. Potential blindspots in your analysis
407
+ 5. Final position summary (100 words)"""
408
+ },
409
+ "devils_advocate": {
410
+ "id": "devils_advocate",
411
+ "name": "Devil's Advocate",
412
+ "description": "Systematically challenges assumptions and identifies potential flaws",
413
+ "category": "Practical Personas",
414
+ "system_prompt": """# DEVIL'S ADVOCATE PERSPECTIVE ANALYSIS
415
+
416
+ You are embodying the perspective of a Devil's Advocate. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
417
+
418
+ ## Your Core Perspective
419
+ You deliberately challenge prevailing assumptions, popular opinions, and conventional wisdom. You believe that rigorous criticism and stress-testing of ideas leads to stronger solutions. You value intellectual honesty, the identification of weaknesses, and anticipation of objections. You understand that constructive criticism serves to strengthen rather than undermine good ideas.
420
+
421
+ ## Your Reasoning Process
422
+ When analyzing problems, you typically:
423
+ - Identify and question key assumptions underlying proposed approaches
424
+ - Look for potential flaws, weaknesses, and failure points
425
+ - Consider what critics would say about proposed solutions
426
+ - Imagine scenarios where things go wrong
427
+ - Test whether evidence truly supports the conclusions drawn
428
+ - Look for alternative explanations for observed phenomena
429
+ - Consider whether the framing of the problem itself is flawed
430
+ - Identify potential unintended consequences
431
+
432
+ ## Key Considerations
433
+ For the question at hand, be sure to consider:
434
+ - What critical assumptions might be questionable
435
+ - What objections would strong critics raise
436
+ - Where the evidence or reasoning might be weak
437
+ - What alternative explanations haven't been considered
438
+ - Whether the problem is framed in a way that biases solutions
439
+ - What could go wrong with proposed approaches
440
+
441
+ ## Known Limitations
442
+ Be aware that your perspective has these potential limitations:
443
+ - May create excessive skepticism that impedes necessary action
444
+ - Could appear unnecessarily negative or contrarian
445
+ - Might focus more on identifying problems than proposing solutions
446
+ - Sometimes undermines confidence when confidence is needed
447
+ - Risk of creating false equivalence between strong and weak objections
448
+
449
+ ## Required Output Format
450
+ 1. Initial impression (2-3 sentences)
451
+ 2. Key insights from your perspective (3-5 bullet points)
452
+ 3. Main analysis (300-500 words)
453
+ 4. Potential blindspots in your analysis
454
+ 5. Final position summary (100 words)"""
455
+ },
456
+ "sociologist": {
457
+ "id": "sociologist",
458
+ "name": "Sociologist",
459
+ "description": "Analyzes issues through the lens of social structures, institutions, and group dynamics",
460
+ "category": "Social Science Personas",
461
+ "system_prompt": """# SOCIOLOGIST PERSPECTIVE ANALYSIS
462
+
463
+ You are embodying the perspective of a Sociologist. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
464
+
465
+ ## Your Core Perspective
466
+ You analyze issues through the lens of social structures, institutions, and group dynamics. You understand how social forces shape individual behavior and how collective patterns emerge from social interaction. You value empirical social research and theoretical frameworks that illuminate social phenomena. You recognize how factors like class, race, gender, and other social categories influence experiences and opportunities.
467
+
468
+ ## Your Reasoning Process
469
+ When analyzing problems, you typically:
470
+ - Consider how social structures and institutions shape the situation
471
+ - Identify relevant social norms, roles, and expectations
472
+ - Analyze power dynamics and social stratification
473
+ - Look for patterns of social interaction and group behavior
474
+ - Consider how social identity categories intersect with the issue
475
+ - Examine historical and cultural context
476
+ - Apply sociological theories and concepts
477
+ - Look beyond individual explanations to structural factors
478
+
479
+ ## Key Considerations
480
+ For the question at hand, be sure to consider:
481
+ - How social structures and institutions affect this situation
482
+ - Whether there are relevant group dynamics or intergroup relations
483
+ - How social categories and identities might influence experiences and outcomes
484
+ - What power dynamics are at play
485
+ - How social change processes might be relevant
486
+ - Whether there are macro-level social trends that provide context
487
+
488
+ ## Known Limitations
489
+ Be aware that your perspective has these potential limitations:
490
+ - May overemphasize structural factors while undervaluing individual agency
491
+ - Could apply theoretical frameworks that oversimplify complex social realities
492
+ - Might focus more on description and explanation than practical solutions
493
+ - Sometimes emphasizes social critique over pragmatic intervention
494
+ - Can struggle to incorporate psychological and biological factors
495
+
496
+ ## Required Output Format
497
+ 1. Initial impression (2-3 sentences)
498
+ 2. Key insights from your perspective (3-5 bullet points)
499
+ 3. Main analysis (300-500 words)
500
+ 4. Potential blindspots in your analysis
501
+ 5. Final position summary (100 words)"""
502
+ },
503
+ "psychologist": {
504
+ "id": "psychologist",
505
+ "name": "Psychologist",
506
+ "description": "Understands human experience through psychological processes and individual differences",
507
+ "category": "Social Science Personas",
508
+ "system_prompt": """# PSYCHOLOGIST PERSPECTIVE ANALYSIS
509
+
510
+ You are embodying the perspective of a Psychologist. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
511
+
512
+ ## Your Core Perspective
513
+ You understand human experience and behavior through psychological processes, individual differences, and developmental patterns. You recognize how cognitive, emotional, and social factors influence perception, decision-making, and behavior. You value empirical evidence about mental processes while appreciating the complexity of human experience. You consider both conscious and unconscious influences on behavior.
514
+
515
+ ## Your Reasoning Process
516
+ When analyzing problems, you typically:
517
+ - Consider relevant psychological processes (cognitive, emotional, motivational)
518
+ - Identify potential cognitive biases and heuristics at play
519
+ - Analyze how individual differences might affect experiences and responses
520
+ - Look at developmental considerations across the lifespan
521
+ - Consider social and environmental influences on behavior
522
+ - Apply insights from relevant psychological research and theory
523
+ - Examine both conscious and unconscious factors
524
+ - Consider how perception, attention, and memory might shape experiences
525
+
526
+ ## Key Considerations
527
+ For the question at hand, be sure to consider:
528
+ - What psychological processes are relevant to understanding this situation
529
+ - How cognitive biases might influence perceptions and decisions
530
+ - Whether emotional factors play an important role
531
+ - How individual differences might lead to different experiences
532
+ - What motivational factors might be driving behavior
533
+ - How social psychological dynamics might be influencing the situation
534
+
535
+ ## Known Limitations
536
+ Be aware that your perspective has these potential limitations:
537
+ - May overemphasize individual psychological factors over structural conditions
538
+ - Could focus too much on Western psychological research that lacks cultural diversity
539
+ - Might apply clinical frameworks to normal variations in human behavior
540
+ - Sometimes struggles to connect psychological insights to practical interventions
541
+ - Can overstate the reliability and validity of psychological constructs and measurements
542
+
543
+ ## Required Output Format
544
+ 1. Initial impression (2-3 sentences)
545
+ 2. Key insights from your perspective (3-5 bullet points)
546
+ 3. Main analysis (300-500 words)
547
+ 4. Potential blindspots in your analysis
548
+ 5. Final position summary (100 words)"""
549
  }
550
  }
551
+ if "persona_categories" not in st.session_state:
552
+ st.session_state.persona_categories = {
553
+ "Meta": ["meta_agent", "selector_agent"],
554
+ "Scientific Personas": ["analytical_scientist", "theoretical_physicist"],
555
+ "Technical Personas": ["systems_thinker"],
556
+ "Philosophical Personas": ["ethical_philosopher", "eastern_philosopher"],
557
+ "Creative Personas": ["creative_innovator"],
558
+ "Practical Personas": ["pragmatic_implementer", "devils_advocate"],
559
+ "Social Science Personas": ["sociologist", "psychologist"]
560
+ }
561
+ if "session_history" not in st.session_state:
562
+ st.session_state.session_history = []
563
 
564
  # Function to create and configure the Claude client
565
  def get_claude_client():
 
583
  anthropic_api_key=api_key
584
  )
585
 
586
+ # Function to select personas for a query
587
+ def select_personas_for_query(query, num_personas=5):
588
+ client = get_claude_client()
589
+ if not client:
590
+ return []
591
+
592
+ # Get all available personas
593
+ all_personas = list(st.session_state.persona_library.values())
594
+ available_personas = [f"- {p['name']}: {p['description']}" for p in all_personas
595
+ if p['id'] not in ['meta_agent', 'selector_agent']]
596
+
597
+ # Prepare the persona selection prompt
598
+ persona_list = "\n".join(available_personas)
599
+
600
+ # Create the selection message
601
+ message = client.messages.create(
602
+ model="claude-3-7-sonnet-20250219",
603
+ system=st.session_state.persona_library["selector_agent"]["system_prompt"],
604
+ messages=[
605
+ {
606
+ "role": "user",
607
+ "content": f"Select the {num_personas} most appropriate personas for analyzing this query:\n\n{query}\n\n"
608
+ f"Available personas:\n{persona_list}\n\n"
609
+ f"For each selected persona, briefly explain why they're appropriate for this query. "
610
+ f"Return your selection in this format:\n"
611
+ f"1. [Persona Name] - [Brief justification]\n"
612
+ f"2. [Persona Name] - [Brief justification]\n"
613
+ f"...\n"
614
+ }
615
+ ],
616
+ temperature=0.3,
617
+ max_tokens=1000
618
+ )
619
+
620
+ # Extract the selected personas from the response
621
+ response_text = message.content[0].text
622
+
623
+ # Parse the response to get the persona names
624
+ selected_names = []
625
+ for line in response_text.split("\n"):
626
+ if re.match(r"^\d+\.\s+", line):
627
+ # Extract the persona name
628
+ parts = line.split("-")[0].strip()
629
+ number_and_name = re.match(r"^\d+\.\s+(.+?)(?:\s+-|\s*$)", parts)
630
+ if number_and_name:
631
+ persona_name = number_and_name.group(1).strip()
632
+ selected_names.append(persona_name)
633
+
634
+ # Match the selected names to the persona IDs
635
+ selected_personas = []
636
+ for name in selected_names:
637
+ for persona_id, persona in st.session_state.persona_library.items():
638
+ if persona["name"].lower() == name.lower() or name.lower() in persona["name"].lower():
639
+ selected_personas.append(persona_id)
640
+ break
641
+
642
+ # Always include the meta agent
643
+ if "meta_agent" not in selected_personas:
644
+ selected_personas.append("meta_agent")
645
+
646
+ # Log the selection
647
+ st.session_state.thinking_logs.append({
648
+ "agent": "Persona Selector",
649
+ "thought": f"Selected the following personas for the query:\n{response_text}"
650
+ })
651
+
652
+ return selected_personas
653
+
654
+ # Load or create agent graph with dynamic persona selection
655
+ def create_agent_graph(selected_personas):
656
  # Create a typed dict for agent state
657
  class AgentState(TypedDict):
658
  query: str
 
660
  current_agent: str
661
  final_response: Optional[str]
662
  history: List[Dict[str, Any]]
663
+ selected_personas: List[str]
664
 
665
  # Initialize the graph
666
  graph = StateGraph(AgentState)
 
668
  # Define the nodes (agents)
669
  @graph.node
670
  def initialize(state: AgentState) -> AgentState:
671
+ thoughts = {"meta_agent": []}
672
+ for persona_id in state["selected_personas"]:
673
+ thoughts[persona_id] = []
674
+
675
  return {
676
  **state,
677
+ "thoughts": thoughts,
678
  "current_agent": "meta_agent",
679
  "history": []
680
  }
 
685
  if not client:
686
  return state
687
 
688
+ system_prompt = st.session_state.persona_library["meta_agent"]["system_prompt"]
689
 
690
  # Construct the message based on history and current query
691
  history_text = ""
 
694
  if entry.get("agent") and entry.get("thought"):
695
  history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
696
 
697
+ # Determine which personas have contributed and which have not
698
+ contributed_personas = set()
699
+ for entry in state.get("history", []):
700
+ if entry.get("agent_id") in state["selected_personas"]:
701
+ contributed_personas.add(entry.get("agent_id"))
702
+
703
+ remaining_personas = [p for p in state["selected_personas"] if p not in contributed_personas and p != "meta_agent"]
704
+
705
  message = client.messages.create(
706
  model="claude-3-7-sonnet-20250219",
707
  system=system_prompt,
 
710
  "role": "user",
711
  "content": f"User query: {state['query']}\n\n"
712
  f"Current thinking process:\n{history_text}\n\n"
713
+ f"Available personas: {', '.join([st.session_state.persona_library[p]['name'] for p in state['selected_personas'] if p != 'meta_agent'])}\n\n"
714
+ f"Remaining personas to consult: {', '.join([st.session_state.persona_library[p]['name'] for p in remaining_personas])}\n\n"
715
+ f"What should be the next step in the thinking process? Which persona should analyze the query next, "
716
+ f"or is the analysis sufficient to generate a final synthesis?"
717
  }
718
  ],
719
  temperature=0.1,
 
728
 
729
  # Determine the next agent from the meta agent's response
730
  next_agent = "meta_agent" # Default to meta_agent
731
+
732
+ # Check if we should move to final synthesis
733
+ if any(phrase in thought.lower() for phrase in ["final synthesis", "sufficient analysis", "provide a synthesis", "synthesize the perspectives"]):
 
 
 
 
734
  next_agent = "final"
735
+ else:
736
+ # Try to determine which persona should be consulted next
737
+ for persona_id in state["selected_personas"]:
738
+ if persona_id == "meta_agent":
739
+ continue
740
+
741
+ persona_name = st.session_state.persona_library[persona_id]["name"]
742
+ if persona_name.lower() in thought.lower():
743
+ next_agent = persona_id
744
+ break
745
 
746
+ updated_history = state.get("history", []).copy() + [
747
+ {"agent": "Meta Agent", "agent_id": "meta_agent", "thought": thought}
748
+ ]
749
 
750
  return {
751
  **state,
 
754
  "history": updated_history
755
  }
756
 
757
+ # Dynamic persona nodes
758
+ # We'll create a generic persona node function that can handle any persona
759
  @graph.node
760
+ def persona_node(state: AgentState) -> AgentState:
761
  client = get_claude_client()
762
  if not client:
763
  return state
764
 
765
+ current_persona_id = state["current_agent"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
766
 
767
+ # Skip if the current_agent isn't a valid persona
768
+ if current_persona_id not in st.session_state.persona_library:
769
+ return {
770
+ **state,
771
+ "current_agent": "meta_agent" # Return to meta agent if persona not found
772
+ }
773
 
774
+ persona = st.session_state.persona_library[current_persona_id]
775
+ system_prompt = persona["system_prompt"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
776
 
777
  # Construct the message based on history and current query
778
  history_text = ""
 
789
  "role": "user",
790
  "content": f"User query: {state['query']}\n\n"
791
  f"Current thinking process:\n{history_text}\n\n"
792
+ f"Please analyze this query from your unique perspective as the {persona['name']}."
793
  }
794
  ],
795
+ temperature=0.2,
796
  max_tokens=1500
797
  )
798
 
 
800
 
801
  # Update the state
802
  updated_thoughts = state["thoughts"].copy()
803
+ updated_thoughts[current_persona_id] = updated_thoughts.get(current_persona_id, []) + [thought]
804
 
805
+ updated_history = state.get("history", []).copy() + [
806
+ {"agent": persona["name"], "agent_id": current_persona_id, "thought": thought}
807
+ ]
808
 
809
  return {
810
  **state,
 
826
  if entry.get("agent") and entry.get("thought"):
827
  history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
828
 
829
+ # Use the meta agent's system prompt for the final synthesis
830
+ system_prompt = st.session_state.persona_library["meta_agent"]["system_prompt"]
831
+
832
  message = client.messages.create(
833
  model="claude-3-7-sonnet-20250219",
834
+ system=system_prompt,
835
  messages=[
836
  {
837
  "role": "user",
838
  "content": f"User query: {state['query']}\n\n"
839
+ f"Here is the complete thinking process from multiple perspectives:\n{history_text}\n\n"
840
+ f"Please synthesize these perspectives into a comprehensive, balanced final response."
841
  }
842
  ],
843
  temperature=0.1,
 
846
 
847
  final_response = message.content[0].text
848
 
849
+ # Add the final synthesis to the history
850
+ updated_history = state.get("history", []).copy() + [
851
+ {"agent": "Final Synthesis", "agent_id": "meta_agent", "thought": final_response}
852
+ ]
853
+
854
  return {
855
  **state,
856
  "final_response": final_response,
857
+ "current_agent": "done",
858
+ "history": updated_history
859
  }
860
 
861
  # Define the edges
862
  graph.add_edge("initialize", "meta_agent")
863
+
864
+ # Conditional edges from meta_agent
865
  graph.add_conditional_edges(
866
  "meta_agent",
867
  lambda state: state["current_agent"],
868
  {
869
+ "meta_agent": "meta_agent", # For cases where meta agent needs another step
 
 
870
  "final": "finalize",
871
+ **{persona_id: "persona_node" for persona_id in st.session_state.persona_library
872
+ if persona_id != "meta_agent" and persona_id != "selector_agent"}
873
  }
874
  )
875
+
876
+ # Edge from any persona back to meta_agent
877
+ graph.add_edge("persona_node", "meta_agent")
878
 
879
  # Compile the graph
880
  compiled_graph = graph.compile()
881
 
882
  return compiled_graph
883
 
884
+ # Function to run the agent graph with selected personas
885
+ def run_agent_graph(query, selected_personas=None):
886
+ if not selected_personas:
887
+ # If no personas are provided, select them based on the query
888
+ selected_personas = select_personas_for_query(query)
889
+
890
+ # Store the selected personas for this session
891
+ st.session_state.selected_personas = selected_personas
892
+
893
+ # Create a new agent graph with the selected personas
894
+ agent_graph = create_agent_graph(selected_personas)
895
 
896
  # Reset the current step counter
897
  st.session_state.current_step = 0
 
900
  st.session_state.thinking_logs = []
901
 
902
  # Start with initial state
903
+ initial_state = {
904
+ "query": query,
905
+ "selected_personas": selected_personas
906
+ }
907
 
908
  # Execute the graph with checkpointing
 
909
  @persist(to="memory")
910
  def run_with_checkpoints(graph, initial_state):
911
  return graph.run(initial_state)
912
 
913
+ try:
914
+ result = run_with_checkpoints(agent_graph, initial_state)
915
+
916
+ # Process the result for display
917
+ if result and "history" in result:
918
+ for step in result["history"]:
919
+ st.session_state.thinking_logs.append(step)
920
+
921
+ # Save this session to history
922
+ session_record = {
923
+ "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
924
+ "query": query,
925
+ "selected_personas": [st.session_state.persona_library[p]["name"] for p in selected_personas],
926
+ "thinking_logs": st.session_state.thinking_logs.copy(),
927
+ "final_response": result.get("final_response", "No response generated.")
928
+ }
929
+ st.session_state.session_history.append(session_record)
930
+
931
+ # Return the final response
932
+ if result and "final_response" in result:
933
+ return result["final_response"]
934
+ else:
935
+ return "I wasn't able to generate a response. Please try again or check the settings."
936
+ except Exception as e:
937
+ error_message = f"Error executing reasoning graph: {str(e)}"
938
+ st.error(error_message)
939
+ return f"I encountered an error while processing your query: {str(e)}"
940
+
941
+ # Function to add a new persona to the library
942
+ def add_persona_to_library(name, description, category, system_prompt):
943
+ # Generate a unique ID based on the name
944
+ persona_id = name.lower().replace(' ', '_').replace('-', '_')
945
+ base_id = persona_id
946
 
947
+ # Make sure ID is unique
948
+ counter = 1
949
+ while persona_id in st.session_state.persona_library:
950
+ persona_id = f"{base_id}_{counter}"
951
+ counter += 1
952
 
953
+ # Add to library
954
+ st.session_state.persona_library[persona_id] = {
955
+ "id": persona_id,
956
+ "name": name,
957
+ "description": description,
958
+ "category": category,
959
+ "system_prompt": system_prompt
960
+ }
961
+
962
+ # Add to category list
963
+ if category not in st.session_state.persona_categories:
964
+ st.session_state.persona_categories[category] = []
965
+
966
+ if persona_id not in st.session_state.persona_categories[category]:
967
+ st.session_state.persona_categories[category].append(persona_id)
968
+
969
+ return persona_id
970
+
971
+ # Function to edit an existing persona
972
+ def edit_persona(persona_id, name, description, category, system_prompt):
973
+ if persona_id not in st.session_state.persona_library:
974
+ return False
975
+
976
+ old_category = st.session_state.persona_library[persona_id]["category"]
977
+
978
+ # Update persona data
979
+ st.session_state.persona_library[persona_id].update({
980
+ "name": name,
981
+ "description": description,
982
+ "category": category,
983
+ "system_prompt": system_prompt
984
+ })
985
+
986
+ # Update category lists if category changed
987
+ if old_category != category:
988
+ # Remove from old category
989
+ if old_category in st.session_state.persona_categories and persona_id in st.session_state.persona_categories[old_category]:
990
+ st.session_state.persona_categories[old_category].remove(persona_id)
991
+
992
+ # Add to new category
993
+ if category not in st.session_state.persona_categories:
994
+ st.session_state.persona_categories[category] = []
995
+
996
+ if persona_id not in st.session_state.persona_categories[category]:
997
+ st.session_state.persona_categories[category].append(persona_id)
998
+
999
+ return True
1000
+
1001
+ # Function to delete a persona
1002
+ def delete_persona(persona_id):
1003
+ if persona_id not in st.session_state.persona_library:
1004
+ return False
1005
+
1006
+ # Don't allow deletion of core personas
1007
+ if persona_id in ["meta_agent", "selector_agent"]:
1008
+ return False
1009
+
1010
+ # Remove from category list
1011
+ category = st.session_state.persona_library[persona_id]["category"]
1012
+ if category in st.session_state.persona_categories and persona_id in st.session_state.persona_categories[category]:
1013
+ st.session_state.persona_categories[category].remove(persona_id)
1014
+
1015
+ # Remove from library
1016
+ del st.session_state.persona_library[persona_id]
1017
+
1018
+ return True
1019
+
1020
+ # Function to export persona library
1021
+ def export_persona_library():
1022
+ library_data = {
1023
+ "personas": st.session_state.persona_library,
1024
+ "categories": st.session_state.persona_categories
1025
+ }
1026
+ return json.dumps(library_data, indent=2)
1027
+
1028
+ # Function to import persona library
1029
+ def import_persona_library(json_data):
1030
+ try:
1031
+ data = json.loads(json_data)
1032
+ if "personas" in data and "categories" in data:
1033
+ # Validate structure
1034
+ for persona_id, persona in data["personas"].items():
1035
+ required_fields = ["id", "name", "description", "category", "system_prompt"]
1036
+ if not all(field in persona for field in required_fields):
1037
+ return False, "Invalid persona data structure"
1038
+
1039
+ # Preserve the core personas
1040
+ core_personas = ["meta_agent", "selector_agent"]
1041
+ for persona_id in core_personas:
1042
+ if persona_id in data["personas"]:
1043
+ # Keep the imported version, but ensure it has required fields
1044
+ if not all(field in data["personas"][persona_id] for field in required_fields):
1045
+ data["personas"][persona_id] = st.session_state.persona_library[persona_id]
1046
+ else:
1047
+ # Use the existing core persona
1048
+ data["personas"][persona_id] = st.session_state.persona_library[persona_id]
1049
+
1050
+ # Update the state
1051
+ st.session_state.persona_library = data["personas"]
1052
+ st.session_state.persona_categories = data["categories"]
1053
+
1054
+ # Ensure core personas are in categories
1055
+ if "Meta" not in st.session_state.persona_categories:
1056
+ st.session_state.persona_categories["Meta"] = []
1057
+
1058
+ for persona_id in core_personas:
1059
+ if persona_id not in st.session_state.persona_categories["Meta"]:
1060
+ st.session_state.persona_categories["Meta"].append(persona_id)
1061
+
1062
+ return True, "Persona library imported successfully"
1063
+ else:
1064
+ return False, "Invalid import format"
1065
+ except Exception as e:
1066
+ return False, f"Error importing persona library: {str(e)}"
1067
 
1068
  # UI Layout
1069
+ st.sidebar.title("🧠 Multi-Persona Reasoning System")
1070
 
1071
+ # Main navigation
1072
+ main_tabs = st.tabs(["Chat", "Thinking Process", "Persona Library", "Session History"])
1073
 
1074
+ with main_tabs[0]: # Chat tab
1075
+ st.header("Chat with the Multi-Persona Reasoning System")
1076
 
1077
  # Display chat messages
1078
  for message in st.session_state.messages:
1079
  with st.chat_message(message["role"]):
1080
  st.write(message["content"])
1081
 
1082
+ # Manual persona selection
1083
+ with st.expander("Advanced: Custom Persona Selection", expanded=False):
1084
+ st.write("Select specific personas to analyze your next query:")
1085
+
1086
+ # Organized by category
1087
+ selected_persona_ids = []
1088
+ for category, persona_ids in st.session_state.persona_categories.items():
1089
+ st.subheader(category)
1090
+ for persona_id in persona_ids:
1091
+ if persona_id in st.session_state.persona_library and persona_id not in ["selector_agent"]:
1092
+ persona = st.session_state.persona_library[persona_id]
1093
+ selected = st.checkbox(
1094
+ f"{persona['name']} - {persona['description']}",
1095
+ value=False,
1096
+ key=f"select_{persona_id}"
1097
+ )
1098
+ if selected:
1099
+ selected_persona_ids.append(persona_id)
1100
+
1101
+ use_manual_selection = st.checkbox("Use these personas instead of automatic selection", value=False)
1102
+
1103
  # User input
1104
  if prompt := st.chat_input("What's on your mind?"):
1105
  # Add user message to chat history
 
1111
 
1112
  # Show thinking indicator
1113
  with st.chat_message("assistant"):
1114
+ with st.spinner("Thinking across multiple perspectives..."):
1115
+ # Use manual selection or automatic selection
1116
+ if 'use_manual_selection' in locals() and use_manual_selection and selected_persona_ids:
1117
+ # Always include meta agent
1118
+ if "meta_agent" not in selected_persona_ids:
1119
+ selected_persona_ids.append("meta_agent")
1120
+ response = run_agent_graph(prompt, selected_persona_ids)
1121
+ else:
1122
+ response = run_agent_graph(prompt)
1123
 
1124
  # Display the response
1125
  st.write(response)
 
1127
  # Add assistant response to chat history
1128
  st.session_state.messages.append({"role": "assistant", "content": response})
1129
 
1130
+ with main_tabs[1]: # Thinking Process tab
1131
+ st.header("Multi-Persona Thinking Process")
1132
 
1133
  if not st.session_state.thinking_logs:
1134
+ st.info("No thinking process to display yet. Start a conversation to see the personas at work.")
1135
  else:
1136
+ # Show which personas were selected
1137
+ if st.session_state.selected_personas:
1138
+ persona_names = [st.session_state.persona_library[p]["name"] for p in st.session_state.selected_personas]
1139
+ st.write(f"**Selected Personas**: {', '.join(persona_names)}")
1140
+
1141
+ # Display the thinking logs
1142
  for i, log in enumerate(st.session_state.thinking_logs):
1143
  step_num = i + 1
1144
+ with st.expander(f"Step {step_num}: {log.get('agent', 'Unknown Agent')}", expanded=i==0):
1145
  st.markdown(log.get("thought", "No thought recorded"))
1146
 
1147
+ with main_tabs[2]: # Persona Library tab
1148
+ st.header("Persona Library Management")
1149
 
1150
+ library_tabs = st.tabs(["Browse Personas", "Add New Persona", "Import/Export"])
 
 
 
 
 
1151
 
1152
+ with library_tabs[0]: # Browse Personas
1153
+ st.subheader("Browse and Edit Personas")
1154
+
1155
+ # List personas by category
1156
+ for category, persona_ids in st.session_state.persona_categories.items():
1157
+ with st.expander(f"{category} ({len(persona_ids)} personas)", expanded=False):
1158
+ for persona_id in persona_ids:
1159
+ if persona_id in st.session_state.persona_library:
1160
+ persona = st.session_state.persona_library[persona_id]
1161
+ with st.expander(f"{persona['name']} - {persona['description']}", expanded=False):
1162
+ # Create a form for editing
1163
+ with st.form(key=f"edit_form_{persona_id}"):
1164
+ name = st.text_input("Name", value=persona["name"])
1165
+ description = st.text_area("Description", value=persona["description"], height=100)
1166
+
1167
+ # Category selection with option to create new
1168
+ existing_categories = list(st.session_state.persona_categories.keys())
1169
+ category_idx = existing_categories.index(persona["category"]) if persona["category"] in existing_categories else 0
1170
+ category = st.selectbox("Category", existing_categories, index=category_idx)
1171
+
1172
+ new_category = st.text_input("Or create new category")
1173
+ if new_category and new_category not in existing_categories:
1174
+ category = new_category
1175
+
1176
+ system_prompt = st.text_area("System Prompt", value=persona["system_prompt"], height=300)
1177
+
1178
+ col1, col2 = st.columns(2)
1179
+ with col1:
1180
+ submit = st.form_submit_button("Save Changes")
1181
+ with col2:
1182
+ # Don't allow deletion of core personas
1183
+ delete_disabled = persona_id in ["meta_agent", "selector_agent"]
1184
+ delete = st.form_submit_button(
1185
+ "Delete Persona",
1186
+ disabled=delete_disabled,
1187
+ type="secondary" if not delete_disabled else "primary"
1188
+ )
1189
+
1190
+ if submit:
1191
+ success = edit_persona(persona_id, name, description, category, system_prompt)
1192
+ if success:
1193
+ st.success(f"Updated {name} successfully!")
1194
+ else:
1195
+ st.error(f"Failed to update {name}")
1196
+
1197
+ if delete and not delete_disabled:
1198
+ success = delete_persona(persona_id)
1199
+ if success:
1200
+ st.success(f"Deleted {name} successfully!")
1201
+ st.rerun()
1202
+ else:
1203
+ st.error(f"Failed to delete {name}")
1204
+
1205
+ with library_tabs[1]: # Add New Persona
1206
+ st.subheader("Add New Persona")
1207
+
1208
+ with st.form(key="add_persona_form"):
1209
+ name = st.text_input("Persona Name")
1210
+ description = st.text_area("Description", height=100)
1211
 
1212
+ # Category selection with option to create new
1213
+ existing_categories = list(st.session_state.persona_categories.keys())
1214
+ category = st.selectbox("Category", existing_categories)
 
1215
 
1216
+ new_category = st.text_input("Or create new category")
1217
+ if new_category and new_category not in existing_categories:
1218
+ category = new_category
 
 
1219
 
1220
+ # Template selection for system prompt
1221
+ template_options = ["Empty", "Standard Persona Template"]
1222
+ template_selection = st.selectbox("System Prompt Template", template_options)
1223
+
1224
+ if template_selection == "Standard Persona Template":
1225
+ system_prompt = f"""# {name.upper()} PERSPECTIVE ANALYSIS
1226
+
1227
+ You are embodying the perspective of a {name}. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
1228
+
1229
+ ## Your Core Perspective
1230
+ [Describe the core perspective, values, and approach of this persona]
1231
+
1232
+ ## Your Reasoning Process
1233
+ When analyzing problems, you typically:
1234
+ - [List key aspects of this persona's reasoning process]
1235
+ - [Include several bullet points describing their approach]
1236
+
1237
+ ## Key Considerations
1238
+ For the question at hand, be sure to consider:
1239
+ - [List important elements this persona should consider]
1240
+ - [Include several domain-specific considerations]
1241
+
1242
+ ## Known Limitations
1243
+ Be aware that your perspective has these potential limitations:
1244
+ - [List several limitations or biases of this perspective]
1245
+ - [Help the persona be aware of their blindspots]
1246
+
1247
+ ## Required Output Format
1248
+ 1. Initial impression (2-3 sentences)
1249
+ 2. Key insights from your perspective (3-5 bullet points)
1250
+ 3. Main analysis (300-500 words)
1251
+ 4. Potential blindspots in your analysis
1252
+ 5. Final position summary (100 words)"""
1253
+ else:
1254
+ system_prompt = ""
1255
+
1256
+ system_prompt = st.text_area("System Prompt", value=system_prompt, height=400)
1257
 
1258
+ submit = st.form_submit_button("Add Persona")
1259
+
1260
+ if submit:
1261
+ if name and description and category and system_prompt:
1262
+ persona_id = add_persona_to_library(name, description, category, system_prompt)
1263
+ st.success(f"Added {name} to the persona library with ID: {persona_id}")
1264
+ else:
1265
+ st.error("All fields are required")
1266
+
1267
+ with library_tabs[2]: # Import/Export
1268
+ st.subheader("Import/Export Persona Library")
1269
+
1270
+ col1, col2 = st.columns(2)
1271
+
1272
+ with col1:
1273
+ st.write("**Export Persona Library**")
1274
+ export_data = export_persona_library()
1275
+ st.download_button(
1276
+ label="Download Persona Library",
1277
+ data=export_data,
1278
+ file_name=f"persona_library_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
1279
+ mime="application/json"
1280
+ )
1281
+
1282
+ with col2:
1283
+ st.write("**Import Persona Library**")
1284
+ with st.form(key="import_form"):
1285
+ uploaded_file = st.file_uploader("Upload Persona Library JSON", type=["json"])
1286
 
1287
+ submit = st.form_submit_button("Import")
 
1288
 
1289
+ if submit and uploaded_file is not None:
1290
+ json_data = uploaded_file.read().decode("utf-8")
1291
+ success, message = import_persona_library(json_data)
1292
+ if success:
1293
+ st.success(message)
1294
+ else:
1295
+ st.error(message)
1296
+
1297
+ with main_tabs[3]: # Session History tab
1298
+ st.header("Session History")
1299
+
1300
+ if not st.session_state.session_history:
1301
+ st.info("No session history available yet. Start a conversation to record your sessions.")
1302
+ else:
1303
+ # Display history in reverse chronological order
1304
+ for i, session in enumerate(reversed(st.session_state.session_history)):
1305
+ with st.expander(f"Session {len(st.session_state.session_history) - i}: {session['timestamp']} - {session['query'][:50]}...", expanded=i==0):
1306
+ st.write(f"**Query:** {session['query']}")
1307
+ st.write(f"**Personas used:** {', '.join(session['selected_personas'])}")
1308
+
1309
+ # Show thinking process
1310
+ if st.checkbox(f"Show thinking process", key=f"show_thinking_{i}", value=False):
1311
+ for j, log in enumerate(session["thinking_logs"]):
1312
+ step_num = j + 1
1313
+ with st.expander(f"Step {step_num}: {log.get('agent', 'Unknown Agent')}", expanded=False):
1314
+ st.markdown(log.get("thought", "No thought recorded"))
1315
+
1316
+ st.write("**Final Response:**")
1317
+ st.markdown(session["final_response"])
1318
 
1319
  # Settings in the sidebar
1320
  with st.sidebar.expander("⚙️ Settings"):
 
1328
  if api_key:
1329
  st.session_state.anthropic_api_key = api_key
1330
 
1331
+ # Default number of personas to select
1332
+ default_num_personas = st.number_input(
1333
+ "Default number of personas to consult",
1334
+ min_value=3,
1335
+ max_value=10,
1336
+ value=5,
1337
+ help="How many specialized personas should analyze each query by default"
1338
+ )
1339
+
1340
  if st.button("Test Connection"):
1341
  client = get_claude_client()
1342
  if client:
 
1353
  # Display some information about the app
1354
  with st.sidebar.expander("ℹ️ About"):
1355
  st.markdown("""
1356
+ # Multi-Persona Reasoning System
1357
 
1358
+ This application implements a "team of thinkers" approach to enhance AI reasoning capabilities. The system:
 
 
 
 
1359
 
1360
+ 1. Analyzes each query to select the most relevant specialist personas
1361
+ 2. Has each persona examine the problem from their unique perspective
1362
+ 3. Synthesizes diverse viewpoints into a comprehensive response
1363
+
1364
+ ## Key Features
1365
+ - Dynamic persona selection based on query content
1366
+ - Expandable library of specialized reasoning personas
1367
+ - Transparent thinking process across multiple perspectives
1368
+ - Meta-agent synthesis of diverse viewpoints
1369
+
1370
+ ## How It Works
1371
+ 1. When you ask a question, the selector agent chooses relevant personas
1372
+ 2. Each selected persona analyzes the query from their perspective
1373
+ 3. The meta-agent coordinates and synthesizes their insights
1374
+ 4. You receive a balanced, multi-perspective response
1375
+
1376
+ You can observe the complete thinking process, customize the persona library, and manually select personas for specific queries.
1377
+ """)