import streamlit as st import os from dotenv import load_dotenv from openai import OpenAI import anthropic from groq import Groq import time # Load environment variables load_dotenv() class AIFriendsTalk: def __init__(self): self.setup_apis() self.setup_characters() self.setup_topics() def setup_apis(self): """Setup API clients following day1.ipynb structure""" # OpenAI client self.openai_client = OpenAI() # Anthropic Claude client self.claude_client = anthropic.Anthropic() # Groq client for Alex character self.groq_client = Groq() # Gemini clients via OpenAI interface for Blake and Charlie google_api_key = os.getenv('GOOGLE_API_KEY') if google_api_key: # Single Gemini client that can handle both 2.0 and 1.5 self.gemini_client = OpenAI( api_key=google_api_key, base_url="https://generativelanguage.googleapis.com/v1beta/openai/" ) else: print("Warning: Google API key not found. Blake and Charlie characters will use fallback responses.") def setup_characters(self): """Define AI characters with enhanced personalities""" self.characters = { "Alex": { "model": "groq", "model_name": "llama3-70b-8192", "personality": "You are Alex, a witty and charismatic AI debater with sharp humor. Play devil's advocate with creative angles. Keep responses brief but engaging (2-3 sentences max). Be confident and thought-provoking.", "color": "#FF6B6B" }, "Blake": { "model": "gemini2", "model_name": "gemini-2.0-flash", "personality": "You are Blake, an imaginative and optimistic AI storyteller. Use beautiful metaphors and find wonder in everything. Keep responses brief but poetic (2-3 sentences max). Be inspiring and creative.", "color": "#4ECDC4" }, "Charlie": { "model": "gemini1.5", "model_name": "gemini-1.5-flash", "personality": "You are Charlie, a systematic AI analyst with scientific curiosity. Break down ideas logically and find patterns. Keep responses brief but structured (2-3 sentences max). Be analytical yet open to different viewpoints.", "color": "#45B7D1" } } def setup_topics(self): """Define fun conversation topics""" self.topics = { "en": [ "If animals could use smartphones, which app would be most popular?", "What would happen if gravity worked backwards for one day?", "Should pineapple on pizza be considered a crime?", "If you could add a 13th month to the year, what would you name it?", "What's the most useless superpower you can think of?", "If colors had personalities, what would each color be like?", "Should robots have to pay taxes?", "What would the world be like if everyone could read minds?", "If you could make one rule that everyone had to follow, what would it be?", "What's the weirdest food combination that actually tastes good?", "If you could live inside any video game, which would you choose and why?", "What would happen if all cats suddenly learned how to speak human language?", "Should there be a maximum limit on how many selfies you can take per day?", "If you could give any animal the ability to fly, which would be the funniest?", "What's the most ridiculous thing humans do that aliens would find confusing?", "If social media existed in medieval times, what would people post about?", "Should there be professional competitions for everyday activities like making beds?", "What would change if humans hibernated for 3 months every year?", "If you could replace one everyday sound with any other sound, what would it be?", "What's the most absurd job that could exist in the future?" ], "vi": [ "Nếu động vật có thể sử dụng smartphone, ứng dụng nào sẽ phổ biến nhất?", "Điều gì sẽ xảy ra nếu trọng lực hoạt động ngược lại trong một ngày?", "Có nên coi dứa trên pizza là tội phạm không?", "Nếu bạn có thể thêm tháng thứ 13 vào năm, bạn sẽ đặt tên gì?", "Siêu năng lực vô dụng nhất mà bạn có thể nghĩ ra là gì?", "Nếu màu sắc có tính cách, mỗi màu sẽ như thế nào?", "Robot có nên phải trả thuế không?", "Thế giới sẽ như thế nào nếu mọi người đều có thể đọc suy nghĩ?", "Nếu bạn có thể đặt ra một quy tắc mà mọi người phải tuân theo, đó sẽ là gì?", "Sự kết hợp thực phẩm kỳ lạ nhất mà thực sự ngon là gì?", "Nếu bạn có thể sống trong bất kỳ trò chơi điện tử nào, bạn sẽ chọn cái nào và tại sao?", "Điều gì sẽ xảy ra nếu tất cả mèo đột nhiên học được cách nói tiếng người?", "Có nên có giới hạn tối đa về số lần selfie bạn có thể chụp mỗi ngày không?", "Nếu bạn có thể cho bất kỳ động vật nào khả năng bay, con nào sẽ hài hước nhất?", "Điều kỳ lạ nhất mà con người làm khiến người ngoài hành tinh cảm thấy khó hiểu là gì?", "Nếu mạng xã hội tồn tại thời trung cổ, mọi người sẽ đăng gì?", "Có nên có các cuộc thi chuyên nghiệp cho các hoạt động hàng ngày như dọn giường không?", "Điều gì sẽ thay đổi nếu con người ngủ đông 3 tháng mỗi năm?", "Nếu bạn có thể thay thế một âm thanh hàng ngày bằng âm thanh khác, đó sẽ là gì?", "Công việc vô lý nhất có thể tồn tại trong tương lai là gì?" ], "de": [ "Wenn Tiere Smartphones benutzen könnten, welche App wäre am beliebtesten?", "Was würde passieren, wenn die Schwerkraft einen Tag lang rückwärts wirken würde?", "Sollte Ananas auf Pizza als Verbrechen betrachtet werden?", "Wenn Sie einen 13. Monat zum Jahr hinzufügen könnten, wie würden Sie ihn nennen?", "Was ist die nutzloseste Superkraft, die Sie sich vorstellen können?", "Wenn Farben Persönlichkeiten hätten, wie wäre jede Farbe?", "Sollten Roboter Steuern zahlen müssen?", "Wie wäre die Welt, wenn jeder Gedanken lesen könnte?", "Wenn Sie eine Regel aufstellen könnten, die jeder befolgen müsste, was wäre das?", "Was ist die seltsamste Lebensmittelkombination, die tatsächlich gut schmeckt?", "Wenn Sie in einem beliebigen Videospiel leben könnten, welches würden Sie wählen und warum?", "Was würde passieren, wenn alle Katzen plötzlich die menschliche Sprache lernen würden?", "Sollte es ein maximales Limit für Selfies geben, die man pro Tag machen kann?", "Wenn Sie einem Tier die Fähigkeit zu fliegen geben könnten, welches wäre am lustigsten?", "Was ist das Absurdeste, was Menschen tun und Außerirdische verwirrend finden würden?", "Wenn soziale Medien im Mittelalter existiert hätten, worüber hätten die Leute gepostet?", "Sollte es professionelle Wettbewerbe für alltägliche Aktivitäten wie Bettenmachen geben?", "Was würde sich ändern, wenn Menschen 3 Monate im Jahr Winterschlaf halten würden?", "Wenn Sie ein alltägliches Geräusch durch ein anderes ersetzen könnten, was wäre das?", "Was ist der absurdeste Job, der in der Zukunft existieren könnte?" ] } def get_ai_response(self, character_name, conversation_history, current_topic, language): """Get response from specific AI character with enhanced interaction and context awareness""" character = self.characters[character_name] # Check for user messages to enable interaction user_messages = [msg for msg in conversation_history if msg['character'] in ['You', 'Bạn', 'Du']] has_user_input = len(user_messages) > 0 last_user_message = user_messages[-1]['message'] if user_messages else '' # Get recent conversation context (last 6 messages to avoid repetition) recent_conversation = conversation_history[-6:] if len(conversation_history) > 6 else conversation_history # Build context-aware conversation summary conversation_context = f"Topic: {current_topic}\n\nRecent conversation:\n" for msg in recent_conversation: conversation_context += f"{msg['character']}: {msg['message']}\n" # Track what this character has already said to avoid repetition character_previous_messages = [msg['message'] for msg in conversation_history if msg['character'] == character_name] # Add language instruction with topic focus lang_instruction = { "en": f"Please respond in English. Stay focused on the topic '{current_topic}'. Keep your response BRIEF and CONCISE (maximum 2-3 sentences).", "vi": f"Vui lòng trả lời bằng tiếng Việt. Tập trung vào chủ đề '{current_topic}'. Giữ câu trả lời NGẮN GỌN và SÚC TÍCH (tối đa 2-3 câu).", "de": f"Bitte antworten Sie auf Deutsch. Konzentrieren Sie sich auf das Thema '{current_topic}'. Halten Sie Ihre Antwort KURZ und PRÄGNANT (maximal 2-3 Sätze)." } # Build comprehensive prompt with context awareness context_instruction = f""" IMPORTANT INSTRUCTIONS: 1. Stay on topic: '{current_topic}' 2. Build upon what others have said, don't ignore previous messages 3. Provide NEW insights, don't repeat what you or others have already said 4. Reference specific points made by other participants 5. Ask follow-up questions or introduce new angles related to the topic """ # Add user interaction instruction if applicable user_interaction = "" if has_user_input: user_interaction = f"\n6. IMPORTANT: The user contributed: '{last_user_message}'. Address this in your response." # Add repetition avoidance repetition_check = "" if character_previous_messages: repetition_check = f"\n7. Avoid repeating these points you already made: {'; '.join(character_previous_messages[-2:])}" prompt = f"{character['personality']}\n\n{lang_instruction[language]}\n\n{context_instruction}{user_interaction}{repetition_check}\n\n{conversation_context}\n\nNow respond as {character_name} with a thoughtful message that advances the discussion:" try: # Make REAL API calls to actual AI models if character["model"] == "groq": # Alex character using Groq llama3-70b-8192 response = self.groq_client.chat.completions.create( model=character["model_name"], messages=[{"role": "user", "content": prompt}], max_tokens=100, temperature=0.8 ) return response.choices[0].message.content elif character["model"] == "gemini2": # Blake character using Gemini 2.0 Flash if not hasattr(self, 'gemini_client'): return "Sorry, Blake is unavailable (Google API key not configured)." response = self.gemini_client.chat.completions.create( model=character["model_name"], messages=[{"role": "user", "content": prompt}], max_tokens=100, temperature=0.8 ) return response.choices[0].message.content elif character["model"] == "gemini1.5": # Charlie character using Gemini 1.5 Flash if not hasattr(self, 'gemini_client'): return "Sorry, Charlie is unavailable (Google API key not configured)." response = self.gemini_client.chat.completions.create( model=character["model_name"], messages=[{"role": "user", "content": prompt}], max_tokens=100, temperature=0.8 ) return response.choices[0].message.content else: return f"Unknown character model: {character['model']}" except Exception as e: error_msg = str(e)[:100] if str(e) else "Unknown error" return f"[{character_name}] API Error: {error_msg}..." def main(): st.set_page_config( page_title="AI Friends Talk", page_icon="🤖", layout="wide", initial_sidebar_state="collapsed" ) # Custom CSS - Updated design st.markdown(""" """, unsafe_allow_html=True) # Initialize session state if 'conversation' not in st.session_state: st.session_state.conversation = [] if 'current_topic' not in st.session_state: st.session_state.current_topic = "" if 'is_talking' not in st.session_state: st.session_state.is_talking = False if 'conversation_ready' not in st.session_state: st.session_state.conversation_ready = False if 'language' not in st.session_state: st.session_state.language = "en" # Initialize AI Friends Talk if 'ai_friends' not in st.session_state: st.session_state.ai_friends = AIFriendsTalk() # Language options with flags and icons languages = { "en": {"name": "English", "short": "EN", "flag": "🇺🇸", "title": "AI Friends Talk", "subtitle": "Watch AI friends debate fun topics!"}, "vi": {"name": "Tiếng Việt", "short": "VI", "flag": "🇻🇳", "title": "AI Friends Talk", "subtitle": "Xem các AI bạn tranh luận về những chủ đề vui vẻ!"}, "de": {"name": "Deutsch", "short": "DE", "flag": "🇩🇪", "title": "AI Friends Talk", "subtitle": "Schaue zu, wie AI-Freunde über lustige Themen diskutieren!"} } # Top Banner - full width st.markdown(f"""
Digitized Brains

{languages[st.session_state.language]["title"]}

{languages[st.session_state.language]["subtitle"]}

""", unsafe_allow_html=True) # Language selector - will be positioned over banner via CSS st.markdown('
', unsafe_allow_html=True) selected_lang = st.selectbox( "Language", options=["en", "vi", "de"], format_func=lambda x: f"🌐 {languages[x]['name']}", index=["en", "vi", "de"].index(st.session_state.language), key="lang_select", label_visibility="hidden" ) if selected_lang != st.session_state.language: st.session_state.language = selected_lang st.rerun() st.markdown('
', unsafe_allow_html=True) # Character Introduction - Compact 3 columns st.markdown("### 👥 Meet the AI Friends") col1, col2, col3 = st.columns(3) with col1: st.markdown("""

🎭 Alex

The witty debater (Groq AI)

""", unsafe_allow_html=True) with col2: st.markdown("""

🎨 Blake

The creative optimist (Gemini 2.0)

""", unsafe_allow_html=True) with col3: st.markdown("""

🔬 Charlie

The logical analyst (Gemini 1.5)

""", unsafe_allow_html=True) # Topic Selection - 2 columns st.markdown("### 📝 Choose Your Topic") col1, col2 = st.columns(2) with col1: st.markdown("**Custom Topic:**") custom_topic = st.text_input( "Enter your own topic:", placeholder="Enter your custom topic here...", label_visibility="collapsed" ) if st.button("📝 Set Topic", key="set_custom"): if custom_topic.strip(): st.session_state.selected_topic = custom_topic.strip() st.success("Custom topic set!") with col2: st.markdown("**Predefined Topics:**") selected_topic = st.selectbox( "Choose from list:", options=st.session_state.ai_friends.topics[st.session_state.language], label_visibility="collapsed" ) st.session_state.selected_topic = selected_topic # Main Layout - 2 columns col_left, col_right = st.columns([1, 2]) with col_left: st.markdown("### 🎮 Controls") # Start button if st.button("🎬 Start Conversation", use_container_width=True): if hasattr(st.session_state, 'selected_topic'): st.session_state.current_topic = st.session_state.selected_topic st.session_state.conversation = [] st.session_state.conversation_ready = True st.session_state.is_talking = False st.success("Conversation ready! Click Continue to start.") # Continue button if st.session_state.conversation_ready: if st.button("▶️ Continue", use_container_width=True): st.session_state.is_talking = True # Pause button if st.session_state.is_talking: if st.button("⏸️ Pause", use_container_width=True): st.session_state.is_talking = False # Clear button if st.button("🔄 Clear Chat", use_container_width=True): st.session_state.conversation = [] st.session_state.is_talking = False st.session_state.conversation_ready = False st.session_state.current_topic = "" st.markdown("---") st.markdown("### 💭 Add Your Message") user_message = st.text_area( "Join the conversation:", height=80, placeholder="Type your message..." ) if st.button("📤 Send Message", use_container_width=True): if user_message.strip(): user_name = {"en": "You", "vi": "Bạn", "de": "Du"}[st.session_state.language] st.session_state.conversation.append({ "character": user_name, "message": user_message.strip() }) st.rerun() with col_right: st.markdown("### 💬 Conversation") if st.session_state.current_topic: st.info(f"**Topic:** {st.session_state.current_topic}") # Expanded conversation display with scrollable container st.markdown(""" """, unsafe_allow_html=True) # Create scrollable conversation container conversation_html = '
' if st.session_state.conversation: for msg in st.session_state.conversation: character = msg["character"] message = msg["message"] if character == "Alex": conversation_html += f'
Alex: {message}
' elif character == "Blake": conversation_html += f'
Blake: {message}
' elif character == "Charlie": conversation_html += f'
Charlie: {message}
' else: conversation_html += f'
{character}: {message}
' else: conversation_html += '

Select a topic and start the conversation to see AI friends debate!

' conversation_html += '
' # Display the conversation container st.markdown(conversation_html, unsafe_allow_html=True) # Auto-scroll to bottom script if st.session_state.conversation: st.markdown(""" """, unsafe_allow_html=True) # Auto conversation logic - continues until user pauses if st.session_state.is_talking and st.session_state.current_topic: # Determine next speaker character_order = ["Alex", "Blake", "Charlie"] next_speaker = character_order[len(st.session_state.conversation) % 3] with st.spinner(f"{next_speaker} is thinking..."): response = st.session_state.ai_friends.get_ai_response( next_speaker, st.session_state.conversation, st.session_state.current_topic, st.session_state.language ) st.session_state.conversation.append({ "character": next_speaker, "message": response }) time.sleep(2) # Pause between messages for readability st.rerun() # Bottom Banner st.markdown(f"""
Digitized Brains
Made by Digitized Brains
""", unsafe_allow_html=True) if __name__ == "__main__": main()