diff --git a/ai_agent_tutorials/ai_breakup_recovery_agent/README.md b/ai_agent_tutorials/ai_breakup_recovery_agent/README.md new file mode 100644 index 0000000..4841802 --- /dev/null +++ b/ai_agent_tutorials/ai_breakup_recovery_agent/README.md @@ -0,0 +1,107 @@ + +# 💔 Breakup Recovery Agent Team + +This is an AI-powered application designed to help users emotionally recover from breakups by providing support, guidance, and emotional outlet messages from a team of specialized AI agents. The app is built using **Streamlit** and **Agno**, leveraging **Gemini 2.0 Flash (Google Vision Model) **. + +## 🚀 Features + +- 🧠 **Multi-Agent Team:** + - **Therapist Agent:** Offers empathetic support and coping strategies. + - **Closure Agent:** Writes emotional messages users shouldn't send for catharsis. + - **Routine Planner Agent:** Suggests daily routines for emotional recovery. + - **Brutal Honesty Agent:** Provides direct, no-nonsense feedback on the breakup. +- 📷 **Chat Screenshot Analysis:** + - Upload screenshots for chat analysis. +- 🔑 **API Key Management:** + - Store and manage your OpenAI API keys securely via Streamlit's sidebar. +- ⚡ **Parallel Execution:** + - Agents process inputs in coordination mode for comprehensive results. +- ✅ **User-Friendly Interface:** + - Simple, intuitive UI with easy interaction and display of agent responses. + +--- + +## 🛠️ Tech Stack + +- **Frontend:** Streamlit (Python) +- **AI Models:** Gemini 2.0 Flash (Google Vision Model) +- **Image Processing:** PIL (for displaying screenshots) +- **Text Extraction:** Google's Gemini Vision model to analyze chat screenshots +- **Environment Variables:** API keys managed with `st.session_state` in Streamlit + +--- + +## 📦 Installation + +1. **Clone the Repository:** + ```bash + git clone + cd breakup-recovery-agent-team + ``` + +2. **Create a Virtual Environment (Optional but Recommended):** + ```bash + conda create --name python= + conda activate + ``` + +3. **Install Dependencies:** + ```bash + pip install -r requirements.txt + ``` + +4. **Run the Streamlit App:** + ```bash + streamlit run app.py + ``` + +--- + +## 🔑 Environment Variables + +Make sure to provide your **Gemini API key** in the Streamlit sidebar: + +- GEMINI_API_KEY=your_google_gemini_api_key + +--- + +## 🛠️ Usage + +1. **Enter Your Feelings:** + - Describe how you're feeling in the text area. +2. **Upload Screenshot (Optional):** + - Upload a chat screenshot (PNG, JPG, JPEG) for analysis. +3. **Execute Agents:** + - Click **"Get Recovery Support"** to run the multi-agent team. +4. **View Results:** + - Individual agent responses are displayed. + - A final summary is provided by the Team Leader. + +--- + +## 🧑‍💻 Agents Overview + +- **Therapist Agent** + - Provides empathetic support and coping strategies. + - Uses **Gemini 2.0 Flash (Google Vision Model)** and DuckDuckGo tools for insights. + +- **Closure Agent** + - Generates unsent emotional messages for emotional release. + - Ensures heartfelt and authentic messages. + +- **Routine Planner Agent** + - Creates a daily recovery routine with balanced activities. + - Includes self-reflection, social interaction, and healthy distractions. + +- **Brutal Honesty Agent** + - Offers direct, objective feedback on the breakup. + - Uses factual language with no sugar-coating. + +--- + + +## 📄 License + +This project is licensed under the **MIT License**. + +--- diff --git a/ai_agent_tutorials/ai_breakup_recovery_agent/agents.py b/ai_agent_tutorials/ai_breakup_recovery_agent/agents.py new file mode 100644 index 0000000..3e59ab9 --- /dev/null +++ b/ai_agent_tutorials/ai_breakup_recovery_agent/agents.py @@ -0,0 +1,124 @@ +from agno.agent import Agent +from agno.team.team import Team +from agno.models.google import Gemini +from agno.tools.duckduckgo import DuckDuckGoTools +import os + +# --- Therapist Agent --- +def create_therapist_agent(): + return Agent( + name="Therapist Agent", + role="You are a therapist who validates feelings and encourages reflection without judgment.", + instructions=[ + "Listen to the user's feelings with empathy and compassion.", + "Ask reflective questions to help them explore their emotions.", + "Offer coping strategies without being dismissive.", + "Validate their experiences and provide emotional support.", + ], + model=Gemini( + id="gemini-2.0-flash", + api_key=os.environ.get("GEMINI_API_KEY") + ), + tools=[DuckDuckGoTools()], + add_datetime_to_instructions=True, + show_tool_calls=True, + markdown=True + ) + +# --- Closure Agent --- +def create_closure_agent(): + return Agent( + name="Closure Agent", + role="You write emotional closure messages the user *should not* send.", + instructions=[ + "Create emotional messages that express raw, honest feelings.", + "The messages should NOT be sent — they are only for emotional release.", + "Format the output clearly with a header: **Message Drafts You Shouldn't Send**", + "Ensure the tone is heartfelt, authentic, and honest.", + ], + model=Gemini( + id="gemini-2.0-flash", + api_key=os.environ.get("GEMINI_API_KEY") + ), + tools=[DuckDuckGoTools()], + add_datetime_to_instructions=True, + show_tool_calls=True, + markdown=True + ) + + + # --- Routine Planner Agent --- +def create_routine_agent(): + """Creates the Routine Planner Agent with recovery routines.""" + return Agent( + name="Routine Planner Agent", + role="Create a realistic daily routine to help someone emotionally recover after a breakup.", + instructions=[ + "Suggest a balanced daily routine with healthy habits.", + "Include time for self-reflection, creative outlets, and physical activities.", + "Suggest social interactions, like reconnecting with friends or family.", + "Include healthy distractions, such as hobbies, reading, or new experiences.", + "Format the output clearly with a header: **Daily Recovery Routine**", + ], + model=Gemini( + id="gemini-2.0-flash", + api_key=os.environ.get("GEMINI_API_KEY") + ), + tools=[DuckDuckGoTools()], + add_datetime_to_instructions=True, + show_tool_calls=True, + markdown=True + ) + +# --- Brutal Honesty Agent --- +def create_honesty_agent(): + """Creates the Brutal Honesty Agent with no-nonsense, direct responses.""" + return Agent( + name="Brutal Honesty Agent", + role="Be brutally honest and objective about what went wrong and why the user needs to move on. No sugar-coating.", + instructions=[ + "Give raw, direct, and objective feedback about the breakup.", + "Explain why the relationship failed with clear, straightforward reasoning.", + "Use blunt, factual language. No sugar-coating or emotional cushioning.", + "Include reasons why the user should move on, based on the situation.", + "Format the output clearly with a header: **Brutal Honesty**", + ], + model=Gemini( + id="gemini-2.0-flash", + api_key=os.environ.get("GEMINI_API_KEY") + ), + tools=[DuckDuckGoTools()], + add_datetime_to_instructions=True, + show_tool_calls=True, + markdown=True + ) + +# --- Team Leader (Breakup Recovery Team) --- +def create_breakup_team(): + return Team( + name="Breakup Recovery Team", + mode="coordinate", # Team execution mode: coordinate or parallel + model=Gemini( + id="gemini-2.0-flash", + api_key=os.environ.get("GEMINI_API_KEY") + ), + members=[ + create_therapist_agent(), + create_closure_agent(), + create_routine_agent(), + create_honesty_agent(), + ], + description="You are a team helping someone recover from a breakup.", + instructions=[ + "First, ask the Therapist Agent to help the user explore their emotions.", + "Then, ask the Closure Agent to create unsent emotional messages.", + "Next, ask the Routine Planner Agent to suggest a healthy daily routine.", + "Finally, ask the Brutal Honesty Agent to give direct and objective feedback.", + "Summarize and refine all responses into a personalized recovery guide.", + "Ensure the responses are supportive, encouraging, and insightful.", + "Use markdown formatting for clear, readable output.", + ], + add_datetime_to_instructions=True, # Add timestamp context + show_members_responses=True, # Display individual agent responses + markdown=True, + ) diff --git a/ai_agent_tutorials/ai_breakup_recovery_agent/app.py b/ai_agent_tutorials/ai_breakup_recovery_agent/app.py new file mode 100644 index 0000000..f36f852 --- /dev/null +++ b/ai_agent_tutorials/ai_breakup_recovery_agent/app.py @@ -0,0 +1,89 @@ +import streamlit as st +from agents import create_breakup_team +from image_input import analyze_chat_screenshot +from PIL import Image + +# --- Streamlit Layout --- +st.title("💔 Breakup Recovery Agent Team") +st.write("Receive support and emotional outlet messages from specialized AI agents.") + +# --- API Keys Input --- +gemini_api_key = st.sidebar.text_input("Gemini API Key", type="password") +submit_button = st.sidebar.button("Submit") + +# --- Store API Keys --- +if submit_button: + if gemini_api_key: + st.session_state["gemini_api_key"] = gemini_api_key + st.success("API key saved successfully!") + else: + st.error("Please enter the API key!") + +# --- User Input --- +user_input = st.text_area("Describe how you're feeling...") + +# --- Image Upload --- +uploaded_image = st.file_uploader("Upload a chat screenshot (optional)", type=["png", "jpg", "jpeg"]) + +# --- Display Uploaded Image and Analysis --- +if uploaded_image: + image = Image.open(uploaded_image) + st.image(image, caption="Uploaded Screenshot", use_column_width=True) + + if st.button("Analyze Chat"): + with st.spinner("Analyzing chat patterns..."): + if not st.session_state.get("gemini_api_key"): + st.error("Please enter your Gemini API key in the sidebar first.") + else: + try: + # Set environment variable for the analysis + import os + os.environ["GEMINI_API_KEY"] = st.session_state["gemini_api_key"] + + # Analyze the chat screenshot + analysis = analyze_chat_screenshot(uploaded_image) + + # Display the analysis + st.subheader("🔍 Chat Analysis") + st.markdown(analysis) + except Exception as e: + st.error(f"An error occurred during analysis: {str(e)}") + st.info("Please check your Gemini API key and try again.") + +# --- Execute Agent Team (only for text input) --- +if st.button("Get Recovery Support"): + with st.spinner("Agents are processing..."): + if not user_input: + st.error("Please enter what you feel.") + elif not st.session_state.get("gemini_api_key"): + st.error("Please enter your Gemini API key in the sidebar first.") + else: + try: + breakup_team = create_breakup_team() + + # Set environment variables + import os + os.environ["GEMINI_API_KEY"] = st.session_state["gemini_api_key"] + + # Execute the team with text input + response = breakup_team.run(user_input) + + # Display responses + st.subheader("💡 Team's Responses") + + # Display individual agent responses + if response.member_responses: + for index, member_response in enumerate(response.member_responses, start=0): + st.markdown(f"### 🛡️ {response.tools[index]['tool_args']['agent_name']}") + st.markdown(member_response.content) + else: + st.warning("⚠️ No individual agent responses received. This might be due to an API error or configuration issue.") + st.info("Please check your Gemini API key and try again.") + + # Display team leader's final summary + if response.content: + st.subheader("📜 Team Leader's Summary") + st.markdown(response.content) + except Exception as e: + st.error(f"An error occurred: {str(e)}") + st.info("Please check your Gemini API key and try again.") diff --git a/ai_agent_tutorials/ai_breakup_recovery_agent/image_input.py b/ai_agent_tutorials/ai_breakup_recovery_agent/image_input.py new file mode 100644 index 0000000..0075f0a --- /dev/null +++ b/ai_agent_tutorials/ai_breakup_recovery_agent/image_input.py @@ -0,0 +1,62 @@ +from agno.agent import Agent +from agno.media import Image +from agno.models.google import Gemini +from agno.tools.duckduckgo import DuckDuckGoTools +from PIL import Image as PILImage +from io import BytesIO +import os + +def load_image(image_data): + """Load and prepare image using PIL""" + # Convert image data to PIL Image + img = PILImage.open(image_data).convert('RGB') + + # Convert PIL image to bytes + buffered = BytesIO() + img.save(buffered, format="JPEG") + img_bytes = buffered.getvalue() + + return img_bytes + +def create_chat_analysis_agent(): + """Creates a specialized agent for analyzing chat patterns""" + return Agent( + name="Chat Analysis Agent", + role="You are a specialized agent that analyzes chat screenshots for relationship patterns and communication issues.", + instructions=[ + "Analyze the chat screenshot for the following patterns:", + "1. Communication Patterns: Identify recurring themes, response times, and conversation flow", + "2. Passive-Aggression: Look for subtle hostile or manipulative language", + "3. Manipulation: Identify gaslighting, guilt-tripping, or controlling behaviors", + "4. Mixed Signals: Detect inconsistent messages or unclear intentions", + "Provide a detailed analysis with specific examples from the chat", + "Format the output clearly with sections for each pattern type", + "Be objective and focus on observable patterns rather than making assumptions", + ], + model=Gemini( + id="gemini-2.0-flash", + api_key=os.environ.get("GEMINI_API_KEY") + ), + tools=[DuckDuckGoTools()], + markdown=True, + ) + +def analyze_chat_screenshot(image_data): + """Analyze a chat screenshot using the specialized agent""" + try: + # Load and process the image + image_bytes = load_image(image_data) + + # Create the chat analysis agent + agent = create_chat_analysis_agent() + + # Analyze the chat screenshot + response = agent.run( + "Please analyze this chat screenshot for communication patterns, passive-aggression, manipulation, and mixed signals.", + images=[Image(content=image_bytes)] + ) + + return response.content + + except Exception as e: + return f"Error analyzing chat screenshot: {str(e)}" \ No newline at end of file diff --git a/ai_agent_tutorials/ai_breakup_recovery_agent/requirements.txt b/ai_agent_tutorials/ai_breakup_recovery_agent/requirements.txt new file mode 100644 index 0000000..9a97ff1 --- /dev/null +++ b/ai_agent_tutorials/ai_breakup_recovery_agent/requirements.txt @@ -0,0 +1,9 @@ +streamlit==1.44.0 +torch==1.13.0 +torchvision==0.14.0 +scikit-image==0.24.0 +scipy==1.13.1 +pillow=11.1.0 +tqdm==4.67.1 +websockets==15.0.1 +typer==0.15.2