```
├── .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
# 🌟 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.
## 🤔 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! 🙏
[](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.