Merge pull request #171 from priyanshm07/ai-breakup-recovery-agent-team

Added new Demo: Multi-Agent Breakup Recovery Team
This commit is contained in:
Shubham Saboo 2025-04-07 20:56:56 -05:00 committed by GitHub
commit 0b58ea5838
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 391 additions and 0 deletions

View file

@ -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 <repository_url>
cd breakup-recovery-agent-team
```
2. **Create a Virtual Environment (Optional but Recommended):**
```bash
conda create --name <env_name> python=<version>
conda activate <env_name>
```
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**.
---

View file

@ -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,
)

View file

@ -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.")

View file

@ -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)}"

View file

@ -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