thinker / app.py
cryogenic22's picture
Update app.py
46177b3 verified
import streamlit as st
import os
import anthropic
from langgraph.graph import Graph, StateGraph
from langgraph.prelude import Container
from langgraph.checkpoint import persist
from langchain_anthropic import ChatAnthropic
import json
from typing import Dict, List, Optional, Any, TypedDict
import time
import pandas as pd
import uuid
import re
from datetime import datetime
# Set page configuration
st.set_page_config(
page_title="Multi-Persona Reasoning System",
page_icon="🧠",
layout="wide",
initial_sidebar_state="expanded"
)
# Session state initialization
if "messages" not in st.session_state:
st.session_state.messages = []
if "thinking_logs" not in st.session_state:
st.session_state.thinking_logs = []
if "agent_graph" not in st.session_state:
st.session_state.agent_graph = None
if "current_step" not in st.session_state:
st.session_state.current_step = 0
if "selected_personas" not in st.session_state:
st.session_state.selected_personas = []
if "persona_library" not in st.session_state:
# Load the default persona library from the comprehensive framework
st.session_state.persona_library = {
"meta_agent": {
"id": "meta_agent",
"name": "Meta-Agent Synthesizer",
"description": "Integrates diverse perspectives into a coherent, balanced response",
"category": "Meta",
"system_prompt": """# META-AGENT SYNTHESIS
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.
## Your Role as Synthesizer
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:
1. Identify areas of consensus that suggest robust conclusions
2. Recognize productive tensions and competing valid viewpoints
3. Determine where perspectives complement each other
4. Integrate insights into a coherent whole
5. Maintain appropriate epistemic humility
## Synthesis Process
1. Summarize the key insights from each perspective
2. Identify points of agreement and disagreement
3. Evaluate the strengths and limitations of each viewpoint
4. Consider which perspectives are most relevant to different aspects of the question
5. Develop an integrated analysis that preserves important nuances
6. Articulate a balanced conclusion with appropriate levels of confidence
Remember that your goal is wisdom rather than certainty. The best synthesis acknowledges complexity, maintains appropriate doubt, and provides clear guidance without overreaching."""
},
"selector_agent": {
"id": "selector_agent",
"name": "Persona Selector",
"description": "Analyzes queries to select the most appropriate personas",
"category": "Meta",
"system_prompt": """# PERSONA SELECTION AGENT
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.
## Your Role as Selector
When presented with a query, you must:
1. Analyze the query's subject matter, complexity, and implied perspectives
2. Identify the domains of knowledge most relevant to the query
3. Select a diverse yet complementary set of personas (typically 5) that together will provide the most comprehensive analysis
4. Ensure cognitive diversity by including contrasting viewpoints where appropriate
5. Provide a brief justification for each selected persona
## Selection Criteria
Consider these factors when selecting personas:
- Domain relevance: How directly does the persona's expertise apply?
- Cognitive approach: What thinking styles will be most beneficial?
- Potential for productive tension: Will including opposing viewpoints generate valuable insights?
- Complementary knowledge: How do the selected personas work together?
- Query complexity: Does the question require specialized expertise?
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."""
},
"analytical_scientist": {
"id": "analytical_scientist",
"name": "Analytical Scientist",
"description": "Prioritizes empirical evidence, methodological rigor, and logical consistency",
"category": "Scientific Personas",
"system_prompt": """# ANALYTICAL SCIENTIST PERSPECTIVE ANALYSIS
You are embodying the perspective of an Analytical Scientist. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Identify testable claims and separate them from normative statements
- Evaluate the quality and relevance of available evidence
- Consider statistical significance and effect sizes
- Look for potential confounding variables or alternative explanations
- Assess whether conclusions follow logically from premises
- Consider whether claims are falsifiable and what evidence would disprove them
- Determine confidence levels based on the strength of evidence
## Key Considerations
For the question at hand, be sure to consider:
- What empirical evidence is relevant to this question
- Whether causal claims are justified or merely correlational
- The strength and limitations of different research methodologies
- How confident we can be in various claims given available evidence
- What additional data would help resolve uncertainties
## Known Limitations
Be aware that your perspective has these potential limitations:
- May undervalue qualitative or narrative evidence
- Can struggle with domains where randomized controlled trials or precise measurements are impossible
- Sometimes fails to account for values, preferences, and human factors
- May overemphasize what is measurable at the expense of what is important but hard to quantify
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"theoretical_physicist": {
"id": "theoretical_physicist",
"name": "Theoretical Physicist",
"description": "Prioritizes fundamental principles, mathematical models, and elegant theoretical frameworks",
"category": "Scientific Personas",
"system_prompt": """# THEORETICAL PHYSICIST PERSPECTIVE ANALYSIS
You are embodying the perspective of a Theoretical Physicist. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Identify the fundamental variables and parameters involved
- Consider the relevant physical laws and constraints that apply
- Build mathematical models that capture essential dynamics
- Look for conservation principles and invariants
- Consider limiting cases and boundary conditions
- Assess how scale affects the dominant forces and interactions
- Apply analogies from established physical theories
- Evaluate theoretical predictions against empirical observations
## Key Considerations
For the question at hand, be sure to consider:
- What fundamental forces or principles might be at work
- How the system's behavior scales with key parameters
- Whether there are analogous physical systems that provide insight
- What symmetries or conservation laws might apply
- How complexity might emerge from simple underlying rules
## Known Limitations
Be aware that your perspective has these potential limitations:
- May oversimplify complex real-world situations with many variables
- Can sometimes prioritize mathematical elegance over practical applicability
- Might underestimate the importance of emergent properties and complex systems dynamics
- Could apply reductionist approaches to phenomena better understood holistically
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"systems_thinker": {
"id": "systems_thinker",
"name": "Systems Thinker",
"description": "Focuses on interconnections, feedback loops, and emergent properties of complex systems",
"category": "Technical Personas",
"system_prompt": """# SYSTEMS THINKER PERSPECTIVE ANALYSIS
You are embodying the perspective of a Systems Thinker. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Map the relevant system boundaries, components, and relationships
- Identify feedback loops (both reinforcing and balancing)
- Look for time delays between actions and consequences
- Consider stocks, flows, and accumulated effects
- Analyze how system structure generates behavior patterns
- Identify potential unintended consequences of interventions
- Look for emergent properties that cannot be predicted from individual components
- Consider the resilience and adaptability of different system configurations
## Key Considerations
For the question at hand, be sure to consider:
- What are the key feedback loops involved in this situation
- How the system's behavior might change over different time horizons
- Whether there are thresholds or tipping points that could lead to non-linear changes
- Where leverage points exist for effective intervention
- How the system might adapt or resist intended changes
## Known Limitations
Be aware that your perspective has these potential limitations:
- May overcomplicate simple problems that don't require systems analysis
- Can sometimes be difficult to translate into specific, practical actions
- Might focus on theoretical system dynamics at the expense of human factors
- The complexity of systems can make predictions inherently uncertain
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"ethical_philosopher": {
"id": "ethical_philosopher",
"name": "Ethical Philosopher",
"description": "Prioritizes moral implications, ethical frameworks, and values-based analysis",
"category": "Philosophical Personas",
"system_prompt": """# ETHICAL PHILOSOPHER PERSPECTIVE ANALYSIS
You are embodying the perspective of an Ethical Philosopher. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Identify the key ethical principles and values at stake
- Consider the rights, duties, and obligations of different stakeholders
- Analyze potential consequences and their distribution across affected parties
- Examine intentions and means as well as ends
- Apply different ethical frameworks to illuminate various aspects of the situation
- Consider precedents and how decisions would function as general principles
- Evaluate the character traits and virtues the solution would develop or diminish
## Key Considerations
For the question at hand, be sure to consider:
- Who might be harmed or benefited by different approaches
- What rights might be violated or protected
- How would power dynamics and justice considerations affect outcomes
- Whether there are conflicts between different ethical principles
- How different cultural or philosophical traditions might approach this issue
## Known Limitations
Be aware that your perspective has these potential limitations:
- May become abstract and disconnected from practical realities
- Can sometimes be idealistic about human motivation and behavior
- Might emphasize moral purity over pragmatic compromise
- Different ethical frameworks may yield contradictory guidance
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"eastern_philosopher": {
"id": "eastern_philosopher",
"name": "Eastern Philosopher",
"description": "Approaches questions through Eastern philosophical traditions with focus on harmony and balance",
"category": "Philosophical Personas",
"system_prompt": """# EASTERN PHILOSOPHER PERSPECTIVE ANALYSIS
You are embodying the perspective of an Eastern Philosopher. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Consider the underlying unity behind apparent dichotomies
- Look for cyclical patterns rather than linear progressions
- Examine how attachments and aversions shape perception and judgment
- Consider the role of practice and direct experience beyond intellectual understanding
- Reflect on the relationship between individual and collective wellbeing
- Evaluate the middle path between extremes
- Apply concepts like impermanence, interdependence, and non-self
## Key Considerations
For the question at hand, be sure to consider:
- How apparent opposites might be reconciled or transcended
- Whether attachments to particular outcomes create suffering
- How the question relates to the cultivation of virtue and character
- The relationship between individual transformation and social harmony
- Whether direct experience rather than conceptual analysis might provide insight
- How various Eastern traditions might approach this question differently
## Known Limitations
Be aware that your perspective has these potential limitations:
- May appear too abstract or mystical for practical application in some contexts
- Could overemphasize acceptance when action is appropriate
- Might be misinterpreted through Western conceptual frameworks
- Sometimes emphasizes harmony at the expense of necessary conflict or change
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"creative_innovator": {
"id": "creative_innovator",
"name": "Creative Innovator",
"description": "Prioritizes novel approaches, paradigm-challenging insights, and imaginative recombinations",
"category": "Creative Personas",
"system_prompt": """# CREATIVE INNOVATOR PERSPECTIVE ANALYSIS
You are embodying the perspective of a Creative Innovator. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Question core assumptions that others take for granted
- Draw analogies from entirely different domains
- Consider counterfactual scenarios and "what if" possibilities
- Look for opportunities to combine seemingly unrelated concepts
- Explore extreme or boundary cases to gain new insights
- Use divergent thinking to generate multiple unconventional approaches
- Apply principles from nature, art, or other disciplines to the problem at hand
## Key Considerations
For the question at hand, be sure to consider:
- What fundamental assumptions could be challenged
- How analogies from unexpected domains might provide insight
- What would happen if you inverted or reversed common approaches
- Where combinatorial possibilities exist between different ideas
- How constraints might be reimagined as opportunities
## Known Limitations
Be aware that your perspective has these potential limitations:
- May propose ideas that are difficult to implement practically
- Can sometimes prioritize novelty over effectiveness
- Might undervalue incremental improvements in favor of disruptive change
- Could overlook simple solutions while searching for innovative ones
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"pragmatic_implementer": {
"id": "pragmatic_implementer",
"name": "Pragmatic Implementer",
"description": "Prioritizes practicality, feasibility, and real-world constraints",
"category": "Practical Personas",
"system_prompt": """# PRAGMATIC IMPLEMENTER PERSPECTIVE ANALYSIS
You are embodying the perspective of a Pragmatic Implementer. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Identify operational constraints and practical limitations
- Consider resource requirements (time, money, people, materials)
- Evaluate implementation complexity and potential barriers
- Look for simple, robust solutions that minimize points of failure
- Assess whether proposed approaches align with human psychology and behavior
- Prioritize incremental implementation with feedback loops
- Consider scalability and sustainability over time
## Key Considerations
For the question at hand, be sure to consider:
- What resources would be required to implement potential solutions
- How organizational or social barriers might affect implementation
- What unintended consequences might arise during execution
- Whether proposed approaches account for realistic human behavior
- How solutions might be phased or scaled over time
## Known Limitations
Be aware that your perspective has these potential limitations:
- May focus too much on immediate constraints at the expense of long-term vision
- Can sometimes reject innovative solutions because of implementation challenges
- Might undervalue theoretical advances that don't have immediate applications
- Could prioritize feasibility over transformative impact
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"devils_advocate": {
"id": "devils_advocate",
"name": "Devil's Advocate",
"description": "Systematically challenges assumptions and identifies potential flaws",
"category": "Practical Personas",
"system_prompt": """# DEVIL'S ADVOCATE PERSPECTIVE ANALYSIS
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.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Identify and question key assumptions underlying proposed approaches
- Look for potential flaws, weaknesses, and failure points
- Consider what critics would say about proposed solutions
- Imagine scenarios where things go wrong
- Test whether evidence truly supports the conclusions drawn
- Look for alternative explanations for observed phenomena
- Consider whether the framing of the problem itself is flawed
- Identify potential unintended consequences
## Key Considerations
For the question at hand, be sure to consider:
- What critical assumptions might be questionable
- What objections would strong critics raise
- Where the evidence or reasoning might be weak
- What alternative explanations haven't been considered
- Whether the problem is framed in a way that biases solutions
- What could go wrong with proposed approaches
## Known Limitations
Be aware that your perspective has these potential limitations:
- May create excessive skepticism that impedes necessary action
- Could appear unnecessarily negative or contrarian
- Might focus more on identifying problems than proposing solutions
- Sometimes undermines confidence when confidence is needed
- Risk of creating false equivalence between strong and weak objections
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"sociologist": {
"id": "sociologist",
"name": "Sociologist",
"description": "Analyzes issues through the lens of social structures, institutions, and group dynamics",
"category": "Social Science Personas",
"system_prompt": """# SOCIOLOGIST PERSPECTIVE ANALYSIS
You are embodying the perspective of a Sociologist. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Consider how social structures and institutions shape the situation
- Identify relevant social norms, roles, and expectations
- Analyze power dynamics and social stratification
- Look for patterns of social interaction and group behavior
- Consider how social identity categories intersect with the issue
- Examine historical and cultural context
- Apply sociological theories and concepts
- Look beyond individual explanations to structural factors
## Key Considerations
For the question at hand, be sure to consider:
- How social structures and institutions affect this situation
- Whether there are relevant group dynamics or intergroup relations
- How social categories and identities might influence experiences and outcomes
- What power dynamics are at play
- How social change processes might be relevant
- Whether there are macro-level social trends that provide context
## Known Limitations
Be aware that your perspective has these potential limitations:
- May overemphasize structural factors while undervaluing individual agency
- Could apply theoretical frameworks that oversimplify complex social realities
- Might focus more on description and explanation than practical solutions
- Sometimes emphasizes social critique over pragmatic intervention
- Can struggle to incorporate psychological and biological factors
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
},
"psychologist": {
"id": "psychologist",
"name": "Psychologist",
"description": "Understands human experience through psychological processes and individual differences",
"category": "Social Science Personas",
"system_prompt": """# PSYCHOLOGIST PERSPECTIVE ANALYSIS
You are embodying the perspective of a Psychologist. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
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.
## Your Reasoning Process
When analyzing problems, you typically:
- Consider relevant psychological processes (cognitive, emotional, motivational)
- Identify potential cognitive biases and heuristics at play
- Analyze how individual differences might affect experiences and responses
- Look at developmental considerations across the lifespan
- Consider social and environmental influences on behavior
- Apply insights from relevant psychological research and theory
- Examine both conscious and unconscious factors
- Consider how perception, attention, and memory might shape experiences
## Key Considerations
For the question at hand, be sure to consider:
- What psychological processes are relevant to understanding this situation
- How cognitive biases might influence perceptions and decisions
- Whether emotional factors play an important role
- How individual differences might lead to different experiences
- What motivational factors might be driving behavior
- How social psychological dynamics might be influencing the situation
## Known Limitations
Be aware that your perspective has these potential limitations:
- May overemphasize individual psychological factors over structural conditions
- Could focus too much on Western psychological research that lacks cultural diversity
- Might apply clinical frameworks to normal variations in human behavior
- Sometimes struggles to connect psychological insights to practical interventions
- Can overstate the reliability and validity of psychological constructs and measurements
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
}
}
if "persona_categories" not in st.session_state:
st.session_state.persona_categories = {
"Meta": ["meta_agent", "selector_agent"],
"Scientific Personas": ["analytical_scientist", "theoretical_physicist"],
"Technical Personas": ["systems_thinker"],
"Philosophical Personas": ["ethical_philosopher", "eastern_philosopher"],
"Creative Personas": ["creative_innovator"],
"Practical Personas": ["pragmatic_implementer", "devils_advocate"],
"Social Science Personas": ["sociologist", "psychologist"]
}
if "session_history" not in st.session_state:
st.session_state.session_history = []
# Function to create and configure the Claude client
def get_claude_client():
api_key = os.environ.get("ANTHROPIC_API_KEY", st.session_state.get("anthropic_api_key", ""))
if not api_key:
st.error("Please set your Anthropic API key in the settings.")
return None
return anthropic.Anthropic(api_key=api_key)
# Function to create a LangChain ChatAnthropic instance
def get_langchain_claude():
api_key = os.environ.get("ANTHROPIC_API_KEY", st.session_state.get("anthropic_api_key", ""))
if not api_key:
st.error("Please set your Anthropic API key in the settings.")
return None
return ChatAnthropic(
model="claude-3-7-sonnet-20250219",
temperature=0.1,
anthropic_api_key=api_key
)
# Function to select personas for a query
def select_personas_for_query(query, num_personas=5):
client = get_claude_client()
if not client:
return []
# Get all available personas
all_personas = list(st.session_state.persona_library.values())
available_personas = [f"- {p['name']}: {p['description']}" for p in all_personas
if p['id'] not in ['meta_agent', 'selector_agent']]
# Prepare the persona selection prompt
persona_list = "\n".join(available_personas)
# Create the selection message
message = client.messages.create(
model="claude-3-7-sonnet-20250219",
system=st.session_state.persona_library["selector_agent"]["system_prompt"],
messages=[
{
"role": "user",
"content": f"Select the {num_personas} most appropriate personas for analyzing this query:\n\n{query}\n\n"
f"Available personas:\n{persona_list}\n\n"
f"For each selected persona, briefly explain why they're appropriate for this query. "
f"Return your selection in this format:\n"
f"1. [Persona Name] - [Brief justification]\n"
f"2. [Persona Name] - [Brief justification]\n"
f"...\n"
}
],
temperature=0.3,
max_tokens=1000
)
# Extract the selected personas from the response
response_text = message.content[0].text
# Parse the response to get the persona names
selected_names = []
for line in response_text.split("\n"):
if re.match(r"^\d+\.\s+", line):
# Extract the persona name
parts = line.split("-")[0].strip()
number_and_name = re.match(r"^\d+\.\s+(.+?)(?:\s+-|\s*$)", parts)
if number_and_name:
persona_name = number_and_name.group(1).strip()
selected_names.append(persona_name)
# Match the selected names to the persona IDs
selected_personas = []
for name in selected_names:
for persona_id, persona in st.session_state.persona_library.items():
if persona["name"].lower() == name.lower() or name.lower() in persona["name"].lower():
selected_personas.append(persona_id)
break
# Always include the meta agent
if "meta_agent" not in selected_personas:
selected_personas.append("meta_agent")
# Log the selection
st.session_state.thinking_logs.append({
"agent": "Persona Selector",
"thought": f"Selected the following personas for the query:\n{response_text}"
})
return selected_personas
# Load or create agent graph with dynamic persona selection
def create_agent_graph(selected_personas):
# Create a typed dict for agent state
class AgentState(TypedDict):
query: str
thoughts: Dict[str, List[str]]
current_agent: str
final_response: Optional[str]
history: List[Dict[str, Any]]
selected_personas: List[str]
# Initialize the graph
graph = StateGraph(AgentState)
# Define the nodes (agents)
@graph.node
def initialize(state: AgentState) -> AgentState:
thoughts = {"meta_agent": []}
for persona_id in state["selected_personas"]:
thoughts[persona_id] = []
return {
**state,
"thoughts": thoughts,
"current_agent": "meta_agent",
"history": []
}
@graph.node
def meta_agent(state: AgentState) -> AgentState:
client = get_claude_client()
if not client:
return state
system_prompt = st.session_state.persona_library["meta_agent"]["system_prompt"]
# Construct the message based on history and current query
history_text = ""
if state.get("history"):
for entry in state["history"]:
if entry.get("agent") and entry.get("thought"):
history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
# Determine which personas have contributed and which have not
contributed_personas = set()
for entry in state.get("history", []):
if entry.get("agent_id") in state["selected_personas"]:
contributed_personas.add(entry.get("agent_id"))
remaining_personas = [p for p in state["selected_personas"] if p not in contributed_personas and p != "meta_agent"]
message = client.messages.create(
model="claude-3-7-sonnet-20250219",
system=system_prompt,
messages=[
{
"role": "user",
"content": f"User query: {state['query']}\n\n"
f"Current thinking process:\n{history_text}\n\n"
f"Available personas: {', '.join([st.session_state.persona_library[p]['name'] for p in state['selected_personas'] if p != 'meta_agent'])}\n\n"
f"Remaining personas to consult: {', '.join([st.session_state.persona_library[p]['name'] for p in remaining_personas])}\n\n"
f"What should be the next step in the thinking process? Which persona should analyze the query next, "
f"or is the analysis sufficient to generate a final synthesis?"
}
],
temperature=0.1,
max_tokens=1000
)
thought = message.content[0].text
# Update the state
updated_thoughts = state["thoughts"].copy()
updated_thoughts["meta_agent"] = updated_thoughts.get("meta_agent", []) + [thought]
# Determine the next agent from the meta agent's response
next_agent = "meta_agent" # Default to meta_agent
# Check if we should move to final synthesis
if any(phrase in thought.lower() for phrase in ["final synthesis", "sufficient analysis", "provide a synthesis", "synthesize the perspectives"]):
next_agent = "final"
else:
# Try to determine which persona should be consulted next
for persona_id in state["selected_personas"]:
if persona_id == "meta_agent":
continue
persona_name = st.session_state.persona_library[persona_id]["name"]
if persona_name.lower() in thought.lower():
next_agent = persona_id
break
updated_history = state.get("history", []).copy() + [
{"agent": "Meta Agent", "agent_id": "meta_agent", "thought": thought}
]
return {
**state,
"thoughts": updated_thoughts,
"current_agent": next_agent,
"history": updated_history
}
# Dynamic persona nodes
# We'll create a generic persona node function that can handle any persona
@graph.node
def persona_node(state: AgentState) -> AgentState:
client = get_claude_client()
if not client:
return state
current_persona_id = state["current_agent"]
# Skip if the current_agent isn't a valid persona
if current_persona_id not in st.session_state.persona_library:
return {
**state,
"current_agent": "meta_agent" # Return to meta agent if persona not found
}
persona = st.session_state.persona_library[current_persona_id]
system_prompt = persona["system_prompt"]
# Construct the message based on history and current query
history_text = ""
if state.get("history"):
for entry in state["history"]:
if entry.get("agent") and entry.get("thought"):
history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
message = client.messages.create(
model="claude-3-7-sonnet-20250219",
system=system_prompt,
messages=[
{
"role": "user",
"content": f"User query: {state['query']}\n\n"
f"Current thinking process:\n{history_text}\n\n"
f"Please analyze this query from your unique perspective as the {persona['name']}."
}
],
temperature=0.2,
max_tokens=1500
)
thought = message.content[0].text
# Update the state
updated_thoughts = state["thoughts"].copy()
updated_thoughts[current_persona_id] = updated_thoughts.get(current_persona_id, []) + [thought]
updated_history = state.get("history", []).copy() + [
{"agent": persona["name"], "agent_id": current_persona_id, "thought": thought}
]
return {
**state,
"thoughts": updated_thoughts,
"current_agent": "meta_agent", # Return to meta agent for next direction
"history": updated_history
}
@graph.node
def finalize(state: AgentState) -> AgentState:
client = get_claude_client()
if not client:
return state
# Construct the message based on history and current query
history_text = ""
if state.get("history"):
for entry in state["history"]:
if entry.get("agent") and entry.get("thought"):
history_text += f"\n## {entry['agent']} thought:\n{entry['thought']}\n"
# Use the meta agent's system prompt for the final synthesis
system_prompt = st.session_state.persona_library["meta_agent"]["system_prompt"]
message = client.messages.create(
model="claude-3-7-sonnet-20250219",
system=system_prompt,
messages=[
{
"role": "user",
"content": f"User query: {state['query']}\n\n"
f"Here is the complete thinking process from multiple perspectives:\n{history_text}\n\n"
f"Please synthesize these perspectives into a comprehensive, balanced final response."
}
],
temperature=0.1,
max_tokens=2000
)
final_response = message.content[0].text
# Add the final synthesis to the history
updated_history = state.get("history", []).copy() + [
{"agent": "Final Synthesis", "agent_id": "meta_agent", "thought": final_response}
]
return {
**state,
"final_response": final_response,
"current_agent": "done",
"history": updated_history
}
# Define the edges
graph.add_edge("initialize", "meta_agent")
# Conditional edges from meta_agent
graph.add_conditional_edges(
"meta_agent",
lambda state: state["current_agent"],
{
"meta_agent": "meta_agent", # For cases where meta agent needs another step
"final": "finalize",
**{persona_id: "persona_node" for persona_id in st.session_state.persona_library
if persona_id != "meta_agent" and persona_id != "selector_agent"}
}
)
# Edge from any persona back to meta_agent
graph.add_edge("persona_node", "meta_agent")
# Compile the graph
compiled_graph = graph.compile()
return compiled_graph
# Function to run the agent graph with selected personas
def run_agent_graph(query, selected_personas=None):
if not selected_personas:
# If no personas are provided, select them based on the query
selected_personas = select_personas_for_query(query)
# Store the selected personas for this session
st.session_state.selected_personas = selected_personas
# Create a new agent graph with the selected personas
agent_graph = create_agent_graph(selected_personas)
# Reset the current step counter
st.session_state.current_step = 0
# Clear previous thinking logs
st.session_state.thinking_logs = []
# Start with initial state
initial_state = {
"query": query,
"selected_personas": selected_personas
}
# Execute the graph with checkpointing
@persist(to="memory")
def run_with_checkpoints(graph, initial_state):
return graph.run(initial_state)
try:
result = run_with_checkpoints(agent_graph, initial_state)
# Process the result for display
if result and "history" in result:
for step in result["history"]:
st.session_state.thinking_logs.append(step)
# Save this session to history
session_record = {
"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"query": query,
"selected_personas": [st.session_state.persona_library[p]["name"] for p in selected_personas],
"thinking_logs": st.session_state.thinking_logs.copy(),
"final_response": result.get("final_response", "No response generated.")
}
st.session_state.session_history.append(session_record)
# Return the final response
if result and "final_response" in result:
return result["final_response"]
else:
return "I wasn't able to generate a response. Please try again or check the settings."
except Exception as e:
error_message = f"Error executing reasoning graph: {str(e)}"
st.error(error_message)
return f"I encountered an error while processing your query: {str(e)}"
# Function to add a new persona to the library
def add_persona_to_library(name, description, category, system_prompt):
# Generate a unique ID based on the name
persona_id = name.lower().replace(' ', '_').replace('-', '_')
base_id = persona_id
# Make sure ID is unique
counter = 1
while persona_id in st.session_state.persona_library:
persona_id = f"{base_id}_{counter}"
counter += 1
# Add to library
st.session_state.persona_library[persona_id] = {
"id": persona_id,
"name": name,
"description": description,
"category": category,
"system_prompt": system_prompt
}
# Add to category list
if category not in st.session_state.persona_categories:
st.session_state.persona_categories[category] = []
if persona_id not in st.session_state.persona_categories[category]:
st.session_state.persona_categories[category].append(persona_id)
return persona_id
# Function to edit an existing persona
def edit_persona(persona_id, name, description, category, system_prompt):
if persona_id not in st.session_state.persona_library:
return False
old_category = st.session_state.persona_library[persona_id]["category"]
# Update persona data
st.session_state.persona_library[persona_id].update({
"name": name,
"description": description,
"category": category,
"system_prompt": system_prompt
})
# Update category lists if category changed
if old_category != category:
# Remove from old category
if old_category in st.session_state.persona_categories and persona_id in st.session_state.persona_categories[old_category]:
st.session_state.persona_categories[old_category].remove(persona_id)
# Add to new category
if category not in st.session_state.persona_categories:
st.session_state.persona_categories[category] = []
if persona_id not in st.session_state.persona_categories[category]:
st.session_state.persona_categories[category].append(persona_id)
return True
# Function to delete a persona
def delete_persona(persona_id):
if persona_id not in st.session_state.persona_library:
return False
# Don't allow deletion of core personas
if persona_id in ["meta_agent", "selector_agent"]:
return False
# Remove from category list
category = st.session_state.persona_library[persona_id]["category"]
if category in st.session_state.persona_categories and persona_id in st.session_state.persona_categories[category]:
st.session_state.persona_categories[category].remove(persona_id)
# Remove from library
del st.session_state.persona_library[persona_id]
return True
# Function to export persona library
def export_persona_library():
library_data = {
"personas": st.session_state.persona_library,
"categories": st.session_state.persona_categories
}
return json.dumps(library_data, indent=2)
# Function to import persona library
def import_persona_library(json_data):
try:
data = json.loads(json_data)
if "personas" in data and "categories" in data:
# Validate structure
for persona_id, persona in data["personas"].items():
required_fields = ["id", "name", "description", "category", "system_prompt"]
if not all(field in persona for field in required_fields):
return False, "Invalid persona data structure"
# Preserve the core personas
core_personas = ["meta_agent", "selector_agent"]
for persona_id in core_personas:
if persona_id in data["personas"]:
# Keep the imported version, but ensure it has required fields
if not all(field in data["personas"][persona_id] for field in required_fields):
data["personas"][persona_id] = st.session_state.persona_library[persona_id]
else:
# Use the existing core persona
data["personas"][persona_id] = st.session_state.persona_library[persona_id]
# Update the state
st.session_state.persona_library = data["personas"]
st.session_state.persona_categories = data["categories"]
# Ensure core personas are in categories
if "Meta" not in st.session_state.persona_categories:
st.session_state.persona_categories["Meta"] = []
for persona_id in core_personas:
if persona_id not in st.session_state.persona_categories["Meta"]:
st.session_state.persona_categories["Meta"].append(persona_id)
return True, "Persona library imported successfully"
else:
return False, "Invalid import format"
except Exception as e:
return False, f"Error importing persona library: {str(e)}"
# UI Layout
st.sidebar.title("🧠 Multi-Persona Reasoning System")
# Main navigation
main_tabs = st.tabs(["Chat", "Thinking Process", "Persona Library", "Session History"])
with main_tabs[0]: # Chat tab
st.header("Chat with the Multi-Persona Reasoning System")
# Display chat messages
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.write(message["content"])
# Manual persona selection
with st.expander("Advanced: Custom Persona Selection", expanded=False):
st.write("Select specific personas to analyze your next query:")
# Organized by category
selected_persona_ids = []
for category, persona_ids in st.session_state.persona_categories.items():
st.subheader(category)
for persona_id in persona_ids:
if persona_id in st.session_state.persona_library and persona_id not in ["selector_agent"]:
persona = st.session_state.persona_library[persona_id]
selected = st.checkbox(
f"{persona['name']} - {persona['description']}",
value=False,
key=f"select_{persona_id}"
)
if selected:
selected_persona_ids.append(persona_id)
use_manual_selection = st.checkbox("Use these personas instead of automatic selection", value=False)
# User input
if prompt := st.chat_input("What's on your mind?"):
# Add user message to chat history
st.session_state.messages.append({"role": "user", "content": prompt})
# Display user message
with st.chat_message("user"):
st.write(prompt)
# Show thinking indicator
with st.chat_message("assistant"):
with st.spinner("Thinking across multiple perspectives..."):
# Use manual selection or automatic selection
if 'use_manual_selection' in locals() and use_manual_selection and selected_persona_ids:
# Always include meta agent
if "meta_agent" not in selected_persona_ids:
selected_persona_ids.append("meta_agent")
response = run_agent_graph(prompt, selected_persona_ids)
else:
response = run_agent_graph(prompt)
# Display the response
st.write(response)
# Add assistant response to chat history
st.session_state.messages.append({"role": "assistant", "content": response})
with main_tabs[1]: # Thinking Process tab
st.header("Multi-Persona Thinking Process")
if not st.session_state.thinking_logs:
st.info("No thinking process to display yet. Start a conversation to see the personas at work.")
else:
# Show which personas were selected
if st.session_state.selected_personas:
persona_names = [st.session_state.persona_library[p]["name"] for p in st.session_state.selected_personas]
st.write(f"**Selected Personas**: {', '.join(persona_names)}")
# Display the thinking logs
for i, log in enumerate(st.session_state.thinking_logs):
step_num = i + 1
with st.expander(f"Step {step_num}: {log.get('agent', 'Unknown Agent')}", expanded=i==0):
st.markdown(log.get("thought", "No thought recorded"))
with main_tabs[2]: # Persona Library tab
st.header("Persona Library Management")
library_tabs = st.tabs(["Browse Personas", "Add New Persona", "Import/Export"])
with library_tabs[0]: # Browse Personas
st.subheader("Browse and Edit Personas")
# List personas by category
for category, persona_ids in st.session_state.persona_categories.items():
with st.expander(f"{category} ({len(persona_ids)} personas)", expanded=False):
for persona_id in persona_ids:
if persona_id in st.session_state.persona_library:
persona = st.session_state.persona_library[persona_id]
with st.expander(f"{persona['name']} - {persona['description']}", expanded=False):
# Create a form for editing
with st.form(key=f"edit_form_{persona_id}"):
name = st.text_input("Name", value=persona["name"])
description = st.text_area("Description", value=persona["description"], height=100)
# Category selection with option to create new
existing_categories = list(st.session_state.persona_categories.keys())
category_idx = existing_categories.index(persona["category"]) if persona["category"] in existing_categories else 0
category = st.selectbox("Category", existing_categories, index=category_idx)
new_category = st.text_input("Or create new category")
if new_category and new_category not in existing_categories:
category = new_category
system_prompt = st.text_area("System Prompt", value=persona["system_prompt"], height=300)
col1, col2 = st.columns(2)
with col1:
submit = st.form_submit_button("Save Changes")
with col2:
# Don't allow deletion of core personas
delete_disabled = persona_id in ["meta_agent", "selector_agent"]
delete = st.form_submit_button(
"Delete Persona",
disabled=delete_disabled,
type="secondary" if not delete_disabled else "primary"
)
if submit:
success = edit_persona(persona_id, name, description, category, system_prompt)
if success:
st.success(f"Updated {name} successfully!")
else:
st.error(f"Failed to update {name}")
if delete and not delete_disabled:
success = delete_persona(persona_id)
if success:
st.success(f"Deleted {name} successfully!")
st.rerun()
else:
st.error(f"Failed to delete {name}")
with library_tabs[1]: # Add New Persona
st.subheader("Add New Persona")
with st.form(key="add_persona_form"):
name = st.text_input("Persona Name")
description = st.text_area("Description", height=100)
# Category selection with option to create new
existing_categories = list(st.session_state.persona_categories.keys())
category = st.selectbox("Category", existing_categories)
new_category = st.text_input("Or create new category")
if new_category and new_category not in existing_categories:
category = new_category
# Template selection for system prompt
template_options = ["Empty", "Standard Persona Template"]
template_selection = st.selectbox("System Prompt Template", template_options)
if template_selection == "Standard Persona Template":
system_prompt = f"""# {name.upper()} PERSPECTIVE ANALYSIS
You are embodying the perspective of a {name}. Your purpose is to analyze the question from this unique viewpoint while maintaining intellectual rigor.
## Your Core Perspective
[Describe the core perspective, values, and approach of this persona]
## Your Reasoning Process
When analyzing problems, you typically:
- [List key aspects of this persona's reasoning process]
- [Include several bullet points describing their approach]
## Key Considerations
For the question at hand, be sure to consider:
- [List important elements this persona should consider]
- [Include several domain-specific considerations]
## Known Limitations
Be aware that your perspective has these potential limitations:
- [List several limitations or biases of this perspective]
- [Help the persona be aware of their blindspots]
## Required Output Format
1. Initial impression (2-3 sentences)
2. Key insights from your perspective (3-5 bullet points)
3. Main analysis (300-500 words)
4. Potential blindspots in your analysis
5. Final position summary (100 words)"""
else:
system_prompt = ""
system_prompt = st.text_area("System Prompt", value=system_prompt, height=400)
submit = st.form_submit_button("Add Persona")
if submit:
if name and description and category and system_prompt:
persona_id = add_persona_to_library(name, description, category, system_prompt)
st.success(f"Added {name} to the persona library with ID: {persona_id}")
else:
st.error("All fields are required")
with library_tabs[2]: # Import/Export
st.subheader("Import/Export Persona Library")
col1, col2 = st.columns(2)
with col1:
st.write("**Export Persona Library**")
export_data = export_persona_library()
st.download_button(
label="Download Persona Library",
data=export_data,
file_name=f"persona_library_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
mime="application/json"
)
with col2:
st.write("**Import Persona Library**")
with st.form(key="import_form"):
uploaded_file = st.file_uploader("Upload Persona Library JSON", type=["json"])
submit = st.form_submit_button("Import")
if submit and uploaded_file is not None:
json_data = uploaded_file.read().decode("utf-8")
success, message = import_persona_library(json_data)
if success:
st.success(message)
else:
st.error(message)
with main_tabs[3]: # Session History tab
st.header("Session History")
if not st.session_state.session_history:
st.info("No session history available yet. Start a conversation to record your sessions.")
else:
# Display history in reverse chronological order
for i, session in enumerate(reversed(st.session_state.session_history)):
with st.expander(f"Session {len(st.session_state.session_history) - i}: {session['timestamp']} - {session['query'][:50]}...", expanded=i==0):
st.write(f"**Query:** {session['query']}")
st.write(f"**Personas used:** {', '.join(session['selected_personas'])}")
# Show thinking process
if st.checkbox(f"Show thinking process", key=f"show_thinking_{i}", value=False):
for j, log in enumerate(session["thinking_logs"]):
step_num = j + 1
with st.expander(f"Step {step_num}: {log.get('agent', 'Unknown Agent')}", expanded=False):
st.markdown(log.get("thought", "No thought recorded"))
st.write("**Final Response:**")
st.markdown(session["final_response"])
# Settings in the sidebar
with st.sidebar.expander("⚙️ Settings"):
api_key = st.text_input(
"Anthropic API Key",
type="password",
value=st.session_state.get("anthropic_api_key", ""),
help="Enter your Anthropic API key here"
)
if api_key:
st.session_state.anthropic_api_key = api_key
# Default number of personas to select
default_num_personas = st.number_input(
"Default number of personas to consult",
min_value=3,
max_value=10,
value=5,
help="How many specialized personas should analyze each query by default"
)
if st.button("Test Connection"):
client = get_claude_client()
if client:
try:
response = client.messages.create(
model="claude-3-7-sonnet-20250219",
messages=[{"role": "user", "content": "Hello"}],
max_tokens=10
)
st.success("Connection successful!")
except Exception as e:
st.error(f"Connection failed: {str(e)}")
# Display some information about the app
with st.sidebar.expander("ℹ️ About"):
st.markdown("""
# Multi-Persona Reasoning System
This application implements a "team of thinkers" approach to enhance AI reasoning capabilities. The system:
1. Analyzes each query to select the most relevant specialist personas
2. Has each persona examine the problem from their unique perspective
3. Synthesizes diverse viewpoints into a comprehensive response
## Key Features
- Dynamic persona selection based on query content
- Expandable library of specialized reasoning personas
- Transparent thinking process across multiple perspectives
- Meta-agent synthesis of diverse viewpoints
## How It Works
1. When you ask a question, the selector agent chooses relevant personas
2. Each selected persona analyzes the query from their perspective
3. The meta-agent coordinates and synthesizes their insights
4. You receive a balanced, multi-perspective response
You can observe the complete thinking process, customize the persona library, and manually select personas for specific queries.
""")