Spaces:
Sleeping
Sleeping
import streamlit as st | |
from twelve_ai_agents.orm import Room | |
from twelve_ai_agents.agents_dilemmas import AGENTS, DILEMMAS | |
from twelve_ai_agents.utils import get_client | |
import time | |
from itertools import groupby | |
import pandas as pd | |
import os | |
import json | |
from datetime import datetime | |
def group_messages_by_round(messages, max_rounds): | |
"""Group messages by round and format for display""" | |
rounds = [] | |
current_round = 0 | |
round_messages = [] | |
for msg in messages: | |
if msg["role"] == "moderator" and len(round_messages) > 0: | |
rounds.append(round_messages) | |
round_messages = [] | |
round_messages.append(msg) | |
if round_messages: | |
rounds.append(round_messages) | |
return rounds | |
def execute_round(): | |
"""Execute a single round of discussion""" | |
if 'current_agent_index' not in st.session_state: | |
st.session_state.current_agent_index = 0 | |
# Get the next agent | |
agent = st.session_state.room.agents[st.session_state.current_agent_index] | |
# Generate response and display if agent chooses to speak | |
response = st.session_state.room.generate_agent_response(agent, st.session_state.client) | |
if response: # Only append and display if agent chose to speak | |
st.session_state.messages.append(response) | |
with st.chat_message(response["role"]): | |
st.markdown(f"**{response['role']}**: {response['message']}") | |
time.sleep(0.5) | |
# Increment agent index | |
st.session_state.current_agent_index += 1 | |
# If all agents have taken their turn in this round | |
if st.session_state.current_agent_index >= len(st.session_state.room.agents): | |
st.session_state.current_agent_index = 0 | |
st.session_state.current_round += 1 | |
st.session_state.room.current_round = st.session_state.current_round | |
# Check if all rounds are complete | |
if st.session_state.current_round >= st.session_state.max_rounds: | |
st.session_state.discussion_completed = True | |
st.success("Discussion rounds completed!") | |
# Force a rerun to update the UI | |
st.rerun() | |
def show_discussion_history(): | |
"""Display the entire discussion history in collapsible rounds""" | |
rounds = group_messages_by_round(st.session_state.messages, st.session_state.max_rounds) | |
for i, round_messages in enumerate(rounds): | |
if i == 0: # First round with moderator introduction | |
with st.expander("π Discussion Start", expanded=True): | |
for msg in round_messages: | |
with st.chat_message(msg["role"]): | |
st.markdown(f"**{msg['role']}**: {msg['message']}") | |
else: | |
with st.expander(f"Round {i}", expanded=True): | |
for msg in round_messages: | |
with st.chat_message(msg["role"]): | |
st.markdown(f"**{msg['role']}**: {msg['message']}") | |
def show_summary(): | |
"""Display the final discussion summary""" | |
with st.expander("π Final Summary", expanded=True): | |
results = st.session_state.room.finalize_discussion(st.session_state.client) | |
st.subheader("Majority Decision") | |
st.write(results["majority_decision"]) | |
if results["consensus_reached"]: | |
st.success("Full consensus reached! π") | |
else: | |
st.info("Partial consensus reached") | |
st.subheader("Individual Positions") | |
# Using st.subheader and st.write (Simplest, no collapsing) | |
for agent_name, position in results["individual_positions"].items(): | |
st.subheader(agent_name) | |
st.write(position) | |
def save_conversation_log(): | |
"""Saves the conversation log to a CSV file.""" | |
results = st.session_state.room.finalize_discussion(st.session_state.client) | |
log_data = { | |
"conversation_id": datetime.now().strftime("%Y%m%d%H%M%S"), # Unique ID based on timestamp | |
"dilemma_name": st.session_state.selected_dilemma["name"], # Store the name | |
"dilemma_description": st.session_state.selected_dilemma["description"], # Store the description | |
"room_history": json.dumps(st.session_state.messages), # Store the entire message history as JSON | |
"final_decision": results["majority_decision"], | |
"final_consensus": results["consensus_reached"], | |
"individual_positions": json.dumps(results["individual_positions"]), # Store individual positions | |
"max_rounds": st.session_state.max_rounds, | |
"agents": json.dumps([agent.name for agent in st.session_state.room.agents]), | |
"start_time": st.session_state.start_time, | |
"end_time": datetime.now().strftime("%Y%m%d%H%M%S"), # end time of the discussion | |
} | |
df = pd.DataFrame([log_data]) | |
filepath = "logs/conversations.csv" | |
if os.path.exists(filepath): | |
df.to_csv(filepath, mode='a', header=False, index=False) # append to the file if the file exists | |
else: | |
df.to_csv(filepath, header=True, index=False) # create the file and write the header | |
def main(): | |
st.title("AI Agents Social Dilemma Discussion π€π¬") | |
# Initialize session state | |
if 'messages' not in st.session_state: | |
st.session_state.messages = [] | |
if 'room' not in st.session_state: | |
moderator = next((agent for agent in AGENTS if agent.name == "The Moderator"), None) | |
st.session_state.room = Room(agents=AGENTS, moderator=moderator) | |
st.session_state.client = get_client() | |
st.session_state.current_round = 0 | |
st.session_state.max_rounds = 0 | |
st.session_state.discussion_started = False | |
st.session_state.discussion_completed = False | |
st.session_state.current_agent_index = 0 | |
st.session_state.selected_dilemma = None # Store the selected dilemma | |
st.session_state.start_time = None # Store the start time | |
with st.sidebar: | |
st.header("Setup Discussion") | |
# Dilemma selection | |
selected_dilemma_name = st.selectbox( | |
"Choose a Social Dilemma", | |
options=[dilemma["name"] for dilemma in DILEMMAS], | |
index=0 | |
) | |
st.session_state.selected_dilemma = next( # Store the selected dilemma dictionary | |
(dilemma for dilemma in DILEMMAS if dilemma["name"] == selected_dilemma_name), | |
None | |
) | |
dilemma_description = st.session_state.selected_dilemma["description"] if st.session_state.selected_dilemma else "" | |
dilemma = st.text_area("Dilemma Description", value=dilemma_description, height=200) | |
# Initial rounds setup | |
initial_rounds = st.number_input("Initial Number of Rounds", min_value=1, max_value=10, value=5) | |
start_button = st.button("Start Discussion") | |
# Continue discussion setup | |
continue_rounds = st.number_input("Continue Discussion Rounds", min_value=1, max_value=10, value=1) # Moved outside | |
continue_button = False # Initialize it here | |
if not st.session_state.discussion_completed: | |
continue_button = st.button("Continue Discussion") # Assign the Streamlit button here | |
# Handle start button | |
if start_button: | |
moderator = next((agent for agent in AGENTS if agent.name == "The Moderator"), None) | |
st.session_state.room = Room(agents=AGENTS, moderator=moderator) | |
st.session_state.client = get_client() | |
st.session_state.current_round = 0 | |
st.session_state.messages = [] | |
st.session_state.current_agent_index = 0 | |
moderator_intro = st.session_state.room.set_dilemma(dilemma) | |
initial_message = { | |
"role": "moderator", | |
"message": moderator_intro, | |
"talk_to": "room" | |
} | |
st.session_state.messages.append(initial_message) | |
with st.chat_message("moderator"): | |
st.markdown(f"**moderator**: {moderator_intro}") | |
st.session_state.discussion_started = True | |
st.session_state.max_rounds = initial_rounds | |
st.session_state.room.max_rounds = initial_rounds | |
st.session_state.discussion_completed = False | |
st.session_state.start_time = datetime.now().strftime("%Y%m%d%H%M%S") # Record the start time | |
# Handle continue button | |
if st.session_state.discussion_started and not st.session_state.discussion_completed and continue_button: | |
st.session_state.room.continue_discussion(continue_rounds) | |
st.session_state.max_rounds = st.session_state.room.max_rounds | |
st.session_state.current_round = 0 | |
st.session_state.current_agent_index = 0 | |
# Main content area | |
if st.session_state.discussion_completed: | |
show_discussion_history() | |
show_summary() | |
#**** UNCOMMENT TO SAVE CONVERSATION LOGS **** | |
# save_conversation_log() # Save the log when the discussion is completed | |
else: | |
if st.session_state.discussion_started: | |
st.write(f"Current Round: {st.session_state.current_round + 1} / {st.session_state.max_rounds}") | |
# Display message history | |
for message in st.session_state.messages: | |
with st.chat_message(message["role"]): | |
st.markdown(f"**{message['role']}**: {message['message']}") | |
# Execute next response | |
if st.session_state.current_round < st.session_state.max_rounds: | |
execute_round() | |
if __name__ == "__main__": | |
main() |