diff --git a/ai_agent_tutorials/ai_breakup_recovery_agent/.gitignore b/ai_agent_tutorials/ai_breakup_recovery_agent/.gitignore new file mode 100644 index 0000000..cb4801b --- /dev/null +++ b/ai_agent_tutorials/ai_breakup_recovery_agent/.gitignore @@ -0,0 +1,42 @@ +# Python-related +__pycache__/ +*.pyc +*.pyo +*.pyd +*.db +*.sqlite3 +*.log +*.json + +# Environment and secrets +.env +*.env + +# Streamlit cache and temporary files +.streamlit/ +.history/ +.cache/ +*.stcache +.stcache/ + +# Logs and temp files +*.log +*.out +*.err + +# IDE and editor config files +.vscode/ +.idea/ +*.swp +*.swo +*.bak +*.tmp + +# System files +.DS_Store +Thumbs.db + +# OCR and image processing cache (if any) +~/.EasyOCR/ +*.easyocr +*.txt 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..757683c --- /dev/null +++ b/ai_agent_tutorials/ai_breakup_recovery_agent/agents.py @@ -0,0 +1,122 @@ +from agno.agent import Agent +from agno.team.team import Team +from agno.models.openai import OpenAIChat +from agno.tools.duckduckgo import DuckDuckGoTools +from PIL import Image +import easyocr + +# --- 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=OpenAIChat(id="gpt-4o-mini"), + tools=[DuckDuckGoTools()], + add_datetime_to_instructions=True, # Add timestamp context + 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=OpenAIChat(id="gpt-4o-mini"), + tools=[DuckDuckGoTools()], + add_datetime_to_instructions=True, # Add timestamp context + 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=OpenAIChat(id="gpt-4o-mini"), + 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=OpenAIChat(id="gpt-4o-mini"), + tools=[DuckDuckGoTools()], + add_datetime_to_instructions=True, + show_tool_calls=True, + markdown=True + ) + + +# # --- Texts Analyzer Agent (Updated with easyocr) --- +# def extract_text_with_easyocr(image): +# """Extract text from image using EasyOCR.""" +# reader = easyocr.Reader(['en']) # Specify language +# results = reader.readtext(image) + +# # Extract and combine text +# extracted_text = " ".join([result[1] for result in results]) +# return extracted_text + +# --- Team Leader (Breakup Recovery Team) --- +def create_breakup_team(): + return Team( + name="Breakup Recovery Team", + mode="coordinate", # Team execution mode: coordinate or parallel + model=OpenAIChat(id="gpt-4o-mini"), + members=[ + create_therapist_agent(), + create_closure_agent(), + create_routine_agent(), # Added Routine Planner Agent + create_honesty_agent(), # Added Brutal Honesty Agent + # extract_text_with_easyocr() + ], + 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..13d1c73 --- /dev/null +++ b/ai_agent_tutorials/ai_breakup_recovery_agent/app.py @@ -0,0 +1,72 @@ +import streamlit as st +from agents import create_breakup_team +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 --- +openai_api_key = st.sidebar.text_input("OpenAI API Key", type="password") +submit_button = st.sidebar.button("Submit") + +# --- Store API Keys --- +if submit_button: + if openai_api_key: + st.session_state["openai_api_key"] = openai_api_key + st.success("API keys saved successfully!") + else: + st.error("Please enter both API keys!") + +# --- User Input --- +user_input = st.text_area("Describe how you're feeling...") +print(user_input) + +# --- Image Upload --- +uploaded_image = st.file_uploader("Upload a chat screenshot (optional)", type=["png", "jpg", "jpeg"]) + +# --- Display Uploaded Image --- +extracted_text = "" +if uploaded_image: + image = Image.open(uploaded_image) + st.image(image, caption="Uploaded Screenshot", use_column_width=True) + + # # ✅ Extract text from the image + # extracted_text = extract_text_with_easyocr(image) + # st.text_area("Extracted Text from Image:", extracted_text) + +# --- Execute Agent Team --- +if st.button("Get Recovery Support"): + with st.spinner("Agents are processing..."): + if not user_input and not uploaded_image: + st.error("Please enter what you feel.") + else: + breakup_team = create_breakup_team() + + # Set environment variables + import os + os.environ["OPENAI_API_KEY"] = st.session_state.get("openai_api_key", "") + # os.environ["AGNO_API_KEY"] = st.session_state.get("agno_api_key", "") + + # Prepare the input + input_data = user_input + if uploaded_image: + input_data += "\n\n[Attached Image Included]" # Add image indicator + + # Execute the team + response = breakup_team.run(user_input) + + # Display responses + st.subheader("💡 Team's Responses") + + # Display individual agent responses + if response.member_responses: + for member_response in response.member_responses: + st.markdown(f"### 🛡️ {member_response.agent_id}") + st.write(member_response.content) + else: + st.warning("⚠️ No individual agent responses received. Showing team leader's summary only.") + + # Display team leader's final summary + st.subheader("📜 Team Leader's Summary") + st.write(response.content)