``` ├── .gitignore ├── LICENSE ├── README.md ├── advanced_ai_agents/ ├── autonomous_game_playing_agent_apps/ ├── ai_3dpygame_r1/ ├── README.md ├── ai_3dpygame_r1.py ├── requirements.txt ├── ai_chess_agent/ ├── README.md ├── ai_chess_agent.py ├── requirements.txt ├── ai_tic_tac_toe_agent/ ├── README.md ├── agents.py ├── app.py ├── requirements.txt ├── utils.py ├── multi_agent_apps/ ├── agent_teams/ ├── ai_competitor_intelligence_agent_team/ ├── README.md ├── competitor_agent_team.py ├── requirements.txt ├── ai_finance_agent_team/ ├── README.md ├── finance_agent_team.py ├── requirements.txt ├── ai_game_design_agent_team/ ├── README.md ├── game_design_agent_team.py ├── requirements.txt ├── ai_legal_agent_team/ ├── README.md ├── legal_agent_team.py ├── local_ai_legal_agent_team/ ├── README.md ├── local_legal_agent.py ├── requirements.txt ├── requirements.txt ├── ai_recruitment_agent_team/ ├── README.md ├── ai_recruitment_agent_team.py ├── requirements.txt ├── ai_services_agency/ ├── README.md ├── agency.py ├── requirements.txt ├── ai_teaching_agent_team/ ├── README.md ├── requirements.txt ├── teaching_agent_team.py ├── multimodal_coding_agent_team/ ├── README.md ├── ai_coding_agent_o3.py ├── requirements.txt ├── multimodal_design_agent_team/ ├── README.md ├── design_agent_team.py ├── requirements.txt ├── ai_aqi_analysis_agent/ ├── README.md ├── ai_aqi_analysis_agent_gradio.py ``` ## /.gitignore ```gitignore path="/.gitignore" ``` ## /LICENSE ``` path="/LICENSE" Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ``` ## /README.md

Unwind AI

LinkedIn Twitter


# 🌟 Awesome LLM Apps A curated collection of awesome LLM apps built with RAG and AI agents. This repository features LLM apps that use models from OpenAI, Anthropic, Google, and open-source models like DeepSeek, Qwen or Llama that you can run locally on your computer.

Shubhamsaboo%2Fawesome-llm-apps | Trendshift

## 🤔 Why Awesome LLM Apps? - 💡 Discover practical and creative ways LLMs can be applied across different domains, from code repositories to email inboxes and more. - 🔥 Explore apps that combine LLMs from OpenAI, Anthropic, Gemini, and open-source alternatives with RAG and AI Agents. - 🎓 Learn from well-documented projects and contribute to the growing open-source ecosystem of LLM-powered applications. ## 🚨 Open Source AI Agent Hackathon We're launching a Global AI Agent Hackathon in collaboration with AI Agent ecosystem partners — open to all developers, builders, and startups working on agents, RAG, tool use, or multi-agent systems. - Win up to **$25,000** in cash by building Agents - Top 5 projects will be featured in the top trending [Awesome LLM Apps](https://github.com/Shubhamsaboo/awesome-llm-apps) repo. - **$20,000** worth of API and tool use credits from the partners ### Participate Now: [Global AI Agent Hackathon](https://github.com/global-agent-hackathon/global-agent-hackathon-may-2025) ⭐ Star this repo and subscribe to [Unwind AI](https://www.theunwindai.com) for latest updates. ## 📂 Featured AI Projects ### AI Agents #### 🌱 Starter AI Agents * [🎙️ AI Blog to Podcast Agent](starter_ai_agents/ai_blog_to_podcast_agent/) * [❤️‍🩹 AI Breakup Recovery Agent](starter_ai_agents/ai_breakup_recovery_agent/) * [📊 AI Data Analysis Agent](starter_ai_agents/ai_data_analysis_agent/) * [🩻 AI Medical Imaging Agent](starter_ai_agents/ai_medical_imaging_agent/) * [😂 AI Meme Generator Agent (Browser)](starter_ai_agents/ai_meme_generator_agent_browseruse/) * [🎵 AI Music Generator Agent](starter_ai_agents/ai_music_generator_agent/) * [🛫 AI Travel Agent (Local & Cloud)](starter_ai_agents/ai_travel_agent/) * [✨ Gemini Multimodal Agent](starter_ai_agents/gemini_multimodal_agent_demo/) * [🌐 Local News Agent (OpenAI Swarm)](starter_ai_agents/local_news_agent_openai_swarm/) * [🔄 Mixture of Agents](starter_ai_agents/mixture_of_agents/) * [📊 xAI Finance Agent](starter_ai_agents/xai_finance_agent/) * [🔍 OpenAI Research Agent](starter_ai_agents/opeani_research_agent/) * [🕸️ Web Scrapping AI Agent (Local & Cloud)](starter_ai_agents/web_scrapping_ai_agent/) #### 🚀 Advanced AI Agents * [🔍 AI Deep Research Agent](advanced_ai_agents/single_agent_apps/ai_deep_research_agent/) * [🏗️ AI System Architect Agent](advanced_ai_agents/single_agent_apps/ai_system_architect_r1/) * [🎯 AI Lead Generation Agent](advanced_ai_agents/single_agent_apps/ai_lead_generation_agent/) * [💰 AI Financial Coach Agent](advanced_ai_agents/multi_agent_apps/ai_financial_coach_agent/) * [🎬 AI Movie Production Agent](advanced_ai_agents/single_agent_apps/ai_movie_production_agent/) * [🏠 AI Real Estate Agent](advanced_ai_agents/single_agent_apps/ai_real_estate_agent/) * [📈 AI Investment Agent](advanced_ai_agents/single_agent_apps/ai_investment_agent/) * [🏋️‍♂️ AI Health & Fitness Agent](advanced_ai_agents/single_agent_apps/ai_health_fitness_agent/) * [🗞️ AI Journalist Agent](advanced_ai_agents/single_agent_apps/ai_journalist_agent/) * [🧠 AI Mental Wellbeing Agent](advanced_ai_agents/multi_agent_apps/ai_mental_wellbeing_agent/) * [📑 AI Meeting Agent](advanced_ai_agents/single_agent_apps/ai_meeting_agent/) #### 🎮 Autonomous Game Playing Agents * [🎮 AI 3D Pygame Agent](advanced_ai_agents/autonomous_game_playing_agent_apps/ai_3dpygame_r1/) * [♜ AI Chess Agent](advanced_ai_agents/autonomous_game_playing_agent_apps/ai_chess_agent/) * [🎲 AI Tic-Tac-Toe Agent](advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/) #### 🤝 Multi-agent Teams * [🧲 AI Competitor Intelligence Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_competitor_intelligence_agent_team/) * [💲 AI Finance Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_finance_agent_team/) * [🎨 AI Game Design Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_game_design_agent_team/) * [👨‍⚖️ AI Legal Agent Team (Cloud & Local)](advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/) * [💼 AI Recruitment Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_recruitment_agent_team/) * [👨‍💼 AI Services Agency (CrewAI)](advanced_ai_agents/multi_agent_apps/agent_teams/ai_services_agency/) * [👨‍🏫 AI Teaching Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/ai_teaching_agent_team/) * [💻 Multimodal Coding Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_coding_agent_team/) * [✨ Multimodal Design Agent Team](advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_design_agent_team/) ### 🗣️ Voice AI Agents * [🗣️ AI Audio Tour Agent](voice_ai_agents/ai_audio_tour_agent/) * [📞 Customer Support Voice Agent](voice_ai_agents/customer_support_voice_agent/) * [🔊 Voice RAG Agent (OpenAI SDK)](voice_ai_agents/voice_rag_openaisdk/) ### 🌐 MCP AI Agents * [♾️ MCP Browser Agent](mcp_ai_agents/browser_mcp_agent/) * [🐙 MCP GitHub Agent](mcp_ai_agents/github_mcp_agent/) ### RAG (Retrieval Augmented Generation) * [🔗 Agentic RAG](rag_tutorials/agentic_rag/) * [📰 AI Blog Search (RAG)](rag_tutorials/ai_blog_search/) * [🔍 Autonomous RAG](rag_tutorials/autonomous_rag/) * [🔄 Corrective RAG (CRAG)](rag_tutorials/corrective_rag/) * [🐋 Deepseek Local RAG Agent](rag_tutorials/deepseek_local_rag_agent/) * [🤔 Gemini Agentic RAG](rag_tutorials/gemini_agentic_rag/) * [👀 Hybrid Search RAG (Cloud)](rag_tutorials/hybrid_search_rag/) * [🔄 Llama 3.1 Local RAG](rag_tutorials/llama3.1_local_rag/) * [🖥️ Local Hybrid Search RAG](rag_tutorials/local_hybrid_search_rag/) * [🦙 Local RAG Agent](rag_tutorials/local_rag_agent/) * [🧩 RAG-as-a-Service](rag_tutorials/rag-as-a-service/) * [✨ RAG Agent with Cohere](rag_tutorials/rag_agent_cohere/) * [⛓️ Basic RAG Chain](rag_tutorials/rag_chain/) * [📠 RAG with Database Routing](rag_tutorials/rag_database_routing/) ### MCP AI Agents - [🐙 MCP GitHub Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/mcp_ai_agents/github_mcp_agent) - [♾️ MCP Browser Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/mcp_ai_agents/browser_mcp_agent) ### 🧠 Advanced LLM Apps #### 💬 Chat with X Tutorials * [💬 Chat with GitHub (GPT & Llama3)](advanced_llm_apps/chat_with_X_tutorials/chat_with_github/) * [📨 Chat with Gmail](advanced_llm_apps/chat_with_X_tutorials/chat_with_gmail/) * [📄 Chat with PDF (GPT & Llama3)](advanced_llm_apps/chat_with_X_tutorials/chat_with_pdf/) * [📚 Chat with Research Papers (ArXiv) (GPT & Llama3)](advanced_llm_apps/chat_with_X_tutorials/chat_with_research_papers/) * [📝 Chat with Substack](advanced_llm_apps/chat_with_X_tutorials/chat_with_substack/) * [📽️ Chat with YouTube Videos](advanced_llm_apps/chat_with_X_tutorials/chat_with_youtube_videos/) #### 💾 LLM Apps with Memory Tutorials * [💾 AI ArXiv Agent with Memory](advanced_llm_apps/llm_apps_with_memory_tutorials/ai_arxiv_agent_memory/) * [🛩️ AI Travel Agent with Memory](advanced_llm_apps/llm_apps_with_memory_tutorials/ai_travel_agent_memory/) * [💬 Llama3 Stateful Chat](advanced_llm_apps/llm_apps_with_memory_tutorials/llama3_stateful_chat/) * [📝 LLM App with Personalized Memory](advanced_llm_apps/llm_apps_with_memory_tutorials/llm_app_personalized_memory/) * [🗄️ Local ChatGPT Clone with Memory](advanced_llm_apps/llm_apps_with_memory_tutorials/local_chatgpt_with_memory/) * [🧠 Multi-LLM Application with Shared Memory](advanced_llm_apps/llm_apps_with_memory_tutorials/multi_llm_memory/) #### 🔧 LLM Fine-tuning Tutorials * [🔧 Llama 3.2 Fine-tuning](advanced_llm_apps/llm_finetuning_tutorials/llama3.2_finetuning/) ## 🚀 Getting Started 1. **Clone the repository** ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git ``` 2. **Navigate to the desired project directory** ```bash cd awesome-llm-apps/starter_ai_agents/ai_travel_agent ``` 3. **Install the required dependencies** ```bash pip install -r requirements.txt ``` 4. **Follow the project-specific instructions** in each project's `README.md` file to set up and run the app. ## 🤝 Contributing to Open Source Contributions are welcome! If you have any ideas, improvements, or new apps to add, please create a new [GitHub Issue](https://github.com/Shubhamsaboo/awesome-llm-apps/issues) or submit a pull request. Make sure to follow the existing project structure and include a detailed `README.md` for each new app. ### Thank You, Community, for the Support! 🙏 [![Star History Chart](https://api.star-history.com/svg?repos=Shubhamsaboo/awesome-llm-apps&type=Date)](https://star-history.com/#Shubhamsaboo/awesome-llm-apps&Date) 🌟 **Don’t miss out on future updates! Star the repo now and be the first to know about new and exciting LLM apps with RAG and AI Agents.** ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_3dpygame_r1/README.md # 🎮 AI 3D PyGame Visualizer with DeepSeek R1 This Project demonstrates R1's code capabilities with a PyGame code generator and visualizer with browser use. The system uses DeepSeek for reasoning, OpenAI for code extraction, and browser automation agents to visualize the code on Trinket.io. ### Features - Generates PyGame code from natural language descriptions - Uses DeepSeek Reasoner for code logic and explanation - Extracts clean code using OpenAI GPT-4o - Automates code visualization on Trinket.io using browser agents - Provides a streamlined Streamlit interface - Multi-agent system for handling different tasks (navigation, coding, execution, viewing) ### How to get Started? 1. Clone the GitHub repository ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd awesome-llm-apps/ai_agent_tutorials/ai_3dpygame_r1 ``` 2. Install the required dependencies: ```bash pip install -r requirements.txt ``` 3. Get your API Keys - Sign up for [DeepSeek](https://platform.deepseek.com/) and obtain your API key - Sign up for [OpenAI](https://platform.openai.com/) and obtain your API key 4. Run the AI PyGame Visualizer ```bash streamlit run ai_3dpygame_r1.py ``` 5. Browser use automatically opens your web browser and navigate to the URL provided in the console output to interact with the PyGame generator. ### How it works? 1. **Query Processing:** User enters a natural language description of the desired PyGame visualization. 2. **Code Generation:** - DeepSeek Reasoner analyzes the query and provides detailed reasoning with code - OpenAI agent extracts clean, executable code from the reasoning 3. **Visualization:** - Browser agents automate the process of running code on Trinket.io - Multiple specialized agents handle different tasks: - Navigation to Trinket.io - Code input - Execution - Visualization viewing 4. **User Interface:** Streamlit provides an intuitive interface for entering queries, viewing code, and managing the visualization process. ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_3dpygame_r1/ai_3dpygame_r1.py ```py path="/advanced_ai_agents/autonomous_game_playing_agent_apps/ai_3dpygame_r1/ai_3dpygame_r1.py" import streamlit as st from openai import OpenAI from agno.agent import Agent as AgnoAgent from agno.models.openai import OpenAIChat as AgnoOpenAIChat from langchain_openai import ChatOpenAI import asyncio from browser_use import Browser st.set_page_config(page_title="PyGame Code Generator", layout="wide") # Initialize session state if "api_keys" not in st.session_state: st.session_state.api_keys = { "deepseek": "", "openai": "" } # Streamlit sidebar for API keys with st.sidebar: st.title("API Keys Configuration") st.session_state.api_keys["deepseek"] = st.text_input( "DeepSeek API Key", type="password", value=st.session_state.api_keys["deepseek"] ) st.session_state.api_keys["openai"] = st.text_input( "OpenAI API Key", type="password", value=st.session_state.api_keys["openai"] ) st.markdown("---") st.info(""" 📝 How to use: 1. Enter your API keys above 2. Write your PyGame visualization query 3. Click 'Generate Code' to get the code 4. Click 'Generate Visualization' to: - Open Trinket.io PyGame editor - Copy and paste the generated code - Watch it run automatically """) # Main UI st.title("🎮 AI 3D Visualizer with DeepSeek R1") example_query = "Create a particle system simulation where 100 particles emit from the mouse position and respond to keyboard-controlled wind forces" query = st.text_area( "Enter your PyGame query:", height=70, placeholder=f"e.g.: {example_query}" ) # Split the buttons into columns col1, col2 = st.columns(2) generate_code_btn = col1.button("Generate Code") generate_vis_btn = col2.button("Generate Visualization") if generate_code_btn and query: if not st.session_state.api_keys["deepseek"] or not st.session_state.api_keys["openai"]: st.error("Please provide both API keys in the sidebar") st.stop() # Initialize Deepseek client deepseek_client = OpenAI( api_key=st.session_state.api_keys["deepseek"], base_url="https://api.deepseek.com" ) system_prompt = """You are a Pygame and Python Expert that specializes in making games and visualisation through pygame and python programming. During your reasoning and thinking, include clear, concise, and well-formatted Python code in your reasoning. Always include explanations for the code you provide.""" try: # Get reasoning from Deepseek with st.spinner("Generating solution..."): deepseek_response = deepseek_client.chat.completions.create( model="deepseek-reasoner", messages=[ {"role": "system", "content": system_prompt}, {"role": "user", "content": query} ], max_tokens=1 ) reasoning_content = deepseek_response.choices[0].message.reasoning_content print("\nDeepseek Reasoning:\n", reasoning_content) with st.expander("R1's Reasoning"): st.write(reasoning_content) # Initialize Claude agent (using PhiAgent) openai_agent = AgnoAgent( model=AgnoOpenAIChat( id="gpt-4o", api_key=st.session_state.api_keys["openai"] ), show_tool_calls=True, markdown=True ) # Extract code extraction_prompt = f"""Extract ONLY the Python code from the following content which is reasoning of a particular query to make a pygame script. Return nothing but the raw code without any explanations, or markdown backticks: {reasoning_content}""" with st.spinner("Extracting code..."): code_response = openai_agent.run(extraction_prompt) extracted_code = code_response.content # Store the generated code in session state st.session_state.generated_code = extracted_code # Display the code with st.expander("Generated PyGame Code", expanded=True): st.code(extracted_code, language="python") st.success("Code generated successfully! Click 'Generate Visualization' to run it.") except Exception as e: st.error(f"An error occurred: {str(e)}") elif generate_vis_btn: if "generated_code" not in st.session_state: st.warning("Please generate code first before visualization") else: async def run_pygame_on_trinket(code: str) -> None: browser = Browser() from browser_use import Agent async with await browser.new_context() as context: model = ChatOpenAI( model="gpt-4o", api_key=st.session_state.api_keys["openai"] ) agent1 = Agent( task='Go to https://trinket.io/features/pygame, thats your only job.', llm=model, browser_context=context, ) executor = Agent( task='Executor. Execute the code written by the User by clicking on the run button on the right. ', llm=model, browser_context=context ) coder = Agent( task='Coder. Your job is to wait for the user for 10 seconds to write the code in the code editor.', llm=model, browser_context=context ) viewer = Agent( task='Viewer. Your job is to just view the pygame window for 10 seconds.', llm=model, browser_context=context, ) with st.spinner("Running code on Trinket..."): try: await agent1.run() await coder.run() await executor.run() await viewer.run() st.success("Code is running on Trinket!") except Exception as e: st.error(f"Error running code on Trinket: {str(e)}") st.info("You can still copy the code above and run it manually on Trinket") # Run the async function with the stored code asyncio.run(run_pygame_on_trinket(st.session_state.generated_code)) elif generate_code_btn and not query: st.warning("Please enter a query before generating code") ``` ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_3dpygame_r1/requirements.txt agno langchain-openai browser-use streamlit ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_chess_agent/README.md # ♜ Agent White vs Agent Black: Chess Game An advanced Chess game system where two AI agents play chess against each other using Autogen in a streamlit app. It is built with robust move validation and game state management. ## Features ### Multi-Agent Architecture - Player White: OpenAI-powered strategic decision maker - Player Black: OpenAI-powered tactical opponent - Board Proxy: Validation agent for move legality and game state ### Safety & Validation - Robust move verification system - Illegal move prevention - Real-time board state monitoring - Secure game progression control ### Strategic Gameplay - AI-powered position evaluation - Deep tactical analysis - Dynamic strategy adaptation - Complete chess ruleset implementation ### How to get Started? 1. Clone the GitHub repository ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd ai_agent_tutorials/ai_chess_game ``` 2. Install the required dependencies: ```bash pip install -r requirements.txt ``` 3. Get your OpenAI API Key - Sign up for an [OpenAI account](https://platform.openai.com/) (or the LLM provider of your choice) and obtain your API key. 4. Run the Streamlit App ```bash streamlit run ai_chess_agent.py ``` ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_chess_agent/ai_chess_agent.py ```py path="/advanced_ai_agents/autonomous_game_playing_agent_apps/ai_chess_agent/ai_chess_agent.py" import chess import chess.svg import streamlit as st from autogen import ConversableAgent, register_function if "openai_api_key" not in st.session_state: st.session_state.openai_api_key = None if "board" not in st.session_state: st.session_state.board = chess.Board() if "made_move" not in st.session_state: st.session_state.made_move = False if "board_svg" not in st.session_state: st.session_state.board_svg = None if "move_history" not in st.session_state: st.session_state.move_history = [] if "max_turns" not in st.session_state: st.session_state.max_turns = 5 st.sidebar.title("Chess Agent Configuration") openai_api_key = st.sidebar.text_input("Enter your OpenAI API key:", type="password") if openai_api_key: st.session_state.openai_api_key = openai_api_key st.sidebar.success("API key saved!") st.sidebar.info(""" For a complete chess game with potential checkmate, it would take max_turns > 200 approximately. However, this will consume significant API credits and a lot of time. For demo purposes, using 5-10 turns is recommended. """) max_turns_input = st.sidebar.number_input( "Enter the number of turns (max_turns):", min_value=1, max_value=1000, value=st.session_state.max_turns, step=1 ) if max_turns_input: st.session_state.max_turns = max_turns_input st.sidebar.success(f"Max turns of total chess moves set to {st.session_state.max_turns}!") st.title("Chess with AutoGen Agents") def available_moves() -> str: available_moves = [str(move) for move in st.session_state.board.legal_moves] return "Available moves are: " + ",".join(available_moves) def execute_move(move: str) -> str: try: chess_move = chess.Move.from_uci(move) if chess_move not in st.session_state.board.legal_moves: return f"Invalid move: {move}. Please call available_moves() to see valid moves." # Update board state st.session_state.board.push(chess_move) st.session_state.made_move = True # Generate and store board visualization board_svg = chess.svg.board(st.session_state.board, arrows=[(chess_move.from_square, chess_move.to_square)], fill={chess_move.from_square: "gray"}, size=400) st.session_state.board_svg = board_svg st.session_state.move_history.append(board_svg) # Get piece information moved_piece = st.session_state.board.piece_at(chess_move.to_square) piece_unicode = moved_piece.unicode_symbol() piece_type_name = chess.piece_name(moved_piece.piece_type) piece_name = piece_type_name.capitalize() if piece_unicode.isupper() else piece_type_name # Generate move description from_square = chess.SQUARE_NAMES[chess_move.from_square] to_square = chess.SQUARE_NAMES[chess_move.to_square] move_desc = f"Moved {piece_name} ({piece_unicode}) from {from_square} to {to_square}." if st.session_state.board.is_checkmate(): winner = 'White' if st.session_state.board.turn == chess.BLACK else 'Black' move_desc += f"\nCheckmate! {winner} wins!" elif st.session_state.board.is_stalemate(): move_desc += "\nGame ended in stalemate!" elif st.session_state.board.is_insufficient_material(): move_desc += "\nGame ended - insufficient material to checkmate!" elif st.session_state.board.is_check(): move_desc += "\nCheck!" return move_desc except ValueError: return f"Invalid move format: {move}. Please use UCI format (e.g., 'e2e4')." def check_made_move(msg): if st.session_state.made_move: st.session_state.made_move = False return True else: return False if st.session_state.openai_api_key: try: agent_white_config_list = [ { "model": "gpt-4o-mini", "api_key": st.session_state.openai_api_key, }, ] agent_black_config_list = [ { "model": "gpt-4o-mini", "api_key": st.session_state.openai_api_key, }, ] agent_white = ConversableAgent( name="Agent_White", system_message="You are a professional chess player and you play as white. " "First call available_moves() first, to get list of legal available moves. " "Then call execute_move(move) to make a move.", llm_config={"config_list": agent_white_config_list, "cache_seed": None}, ) agent_black = ConversableAgent( name="Agent_Black", system_message="You are a professional chess player and you play as black. " "First call available_moves() first, to get list of legal available moves. " "Then call execute_move(move) to make a move.", llm_config={"config_list": agent_black_config_list, "cache_seed": None}, ) game_master = ConversableAgent( name="Game_Master", llm_config=False, is_termination_msg=check_made_move, default_auto_reply="Please make a move.", human_input_mode="NEVER", ) register_function( execute_move, caller=agent_white, executor=game_master, name="execute_move", description="Call this tool to make a move.", ) register_function( available_moves, caller=agent_white, executor=game_master, name="available_moves", description="Get legal moves.", ) register_function( execute_move, caller=agent_black, executor=game_master, name="execute_move", description="Call this tool to make a move.", ) register_function( available_moves, caller=agent_black, executor=game_master, name="available_moves", description="Get legal moves.", ) agent_white.register_nested_chats( trigger=agent_black, chat_queue=[ { "sender": game_master, "recipient": agent_white, "summary_method": "last_msg", } ], ) agent_black.register_nested_chats( trigger=agent_white, chat_queue=[ { "sender": game_master, "recipient": agent_black, "summary_method": "last_msg", } ], ) st.info(""" This chess game is played between two AG2 AI agents: - **Agent White**: A GPT-4o-mini powered chess player controlling white pieces - **Agent Black**: A GPT-4o-mini powered chess player controlling black pieces The game is managed by a **Game Master** that: - Validates all moves - Updates the chess board - Manages turn-taking between players - Provides legal move information """) initial_board_svg = chess.svg.board(st.session_state.board, size=300) st.subheader("Initial Board") st.image(initial_board_svg) if st.button("Start Game"): st.session_state.board.reset() st.session_state.made_move = False st.session_state.move_history = [] st.session_state.board_svg = chess.svg.board(st.session_state.board, size=300) st.info("The AI agents will now play against each other. Each agent will analyze the board, " "request legal moves from the Game Master (proxy agent), and make strategic decisions.") st.success("You can view the interaction between the agents in the terminal output, after the turns between agents end, you get view all the chess board moves displayed below!") st.write("Game started! White's turn.") chat_result = agent_black.initiate_chat( recipient=agent_white, message="Let's play chess! You go first, its your move.", max_turns=st.session_state.max_turns, summary_method="reflection_with_llm" ) st.markdown(chat_result.summary) # Display the move history (boards for each move) st.subheader("Move History") for i, move_svg in enumerate(st.session_state.move_history): # Determine which agent made the move if i % 2 == 0: move_by = "Agent White" # Even-indexed moves are by White else: move_by = "Agent Black" # Odd-indexed moves are by Black st.write(f"Move {i + 1} by {move_by}") st.image(move_svg) if st.button("Reset Game"): st.session_state.board.reset() st.session_state.made_move = False st.session_state.move_history = [] st.session_state.board_svg = None st.write("Game reset! Click 'Start Game' to begin a new game.") except Exception as e: st.error(f"An error occurred: {e}. Please check your API key and try again.") else: st.warning("Please enter your OpenAI API key in the sidebar to start the game.") ``` ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_chess_agent/requirements.txt streamlit chess==1.11.1 autogen==0.6.1 cairosvg pillow ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/README.md # 🎮 Agent X vs Agent O: Tic-Tac-Toe Game An interactive Tic-Tac-Toe game where two AI agents powered by different language models compete against each other built on Agno Agent Framework and Streamlit as UI. This example shows how to build an interactive Tic Tac Toe game where AI agents compete against each other. The application showcases how to: - Coordinate multiple AI agents in a turn-based game - Use different language models for different players - Create an interactive web interface with Streamlit - Handle game state and move validation - Display real-time game progress and move history ## Features - Multiple AI models support (GPT-4, Claude, Gemini, etc.) - Real-time game visualization - Move history tracking with board states - Interactive player selection - Game state management - Move validation and coordination ## How to Run? 1. **Setup Environment** ```bash # Clone the repository git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd ai_agent_tutorials/ai_tic_tac_toe_agent # Install dependencies pip install -r requirements.txt ``` ### 2. Install dependencies ```shell pip install -r requirements.txt ``` ### 3. Export API Keys The game supports multiple AI models. Export the API keys for the models you want to use: ```shell # Required for OpenAI models export OPENAI_API_KEY=*** # Optional - for additional models export ANTHROPIC_API_KEY=*** # For Claude models export GOOGLE_API_KEY=*** # For Gemini models export GROQ_API_KEY=*** # For Groq models ``` ### 4. Run the Game ```shell streamlit run app.py ``` - Open [localhost:8501](http://localhost:8501) to view the game interface ## How It Works The game consists of three agents: 1. **Master Agent (Referee)** - Coordinates the game - Validates moves - Maintains game state - Determines game outcome 2. **Two Player Agents** - Make strategic moves - Analyze board state - Follow game rules - Respond to opponent moves ## Available Models The game supports various AI models: - GPT-4o (OpenAI) - GPT-o3-mini (OpenAI) - Gemini (Google) - Llama 3 (Groq) - Claude (Anthropic) ## Game Features 1. **Interactive Board** - Real-time updates - Visual move tracking - Clear game status display 2. **Move History** - Detailed move tracking - Board state visualization - Player action timeline 3. **Game Controls** - Start/Pause game - Reset board - Select AI models - View game history 4. **Performance Analysis** - Move timing - Strategy tracking - Game statistics ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/agents.py ```py path="/advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/agents.py" """ Tic Tac Toe Battle --------------------------------- This example shows how to build a Tic Tac Toe game where two AI agents play against each other. The game features a referee agent coordinating between two player agents using different language models. Usage Examples: --------------- 1. Quick game with default settings: referee_agent = get_tic_tac_toe_referee() play_tic_tac_toe() 2. Game with debug mode off: referee_agent = get_tic_tac_toe_referee(debug_mode=False) play_tic_tac_toe(debug_mode=False) The game integrates: - Multiple AI models (Claude, GPT-4, etc.) - Turn-based gameplay coordination - Move validation and game state management """ import sys from pathlib import Path from textwrap import dedent from typing import Tuple from agno.agent import Agent from agno.models.anthropic import Claude from agno.models.google import Gemini from agno.models.groq import Groq from agno.models.openai import OpenAIChat project_root = str(Path(__file__).parent.parent.parent.parent) if project_root not in sys.path: sys.path.append(project_root) def get_model_for_provider(provider: str, model_name: str): """ Creates and returns the appropriate model instance based on the provider. Args: provider: The model provider (e.g., 'openai', 'google', 'anthropic', 'groq') model_name: The specific model name/ID Returns: An instance of the appropriate model class Raises: ValueError: If the provider is not supported """ if provider == "openai": return OpenAIChat(id=model_name) elif provider == "google": return Gemini(id=model_name) elif provider == "anthropic": if model_name == "claude-3-5-sonnet": return Claude(id="claude-3-5-sonnet-20241022", max_tokens=8192) elif model_name == "claude-3-7-sonnet": return Claude( id="claude-3-7-sonnet-20250219", max_tokens=8192, ) elif model_name == "claude-3-7-sonnet-thinking": return Claude( id="claude-3-7-sonnet-20250219", max_tokens=8192, thinking={"type": "enabled", "budget_tokens": 4096}, ) else: return Claude(id=model_name) elif provider == "groq": return Groq(id=model_name) else: raise ValueError(f"Unsupported model provider: {provider}") def get_tic_tac_toe_players( model_x: str = "openai:gpt-4o", model_o: str = "openai:o3-mini", debug_mode: bool = True, ) -> Tuple[Agent, Agent]: """ Returns an instance of the Tic Tac Toe Referee Agent that coordinates the game. Args: model_x: ModelConfig for player X model_o: ModelConfig for player O model_referee: ModelConfig for the referee agent debug_mode: Enable logging and debug features Returns: An instance of the configured Referee Agent """ # Parse model provider and name provider_x, model_name_x = model_x.split(":") provider_o, model_name_o = model_o.split(":") # Create model instances using the helper function model_x = get_model_for_provider(provider_x, model_name_x) model_o = get_model_for_provider(provider_o, model_name_o) player_x = Agent( name="Player X", description=dedent("""\ You are Player X in a Tic Tac Toe game. Your goal is to win by placing three X's in a row (horizontally, vertically, or diagonally). BOARD LAYOUT: - The board is a 3x3 grid with coordinates from (0,0) to (2,2) - Top-left is (0,0), bottom-right is (2,2) RULES: - You can only place X in empty spaces (shown as " " on the board) - Players take turns placing their marks - First to get 3 marks in a row (horizontal, vertical, or diagonal) wins - If all spaces are filled with no winner, the game is a draw YOUR RESPONSE: - Provide ONLY two numbers separated by a space (row column) - Example: "1 2" places your X in row 1, column 2 - Choose only from the valid moves list provided to you STRATEGY TIPS: - Study the board carefully and make strategic moves - Block your opponent's potential winning moves - Create opportunities for multiple winning paths - Pay attention to the valid moves and avoid illegal moves """), model=model_x, debug_mode=debug_mode, ) player_o = Agent( name="Player O", description=dedent("""\ You are Player O in a Tic Tac Toe game. Your goal is to win by placing three O's in a row (horizontally, vertically, or diagonally). BOARD LAYOUT: - The board is a 3x3 grid with coordinates from (0,0) to (2,2) - Top-left is (0,0), bottom-right is (2,2) RULES: - You can only place X in empty spaces (shown as " " on the board) - Players take turns placing their marks - First to get 3 marks in a row (horizontal, vertical, or diagonal) wins - If all spaces are filled with no winner, the game is a draw YOUR RESPONSE: - Provide ONLY two numbers separated by a space (row column) - Example: "1 2" places your X in row 1, column 2 - Choose only from the valid moves list provided to you STRATEGY TIPS: - Study the board carefully and make strategic moves - Block your opponent's potential winning moves - Create opportunities for multiple winning paths - Pay attention to the valid moves and avoid illegal moves """), model=model_o, debug_mode=debug_mode, ) return player_x, player_o ``` ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/app.py ```py path="/advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/app.py" import nest_asyncio import streamlit as st from agents import get_tic_tac_toe_players from agno.utils.log import logger from utils import ( CUSTOM_CSS, TicTacToeBoard, display_board, display_move_history, show_agent_status, ) nest_asyncio.apply() # Page configuration st.set_page_config( page_title="Agent Tic Tac Toe", page_icon="🎮", layout="wide", initial_sidebar_state="expanded", ) # Load custom CSS with dark mode support st.markdown(CUSTOM_CSS, unsafe_allow_html=True) def main(): #################################################################### # App header #################################################################### st.markdown( "

Watch Agents play Tic Tac Toe

", unsafe_allow_html=True, ) #################################################################### # Initialize session state #################################################################### if "game_started" not in st.session_state: st.session_state.game_started = False st.session_state.game_paused = False st.session_state.move_history = [] with st.sidebar: st.markdown("### Game Controls") model_options = { "gpt-4o": "openai:gpt-4o", "o3-mini": "openai:o3-mini", "claude-3.5": "anthropic:claude-3-5-sonnet", "claude-3.7": "anthropic:claude-3-7-sonnet", "claude-3.7-thinking": "anthropic:claude-3-7-sonnet-thinking", "gemini-flash": "google:gemini-2.0-flash", "gemini-pro": "google:gemini-2.0-pro-exp-02-05", "llama-3.3": "groq:llama-3.3-70b-versatile", } ################################################################ # Model selection ################################################################ selected_p_x = st.selectbox( "Select Player X", list(model_options.keys()), index=list(model_options.keys()).index("claude-3.7-thinking"), key="model_p1", ) selected_p_o = st.selectbox( "Select Player O", list(model_options.keys()), index=list(model_options.keys()).index("o3-mini"), key="model_p2", ) ################################################################ # Game controls ################################################################ col1, col2 = st.columns(2) with col1: if not st.session_state.game_started: if st.button("▶️ Start Game"): st.session_state.player_x, st.session_state.player_o = ( get_tic_tac_toe_players( model_x=model_options[selected_p_x], model_o=model_options[selected_p_o], debug_mode=True, ) ) st.session_state.game_board = TicTacToeBoard() st.session_state.game_started = True st.session_state.game_paused = False st.session_state.move_history = [] st.rerun() else: game_over, _ = st.session_state.game_board.get_game_state() if not game_over: if st.button( "⏸️ Pause" if not st.session_state.game_paused else "▶️ Resume" ): st.session_state.game_paused = not st.session_state.game_paused st.rerun() with col2: if st.session_state.game_started: if st.button("🔄 New Game"): st.session_state.player_x, st.session_state.player_o = ( get_tic_tac_toe_players( model_x=model_options[selected_p_x], model_o=model_options[selected_p_o], debug_mode=True, ) ) st.session_state.game_board = TicTacToeBoard() st.session_state.game_paused = False st.session_state.move_history = [] st.rerun() #################################################################### # Header showing current models #################################################################### if st.session_state.game_started: st.markdown( f"

{selected_p_x} vs {selected_p_o}

", unsafe_allow_html=True, ) #################################################################### # Main game area #################################################################### if st.session_state.game_started: game_over, status = st.session_state.game_board.get_game_state() display_board(st.session_state.game_board) # Show game status (winner/draw/current player) if game_over: winner_player = ( "X" if "X wins" in status else "O" if "O wins" in status else None ) if winner_player: winner_num = "1" if winner_player == "X" else "2" winner_model = selected_p_x if winner_player == "X" else selected_p_o st.success(f"🏆 Game Over! Player {winner_num} ({winner_model}) wins!") else: st.info("🤝 Game Over! It's a draw!") else: # Show current player status current_player = st.session_state.game_board.current_player player_num = "1" if current_player == "X" else "2" current_model_name = selected_p_x if current_player == "X" else selected_p_o show_agent_status( f"Player {player_num} ({current_model_name})", "It's your turn", ) display_move_history() if not st.session_state.game_paused and not game_over: # Thinking indicator st.markdown( f"""
🔄
Player {player_num} ({current_model_name}) is thinking...
""", unsafe_allow_html=True, ) valid_moves = st.session_state.game_board.get_valid_moves() current_agent = ( st.session_state.player_x if current_player == "X" else st.session_state.player_o ) response = current_agent.run( f"""\ Current board state:\n{st.session_state.game_board.get_board_state()}\n Available valid moves (row, col): {valid_moves}\n Choose your next move from the valid moves above. Respond with ONLY two numbers for row and column, e.g. "1 2".""", stream=False, ) try: import re numbers = re.findall(r"\d+", response.content if response else "") row, col = map(int, numbers[:2]) success, message = st.session_state.game_board.make_move(row, col) if success: move_number = len(st.session_state.move_history) + 1 st.session_state.move_history.append( { "number": move_number, "player": f"Player {player_num} ({current_model_name})", "move": f"{row},{col}", } ) logger.info( f"Move {move_number}: Player {player_num} ({current_model_name}) placed at position ({row}, {col})" ) logger.info( f"Board state:\n{st.session_state.game_board.get_board_state()}" ) # Check game state after move game_over, status = st.session_state.game_board.get_game_state() if game_over: logger.info(f"Game Over - {status}") if "wins" in status: st.success(f"🏆 Game Over! {status}") else: st.info(f"🤝 Game Over! {status}") st.session_state.game_paused = True st.rerun() else: logger.error(f"Invalid move attempt: {message}") response = current_agent.run( f"""\ Invalid move: {message} Current board state:\n{st.session_state.game_board.get_board_state()}\n Available valid moves (row, col): {valid_moves}\n Please choose a valid move from the list above. Respond with ONLY two numbers for row and column, e.g. "1 2".""", stream=False, ) st.rerun() except Exception as e: logger.error(f"Error processing move: {str(e)}") st.error(f"Error processing move: {str(e)}") st.rerun() else: st.info("👈 Press 'Start Game' to begin!") #################################################################### # About section #################################################################### st.sidebar.markdown(f""" ### 🎮 Agent Tic Tac Toe Battle Watch two agents compete in real-time! **Current Players:** * 🔵 Player X: `{selected_p_x}` * 🔴 Player O: `{selected_p_o}` **How it Works:** Each Agent analyzes the board and employs strategic thinking to: * 🏆 Find winning moves * 🛡️ Block opponent victories * ⭐ Control strategic positions * 🤔 Plan multiple moves ahead Built with Streamlit and Agno """) if __name__ == "__main__": main() ``` ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/requirements.txt # This file was autogenerated by uv via the following command: # ./generate_requirements.sh agno==1.1.6 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in altair==5.5.0 # via streamlit annotated-types==0.7.0 # via pydantic anthropic==0.47.1 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in anyio==4.8.0 # via # anthropic # groq # httpx # openai attrs==25.1.0 # via # jsonschema # referencing blinker==1.9.0 # via streamlit build==1.2.2.post1 # via pip-tools cachetools==5.5.2 # via # google-auth # streamlit certifi==2025.1.31 # via # httpcore # httpx # requests charset-normalizer==3.4.1 # via requests click==8.1.8 # via # pip-tools # streamlit # typer distro==1.9.0 # via # anthropic # groq # openai docstring-parser==0.16 # via agno gitdb==4.0.12 # via gitpython gitpython==3.1.44 # via # agno # streamlit google-auth==2.38.0 # via google-genai google-genai==1.3.0 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in groq==0.18.0 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in h11==0.14.0 # via httpcore httpcore==1.0.7 # via httpx httpx==0.28.1 # via # agno # anthropic # google-genai # groq # ollama # openai idna==3.10 # via # anyio # httpx # requests jinja2==3.1.5 # via # altair # pydeck jiter==0.8.2 # via # anthropic # openai jsonschema==4.23.0 # via altair jsonschema-specifications==2024.10.1 # via jsonschema markdown-it-py==3.0.0 # via rich markupsafe==3.0.2 # via jinja2 mdurl==0.1.2 # via markdown-it-py narwhals==1.28.0 # via altair nest-asyncio==1.6.0 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in numpy==2.2.3 # via # pandas # pydeck # streamlit ollama==0.4.7 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in openai==1.64.0 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in packaging==24.2 # via # altair # build # streamlit pandas==2.2.3 # via streamlit pathlib==1.0.1 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in pillow==11.1.0 # via # -r cookbook/examples/apps/tic_tac_toe/requirements.in # streamlit pip==25.0.1 # via pip-tools pip-tools==7.4.1 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in protobuf==5.29.3 # via streamlit pyarrow==19.0.1 # via streamlit pyasn1==0.6.1 # via # pyasn1-modules # rsa pyasn1-modules==0.4.1 # via google-auth pydantic==2.10.6 # via # agno # anthropic # google-genai # groq # ollama # openai # pydantic-settings pydantic-core==2.27.2 # via pydantic pydantic-settings==2.8.0 # via agno pydeck==0.9.1 # via streamlit pygments==2.19.1 # via rich pyproject-hooks==1.2.0 # via # build # pip-tools python-dateutil==2.9.0.post0 # via pandas python-dotenv==1.0.1 # via # -r cookbook/examples/apps/tic_tac_toe/requirements.in # agno # pydantic-settings python-multipart==0.0.20 # via agno pytz==2025.1 # via pandas pyyaml==6.0.2 # via agno referencing==0.36.2 # via # jsonschema # jsonschema-specifications requests==2.32.3 # via # google-genai # streamlit rich==13.9.4 # via # -r cookbook/examples/apps/tic_tac_toe/requirements.in # agno # streamlit # typer rpds-py==0.23.1 # via # jsonschema # referencing rsa==4.9 # via google-auth setuptools==75.8.0 # via pip-tools shellingham==1.5.4 # via typer six==1.17.0 # via python-dateutil smmap==5.0.2 # via gitdb sniffio==1.3.1 # via # anthropic # anyio # groq # openai streamlit==1.42.2 # via -r cookbook/examples/apps/tic_tac_toe/requirements.in tenacity==9.0.0 # via streamlit toml==0.10.2 # via streamlit tomli==2.2.1 # via agno tornado==6.4.2 # via streamlit tqdm==4.67.1 # via openai typer==0.15.1 # via agno typing-extensions==4.12.2 # via # agno # altair # anthropic # anyio # google-genai # groq # openai # pydantic # pydantic-core # referencing # streamlit # typer tzdata==2025.1 # via pandas urllib3==2.3.0 # via requests websockets==14.2 # via google-genai wheel==0.45.1 # via pip-tools ## /advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/utils.py ```py path="/advanced_ai_agents/autonomous_game_playing_agent_apps/ai_tic_tac_toe_agent/utils.py" from typing import List, Optional, Tuple import streamlit as st # Define constants for players X_PLAYER = "X" O_PLAYER = "O" EMPTY = " " class TicTacToeBoard: def __init__(self): # Initialize empty 3x3 board self.board = [[EMPTY for _ in range(3)] for _ in range(3)] self.current_player = X_PLAYER def make_move(self, row: int, col: int) -> Tuple[bool, str]: """ Make a move on the board. Args: row (int): Row index (0-2) col (int): Column index (0-2) Returns: Tuple[bool, str]: (Success status, Message with current board state or error) """ # Validate move coordinates if not (0 <= row <= 2 and 0 <= col <= 2): return ( False, "Invalid move: Position out of bounds. Please choose row and column between 0 and 2.", ) # Check if position is already occupied if self.board[row][col] != EMPTY: return False, f"Invalid move: Position ({row}, {col}) is already occupied." # Make the move self.board[row][col] = self.current_player # Get board state board_state = self.get_board_state() # Switch player self.current_player = O_PLAYER if self.current_player == X_PLAYER else X_PLAYER return True, f"Move successful!\n{board_state}" def get_board_state(self) -> str: """ Returns a string representation of the current board state. """ board_str = "\n-------------\n" for row in self.board: board_str += f"| {' | '.join(row)} |\n-------------\n" return board_str def check_winner(self) -> Optional[str]: """ Check if there's a winner. Returns: Optional[str]: The winning player (X or O) or None if no winner """ # Check rows for row in self.board: if row.count(row[0]) == 3 and row[0] != EMPTY: return row[0] # Check columns for col in range(3): column = [self.board[row][col] for row in range(3)] if column.count(column[0]) == 3 and column[0] != EMPTY: return column[0] # Check diagonals diagonal1 = [self.board[i][i] for i in range(3)] if diagonal1.count(diagonal1[0]) == 3 and diagonal1[0] != EMPTY: return diagonal1[0] diagonal2 = [self.board[i][2 - i] for i in range(3)] if diagonal2.count(diagonal2[0]) == 3 and diagonal2[0] != EMPTY: return diagonal2[0] return None def is_board_full(self) -> bool: """ Check if the board is full (draw condition). """ return all(cell != EMPTY for row in self.board for cell in row) def get_valid_moves(self) -> List[Tuple[int, int]]: """ Get a list of valid moves (empty positions). Returns: List[Tuple[int, int]]: List of (row, col) tuples representing valid moves """ valid_moves = [] for row in range(3): for col in range(3): if self.board[row][col] == EMPTY: valid_moves.append((row, col)) return valid_moves def get_game_state(self) -> Tuple[bool, str]: """ Get the current game state. Returns: Tuple[bool, str]: (is_game_over, status_message) """ winner = self.check_winner() if winner: return True, f"Player {winner} wins!" if self.is_board_full(): return True, "It's a draw!" return False, "Game in progress" def display_board(board: TicTacToeBoard): """Display the Tic Tac Toe board using Streamlit""" board_html = '
' for i in range(3): for j in range(3): cell_value = board.board[i][j] board_html += f'
{cell_value}
' board_html += "
" st.markdown(board_html, unsafe_allow_html=True) def show_agent_status(agent_name: str, status: str): """Display the current agent status""" st.markdown( f"""
🤖 {agent_name}: {status}
""", unsafe_allow_html=True, ) def create_mini_board_html( board_state: list, highlight_pos: tuple = None, is_player1: bool = True ) -> str: """Create HTML for a mini board with player-specific highlighting""" html = '
' for i in range(3): for j in range(3): highlight = ( f"highlight player{1 if is_player1 else 2}" if highlight_pos and (i, j) == highlight_pos else "" ) html += f'
{board_state[i][j]}
' html += "
" return html def display_move_history(): """Display the move history with mini boards in two columns""" st.markdown( '

📜 Game History

', unsafe_allow_html=True, ) history_container = st.empty() if "move_history" in st.session_state and st.session_state.move_history: # Split moves into player 1 and player 2 moves p1_moves = [] p2_moves = [] current_board = [[" " for _ in range(3)] for _ in range(3)] # Process all moves first for move in st.session_state.move_history: row, col = map(int, move["move"].split(",")) is_player1 = "Player 1" in move["player"] symbol = "X" if is_player1 else "O" current_board[row][col] = symbol board_copy = [row[:] for row in current_board] move_html = f"""
{create_mini_board_html(board_copy, (row, col), is_player1)}
Move #{move["number"]}
{move["player"]}
Position: ({row}, {col})
""" if is_player1: p1_moves.append(move_html) else: p2_moves.append(move_html) max_moves = max(len(p1_moves), len(p2_moves)) history_content = '
' # Left column (Player 1) history_content += '
' for i in range(max_moves): entry_html = "" # Player 1 move if i < len(p1_moves): entry_html += p1_moves[i] history_content += entry_html history_content += "
" # Right column (Player 2) history_content += '
' for i in range(max_moves): entry_html = "" # Player 2 move if i < len(p2_moves): entry_html += p2_moves[i] history_content += entry_html history_content += "
" history_content += "
" # Display the content history_container.markdown(history_content, unsafe_allow_html=True) else: history_container.markdown( """
No moves yet. Start the game to see the history!
""", unsafe_allow_html=True, ) CUSTOM_CSS = """ """ ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_competitor_intelligence_agent_team/README.md # 🧲 AI Competitor Intelligence Agent Team The AI Competitor Intelligence Agent Team is a powerful competitor analysis tool powered by Firecrawl and Agno's AI Agent framework. This app helps businesses analyze their competitors by extracting structured data from competitor websites and generating actionable insights using AI. ## Features - **Multi-Agent System** - **Firecrawl Agent**: Specializes in crawling and summarizing competitor websites - **Analysis Agent**: Generates detailed competitive analysis reports - **Comparison Agent**: Creates structured comparisons between competitors - **Competitor Discovery**: - Finds similar companies using URL matching with Exa AI - Discovers competitors based on business descriptions - Automatically extracts relevant competitor URLs - **Comprehensive Analysis**: - Provides structured analysis reports with: - Market gaps and opportunities - Competitor weaknesses - Recommended features - Pricing strategies - Growth opportunities - Actionable recommendations - **Interactive Analysis**: Users can input either their company URL or description for analysis ## Requirements The application requires the following Python libraries: - `agno` - `exa-py` - `streamlit` - `pandas` - `firecrawl-py` You'll also need API keys for: - OpenAI - Firecrawl - Exa ## How to Run Follow these steps to set up and run the application: 1. **Clone the Repository**: ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd ai_agent_tutorials/ai_competitors_analysis_team ``` 2. **Install the dependencies**: ```bash pip install -r requirements.txt ``` 3. **Set up your API keys**: - Get an OpenAI API key from: https://platform.openai.com/api-keys - Get a Firecrawl API key from: [Firecrawl website](https://www.firecrawl.dev/app/api-keys) - Get an Exa API key from: [Exa website](https://dashboard.exa.ai/api-keys) 4. **Run the Streamlit app**: ```bash streamlit run ai_competitor_analyser.py ``` ## Usage 1. Enter your API keys in the sidebar 2. Input either: - Your company's website URL - A description of your company 3. Click "Analyze Competitors" to generate: - Competitor comparison table - Detailed analysis report - Strategic recommendations ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_competitor_intelligence_agent_team/competitor_agent_team.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/ai_competitor_intelligence_agent_team/competitor_agent_team.py" import streamlit as st from exa_py import Exa from agno.agent import Agent from agno.tools.firecrawl import FirecrawlTools from agno.models.openai import OpenAIChat from agno.tools.duckduckgo import DuckDuckGoTools import pandas as pd import requests from firecrawl import FirecrawlApp from pydantic import BaseModel, Field from typing import List, Optional import json # Streamlit UI st.set_page_config(page_title="AI Competitor Intelligence Agent Team", layout="wide") # Sidebar for API keys st.sidebar.title("API Keys") openai_api_key = st.sidebar.text_input("OpenAI API Key", type="password") firecrawl_api_key = st.sidebar.text_input("Firecrawl API Key", type="password") # Add search engine selection before API keys search_engine = st.sidebar.selectbox( "Select Search Endpoint", options=["Perplexity AI - Sonar Pro", "Exa AI"], help="Choose which AI service to use for finding competitor URLs" ) # Show relevant API key input based on selection if search_engine == "Perplexity AI - Sonar Pro": perplexity_api_key = st.sidebar.text_input("Perplexity API Key", type="password") # Store API keys in session state if openai_api_key and firecrawl_api_key and perplexity_api_key: st.session_state.openai_api_key = openai_api_key st.session_state.firecrawl_api_key = firecrawl_api_key st.session_state.perplexity_api_key = perplexity_api_key else: st.sidebar.warning("Please enter all required API keys to proceed.") else: # Exa AI exa_api_key = st.sidebar.text_input("Exa API Key", type="password") # Store API keys in session state if openai_api_key and firecrawl_api_key and exa_api_key: st.session_state.openai_api_key = openai_api_key st.session_state.firecrawl_api_key = firecrawl_api_key st.session_state.exa_api_key = exa_api_key else: st.sidebar.warning("Please enter all required API keys to proceed.") # Main UI st.title("🧲 AI Competitor Intelligence Agent Team") st.info( """ This app helps businesses analyze their competitors by extracting structured data from competitor websites and generating insights using AI. - Provide a **URL** or a **description** of your company. - The app will fetch competitor URLs, extract relevant information, and generate a detailed analysis report. """ ) st.success("For better results, provide both URL and a 5-6 word description of your company!") # Input fields for URL and description url = st.text_input("Enter your company URL :") description = st.text_area("Enter a description of your company (if URL is not available):") # Initialize API keys and tools if "openai_api_key" in st.session_state and "firecrawl_api_key" in st.session_state: if (search_engine == "Perplexity AI - Sonar Pro" and "perplexity_api_key" in st.session_state) or \ (search_engine == "Exa AI" and "exa_api_key" in st.session_state): # Initialize Exa only if selected if search_engine == "Exa AI": exa = Exa(api_key=st.session_state.exa_api_key) firecrawl_tools = FirecrawlTools( api_key=st.session_state.firecrawl_api_key, scrape=False, crawl=True, limit=5 ) firecrawl_agent = Agent( model=OpenAIChat(id="gpt-4o", api_key=st.session_state.openai_api_key), tools=[firecrawl_tools, DuckDuckGoTools()], show_tool_calls=True, markdown=True ) analysis_agent = Agent( model=OpenAIChat(id="gpt-4o", api_key=st.session_state.openai_api_key), show_tool_calls=True, markdown=True ) # New agent for comparing competitor data comparison_agent = Agent( model=OpenAIChat(id="gpt-4o", api_key=st.session_state.openai_api_key), show_tool_calls=True, markdown=True ) def get_competitor_urls(url: str = None, description: str = None) -> list[str]: if not url and not description: raise ValueError("Please provide either a URL or a description.") if search_engine == "Perplexity AI - Sonar Pro": perplexity_url = "https://api.perplexity.ai/chat/completions" content = "Find me 3 competitor company URLs similar to the company with " if url and description: content += f"URL: {url} and description: {description}" elif url: content += f"URL: {url}" else: content += f"description: {description}" content += ". ONLY RESPOND WITH THE URLS, NO OTHER TEXT." payload = { "model": "sonar-pro", "messages": [ { "role": "system", "content": "Be precise and only return 3 company URLs ONLY." }, { "role": "user", "content": content } ], "max_tokens": 1000, "temperature": 0.2, } headers = { "Authorization": f"Bearer {st.session_state.perplexity_api_key}", "Content-Type": "application/json" } try: response = requests.post(perplexity_url, json=payload, headers=headers) response.raise_for_status() urls = response.json()['choices'][0]['message']['content'].strip().split('\n') return [url.strip() for url in urls if url.strip()] except Exception as e: st.error(f"Error fetching competitor URLs from Perplexity: {str(e)}") return [] else: # Exa AI try: if url: result = exa.find_similar( url=url, num_results=3, exclude_source_domain=True, category="company" ) else: result = exa.search( description, type="neural", category="company", use_autoprompt=True, num_results=3 ) return [item.url for item in result.results] except Exception as e: st.error(f"Error fetching competitor URLs from Exa: {str(e)}") return [] class CompetitorDataSchema(BaseModel): company_name: str = Field(description="Name of the company") pricing: str = Field(description="Pricing details, tiers, and plans") key_features: List[str] = Field(description="Main features and capabilities of the product/service") tech_stack: List[str] = Field(description="Technologies, frameworks, and tools used") marketing_focus: str = Field(description="Main marketing angles and target audience") customer_feedback: str = Field(description="Customer testimonials, reviews, and feedback") def extract_competitor_info(competitor_url: str) -> Optional[dict]: try: # Initialize FirecrawlApp with API key app = FirecrawlApp(api_key=st.session_state.firecrawl_api_key) # Add wildcard to crawl subpages url_pattern = f"{competitor_url}/*" extraction_prompt = """ Extract detailed information about the company's offerings, including: - Company name and basic information - Pricing details, plans, and tiers - Key features and main capabilities - Technology stack and technical details - Marketing focus and target audience - Customer feedback and testimonials Analyze the entire website content to provide comprehensive information for each field. """ response = app.extract( [url_pattern], { 'prompt': extraction_prompt, 'schema': CompetitorDataSchema.model_json_schema(), } ) if response.get('success') and response.get('data'): extracted_info = response['data'] # Create JSON structure competitor_json = { "competitor_url": competitor_url, "company_name": extracted_info.get('company_name', 'N/A'), "pricing": extracted_info.get('pricing', 'N/A'), "key_features": extracted_info.get('key_features', [])[:5], # Top 5 features "tech_stack": extracted_info.get('tech_stack', [])[:5], # Top 5 tech stack items "marketing_focus": extracted_info.get('marketing_focus', 'N/A'), "customer_feedback": extracted_info.get('customer_feedback', 'N/A') } return competitor_json else: return None except Exception as e: return None def generate_comparison_report(competitor_data: list) -> None: # Format the competitor data for the prompt formatted_data = json.dumps(competitor_data, indent=2) print(formatted_data) # Updated system prompt for more structured output system_prompt = f""" As an expert business analyst, analyze the following competitor data in JSON format and create a structured comparison. Extract and summarize the key information into concise points. {formatted_data} Return the data in a structured format with EXACTLY these columns: Company, Pricing, Key Features, Tech Stack, Marketing Focus, Customer Feedback Rules: 1. For Company: Include company name and URL 2. For Key Features: List top 3 most important features only 3. For Tech Stack: List top 3 most relevant technologies only 4. Keep all entries clear and concise 5. Format feedback as brief quotes 6. Return ONLY the structured data, no additional text """ # Get comparison data from agent comparison_response = comparison_agent.run(system_prompt) try: # Split the response into lines and clean them table_lines = [ line.strip() for line in comparison_response.content.split('\n') if line.strip() and '|' in line ] # Extract headers (first row) headers = [ col.strip() for col in table_lines[0].split('|') if col.strip() ] # Extract data rows (skip header and separator rows) data_rows = [] for line in table_lines[2:]: # Skip header and separator rows row_data = [ cell.strip() for cell in line.split('|') if cell.strip() ] if len(row_data) == len(headers): data_rows.append(row_data) # Create DataFrame df = pd.DataFrame( data_rows, columns=headers ) # Display the table st.subheader("Competitor Comparison") st.table(df) except Exception as e: st.error(f"Error creating comparison table: {str(e)}") st.write("Raw comparison data for debugging:", comparison_response.content) def generate_analysis_report(competitor_data: list): # Format the competitor data for the prompt formatted_data = json.dumps(competitor_data, indent=2) print("Analysis Data:", formatted_data) # For debugging report = analysis_agent.run( f"""Analyze the following competitor data in JSON format and identify market opportunities to improve my own company: {formatted_data} Tasks: 1. Identify market gaps and opportunities based on competitor offerings 2. Analyze competitor weaknesses that we can capitalize on 3. Recommend unique features or capabilities we should develop 4. Suggest pricing and positioning strategies to gain competitive advantage 5. Outline specific growth opportunities in underserved market segments 6. Provide actionable recommendations for product development and go-to-market strategy Focus on finding opportunities where we can differentiate and do better than competitors. Highlight any unmet customer needs or pain points we can address. """ ) return report.content # Run analysis when the user clicks the button if st.button("Analyze Competitors"): if url or description: with st.spinner("Fetching competitor URLs..."): competitor_urls = get_competitor_urls(url=url, description=description) st.write(f"Competitor URLs: {competitor_urls}") competitor_data = [] for comp_url in competitor_urls: with st.spinner(f"Analyzing Competitor: {comp_url}..."): competitor_info = extract_competitor_info(comp_url) if competitor_info is not None: competitor_data.append(competitor_info) if competitor_data: # Generate and display comparison report with st.spinner("Generating comparison table..."): generate_comparison_report(competitor_data) # Generate and display final analysis report with st.spinner("Generating analysis report..."): analysis_report = generate_analysis_report(competitor_data) st.subheader("Competitor Analysis Report") st.markdown(analysis_report) st.success("Analysis complete!") else: st.error("Could not extract data from any competitor URLs") else: st.error("Please provide either a URL or a description.") ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_competitor_intelligence_agent_team/requirements.txt exa-py==1.7.1 firecrawl-py==1.9.0 duckduckgo-search==7.2.1 agno streamlit==1.41.1 ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_finance_agent_team/README.md ## 💲 AI Finance Agent Team with Web Access This script demonstrates how to build a team of AI agents that work together as a financial analyst using GPT-4o in just 20 lines of Python code. The system combines web search capabilities with financial data analysis tools to provide comprehensive financial insights. ### Features - Multi-agent system with specialized roles: - Web Agent for general internet research - Finance Agent for detailed financial analysis - Team Agent for coordinating between agents - Real-time financial data access through YFinance - Web search capabilities using DuckDuckGo - Persistent storage of agent interactions using SQLite ### How to get Started? 1. Clone the GitHub repository ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd awesome-llm-apps/ai_agent_tutorials/ai_finance_agent_team ``` 2. Install the required dependencies: ```bash pip install -r requirements.txt ``` 3. Get your OpenAI API Key - Sign up for an [OpenAI account](https://platform.openai.com/) (or the LLM provider of your choice) and obtain your API key. - Set your OpenAI API key as an environment variable: ```bash export OPENAI_API_KEY='your-api-key-here' ``` 4. Run the team of AI Agents ```bash python3 finance_agent_team.py ``` 5. Open your web browser and navigate to the URL provided in the console output to interact with the team of AI agents through the playground interface. ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_finance_agent_team/finance_agent_team.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/ai_finance_agent_team/finance_agent_team.py" from agno.agent import Agent from agno.models.openai import OpenAIChat from agno.storage.agent.sqlite import SqliteAgentStorage from agno.tools.duckduckgo import DuckDuckGoTools from agno.tools.yfinance import YFinanceTools from agno.playground import Playground, serve_playground_app web_agent = Agent( name="Web Agent", role="Search the web for information", model=OpenAIChat(id="gpt-4o"), tools=[DuckDuckGoTools()], storage=SqliteAgentStorage(table_name="web_agent", db_file="agents.db"), add_history_to_messages=True, markdown=True, ) finance_agent = Agent( name="Finance Agent", role="Get financial data", model=OpenAIChat(id="gpt-4o"), tools=[YFinanceTools(stock_price=True, analyst_recommendations=True, company_info=True, company_news=True)], instructions=["Always use tables to display data"], storage=SqliteAgentStorage(table_name="finance_agent", db_file="agents.db"), add_history_to_messages=True, markdown=True, ) agent_team = Agent( team=[web_agent, finance_agent], name="Agent Team (Web+Finance)", model=OpenAIChat(id="gpt-4o"), show_tool_calls=True, markdown=True, ) app = Playground(agents=[agent_team]).get_app() if __name__ == "__main__": serve_playground_app("finance_agent_team:app", reload=True) ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_finance_agent_team/requirements.txt openai agno duckduckgo-search yfinance fastapi[standard] sqlalchemy ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_game_design_agent_team/README.md # AI Game Design Agent Team 🎮 The AI Game Design Agent Team is a collaborative game design system powered by [AG2](https://github.com/ag2ai/ag2?tab=readme-ov-file)(formerly AutoGen)'s AI Agent framework. This app generates comprehensive game concepts through the coordination of multiple specialized AI agents, each focusing on different aspects of game design based on user inputs such as game type, target audience, art style, and technical requirements. This is built on AG2's new swarm feature run through initiate_chat() method. ## Features - **Specialized Game Design Agent Team** - 🎭 **Story Agent**: Specializes in narrative design and world-building, including character development, plot arcs, dialogue writing, and lore creation - 🎮 **Gameplay Agent**: Focuses on game mechanics and systems design, including player progression, combat systems, resource management, and balancing - 🎨 **Visuals Agent**: Handles art direction and audio design, covering UI/UX, character/environment art style, sound effects, and music composition - ⚙️ **Tech Agent**: Provides technical architecture and implementation guidance, including engine selection, optimization strategies, networking requirements, and development roadmap - 🎯 **Task Agent**: Coordinates between all specialized agents and ensures cohesive integration of different game aspects - **Comprehensive Game Design Outputs**: - Detailed narrative and world-building elements - Core gameplay mechanics and systems - Visual and audio direction - Technical specifications and requirements - Development timeline and budget considerations - Coherent game design from the team. - **Customizable Input Parameters**: - Game type and target audience - Art style and visual preferences - Platform requirements - Development constraints (time, budget) - Core mechanics and gameplay features - **Interactive Results**: - Quick show of game design ideas from each agent - Detailed results are presented in expandable sections for easy navigation and reference ## How to Run Follow these steps to set up and run the application: 1. **Clone the Repository**: ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd ai_agent_tutorials/ai_game_design_team ``` 2. **Install Dependencies**: ```bash pip install -r requirements.txt ``` 3. **Set Up OpenAI API Key**: - Obtain an OpenAI API key from [OpenAI's platform](https://platform.openai.com) - You'll input this key in the app's sidebar when running 4. **Run the Streamlit App**: ```bash streamlit run ai_game_design_agent_team/game_design_agent_team.py ``` ## Usage 1. Enter your OpenAI API key in the sidebar 2. Fill in the game details: - Background vibe and setting - Game type and target audience - Visual style preferences - Technical requirements - Development constraints 3. Click "Generate Game Concept" to receive comprehensive design documentation from all agents 4. Review the outputs in the expandable sections for each aspect of game design ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_game_design_agent_team/game_design_agent_team.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/ai_game_design_agent_team/game_design_agent_team.py" import asyncio import streamlit as st from autogen import ( SwarmAgent, SwarmResult, initiate_swarm_chat, OpenAIWrapper, AFTER_WORK, UPDATE_SYSTEM_MESSAGE ) # Initialize session state if 'output' not in st.session_state: st.session_state.output = {'story': '', 'gameplay': '', 'visuals': '', 'tech': ''} # Sidebar for API key input st.sidebar.title("API Key") api_key = st.sidebar.text_input("Enter your OpenAI API Key", type="password") # Add guidance in sidebar st.sidebar.success(""" ✨ **Getting Started** Please provide inputs and features for your dream game! Consider: - The overall vibe and setting - Core gameplay elements - Target audience and platforms - Visual style preferences - Technical requirements The AI agents will collaborate to develop a comprehensive game concept based on your specifications. """) # Main app UI st.title("🎮 AI Game Design Agent Team") # Add agent information below title st.info(""" **Meet Your AI Game Design Team:** 🎭 **Story Agent** - Crafts compelling narratives and rich worlds 🎮 **Gameplay Agent** - Creates engaging mechanics and systems 🎨 **Visuals Agent** - Shapes the artistic vision and style ⚙️ **Tech Agent** - Provides technical direction and solutions These agents collaborate to create a comprehensive game concept based on your inputs. """) # User inputs st.subheader("Game Details") col1, col2 = st.columns(2) with col1: background_vibe = st.text_input("Background Vibe", "Epic fantasy with dragons") game_type = st.selectbox("Game Type", ["RPG", "Action", "Adventure", "Puzzle", "Strategy", "Simulation", "Platform", "Horror"]) target_audience = st.selectbox("Target Audience", ["Kids (7-12)", "Teens (13-17)", "Young Adults (18-25)", "Adults (26+)", "All Ages"]) player_perspective = st.selectbox("Player Perspective", ["First Person", "Third Person", "Top Down", "Side View", "Isometric"]) multiplayer = st.selectbox("Multiplayer Support", ["Single Player Only", "Local Co-op", "Online Multiplayer", "Both Local and Online"]) with col2: game_goal = st.text_input("Game Goal", "Save the kingdom from eternal winter") art_style = st.selectbox("Art Style", ["Realistic", "Cartoon", "Pixel Art", "Stylized", "Low Poly", "Anime", "Hand-drawn"]) platform = st.multiselect("Target Platforms", ["PC", "Mobile", "PlayStation", "Xbox", "Nintendo Switch", "Web Browser"]) development_time = st.slider("Development Time (months)", 1, 36, 12) cost = st.number_input("Budget (USD)", min_value=0, value=10000, step=5000) # Additional details st.subheader("Detailed Preferences") col3, col4 = st.columns(2) with col3: core_mechanics = st.multiselect( "Core Gameplay Mechanics", ["Combat", "Exploration", "Puzzle Solving", "Resource Management", "Base Building", "Stealth", "Racing", "Crafting"] ) mood = st.multiselect( "Game Mood/Atmosphere", ["Epic", "Mysterious", "Peaceful", "Tense", "Humorous", "Dark", "Whimsical", "Scary"] ) with col4: inspiration = st.text_area("Games for Inspiration (comma-separated)", "") unique_features = st.text_area("Unique Features or Requirements", "") depth = st.selectbox("Level of Detail in Response", ["Low", "Medium", "High"]) # Button to start the agent collaboration if st.button("Generate Game Concept"): # Check if API key is provided if not api_key: st.error("Please enter your OpenAI API key.") else: with st.spinner('🤖 AI Agents are collaborating on your game concept...'): # Prepare the task based on user inputs task = f""" Create a game concept with the following details: - Background Vibe: {background_vibe} - Game Type: {game_type} - Game Goal: {game_goal} - Target Audience: {target_audience} - Player Perspective: {player_perspective} - Multiplayer Support: {multiplayer} - Art Style: {art_style} - Target Platforms: {', '.join(platform)} - Development Time: {development_time} months - Budget: ${cost:,} - Core Mechanics: {', '.join(core_mechanics)} - Mood/Atmosphere: {', '.join(mood)} - Inspiration: {inspiration} - Unique Features: {unique_features} - Detail Level: {depth} """ llm_config = {"config_list": [{"model": "gpt-4o-mini","api_key": api_key}]} # initialize context variables context_variables = { "story": None, "gameplay": None, "visuals": None, "tech": None, } # define functions to be called by the agents def update_story_overview(story_summary:str, context_variables:dict) -> SwarmResult: """Keep the summary as short as possible.""" context_variables["story"] = story_summary st.sidebar.success('Story overview: ' + story_summary) return SwarmResult(agent="gameplay_agent", context_variables=context_variables) def update_gameplay_overview(gameplay_summary:str, context_variables:dict) -> SwarmResult: """Keep the summary as short as possible.""" context_variables["gameplay"] = gameplay_summary st.sidebar.success('Gameplay overview: ' + gameplay_summary) return SwarmResult(agent="visuals_agent", context_variables=context_variables) def update_visuals_overview(visuals_summary:str, context_variables:dict) -> SwarmResult: """Keep the summary as short as possible.""" context_variables["visuals"] = visuals_summary st.sidebar.success('Visuals overview: ' + visuals_summary) return SwarmResult(agent="tech_agent", context_variables=context_variables) def update_tech_overview(tech_summary:str, context_variables:dict) -> SwarmResult: """Keep the summary as short as possible.""" context_variables["tech"] = tech_summary st.sidebar.success('Tech overview: ' + tech_summary) return SwarmResult(agent="story_agent", context_variables=context_variables) system_messages = { "story_agent": """ You are an experienced game story designer specializing in narrative design and world-building. Your task is to: 1. Create a compelling narrative that aligns with the specified game type and target audience. 2. Design memorable characters with clear motivations and character arcs. 3. Develop the game's world, including its history, culture, and key locations. 4. Plan story progression and major plot points. 5. Integrate the narrative with the specified mood/atmosphere. 6. Consider how the story supports the core gameplay mechanics. """, "gameplay_agent": """ You are a senior game mechanics designer with expertise in player engagement and systems design. Your task is to: 1. Design core gameplay loops that match the specified game type and mechanics. 2. Create progression systems (character development, skills, abilities). 3. Define player interactions and control schemes for the chosen perspective. 4. Balance gameplay elements for the target audience. 5. Design multiplayer interactions if applicable. 6. Specify game modes and difficulty settings. 7. Consider the budget and development time constraints. """, "visuals_agent": """ You are a creative art director with expertise in game visual and audio design. Your task is to: 1. Define the visual style guide matching the specified art style. 2. Design character and environment aesthetics. 3. Plan visual effects and animations. 4. Create the audio direction including music style, sound effects, and ambient sound. 5. Consider technical constraints of chosen platforms. 6. Align visual elements with the game's mood/atmosphere. 7. Work within the specified budget constraints. """, "tech_agent": """ You are a technical director with extensive game development experience. Your task is to: 1. Recommend appropriate game engine and development tools. 2. Define technical requirements for all target platforms. 3. Plan the development pipeline and asset workflow. 4. Identify potential technical challenges and solutions. 5. Estimate resource requirements within the budget. 6. Consider scalability and performance optimization. 7. Plan for multiplayer infrastructure if applicable. """ } def update_system_message_func(agent: SwarmAgent, messages) -> str: """""" system_prompt = system_messages[agent.name] current_gen = agent.name.split("_")[0] if agent._context_variables.get(current_gen) is None: system_prompt += f"Call the update function provided to first provide a 2-3 sentence summary of your ideas on {current_gen.upper()} based on the context provided." agent.llm_config['tool_choice'] = {"type": "function", "function": {"name": f"update_{current_gen}_overview"}} agent.client = OpenAIWrapper(**agent.llm_config) else: # remove the tools to avoid the agent from using it and reduce cost agent.llm_config["tools"] = None agent.llm_config['tool_choice'] = None agent.client = OpenAIWrapper(**agent.llm_config) # the agent has given a summary, now it should generate a detailed response system_prompt += f"\n\nYour task\nYou task is write the {current_gen} part of the report. Do not include any other parts. Do not use XML tags.\nStart your response with: '## {current_gen.capitalize()} Design'." # Remove all messages except the first one with less cost k = list(agent._oai_messages.keys())[-1] agent._oai_messages[k] = agent._oai_messages[k][:1] system_prompt += f"\n\n\nBelow are some context for you to refer to:" # Add context variables to the prompt for k, v in agent._context_variables.items(): if v is not None: system_prompt += f"\n{k.capitalize()} Summary:\n{v}" return system_prompt state_update = UPDATE_SYSTEM_MESSAGE(update_system_message_func) # Define agents story_agent = SwarmAgent( "story_agent", llm_config=llm_config, functions=update_story_overview, update_agent_state_before_reply=[state_update] ) gameplay_agent = SwarmAgent( "gameplay_agent", llm_config= llm_config, functions=update_gameplay_overview, update_agent_state_before_reply=[state_update] ) visuals_agent = SwarmAgent( "visuals_agent", llm_config=llm_config, functions=update_visuals_overview, update_agent_state_before_reply=[state_update] ) tech_agent = SwarmAgent( name="tech_agent", llm_config=llm_config, functions=update_tech_overview, update_agent_state_before_reply=[state_update] ) story_agent.register_hand_off(AFTER_WORK(gameplay_agent)) gameplay_agent.register_hand_off(AFTER_WORK(visuals_agent)) visuals_agent.register_hand_off(AFTER_WORK(tech_agent)) tech_agent.register_hand_off(AFTER_WORK(story_agent)) result, _, _ = initiate_swarm_chat( initial_agent=story_agent, agents=[story_agent, gameplay_agent, visuals_agent, tech_agent], user_agent=None, messages=task, max_rounds=13, ) # Update session state with the individual responses st.session_state.output = { 'story': result.chat_history[-4]['content'], 'gameplay': result.chat_history[-3]['content'], 'visuals': result.chat_history[-2]['content'], 'tech': result.chat_history[-1]['content'] } # Display success message after completion st.success('✨ Game concept generated successfully!') # Display the individual outputs in expanders with st.expander("Story Design"): st.markdown(st.session_state.output['story']) with st.expander("Gameplay Mechanics"): st.markdown(st.session_state.output['gameplay']) with st.expander("Visual and Audio Design"): st.markdown(st.session_state.output['visuals']) with st.expander("Technical Recommendations"): st.markdown(st.session_state.output['tech']) ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_game_design_agent_team/requirements.txt streamlit==1.41.1 autogen ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/README.md # 👨‍⚖️ AI Legal Agent Team A Streamlit application that simulates a full-service legal team using multiple AI agents to analyze legal documents and provide comprehensive legal insights. Each agent represents a different legal specialist role, from research and contract analysis to strategic planning, working together to provide thorough legal analysis and recommendations. ## Features - **Specialized Legal AI Agent Team** - **Legal Researcher**: Equipped with DuckDuckGo search tool to find and cite relevant legal cases and precedents. Provides detailed research summaries with sources and references specific sections from uploaded documents. - **Contract Analyst**: Specializes in thorough contract review, identifying key terms, obligations, and potential issues. References specific clauses from documents for detailed analysis. - **Legal Strategist**: Focuses on developing comprehensive legal strategies, providing actionable recommendations while considering both risks and opportunities. - **Team Lead**: Coordinates analysis between team members, ensures comprehensive responses, properly sourced recommendations, and references to specific document parts. Acts as an Agent Team coordinator for all three agents. - **Document Analysis Types** - Contract Review - Done by Contract Analyst - Legal Research - Done by Legal Researcher - Risk Assessment - Done by Legal Strategist, Contract Analyst - Compliance Check - Done by Legal Strategist, Legal Researcher, Contract Analyst - Custom Queries - Done by Agent Team - Legal Researcher, Legal Strategist, Contract Analyst ## How to Run 1. **Setup Environment** ```bash # Clone the repository git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd awesome-llm-apps/ai_agent_tutorials/ai_legal_agent_team # Install dependencies pip install -r requirements.txt ``` 2. **Configure API Keys** - Get OpenAI API key from [OpenAI Platform](https://platform.openai.com) - Get Qdrant API key and URL from [Qdrant Cloud](https://cloud.qdrant.io) 3. **Run the Application** ```bash streamlit run legal_agent_team.py ``` 4. **Use the Interface** - Enter API credentials - Upload a legal document (PDF) - Select analysis type - Add custom queries if needed - View analysis results ## Notes - Supports PDF documents only - Uses GPT-4o for analysis - Uses text-embedding-3-small for embeddings - Requires stable internet connection - API usage costs apply ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/legal_agent_team.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/legal_agent_team.py" import streamlit as st from agno.agent import Agent from agno.knowledge.pdf import PDFKnowledgeBase, PDFReader from agno.vectordb.qdrant import Qdrant from agno.tools.duckduckgo import DuckDuckGoTools from agno.models.openai import OpenAIChat from agno.embedder.openai import OpenAIEmbedder import tempfile import os from agno.document.chunking.document import DocumentChunking def init_session_state(): """Initialize session state variables""" if 'openai_api_key' not in st.session_state: st.session_state.openai_api_key = None if 'qdrant_api_key' not in st.session_state: st.session_state.qdrant_api_key = None if 'qdrant_url' not in st.session_state: st.session_state.qdrant_url = None if 'vector_db' not in st.session_state: st.session_state.vector_db = None if 'legal_team' not in st.session_state: st.session_state.legal_team = None if 'knowledge_base' not in st.session_state: st.session_state.knowledge_base = None # Add a new state variable to track processed files if 'processed_files' not in st.session_state: st.session_state.processed_files = set() COLLECTION_NAME = "legal_documents" # Define your collection name def init_qdrant(): """Initialize Qdrant client with configured settings.""" if not all([st.session_state.qdrant_api_key, st.session_state.qdrant_url]): return None try: # Create Agno's Qdrant instance which implements VectorDb vector_db = Qdrant( collection=COLLECTION_NAME, url=st.session_state.qdrant_url, api_key=st.session_state.qdrant_api_key, embedder=OpenAIEmbedder( id="text-embedding-3-small", api_key=st.session_state.openai_api_key ) ) return vector_db except Exception as e: st.error(f"🔴 Qdrant connection failed: {str(e)}") return None def process_document(uploaded_file, vector_db: Qdrant): """ Process document, create embeddings and store in Qdrant vector database Args: uploaded_file: Streamlit uploaded file object vector_db (Qdrant): Initialized Qdrant instance from Agno Returns: PDFKnowledgeBase: Initialized knowledge base with processed documents """ if not st.session_state.openai_api_key: raise ValueError("OpenAI API key not provided") os.environ['OPENAI_API_KEY'] = st.session_state.openai_api_key try: # Save the uploaded file to a temporary location with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as temp_file: temp_file.write(uploaded_file.getvalue()) temp_file_path = temp_file.name st.info("Loading and processing document...") # Create a PDFKnowledgeBase with the vector_db knowledge_base = PDFKnowledgeBase( path=temp_file_path, # Single string path, not a list vector_db=vector_db, reader=PDFReader(), chunking_strategy=DocumentChunking( chunk_size=1000, overlap=200 ) ) # Load the documents into the knowledge base with st.spinner('📤 Loading documents into knowledge base...'): try: knowledge_base.load(recreate=True, upsert=True) st.success("✅ Documents stored successfully!") except Exception as e: st.error(f"Error loading documents: {str(e)}") raise # Clean up the temporary file try: os.unlink(temp_file_path) except Exception: pass return knowledge_base except Exception as e: st.error(f"Document processing error: {str(e)}") raise Exception(f"Error processing document: {str(e)}") def main(): st.set_page_config(page_title="Legal Document Analyzer", layout="wide") init_session_state() st.title("AI Legal Agent Team 👨‍⚖️") with st.sidebar: st.header("🔑 API Configuration") openai_key = st.text_input( "OpenAI API Key", type="password", value=st.session_state.openai_api_key if st.session_state.openai_api_key else "", help="Enter your OpenAI API key" ) if openai_key: st.session_state.openai_api_key = openai_key qdrant_key = st.text_input( "Qdrant API Key", type="password", value=st.session_state.qdrant_api_key if st.session_state.qdrant_api_key else "", help="Enter your Qdrant API key" ) if qdrant_key: st.session_state.qdrant_api_key = qdrant_key qdrant_url = st.text_input( "Qdrant URL", value=st.session_state.qdrant_url if st.session_state.qdrant_url else "", help="Enter your Qdrant instance URL" ) if qdrant_url: st.session_state.qdrant_url = qdrant_url if all([st.session_state.qdrant_api_key, st.session_state.qdrant_url]): try: if not st.session_state.vector_db: # Make sure we're initializing a QdrantClient here st.session_state.vector_db = init_qdrant() if st.session_state.vector_db: st.success("Successfully connected to Qdrant!") except Exception as e: st.error(f"Failed to connect to Qdrant: {str(e)}") st.divider() if all([st.session_state.openai_api_key, st.session_state.vector_db]): st.header("📄 Document Upload") uploaded_file = st.file_uploader("Upload Legal Document", type=['pdf']) if uploaded_file: # Check if this file has already been processed if uploaded_file.name not in st.session_state.processed_files: with st.spinner("Processing document..."): try: # Process the document and get the knowledge base knowledge_base = process_document(uploaded_file, st.session_state.vector_db) if knowledge_base: st.session_state.knowledge_base = knowledge_base # Add the file to processed files st.session_state.processed_files.add(uploaded_file.name) # Initialize agents legal_researcher = Agent( name="Legal Researcher", role="Legal research specialist", model=OpenAIChat(id="gpt-4.1"), tools=[DuckDuckGoTools()], knowledge=st.session_state.knowledge_base, search_knowledge=True, instructions=[ "Find and cite relevant legal cases and precedents", "Provide detailed research summaries with sources", "Reference specific sections from the uploaded document", "Always search the knowledge base for relevant information" ], show_tool_calls=True, markdown=True ) contract_analyst = Agent( name="Contract Analyst", role="Contract analysis specialist", model=OpenAIChat(id="gpt-4.1"), knowledge=st.session_state.knowledge_base, search_knowledge=True, instructions=[ "Review contracts thoroughly", "Identify key terms and potential issues", "Reference specific clauses from the document" ], markdown=True ) legal_strategist = Agent( name="Legal Strategist", role="Legal strategy specialist", model=OpenAIChat(id="gpt-4.1"), knowledge=st.session_state.knowledge_base, search_knowledge=True, instructions=[ "Develop comprehensive legal strategies", "Provide actionable recommendations", "Consider both risks and opportunities" ], markdown=True ) # Legal Agent Team st.session_state.legal_team = Agent( name="Legal Team Lead", role="Legal team coordinator", model=OpenAIChat(id="gpt-4.1"), team=[legal_researcher, contract_analyst, legal_strategist], knowledge=st.session_state.knowledge_base, search_knowledge=True, instructions=[ "Coordinate analysis between team members", "Provide comprehensive responses", "Ensure all recommendations are properly sourced", "Reference specific parts of the uploaded document", "Always search the knowledge base before delegating tasks" ], show_tool_calls=True, markdown=True ) st.success("✅ Document processed and team initialized!") except Exception as e: st.error(f"Error processing document: {str(e)}") else: # File already processed, just show a message st.success("✅ Document already processed and team ready!") st.divider() st.header("🔍 Analysis Options") analysis_type = st.selectbox( "Select Analysis Type", [ "Contract Review", "Legal Research", "Risk Assessment", "Compliance Check", "Custom Query" ] ) else: st.warning("Please configure all API credentials to proceed") # Main content area if not all([st.session_state.openai_api_key, st.session_state.vector_db]): st.info("👈 Please configure your API credentials in the sidebar to begin") elif not uploaded_file: st.info("👈 Please upload a legal document to begin analysis") elif st.session_state.legal_team: # Create a dictionary for analysis type icons analysis_icons = { "Contract Review": "📑", "Legal Research": "🔍", "Risk Assessment": "⚠️", "Compliance Check": "✅", "Custom Query": "💭" } # Dynamic header with icon st.header(f"{analysis_icons[analysis_type]} {analysis_type} Analysis") analysis_configs = { "Contract Review": { "query": "Review this contract and identify key terms, obligations, and potential issues.", "agents": ["Contract Analyst"], "description": "Detailed contract analysis focusing on terms and obligations" }, "Legal Research": { "query": "Research relevant cases and precedents related to this document.", "agents": ["Legal Researcher"], "description": "Research on relevant legal cases and precedents" }, "Risk Assessment": { "query": "Analyze potential legal risks and liabilities in this document.", "agents": ["Contract Analyst", "Legal Strategist"], "description": "Combined risk analysis and strategic assessment" }, "Compliance Check": { "query": "Check this document for regulatory compliance issues.", "agents": ["Legal Researcher", "Contract Analyst", "Legal Strategist"], "description": "Comprehensive compliance analysis" }, "Custom Query": { "query": None, "agents": ["Legal Researcher", "Contract Analyst", "Legal Strategist"], "description": "Custom analysis using all available agents" } } st.info(f"📋 {analysis_configs[analysis_type]['description']}") st.write(f"🤖 Active Legal AI Agents: {', '.join(analysis_configs[analysis_type]['agents'])}") #dictionary!! # Replace the existing user_query section with this: if analysis_type == "Custom Query": user_query = st.text_area( "Enter your specific query:", help="Add any specific questions or points you want to analyze" ) else: user_query = None # Set to None for non-custom queries if st.button("Analyze"): if analysis_type == "Custom Query" and not user_query: st.warning("Please enter a query") else: with st.spinner("Analyzing document..."): try: # Ensure OpenAI API key is set os.environ['OPENAI_API_KEY'] = st.session_state.openai_api_key # Combine predefined and user queries if analysis_type != "Custom Query": combined_query = f""" Using the uploaded document as reference: Primary Analysis Task: {analysis_configs[analysis_type]['query']} Focus Areas: {', '.join(analysis_configs[analysis_type]['agents'])} Please search the knowledge base and provide specific references from the document. """ else: combined_query = f""" Using the uploaded document as reference: {user_query} Please search the knowledge base and provide specific references from the document. Focus Areas: {', '.join(analysis_configs[analysis_type]['agents'])} """ response = st.session_state.legal_team.run(combined_query) # Display results in tabs tabs = st.tabs(["Analysis", "Key Points", "Recommendations"]) with tabs[0]: st.markdown("### Detailed Analysis") if response.content: st.markdown(response.content) else: for message in response.messages: if message.role == 'assistant' and message.content: st.markdown(message.content) with tabs[1]: st.markdown("### Key Points") key_points_response = st.session_state.legal_team.run( f"""Based on this previous analysis: {response.content} Please summarize the key points in bullet points. Focus on insights from: {', '.join(analysis_configs[analysis_type]['agents'])}""" ) if key_points_response.content: st.markdown(key_points_response.content) else: for message in key_points_response.messages: if message.role == 'assistant' and message.content: st.markdown(message.content) with tabs[2]: st.markdown("### Recommendations") recommendations_response = st.session_state.legal_team.run( f"""Based on this previous analysis: {response.content} What are your key recommendations based on the analysis, the best course of action? Provide specific recommendations from: {', '.join(analysis_configs[analysis_type]['agents'])}""" ) if recommendations_response.content: st.markdown(recommendations_response.content) else: for message in recommendations_response.messages: if message.role == 'assistant' and message.content: st.markdown(message.content) except Exception as e: st.error(f"Error during analysis: {str(e)}") else: st.info("Please upload a legal document to begin analysis") if __name__ == "__main__": main() ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/local_ai_legal_agent_team/README.md ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/local_ai_legal_agent_team/local_legal_agent.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/local_ai_legal_agent_team/local_legal_agent.py" import streamlit as st from agno.agent import Agent from agno.knowledge.pdf import PDFKnowledgeBase, PDFReader from agno.vectordb.qdrant import Qdrant from agno.models.ollama import Ollama from agno.embedder.ollama import OllamaEmbedder import tempfile import os def init_session_state(): if 'vector_db' not in st.session_state: st.session_state.vector_db = None if 'legal_team' not in st.session_state: st.session_state.legal_team = None if 'knowledge_base' not in st.session_state: st.session_state.knowledge_base = None def init_qdrant(): """Initialize local Qdrant vector database""" return Qdrant( collection="legal_knowledge", url="http://localhost:6333", embedder=OllamaEmbedder(model="openhermes") ) def process_document(uploaded_file, vector_db: Qdrant): """Process document using local resources""" with tempfile.TemporaryDirectory() as temp_dir: temp_file_path = os.path.join(temp_dir, uploaded_file.name) with open(temp_file_path, "wb") as f: f.write(uploaded_file.getbuffer()) try: st.write("Processing document...") # Create knowledge base with local embedder knowledge_base = PDFKnowledgeBase( path=temp_dir, vector_db=vector_db, reader=PDFReader(chunk=True), recreate_vector_db=True ) st.write("Loading knowledge base...") knowledge_base.load() # Verify knowledge base st.write("Verifying knowledge base...") test_results = knowledge_base.search("test") if not test_results: raise Exception("Knowledge base verification failed") st.write("Knowledge base ready!") return knowledge_base except Exception as e: raise Exception(f"Error processing document: {str(e)}") def main(): st.set_page_config(page_title="Local Legal Document Analyzer", layout="wide") init_session_state() st.title("Local AI Legal Agent Team") # Initialize local Qdrant if not st.session_state.vector_db: try: st.session_state.vector_db = init_qdrant() st.success("Connected to local Qdrant!") except Exception as e: st.error(f"Failed to connect to Qdrant: {str(e)}") return # Document upload section st.header("📄 Document Upload") uploaded_file = st.file_uploader("Upload Legal Document", type=['pdf']) if uploaded_file: with st.spinner("Processing document..."): try: knowledge_base = process_document(uploaded_file, st.session_state.vector_db) st.session_state.knowledge_base = knowledge_base # Initialize agents with Llama model legal_researcher = Agent( name="Legal Researcher", role="Legal research specialist", model=Ollama(id="llama3.1:8b"), knowledge=st.session_state.knowledge_base, search_knowledge=True, instructions=[ "Find and cite relevant legal cases and precedents", "Provide detailed research summaries with sources", "Reference specific sections from the uploaded document" ], markdown=True ) contract_analyst = Agent( name="Contract Analyst", role="Contract analysis specialist", model=Ollama(id="llama3.1:8b"), knowledge=knowledge_base, search_knowledge=True, instructions=[ "Review contracts thoroughly", "Identify key terms and potential issues", "Reference specific clauses from the document" ], markdown=True ) legal_strategist = Agent( name="Legal Strategist", role="Legal strategy specialist", model=Ollama(id="llama3.1:8b"), knowledge=knowledge_base, search_knowledge=True, instructions=[ "Develop comprehensive legal strategies", "Provide actionable recommendations", "Consider both risks and opportunities" ], markdown=True ) # Legal Agent Team st.session_state.legal_team = Agent( name="Legal Team Lead", role="Legal team coordinator", model=Ollama(id="llama3.1:8b"), team=[legal_researcher, contract_analyst, legal_strategist], knowledge=st.session_state.knowledge_base, search_knowledge=True, instructions=[ "Coordinate analysis between team members", "Provide comprehensive responses", "Ensure all recommendations are properly sourced", "Reference specific parts of the uploaded document" ], markdown=True ) st.success("✅ Document processed and team initialized!") except Exception as e: st.error(f"Error processing document: {str(e)}") st.divider() st.header("🔍 Analysis Options") analysis_type = st.selectbox( "Select Analysis Type", [ "Contract Review", "Legal Research", "Risk Assessment", "Compliance Check", "Custom Query" ] ) # Main content area if not st.session_state.vector_db: st.info("👈 Waiting for Qdrant connection...") elif not uploaded_file: st.info("👈 Please upload a legal document to begin analysis") elif st.session_state.legal_team: st.header("Document Analysis") analysis_configs = { "Contract Review": { "query": "Review this contract and identify key terms, obligations, and potential issues.", "agents": ["Contract Analyst"], "description": "Detailed contract analysis focusing on terms and obligations" }, "Legal Research": { "query": "Research relevant cases and precedents related to this document.", "agents": ["Legal Researcher"], "description": "Research on relevant legal cases and precedents" }, "Risk Assessment": { "query": "Analyze potential legal risks and liabilities in this document.", "agents": ["Contract Analyst", "Legal Strategist"], "description": "Combined risk analysis and strategic assessment" }, "Compliance Check": { "query": "Check this document for regulatory compliance issues.", "agents": ["Legal Researcher", "Contract Analyst", "Legal Strategist"], "description": "Comprehensive compliance analysis" }, "Custom Query": { "query": None, "agents": ["Legal Researcher", "Contract Analyst", "Legal Strategist"], "description": "Custom analysis using all available agents" } } st.info(f"📋 {analysis_configs[analysis_type]['description']}") st.write(f"🤖 Active Agents: {', '.join(analysis_configs[analysis_type]['agents'])}") user_query = st.text_area( "Enter your specific query:", help="Add any specific questions or points you want to analyze" ) if st.button("Analyze"): if user_query or analysis_type != "Custom Query": with st.spinner("Analyzing document..."): try: # Combine predefined and user queries if analysis_type != "Custom Query": combined_query = f""" Using the uploaded document as reference: Primary Analysis Task: {analysis_configs[analysis_type]['query']} Additional User Query: {user_query if user_query else 'None'} Focus Areas: {', '.join(analysis_configs[analysis_type]['agents'])} Please search the knowledge base and provide specific references from the document. """ else: combined_query = user_query response = st.session_state.legal_team.run(combined_query) # Display results in tabs tabs = st.tabs(["Analysis", "Key Points", "Recommendations"]) with tabs[0]: st.markdown("### Detailed Analysis") if response.content: st.markdown(response.content) else: for message in response.messages: if message.role == 'assistant' and message.content: st.markdown(message.content) with tabs[1]: st.markdown("### Key Points") key_points_response = st.session_state.legal_team.run( f"""Based on this previous analysis: {response.content} Please summarize the key points in bullet points. Focus on insights from: {', '.join(analysis_configs[analysis_type]['agents'])}""" ) if key_points_response.content: st.markdown(key_points_response.content) else: for message in key_points_response.messages: if message.role == 'assistant' and message.content: st.markdown(message.content) with tabs[2]: st.markdown("### Recommendations") recommendations_response = st.session_state.legal_team.run( f"""Based on this previous analysis: {response.content} What are your key recommendations based on the analysis, the best course of action? Provide specific recommendations from: {', '.join(analysis_configs[analysis_type]['agents'])}""" ) if recommendations_response.content: st.markdown(recommendations_response.content) else: for message in recommendations_response.messages: if message.role == 'assistant' and message.content: st.markdown(message.content) except Exception as e: st.error(f"Error during analysis: {str(e)}") else: st.warning("Please enter a query or select an analysis type") else: st.info("Please upload a legal document to begin analysis") if __name__ == "__main__": main() ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/local_ai_legal_agent_team/requirements.txt agno streamlit==1.40.2 qdrant-client==1.12.1 ollama==0.4.4 ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_legal_agent_team/requirements.txt agno streamlit==1.40.2 qdrant-client==1.12.1 openai pypdf duckduckgo-search ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_recruitment_agent_team/README.md # 💼 AI Recruitment Agent Team A Streamlit application that simulates a full-service recruitment team using multiple AI agents to automate and streamline the hiring process. Each agent represents a different recruitment specialist role - from resume analysis and candidate evaluation to interview scheduling and communication - working together to provide comprehensive hiring solutions. The system combines the expertise of technical recruiters, HR coordinators, and scheduling specialists into a cohesive automated workflow. ## Features #### Specialized AI Agents - Technical Recruiter Agent: Analyzes resumes and evaluates technical skills - Communication Agent: Handles professional email correspondence - Scheduling Coordinator Agent: Manages interview scheduling and coordination - Each agent has specific expertise and collaborates for comprehensive recruitment #### End-to-End Recruitment Process - Automated resume screening and analysis - Role-specific technical evaluation - Professional candidate communication - Automated interview scheduling - Integrated feedback system ## Important Things to do before running the application - Create/Use a new Gmail account for the recruiter - Enable 2-Step Verification and generate an App Password for the Gmail account - The App Password is a 16 digit code (use without spaces) that should be generated here - [Google App Password](https://support.google.com/accounts/answer/185833?hl=en) Please go through the steps to generate the password - it will of the format - 'afec wejf awoj fwrv' (remove the spaces and enter it in the streamlit app) - Create/ Use a Zoom account and go to the Zoom App Marketplace to get the API credentials : [Zoom Marketplace](https://marketplace.zoom.us) - Go to Developer Dashboard and create a new app - Select Server to Server OAuth and get the credentials, You see 3 credentials - Client ID, Client Secret and Account ID - After that, you need to add a few scopes to the app - so that the zoom link of the candidate is sent and created through the mail. - The Scopes are meeting:write:invite_links:admin, meeting:write:meeting:admin, meeting:write:meeting:master, meeting:write:invite_links:master, meeting:write:open_app:admin, user:read:email:admin, user:read:list_users:admin, billing:read:user_entitlement:admin, dashboard:read:list_meeting_participants:admin [last 3 are optional] ## How to Run 1. **Setup Environment** ```bash # Clone the repository git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd ai_agent_tutorials/ai_recruitment_agent_team # Install dependencies pip install -r requirements.txt ``` 2. **Configure API Keys** - OpenAI API key for GPT-4o access - Zoom API credentials (Account ID, Client ID, Client Secret) - Email App Password of Recruiter's Email 3. **Run the Application** ```bash streamlit run ai_recruitment_agent_team.py ``` ## System Components - **Resume Analyzer Agent** - Skills matching algorithm - Experience verification - Technical assessment - Selection decision making - **Email Communication Agent** - Professional email drafting - Automated notifications - Feedback communication - Follow-up management - **Interview Scheduler Agent** - Zoom meeting coordination - Calendar management - Timezone handling - Reminder system - **Candidate Experience** - Simple upload interface - Real-time feedback - Clear communication - Streamlined process ## Technical Stack - **Framework**: Phidata - **Model**: OpenAI GPT-4o - **Integration**: Zoom API, EmailTools Tool from Phidata - **PDF Processing**: PyPDF2 - **Time Management**: pytz - **State Management**: Streamlit Session State ## Disclaimer This tool is designed to assist in the recruitment process but should not completely replace human judgment in hiring decisions. All automated decisions should be reviewed by human recruiters for final approval. ## Future Enhancements - Integration with ATS systems - Advanced candidate scoring - Video interview capabilities - Skills assessment integration - Multi-language support ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_recruitment_agent_team/ai_recruitment_agent_team.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/ai_recruitment_agent_team/ai_recruitment_agent_team.py" from typing import Literal, Tuple, Dict, Optional import os import time import json import requests import PyPDF2 from datetime import datetime, timedelta import pytz import streamlit as st from agno.agent import Agent from agno.models.openai import OpenAIChat from agno.tools.email import EmailTools from phi.tools.zoom import ZoomTool from phi.utils.log import logger from streamlit_pdf_viewer import pdf_viewer class CustomZoomTool(ZoomTool): def __init__(self, *, account_id: Optional[str] = None, client_id: Optional[str] = None, client_secret: Optional[str] = None, name: str = "zoom_tool"): super().__init__(account_id=account_id, client_id=client_id, client_secret=client_secret, name=name) self.token_url = "https://zoom.us/oauth/token" self.access_token = None self.token_expires_at = 0 def get_access_token(self) -> str: if self.access_token and time.time() < self.token_expires_at: return str(self.access_token) headers = {"Content-Type": "application/x-www-form-urlencoded"} data = {"grant_type": "account_credentials", "account_id": self.account_id} try: response = requests.post(self.token_url, headers=headers, data=data, auth=(self.client_id, self.client_secret)) response.raise_for_status() token_info = response.json() self.access_token = token_info["access_token"] expires_in = token_info["expires_in"] self.token_expires_at = time.time() + expires_in - 60 self._set_parent_token(str(self.access_token)) return str(self.access_token) except requests.RequestException as e: logger.error(f"Error fetching access token: {e}") return "" def _set_parent_token(self, token: str) -> None: """Helper method to set the token in the parent ZoomTool class""" if token: self._ZoomTool__access_token = token # Role requirements as a constant dictionary ROLE_REQUIREMENTS: Dict[str, str] = { "ai_ml_engineer": """ Required Skills: - Python, PyTorch/TensorFlow - Machine Learning algorithms and frameworks - Deep Learning and Neural Networks - Data preprocessing and analysis - MLOps and model deployment - RAG, LLM, Finetuning and Prompt Engineering """, "frontend_engineer": """ Required Skills: - React/Vue.js/Angular - HTML5, CSS3, JavaScript/TypeScript - Responsive design - State management - Frontend testing """, "backend_engineer": """ Required Skills: - Python/Java/Node.js - REST APIs - Database design and management - System architecture - Cloud services (AWS/GCP/Azure) - Kubernetes, Docker, CI/CD """ } def init_session_state() -> None: """Initialize only necessary session state variables.""" defaults = { 'candidate_email': "", 'openai_api_key': "", 'resume_text': "", 'analysis_complete': False, 'is_selected': False, 'zoom_account_id': "", 'zoom_client_id': "", 'zoom_client_secret': "", 'email_sender': "", 'email_passkey': "", 'company_name': "", 'current_pdf': None } for key, value in defaults.items(): if key not in st.session_state: st.session_state[key] = value def create_resume_analyzer() -> Agent: """Creates and returns a resume analysis agent.""" if not st.session_state.openai_api_key: st.error("Please enter your OpenAI API key first.") return None return Agent( model=OpenAIChat( id="gpt-4o", api_key=st.session_state.openai_api_key ), description="You are an expert technical recruiter who analyzes resumes.", instructions=[ "Analyze the resume against the provided job requirements", "Be lenient with AI/ML candidates who show strong potential", "Consider project experience as valid experience", "Value hands-on experience with key technologies", "Return a JSON response with selection decision and feedback" ], markdown=True ) def create_email_agent() -> Agent: return Agent( model=OpenAIChat( id="gpt-4o", api_key=st.session_state.openai_api_key ), tools=[EmailTools( receiver_email=st.session_state.candidate_email, sender_email=st.session_state.email_sender, sender_name=st.session_state.company_name, sender_passkey=st.session_state.email_passkey )], description="You are a professional recruitment coordinator handling email communications.", instructions=[ "Draft and send professional recruitment emails", "Act like a human writing an email and use all lowercase letters", "Maintain a friendly yet professional tone", "Always end emails with exactly: 'best,\nthe ai recruiting team'", "Never include the sender's or receiver's name in the signature", f"The name of the company is '{st.session_state.company_name}'" ], markdown=True, show_tool_calls=True ) def create_scheduler_agent() -> Agent: zoom_tools = CustomZoomTool( account_id=st.session_state.zoom_account_id, client_id=st.session_state.zoom_client_id, client_secret=st.session_state.zoom_client_secret ) return Agent( name="Interview Scheduler", model=OpenAIChat( id="gpt-4o", api_key=st.session_state.openai_api_key ), tools=[zoom_tools], description="You are an interview scheduling coordinator.", instructions=[ "You are an expert at scheduling technical interviews using Zoom.", "Schedule interviews during business hours (9 AM - 5 PM EST)", "Create meetings with proper titles and descriptions", "Ensure all meeting details are included in responses", "Use ISO 8601 format for dates", "Handle scheduling errors gracefully" ], markdown=True, show_tool_calls=True ) def extract_text_from_pdf(pdf_file) -> str: try: pdf_reader = PyPDF2.PdfReader(pdf_file) text = "" for page in pdf_reader.pages: text += page.extract_text() return text except Exception as e: st.error(f"Error extracting PDF text: {str(e)}") return "" def analyze_resume( resume_text: str, role: Literal["ai_ml_engineer", "frontend_engineer", "backend_engineer"], analyzer: Agent ) -> Tuple[bool, str]: try: response = analyzer.run( f"""Please analyze this resume against the following requirements and provide your response in valid JSON format: Role Requirements: {ROLE_REQUIREMENTS[role]} Resume Text: {resume_text} Your response must be a valid JSON object like this: {{ "selected": true/false, "feedback": "Detailed feedback explaining the decision", "matching_skills": ["skill1", "skill2"], "missing_skills": ["skill3", "skill4"], "experience_level": "junior/mid/senior" }} Evaluation criteria: 1. Match at least 70% of required skills 2. Consider both theoretical knowledge and practical experience 3. Value project experience and real-world applications 4. Consider transferable skills from similar technologies 5. Look for evidence of continuous learning and adaptability Important: Return ONLY the JSON object without any markdown formatting or backticks. """ ) assistant_message = next((msg.content for msg in response.messages if msg.role == 'assistant'), None) if not assistant_message: raise ValueError("No assistant message found in response.") result = json.loads(assistant_message.strip()) if not isinstance(result, dict) or not all(k in result for k in ["selected", "feedback"]): raise ValueError("Invalid response format") return result["selected"], result["feedback"] except (json.JSONDecodeError, ValueError) as e: st.error(f"Error processing response: {str(e)}") return False, f"Error analyzing resume: {str(e)}" def send_selection_email(email_agent: Agent, to_email: str, role: str) -> None: email_agent.run( f""" Send an email to {to_email} regarding their selection for the {role} position. The email should: 1. Congratulate them on being selected 2. Explain the next steps in the process 3. Mention that they will receive interview details shortly 4. The name of the company is 'AI Recruiting Team' """ ) def send_rejection_email(email_agent: Agent, to_email: str, role: str, feedback: str) -> None: """ Send a rejection email with constructive feedback. """ email_agent.run( f""" Send an email to {to_email} regarding their application for the {role} position. Use this specific style: 1. use all lowercase letters 2. be empathetic and human 3. mention specific feedback from: {feedback} 4. encourage them to upskill and try again 5. suggest some learning resources based on missing skills 6. end the email with exactly: best, the ai recruiting team Do not include any names in the signature. The tone should be like a human writing a quick but thoughtful email. """ ) def schedule_interview(scheduler: Agent, candidate_email: str, email_agent: Agent, role: str) -> None: """ Schedule interviews during business hours (9 AM - 5 PM IST). """ try: # Get current time in IST ist_tz = pytz.timezone('Asia/Kolkata') current_time_ist = datetime.now(ist_tz) tomorrow_ist = current_time_ist + timedelta(days=1) interview_time = tomorrow_ist.replace(hour=11, minute=0, second=0, microsecond=0) formatted_time = interview_time.strftime('%Y-%m-%dT%H:%M:%S') meeting_response = scheduler.run( f"""Schedule a 60-minute technical interview with these specifications: - Title: '{role} Technical Interview' - Date: {formatted_time} - Timezone: IST (India Standard Time) - Attendee: {candidate_email} Important Notes: - The meeting must be between 9 AM - 5 PM IST - Use IST (UTC+5:30) timezone for all communications - Include timezone information in the meeting details """ ) email_agent.run( f"""Send an interview confirmation email with these details: - Role: {role} position - Meeting Details: {meeting_response} Important: - Clearly specify that the time is in IST (India Standard Time) - Ask the candidate to join 5 minutes early - Include timezone conversion link if possible - Ask him to be confident and not so nervous and prepare well for the interview """ ) st.success("Interview scheduled successfully! Check your email for details.") except Exception as e: logger.error(f"Error scheduling interview: {str(e)}") st.error("Unable to schedule interview. Please try again.") def main() -> None: st.title("AI Recruitment System") init_session_state() with st.sidebar: st.header("Configuration") # OpenAI Configuration st.subheader("OpenAI Settings") api_key = st.text_input("OpenAI API Key", type="password", value=st.session_state.openai_api_key, help="Get your API key from platform.openai.com") if api_key: st.session_state.openai_api_key = api_key st.subheader("Zoom Settings") zoom_account_id = st.text_input("Zoom Account ID", type="password", value=st.session_state.zoom_account_id) zoom_client_id = st.text_input("Zoom Client ID", type="password", value=st.session_state.zoom_client_id) zoom_client_secret = st.text_input("Zoom Client Secret", type="password", value=st.session_state.zoom_client_secret) st.subheader("Email Settings") email_sender = st.text_input("Sender Email", value=st.session_state.email_sender, help="Email address to send from") email_passkey = st.text_input("Email App Password", type="password", value=st.session_state.email_passkey, help="App-specific password for email") company_name = st.text_input("Company Name", value=st.session_state.company_name, help="Name to use in email communications") if zoom_account_id: st.session_state.zoom_account_id = zoom_account_id if zoom_client_id: st.session_state.zoom_client_id = zoom_client_id if zoom_client_secret: st.session_state.zoom_client_secret = zoom_client_secret if email_sender: st.session_state.email_sender = email_sender if email_passkey: st.session_state.email_passkey = email_passkey if company_name: st.session_state.company_name = company_name required_configs = {'OpenAI API Key': st.session_state.openai_api_key, 'Zoom Account ID': st.session_state.zoom_account_id, 'Zoom Client ID': st.session_state.zoom_client_id, 'Zoom Client Secret': st.session_state.zoom_client_secret, 'Email Sender': st.session_state.email_sender, 'Email Password': st.session_state.email_passkey, 'Company Name': st.session_state.company_name} missing_configs = [k for k, v in required_configs.items() if not v] if missing_configs: st.warning(f"Please configure the following in the sidebar: {', '.join(missing_configs)}") return if not st.session_state.openai_api_key: st.warning("Please enter your OpenAI API key in the sidebar to continue.") return role = st.selectbox("Select the role you're applying for:", ["ai_ml_engineer", "frontend_engineer", "backend_engineer"]) with st.expander("View Required Skills", expanded=True): st.markdown(ROLE_REQUIREMENTS[role]) # Add a "New Application" button before the resume upload if st.button("📝 New Application"): # Clear only the application-related states keys_to_clear = ['resume_text', 'analysis_complete', 'is_selected', 'candidate_email', 'current_pdf'] for key in keys_to_clear: if key in st.session_state: st.session_state[key] = None if key == 'current_pdf' else "" st.rerun() resume_file = st.file_uploader("Upload your resume (PDF)", type=["pdf"], key="resume_uploader") if resume_file is not None and resume_file != st.session_state.get('current_pdf'): st.session_state.current_pdf = resume_file st.session_state.resume_text = "" st.session_state.analysis_complete = False st.session_state.is_selected = False st.rerun() if resume_file: st.subheader("Uploaded Resume") col1, col2 = st.columns([4, 1]) with col1: import tempfile, os with tempfile.NamedTemporaryFile(delete=False, suffix='.pdf') as tmp_file: tmp_file.write(resume_file.read()) tmp_file_path = tmp_file.name resume_file.seek(0) try: pdf_viewer(tmp_file_path) finally: os.unlink(tmp_file_path) with col2: st.download_button(label="📥 Download", data=resume_file, file_name=resume_file.name, mime="application/pdf") # Process the resume text if not st.session_state.resume_text: with st.spinner("Processing your resume..."): resume_text = extract_text_from_pdf(resume_file) if resume_text: st.session_state.resume_text = resume_text st.success("Resume processed successfully!") else: st.error("Could not process the PDF. Please try again.") # Email input with session state email = st.text_input( "Candidate's email address", value=st.session_state.candidate_email, key="email_input" ) st.session_state.candidate_email = email # Analysis and next steps if st.session_state.resume_text and email and not st.session_state.analysis_complete: if st.button("Analyze Resume"): with st.spinner("Analyzing your resume..."): resume_analyzer = create_resume_analyzer() email_agent = create_email_agent() # Create email agent here if resume_analyzer and email_agent: print("DEBUG: Starting resume analysis") is_selected, feedback = analyze_resume( st.session_state.resume_text, role, resume_analyzer ) print(f"DEBUG: Analysis complete - Selected: {is_selected}, Feedback: {feedback}") if is_selected: st.success("Congratulations! Your skills match our requirements.") st.session_state.analysis_complete = True st.session_state.is_selected = True st.rerun() else: st.warning("Unfortunately, your skills don't match our requirements.") st.write(f"Feedback: {feedback}") # Send rejection email with st.spinner("Sending feedback email..."): try: send_rejection_email( email_agent=email_agent, to_email=email, role=role, feedback=feedback ) st.info("We've sent you an email with detailed feedback.") except Exception as e: logger.error(f"Error sending rejection email: {e}") st.error("Could not send feedback email. Please try again.") if st.session_state.get('analysis_complete') and st.session_state.get('is_selected', False): st.success("Congratulations! Your skills match our requirements.") st.info("Click 'Proceed with Application' to continue with the interview process.") if st.button("Proceed with Application", key="proceed_button"): print("DEBUG: Proceed button clicked") # Debug with st.spinner("🔄 Processing your application..."): try: print("DEBUG: Creating email agent") # Debug email_agent = create_email_agent() print(f"DEBUG: Email agent created: {email_agent}") # Debug print("DEBUG: Creating scheduler agent") # Debug scheduler_agent = create_scheduler_agent() print(f"DEBUG: Scheduler agent created: {scheduler_agent}") # Debug # 3. Send selection email with st.status("📧 Sending confirmation email...", expanded=True) as status: print(f"DEBUG: Attempting to send email to {st.session_state.candidate_email}") # Debug send_selection_email( email_agent, st.session_state.candidate_email, role ) print("DEBUG: Email sent successfully") # Debug status.update(label="✅ Confirmation email sent!") # 4. Schedule interview with st.status("📅 Scheduling interview...", expanded=True) as status: print("DEBUG: Attempting to schedule interview") # Debug schedule_interview( scheduler_agent, st.session_state.candidate_email, email_agent, role ) print("DEBUG: Interview scheduled successfully") # Debug status.update(label="✅ Interview scheduled!") print("DEBUG: All processes completed successfully") # Debug st.success(""" 🎉 Application Successfully Processed! Please check your email for: 1. Selection confirmation ✅ 2. Interview details with Zoom link 🔗 Next steps: 1. Review the role requirements 2. Prepare for your technical interview 3. Join the interview 5 minutes early """) except Exception as e: print(f"DEBUG: Error occurred: {str(e)}") # Debug print(f"DEBUG: Error type: {type(e)}") # Debug import traceback print(f"DEBUG: Full traceback: {traceback.format_exc()}") # Debug st.error(f"An error occurred: {str(e)}") st.error("Please try again or contact support.") # Reset button if st.sidebar.button("Reset Application"): for key in st.session_state.keys(): if key != 'openai_api_key': del st.session_state[key] st.rerun() if __name__ == "__main__": main() ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_recruitment_agent_team/requirements.txt # Core dependencies phidata agno streamlit==1.40.2 PyPDF2==3.0.1 streamlit-pdf-viewer==0.0.19 requests==2.32.3 pytz==2023.4 typing-extensions>=4.9.0 # Optional but recommended black>=24.1.1 # for code formatting python-dateutil>=2.8.2 # for date parsing ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_services_agency/README.md # AI Services Agency 👨‍💼 An AI application that simulates a full-service digital agency using multiple AI agents to analyze and plan software projects. Each agent represents a different role in the project lifecycle, from strategic planning to technical implementation. ## Demo: https://github.com/user-attachments/assets/a0befa3a-f4c3-400d-9790-4b9e37254405 ## Features ### Five specialized AI agents - **CEO Agent**: Strategic leader and final decision maker - Analyzes startup ideas using structured evaluation - Makes strategic decisions across product, technical, marketing, and financial domains - Uses AnalyzeStartupTool and MakeStrategicDecision tools - **CTO Agent**: Technical architecture and feasibility expert - Evaluates technical requirements and feasibility - Provides architecture decisions - Uses QueryTechnicalRequirements and EvaluateTechnicalFeasibility tools - **Product Manager Agent**: Product strategy specialist - Defines product strategy and roadmap - Coordinates between technical and marketing teams - Focuses on product-market fit - **Developer Agent**: Technical implementation expert - Provides detailed technical implementation guidance - Suggests optimal tech stack and cloud solutions - Estimates development costs and timelines - **Client Success Agent**: Marketing strategy leader - Develops go-to-market strategies - Plans customer acquisition approaches - Coordinates with product team ### Custom Tools The agency uses specialized tools built with OpenAI Schema for structured analysis: - **Analysis Tools**: AnalyzeProjectRequirements for market evaluation and analysis of startup idea - **Technical Tools**: CreateTechnicalSpecification for technical assessment ### 🔄 Asynchronous Communication The agency operates in async mode, enabling: - Parallel processing of analyses from different agents - Efficient multi-agent collaboration - Real-time communication between agents - Non-blocking operations for better performance ### 🔗 Agent Communication Flows - CEO ↔️ All Agents (Strategic Oversight) - CTO ↔️ Developer (Technical Implementation) - Product Manager ↔️ Marketing Manager (Go-to-Market Strategy) - Product Manager ↔️ Developer (Feature Implementation) - (and more!) ## How to Run Follow the steps below to set up and run the application: Before anything else, Please get your OpenAI API Key here: https://platform.openai.com/api-keys 1. **Clone the Repository**: ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd awesome-llm-apps/ai_agent_tutorials/ai_services_agency ``` 2. **Install the dependencies**: ```bash pip install -r requirements.txt ``` 3. **Run the Streamlit app**: ```bash streamlit run ai_services_agency/agency.py ``` 4. **Enter your OpenAI API Key** in the sidebar when prompted and start analyzing your startup idea! ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_services_agency/agency.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/ai_services_agency/agency.py" from typing import List, Literal, Dict, Optional from agency_swarm import Agent, Agency, set_openai_key, BaseTool from pydantic import Field, BaseModel import streamlit as st class AnalyzeProjectRequirements(BaseTool): project_name: str = Field(..., description="Name of the project") project_description: str = Field(..., description="Project description and goals") project_type: Literal["Web Application", "Mobile App", "API Development", "Data Analytics", "AI/ML Solution", "Other"] = Field(..., description="Type of project") budget_range: Literal["$10k-$25k", "$25k-$50k", "$50k-$100k", "$100k+"] = Field(..., description="Budget range for the project") class ToolConfig: name = "analyze_project" description = "Analyzes project requirements and feasibility" one_call_at_a_time = True def run(self) -> str: """Analyzes project and stores results in shared state""" if self._shared_state.get("project_analysis", None) is not None: raise ValueError("Project analysis already exists. Please proceed with technical specification.") analysis = { "name": self.project_name, "type": self.project_type, "complexity": "high", "timeline": "6 months", "budget_feasibility": "within range", "requirements": ["Scalable architecture", "Security", "API integration"] } self._shared_state.set("project_analysis", analysis) return "Project analysis completed. Please proceed with technical specification." class CreateTechnicalSpecification(BaseTool): architecture_type: Literal["monolithic", "microservices", "serverless", "hybrid"] = Field( ..., description="Proposed architecture type" ) core_technologies: str = Field( ..., description="Comma-separated list of main technologies and frameworks" ) scalability_requirements: Literal["high", "medium", "low"] = Field( ..., description="Scalability needs" ) class ToolConfig: name = "create_technical_spec" description = "Creates technical specifications based on project analysis" one_call_at_a_time = True def run(self) -> str: """Creates technical specification based on analysis""" project_analysis = self._shared_state.get("project_analysis", None) if project_analysis is None: raise ValueError("Please analyze project requirements first using AnalyzeProjectRequirements tool.") spec = { "project_name": project_analysis["name"], "architecture": self.architecture_type, "technologies": self.core_technologies.split(","), "scalability": self.scalability_requirements } self._shared_state.set("technical_specification", spec) return f"Technical specification created for {project_analysis['name']}." def init_session_state() -> None: """Initialize session state variables""" if 'messages' not in st.session_state: st.session_state.messages = [] if 'api_key' not in st.session_state: st.session_state.api_key = None def main() -> None: st.set_page_config(page_title="AI Services Agency", layout="wide") init_session_state() st.title("🚀 AI Services Agency") # API Configuration with st.sidebar: st.header("🔑 API Configuration") openai_api_key = st.text_input( "OpenAI API Key", type="password", help="Enter your OpenAI API key to continue" ) if openai_api_key: st.session_state.api_key = openai_api_key st.success("API Key accepted!") else: st.warning("⚠️ Please enter your OpenAI API Key to proceed") st.markdown("[Get your API key here](https://platform.openai.com/api-keys)") return # Initialize agents with the provided API key set_openai_key(st.session_state.api_key) api_headers = {"Authorization": f"Bearer {st.session_state.api_key}"} # Project Input Form with st.form("project_form"): st.subheader("Project Details") project_name = st.text_input("Project Name") project_description = st.text_area( "Project Description", help="Describe the project, its goals, and any specific requirements" ) col1, col2 = st.columns(2) with col1: project_type = st.selectbox( "Project Type", ["Web Application", "Mobile App", "API Development", "Data Analytics", "AI/ML Solution", "Other"] ) timeline = st.selectbox( "Expected Timeline", ["1-2 months", "3-4 months", "5-6 months", "6+ months"] ) with col2: budget_range = st.selectbox( "Budget Range", ["$10k-$25k", "$25k-$50k", "$50k-$100k", "$100k+"] ) priority = st.selectbox( "Project Priority", ["High", "Medium", "Low"] ) tech_requirements = st.text_area( "Technical Requirements (optional)", help="Any specific technical requirements or preferences" ) special_considerations = st.text_area( "Special Considerations (optional)", help="Any additional information or special requirements" ) submitted = st.form_submit_button("Analyze Project") if submitted and project_name and project_description: try: # Set OpenAI key set_openai_key(st.session_state.api_key) # Create agents ceo = Agent( name="Project Director", description="You are a CEO of multiple companies in the past and have a lot of experience in evaluating projects and making strategic decisions.", instructions=""" You are an experienced CEO who evaluates projects. Follow these steps strictly: 1. FIRST, use the AnalyzeProjectRequirements tool with: - project_name: The name from the project details - project_description: The full project description - project_type: The type of project (Web Application, Mobile App, etc) - budget_range: The specified budget range 2. WAIT for the analysis to complete before proceeding. 3. Review the analysis results and provide strategic recommendations. """, tools=[AnalyzeProjectRequirements], api_headers=api_headers, temperature=0.7, max_prompt_tokens=25000 ) cto = Agent( name="Technical Architect", description="Senior technical architect with deep expertise in system design.", instructions=""" You are a technical architect. Follow these steps strictly: 1. WAIT for the project analysis to be completed by the CEO. 2. Use the CreateTechnicalSpecification tool with: - architecture_type: Choose from monolithic/microservices/serverless/hybrid - core_technologies: List main technologies as comma-separated values - scalability_requirements: Choose high/medium/low based on project needs 3. Review the technical specification and provide additional recommendations. """, tools=[CreateTechnicalSpecification], api_headers=api_headers, temperature=0.5, max_prompt_tokens=25000 ) product_manager = Agent( name="Product Manager", description="Experienced product manager focused on delivery excellence.", instructions=""" - Manage project scope and timeline giving the roadmap of the project - Define product requirements and you should give potential products and features that can be built for the startup """, api_headers=api_headers, temperature=0.4, max_prompt_tokens=25000 ) developer = Agent( name="Lead Developer", description="Senior developer with full-stack expertise.", instructions=""" - Plan technical implementation - Provide effort estimates - Review technical feasibility """, api_headers=api_headers, temperature=0.3, max_prompt_tokens=25000 ) client_manager = Agent( name="Client Success Manager", description="Experienced client manager focused on project delivery.", instructions=""" - Ensure client satisfaction - Manage expectations - Handle feedback """, api_headers=api_headers, temperature=0.6, max_prompt_tokens=25000 ) # Create agency agency = Agency( [ ceo, cto, product_manager, developer, client_manager, [ceo, cto], [ceo, product_manager], [ceo, developer], [ceo, client_manager], [cto, developer], [product_manager, developer], [product_manager, client_manager] ], async_mode='threading', shared_files='shared_files' ) # Prepare project info project_info = { "name": project_name, "description": project_description, "type": project_type, "timeline": timeline, "budget": budget_range, "priority": priority, "technical_requirements": tech_requirements, "special_considerations": special_considerations } st.session_state.messages.append({"role": "user", "content": str(project_info)}) # Create tabs and run analysis with st.spinner("AI Services Agency is analyzing your project..."): try: # Get analysis from each agent using agency.get_completion() ceo_response = agency.get_completion( message=f"""Analyze this project using the AnalyzeProjectRequirements tool: Project Name: {project_name} Project Description: {project_description} Project Type: {project_type} Budget Range: {budget_range} Use these exact values with the tool and wait for the analysis results.""", recipient_agent=ceo ) cto_response = agency.get_completion( message=f"""Review the project analysis and create technical specifications using the CreateTechnicalSpecification tool. Choose the most appropriate: - architecture_type (monolithic/microservices/serverless/hybrid) - core_technologies (comma-separated list) - scalability_requirements (high/medium/low) Base your choices on the project requirements and analysis.""", recipient_agent=cto ) pm_response = agency.get_completion( message=f"Analyze project management aspects: {str(project_info)}", recipient_agent=product_manager, additional_instructions="Focus on product-market fit and roadmap development, and coordinate with technical and marketing teams." ) developer_response = agency.get_completion( message=f"Analyze technical implementation based on CTO's specifications: {str(project_info)}", recipient_agent=developer, additional_instructions="Provide technical implementation details, optimal tech stack you would be using including the costs of cloud services (if any) and feasibility feedback, and coordinate with product manager and CTO to build the required products for the startup." ) client_response = agency.get_completion( message=f"Analyze client success aspects: {str(project_info)}", recipient_agent=client_manager, additional_instructions="Provide detailed go-to-market strategy and customer acquisition plan, and coordinate with product manager." ) # Create tabs for different analyses tabs = st.tabs([ "CEO's Project Analysis", "CTO's Technical Specification", "Product Manager's Plan", "Developer's Implementation", "Client Success Strategy" ]) with tabs[0]: st.markdown("## CEO's Strategic Analysis") st.markdown(ceo_response) st.session_state.messages.append({"role": "assistant", "content": ceo_response}) with tabs[1]: st.markdown("## CTO's Technical Specification") st.markdown(cto_response) st.session_state.messages.append({"role": "assistant", "content": cto_response}) with tabs[2]: st.markdown("## Product Manager's Plan") st.markdown(pm_response) st.session_state.messages.append({"role": "assistant", "content": pm_response}) with tabs[3]: st.markdown("## Lead Developer's Development Plan") st.markdown(developer_response) st.session_state.messages.append({"role": "assistant", "content": developer_response}) with tabs[4]: st.markdown("## Client Success Strategy") st.markdown(client_response) st.session_state.messages.append({"role": "assistant", "content": client_response}) except Exception as e: st.error(f"Error during analysis: {str(e)}") st.error("Please check your inputs and API key and try again.") except Exception as e: st.error(f"Error during analysis: {str(e)}") st.error("Please check your API key and try again.") # Add history management in sidebar with st.sidebar: st.subheader("Options") if st.checkbox("Show Analysis History"): for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) if st.button("Clear History"): st.session_state.messages = [] st.rerun() if __name__ == "__main__": main() ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_services_agency/requirements.txt python-dotenv==1.0.1 agency-swarm==0.4.1 streamlit ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_teaching_agent_team/README.md # 👨‍🏫 AI Teaching Agent Team A Streamlit application that brings together a team of specialized AI teaching agents who collaborate like a professional teaching faculty. Each agent acts as a specialized educator: a curriculum designer, learning path expert, resource librarian, and practice instructor - working together to create a complete educational experience through Google Docs. ## 🪄 Meet your AI Teaching Agent Team #### 🧠 Professor Agent - Creates fundamental knowledge base in Google Docs - Organizes content with proper headings and sections - Includes detailed explanations and examples - Output: Comprehensive knowledge base document with table of contents #### 🗺️ Academic Advisor Agent - Designs learning path in a structured Google Doc - Creates progressive milestone markers - Includes time estimates and prerequisites - Output: Visual roadmap document with clear progression paths #### 📚 Research Librarian Agent - Compiles resources in an organized Google Doc - Includes links to academic papers and tutorials - Adds descriptions and difficulty levels - Output: Categorized resource list with quality ratings #### ✍️ Teaching Assistant Agent - Develops exercises in an interactive Google Doc - Creates structured practice sections - Includes solution guides - Output: Complete practice workbook with answers ## How to Run 1. Clone the repository ```bash # Clone the repository git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd ai_agent_tutorials/ai_personal_learning_agent # Install dependencies pip install -r requirements.txt ``` ## Configuration - IMPORTANT STEP 1. Get your OpenAI API Key - Create an account on [OpenAI Platform](https://platform.openai.com/) - Navigate to API Keys section - Create a new API key 2. Get your Composio API Key - Create an account on [Composio Platform](https://composio.ai/) - **IMPORTANT** - For you to use the app, you need to make new connection ID with google docs and composio.Follow the below two steps to do so: - composio add googledocs (IN THE TERMINAL) - Create a new connection - Select OAUTH2 - Select Google Account and Done. - On the composio account website, go to apps, select google docs tool, and [click create integration](https://app.composio.dev/app/googledocs) (violet button) and click Try connecting default’s googldocs button and we are done. 3. Sign up and get the [SerpAPI Key](https://serpapi.com/) ## How to Use? 1. Start the Streamlit app ```bash streamlit run teaching_agent_team.py ``` 2. Use the application - Enter your OpenAI API key in the sidebar (if not set in environment) - Enter your Composio API key in the sidebar - Type a topic you want to learn about (e.g., "Python Programming", "Machine Learning") - Click "Generate Learning Plan" - Wait for the agents to generate your personalized learning plan - View the results and terminal output in the interface ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_teaching_agent_team/requirements.txt streamlit==1.41.1 openai==1.58.1 duckduckgo-search==6.4.1 typing-extensions>=4.5.0 agno composio-phidata==0.6.9 composio_core composio==0.1.1 google-search-results==2.4.2 ## /advanced_ai_agents/multi_agent_apps/agent_teams/ai_teaching_agent_team/teaching_agent_team.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/ai_teaching_agent_team/teaching_agent_team.py" import streamlit as st from agno.agent import Agent, RunResponse from agno.models.openai import OpenAIChat from composio_phidata import Action, ComposioToolSet import os from agno.tools.arxiv import ArxivTools from agno.utils.pprint import pprint_run_response from agno.tools.serpapi import SerpApiTools # Set page configuration st.set_page_config(page_title="👨‍🏫 AI Teaching Agent Team", layout="centered") # Initialize session state for API keys and topic if 'openai_api_key' not in st.session_state: st.session_state['openai_api_key'] = '' if 'composio_api_key' not in st.session_state: st.session_state['composio_api_key'] = '' if 'serpapi_api_key' not in st.session_state: st.session_state['serpapi_api_key'] = '' if 'topic' not in st.session_state: st.session_state['topic'] = '' # Streamlit sidebar for API keys with st.sidebar: st.title("API Keys Configuration") st.session_state['openai_api_key'] = st.text_input("Enter your OpenAI API Key", type="password").strip() st.session_state['composio_api_key'] = st.text_input("Enter your Composio API Key", type="password").strip() st.session_state['serpapi_api_key'] = st.text_input("Enter your SerpAPI Key", type="password").strip() # Add info about terminal responses st.info("Note: You can also view detailed agent responses\nin your terminal after execution.") # Validate API keys if not st.session_state['openai_api_key'] or not st.session_state['composio_api_key'] or not st.session_state['serpapi_api_key']: st.error("Please enter OpenAI, Composio, and SerpAPI keys in the sidebar.") st.stop() # Set the OpenAI API key and Composio API key from session state os.environ["OPENAI_API_KEY"] = st.session_state['openai_api_key'] try: composio_toolset = ComposioToolSet(api_key=st.session_state['composio_api_key']) google_docs_tool = composio_toolset.get_tools(actions=[Action.GOOGLEDOCS_CREATE_DOCUMENT])[0] google_docs_tool_update = composio_toolset.get_tools(actions=[Action.GOOGLEDOCS_UPDATE_EXISTING_DOCUMENT])[0] except Exception as e: st.error(f"Error initializing ComposioToolSet: {e}") st.stop() # Create the Professor agent (formerly KnowledgeBuilder) professor_agent = Agent( name="Professor", role="Research and Knowledge Specialist", model=OpenAIChat(id="gpt-4o-mini", api_key=st.session_state['openai_api_key']), tools=[google_docs_tool], instructions=[ "Create a comprehensive knowledge base that covers fundamental concepts, advanced topics, and current developments of the given topic.", "Exlain the topic from first principles first. Include key terminology, core principles, and practical applications and make it as a detailed report that anyone who's starting out can read and get maximum value out of it.", "Make sure it is formatted in a way that is easy to read and understand. DONT FORGET TO CREATE THE GOOGLE DOCUMENT.", "Open a new Google Doc and write down the response of the agent neatly with great formatting and structure in it. **Include the Google Doc link in your response.**", ], show_tool_calls=True, markdown=True, ) # Create the Academic Advisor agent (formerly RoadmapArchitect) academic_advisor_agent = Agent( name="Academic Advisor", role="Learning Path Designer", model=OpenAIChat(id="gpt-4o-mini", api_key=st.session_state['openai_api_key']), tools=[google_docs_tool], instructions=[ "Using the knowledge base for the given topic, create a detailed learning roadmap.", "Break down the topic into logical subtopics and arrange them in order of progression, a detailed report of roadmap that includes all the subtopics in order to be an expert in this topic.", "Include estimated time commitments for each section.", "Present the roadmap in a clear, structured format. DONT FORGET TO CREATE THE GOOGLE DOCUMENT.", "Open a new Google Doc and write down the response of the agent neatly with great formatting and structure in it. **Include the Google Doc link in your response.**", ], show_tool_calls=True, markdown=True ) # Create the Research Librarian agent (formerly ResourceCurator) research_librarian_agent = Agent( name="Research Librarian", role="Learning Resource Specialist", model=OpenAIChat(id="gpt-4o-mini", api_key=st.session_state['openai_api_key']), tools=[google_docs_tool, SerpApiTools(api_key=st.session_state['serpapi_api_key']) ], instructions=[ "Make a list of high-quality learning resources for the given topic.", "Use the SerpApi search tool to find current and relevant learning materials.", "Using SerpApi search tool, Include technical blogs, GitHub repositories, official documentation, video tutorials, and courses.", "Present the resources in a curated list with descriptions and quality assessments. DONT FORGET TO CREATE THE GOOGLE DOCUMENT.", "Open a new Google Doc and write down the response of the agent neatly with great formatting and structure in it. **Include the Google Doc link in your response.**", ], show_tool_calls=True, markdown=True, ) # Create the Teaching Assistant agent (formerly PracticeDesigner) teaching_assistant_agent = Agent( name="Teaching Assistant", role="Exercise Creator", model=OpenAIChat(id="gpt-4o-mini", api_key=st.session_state['openai_api_key']), tools=[google_docs_tool, SerpApiTools(api_key=st.session_state['serpapi_api_key'])], instructions=[ "Create comprehensive practice materials for the given topic.", "Use the SerpApi search tool to find example problems and real-world applications.", "Include progressive exercises, quizzes, hands-on projects, and real-world application scenarios.", "Ensure the materials align with the roadmap progression.", "Provide detailed solutions and explanations for all practice materials.DONT FORGET TO CREATE THE GOOGLE DOCUMENT.", "Open a new Google Doc and write down the response of the agent neatly with great formatting and structure in it. **Include the Google Doc link in your response.**", ], show_tool_calls=True, markdown=True, ) # Streamlit main UI st.title("👨‍🏫 AI Teaching Agent Team") st.markdown("Enter a topic to generate a detailed learning path and resources") # Add info message about Google Docs st.info("📝 The agents will create detailed Google Docs for each section (Professor, Academic Advisor, Research Librarian, and Teaching Assistant). The links to these documents will be displayed below after processing.") # Query bar for topic input st.session_state['topic'] = st.text_input("Enter the topic you want to learn about:", placeholder="e.g., Machine Learning, LoRA, etc.") # Start button if st.button("Start"): if not st.session_state['topic']: st.error("Please enter a topic.") else: # Display loading animations while generating responses with st.spinner("Generating Knowledge Base..."): professor_response: RunResponse = professor_agent.run( f"the topic is: {st.session_state['topic']},Don't forget to add the Google Doc link in your response.", stream=False ) with st.spinner("Generating Learning Roadmap..."): academic_advisor_response: RunResponse = academic_advisor_agent.run( f"the topic is: {st.session_state['topic']},Don't forget to add the Google Doc link in your response.", stream=False ) with st.spinner("Curating Learning Resources..."): research_librarian_response: RunResponse = research_librarian_agent.run( f"the topic is: {st.session_state['topic']},Don't forget to add the Google Doc link in your response.", stream=False ) with st.spinner("Creating Practice Materials..."): teaching_assistant_response: RunResponse = teaching_assistant_agent.run( f"the topic is: {st.session_state['topic']},Don't forget to add the Google Doc link in your response.", stream=False ) # Extract Google Doc links from the responses def extract_google_doc_link(response_content): # Assuming the Google Doc link is embedded in the response content # You may need to adjust this logic based on the actual response format if "https://docs.google.com" in response_content: return response_content.split("https://docs.google.com")[1].split()[0] return None professor_doc_link = extract_google_doc_link(professor_response.content) academic_advisor_doc_link = extract_google_doc_link(academic_advisor_response.content) research_librarian_doc_link = extract_google_doc_link(research_librarian_response.content) teaching_assistant_doc_link = extract_google_doc_link(teaching_assistant_response.content) # Display Google Doc links at the top of the Streamlit UI st.markdown("### Google Doc Links:") if professor_doc_link: st.markdown(f"- **Professor Document:** [View Document](https://docs.google.com{professor_doc_link})") if academic_advisor_doc_link: st.markdown(f"- **Academic Advisor Document:** [View Document](https://docs.google.com{academic_advisor_doc_link})") if research_librarian_doc_link: st.markdown(f"- **Research Librarian Document:** [View Document](https://docs.google.com{research_librarian_doc_link})") if teaching_assistant_doc_link: st.markdown(f"- **Teaching Assistant Document:** [View Document](https://docs.google.com{teaching_assistant_doc_link})") # Display responses in the Streamlit UI using pprint_run_response st.markdown("### Professor Response:") st.markdown(professor_response.content) pprint_run_response(professor_response, markdown=True) st.divider() st.markdown("### Academic Advisor Response:") st.markdown(academic_advisor_response.content) pprint_run_response(academic_advisor_response, markdown=True) st.divider() st.markdown("### Research Librarian Response:") st.markdown(research_librarian_response.content) pprint_run_response(research_librarian_response, markdown=True) st.divider() st.markdown("### Teaching Assistant Response:") st.markdown(teaching_assistant_response.content) pprint_run_response(teaching_assistant_response, markdown=True) st.divider() # Information about the agents st.markdown("---") st.markdown("### About the Agents:") st.markdown(""" - **Professor**: Researches the topic and creates a detailed knowledge base. - **Academic Advisor**: Designs a structured learning roadmap for the topic. - **Research Librarian**: Curates high-quality learning resources. - **Teaching Assistant**: Creates practice materials, exercises, and projects. """) ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_coding_agent_team/README.md # 💻 Multimodal AI Coding Agent Team with o3-mini and Gemini An AI Powered Streamlit application that serves as your personal coding assistant, powered by multiple Agents built on the new o3-mini model. You can also upload an image of a coding problem or describe it in text, and the AI agent will analyze, generate an optimal solution, and execute it in a sandbox environment. ## Features #### Multi-Modal Problem Input - Upload images of coding problems (supports PNG, JPG, JPEG) - Type problems in natural language - Automatic problem extraction from images - Interactive problem processing #### Intelligent Code Generation - Optimal solution generation with best time/space complexity - Clean, documented Python code output - Type hints and proper documentation - Edge case handling #### Secure Code Execution - Sandboxed code execution environment - Real-time execution results - Error handling and explanations - 30-second execution timeout protection #### Multi-Agent Architecture - Vision Agent (Gemini-2.0-flash) for image processing - Coding Agent (OpenAI- o3-mini) for solution generation - Execution Agent (OpenAI) for code running and result analysis - E2B Sandbox for secure code execution ## How to Run Follow the steps below to set up and run the application: - Get an OpenAI API key from: https://platform.openai.com/ - Get a Google (Gemini) API key from: https://makersuite.google.com/app/apikey - Get an E2B API key from: https://e2b.dev/docs/getting-started/api-key 1. **Clone the Repository** ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd ai_agent_tutorials/ai_coding_agent_o3-mini ``` 2. **Install the dependencies** ```bash pip install -r requirements.txt ``` 3. **Run the Streamlit app** ```bash streamlit run ai_coding_agent_o3.py ``` 4. **Configure API Keys** - Enter your API keys in the sidebar - All three keys (OpenAI, Gemini, E2B) are required for full functionality ## Usage 1. Upload an image of a coding problem OR type your problem description 2. Click "Generate & Execute Solution" 3. View the generated solution with full documentation 4. See execution results and any generated files 5. Review any error messages or execution timeouts ## /advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_coding_agent_team/ai_coding_agent_o3.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_coding_agent_team/ai_coding_agent_o3.py" from typing import Optional, Dict, Any import streamlit as st from agno.agent import Agent, RunResponse from agno.models.openai import OpenAIChat from agno.models.google import Gemini from e2b_code_interpreter import Sandbox import os from PIL import Image from io import BytesIO import base64 def initialize_session_state() -> None: if 'openai_key' not in st.session_state: st.session_state.openai_key = '' if 'gemini_key' not in st.session_state: st.session_state.gemini_key = '' if 'e2b_key' not in st.session_state: st.session_state.e2b_key = '' if 'sandbox' not in st.session_state: st.session_state.sandbox = None def setup_sidebar() -> None: with st.sidebar: st.title("API Configuration") st.session_state.openai_key = st.text_input("OpenAI API Key", value=st.session_state.openai_key, type="password") st.session_state.gemini_key = st.text_input("Gemini API Key", value=st.session_state.gemini_key, type="password") st.session_state.e2b_key = st.text_input("E2B API Key", value=st.session_state.e2b_key, type="password") def create_agents() -> tuple[Agent, Agent, Agent]: vision_agent = Agent( model=Gemini(id="gemini-2.0-flash", api_key=st.session_state.gemini_key), markdown=True, ) coding_agent = Agent( model=OpenAIChat( id="o3-mini", api_key=st.session_state.openai_key, system_prompt="""You are an expert Python programmer. You will receive coding problems similar to LeetCode questions, which may include problem statements, sample inputs, and examples. Your task is to: 1. Analyze the problem carefully and Optimally with best possible time and space complexities. 2. Write clean, efficient Python code to solve it 3. Include proper documentation and type hints 4. The code will be executed in an e2b sandbox environment Please ensure your code is complete and handles edge cases appropriately.""" ), markdown=True ) execution_agent = Agent( model=OpenAIChat( id="o3-mini", api_key=st.session_state.openai_key, system_prompt="""You are an expert at executing Python code in sandbox environments. Your task is to: 1. Take the provided Python code 2. Execute it in the e2b sandbox 3. Format and explain the results clearly 4. Handle any execution errors gracefully Always ensure proper error handling and clear output formatting.""" ), markdown=True ) return vision_agent, coding_agent, execution_agent def initialize_sandbox() -> None: try: if st.session_state.sandbox: try: st.session_state.sandbox.close() except: pass os.environ['E2B_API_KEY'] = st.session_state.e2b_key # Initialize sandbox with 60 second timeout st.session_state.sandbox = Sandbox(timeout=60) except Exception as e: st.error(f"Failed to initialize sandbox: {str(e)}") st.session_state.sandbox = None def run_code_in_sandbox(code: str) -> Dict[str, Any]: if not st.session_state.sandbox: initialize_sandbox() execution = st.session_state.sandbox.run_code(code) return { "logs": execution.logs, "files": st.session_state.sandbox.files.list("/") } def process_image_with_gemini(vision_agent: Agent, image: Image) -> str: prompt = """Analyze this image and extract any coding problem or code snippet shown. Describe it in clear natural language, including any: 1. Problem statement 2. Input/output examples 3. Constraints or requirements Format it as a proper coding problem description.""" # Save image to a temporary file temp_path = "temp_image.png" try: # Convert to RGB if needed if image.mode != 'RGB': image = image.convert('RGB') image.save(temp_path, format="PNG") # Read the file and create image data with open(temp_path, 'rb') as img_file: img_bytes = img_file.read() # Pass image to Gemini response = vision_agent.run( prompt, images=[{"filepath": temp_path}] # Use filepath instead of content ) return response.content except Exception as e: st.error(f"Error processing image: {str(e)}") return "Failed to process the image. Please try again or use text input instead." finally: # Clean up temporary file if os.path.exists(temp_path): os.remove(temp_path) def execute_code_with_agent(execution_agent: Agent, code: str, sandbox: Sandbox) -> str: try: # Set timeout to 30 seconds for code execution sandbox.set_timeout(30) execution = sandbox.run_code(code) # Handle execution errors if execution.error: if "TimeoutException" in str(execution.error): return "⚠️ Execution Timeout: The code took too long to execute (>30 seconds). Please optimize your solution or try a smaller input." error_prompt = f"""The code execution resulted in an error: Error: {execution.error} Please analyze the error and provide a clear explanation of what went wrong.""" response = execution_agent.run(error_prompt) return f"⚠️ Execution Error:\n{response.content}" # Get files list safely try: files = sandbox.files.list("/") except: files = [] prompt = f"""Here is the code execution result: Logs: {execution.logs} Files: {str(files)} Please provide a clear explanation of the results and any outputs.""" response = execution_agent.run(prompt) return response.content except Exception as e: # Reinitialize sandbox on error try: initialize_sandbox() except: pass return f"⚠️ Sandbox Error: {str(e)}" def main() -> None: st.title("O3-Mini Coding Agent") # Add timeout info in sidebar initialize_session_state() setup_sidebar() with st.sidebar: st.info("⏱️ Code execution timeout: 30 seconds") # Check all required API keys if not (st.session_state.openai_key and st.session_state.gemini_key and st.session_state.e2b_key): st.warning("Please enter all required API keys in the sidebar.") return vision_agent, coding_agent, execution_agent = create_agents() # Clean, single-column layout uploaded_image = st.file_uploader( "Upload an image of your coding problem (optional)", type=['png', 'jpg', 'jpeg'] ) if uploaded_image: st.image(uploaded_image, caption="Uploaded Image", use_container_width=True) user_query = st.text_area( "Or type your coding problem here:", placeholder="Example: Write a function to find the sum of two numbers. Include sample input/output cases.", height=100 ) # Process button if st.button("Generate & Execute Solution", type="primary"): if uploaded_image and not user_query: # Process image with Gemini with st.spinner("Processing image..."): try: # Save uploaded file to temporary location image = Image.open(uploaded_image) extracted_query = process_image_with_gemini(vision_agent, image) if extracted_query.startswith("Failed to process"): st.error(extracted_query) return st.info("📝 Extracted Problem:") st.write(extracted_query) # Pass extracted query to coding agent with st.spinner("Generating solution..."): response = coding_agent.run(extracted_query) except Exception as e: st.error(f"Error processing image: {str(e)}") return elif user_query and not uploaded_image: # Direct text input processing with st.spinner("Generating solution..."): response = coding_agent.run(user_query) elif user_query and uploaded_image: st.error("Please use either image upload OR text input, not both.") return else: st.warning("Please provide either an image or text description of your coding problem.") return # Display and execute solution if 'response' in locals(): st.divider() st.subheader("💻 Solution") # Extract code from markdown response code_blocks = response.content.split("\`\`\`python") if len(code_blocks) > 1: code = code_blocks[1].split("\`\`\`")[0].strip() # Display the code st.code(code, language="python") # Execute code with execution agent with st.spinner("Executing code..."): # Always initialize a fresh sandbox for each execution initialize_sandbox() if st.session_state.sandbox: execution_results = execute_code_with_agent( execution_agent, code, st.session_state.sandbox ) # Display execution results st.divider() st.subheader("🚀 Execution Results") st.markdown(execution_results) # Try to display files if available try: files = st.session_state.sandbox.files.list("/") if files: st.markdown("📁 **Generated Files:**") st.json(files) except: pass if __name__ == "__main__": main() ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_coding_agent_team/requirements.txt streamlit e2b-code-interpreter agno Pillow ## /advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_design_agent_team/README.md # Multimodal AI Design Agent Team A Streamlit application that provides comprehensive design analysis using a team of specialized AI agents powered by Google's Gemini model. This application leverages multiple specialized AI agents to provide comprehensive analysis of UI/UX designs of your product and your competitors, combining visual understanding, user experience evaluation, and market research insights. ## Features - **Specialized Legal AI Agent Team** - 🎨 **Visual Design Agent**: Evaluates design elements, patterns, color schemes, typography, and visual hierarchy - 🔄 **UX Analysis Agent**: Assesses user flows, interaction patterns, usability, and accessibility - 📊 **Market Analysis Agent**: Provides market insights, competitor analysis, and positioning recommendations - **Multiple Analysis Types**: Choose from Visual Design, UX, and Market Analysis - **Comparative Analysis**: Upload competitor designs for comparative insights - **Customizable Focus Areas**: Select specific aspects for detailed analysis - **Context-Aware**: Provide additional context for more relevant insights - **Real-time Processing**: Get instant analysis with progress indicators - **Structured Output**: Receive well-organized, actionable insights ## How to Run 1. **Setup Environment** ```bash # Clone the repository git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd awesome-llm-apps/ai_agent_tutorials/multimodal_design_agent_team # Create and activate virtual environment (optional) python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate # Install dependencies pip install -r requirements.txt ``` 2. **Get API Key** - Visit [Google AI Studio](https://aistudio.google.com/apikey) - Generate an API key 3. **Run the Application** ```bash streamlit run design_agent_team.py ``` 4. **Use the Application** - Enter your Gemini API key in the sidebar - Upload design files (supported formats: JPG, JPEG, PNG) - Select analysis types and focus areas - Add context if needed - Click "Run Analysis" to get insights ## Technical Stack - **Frontend**: Streamlit - **AI Model**: Google Gemini 2.0 - **Image Processing**: Pillow - **Market Research**: DuckDuckGo Search API - **Framework**: Phidata for agent orchestration ## Tips for Best Results - Upload clear, high-resolution images - Include multiple views/screens for better context - Add competitor designs for comparative analysis - Provide specific context about your target audience ## /advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_design_agent_team/design_agent_team.py ```py path="/advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_design_agent_team/design_agent_team.py" from agno.agent import Agent from agno.models.google import Gemini from agno.media import Image as AgnoImage from agno.tools.duckduckgo import DuckDuckGoTools import streamlit as st from typing import List, Optional import logging from pathlib import Path import tempfile import os # Configure logging for errors only logging.basicConfig(level=logging.ERROR) logger = logging.getLogger(__name__) def initialize_agents(api_key: str) -> tuple[Agent, Agent, Agent]: try: model = Gemini(id="gemini-2.0-flash-exp", api_key=api_key) vision_agent = Agent( model=model, instructions=[ "You are a visual analysis expert that:", "1. Identifies design elements, patterns, and visual hierarchy", "2. Analyzes color schemes, typography, and layouts", "3. Detects UI components and their relationships", "4. Evaluates visual consistency and branding", "Be specific and technical in your analysis" ], markdown=True ) ux_agent = Agent( model=model, instructions=[ "You are a UX analysis expert that:", "1. Evaluates user flows and interaction patterns", "2. Identifies usability issues and opportunities", "3. Suggests UX improvements based on best practices", "4. Analyzes accessibility and inclusive design", "Focus on user-centric insights and practical improvements" ], markdown=True ) market_agent = Agent( model=model, tools=[DuckDuckGoTools()], instructions=[ "You are a market research expert that:", "1. Identifies market trends and competitor patterns", "2. Analyzes similar products and features", "3. Suggests market positioning and opportunities", "4. Provides industry-specific insights", "Focus on actionable market intelligence" ], markdown=True ) return vision_agent, ux_agent, market_agent except Exception as e: st.error(f"Error initializing agents: {str(e)}") return None, None, None # Set page config and UI elements st.set_page_config(page_title="Multimodal AI Design Agent Team", layout="wide") # Sidebar for API key input with st.sidebar: st.header("🔑 API Configuration") if "api_key_input" not in st.session_state: st.session_state.api_key_input = "" api_key = st.text_input( "Enter your Gemini API Key", value=st.session_state.api_key_input, type="password", help="Get your API key from Google AI Studio", key="api_key_widget" ) if api_key != st.session_state.api_key_input: st.session_state.api_key_input = api_key if api_key: st.success("API Key provided! ✅") else: st.warning("Please enter your API key to proceed") st.markdown(""" To get your API key: 1. Go to [Google AI Studio](https://makersuite.google.com/app/apikey) 2. Enable the Generative Language API in your [Google Cloud Console](https://console.developers.google.com/apis/api/generativelanguage.googleapis.com) """) st.title("Multimodal AI Design Agent Team") if st.session_state.api_key_input: vision_agent, ux_agent, market_agent = initialize_agents(st.session_state.api_key_input) if all([vision_agent, ux_agent, market_agent]): # File Upload Section st.header("📤 Upload Content") col1, space, col2 = st.columns([1, 0.1, 1]) with col1: design_files = st.file_uploader( "Upload UI/UX Designs", type=["jpg", "jpeg", "png"], accept_multiple_files=True, key="designs" ) if design_files: for file in design_files: st.image(file, caption=file.name, use_container_width=True) with col2: competitor_files = st.file_uploader( "Upload Competitor Designs (Optional)", type=["jpg", "jpeg", "png"], accept_multiple_files=True, key="competitors" ) if competitor_files: for file in competitor_files: st.image(file, caption=f"Competitor: {file.name}", use_container_width=True) # Analysis Configuration st.header("🎯 Analysis Configuration") analysis_types = st.multiselect( "Select Analysis Types", ["Visual Design", "User Experience", "Market Analysis"], default=["Visual Design"] ) specific_elements = st.multiselect( "Focus Areas", ["Color Scheme", "Typography", "Layout", "Navigation", "Interactions", "Accessibility", "Branding", "Market Fit"] ) context = st.text_area( "Additional Context", placeholder="Describe your product, target audience, or specific concerns..." ) # Analysis Process if st.button("🚀 Run Analysis", type="primary"): if design_files: try: st.header("📊 Analysis Results") def process_images(files): processed_images = [] for file in files: try: temp_dir = tempfile.gettempdir() temp_path = os.path.join(temp_dir, f"temp_{file.name}") with open(temp_path, "wb") as f: f.write(file.getvalue()) agno_image = AgnoImage(filepath=Path(temp_path)) processed_images.append(agno_image) except Exception as e: logger.error(f"Error processing image {file.name}: {str(e)}") continue return processed_images design_images = process_images(design_files) competitor_images = process_images(competitor_files) if competitor_files else [] all_images = design_images + competitor_images # Visual Design Analysis if "Visual Design" in analysis_types and design_files: with st.spinner("🎨 Analyzing visual design..."): if all_images: vision_prompt = f""" Analyze these designs focusing on: {', '.join(specific_elements)} Additional context: {context} Provide specific insights about visual design elements. Please format your response with clear headers and bullet points. Focus on concrete observations and actionable insights. """ response = vision_agent.run( message=vision_prompt, images=all_images ) st.subheader("🎨 Visual Design Analysis") st.markdown(response.content) # UX Analysis if "User Experience" in analysis_types: with st.spinner("🔄 Analyzing user experience..."): if all_images: ux_prompt = f""" Evaluate the user experience considering: {', '.join(specific_elements)} Additional context: {context} Focus on user flows, interactions, and accessibility. Please format your response with clear headers and bullet points. Focus on concrete observations and actionable improvements. """ response = ux_agent.run( message=ux_prompt, images=all_images ) st.subheader("🔄 UX Analysis") st.markdown(response.content) # Market Analysis if "Market Analysis" in analysis_types: with st.spinner("📊 Conducting market analysis..."): market_prompt = f""" Analyze market positioning and trends based on these designs. Context: {context} Compare with competitor designs if provided. Suggest market opportunities and positioning. Please format your response with clear headers and bullet points. Focus on concrete market insights and actionable recommendations. """ response = market_agent.run( message=market_prompt, images=all_images ) st.subheader("📊 Market Analysis") st.markdown(response.content) except Exception as e: logger.error(f"Error during analysis: {str(e)}") st.error("An error occurred during analysis. Please check the logs for details.") else: st.warning("Please upload at least one design to analyze.") else: st.info("👈 Please enter your API key in the sidebar to get started") else: st.info("👈 Please enter your API key in the sidebar to get started") # Footer with usage tips st.markdown("---") st.markdown("""

Tips for Best Results

• Upload clear, high-resolution images
• Include multiple views/screens for better context
• Add competitor designs for comparative analysis
• Provide specific context about your target audience

""", unsafe_allow_html=True) ``` ## /advanced_ai_agents/multi_agent_apps/agent_teams/multimodal_design_agent_team/requirements.txt google-generativeai==0.8.3 streamlit==1.41.1 agno Pillow==11.0.0 duckduckgo-search==6.3.7 ## /advanced_ai_agents/multi_agent_apps/ai_aqi_analysis_agent/README.md # 🌍 AQI Analysis Agent The AQI Analysis Agent is a powerful air quality monitoring and health recommendation tool powered by Firecrawl and Agno's AI Agent framework. This app helps users make informed decisions about outdoor activities by analyzing real-time air quality data and providing personalized health recommendations. ## Features - **Multi-Agent System** - **AQI Analyzer**: Fetches and processes real-time air quality data - **Health Recommendation Agent**: Generates personalized health advice - **Air Quality Metrics**: - Overall Air Quality Index (AQI) - Particulate Matter (PM2.5 and PM10) - Carbon Monoxide (CO) levels - Temperature - Humidity - Wind Speed - **Comprehensive Analysis**: - Real-time data visualization - Health impact assessment - Activity safety recommendations - Best time suggestions for outdoor activities - Weather condition correlations - **Interactive Features**: - Location-based analysis - Medical condition considerations - Activity-specific recommendations - Downloadable reports - Example queries for quick testing ## How to Run Follow these steps to set up and run the application: 1. **Clone the Repository**: ```bash git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git cd ai_agent_tutorials/ai_aqi_analysis_agent ``` 2. **Install the dependencies**: ```bash pip install -r requirements.txt ``` 3. **Set up your API keys**: - Get an OpenAI API key from: https://platform.openai.com/api-keys - Get a Firecrawl API key from: [Firecrawl website](https://www.firecrawl.dev/app/api-keys) 4. **Run the Gradio app**: ```bash python ai_aqi_analysis_agent.py ``` 5. **Access the Web Interface**: - The terminal will display two URLs: - Local URL: `http://127.0.0.1:7860` (for local access) - Public URL: `https://xxx-xxx-xxx.gradio.live` (for temporary public access) - Click on either URL to open the web interface in your browser ## Usage 1. Enter your API keys in the API Configuration section 2. Input location details: - City name - State (optional for Union Territories/US cities) - Country 3. Provide personal information: - Medical conditions (optional) - Planned outdoor activity 4. Click "Analyze & Get Recommendations" to receive: - Current air quality data - Health impact analysis - Activity safety recommendations 5. Try the example queries for quick testing ## Note The air quality data is fetched using Firecrawl's web scraping capabilities. Due to caching and rate limiting, the data might not always match real-time values on the website. For the most accurate real-time data, consider checking the source website directly. The content has been capped at 50000 tokens, and files over NaN bytes have been omitted. The user could consider applying other filters to refine the result. The better and more specific the context, the better the LLM can follow instructions. If the context seems verbose, the user can refine the filter using uithub. Thank you for using https://uithub.com - Perfect LLM context for any GitHub repo.