Merge pull request #171 from priyanshm07/ai-breakup-recovery-agent-team
Added new Demo: Multi-Agent Breakup Recovery Team
This commit is contained in:
commit
0b58ea5838
5 changed files with 391 additions and 0 deletions
107
ai_agent_tutorials/ai_breakup_recovery_agent/README.md
Normal file
107
ai_agent_tutorials/ai_breakup_recovery_agent/README.md
Normal 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**.
|
||||
|
||||
---
|
||||
124
ai_agent_tutorials/ai_breakup_recovery_agent/agents.py
Normal file
124
ai_agent_tutorials/ai_breakup_recovery_agent/agents.py
Normal 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,
|
||||
)
|
||||
89
ai_agent_tutorials/ai_breakup_recovery_agent/app.py
Normal file
89
ai_agent_tutorials/ai_breakup_recovery_agent/app.py
Normal 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.")
|
||||
62
ai_agent_tutorials/ai_breakup_recovery_agent/image_input.py
Normal file
62
ai_agent_tutorials/ai_breakup_recovery_agent/image_input.py
Normal 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)}"
|
||||
|
|
@ -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
|
||||
Loading…
Reference in a new issue