Merge branch 'Shubhamsaboo:main' into main
This commit is contained in:
commit
51836ad0fc
212 changed files with 14792 additions and 453 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
147
README.md
147
README.md
|
|
@ -1,6 +1,6 @@
|
|||
<p align="center">
|
||||
<a href="http://www.theunwindai.com">
|
||||
<img src="docs/banner/unwind.png" width="600px" alt="Unwind AI">
|
||||
<img src="docs/banner/unwind_black.png" width="900px" alt="Unwind AI">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
|
|
@ -16,89 +16,122 @@
|
|||
<hr/>
|
||||
|
||||
# 🌟 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 even open-source models like LLaMA that you can run locally on your computer.
|
||||
|
||||
<a href="https://trendshift.io/repositories/9876" target="_blank"><img src="https://trendshift.io/api/badge/repositories/9876" alt="Shubhamsaboo%2Fawesome-llm-apps | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
||||
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.
|
||||
|
||||
## 📑 Table of Contents
|
||||
|
||||
- [🤔 Why Awesome LLM Apps?](#-why-awesome-llm-apps)
|
||||
- [📂 Featured Projects](#-featured-projects)
|
||||
- **AI Agents**
|
||||
- [💼 AI Customer Support Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_customer_support_agent)
|
||||
- [📈 AI Investment Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_investment_agent)
|
||||
- [🗞️ AI Journalist Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_journalist_agent)
|
||||
- [📊 AI Finance Agent Team](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_finance_agent_team)
|
||||
- [💰 AI Personal Finance Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_personal_finance_agent)
|
||||
- [🛫 AI Travel Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_travel_agent)
|
||||
- [🎬 AI Movie Production Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_movie_production_agent)
|
||||
- [📰 Multi-Agent AI Researcher](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/multi_agent_researcher)
|
||||
- [📑 AI Meeting Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_meeting_agent)
|
||||
- [🌐 Local News Agent OpenAI Swarm](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/local_news_agent_openai_swarm)
|
||||
- **RAG (Retrieval Augmented Generation)**
|
||||
- [🔍 Autonomous RAG](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/autonomous_rag)
|
||||
- [🔗 Agentic RAG](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/agentic_rag)
|
||||
- [🔄 Llama3.1 Local RAG](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/llama3.1_local_rag)
|
||||
- [🧩 RAG-as-a-Service](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/rag-as-a-service)
|
||||
- **LLM Apps with Memory**
|
||||
- [💾 AI Arxiv Agent with Memory](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_apps_with_memory_tutorials/ai_arxiv_agent_memory)
|
||||
- [📝 LLM App with Personalized Memory](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_apps_with_memory_tutorials/llm_app_personalized_memory)
|
||||
- [🛩️ AI Travel Agent with Memory](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_apps_with_memory_tutorials/ai_travel_agent_memory)
|
||||
- [🗄️ Local ChatGPT with Memory](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_apps_with_memory_tutorials/local_chatgpt_with_memory)
|
||||
- **Chat with X**
|
||||
- [💬 Chat with GitHub Repo](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_github)
|
||||
- [📨 Chat with Gmail](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_gmail)
|
||||
- [📄 Chat with PDF](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_pdf)
|
||||
- [📚 Chat with Research Papers](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_research_papers)
|
||||
- [📝 Chat with Substack Newsletter](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_substack)
|
||||
- [📽️ Chat with YouTube Videos](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_youtube_videos)
|
||||
- **LLM Finetuning**
|
||||
- [🌐 Llama3.2 Finetuning](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_finetuning_tutorials/llama3.2_finetuning)
|
||||
- **Advanced Tools and Frameworks**
|
||||
- [🧪 Gemini Multimodal Chatbot](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/gemini_multimodal_chatbot)
|
||||
- [🔄 Mixture of Agents](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/mixture_of_agents)
|
||||
- [🌐 MultiLLM Chat Playground](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/multillm_chat_playground)
|
||||
- [🔗 LLM Router App](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/llm_router_app)
|
||||
- [💬 Local ChatGPT Clone](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/local_chatgpt_clone)
|
||||
- [🌍 Web Scraping AI Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/web_scrapping_ai_agent)
|
||||
- [🔍 Web Search AI Assistant](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/web_search_ai_assistant)
|
||||
- [🧪 Cursor AI Experiments](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/cursor_ai_experiments)
|
||||
|
||||
- [🚀 Getting Started](#-getting-started)
|
||||
- [🤝 Contributing to Opensource](#-contributing-to-opensource)
|
||||
<p align="center">
|
||||
<a href="https://trendshift.io/repositories/9876" target="_blank">
|
||||
<img src="https://trendshift.io/api/badge/repositories/9876" alt="Shubhamsaboo%2Fawesome-llm-apps | Trendshift" style="width: 250px; height: 55px;" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## 🤔 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.
|
||||
|
||||
## 📂 Featured AI Projects
|
||||
|
||||
### AI Agents
|
||||
- [💼 AI Customer Support Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_customer_support_agent)
|
||||
- [📈 AI Investment Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_investment_agent)
|
||||
- [👨⚖️ AI Legal Agent Team](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_legal_agent_team)
|
||||
- [💼 AI Recruitment Agent Team](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_recruitment_agent_team)
|
||||
- [👨💼 AI Services Agency](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_services_agency)
|
||||
- [🧲 AI Competitor Intelligence Agent Team](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_competitor_intelligence_agent_team)
|
||||
- [🏋️♂️ AI Health & Fitness Planner Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_health_fitness_agent)
|
||||
- [📈 AI Startup Trend Analysis Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_startup_trend_analysis_agent)
|
||||
- [🗞️ AI Journalist Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_journalist_agent)
|
||||
- [💲 AI Finance Agent Team](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_finance_agent_team)
|
||||
- [🧲 AI Competitor Intelligence Agent Team](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_competitor_intelligence_agent_team)
|
||||
- [🎯 AI Lead Generation Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_lead_generation_agent)
|
||||
- [💰 AI Personal Finance Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_personal_finance_agent)
|
||||
- [🩻 AI Medical Scan Diagnosis Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_medical_imaging_agent)
|
||||
- [👨🏫 AI Teaching Agent Team](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_teaching_agent_team)
|
||||
- [🛫 AI Travel Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_travel_agent)
|
||||
- [🎬 AI Movie Production Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_movie_production_agent)
|
||||
- [📰 Multi-Agent AI Researcher](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/multi_agent_researcher)
|
||||
- [💻 Multimodal AI Coding Agent Team with o3-mini and Gemini](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_coding_agent_o3-mini)
|
||||
- [📑 AI Meeting Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_meeting_agent)
|
||||
- [♜ AI Chess Agent Game](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_chess_agent)
|
||||
- [🏠 AI Real Estate Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_real_estate_agent)
|
||||
- [🌐 Local News Agent OpenAI Swarm](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/local_news_agent_openai_swarm)
|
||||
- [📊 AI Finance Agent with xAI Grok](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/xai_finance_agent)
|
||||
- [🎮 AI 3D PyGame Visualizer with DeepSeek R1](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_3dpygame_r1)
|
||||
- [🧠 AI Reasoning Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/ai_reasoning_agent)
|
||||
- [🧬 Multimodal AI Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/ai_agent_tutorials/multimodal_ai_agent)
|
||||
|
||||
### RAG (Retrieval Augmented Generation)
|
||||
- [🔍 Autonomous RAG](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/autonomous_rag)
|
||||
- [🔗 Agentic RAG](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/agentic_rag)
|
||||
- [🤔 Agentic RAG with Gemini Flash Thinking](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/gemini_agentic_rag)
|
||||
- [🐋 Deepseek Local RAG Reasoning Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/deepseek_local_rag_agent)
|
||||
- [🔄 Llama3.1 Local RAG](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/llama3.1_local_rag)
|
||||
- [🧩 RAG-as-a-Service](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/rag-as-a-service)
|
||||
- [🦙 Local RAG Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/local_rag_agent)
|
||||
- [👀 RAG App with Hybrid Search](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/hybrid_search_rag)
|
||||
- [🖥️ Local RAG App with Hybrid Search](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/local_hybrid_search_rag)
|
||||
- [📠 RAG Agent with Database Routing](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/rag_database_routing)
|
||||
- [🔄 Corrective RAG Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/rag_tutorials/corrective_rag)
|
||||
|
||||
### MCP AI Agents
|
||||
- [🐙 MCP GitHub Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/mcp_ai_agents/github_mcp_agent)
|
||||
|
||||
### LLM Apps with Memory
|
||||
- [💾 AI Arxiv Agent with Memory](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_apps_with_memory_tutorials/ai_arxiv_agent_memory)
|
||||
- [📝 LLM App with Personalized Memory](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_apps_with_memory_tutorials/llm_app_personalized_memory)
|
||||
- [🛩️ AI Travel Agent with Memory](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_apps_with_memory_tutorials/ai_travel_agent_memory)
|
||||
- [🗄️ Local ChatGPT with Memory](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_apps_with_memory_tutorials/local_chatgpt_with_memory)
|
||||
|
||||
### Chat with X
|
||||
- [💬 Chat with GitHub Repo](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_github)
|
||||
- [📨 Chat with Gmail](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_gmail)
|
||||
- [📄 Chat with PDF](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_pdf)
|
||||
- [📚 Chat with Research Papers](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_research_papers)
|
||||
- [📝 Chat with Substack Newsletter](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_substack)
|
||||
- [📽️ Chat with YouTube Videos](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/chat_with_X_tutorials/chat_with_youtube_videos)
|
||||
|
||||
### LLM Finetuning
|
||||
- [🌐 Llama3.2 Finetuning](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/llm_finetuning_tutorials/llama3.2_finetuning)
|
||||
|
||||
### Advanced Tools and Frameworks
|
||||
- [🧪 Gemini Multimodal Chatbot](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/gemini_multimodal_chatbot)
|
||||
- [🔄 Mixture of Agents](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/mixture_of_agents)
|
||||
- [🌐 MultiLLM Chat Playground](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/multillm_chat_playground)
|
||||
- [🔗 LLM Router App](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/llm_router_app)
|
||||
- [💬 Local ChatGPT Clone](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/local_chatgpt_clone)
|
||||
- [🌍 Web Scraping AI Agent](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/web_scrapping_ai_agent)
|
||||
- [🔍 Web Search AI Assistant](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/web_search_ai_assistant)
|
||||
- [🧪 Cursor AI Experiments](https://github.com/Shubhamsaboo/awesome-llm-apps/tree/main/advanced_tools_frameworks/cursor_ai_experiments)
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
1. Clone the repository
|
||||
1. **Clone the repository**
|
||||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
```
|
||||
|
||||
2. Navigate to the desired project directory
|
||||
2. **Navigate to the desired project directory**
|
||||
|
||||
```bash
|
||||
cd awesome-llm-apps/chat_with_gmail
|
||||
cd awesome-llm-apps/chat_with_X_tutorials/chat_with_gmail
|
||||
```
|
||||
|
||||
3. Install the required dependencies
|
||||
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.
|
||||
4. **Follow the project-specific instructions** in each project's `README.md` file to set up and run the app.
|
||||
|
||||
## 🤝 Contributing to Opensource
|
||||
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.
|
||||
## 🤝 Contributing to Open Source
|
||||
|
||||
### Thank you community for the support 🙏
|
||||
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)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,17 @@ import os
|
|||
gpt4_model = None
|
||||
|
||||
def create_article_crew(topic):
|
||||
"""Creates a team of agents to research, write, and edit an article on a given topic.
|
||||
|
||||
This function sets up a crew consisting of three agents: a researcher, a writer, and an editor.
|
||||
Each agent is assigned a specific task to ensure the production of a well-researched,
|
||||
well-written, and polished article. The article is formatted using markdown standards.
|
||||
|
||||
Args:
|
||||
topic (str): The subject matter on which the article will be based.
|
||||
|
||||
Returns:
|
||||
Crew: A crew object that contains the agents and tasks necessary to complete the article."""
|
||||
# Create agents
|
||||
researcher = Agent(
|
||||
role='Researcher',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
scrapegraphai
|
||||
playwright
|
||||
langchain-community
|
||||
streamlit-chat
|
||||
streamlit
|
||||
crewai
|
||||
ollama
|
||||
|
|
@ -12,6 +12,7 @@ This repository contains a Streamlit application that demonstrates a multimodal
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/advanced_tools_frameworks/gemini_multimodal_chatbot
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ This Streamlit application demonstrates the use of RouteLLM, a system that intel
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/advanced_tools_frameworks/llm_router_app
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
streamlit
|
||||
"routellm[serve,eval]"
|
||||
"routellm[serve,eval]"
|
||||
routellm
|
||||
|
|
@ -12,6 +12,7 @@ This project demonstrates how to build a ChatGPT clone using the Llama-3 model r
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/advanced_tools_frameworks/local_chatgpt_clone
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ This Streamlit app demonstrates function calling with the local Llama3 model usi
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd local-llama3-tool-use
|
||||
cd awesome-llm-apps/advanced_tools_frameworks/local_llama3.1_tool_use
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import streamlit as st
|
||||
import os
|
||||
from phi.assistant import Assistant
|
||||
from phi.llm.ollama import Ollama
|
||||
from phi.tools.yfinance import YFinanceTools
|
||||
from phi.tools.serpapi_tools import SerpApiTools
|
||||
from agno.agent import Agent
|
||||
from agno.models.ollama import Ollama
|
||||
from agno.tools.yfinance import YFinanceTools
|
||||
from agno.tools.serpapi import SerpApiTools
|
||||
|
||||
st.set_page_config(page_title="Llama-3 Tool Use", page_icon="🦙")
|
||||
|
||||
|
|
@ -13,9 +13,21 @@ if 'SERPAPI_API_KEY' not in os.environ:
|
|||
st.stop()
|
||||
|
||||
def get_assistant(tools):
|
||||
return Assistant(
|
||||
"""Creates and returns a configured assistant agent.
|
||||
|
||||
This function initializes an assistant agent with a specific model and toolset.
|
||||
The assistant is capable of accessing tools selected by the user and includes
|
||||
additional features such as showing tool call details, running in debug mode,
|
||||
and appending the current datetime to its instructions.
|
||||
|
||||
Args:
|
||||
tools (list): A list of tools that the assistant can access.
|
||||
|
||||
Returns:
|
||||
Agent: A configured assistant agent with specified capabilities and settings."""
|
||||
return Agent(
|
||||
name="llama3_assistant",
|
||||
llm=Ollama(model="llama3"),
|
||||
model=Ollama(id="llama3.1:8b"),
|
||||
tools=tools,
|
||||
description="You are a helpful assistant that can access specific tools based on user selection.",
|
||||
show_tool_calls=True,
|
||||
|
|
@ -25,7 +37,7 @@ def get_assistant(tools):
|
|||
|
||||
)
|
||||
|
||||
st.title("🦙 Local Llama-3 Tool Use")
|
||||
st.title("🦙 Local Llama-3.1 Tool Use")
|
||||
st.markdown("""
|
||||
This app demonstrates function calling with the local Llama3 model using Ollama.
|
||||
Select tools in the sidebar and ask relevant questions!
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
streamlit
|
||||
ollama
|
||||
phidata
|
||||
agno
|
||||
|
|
@ -12,6 +12,7 @@ This Streamlit app allows you to scrape a website using OpenAI API and the scrap
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/advanced_tools_frameworks/web_scrapping_ai_agent
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ This Streamlit app combines the power of search engines and LLMs to provide you
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/advanced_tools_frameworks/web_search_ai_assistant
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Import the required libraries
|
||||
import streamlit as st
|
||||
from phi.assistant import Assistant
|
||||
from phi.tools.duckduckgo import DuckDuckGo
|
||||
from phi.llm.anthropic import Claude
|
||||
from agno.agent import Agent
|
||||
from agno.tools.duckduckgo import DuckDuckGoTools
|
||||
from agno.models.anthropic import Claude
|
||||
|
||||
# Set up the Streamlit app
|
||||
st.title("Claude Sonnet + AI Web Search 🤖")
|
||||
|
|
@ -13,12 +13,12 @@ anthropic_api_key = st.text_input("Anthropic's Claude API Key", type="password")
|
|||
|
||||
# If Anthropic API key is provided, create an instance of Assistant
|
||||
if anthropic_api_key:
|
||||
assistant = Assistant(
|
||||
llm=Claude(
|
||||
model="claude-3-5-sonnet-20240620",
|
||||
assistant = Agent(
|
||||
model=Claude(
|
||||
id="claude-3-5-sonnet-20240620",
|
||||
max_tokens=1024,
|
||||
temperature=0.9,
|
||||
api_key=anthropic_api_key) , tools=[DuckDuckGo()], show_tool_calls=True
|
||||
temperature=0.3,
|
||||
api_key=anthropic_api_key) , tools=[DuckDuckGoTools()], show_tool_calls=True
|
||||
)
|
||||
# Get the search query from the user
|
||||
query= st.text_input("Enter the Search Query", type="default")
|
||||
|
|
@ -26,4 +26,4 @@ if anthropic_api_key:
|
|||
if query:
|
||||
# Search the web using the AI Assistant
|
||||
response = assistant.run(query, stream=False)
|
||||
st.write(response)
|
||||
st.write(response.content)
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
# Import the required libraries
|
||||
import streamlit as st
|
||||
from phi.assistant import Assistant
|
||||
from phi.tools.duckduckgo import DuckDuckGo
|
||||
from phi.llm.openai import OpenAIChat
|
||||
from agno.agent import Agent
|
||||
from agno.tools.duckduckgo import DuckDuckGoTools
|
||||
from agno.models.openai import OpenAIChat
|
||||
|
||||
# Set up the Streamlit app
|
||||
st.title("AI Web Search Assistant 🤖")
|
||||
|
|
@ -14,12 +14,12 @@ openai_access_token = st.text_input("OpenAI API Key", type="password")
|
|||
# If OpenAI API key is provided, create an instance of Assistant
|
||||
if openai_access_token:
|
||||
# Create an instance of the Assistant
|
||||
assistant = Assistant(
|
||||
llm=OpenAIChat(
|
||||
model="gpt-4o",
|
||||
assistant = Agent(
|
||||
model=OpenAIChat(
|
||||
id="gpt-4o",
|
||||
max_tokens=1024,
|
||||
temperature=0.9,
|
||||
api_key=openai_access_token) , tools=[DuckDuckGo()], show_tool_calls=True
|
||||
api_key=openai_access_token) , tools=[DuckDuckGoTools()], show_tool_calls=True
|
||||
)
|
||||
|
||||
# Get the search query from the user
|
||||
|
|
@ -28,4 +28,4 @@ if openai_access_token:
|
|||
if query:
|
||||
# Search the web using the AI Assistant
|
||||
response = assistant.run(query, stream=False)
|
||||
st.write(response)
|
||||
st.write(response.content)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
streamlit
|
||||
openai
|
||||
phidata
|
||||
agno
|
||||
duckduckgo-search
|
||||
50
ai_agent_tutorials/ai_3dpygame_r1/README.md
Normal file
50
ai_agent_tutorials/ai_3dpygame_r1/README.md
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
# 🎮 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.
|
||||
173
ai_agent_tutorials/ai_3dpygame_r1/ai_3dpygame_r1.py
Normal file
173
ai_agent_tutorials/ai_3dpygame_r1/ai_3dpygame_r1.py
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
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")
|
||||
4
ai_agent_tutorials/ai_3dpygame_r1/requirements.txt
Normal file
4
ai_agent_tutorials/ai_3dpygame_r1/requirements.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
agno
|
||||
langchain-openai
|
||||
browser-use
|
||||
streamlit
|
||||
81
ai_agent_tutorials/ai_aqi_analysis_agent/README.md
Normal file
81
ai_agent_tutorials/ai_aqi_analysis_agent/README.md
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
# 🌍 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.
|
||||
|
|
@ -0,0 +1,272 @@
|
|||
from typing import Dict, Optional
|
||||
from dataclasses import dataclass
|
||||
from pydantic import BaseModel, Field
|
||||
from agno.agent import Agent
|
||||
from agno.models.openai import OpenAIChat
|
||||
from firecrawl import FirecrawlApp
|
||||
import gradio as gr
|
||||
import json
|
||||
|
||||
class AQIResponse(BaseModel):
|
||||
success: bool
|
||||
data: Dict[str, float]
|
||||
status: str
|
||||
expiresAt: str
|
||||
|
||||
class ExtractSchema(BaseModel):
|
||||
aqi: float = Field(description="Air Quality Index")
|
||||
temperature: float = Field(description="Temperature in degrees Celsius")
|
||||
humidity: float = Field(description="Humidity percentage")
|
||||
wind_speed: float = Field(description="Wind speed in kilometers per hour")
|
||||
pm25: float = Field(description="Particulate Matter 2.5 micrometers")
|
||||
pm10: float = Field(description="Particulate Matter 10 micrometers")
|
||||
co: float = Field(description="Carbon Monoxide level")
|
||||
|
||||
@dataclass
|
||||
class UserInput:
|
||||
city: str
|
||||
state: str
|
||||
country: str
|
||||
medical_conditions: Optional[str]
|
||||
planned_activity: str
|
||||
|
||||
class AQIAnalyzer:
|
||||
|
||||
def __init__(self, firecrawl_key: str) -> None:
|
||||
self.firecrawl = FirecrawlApp(api_key=firecrawl_key)
|
||||
|
||||
def _format_url(self, country: str, state: str, city: str) -> str:
|
||||
"""Format URL based on location, handling cases with and without state"""
|
||||
country_clean = country.lower().replace(' ', '-')
|
||||
city_clean = city.lower().replace(' ', '-')
|
||||
|
||||
if not state or state.lower() == 'none':
|
||||
return f"https://www.aqi.in/dashboard/{country_clean}/{city_clean}"
|
||||
|
||||
state_clean = state.lower().replace(' ', '-')
|
||||
return f"https://www.aqi.in/dashboard/{country_clean}/{state_clean}/{city_clean}"
|
||||
|
||||
def fetch_aqi_data(self, city: str, state: str, country: str) -> tuple[Dict[str, float], str]:
|
||||
"""Fetch AQI data using Firecrawl"""
|
||||
try:
|
||||
url = self._format_url(country, state, city)
|
||||
info_msg = f"Accessing URL: {url}"
|
||||
|
||||
response = self.firecrawl.extract(
|
||||
urls=[f"{url}/*"],
|
||||
params={
|
||||
'prompt': 'Extract the current real-time AQI, temperature, humidity, wind speed, PM2.5, PM10, and CO levels from the page. Also extract the timestamp of the data.',
|
||||
'schema': ExtractSchema.model_json_schema()
|
||||
}
|
||||
)
|
||||
|
||||
aqi_response = AQIResponse(**response)
|
||||
if not aqi_response.success:
|
||||
raise ValueError(f"Failed to fetch AQI data: {aqi_response.status}")
|
||||
|
||||
return aqi_response.data, info_msg
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error fetching AQI data: {str(e)}"
|
||||
return {
|
||||
'aqi': 0,
|
||||
'temperature': 0,
|
||||
'humidity': 0,
|
||||
'wind_speed': 0,
|
||||
'pm25': 0,
|
||||
'pm10': 0,
|
||||
'co': 0
|
||||
}, error_msg
|
||||
|
||||
class HealthRecommendationAgent:
|
||||
|
||||
def __init__(self, openai_key: str) -> None:
|
||||
self.agent = Agent(
|
||||
model=OpenAIChat(
|
||||
id="gpt-4o",
|
||||
name="Health Recommendation Agent",
|
||||
api_key=openai_key
|
||||
)
|
||||
)
|
||||
|
||||
def get_recommendations(
|
||||
self,
|
||||
aqi_data: Dict[str, float],
|
||||
user_input: UserInput
|
||||
) -> str:
|
||||
prompt = self._create_prompt(aqi_data, user_input)
|
||||
response = self.agent.run(prompt)
|
||||
return response.content
|
||||
|
||||
def _create_prompt(self, aqi_data: Dict[str, float], user_input: UserInput) -> str:
|
||||
return f"""
|
||||
Based on the following air quality conditions in {user_input.city}, {user_input.state}, {user_input.country}:
|
||||
- Overall AQI: {aqi_data['aqi']}
|
||||
- PM2.5 Level: {aqi_data['pm25']} µg/m³
|
||||
- PM10 Level: {aqi_data['pm10']} µg/m³
|
||||
- CO Level: {aqi_data['co']} ppb
|
||||
|
||||
Weather conditions:
|
||||
- Temperature: {aqi_data['temperature']}°C
|
||||
- Humidity: {aqi_data['humidity']}%
|
||||
- Wind Speed: {aqi_data['wind_speed']} km/h
|
||||
|
||||
User's Context:
|
||||
- Medical Conditions: {user_input.medical_conditions or 'None'}
|
||||
- Planned Activity: {user_input.planned_activity}
|
||||
**Comprehensive Health Recommendations:**
|
||||
1. **Impact of Current Air Quality on Health:**
|
||||
2. **Necessary Safety Precautions for Planned Activity:**
|
||||
3. **Advisability of Planned Activity:**
|
||||
4. **Best Time to Conduct the Activity:**
|
||||
"""
|
||||
|
||||
def analyze_conditions(
|
||||
city: str,
|
||||
state: str,
|
||||
country: str,
|
||||
medical_conditions: str,
|
||||
planned_activity: str,
|
||||
firecrawl_key: str,
|
||||
openai_key: str
|
||||
) -> tuple[str, str, str, str]:
|
||||
"""Analyze conditions and return AQI data, recommendations, and status messages"""
|
||||
try:
|
||||
# Initialize analyzers
|
||||
aqi_analyzer = AQIAnalyzer(firecrawl_key=firecrawl_key)
|
||||
health_agent = HealthRecommendationAgent(openai_key=openai_key)
|
||||
|
||||
# Create user input
|
||||
user_input = UserInput(
|
||||
city=city,
|
||||
state=state,
|
||||
country=country,
|
||||
medical_conditions=medical_conditions,
|
||||
planned_activity=planned_activity
|
||||
)
|
||||
|
||||
# Get AQI data
|
||||
aqi_data, info_msg = aqi_analyzer.fetch_aqi_data(
|
||||
city=user_input.city,
|
||||
state=user_input.state,
|
||||
country=user_input.country
|
||||
)
|
||||
|
||||
# Format AQI data for display
|
||||
aqi_json = json.dumps({
|
||||
"Air Quality Index (AQI)": aqi_data['aqi'],
|
||||
"PM2.5": f"{aqi_data['pm25']} µg/m³",
|
||||
"PM10": f"{aqi_data['pm10']} µg/m³",
|
||||
"Carbon Monoxide (CO)": f"{aqi_data['co']} ppb",
|
||||
"Temperature": f"{aqi_data['temperature']}°C",
|
||||
"Humidity": f"{aqi_data['humidity']}%",
|
||||
"Wind Speed": f"{aqi_data['wind_speed']} km/h"
|
||||
}, indent=2)
|
||||
|
||||
# Get recommendations
|
||||
recommendations = health_agent.get_recommendations(aqi_data, user_input)
|
||||
|
||||
warning_msg = """
|
||||
⚠️ Note: The data shown may not match real-time values on the website.
|
||||
This could be due to:
|
||||
- Cached data in Firecrawl
|
||||
- Rate limiting
|
||||
- Website updates not being captured
|
||||
|
||||
Consider refreshing or checking the website directly for real-time values.
|
||||
"""
|
||||
|
||||
return aqi_json, recommendations, info_msg, warning_msg
|
||||
|
||||
except Exception as e:
|
||||
error_msg = f"Error occurred: {str(e)}"
|
||||
return "", "Analysis failed", error_msg, ""
|
||||
|
||||
def create_demo() -> gr.Blocks:
|
||||
"""Create and configure the Gradio interface"""
|
||||
with gr.Blocks(title="AQI Analysis Agent") as demo:
|
||||
gr.Markdown(
|
||||
"""
|
||||
# 🌍 AQI Analysis Agent
|
||||
Get personalized health recommendations based on air quality conditions.
|
||||
"""
|
||||
)
|
||||
|
||||
# API Configuration
|
||||
with gr.Accordion("API Configuration", open=False):
|
||||
firecrawl_key = gr.Textbox(
|
||||
label="Firecrawl API Key",
|
||||
type="password",
|
||||
placeholder="Enter your Firecrawl API key"
|
||||
)
|
||||
openai_key = gr.Textbox(
|
||||
label="OpenAI API Key",
|
||||
type="password",
|
||||
placeholder="Enter your OpenAI API key"
|
||||
)
|
||||
|
||||
# Location Details
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
city = gr.Textbox(label="City", placeholder="e.g., Mumbai")
|
||||
state = gr.Textbox(
|
||||
label="State",
|
||||
placeholder="Leave blank for Union Territories or US cities",
|
||||
value=""
|
||||
)
|
||||
country = gr.Textbox(label="Country", value="India")
|
||||
|
||||
# Personal Details
|
||||
with gr.Row():
|
||||
with gr.Column():
|
||||
medical_conditions = gr.Textbox(
|
||||
label="Medical Conditions (optional)",
|
||||
placeholder="e.g., asthma, allergies",
|
||||
lines=2
|
||||
)
|
||||
planned_activity = gr.Textbox(
|
||||
label="Planned Activity",
|
||||
placeholder="e.g., morning jog for 2 hours",
|
||||
lines=2
|
||||
)
|
||||
|
||||
# Status Messages
|
||||
info_box = gr.Textbox(label="ℹ️ Status", interactive=False)
|
||||
warning_box = gr.Textbox(label="⚠️ Warning", interactive=False)
|
||||
|
||||
# Output Areas
|
||||
aqi_data_json = gr.JSON(label="📊 Current Air Quality Data")
|
||||
recommendations = gr.Markdown(label="🏥 Health Recommendations")
|
||||
|
||||
# Analyze Button
|
||||
analyze_btn = gr.Button("🔍 Analyze & Get Recommendations", variant="primary")
|
||||
analyze_btn.click(
|
||||
fn=analyze_conditions,
|
||||
inputs=[
|
||||
city,
|
||||
state,
|
||||
country,
|
||||
medical_conditions,
|
||||
planned_activity,
|
||||
firecrawl_key,
|
||||
openai_key
|
||||
],
|
||||
outputs=[aqi_data_json, recommendations, info_box, warning_box]
|
||||
)
|
||||
|
||||
# Examples
|
||||
gr.Examples(
|
||||
examples=[
|
||||
["Mumbai", "Maharashtra", "India", "asthma", "morning walk for 30 minutes"],
|
||||
["Delhi", "", "India", "", "outdoor yoga session"],
|
||||
["New York", "", "United States", "allergies", "afternoon run"],
|
||||
["Kakinada", "Andhra Pradesh", "India", "none", "Tennis for 2 hours"]
|
||||
],
|
||||
inputs=[city, state, country, medical_conditions, planned_activity]
|
||||
)
|
||||
|
||||
return demo
|
||||
|
||||
if __name__ == "__main__":
|
||||
demo = create_demo()
|
||||
demo.launch(share=True)
|
||||
|
|
@ -0,0 +1,265 @@
|
|||
from typing import Dict, Optional
|
||||
from dataclasses import dataclass
|
||||
from pydantic import BaseModel, Field
|
||||
from agno.agent import Agent
|
||||
from agno.models.openai import OpenAIChat
|
||||
from firecrawl import FirecrawlApp
|
||||
import streamlit as st
|
||||
|
||||
class AQIResponse(BaseModel):
|
||||
success: bool
|
||||
data: Dict[str, float]
|
||||
status: str
|
||||
expiresAt: str
|
||||
|
||||
class ExtractSchema(BaseModel):
|
||||
aqi: float = Field(description="Air Quality Index")
|
||||
temperature: float = Field(description="Temperature in degrees Celsius")
|
||||
humidity: float = Field(description="Humidity percentage")
|
||||
wind_speed: float = Field(description="Wind speed in kilometers per hour")
|
||||
pm25: float = Field(description="Particulate Matter 2.5 micrometers")
|
||||
pm10: float = Field(description="Particulate Matter 10 micrometers")
|
||||
co: float = Field(description="Carbon Monoxide level")
|
||||
|
||||
@dataclass
|
||||
class UserInput:
|
||||
city: str
|
||||
state: str
|
||||
country: str
|
||||
medical_conditions: Optional[str]
|
||||
planned_activity: str
|
||||
|
||||
class AQIAnalyzer:
|
||||
|
||||
def __init__(self, firecrawl_key: str) -> None:
|
||||
self.firecrawl = FirecrawlApp(api_key=firecrawl_key)
|
||||
|
||||
def _format_url(self, country: str, state: str, city: str) -> str:
|
||||
"""Format URL based on location, handling cases with and without state"""
|
||||
country_clean = country.lower().replace(' ', '-')
|
||||
city_clean = city.lower().replace(' ', '-')
|
||||
|
||||
if not state or state.lower() == 'none':
|
||||
return f"https://www.aqi.in/dashboard/{country_clean}/{city_clean}"
|
||||
|
||||
state_clean = state.lower().replace(' ', '-')
|
||||
return f"https://www.aqi.in/dashboard/{country_clean}/{state_clean}/{city_clean}"
|
||||
|
||||
def fetch_aqi_data(self, city: str, state: str, country: str) -> Dict[str, float]:
|
||||
"""Fetch AQI data using Firecrawl"""
|
||||
try:
|
||||
url = self._format_url(country, state, city)
|
||||
st.info(f"Accessing URL: {url}") # Display URL being accessed
|
||||
|
||||
response = self.firecrawl.extract(
|
||||
urls=[f"{url}/*"],
|
||||
params={
|
||||
'prompt': 'Extract the current real-time AQI, temperature, humidity, wind speed, PM2.5, PM10, and CO levels from the page. Also extract the timestamp of the data.',
|
||||
'schema': ExtractSchema.model_json_schema()
|
||||
}
|
||||
)
|
||||
|
||||
aqi_response = AQIResponse(**response)
|
||||
if not aqi_response.success:
|
||||
raise ValueError(f"Failed to fetch AQI data: {aqi_response.status}")
|
||||
|
||||
with st.expander("📦 Raw AQI Data", expanded=True):
|
||||
st.json({
|
||||
"url_accessed": url,
|
||||
"timestamp": aqi_response.expiresAt,
|
||||
"data": aqi_response.data
|
||||
})
|
||||
|
||||
st.warning("""
|
||||
⚠️ Note: The data shown may not match real-time values on the website.
|
||||
This could be due to:
|
||||
- Cached data in Firecrawl
|
||||
- Rate limiting
|
||||
- Website updates not being captured
|
||||
|
||||
Consider refreshing or checking the website directly for real-time values.
|
||||
""")
|
||||
|
||||
return aqi_response.data
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"Error fetching AQI data: {str(e)}")
|
||||
return {
|
||||
'aqi': 0,
|
||||
'temperature': 0,
|
||||
'humidity': 0,
|
||||
'wind_speed': 0,
|
||||
'pm25': 0,
|
||||
'pm10': 0,
|
||||
'co': 0
|
||||
}
|
||||
|
||||
class HealthRecommendationAgent:
|
||||
|
||||
def __init__(self, openai_key: str) -> None:
|
||||
self.agent = Agent(
|
||||
model=OpenAIChat(
|
||||
id="gpt-4o",
|
||||
name="Health Recommendation Agent",
|
||||
api_key=openai_key
|
||||
)
|
||||
)
|
||||
|
||||
def get_recommendations(
|
||||
self,
|
||||
aqi_data: Dict[str, float],
|
||||
user_input: UserInput
|
||||
) -> str:
|
||||
prompt = self._create_prompt(aqi_data, user_input)
|
||||
response = self.agent.run(prompt)
|
||||
return response.content
|
||||
|
||||
def _create_prompt(self, aqi_data: Dict[str, float], user_input: UserInput) -> str:
|
||||
return f"""
|
||||
Based on the following air quality conditions in {user_input.city}, {user_input.state}, {user_input.country}:
|
||||
- Overall AQI: {aqi_data['aqi']}
|
||||
- PM2.5 Level: {aqi_data['pm25']} µg/m³
|
||||
- PM10 Level: {aqi_data['pm10']} µg/m³
|
||||
- CO Level: {aqi_data['co']} ppb
|
||||
|
||||
Weather conditions:
|
||||
- Temperature: {aqi_data['temperature']}°C
|
||||
- Humidity: {aqi_data['humidity']}%
|
||||
- Wind Speed: {aqi_data['wind_speed']} km/h
|
||||
|
||||
User's Context:
|
||||
- Medical Conditions: {user_input.medical_conditions or 'None'}
|
||||
- Planned Activity: {user_input.planned_activity}
|
||||
**Comprehensive Health Recommendations:**
|
||||
1. **Impact of Current Air Quality on Health:**
|
||||
2. **Necessary Safety Precautions for Planned Activity:**
|
||||
3. **Advisability of Planned Activity:**
|
||||
4. **Best Time to Conduct the Activity:**
|
||||
"""
|
||||
|
||||
def analyze_conditions(
|
||||
user_input: UserInput,
|
||||
api_keys: Dict[str, str]
|
||||
) -> str:
|
||||
aqi_analyzer = AQIAnalyzer(firecrawl_key=api_keys['firecrawl'])
|
||||
health_agent = HealthRecommendationAgent(openai_key=api_keys['openai'])
|
||||
|
||||
aqi_data = aqi_analyzer.fetch_aqi_data(
|
||||
city=user_input.city,
|
||||
state=user_input.state,
|
||||
country=user_input.country
|
||||
)
|
||||
|
||||
return health_agent.get_recommendations(aqi_data, user_input)
|
||||
|
||||
def initialize_session_state():
|
||||
if 'api_keys' not in st.session_state:
|
||||
st.session_state.api_keys = {
|
||||
'firecrawl': '',
|
||||
'openai': ''
|
||||
}
|
||||
|
||||
def setup_page():
|
||||
st.set_page_config(
|
||||
page_title="AQI Analysis Agent",
|
||||
page_icon="🌍",
|
||||
layout="wide"
|
||||
)
|
||||
|
||||
st.title("🌍 AQI Analysis Agent")
|
||||
st.info("Get personalized health recommendations based on air quality conditions.")
|
||||
|
||||
def render_sidebar():
|
||||
"""Render sidebar with API configuration"""
|
||||
with st.sidebar:
|
||||
st.header("🔑 API Configuration")
|
||||
|
||||
new_firecrawl_key = st.text_input(
|
||||
"Firecrawl API Key",
|
||||
type="password",
|
||||
value=st.session_state.api_keys['firecrawl'],
|
||||
help="Enter your Firecrawl API key"
|
||||
)
|
||||
new_openai_key = st.text_input(
|
||||
"OpenAI API Key",
|
||||
type="password",
|
||||
value=st.session_state.api_keys['openai'],
|
||||
help="Enter your OpenAI API key"
|
||||
)
|
||||
|
||||
if (new_firecrawl_key and new_openai_key and
|
||||
(new_firecrawl_key != st.session_state.api_keys['firecrawl'] or
|
||||
new_openai_key != st.session_state.api_keys['openai'])):
|
||||
st.session_state.api_keys.update({
|
||||
'firecrawl': new_firecrawl_key,
|
||||
'openai': new_openai_key
|
||||
})
|
||||
st.success("✅ API keys updated!")
|
||||
|
||||
def render_main_content():
|
||||
st.header("📍 Location Details")
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
city = st.text_input("City", placeholder="e.g., Mumbai")
|
||||
state = st.text_input("State", placeholder="If it's a Union Territory or a city in the US, leave it blank")
|
||||
country = st.text_input("Country", value="India", placeholder="United States")
|
||||
|
||||
with col2:
|
||||
st.header("👤 Personal Details")
|
||||
medical_conditions = st.text_area(
|
||||
"Medical Conditions (optional)",
|
||||
placeholder="e.g., asthma, allergies"
|
||||
)
|
||||
planned_activity = st.text_area(
|
||||
"Planned Activity",
|
||||
placeholder="e.g., morning jog for 2 hours"
|
||||
)
|
||||
|
||||
return UserInput(
|
||||
city=city,
|
||||
state=state,
|
||||
country=country,
|
||||
medical_conditions=medical_conditions,
|
||||
planned_activity=planned_activity
|
||||
)
|
||||
|
||||
def main():
|
||||
"""Main application entry point"""
|
||||
initialize_session_state()
|
||||
setup_page()
|
||||
render_sidebar()
|
||||
user_input = render_main_content()
|
||||
|
||||
result = None
|
||||
|
||||
if st.button("🔍 Analyze & Get Recommendations"):
|
||||
if not all([user_input.city, user_input.planned_activity]):
|
||||
st.error("Please fill in all required fields (state and medical conditions are optional)")
|
||||
elif not all(st.session_state.api_keys.values()):
|
||||
st.error("Please provide both API keys in the sidebar")
|
||||
else:
|
||||
try:
|
||||
with st.spinner("🔄 Analyzing conditions..."):
|
||||
result = analyze_conditions(
|
||||
user_input=user_input,
|
||||
api_keys=st.session_state.api_keys
|
||||
)
|
||||
st.success("✅ Analysis completed!")
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"❌ Error: {str(e)}")
|
||||
|
||||
if result:
|
||||
st.markdown("### 📦 Recommendations")
|
||||
st.markdown(result)
|
||||
|
||||
st.download_button(
|
||||
"💾 Download Recommendations",
|
||||
data=result,
|
||||
file_name=f"aqi_recommendations_{user_input.city}_{user_input.state}.txt",
|
||||
mime="text/plain"
|
||||
)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
agno
|
||||
openai
|
||||
firecrawl-py==1.9.0
|
||||
gradio==5.9.1
|
||||
pydantic
|
||||
dataclasses
|
||||
46
ai_agent_tutorials/ai_chess_agent/README.md
Normal file
46
ai_agent_tutorials/ai_chess_agent/README.md
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# ♜ 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
|
||||
```
|
||||
|
||||
249
ai_agent_tutorials/ai_chess_agent/ai_chess_agent.py
Normal file
249
ai_agent_tutorials/ai_chess_agent/ai_chess_agent.py
Normal file
|
|
@ -0,0 +1,249 @@
|
|||
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.")
|
||||
5
ai_agent_tutorials/ai_chess_agent/requirements.txt
Normal file
5
ai_agent_tutorials/ai_chess_agent/requirements.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
streamlit
|
||||
chess==1.11.1
|
||||
autogen==0.6.1
|
||||
cairosvg
|
||||
pillow
|
||||
61
ai_agent_tutorials/ai_coding_agent_o3-mini/README.md
Normal file
61
ai_agent_tutorials/ai_coding_agent_o3-mini/README.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
# 💻 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
|
||||
280
ai_agent_tutorials/ai_coding_agent_o3-mini/ai_coding_agent_o3.py
Normal file
280
ai_agent_tutorials/ai_coding_agent_o3-mini/ai_coding_agent_o3.py
Normal file
|
|
@ -0,0 +1,280 @@
|
|||
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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
streamlit
|
||||
e2b-code-interpreter
|
||||
agno
|
||||
Pillow
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
# 🧲 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
|
||||
|
|
@ -0,0 +1,346 @@
|
|||
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.")
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
exa-py==1.7.1
|
||||
firecrawl-py==1.9.0
|
||||
duckduckgo-search==7.2.1
|
||||
agno
|
||||
streamlit==1.41.1
|
||||
|
|
@ -13,6 +13,7 @@ This Streamlit app implements an AI-powered customer support agent for synthetic
|
|||
1. Clone the GitHub repository
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/ai_agent_tutorials/ai_customer_support_agent
|
||||
```
|
||||
|
||||
2. Install the required dependencies:
|
||||
|
|
@ -28,7 +29,7 @@ The app expects Qdrant to be running on localhost:6333. Adjust the configuration
|
|||
docker pull qdrant/qdrant
|
||||
|
||||
docker run -p 6333:6333 -p 6334:6334 \
|
||||
-v $(pwd)/qdrant_storage:/qdrant/storage:z \
|
||||
-v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
|
||||
qdrant/qdrant
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -14,84 +14,115 @@ openai_api_key = st.text_input("Enter OpenAI API Key", type="password")
|
|||
|
||||
if openai_api_key:
|
||||
os.environ['OPENAI_API_KEY'] = openai_api_key
|
||||
|
||||
|
||||
class CustomerSupportAIAgent:
|
||||
def __init__(self):
|
||||
# Initialize Mem0 with Qdrant as the vector store
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"model": "gpt-4o-mini",
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
self.memory = Memory.from_config(config)
|
||||
try:
|
||||
self.memory = Memory.from_config(config)
|
||||
except Exception as e:
|
||||
st.error(f"Failed to initialize memory: {e}")
|
||||
st.stop() # Stop execution if memory initialization fails
|
||||
|
||||
self.client = OpenAI()
|
||||
self.app_id = "customer-support"
|
||||
|
||||
def handle_query(self, query, user_id=None):
|
||||
relevant_memories = self.memory.search(query=query, user_id=user_id)
|
||||
context = "Relevant past information:\n"
|
||||
for mem in relevant_memories:
|
||||
context += f"- {mem['text']}\n"
|
||||
try:
|
||||
# Search for relevant memories
|
||||
relevant_memories = self.memory.search(query=query, user_id=user_id)
|
||||
|
||||
# Build context from relevant memories
|
||||
context = "Relevant past information:\n"
|
||||
if relevant_memories and "results" in relevant_memories:
|
||||
for memory in relevant_memories["results"]:
|
||||
if "memory" in memory:
|
||||
context += f"- {memory['memory']}\n"
|
||||
|
||||
full_prompt = f"{context}\nCustomer: {query}\nSupport Agent:"
|
||||
# Generate a response using OpenAI
|
||||
full_prompt = f"{context}\nCustomer: {query}\nSupport Agent:"
|
||||
response = self.client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a customer support AI agent for TechGadgets.com, an online electronics store."},
|
||||
{"role": "user", "content": full_prompt}
|
||||
]
|
||||
)
|
||||
answer = response.choices[0].message.content
|
||||
|
||||
response = self.client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a customer support AI agent for TechGadgets.com, an online electronics store."},
|
||||
{"role": "user", "content": full_prompt}
|
||||
]
|
||||
)
|
||||
answer = response.choices[0].message.content
|
||||
# Add the query and answer to memory
|
||||
self.memory.add(query, user_id=user_id, metadata={"app_id": self.app_id, "role": "user"})
|
||||
self.memory.add(answer, user_id=user_id, metadata={"app_id": self.app_id, "role": "assistant"})
|
||||
|
||||
self.memory.add(query, user_id=user_id, metadata={"app_id": self.app_id, "role": "user"})
|
||||
self.memory.add(answer, user_id=user_id, metadata={"app_id": self.app_id, "role": "assistant"})
|
||||
|
||||
return answer
|
||||
return answer
|
||||
except Exception as e:
|
||||
st.error(f"An error occurred while handling the query: {e}")
|
||||
return "Sorry, I encountered an error. Please try again later."
|
||||
|
||||
def get_memories(self, user_id=None):
|
||||
return self.memory.get_all(user_id=user_id)
|
||||
try:
|
||||
# Retrieve all memories for a user
|
||||
return self.memory.get_all(user_id=user_id)
|
||||
except Exception as e:
|
||||
st.error(f"Failed to retrieve memories: {e}")
|
||||
return None
|
||||
|
||||
def generate_synthetic_data(self, user_id):
|
||||
today = datetime.now()
|
||||
order_date = (today - timedelta(days=10)).strftime("%B %d, %Y")
|
||||
expected_delivery = (today + timedelta(days=2)).strftime("%B %d, %Y")
|
||||
def generate_synthetic_data(self, user_id: str) -> dict | None:
|
||||
try:
|
||||
today = datetime.now()
|
||||
order_date = (today - timedelta(days=10)).strftime("%B %d, %Y")
|
||||
expected_delivery = (today + timedelta(days=2)).strftime("%B %d, %Y")
|
||||
|
||||
prompt = f"""Generate a detailed customer profile and order history for a TechGadgets.com customer with ID {user_id}. Include:
|
||||
1. Customer name and basic info
|
||||
2. A recent order of a high-end electronic device (placed on {order_date}, to be delivered by {expected_delivery})
|
||||
3. Order details (product, price, order number)
|
||||
4. Customer's shipping address
|
||||
5. 2-3 previous orders from the past year
|
||||
6. 2-3 customer service interactions related to these orders
|
||||
7. Any preferences or patterns in their shopping behavior
|
||||
prompt = f"""Generate a detailed customer profile and order history for a TechGadgets.com customer with ID {user_id}. Include:
|
||||
1. Customer name and basic info
|
||||
2. A recent order of a high-end electronic device (placed on {order_date}, to be delivered by {expected_delivery})
|
||||
3. Order details (product, price, order number)
|
||||
4. Customer's shipping address
|
||||
5. 2-3 previous orders from the past year
|
||||
6. 2-3 customer service interactions related to these orders
|
||||
7. Any preferences or patterns in their shopping behavior
|
||||
|
||||
Format the output as a JSON object."""
|
||||
Format the output as a JSON object."""
|
||||
|
||||
response = self.client.chat.completions.create(
|
||||
model="gpt-4o-mini",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a data generation AI that creates realistic customer profiles and order histories. Always respond with valid JSON."},
|
||||
{"role": "user", "content": prompt}
|
||||
],
|
||||
response_format={"type": "json_object"}
|
||||
)
|
||||
response = self.client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a data generation AI that creates realistic customer profiles and order histories. Always respond with valid JSON."},
|
||||
{"role": "user", "content": prompt}
|
||||
]
|
||||
)
|
||||
|
||||
customer_data = json.loads(response.choices[0].message.content)
|
||||
customer_data = json.loads(response.choices[0].message.content)
|
||||
|
||||
# Add generated data to memory
|
||||
for key, value in customer_data.items():
|
||||
if isinstance(value, list):
|
||||
for item in value:
|
||||
self.memory.add(json.dumps(item), user_id=user_id, metadata={"app_id": self.app_id, "role": "system"})
|
||||
else:
|
||||
self.memory.add(f"{key}: {json.dumps(value)}", user_id=user_id, metadata={"app_id": self.app_id, "role": "system"})
|
||||
# Add generated data to memory
|
||||
for key, value in customer_data.items():
|
||||
if isinstance(value, list):
|
||||
for item in value:
|
||||
self.memory.add(
|
||||
json.dumps(item),
|
||||
user_id=user_id,
|
||||
metadata={"app_id": self.app_id, "role": "system"}
|
||||
)
|
||||
else:
|
||||
self.memory.add(
|
||||
f"{key}: {json.dumps(value)}",
|
||||
user_id=user_id,
|
||||
metadata={"app_id": self.app_id, "role": "system"}
|
||||
)
|
||||
|
||||
return customer_data
|
||||
return customer_data
|
||||
except Exception as e:
|
||||
st.error(f"Failed to generate synthetic data: {e}")
|
||||
return None
|
||||
|
||||
# Initialize the CustomerSupportAIAgent
|
||||
support_agent = CustomerSupportAIAgent()
|
||||
|
|
@ -111,7 +142,10 @@ if openai_api_key:
|
|||
if customer_id:
|
||||
with st.spinner("Generating customer data..."):
|
||||
st.session_state.customer_data = support_agent.generate_synthetic_data(customer_id)
|
||||
st.sidebar.success("Synthetic data generated successfully!")
|
||||
if st.session_state.customer_data:
|
||||
st.sidebar.success("Synthetic data generated successfully!")
|
||||
else:
|
||||
st.sidebar.error("Failed to generate synthetic data.")
|
||||
else:
|
||||
st.sidebar.error("Please enter a customer ID first.")
|
||||
|
||||
|
|
@ -126,8 +160,10 @@ if openai_api_key:
|
|||
memories = support_agent.get_memories(user_id=customer_id)
|
||||
if memories:
|
||||
st.sidebar.write(f"Memory for customer **{customer_id}**:")
|
||||
for mem in memories:
|
||||
st.sidebar.write(f"- {mem['text']}")
|
||||
if memories and "results" in memories:
|
||||
for memory in memories["results"]:
|
||||
if "memory" in memory:
|
||||
st.write(f"- {memory['memory']}")
|
||||
else:
|
||||
st.sidebar.info("No memory found for this customer ID.")
|
||||
else:
|
||||
|
|
@ -152,7 +188,8 @@ if openai_api_key:
|
|||
st.markdown(query)
|
||||
|
||||
# Generate and display response
|
||||
answer = support_agent.handle_query(query, user_id=customer_id)
|
||||
with st.spinner("Generating response..."):
|
||||
answer = support_agent.handle_query(query, user_id=customer_id)
|
||||
|
||||
# Add assistant response to chat history
|
||||
st.session_state.messages.append({"role": "assistant", "content": answer})
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
streamlit
|
||||
openai
|
||||
mem0ai
|
||||
mem0ai==0.1.29
|
||||
55
ai_agent_tutorials/ai_data_analysis_agent/README.md
Normal file
55
ai_agent_tutorials/ai_data_analysis_agent/README.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# 📊 AI Data Analysis Agent
|
||||
|
||||
An AI data analysis Agent built using the Agno Agent framework and Openai's gpt-4o model. This agent helps users analyze their data - csv, excel files through natural language queries, powered by OpenAI's language models and DuckDB for efficient data processing - making data analysis accessible to users regardless of their SQL expertise.
|
||||
|
||||
## Features
|
||||
|
||||
- 📤 **File Upload Support**:
|
||||
- Upload CSV and Excel files
|
||||
- Automatic data type detection and schema inference
|
||||
- Support for multiple file formats
|
||||
|
||||
- 💬 **Natural Language Queries**:
|
||||
- Convert natural language questions into SQL queries
|
||||
- Get instant answers about your data
|
||||
- No SQL knowledge required
|
||||
|
||||
- 🔍 **Advanced Analysis**:
|
||||
- Perform complex data aggregations
|
||||
- Filter and sort data
|
||||
- Generate statistical summaries
|
||||
- Create data visualizations
|
||||
|
||||
- 🎯 **Interactive UI**:
|
||||
- User-friendly Streamlit interface
|
||||
- Real-time query processing
|
||||
- Clear result presentation
|
||||
|
||||
## 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_data_analysis_agent
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. **Configure API Keys**
|
||||
- Get OpenAI API key from [OpenAI Platform](https://platform.openai.com)
|
||||
|
||||
3. **Run the Application**
|
||||
```bash
|
||||
streamlit run ai_data_analyst.py
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1. Launch the application using the command above
|
||||
2. Provide your OpenAI API key in the sidebar of Streamlit
|
||||
3. Upload your CSV or Excel file through the Streamlit interface
|
||||
4. Ask questions about your data in natural language
|
||||
5. View the results and generated visualizations
|
||||
|
||||
137
ai_agent_tutorials/ai_data_analysis_agent/ai_data_analyst.py
Normal file
137
ai_agent_tutorials/ai_data_analysis_agent/ai_data_analyst.py
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
import json
|
||||
import tempfile
|
||||
import csv
|
||||
import streamlit as st
|
||||
import pandas as pd
|
||||
from agno.models.openai import OpenAIChat
|
||||
from phi.agent.duckdb import DuckDbAgent
|
||||
from agno.tools.pandas import PandasTools
|
||||
import re
|
||||
|
||||
# Function to preprocess and save the uploaded file
|
||||
def preprocess_and_save(file):
|
||||
try:
|
||||
# Read the uploaded file into a DataFrame
|
||||
if file.name.endswith('.csv'):
|
||||
df = pd.read_csv(file, encoding='utf-8', na_values=['NA', 'N/A', 'missing'])
|
||||
elif file.name.endswith('.xlsx'):
|
||||
df = pd.read_excel(file, na_values=['NA', 'N/A', 'missing'])
|
||||
else:
|
||||
st.error("Unsupported file format. Please upload a CSV or Excel file.")
|
||||
return None, None, None
|
||||
|
||||
# Ensure string columns are properly quoted
|
||||
for col in df.select_dtypes(include=['object']):
|
||||
df[col] = df[col].astype(str).replace({r'"': '""'}, regex=True)
|
||||
|
||||
# Parse dates and numeric columns
|
||||
for col in df.columns:
|
||||
if 'date' in col.lower():
|
||||
df[col] = pd.to_datetime(df[col], errors='coerce')
|
||||
elif df[col].dtype == 'object':
|
||||
try:
|
||||
df[col] = pd.to_numeric(df[col])
|
||||
except (ValueError, TypeError):
|
||||
# Keep as is if conversion fails
|
||||
pass
|
||||
|
||||
# Create a temporary file to save the preprocessed data
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as temp_file:
|
||||
temp_path = temp_file.name
|
||||
# Save the DataFrame to the temporary CSV file with quotes around string fields
|
||||
df.to_csv(temp_path, index=False, quoting=csv.QUOTE_ALL)
|
||||
|
||||
return temp_path, df.columns.tolist(), df # Return the DataFrame as well
|
||||
except Exception as e:
|
||||
st.error(f"Error processing file: {e}")
|
||||
return None, None, None
|
||||
|
||||
# Streamlit app
|
||||
st.title("📊 Data Analyst Agent")
|
||||
|
||||
# Sidebar for API keys
|
||||
with st.sidebar:
|
||||
st.header("API Keys")
|
||||
openai_key = st.text_input("Enter your OpenAI API key:", type="password")
|
||||
if openai_key:
|
||||
st.session_state.openai_key = openai_key
|
||||
st.success("API key saved!")
|
||||
else:
|
||||
st.warning("Please enter your OpenAI API key to proceed.")
|
||||
|
||||
# File upload widget
|
||||
uploaded_file = st.file_uploader("Upload a CSV or Excel file", type=["csv", "xlsx"])
|
||||
|
||||
if uploaded_file is not None and "openai_key" in st.session_state:
|
||||
# Preprocess and save the uploaded file
|
||||
temp_path, columns, df = preprocess_and_save(uploaded_file)
|
||||
|
||||
if temp_path and columns and df is not None:
|
||||
# Display the uploaded data as a table
|
||||
st.write("Uploaded Data:")
|
||||
st.dataframe(df) # Use st.dataframe for an interactive table
|
||||
|
||||
# Display the columns of the uploaded data
|
||||
st.write("Uploaded columns:", columns)
|
||||
|
||||
# Configure the semantic model with the temporary file path
|
||||
semantic_model = {
|
||||
"tables": [
|
||||
{
|
||||
"name": "uploaded_data",
|
||||
"description": "Contains the uploaded dataset.",
|
||||
"path": temp_path,
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
# Initialize the DuckDbAgent for SQL query generation
|
||||
duckdb_agent = DuckDbAgent(
|
||||
model=OpenAIChat(model="gpt-4", api_key=st.session_state.openai_key),
|
||||
semantic_model=json.dumps(semantic_model),
|
||||
tools=[PandasTools()],
|
||||
markdown=True,
|
||||
add_history_to_messages=False, # Disable chat history
|
||||
followups=False, # Disable follow-up queries
|
||||
read_tool_call_history=False, # Disable reading tool call history
|
||||
system_prompt="You are an expert data analyst. Generate SQL queries to solve the user's query. Return only the SQL query, enclosed in ```sql ``` and give the final answer.",
|
||||
)
|
||||
|
||||
# Initialize code storage in session state
|
||||
if "generated_code" not in st.session_state:
|
||||
st.session_state.generated_code = None
|
||||
|
||||
# Main query input widget
|
||||
user_query = st.text_area("Ask a query about the data:")
|
||||
|
||||
# Add info message about terminal output
|
||||
st.info("💡 Check your terminal for a clearer output of the agent's response")
|
||||
|
||||
if st.button("Submit Query"):
|
||||
if user_query.strip() == "":
|
||||
st.warning("Please enter a query.")
|
||||
else:
|
||||
try:
|
||||
# Show loading spinner while processing
|
||||
with st.spinner('Processing your query...'):
|
||||
# Get the response from DuckDbAgent
|
||||
|
||||
response1 = duckdb_agent.run(user_query)
|
||||
|
||||
# Extract the content from the RunResponse object
|
||||
if hasattr(response1, 'content'):
|
||||
response_content = response1.content
|
||||
else:
|
||||
response_content = str(response1)
|
||||
response = duckdb_agent.print_response(
|
||||
user_query,
|
||||
stream=True,
|
||||
)
|
||||
|
||||
# Display the response in Streamlit
|
||||
st.markdown(response_content)
|
||||
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"Error generating response from the DuckDbAgent: {e}")
|
||||
st.error("Please try rephrasing your query or check if the data format is correct.")
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
phidata
|
||||
streamlit==1.41.1
|
||||
openai==1.58.1
|
||||
duckdb==1.1.3
|
||||
pandas
|
||||
numpy==1.26.4
|
||||
agno
|
||||
41
ai_agent_tutorials/ai_data_visualisation_agent/README.md
Normal file
41
ai_agent_tutorials/ai_data_visualisation_agent/README.md
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
# 📊 AI Data Visualization Agent
|
||||
A Streamlit application that acts as your personal data visualization expert, powered by LLMs. Simply upload your dataset and ask questions in natural language - the AI agent will analyze your data, generate appropriate visualizations, and provide insights through a combination of charts, statistics, and explanations.
|
||||
|
||||
## Features
|
||||
#### Natural Language Data Analysis
|
||||
- Ask questions about your data in plain English
|
||||
- Get instant visualizations and statistical analysis
|
||||
- Receive explanations of findings and insights
|
||||
- Interactive follow-up questioning
|
||||
|
||||
#### Intelligent Visualization Selection
|
||||
- Automatic choice of appropriate chart types
|
||||
- Dynamic visualization generation
|
||||
- Statistical visualization support
|
||||
- Custom plot formatting and styling
|
||||
|
||||
#### Multi-Model AI Support
|
||||
- Meta-Llama 3.1 405B for complex analysis
|
||||
- DeepSeek V3 for detailed insights
|
||||
- Qwen 2.5 7B for quick analysis
|
||||
- Meta-Llama 3.3 70B for advanced queries
|
||||
|
||||
## How to Run
|
||||
|
||||
Follow the steps below to set up and run the application:
|
||||
- Before anything else, Please get a free Together AI API Key here: https://api.together.ai/signin
|
||||
- Get a free E2B API Key here: https://e2b.dev/ ; https://e2b.dev/docs/legacy/getting-started/api-key
|
||||
|
||||
1. **Clone the Repository**
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd ai_agent_tutorials/ai_data_visualisation_agent
|
||||
```
|
||||
2. **Install the dependencies**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
3. **Run the Streamlit app**
|
||||
```bash
|
||||
streamlit run ai_data_visualisation_agent.py
|
||||
```
|
||||
|
|
@ -0,0 +1,178 @@
|
|||
import os
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
import io
|
||||
import contextlib
|
||||
import warnings
|
||||
from typing import Optional, List, Any, Tuple
|
||||
from PIL import Image
|
||||
import streamlit as st
|
||||
import pandas as pd
|
||||
import base64
|
||||
from io import BytesIO
|
||||
from together import Together
|
||||
from e2b_code_interpreter import Sandbox
|
||||
|
||||
warnings.filterwarnings("ignore", category=UserWarning, module="pydantic")
|
||||
|
||||
pattern = re.compile(r"```python\n(.*?)\n```", re.DOTALL)
|
||||
|
||||
def code_interpret(e2b_code_interpreter: Sandbox, code: str) -> Optional[List[Any]]:
|
||||
with st.spinner('Executing code in E2B sandbox...'):
|
||||
stdout_capture = io.StringIO()
|
||||
stderr_capture = io.StringIO()
|
||||
|
||||
with contextlib.redirect_stdout(stdout_capture), contextlib.redirect_stderr(stderr_capture):
|
||||
with warnings.catch_warnings():
|
||||
warnings.simplefilter("ignore")
|
||||
exec = e2b_code_interpreter.run_code(code)
|
||||
|
||||
if stderr_capture.getvalue():
|
||||
print("[Code Interpreter Warnings/Errors]", file=sys.stderr)
|
||||
print(stderr_capture.getvalue(), file=sys.stderr)
|
||||
|
||||
if stdout_capture.getvalue():
|
||||
print("[Code Interpreter Output]", file=sys.stdout)
|
||||
print(stdout_capture.getvalue(), file=sys.stdout)
|
||||
|
||||
if exec.error:
|
||||
print(f"[Code Interpreter ERROR] {exec.error}", file=sys.stderr)
|
||||
return None
|
||||
return exec.results
|
||||
|
||||
def match_code_blocks(llm_response: str) -> str:
|
||||
match = pattern.search(llm_response)
|
||||
if match:
|
||||
code = match.group(1)
|
||||
return code
|
||||
return ""
|
||||
|
||||
def chat_with_llm(e2b_code_interpreter: Sandbox, user_message: str, dataset_path: str) -> Tuple[Optional[List[Any]], str]:
|
||||
# Update system prompt to include dataset path information
|
||||
system_prompt = f"""You're a Python data scientist and data visualization expert. You are given a dataset at path '{dataset_path}' and also the user's query.
|
||||
You need to analyze the dataset and answer the user's query with a response and you run Python code to solve them.
|
||||
IMPORTANT: Always use the dataset path variable '{dataset_path}' in your code when reading the CSV file."""
|
||||
|
||||
messages = [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": user_message},
|
||||
]
|
||||
|
||||
with st.spinner('Getting response from Together AI LLM model...'):
|
||||
client = Together(api_key=st.session_state.together_api_key)
|
||||
response = client.chat.completions.create(
|
||||
model=st.session_state.model_name,
|
||||
messages=messages,
|
||||
)
|
||||
|
||||
response_message = response.choices[0].message
|
||||
python_code = match_code_blocks(response_message.content)
|
||||
|
||||
if python_code:
|
||||
code_interpreter_results = code_interpret(e2b_code_interpreter, python_code)
|
||||
return code_interpreter_results, response_message.content
|
||||
else:
|
||||
st.warning(f"Failed to match any Python code in model's response")
|
||||
return None, response_message.content
|
||||
|
||||
def upload_dataset(code_interpreter: Sandbox, uploaded_file) -> str:
|
||||
dataset_path = f"./{uploaded_file.name}"
|
||||
|
||||
try:
|
||||
code_interpreter.files.write(dataset_path, uploaded_file)
|
||||
return dataset_path
|
||||
except Exception as error:
|
||||
st.error(f"Error during file upload: {error}")
|
||||
raise error
|
||||
|
||||
|
||||
def main():
|
||||
"""Main Streamlit application."""
|
||||
st.title("📊 AI Data Visualization Agent")
|
||||
st.write("Upload your dataset and ask questions about it!")
|
||||
|
||||
# Initialize session state variables
|
||||
if 'together_api_key' not in st.session_state:
|
||||
st.session_state.together_api_key = ''
|
||||
if 'e2b_api_key' not in st.session_state:
|
||||
st.session_state.e2b_api_key = ''
|
||||
if 'model_name' not in st.session_state:
|
||||
st.session_state.model_name = ''
|
||||
|
||||
with st.sidebar:
|
||||
st.header("API Keys and Model Configuration")
|
||||
st.session_state.together_api_key = st.sidebar.text_input("Together AI API Key", type="password")
|
||||
st.sidebar.info("💡 Everyone gets a free $1 credit by Together AI - AI Acceleration Cloud platform")
|
||||
st.sidebar.markdown("[Get Together AI API Key](https://api.together.ai/signin)")
|
||||
|
||||
st.session_state.e2b_api_key = st.sidebar.text_input("Enter E2B API Key", type="password")
|
||||
st.sidebar.markdown("[Get E2B API Key](https://e2b.dev/docs/legacy/getting-started/api-key)")
|
||||
|
||||
# Add model selection dropdown
|
||||
model_options = {
|
||||
"Meta-Llama 3.1 405B": "meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo",
|
||||
"DeepSeek V3": "deepseek-ai/DeepSeek-V3",
|
||||
"Qwen 2.5 7B": "Qwen/Qwen2.5-7B-Instruct-Turbo",
|
||||
"Meta-Llama 3.3 70B": "meta-llama/Llama-3.3-70B-Instruct-Turbo"
|
||||
}
|
||||
st.session_state.model_name = st.selectbox(
|
||||
"Select Model",
|
||||
options=list(model_options.keys()),
|
||||
index=0 # Default to first option
|
||||
)
|
||||
st.session_state.model_name = model_options[st.session_state.model_name]
|
||||
|
||||
uploaded_file = st.file_uploader("Choose a CSV file", type="csv")
|
||||
|
||||
if uploaded_file is not None:
|
||||
# Display dataset with toggle
|
||||
df = pd.read_csv(uploaded_file)
|
||||
st.write("Dataset:")
|
||||
show_full = st.checkbox("Show full dataset")
|
||||
if show_full:
|
||||
st.dataframe(df)
|
||||
else:
|
||||
st.write("Preview (first 5 rows):")
|
||||
st.dataframe(df.head())
|
||||
# Query input
|
||||
query = st.text_area("What would you like to know about your data?",
|
||||
"Can you compare the average cost for two people between different categories?")
|
||||
|
||||
if st.button("Analyze"):
|
||||
if not st.session_state.together_api_key or not st.session_state.e2b_api_key:
|
||||
st.error("Please enter both API keys in the sidebar.")
|
||||
else:
|
||||
with Sandbox(api_key=st.session_state.e2b_api_key) as code_interpreter:
|
||||
# Upload the dataset
|
||||
dataset_path = upload_dataset(code_interpreter, uploaded_file)
|
||||
|
||||
# Pass dataset_path to chat_with_llm
|
||||
code_results, llm_response = chat_with_llm(code_interpreter, query, dataset_path)
|
||||
|
||||
# Display LLM's text response
|
||||
st.write("AI Response:")
|
||||
st.write(llm_response)
|
||||
|
||||
# Display results/visualizations
|
||||
if code_results:
|
||||
for result in code_results:
|
||||
if hasattr(result, 'png') and result.png: # Check if PNG data is available
|
||||
# Decode the base64-encoded PNG data
|
||||
png_data = base64.b64decode(result.png)
|
||||
|
||||
# Convert PNG data to an image and display it
|
||||
image = Image.open(BytesIO(png_data))
|
||||
st.image(image, caption="Generated Visualization", use_container_width=False)
|
||||
elif hasattr(result, 'figure'): # For matplotlib figures
|
||||
fig = result.figure # Extract the matplotlib figure
|
||||
st.pyplot(fig) # Display using st.pyplot
|
||||
elif hasattr(result, 'show'): # For plotly figures
|
||||
st.plotly_chart(result)
|
||||
elif isinstance(result, (pd.DataFrame, pd.Series)):
|
||||
st.dataframe(result)
|
||||
else:
|
||||
st.write(result)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
together==1.3.10
|
||||
e2b-code-interpreter==1.0.3
|
||||
e2b==1.0.5
|
||||
Pillow==10.4.0
|
||||
streamlit
|
||||
pandas
|
||||
matplotlib
|
||||
74
ai_agent_tutorials/ai_deep_research_agent/README.md
Normal file
74
ai_agent_tutorials/ai_deep_research_agent/README.md
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# Deep Research Agent with OpenAI Agents SDK and Firecrawl
|
||||
|
||||
A powerful research assistant that leverages OpenAI's Agents SDK and Firecrawl's deep research capabilities to perform comprehensive web research on any topic and any question.
|
||||
|
||||
## Features
|
||||
|
||||
- **Deep Web Research**: Automatically searches the web, extracts content, and synthesizes findings
|
||||
- **Enhanced Analysis**: Uses OpenAI's Agents SDK to elaborate on research findings with additional context and insights
|
||||
- **Interactive UI**: Clean Streamlit interface for easy interaction
|
||||
- **Downloadable Reports**: Export research findings as markdown files
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Input Phase**: User provides a research topic and API credentials
|
||||
2. **Research Phase**: The tool uses Firecrawl to search the web and extract relevant information
|
||||
3. **Analysis Phase**: An initial research report is generated based on the findings
|
||||
4. **Enhancement Phase**: A second agent elaborates on the initial report, adding depth and context
|
||||
5. **Output Phase**: The enhanced report is presented to the user and available for download
|
||||
|
||||
## Requirements
|
||||
|
||||
- Python 3.8+
|
||||
- OpenAI API key
|
||||
- Firecrawl API key
|
||||
- Required Python packages (see `requirements.txt`)
|
||||
|
||||
## Installation
|
||||
|
||||
1. Clone this repository:
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd ai_agent_tutorials/ai_deep_research_agent
|
||||
```
|
||||
|
||||
2. Install the required packages:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1. Run the Streamlit app:
|
||||
```bash
|
||||
streamlit run deep_research_openai.py
|
||||
```
|
||||
|
||||
2. Enter your API keys in the sidebar:
|
||||
- OpenAI API key
|
||||
- Firecrawl API key
|
||||
|
||||
3. Enter your research topic in the main input field
|
||||
|
||||
4. Click "Start Research" and wait for the process to complete
|
||||
|
||||
5. View and download your enhanced research report
|
||||
|
||||
## Example Research Topics
|
||||
|
||||
- "Latest developments in quantum computing"
|
||||
- "Impact of climate change on marine ecosystems"
|
||||
- "Advancements in renewable energy storage"
|
||||
- "Ethical considerations in artificial intelligence"
|
||||
- "Emerging trends in remote work technologies"
|
||||
|
||||
## Technical Details
|
||||
|
||||
The application uses two specialized agents:
|
||||
|
||||
1. **Research Agent**: Utilizes Firecrawl's deep research endpoint to gather comprehensive information from multiple web sources.
|
||||
|
||||
2. **Elaboration Agent**: Enhances the initial research by adding detailed explanations, examples, case studies, and practical implications.
|
||||
|
||||
The Firecrawl deep research tool performs multiple iterations of web searches, content extraction, and analysis to provide thorough coverage of the topic.
|
||||
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
import asyncio
|
||||
import streamlit as st
|
||||
from typing import Dict, Any, List
|
||||
from agents import Agent, Runner, trace
|
||||
from agents import set_default_openai_key
|
||||
from firecrawl import FirecrawlApp
|
||||
from agents.tool import function_tool
|
||||
|
||||
# Set page configuration
|
||||
st.set_page_config(
|
||||
page_title="OpenAI Deep Research Agent",
|
||||
page_icon="📘",
|
||||
layout="wide"
|
||||
)
|
||||
|
||||
# Initialize session state for API keys if not exists
|
||||
if "openai_api_key" not in st.session_state:
|
||||
st.session_state.openai_api_key = ""
|
||||
if "firecrawl_api_key" not in st.session_state:
|
||||
st.session_state.firecrawl_api_key = ""
|
||||
|
||||
# Sidebar for API keys
|
||||
with st.sidebar:
|
||||
st.title("API Configuration")
|
||||
openai_api_key = st.text_input(
|
||||
"OpenAI API Key",
|
||||
value=st.session_state.openai_api_key,
|
||||
type="password"
|
||||
)
|
||||
firecrawl_api_key = st.text_input(
|
||||
"Firecrawl API Key",
|
||||
value=st.session_state.firecrawl_api_key,
|
||||
type="password"
|
||||
)
|
||||
|
||||
if openai_api_key:
|
||||
st.session_state.openai_api_key = openai_api_key
|
||||
set_default_openai_key(openai_api_key)
|
||||
if firecrawl_api_key:
|
||||
st.session_state.firecrawl_api_key = firecrawl_api_key
|
||||
|
||||
# Main content
|
||||
st.title("📘 OpenAI Deep Research Agent")
|
||||
st.markdown("This OpenAI Agent from the OpenAI Agents SDK performs deep research on any topic using Firecrawl")
|
||||
|
||||
# Research topic input
|
||||
research_topic = st.text_input("Enter your research topic:", placeholder="e.g., Latest developments in AI")
|
||||
|
||||
# Keep the original deep_research tool
|
||||
@function_tool
|
||||
async def deep_research(query: str, max_depth: int, time_limit: int, max_urls: int) -> Dict[str, Any]:
|
||||
"""
|
||||
Perform comprehensive web research using Firecrawl's deep research endpoint.
|
||||
"""
|
||||
try:
|
||||
# Initialize FirecrawlApp with the API key from session state
|
||||
firecrawl_app = FirecrawlApp(api_key=st.session_state.firecrawl_api_key)
|
||||
|
||||
# Define research parameters
|
||||
params = {
|
||||
"maxDepth": max_depth,
|
||||
"timeLimit": time_limit,
|
||||
"maxUrls": max_urls
|
||||
}
|
||||
|
||||
# Set up a callback for real-time updates
|
||||
def on_activity(activity):
|
||||
st.write(f"[{activity['type']}] {activity['message']}")
|
||||
|
||||
# Run deep research
|
||||
with st.spinner("Performing deep research..."):
|
||||
results = firecrawl_app.deep_research(
|
||||
query=query,
|
||||
params=params,
|
||||
on_activity=on_activity
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"final_analysis": results['data']['finalAnalysis'],
|
||||
"sources_count": len(results['data']['sources']),
|
||||
"sources": results['data']['sources']
|
||||
}
|
||||
except Exception as e:
|
||||
st.error(f"Deep research error: {str(e)}")
|
||||
return {"error": str(e), "success": False}
|
||||
|
||||
# Keep the original agents
|
||||
research_agent = Agent(
|
||||
name="research_agent",
|
||||
instructions="""You are a research assistant that can perform deep web research on any topic.
|
||||
|
||||
When given a research topic or question:
|
||||
1. Use the deep_research tool to gather comprehensive information
|
||||
- Always use these parameters:
|
||||
* max_depth: 3 (for moderate depth)
|
||||
* time_limit: 180 (3 minutes)
|
||||
* max_urls: 10 (sufficient sources)
|
||||
2. The tool will search the web, analyze multiple sources, and provide a synthesis
|
||||
3. Review the research results and organize them into a well-structured report
|
||||
4. Include proper citations for all sources
|
||||
5. Highlight key findings and insights
|
||||
""",
|
||||
tools=[deep_research]
|
||||
)
|
||||
|
||||
elaboration_agent = Agent(
|
||||
name="elaboration_agent",
|
||||
instructions="""You are an expert content enhancer specializing in research elaboration.
|
||||
|
||||
When given a research report:
|
||||
1. Analyze the structure and content of the report
|
||||
2. Enhance the report by:
|
||||
- Adding more detailed explanations of complex concepts
|
||||
- Including relevant examples, case studies, and real-world applications
|
||||
- Expanding on key points with additional context and nuance
|
||||
- Adding visual elements descriptions (charts, diagrams, infographics)
|
||||
- Incorporating latest trends and future predictions
|
||||
- Suggesting practical implications for different stakeholders
|
||||
3. Maintain academic rigor and factual accuracy
|
||||
4. Preserve the original structure while making it more comprehensive
|
||||
5. Ensure all additions are relevant and valuable to the topic
|
||||
"""
|
||||
)
|
||||
|
||||
async def run_research_process(topic: str):
|
||||
"""Run the complete research process."""
|
||||
# Step 1: Initial Research
|
||||
with st.spinner("Conducting initial research..."):
|
||||
research_result = await Runner.run(research_agent, topic)
|
||||
initial_report = research_result.final_output
|
||||
|
||||
# Display initial report in an expander
|
||||
with st.expander("View Initial Research Report"):
|
||||
st.markdown(initial_report)
|
||||
|
||||
# Step 2: Enhance the report
|
||||
with st.spinner("Enhancing the report with additional information..."):
|
||||
elaboration_input = f"""
|
||||
RESEARCH TOPIC: {topic}
|
||||
|
||||
INITIAL RESEARCH REPORT:
|
||||
{initial_report}
|
||||
|
||||
Please enhance this research report with additional information, examples, case studies,
|
||||
and deeper insights while maintaining its academic rigor and factual accuracy.
|
||||
"""
|
||||
|
||||
elaboration_result = await Runner.run(elaboration_agent, elaboration_input)
|
||||
enhanced_report = elaboration_result.final_output
|
||||
|
||||
return enhanced_report
|
||||
|
||||
# Main research process
|
||||
if st.button("Start Research", disabled=not (openai_api_key and firecrawl_api_key and research_topic)):
|
||||
if not openai_api_key or not firecrawl_api_key:
|
||||
st.warning("Please enter both API keys in the sidebar.")
|
||||
elif not research_topic:
|
||||
st.warning("Please enter a research topic.")
|
||||
else:
|
||||
try:
|
||||
# Create placeholder for the final report
|
||||
report_placeholder = st.empty()
|
||||
|
||||
# Run the research process
|
||||
enhanced_report = asyncio.run(run_research_process(research_topic))
|
||||
|
||||
# Display the enhanced report
|
||||
report_placeholder.markdown("## Enhanced Research Report")
|
||||
report_placeholder.markdown(enhanced_report)
|
||||
|
||||
# Add download button
|
||||
st.download_button(
|
||||
"Download Report",
|
||||
enhanced_report,
|
||||
file_name=f"{research_topic.replace(' ', '_')}_report.md",
|
||||
mime="text/markdown"
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"An error occurred: {str(e)}")
|
||||
|
||||
# Footer
|
||||
st.markdown("---")
|
||||
st.markdown("Powered by OpenAI Agents SDK and Firecrawl")
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
openai-agents
|
||||
firecrawl
|
||||
streamlit
|
||||
firecrawl-py
|
||||
|
|
@ -15,6 +15,7 @@ This script demonstrates how to build a team of AI agents that work together as
|
|||
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:
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
from phi.agent import Agent
|
||||
from phi.model.openai import OpenAIChat
|
||||
from phi.storage.agent.sqlite import SqlAgentStorage
|
||||
from phi.tools.duckduckgo import DuckDuckGo
|
||||
from phi.tools.yfinance import YFinanceTools
|
||||
from phi.playground import Playground, serve_playground_app
|
||||
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=[DuckDuckGo()],
|
||||
storage=SqlAgentStorage(table_name="web_agent", db_file="agents.db"),
|
||||
tools=[DuckDuckGoTools()],
|
||||
storage=SqliteAgentStorage(table_name="web_agent", db_file="agents.db"),
|
||||
add_history_to_messages=True,
|
||||
markdown=True,
|
||||
)
|
||||
|
|
@ -21,7 +21,7 @@ finance_agent = Agent(
|
|||
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=SqlAgentStorage(table_name="finance_agent", db_file="agents.db"),
|
||||
storage=SqliteAgentStorage(table_name="finance_agent", db_file="agents.db"),
|
||||
add_history_to_messages=True,
|
||||
markdown=True,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
openai
|
||||
phidata
|
||||
agno
|
||||
duckduckgo-search
|
||||
yfinance
|
||||
fastapi[standard]
|
||||
|
|
|
|||
67
ai_agent_tutorials/ai_game_design_agent_team/README.md
Normal file
67
ai_agent_tutorials/ai_game_design_agent_team/README.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# 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
|
||||
|
|
@ -0,0 +1,290 @@
|
|||
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'])
|
||||
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
streamlit==1.41.1
|
||||
autogen
|
||||
53
ai_agent_tutorials/ai_health_fitness_agent/README.md
Normal file
53
ai_agent_tutorials/ai_health_fitness_agent/README.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# AI Health & Fitness Planner Agent 🏋️♂️
|
||||
|
||||
The **AI Health & Fitness Planner** is a personalized health and fitness Agent powered by Agno AI Agent framework. This app generates tailored dietary and fitness plans based on user inputs such as age, weight, height, activity level, dietary preferences, and fitness goals.
|
||||
|
||||
## Features
|
||||
|
||||
- **Health Agent and Fitness Agent**
|
||||
- The app has two phidata agents that are specialists in giving Diet advice and Fitness/workout advice respectively.
|
||||
|
||||
- **Personalized Dietary Plans**:
|
||||
- Generates detailed meal plans (breakfast, lunch, dinner, and snacks).
|
||||
- Includes important considerations like hydration, electrolytes, and fiber intake.
|
||||
- Supports various dietary preferences like Keto, Vegetarian, Low Carb, etc.
|
||||
|
||||
- **Personalized Fitness Plans**:
|
||||
- Provides customized exercise routines based on fitness goals.
|
||||
- Covers warm-ups, main workouts, and cool-downs.
|
||||
- Includes actionable fitness tips and progress tracking advice.
|
||||
|
||||
- **Interactive Q&A**: Allows users to ask follow-up questions about their plans.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
The application requires the following Python libraries:
|
||||
|
||||
- `agno`
|
||||
- `google-generativeai`
|
||||
- `streamlit`
|
||||
|
||||
Ensure these dependencies are installed via the `requirements.txt` file according to their mentioned versions
|
||||
|
||||
## How to Run
|
||||
|
||||
Follow the steps below to set up and run the application:
|
||||
Before anything else, Please get a free Gemini API Key provided by Google AI here: https://aistudio.google.com/apikey
|
||||
|
||||
1. **Clone the Repository**:
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/ai_agent_tutorials/ai_health_fitness_agent
|
||||
```
|
||||
|
||||
2. **Install the dependencies**
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
3. **Run the Streamlit app**
|
||||
```bash
|
||||
streamlit run health_agent.py
|
||||
```
|
||||
|
||||
|
||||
244
ai_agent_tutorials/ai_health_fitness_agent/health_agent.py
Normal file
244
ai_agent_tutorials/ai_health_fitness_agent/health_agent.py
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
import streamlit as st
|
||||
from agno.agent import Agent
|
||||
from agno.models.google import Gemini
|
||||
|
||||
st.set_page_config(
|
||||
page_title="AI Health & Fitness Planner",
|
||||
page_icon="🏋️♂️",
|
||||
layout="wide",
|
||||
initial_sidebar_state="expanded"
|
||||
)
|
||||
|
||||
st.markdown("""
|
||||
<style>
|
||||
.main {
|
||||
padding: 2rem;
|
||||
}
|
||||
.stButton>button {
|
||||
width: 100%;
|
||||
border-radius: 5px;
|
||||
height: 3em;
|
||||
}
|
||||
.success-box {
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: #f0fff4;
|
||||
border: 1px solid #9ae6b4;
|
||||
}
|
||||
.warning-box {
|
||||
padding: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
background-color: #fffaf0;
|
||||
border: 1px solid #fbd38d;
|
||||
}
|
||||
div[data-testid="stExpander"] div[role="button"] p {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
def display_dietary_plan(plan_content):
|
||||
with st.expander("📋 Your Personalized Dietary Plan", expanded=True):
|
||||
col1, col2 = st.columns([2, 1])
|
||||
|
||||
with col1:
|
||||
st.markdown("### 🎯 Why this plan works")
|
||||
st.info(plan_content.get("why_this_plan_works", "Information not available"))
|
||||
st.markdown("### 🍽️ Meal Plan")
|
||||
st.write(plan_content.get("meal_plan", "Plan not available"))
|
||||
|
||||
with col2:
|
||||
st.markdown("### ⚠️ Important Considerations")
|
||||
considerations = plan_content.get("important_considerations", "").split('\n')
|
||||
for consideration in considerations:
|
||||
if consideration.strip():
|
||||
st.warning(consideration)
|
||||
|
||||
def display_fitness_plan(plan_content):
|
||||
with st.expander("💪 Your Personalized Fitness Plan", expanded=True):
|
||||
col1, col2 = st.columns([2, 1])
|
||||
|
||||
with col1:
|
||||
st.markdown("### 🎯 Goals")
|
||||
st.success(plan_content.get("goals", "Goals not specified"))
|
||||
st.markdown("### 🏋️♂️ Exercise Routine")
|
||||
st.write(plan_content.get("routine", "Routine not available"))
|
||||
|
||||
with col2:
|
||||
st.markdown("### 💡 Pro Tips")
|
||||
tips = plan_content.get("tips", "").split('\n')
|
||||
for tip in tips:
|
||||
if tip.strip():
|
||||
st.info(tip)
|
||||
|
||||
def main():
|
||||
if 'dietary_plan' not in st.session_state:
|
||||
st.session_state.dietary_plan = {}
|
||||
st.session_state.fitness_plan = {}
|
||||
st.session_state.qa_pairs = []
|
||||
st.session_state.plans_generated = False
|
||||
|
||||
st.title("🏋️♂️ AI Health & Fitness Planner")
|
||||
st.markdown("""
|
||||
<div style='background-color: #00008B; padding: 1rem; border-radius: 0.5rem; margin-bottom: 2rem;'>
|
||||
Get personalized dietary and fitness plans tailored to your goals and preferences.
|
||||
Our AI-powered system considers your unique profile to create the perfect plan for you.
|
||||
</div>
|
||||
""", unsafe_allow_html=True)
|
||||
|
||||
with st.sidebar:
|
||||
st.header("🔑 API Configuration")
|
||||
gemini_api_key = st.text_input(
|
||||
"Gemini API Key",
|
||||
type="password",
|
||||
help="Enter your Gemini API key to access the service"
|
||||
)
|
||||
|
||||
if not gemini_api_key:
|
||||
st.warning("⚠️ Please enter your Gemini API Key to proceed")
|
||||
st.markdown("[Get your API key here](https://aistudio.google.com/apikey)")
|
||||
return
|
||||
|
||||
st.success("API Key accepted!")
|
||||
|
||||
if gemini_api_key:
|
||||
try:
|
||||
gemini_model = Gemini(id="gemini-1.5-flash", api_key=gemini_api_key)
|
||||
except Exception as e:
|
||||
st.error(f"❌ Error initializing Gemini model: {e}")
|
||||
return
|
||||
|
||||
st.header("👤 Your Profile")
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
age = st.number_input("Age", min_value=10, max_value=100, step=1, help="Enter your age")
|
||||
height = st.number_input("Height (cm)", min_value=100.0, max_value=250.0, step=0.1)
|
||||
activity_level = st.selectbox(
|
||||
"Activity Level",
|
||||
options=["Sedentary", "Lightly Active", "Moderately Active", "Very Active", "Extremely Active"],
|
||||
help="Choose your typical activity level"
|
||||
)
|
||||
dietary_preferences = st.selectbox(
|
||||
"Dietary Preferences",
|
||||
options=["Vegetarian", "Keto", "Gluten Free", "Low Carb", "Dairy Free"],
|
||||
help="Select your dietary preference"
|
||||
)
|
||||
|
||||
with col2:
|
||||
weight = st.number_input("Weight (kg)", min_value=20.0, max_value=300.0, step=0.1)
|
||||
sex = st.selectbox("Sex", options=["Male", "Female", "Other"])
|
||||
fitness_goals = st.selectbox(
|
||||
"Fitness Goals",
|
||||
options=["Lose Weight", "Gain Muscle", "Endurance", "Stay Fit", "Strength Training"],
|
||||
help="What do you want to achieve?"
|
||||
)
|
||||
|
||||
if st.button("🎯 Generate My Personalized Plan", use_container_width=True):
|
||||
with st.spinner("Creating your perfect health and fitness routine..."):
|
||||
try:
|
||||
dietary_agent = Agent(
|
||||
name="Dietary Expert",
|
||||
role="Provides personalized dietary recommendations",
|
||||
model=gemini_model,
|
||||
instructions=[
|
||||
"Consider the user's input, including dietary restrictions and preferences.",
|
||||
"Suggest a detailed meal plan for the day, including breakfast, lunch, dinner, and snacks.",
|
||||
"Provide a brief explanation of why the plan is suited to the user's goals.",
|
||||
"Focus on clarity, coherence, and quality of the recommendations.",
|
||||
]
|
||||
)
|
||||
|
||||
fitness_agent = Agent(
|
||||
name="Fitness Expert",
|
||||
role="Provides personalized fitness recommendations",
|
||||
model=gemini_model,
|
||||
instructions=[
|
||||
"Provide exercises tailored to the user's goals.",
|
||||
"Include warm-up, main workout, and cool-down exercises.",
|
||||
"Explain the benefits of each recommended exercise.",
|
||||
"Ensure the plan is actionable and detailed.",
|
||||
]
|
||||
)
|
||||
|
||||
user_profile = f"""
|
||||
Age: {age}
|
||||
Weight: {weight}kg
|
||||
Height: {height}cm
|
||||
Sex: {sex}
|
||||
Activity Level: {activity_level}
|
||||
Dietary Preferences: {dietary_preferences}
|
||||
Fitness Goals: {fitness_goals}
|
||||
"""
|
||||
|
||||
dietary_plan_response = dietary_agent.run(user_profile)
|
||||
dietary_plan = {
|
||||
"why_this_plan_works": "High Protein, Healthy Fats, Moderate Carbohydrates, and Caloric Balance",
|
||||
"meal_plan": dietary_plan_response.content,
|
||||
"important_considerations": """
|
||||
- Hydration: Drink plenty of water throughout the day
|
||||
- Electrolytes: Monitor sodium, potassium, and magnesium levels
|
||||
- Fiber: Ensure adequate intake through vegetables and fruits
|
||||
- Listen to your body: Adjust portion sizes as needed
|
||||
"""
|
||||
}
|
||||
|
||||
fitness_plan_response = fitness_agent.run(user_profile)
|
||||
fitness_plan = {
|
||||
"goals": "Build strength, improve endurance, and maintain overall fitness",
|
||||
"routine": fitness_plan_response.content,
|
||||
"tips": """
|
||||
- Track your progress regularly
|
||||
- Allow proper rest between workouts
|
||||
- Focus on proper form
|
||||
- Stay consistent with your routine
|
||||
"""
|
||||
}
|
||||
|
||||
st.session_state.dietary_plan = dietary_plan
|
||||
st.session_state.fitness_plan = fitness_plan
|
||||
st.session_state.plans_generated = True
|
||||
st.session_state.qa_pairs = []
|
||||
|
||||
display_dietary_plan(dietary_plan)
|
||||
display_fitness_plan(fitness_plan)
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"❌ An error occurred: {e}")
|
||||
|
||||
if st.session_state.plans_generated:
|
||||
st.header("❓ Questions about your plan?")
|
||||
question_input = st.text_input("What would you like to know?")
|
||||
|
||||
if st.button("Get Answer"):
|
||||
if question_input:
|
||||
with st.spinner("Finding the best answer for you..."):
|
||||
dietary_plan = st.session_state.dietary_plan
|
||||
fitness_plan = st.session_state.fitness_plan
|
||||
|
||||
context = f"Dietary Plan: {dietary_plan.get('meal_plan', '')}\n\nFitness Plan: {fitness_plan.get('routine', '')}"
|
||||
full_context = f"{context}\nUser Question: {question_input}"
|
||||
|
||||
try:
|
||||
agent = Agent(model=gemini_model, show_tool_calls=True, markdown=True)
|
||||
run_response = agent.run(full_context)
|
||||
|
||||
if hasattr(run_response, 'content'):
|
||||
answer = run_response.content
|
||||
else:
|
||||
answer = "Sorry, I couldn't generate a response at this time."
|
||||
|
||||
st.session_state.qa_pairs.append((question_input, answer))
|
||||
except Exception as e:
|
||||
st.error(f"❌ An error occurred while getting the answer: {e}")
|
||||
|
||||
if st.session_state.qa_pairs:
|
||||
st.header("💬 Q&A History")
|
||||
for question, answer in st.session_state.qa_pairs:
|
||||
st.markdown(f"**Q:** {question}")
|
||||
st.markdown(f"**A:** {answer}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
google-generativeai==0.8.3
|
||||
streamlit==1.40.2
|
||||
agno
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
## 📈 AI Investment Agent
|
||||
This Streamlit app is an AI-powered investment agent that compares the performance of two stocks and generates detailed reports. By using GPT-4o with Yahoo Finance data, this app provides valuable insights to help you make informed investment decisions.
|
||||
This Streamlit app is an AI-powered investment agent built with Agno's AI Agent framework that compares the performance of two stocks and generates detailed reports. By using GPT-4o with Yahoo Finance data, this app provides valuable insights to help you make informed investment decisions.
|
||||
|
||||
### Features
|
||||
- Compare the performance of two stocks
|
||||
|
|
@ -13,6 +13,7 @@ This Streamlit app is an AI-powered investment agent that compares the performan
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/ai_agent_tutorials/ai_investment_agent
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ streamlit run investment_agent.py
|
|||
### How it Works?
|
||||
|
||||
- Upon running the app, you will be prompted to enter your OpenAI API key. This key is used to authenticate and access the OpenAI language model.
|
||||
- Once you provide a valid API key, an instance of the Assistant class is created. This assistant utilizes the GPT-4 language model from OpenAI and the YFinanceTools for accessing stock data.
|
||||
- Once you provide a valid API key, an instance of the Assistant class is created. This assistant utilizes the GPT-4o language model from OpenAI and the YFinanceTools for accessing stock data.
|
||||
- Enter the stock symbols of the two companies you want to compare in the provided text input fields.
|
||||
- The assistant will perform the following steps:
|
||||
- Retrieve real-time stock prices and historical data using YFinanceTools
|
||||
|
|
|
|||
|
|
@ -1,30 +1,34 @@
|
|||
# Import the required libraries
|
||||
import streamlit as st
|
||||
from phi.assistant import Assistant
|
||||
from phi.llm.openai import OpenAIChat
|
||||
from phi.tools.yfinance import YFinanceTools
|
||||
from agno.agent import Agent
|
||||
from agno.models.openai import OpenAIChat
|
||||
from agno.tools.yfinance import YFinanceTools
|
||||
|
||||
# Set up the Streamlit app
|
||||
st.title("AI Investment Agent 📈🤖")
|
||||
st.caption("This app allows you to compare the performance of two stocks and generate detailed reports.")
|
||||
|
||||
# Get OpenAI API key from user
|
||||
openai_api_key = st.text_input("OpenAI API Key", type="password")
|
||||
|
||||
if openai_api_key:
|
||||
# Create an instance of the Assistant
|
||||
assistant = Assistant(
|
||||
llm=OpenAIChat(model="gpt-4o", api_key=openai_api_key),
|
||||
tools=[YFinanceTools(stock_price=True, analyst_recommendations=True, company_info=True, company_news=True)],
|
||||
assistant = Agent(
|
||||
model=OpenAIChat(id="gpt-4o", api_key=openai_api_key),
|
||||
tools=[
|
||||
YFinanceTools(stock_price=True, analyst_recommendations=True, stock_fundamentals=True)
|
||||
],
|
||||
show_tool_calls=True,
|
||||
description="You are an investment analyst that researches stock prices, analyst recommendations, and stock fundamentals.",
|
||||
instructions=[
|
||||
"Format your response using markdown and use tables to display data where possible."
|
||||
],
|
||||
)
|
||||
|
||||
# Input fields for the stocks to compare
|
||||
stock1 = st.text_input("Enter the first stock symbol")
|
||||
stock2 = st.text_input("Enter the second stock symbol")
|
||||
col1, col2 = st.columns(2)
|
||||
with col1:
|
||||
stock1 = st.text_input("Enter first stock symbol (e.g. AAPL)")
|
||||
with col2:
|
||||
stock2 = st.text_input("Enter second stock symbol (e.g. MSFT)")
|
||||
|
||||
if stock1 and stock2:
|
||||
# Get the response from the assistant
|
||||
query = f"Compare {stock1} to {stock2}. Use every tool you have."
|
||||
response = assistant.run(query, stream=False)
|
||||
st.write(response)
|
||||
with st.spinner(f"Analyzing {stock1} and {stock2}..."):
|
||||
query = f"Compare both the stocks - {stock1} and {stock2} and make a detailed report for an investment trying to invest and compare these stocks"
|
||||
response = assistant.run(query, stream=False)
|
||||
st.markdown(response.content)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
streamlit
|
||||
phidata
|
||||
agno
|
||||
openai
|
||||
yfinance
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ This Streamlit app is an AI-powered journalist agent that generates high-quality
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/ai_agent_tutorials/ai_journalist_agent
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
# Import the required libraries
|
||||
from textwrap import dedent
|
||||
from phi.assistant import Assistant
|
||||
from phi.tools.serpapi_tools import SerpApiTools
|
||||
from phi.tools.newspaper_toolkit import NewspaperToolkit
|
||||
from agno.agent import Agent
|
||||
from agno.tools.serpapi import SerpApiTools
|
||||
from agno.tools.newspaper4k import Newspaper4kTools
|
||||
import streamlit as st
|
||||
from phi.llm.openai import OpenAIChat
|
||||
from agno.models.openai import OpenAIChat
|
||||
|
||||
# Set up the Streamlit app
|
||||
st.title("AI Journalist Agent 🗞️")
|
||||
|
|
@ -17,10 +17,10 @@ openai_api_key = st.text_input("Enter OpenAI API Key to access GPT-4o", type="pa
|
|||
serp_api_key = st.text_input("Enter Serp API Key for Search functionality", type="password")
|
||||
|
||||
if openai_api_key and serp_api_key:
|
||||
searcher = Assistant(
|
||||
searcher = Agent(
|
||||
name="Searcher",
|
||||
role="Searches for top URLs based on a topic",
|
||||
llm=OpenAIChat(model="gpt-4o", api_key=openai_api_key),
|
||||
model=OpenAIChat(id="gpt-4o", api_key=openai_api_key),
|
||||
description=dedent(
|
||||
"""\
|
||||
You are a world-class journalist for the New York Times. Given a topic, generate a list of 3 search terms
|
||||
|
|
@ -37,10 +37,10 @@ if openai_api_key and serp_api_key:
|
|||
tools=[SerpApiTools(api_key=serp_api_key)],
|
||||
add_datetime_to_instructions=True,
|
||||
)
|
||||
writer = Assistant(
|
||||
writer = Agent(
|
||||
name="Writer",
|
||||
role="Retrieves text from URLs and writes a high-quality article",
|
||||
llm=OpenAIChat(model="gpt-4o", api_key=openai_api_key),
|
||||
model=OpenAIChat(id="gpt-4o", api_key=openai_api_key),
|
||||
description=dedent(
|
||||
"""\
|
||||
You are a senior writer for the New York Times. Given a topic and a list of URLs,
|
||||
|
|
@ -57,15 +57,14 @@ if openai_api_key and serp_api_key:
|
|||
"Focus on clarity, coherence, and overall quality.",
|
||||
"Never make up facts or plagiarize. Always provide proper attribution.",
|
||||
],
|
||||
tools=[NewspaperToolkit()],
|
||||
tools=[Newspaper4kTools()],
|
||||
add_datetime_to_instructions=True,
|
||||
add_chat_history_to_prompt=True,
|
||||
num_history_messages=3,
|
||||
markdown=True,
|
||||
)
|
||||
|
||||
editor = Assistant(
|
||||
editor = Agent(
|
||||
name="Editor",
|
||||
llm=OpenAIChat(model="gpt-4o", api_key=openai_api_key),
|
||||
model=OpenAIChat(id="gpt-4o", api_key=openai_api_key),
|
||||
team=[searcher, writer],
|
||||
description="You are a senior NYT editor. Given a topic, your goal is to write a NYT worthy article.",
|
||||
instructions=[
|
||||
|
|
@ -88,4 +87,4 @@ if openai_api_key and serp_api_key:
|
|||
with st.spinner("Processing..."):
|
||||
# Get the response from the assistant
|
||||
response = editor.run(query, stream=False)
|
||||
st.write(response)
|
||||
st.write(response.content)
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
streamlit
|
||||
phidata
|
||||
agno
|
||||
openai
|
||||
google-search-results
|
||||
newspaper3k
|
||||
newspaper4k
|
||||
lxml_html_clean
|
||||
35
ai_agent_tutorials/ai_lead_generation_agent/README.md
Normal file
35
ai_agent_tutorials/ai_lead_generation_agent/README.md
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
## 🎯 AI Lead Generation Agent - Powered by Firecrawl's Extract Endpoint
|
||||
|
||||
The AI Lead Generation Agent automates the process of finding and qualifying potential leads from Quora. It uses Firecrawl's search and the new Extract endpoint to identify relevant user profiles, extract valuable information, and organize it into a structured format in Google Sheets. This agent helps sales and marketing teams efficiently build targeted lead lists while saving hours of manual research.
|
||||
|
||||
### Features
|
||||
- **Targeted Search**: Uses Firecrawl's search endpoint to find relevant Quora URLs based on your search criteria
|
||||
- **Intelligent Extraction**: Leverages Firecrawl's new Extract endpoint to pull user information from Quora profiles
|
||||
- **Automated Processing**: Formats extracted user information into a clean, structured format
|
||||
- **Google Sheets Integration**: Automatically creates and populates Google Sheets with lead information
|
||||
- **Customizable Criteria**: Allows you to define specific search parameters to find your ideal leads for your niche
|
||||
|
||||
### How to Get Started
|
||||
1. **Clone the repository**:
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd ai_agent_tutorials/ai_lead_generation_agent
|
||||
```
|
||||
3. **Install the required packages**:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
4. **Important thing to do in composio**:
|
||||
- in the terminal, run this command: `composio add googlesheets`
|
||||
- In your compposio dashboard, create a new google sheet intergation and make sure it is active in the active integrations/connections tab
|
||||
|
||||
5. **Set up your API keys**:
|
||||
- Get your Firecrawl API key from [Firecrawl's website](https://www.firecrawl.dev/app/api-keys)
|
||||
- Get your Composio API key from [Composio's website](https://composio.ai)
|
||||
- Get your OpenAI API key from [OpenAI's website](https://platform.openai.com/api-keys)
|
||||
|
||||
6. **Run the application**:
|
||||
```bash
|
||||
streamlit run ai_lead_generation_agent.py
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
import streamlit as st
|
||||
import requests
|
||||
from agno.agent import Agent
|
||||
from agno.tools.firecrawl import FirecrawlTools
|
||||
from agno.models.openai import OpenAIChat
|
||||
from firecrawl import FirecrawlApp
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List
|
||||
from composio_phidata import Action, ComposioToolSet
|
||||
import json
|
||||
|
||||
class QuoraUserInteractionSchema(BaseModel):
|
||||
username: str = Field(description="The username of the user who posted the question or answer")
|
||||
bio: str = Field(description="The bio or description of the user")
|
||||
post_type: str = Field(description="The type of post, either 'question' or 'answer'")
|
||||
timestamp: str = Field(description="When the question or answer was posted")
|
||||
upvotes: int = Field(default=0, description="Number of upvotes received")
|
||||
links: List[str] = Field(default_factory=list, description="Any links included in the post")
|
||||
|
||||
class QuoraPageSchema(BaseModel):
|
||||
interactions: List[QuoraUserInteractionSchema] = Field(description="List of all user interactions (questions and answers) on the page")
|
||||
|
||||
def search_for_urls(company_description: str, firecrawl_api_key: str, num_links: int) -> List[str]:
|
||||
url = "https://api.firecrawl.dev/v1/search"
|
||||
headers = {
|
||||
"Authorization": f"Bearer {firecrawl_api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
query1 = f"quora websites where people are looking for {company_description} services"
|
||||
payload = {
|
||||
"query": query1,
|
||||
"limit": num_links,
|
||||
"lang": "en",
|
||||
"location": "United States",
|
||||
"timeout": 60000,
|
||||
}
|
||||
response = requests.post(url, json=payload, headers=headers)
|
||||
if response.status_code == 200:
|
||||
data = response.json()
|
||||
if data.get("success"):
|
||||
results = data.get("data", [])
|
||||
return [result["url"] for result in results]
|
||||
return []
|
||||
|
||||
def extract_user_info_from_urls(urls: List[str], firecrawl_api_key: str) -> List[dict]:
|
||||
user_info_list = []
|
||||
firecrawl_app = FirecrawlApp(api_key=firecrawl_api_key)
|
||||
|
||||
try:
|
||||
for url in urls:
|
||||
response = firecrawl_app.extract(
|
||||
[url],
|
||||
{
|
||||
'prompt': 'Extract all user information including username, bio, post type (question/answer), timestamp, upvotes, and any links from Quora posts. Focus on identifying potential leads who are asking questions or providing answers related to the topic.',
|
||||
'schema': QuoraPageSchema.model_json_schema(),
|
||||
}
|
||||
)
|
||||
|
||||
if response.get('success') and response.get('status') == 'completed':
|
||||
interactions = response.get('data', {}).get('interactions', [])
|
||||
if interactions:
|
||||
user_info_list.append({
|
||||
"website_url": url,
|
||||
"user_info": interactions
|
||||
})
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return user_info_list
|
||||
|
||||
def format_user_info_to_flattened_json(user_info_list: List[dict]) -> List[dict]:
|
||||
flattened_data = []
|
||||
|
||||
for info in user_info_list:
|
||||
website_url = info["website_url"]
|
||||
user_info = info["user_info"]
|
||||
|
||||
for interaction in user_info:
|
||||
flattened_interaction = {
|
||||
"Website URL": website_url,
|
||||
"Username": interaction.get("username", ""),
|
||||
"Bio": interaction.get("bio", ""),
|
||||
"Post Type": interaction.get("post_type", ""),
|
||||
"Timestamp": interaction.get("timestamp", ""),
|
||||
"Upvotes": interaction.get("upvotes", 0),
|
||||
"Links": ", ".join(interaction.get("links", [])),
|
||||
}
|
||||
flattened_data.append(flattened_interaction)
|
||||
|
||||
return flattened_data
|
||||
|
||||
def create_google_sheets_agent(composio_api_key: str, openai_api_key: str) -> Agent:
|
||||
composio_toolset = ComposioToolSet(api_key=composio_api_key)
|
||||
google_sheets_tool = composio_toolset.get_tools(actions=[Action.GOOGLESHEETS_SHEET_FROM_JSON])[0]
|
||||
|
||||
google_sheets_agent = Agent(
|
||||
model=OpenAIChat(id="gpt-4o-mini", api_key=openai_api_key),
|
||||
tools=[google_sheets_tool],
|
||||
show_tool_calls=True,
|
||||
system_prompt="You are an expert at creating and updating Google Sheets. You will be given user information in JSON format, and you need to write it into a new Google Sheet.",
|
||||
markdown=True
|
||||
)
|
||||
return google_sheets_agent
|
||||
|
||||
def write_to_google_sheets(flattened_data: List[dict], composio_api_key: str, openai_api_key: str) -> str:
|
||||
google_sheets_agent = create_google_sheets_agent(composio_api_key, openai_api_key)
|
||||
|
||||
try:
|
||||
message = (
|
||||
"Create a new Google Sheet with this data. "
|
||||
"The sheet should have these columns: Website URL, Username, Bio, Post Type, Timestamp, Upvotes, and Links in the same order as mentioned. "
|
||||
"Here's the data in JSON format:\n\n"
|
||||
f"{json.dumps(flattened_data, indent=2)}"
|
||||
)
|
||||
|
||||
create_sheet_response = google_sheets_agent.run(message)
|
||||
|
||||
if "https://docs.google.com/spreadsheets/d/" in create_sheet_response.content:
|
||||
google_sheets_link = create_sheet_response.content.split("https://docs.google.com/spreadsheets/d/")[1].split(" ")[0]
|
||||
return f"https://docs.google.com/spreadsheets/d/{google_sheets_link}"
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
def create_prompt_transformation_agent(openai_api_key: str) -> Agent:
|
||||
return Agent(
|
||||
model=OpenAIChat(id="gpt-4o-mini", api_key=openai_api_key),
|
||||
system_prompt="""You are an expert at transforming detailed user queries into concise company descriptions.
|
||||
Your task is to extract the core business/product focus in 3-4 words.
|
||||
|
||||
Examples:
|
||||
Input: "Generate leads looking for AI-powered customer support chatbots for e-commerce stores."
|
||||
Output: "AI customer support chatbots for e commerce"
|
||||
|
||||
Input: "Find people interested in voice cloning technology for creating audiobooks and podcasts"
|
||||
Output: "voice cloning technology"
|
||||
|
||||
Input: "Looking for users who need automated video editing software with AI capabilities"
|
||||
Output: "AI video editing software"
|
||||
|
||||
Input: "Need to find businesses interested in implementing machine learning solutions for fraud detection"
|
||||
Output: "ML fraud detection"
|
||||
|
||||
Always focus on the core product/service and keep it concise but clear.""",
|
||||
markdown=True
|
||||
)
|
||||
|
||||
def main():
|
||||
st.title("🎯 AI Lead Generation Agent")
|
||||
st.info("This firecrawl powered agent helps you generate leads from Quora by searching for relevant posts and extracting user information.")
|
||||
|
||||
with st.sidebar:
|
||||
st.header("API Keys")
|
||||
firecrawl_api_key = st.text_input("Firecrawl API Key", type="password")
|
||||
st.caption(" Get your Firecrawl API key from [Firecrawl's website](https://www.firecrawl.dev/app/api-keys)")
|
||||
openai_api_key = st.text_input("OpenAI API Key", type="password")
|
||||
st.caption(" Get your OpenAI API key from [OpenAI's website](https://platform.openai.com/api-keys)")
|
||||
composio_api_key = st.text_input("Composio API Key", type="password")
|
||||
st.caption(" Get your Composio API key from [Composio's website](https://composio.ai)")
|
||||
|
||||
num_links = st.number_input("Number of links to search", min_value=1, max_value=10, value=3)
|
||||
|
||||
if st.button("Reset"):
|
||||
st.session_state.clear()
|
||||
st.experimental_rerun()
|
||||
|
||||
user_query = st.text_area(
|
||||
"Describe what kind of leads you're looking for:",
|
||||
placeholder="e.g., Looking for users who need automated video editing software with AI capabilities",
|
||||
help="Be specific about the product/service and target audience. The AI will convert this into a focused search query."
|
||||
)
|
||||
|
||||
if st.button("Generate Leads"):
|
||||
if not all([firecrawl_api_key, openai_api_key, composio_api_key, user_query]):
|
||||
st.error("Please fill in all the API keys and describe what leads you're looking for.")
|
||||
else:
|
||||
with st.spinner("Processing your query..."):
|
||||
transform_agent = create_prompt_transformation_agent(openai_api_key)
|
||||
company_description = transform_agent.run(f"Transform this query into a concise 3-4 word company description: {user_query}")
|
||||
st.write("🎯 Searching for:", company_description.content)
|
||||
|
||||
with st.spinner("Searching for relevant URLs..."):
|
||||
urls = search_for_urls(company_description.content, firecrawl_api_key, num_links)
|
||||
|
||||
if urls:
|
||||
st.subheader("Quora Links Used:")
|
||||
for url in urls:
|
||||
st.write(url)
|
||||
|
||||
with st.spinner("Extracting user info from URLs..."):
|
||||
user_info_list = extract_user_info_from_urls(urls, firecrawl_api_key)
|
||||
|
||||
with st.spinner("Formatting user info..."):
|
||||
flattened_data = format_user_info_to_flattened_json(user_info_list)
|
||||
|
||||
with st.spinner("Writing to Google Sheets..."):
|
||||
google_sheets_link = write_to_google_sheets(flattened_data, composio_api_key, openai_api_key)
|
||||
|
||||
if google_sheets_link:
|
||||
st.success("Lead generation and data writing to Google Sheets completed successfully!")
|
||||
st.subheader("Google Sheets Link:")
|
||||
st.markdown(f"[View Google Sheet]({google_sheets_link})")
|
||||
else:
|
||||
st.error("Failed to retrieve the Google Sheets link.")
|
||||
else:
|
||||
st.warning("No relevant URLs found.")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
firecrawl-py==1.9.0
|
||||
agno
|
||||
composio-phidata
|
||||
composio==0.1.1
|
||||
pydantic==2.10.5
|
||||
streamlit
|
||||
56
ai_agent_tutorials/ai_legal_agent_team/README.md
Normal file
56
ai_agent_tutorials/ai_legal_agent_team/README.md
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# 👨⚖️ 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
|
||||
400
ai_agent_tutorials/ai_legal_agent_team/legal_agent_team.py
Normal file
400
ai_agent_tutorials/ai_legal_agent_team/legal_agent_team.py
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
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-4o"),
|
||||
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-4o"),
|
||||
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-4o"),
|
||||
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-4o"),
|
||||
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()
|
||||
|
|
@ -0,0 +1,278 @@
|
|||
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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
agno
|
||||
streamlit==1.40.2
|
||||
qdrant-client==1.12.1
|
||||
ollama==0.4.4
|
||||
6
ai_agent_tutorials/ai_legal_agent_team/requirements.txt
Normal file
6
ai_agent_tutorials/ai_legal_agent_team/requirements.txt
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
agno
|
||||
streamlit==1.40.2
|
||||
qdrant-client==1.12.1
|
||||
openai
|
||||
pypdf
|
||||
duckduckgo-search
|
||||
66
ai_agent_tutorials/ai_medical_imaging_agent/README.md
Normal file
66
ai_agent_tutorials/ai_medical_imaging_agent/README.md
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
# 🩻 Medical Imaging Diagnosis Agent
|
||||
|
||||
A Medical Imaging Diagnosis Agent build on agno powered by Gemini 2.0 Flash that provides AI-assisted analysis of medical images of various scans. The agent acts as a medical imaging diagnosis expert to analyze various types of medical images and videos, providing detailed diagnostic insights and explanations.
|
||||
|
||||
## Features
|
||||
|
||||
- **Comprehensive Image Analysis**
|
||||
- Image Type Identification (X-ray, MRI, CT scan, ultrasound)
|
||||
- Anatomical Region Detection
|
||||
- Key Findings and Observations
|
||||
- Potential Abnormalities Detection
|
||||
- Image Quality Assessment
|
||||
- Research and Reference
|
||||
|
||||
## 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_medical_imaging_agent
|
||||
|
||||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. **Configure API Keys**
|
||||
- Get Google API key from [Google AI Studio](https://aistudio.google.com)
|
||||
|
||||
3. **Run the Application**
|
||||
```bash
|
||||
streamlit run ai_medical_imaging.py
|
||||
```
|
||||
|
||||
## Analysis Components
|
||||
|
||||
- **Image Type and Region**
|
||||
- Identifies imaging modality
|
||||
- Specifies anatomical region
|
||||
|
||||
- **Key Findings**
|
||||
- Systematic listing of observations
|
||||
- Detailed appearance descriptions
|
||||
- Abnormality highlighting
|
||||
|
||||
- **Diagnostic Assessment**
|
||||
- Potential diagnoses ranking
|
||||
- Differential diagnoses
|
||||
- Severity assessment
|
||||
|
||||
- **Patient-Friendly Explanations**
|
||||
- Simplified terminology
|
||||
- Detailed first-principles explanations
|
||||
- Visual reference points
|
||||
|
||||
## Notes
|
||||
|
||||
- Uses Gemini 2.0 Flash for analysis
|
||||
- Requires stable internet connection
|
||||
- Free API usage costs - 1,500 free requests per day by google!
|
||||
- For educational and development purposes only
|
||||
- Not a replacement for professional medical diagnosis
|
||||
|
||||
## Disclaimer
|
||||
|
||||
This tool is for educational and informational purposes only. All analyses should be reviewed by qualified healthcare professionals. Do not make medical decisions based solely on this analysis.
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
import os
|
||||
from PIL import Image as PILImage
|
||||
from agno.agent import Agent
|
||||
from agno.models.google import Gemini
|
||||
import streamlit as st
|
||||
from agno.tools.duckduckgo import DuckDuckGoTools
|
||||
from agno.media import Image as AgnoImage
|
||||
|
||||
if "GOOGLE_API_KEY" not in st.session_state:
|
||||
st.session_state.GOOGLE_API_KEY = None
|
||||
|
||||
with st.sidebar:
|
||||
st.title("ℹ️ Configuration")
|
||||
|
||||
if not st.session_state.GOOGLE_API_KEY:
|
||||
api_key = st.text_input(
|
||||
"Enter your Google API Key:",
|
||||
type="password"
|
||||
)
|
||||
st.caption(
|
||||
"Get your API key from [Google AI Studio]"
|
||||
"(https://aistudio.google.com/apikey) 🔑"
|
||||
)
|
||||
if api_key:
|
||||
st.session_state.GOOGLE_API_KEY = api_key
|
||||
st.success("API Key saved!")
|
||||
st.rerun()
|
||||
else:
|
||||
st.success("API Key is configured")
|
||||
if st.button("🔄 Reset API Key"):
|
||||
st.session_state.GOOGLE_API_KEY = None
|
||||
st.rerun()
|
||||
|
||||
st.info(
|
||||
"This tool provides AI-powered analysis of medical imaging data using "
|
||||
"advanced computer vision and radiological expertise."
|
||||
)
|
||||
st.warning(
|
||||
"⚠DISCLAIMER: This tool is for educational and informational purposes only. "
|
||||
"All analyses should be reviewed by qualified healthcare professionals. "
|
||||
"Do not make medical decisions based solely on this analysis."
|
||||
)
|
||||
|
||||
medical_agent = Agent(
|
||||
model=Gemini(
|
||||
id="gemini-2.0-flash",
|
||||
api_key=st.session_state.GOOGLE_API_KEY
|
||||
),
|
||||
tools=[DuckDuckGoTools()],
|
||||
markdown=True
|
||||
) if st.session_state.GOOGLE_API_KEY else None
|
||||
|
||||
if not medical_agent:
|
||||
st.warning("Please configure your API key in the sidebar to continue")
|
||||
|
||||
# Medical Analysis Query
|
||||
query = """
|
||||
You are a highly skilled medical imaging expert with extensive knowledge in radiology and diagnostic imaging. Analyze the patient's medical image and structure your response as follows:
|
||||
|
||||
### 1. Image Type & Region
|
||||
- Specify imaging modality (X-ray/MRI/CT/Ultrasound/etc.)
|
||||
- Identify the patient's anatomical region and positioning
|
||||
- Comment on image quality and technical adequacy
|
||||
|
||||
### 2. Key Findings
|
||||
- List primary observations systematically
|
||||
- Note any abnormalities in the patient's imaging with precise descriptions
|
||||
- Include measurements and densities where relevant
|
||||
- Describe location, size, shape, and characteristics
|
||||
- Rate severity: Normal/Mild/Moderate/Severe
|
||||
|
||||
### 3. Diagnostic Assessment
|
||||
- Provide primary diagnosis with confidence level
|
||||
- List differential diagnoses in order of likelihood
|
||||
- Support each diagnosis with observed evidence from the patient's imaging
|
||||
- Note any critical or urgent findings
|
||||
|
||||
### 4. Patient-Friendly Explanation
|
||||
- Explain the findings in simple, clear language that the patient can understand
|
||||
- Avoid medical jargon or provide clear definitions
|
||||
- Include visual analogies if helpful
|
||||
- Address common patient concerns related to these findings
|
||||
|
||||
### 5. Research Context
|
||||
IMPORTANT: Use the DuckDuckGo search tool to:
|
||||
- Find recent medical literature about similar cases
|
||||
- Search for standard treatment protocols
|
||||
- Provide a list of relevant medical links of them too
|
||||
- Research any relevant technological advances
|
||||
- Include 2-3 key references to support your analysis
|
||||
|
||||
Format your response using clear markdown headers and bullet points. Be concise yet thorough.
|
||||
"""
|
||||
|
||||
st.title("🏥 Medical Imaging Diagnosis Agent")
|
||||
st.write("Upload a medical image for professional analysis")
|
||||
|
||||
# Create containers for better organization
|
||||
upload_container = st.container()
|
||||
image_container = st.container()
|
||||
analysis_container = st.container()
|
||||
|
||||
with upload_container:
|
||||
uploaded_file = st.file_uploader(
|
||||
"Upload Medical Image",
|
||||
type=["jpg", "jpeg", "png", "dicom"],
|
||||
help="Supported formats: JPG, JPEG, PNG, DICOM"
|
||||
)
|
||||
|
||||
if uploaded_file is not None:
|
||||
with image_container:
|
||||
col1, col2, col3 = st.columns([1, 2, 1])
|
||||
with col2:
|
||||
image = PILImage.open(uploaded_file)
|
||||
width, height = image.size
|
||||
aspect_ratio = width / height
|
||||
new_width = 500
|
||||
new_height = int(new_width / aspect_ratio)
|
||||
resized_image = image.resize((new_width, new_height))
|
||||
|
||||
st.image(
|
||||
resized_image,
|
||||
caption="Uploaded Medical Image",
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
analyze_button = st.button(
|
||||
"🔍 Analyze Image",
|
||||
type="primary",
|
||||
use_container_width=True
|
||||
)
|
||||
|
||||
with analysis_container:
|
||||
if analyze_button:
|
||||
with st.spinner("🔄 Analyzing image... Please wait."):
|
||||
try:
|
||||
temp_path = "temp_resized_image.png"
|
||||
resized_image.save(temp_path)
|
||||
|
||||
# Create AgnoImage object
|
||||
agno_image = AgnoImage(filepath=temp_path) # Adjust if constructor differs
|
||||
|
||||
# Run analysis
|
||||
response = medical_agent.run(query, images=[agno_image])
|
||||
st.markdown("### 📋 Analysis Results")
|
||||
st.markdown("---")
|
||||
st.markdown(response.content)
|
||||
st.markdown("---")
|
||||
st.caption(
|
||||
"Note: This analysis is generated by AI and should be reviewed by "
|
||||
"a qualified healthcare professional."
|
||||
)
|
||||
except Exception as e:
|
||||
st.error(f"Analysis error: {e}")
|
||||
else:
|
||||
st.info("👆 Please upload a medical image to begin analysis")
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
streamlit==1.40.2
|
||||
agno
|
||||
Pillow==10.0.0
|
||||
duckduckgo-search==6.4.1
|
||||
google-generativeai==0.8.3
|
||||
|
|
@ -14,6 +14,7 @@ This Streamlit application leverages multiple AI agents to create comprehensive
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/ai_agent_tutorials/ai_meeting_agent
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import streamlit as st
|
||||
from crewai import Agent, Task, Crew, Process
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
from crewai import Agent, Task, Crew, LLM
|
||||
from crewai.process import Process
|
||||
from crewai_tools import SerperDevTool
|
||||
import os
|
||||
|
||||
|
|
@ -11,20 +10,16 @@ st.title("AI Meeting Preparation Agent 📝")
|
|||
|
||||
# Sidebar for API keys
|
||||
st.sidebar.header("API Keys")
|
||||
openai_api_key = st.sidebar.text_input("OpenAI API Key", type="password")
|
||||
anthropic_api_key = st.sidebar.text_input("Anthropic API Key", type="password")
|
||||
serper_api_key = st.sidebar.text_input("Serper API Key", type="password")
|
||||
|
||||
# Check if all API keys are set
|
||||
if openai_api_key and anthropic_api_key and serper_api_key:
|
||||
# Set API keys as environment variables
|
||||
os.environ["OPENAI_API_KEY"] = openai_api_key
|
||||
if anthropic_api_key and serper_api_key:
|
||||
# # Set API keys as environment variables
|
||||
os.environ["ANTHROPIC_API_KEY"] = anthropic_api_key
|
||||
os.environ["SERPER_API_KEY"] = serper_api_key
|
||||
|
||||
# Initialize the AI models and tools
|
||||
gpt4 = ChatOpenAI(model_name="gpt-4o-mini")
|
||||
claude = ChatAnthropic(model_name="claude-3-5-sonnet-20240620")
|
||||
claude = LLM(model="claude-3-5-sonnet-20240620", temperature= 0.7, api_key=anthropic_api_key)
|
||||
search_tool = SerperDevTool()
|
||||
|
||||
# Input fields
|
||||
|
|
@ -41,7 +36,7 @@ if openai_api_key and anthropic_api_key and serper_api_key:
|
|||
backstory='You are an expert at quickly understanding complex business contexts and identifying critical information.',
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
llm=gpt4,
|
||||
llm=claude,
|
||||
tools=[search_tool]
|
||||
)
|
||||
|
||||
|
|
@ -51,7 +46,7 @@ if openai_api_key and anthropic_api_key and serper_api_key:
|
|||
backstory='You are a seasoned industry analyst with a knack for spotting emerging trends and opportunities.',
|
||||
verbose=True,
|
||||
allow_delegation=False,
|
||||
llm=gpt4,
|
||||
llm=claude,
|
||||
tools=[search_tool]
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
# 🥸 AI Meme Generator Agent - Browser Use
|
||||
|
||||
The AI Meme Generator Agent is a powerful browser automation tool that creates memes using AI agents. This app combines multi-LLM capabilities with automated browser interactions to generate memes based on text prompts through direct website manipulation.
|
||||
|
||||
## Features
|
||||
|
||||
- **Multi-LLM Support**
|
||||
- Claude 3.5 Sonnet (Anthropic)
|
||||
- GPT-4o (OpenAI)
|
||||
- Deepseek v3 (Deepseek)
|
||||
- Automatic model switching with API key validation
|
||||
|
||||
- **Browser Automation**:
|
||||
- Direct interaction with imgflip.com meme templates
|
||||
- Automated search for relevant meme formats
|
||||
- Dynamic text insertion for top/bottom captions
|
||||
- Image link extraction from generated memes
|
||||
|
||||
- **Smart Generation Workflow**:
|
||||
- Action verb extraction from prompts
|
||||
- Metaphorical template matching
|
||||
- Multi-step quality validation
|
||||
- Automatic retry mechanism for failed generations
|
||||
|
||||
- **User-Friendly Interface**:
|
||||
- Model configuration sidebar
|
||||
- API key management
|
||||
- Direct meme preview with clickable links
|
||||
- Responsive error handling
|
||||
|
||||
|
||||
API keys required:
|
||||
- **Anthropic** (for Claude)
|
||||
- **Deepseek**
|
||||
- **OpenAI** (for GPT-4o)
|
||||
|
||||
## How to Run
|
||||
|
||||
1. **Clone the Repository**:
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd ai_agent_tutorials/ai_meme_generator_browseruse
|
||||
```
|
||||
2. **Install the dependencies**:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
3. **Run the Streamlit app**:
|
||||
```bash
|
||||
streamlit run ai_meme_generator.py
|
||||
```
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
import asyncio
|
||||
import streamlit as st
|
||||
from browser_use import Agent, SystemPrompt
|
||||
from langchain_openai import ChatOpenAI
|
||||
from langchain_anthropic import ChatAnthropic
|
||||
from langchain_core.messages import HumanMessage
|
||||
import re
|
||||
|
||||
async def generate_meme(query: str, model_choice: str, api_key: str) -> None:
|
||||
# Initialize the appropriate LLM based on user selection
|
||||
if model_choice == "Claude":
|
||||
llm = ChatAnthropic(
|
||||
model="claude-3-5-sonnet-20241022",
|
||||
api_key=api_key
|
||||
)
|
||||
elif model_choice == "Deepseek":
|
||||
llm = ChatOpenAI(
|
||||
base_url='https://api.deepseek.com/v1',
|
||||
model='deepseek-chat',
|
||||
api_key=api_key,
|
||||
temperature=0.3
|
||||
)
|
||||
else: # OpenAI
|
||||
llm = ChatOpenAI(
|
||||
model="gpt-4o",
|
||||
api_key=api_key,
|
||||
temperature=0.0
|
||||
)
|
||||
|
||||
task_description = (
|
||||
"You are a meme generator expert. You are given a query and you need to generate a meme for it.\n"
|
||||
"1. Go to https://imgflip.com/memetemplates \n"
|
||||
"2. Click on the Search bar in the middle and search for ONLY ONE MAIN ACTION VERB (like 'bully', 'laugh', 'cry') in this query: '{0}'\n"
|
||||
"3. Choose any meme template that metaphorically fits the meme topic: '{0}'\n"
|
||||
" by clicking on the 'Add Caption' button below it\n"
|
||||
"4. Write a Top Text (setup/context) and Bottom Text (punchline/outcome) related to '{0}'.\n"
|
||||
"5. Check the preview making sure it is funny and a meaningful meme. Adjust text directly if needed. \n"
|
||||
"6. Look at the meme and text on it, if it doesnt make sense, PLEASE retry by filling the text boxes with different text. \n"
|
||||
"7. Click on the Generate meme button to generate the meme\n"
|
||||
"8. Copy the image link and give it as the output\n"
|
||||
).format(query)
|
||||
|
||||
agent = Agent(
|
||||
task=task_description,
|
||||
llm=llm,
|
||||
max_actions_per_step=5,
|
||||
max_failures=25,
|
||||
use_vision=(model_choice != "Deepseek")
|
||||
)
|
||||
|
||||
history = await agent.run()
|
||||
|
||||
# Extract final result from agent history
|
||||
final_result = history.final_result()
|
||||
|
||||
# Use regex to find the meme URL in the result
|
||||
url_match = re.search(r'https://imgflip\.com/i/(\w+)', final_result)
|
||||
if url_match:
|
||||
meme_id = url_match.group(1)
|
||||
return f"https://i.imgflip.com/{meme_id}.jpg"
|
||||
return None
|
||||
|
||||
def main():
|
||||
# Custom CSS styling
|
||||
|
||||
|
||||
st.title("🥸 AI Meme Generator Agent - Browser Use")
|
||||
st.info("This AI browser agent does browser automation to generate memes based on your input with browser use. Please enter your API key and describe the meme you want to generate.")
|
||||
|
||||
# Sidebar configuration
|
||||
with st.sidebar:
|
||||
st.markdown('<p class="sidebar-header">⚙️ Model Configuration</p>', unsafe_allow_html=True)
|
||||
|
||||
# Model selection
|
||||
model_choice = st.selectbox(
|
||||
"Select AI Model",
|
||||
["Claude", "Deepseek", "OpenAI"],
|
||||
index=0,
|
||||
help="Choose which LLM to use for meme generation"
|
||||
)
|
||||
|
||||
# API key input based on model selection
|
||||
api_key = ""
|
||||
if model_choice == "Claude":
|
||||
api_key = st.text_input("Claude API Key", type="password",
|
||||
help="Get your API key from https://console.anthropic.com")
|
||||
elif model_choice == "Deepseek":
|
||||
api_key = st.text_input("Deepseek API Key", type="password",
|
||||
help="Get your API key from https://platform.deepseek.com")
|
||||
else:
|
||||
api_key = st.text_input("OpenAI API Key", type="password",
|
||||
help="Get your API key from https://platform.openai.com")
|
||||
|
||||
# Main content area
|
||||
st.markdown('<p class="header-text">🎨 Describe Your Meme Concept</p>', unsafe_allow_html=True)
|
||||
|
||||
query = st.text_input(
|
||||
"Meme Idea Input",
|
||||
placeholder="Example: 'Ilya's SSI quietly looking at the OpenAI vs Deepseek debate while diligently working on ASI'",
|
||||
label_visibility="collapsed"
|
||||
)
|
||||
|
||||
if st.button("Generate Meme 🚀"):
|
||||
if not api_key:
|
||||
st.warning(f"Please provide the {model_choice} API key")
|
||||
st.stop()
|
||||
if not query:
|
||||
st.warning("Please enter a meme idea")
|
||||
st.stop()
|
||||
|
||||
with st.spinner(f"🧠 {model_choice} is generating your meme..."):
|
||||
try:
|
||||
meme_url = asyncio.run(generate_meme(query, model_choice, api_key))
|
||||
|
||||
if meme_url:
|
||||
st.success("✅ Meme Generated Successfully!")
|
||||
st.image(meme_url, caption="Generated Meme Preview", use_container_width=True)
|
||||
st.markdown(f"""
|
||||
**Direct Link:** [Open in ImgFlip]({meme_url})
|
||||
**Embed URL:** `{meme_url}`
|
||||
""")
|
||||
else:
|
||||
st.error("❌ Failed to generate meme. Please try again with a different prompt.")
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"Error: {str(e)}")
|
||||
st.info("💡 If using OpenAI, ensure your account has GPT-4o access")
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
streamlit
|
||||
browser-use==0.1.26
|
||||
playwright==1.49.1
|
||||
langchain-openai
|
||||
langchain-anthropic
|
||||
asyncio
|
||||
73
ai_agent_tutorials/ai_mental_wellbeing_agent/README.md
Normal file
73
ai_agent_tutorials/ai_mental_wellbeing_agent/README.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# AI Mental Wellbeing Agent Team 🧠
|
||||
|
||||
The AI Mental Wellbeing Agent Team is a supportive mental health assessment and guidance system powered by [AG2](https://github.com/ag2ai/ag2?tab=readme-ov-file)(formerly AutoGen)'s AI Agent framework. This app provides personalized mental health support through the coordination of specialized AI agents, each focusing on different aspects of mental health care based on user inputs such as emotional state, stress levels, sleep patterns, and current symptoms. This is built on AG2's new swarm feature run through initiate_swarm_chat() method.
|
||||
|
||||
## Features
|
||||
|
||||
- **Specialized Mental Wellbeing Support Team**
|
||||
- 🧠 **Assessment Agent**: Analyzes emotional state and psychological needs with clinical precision and empathy
|
||||
- 🎯 **Action Agent**: Creates immediate action plans and connects users with appropriate resources
|
||||
- 🔄 **Follow-up Agent**: Designs long-term support strategies and prevention plans
|
||||
|
||||
- **Comprehensive Mental Wellbeing Support**:
|
||||
- Detailed psychological assessment
|
||||
- Immediate coping strategies
|
||||
- Resource recommendations
|
||||
- Long-term support planning
|
||||
- Crisis prevention strategies
|
||||
- Progress monitoring systems
|
||||
|
||||
- **Customizable Input Parameters**:
|
||||
- Current emotional state
|
||||
- Sleep patterns
|
||||
- Stress levels
|
||||
- Support system information
|
||||
- Recent life changes
|
||||
- Current symptoms
|
||||
|
||||
- **Interactive Results**:
|
||||
- Real-time assessment summaries
|
||||
- Detailed recommendations in expandable sections
|
||||
- Clear action steps and resources
|
||||
- Long-term support strategies
|
||||
|
||||
## 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_mental_wellbeing_agent
|
||||
```
|
||||
|
||||
2. **Install Dependencies**:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. **Create Environment File**:
|
||||
Create a `.env` file in the project directory:
|
||||
```bash
|
||||
echo "AUTOGEN_USE_DOCKER=0" > .env
|
||||
```
|
||||
This disables Docker requirement for code execution in AutoGen.
|
||||
|
||||
4. **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
|
||||
|
||||
5. **Run the Streamlit App**:
|
||||
```bash
|
||||
streamlit run ai_mental_wellbeing_agent.py
|
||||
```
|
||||
|
||||
|
||||
## ⚠️ Important Notice
|
||||
|
||||
This application is a supportive tool and does not replace professional mental health care. If you're experiencing thoughts of self-harm or severe crisis:
|
||||
|
||||
- Call National Crisis Hotline: 988
|
||||
- Call Emergency Services: 911
|
||||
- Seek immediate professional help
|
||||
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
import streamlit as st
|
||||
from autogen import (SwarmAgent, SwarmResult, initiate_swarm_chat, OpenAIWrapper,AFTER_WORK,UPDATE_SYSTEM_MESSAGE)
|
||||
import os
|
||||
|
||||
os.environ["AUTOGEN_USE_DOCKER"] = "0"
|
||||
|
||||
if 'output' not in st.session_state:
|
||||
st.session_state.output = {
|
||||
'assessment': '',
|
||||
'action': '',
|
||||
'followup': ''
|
||||
}
|
||||
|
||||
st.sidebar.title("OpenAI API Key")
|
||||
api_key = st.sidebar.text_input("Enter your OpenAI API Key", type="password")
|
||||
|
||||
st.sidebar.warning("""
|
||||
## ⚠️ Important Notice
|
||||
|
||||
This application is a supportive tool and does not replace professional mental health care. If you're experiencing thoughts of self-harm or severe crisis:
|
||||
|
||||
- Call National Crisis Hotline: 988
|
||||
- Call Emergency Services: 911
|
||||
- Seek immediate professional help
|
||||
""")
|
||||
|
||||
st.title("🧠 Mental Wellbeing Agent")
|
||||
|
||||
st.info("""
|
||||
**Meet Your Mental Wellbeing Agent Team:**
|
||||
|
||||
🧠 **Assessment Agent** - Analyzes your situation and emotional needs
|
||||
🎯 **Action Agent** - Creates immediate action plan and connects you with resources
|
||||
🔄 **Follow-up Agent** - Designs your long-term support strategy
|
||||
""")
|
||||
|
||||
st.subheader("Personal Information")
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
mental_state = st.text_area("How have you been feeling recently?",
|
||||
placeholder="Describe your emotional state, thoughts, or concerns...")
|
||||
sleep_pattern = st.select_slider(
|
||||
"Sleep Pattern (hours per night)",
|
||||
options=[f"{i}" for i in range(0, 13)],
|
||||
value="7"
|
||||
)
|
||||
|
||||
with col2:
|
||||
stress_level = st.slider("Current Stress Level (1-10)", 1, 10, 5)
|
||||
support_system = st.multiselect(
|
||||
"Current Support System",
|
||||
["Family", "Friends", "Therapist", "Support Groups", "None"]
|
||||
)
|
||||
|
||||
recent_changes = st.text_area(
|
||||
"Any significant life changes or events recently?",
|
||||
placeholder="Job changes, relationships, losses, etc..."
|
||||
)
|
||||
|
||||
current_symptoms = st.multiselect(
|
||||
"Current Symptoms",
|
||||
["Anxiety", "Depression", "Insomnia", "Fatigue", "Loss of Interest",
|
||||
"Difficulty Concentrating", "Changes in Appetite", "Social Withdrawal",
|
||||
"Mood Swings", "Physical Discomfort"]
|
||||
)
|
||||
|
||||
if st.button("Get Support Plan"):
|
||||
if not api_key:
|
||||
st.error("Please enter your OpenAI API key.")
|
||||
else:
|
||||
with st.spinner('🤖 AI Agents are analyzing your situation...'):
|
||||
try:
|
||||
task = f"""
|
||||
Create a comprehensive mental health support plan based on:
|
||||
|
||||
Emotional State: {mental_state}
|
||||
Sleep: {sleep_pattern} hours per night
|
||||
Stress Level: {stress_level}/10
|
||||
Support System: {', '.join(support_system) if support_system else 'None reported'}
|
||||
Recent Changes: {recent_changes}
|
||||
Current Symptoms: {', '.join(current_symptoms) if current_symptoms else 'None reported'}
|
||||
"""
|
||||
|
||||
system_messages = {
|
||||
"assessment_agent": """
|
||||
You are an experienced mental health professional speaking directly to the user. Your task is to:
|
||||
1. Create a safe space by acknowledging their courage in seeking support
|
||||
2. Analyze their emotional state with clinical precision and genuine empathy
|
||||
3. Ask targeted follow-up questions to understand their full situation
|
||||
4. Identify patterns in their thoughts, behaviors, and relationships
|
||||
5. Assess risk levels with validated screening approaches
|
||||
6. Help them understand their current mental health in accessible language
|
||||
7. Validate their experiences without minimizing or catastrophizing
|
||||
|
||||
Always use "you" and "your" when addressing the user. Blend clinical expertise with genuine warmth and never rush to conclusions.
|
||||
""",
|
||||
|
||||
"action_agent": """
|
||||
You are a crisis intervention and resource specialist speaking directly to the user. Your task is to:
|
||||
1. Provide immediate evidence-based coping strategies tailored to their specific situation
|
||||
2. Prioritize interventions based on urgency and effectiveness
|
||||
3. Connect them with appropriate mental health services while acknowledging barriers (cost, access, stigma)
|
||||
4. Create a concrete daily wellness plan with specific times and activities
|
||||
5. Suggest specific support communities with details on how to join
|
||||
6. Balance crisis resources with empowerment techniques
|
||||
7. Teach simple self-regulation techniques they can use immediately
|
||||
|
||||
Focus on practical, achievable steps that respect their current capacity and energy levels. Provide options ranging from minimal effort to more involved actions.
|
||||
""",
|
||||
|
||||
"followup_agent": """
|
||||
You are a mental health recovery planner speaking directly to the user. Your task is to:
|
||||
1. Design a personalized long-term support strategy with milestone markers
|
||||
2. Create a progress monitoring system that matches their preferences and habits
|
||||
3. Develop specific relapse prevention strategies based on their unique triggers
|
||||
4. Establish a support network mapping exercise to identify existing resources
|
||||
5. Build a graduated self-care routine that evolves with their recovery
|
||||
6. Plan for setbacks with self-compassion techniques
|
||||
7. Set up a maintenance schedule with clear check-in mechanisms
|
||||
|
||||
Focus on building sustainable habits that integrate with their lifestyle and values. Emphasize progress over perfection and teach skills for self-directed care.
|
||||
"""
|
||||
}
|
||||
|
||||
llm_config = {
|
||||
"config_list": [{"model": "gpt-4o", "api_key": api_key}]
|
||||
}
|
||||
|
||||
context_variables = {
|
||||
"assessment": None,
|
||||
"action": None,
|
||||
"followup": None,
|
||||
}
|
||||
|
||||
def update_assessment_overview(assessment_summary: str, context_variables: dict) -> SwarmResult:
|
||||
context_variables["assessment"] = assessment_summary
|
||||
st.sidebar.success('Assessment: ' + assessment_summary)
|
||||
return SwarmResult(agent="action_agent", context_variables=context_variables)
|
||||
|
||||
def update_action_overview(action_summary: str, context_variables: dict) -> SwarmResult:
|
||||
context_variables["action"] = action_summary
|
||||
st.sidebar.success('Action Plan: ' + action_summary)
|
||||
return SwarmResult(agent="followup_agent", context_variables=context_variables)
|
||||
|
||||
def update_followup_overview(followup_summary: str, context_variables: dict) -> SwarmResult:
|
||||
context_variables["followup"] = followup_summary
|
||||
st.sidebar.success('Follow-up Strategy: ' + followup_summary)
|
||||
return SwarmResult(agent="assessment_agent", context_variables=context_variables)
|
||||
|
||||
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"}}
|
||||
else:
|
||||
agent.llm_config["tools"] = None
|
||||
agent.llm_config['tool_choice'] = None
|
||||
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 reponse with: '## {current_gen.capitalize()} Design'."
|
||||
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:"
|
||||
for k, v in agent._context_variables.items():
|
||||
if v is not None:
|
||||
system_prompt += f"\n{k.capitalize()} Summary:\n{v}"
|
||||
|
||||
agent.client = OpenAIWrapper(**agent.llm_config)
|
||||
return system_prompt
|
||||
|
||||
state_update = UPDATE_SYSTEM_MESSAGE(update_system_message_func)
|
||||
|
||||
assessment_agent = SwarmAgent(
|
||||
"assessment_agent",
|
||||
llm_config=llm_config,
|
||||
functions=update_assessment_overview,
|
||||
update_agent_state_before_reply=[state_update]
|
||||
)
|
||||
|
||||
action_agent = SwarmAgent(
|
||||
"action_agent",
|
||||
llm_config=llm_config,
|
||||
functions=update_action_overview,
|
||||
update_agent_state_before_reply=[state_update]
|
||||
)
|
||||
|
||||
followup_agent = SwarmAgent(
|
||||
"followup_agent",
|
||||
llm_config=llm_config,
|
||||
functions=update_followup_overview,
|
||||
update_agent_state_before_reply=[state_update]
|
||||
)
|
||||
|
||||
assessment_agent.register_hand_off(AFTER_WORK(action_agent))
|
||||
action_agent.register_hand_off(AFTER_WORK(followup_agent))
|
||||
followup_agent.register_hand_off(AFTER_WORK(assessment_agent))
|
||||
|
||||
result, _, _ = initiate_swarm_chat(
|
||||
initial_agent=assessment_agent,
|
||||
agents=[assessment_agent, action_agent, followup_agent],
|
||||
user_agent=None,
|
||||
messages=task,
|
||||
max_rounds=13,
|
||||
)
|
||||
|
||||
st.session_state.output = {
|
||||
'assessment': result.chat_history[-3]['content'],
|
||||
'action': result.chat_history[-2]['content'],
|
||||
'followup': result.chat_history[-1]['content']
|
||||
}
|
||||
|
||||
with st.expander("Situation Assessment"):
|
||||
st.markdown(st.session_state.output['assessment'])
|
||||
|
||||
with st.expander("Action Plan & Resources"):
|
||||
st.markdown(st.session_state.output['action'])
|
||||
|
||||
with st.expander("Long-term Support Strategy"):
|
||||
st.markdown(st.session_state.output['followup'])
|
||||
|
||||
st.success('✨ Mental health support plan generated successfully!')
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"An error occurred: {str(e)}")
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
autogen-agentchat
|
||||
autogen-ext
|
||||
pyautogen
|
||||
streamlit
|
||||
|
|
@ -12,6 +12,7 @@ This Streamlit app is an AI-powered movie production assistant that helps bring
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/ai_agent_tutorials/ai_movie_production_agent
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
# Import the required libraries
|
||||
import streamlit as st
|
||||
from phi.assistant import Assistant
|
||||
from phi.tools.serpapi_tools import SerpApiTools
|
||||
from phi.llm.anthropic import Claude
|
||||
from agno.agent import Agent
|
||||
from agno.tools.serpapi import SerpApiTools
|
||||
from agno.models.anthropic import Claude
|
||||
from textwrap import dedent
|
||||
|
||||
# Set up the Streamlit app
|
||||
|
|
@ -15,9 +15,9 @@ anthropic_api_key = st.text_input("Enter Anthropic API Key to access Claude Sonn
|
|||
serp_api_key = st.text_input("Enter Serp API Key for Search functionality", type="password")
|
||||
|
||||
if anthropic_api_key and serp_api_key:
|
||||
script_writer = Assistant(
|
||||
script_writer = Agent(
|
||||
name="ScriptWriter",
|
||||
llm=Claude(model="claude-3-5-sonnet-20240620", api_key=anthropic_api_key),
|
||||
model=Claude(id="claude-3-5-sonnet-20240620", api_key=anthropic_api_key),
|
||||
description=dedent(
|
||||
"""\
|
||||
You are an expert screenplay writer. Given a movie idea and genre,
|
||||
|
|
@ -31,9 +31,9 @@ if anthropic_api_key and serp_api_key:
|
|||
],
|
||||
)
|
||||
|
||||
casting_director = Assistant(
|
||||
casting_director = Agent(
|
||||
name="CastingDirector",
|
||||
llm=Claude(model="claude-3-5-sonnet-20240620", api_key=anthropic_api_key),
|
||||
model=Claude(id="claude-3-5-sonnet-20240620", api_key=anthropic_api_key),
|
||||
description=dedent(
|
||||
"""\
|
||||
You are a talented casting director. Given a script outline and character descriptions,
|
||||
|
|
@ -49,9 +49,9 @@ if anthropic_api_key and serp_api_key:
|
|||
tools=[SerpApiTools(api_key=serp_api_key)],
|
||||
)
|
||||
|
||||
movie_producer = Assistant(
|
||||
movie_producer = Agent(
|
||||
name="MovieProducer",
|
||||
llm=Claude(model="claude-3-5-sonnet-20240620", api_key=anthropic_api_key),
|
||||
model=Claude(id="claude-3-5-sonnet-20240620", api_key=anthropic_api_key),
|
||||
team=[script_writer, casting_director],
|
||||
description="Experienced movie producer overseeing script and casting.",
|
||||
instructions=[
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
streamlit
|
||||
phidata
|
||||
agno
|
||||
anthropic
|
||||
google-search-results
|
||||
lxml_html_clean
|
||||
|
|
@ -12,6 +12,7 @@ This Streamlit app is an AI-powered personal finance planner that generates pers
|
|||
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/ai_agent_tutorials/ai_personal_finance_agent
|
||||
```
|
||||
2. Install the required dependencies:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
from textwrap import dedent
|
||||
from phi.assistant import Assistant
|
||||
from phi.tools.serpapi_tools import SerpApiTools
|
||||
from agno.agent import Agent
|
||||
from agno.tools.serpapi import SerpApiTools
|
||||
import streamlit as st
|
||||
from phi.llm.openai import OpenAIChat
|
||||
from agno.models.openai import OpenAIChat
|
||||
|
||||
# Set up the Streamlit app
|
||||
st.title("AI Personal Finance Planner 💰")
|
||||
|
|
@ -15,10 +15,10 @@ openai_api_key = st.text_input("Enter OpenAI API Key to access GPT-4o", type="pa
|
|||
serp_api_key = st.text_input("Enter Serp API Key for Search functionality", type="password")
|
||||
|
||||
if openai_api_key and serp_api_key:
|
||||
researcher = Assistant(
|
||||
researcher = Agent(
|
||||
name="Researcher",
|
||||
role="Searches for financial advice, investment opportunities, and savings strategies based on user preferences",
|
||||
llm=OpenAIChat(model="gpt-4o", api_key=openai_api_key),
|
||||
model=OpenAIChat(id="gpt-4o", api_key=openai_api_key),
|
||||
description=dedent(
|
||||
"""\
|
||||
You are a world-class financial researcher. Given a user's financial goals and current financial situation,
|
||||
|
|
@ -35,10 +35,10 @@ if openai_api_key and serp_api_key:
|
|||
tools=[SerpApiTools(api_key=serp_api_key)],
|
||||
add_datetime_to_instructions=True,
|
||||
)
|
||||
planner = Assistant(
|
||||
planner = Agent(
|
||||
name="Planner",
|
||||
role="Generates a personalized financial plan based on user preferences and research results",
|
||||
llm=OpenAIChat(model="gpt-4o", api_key=openai_api_key),
|
||||
model=OpenAIChat(id="gpt-4o", api_key=openai_api_key),
|
||||
description=dedent(
|
||||
"""\
|
||||
You are a senior financial planner. Given a user's financial goals, current financial situation, and a list of research results,
|
||||
|
|
@ -54,8 +54,6 @@ if openai_api_key and serp_api_key:
|
|||
"Never make up facts or plagiarize. Always provide proper attribution.",
|
||||
],
|
||||
add_datetime_to_instructions=True,
|
||||
add_chat_history_to_prompt=True,
|
||||
num_history_messages=3,
|
||||
)
|
||||
|
||||
# Input fields for the user's financial goals and current financial situation
|
||||
|
|
@ -66,4 +64,4 @@ if openai_api_key and serp_api_key:
|
|||
with st.spinner("Processing..."):
|
||||
# Get the response from the assistant
|
||||
response = planner.run(f"Financial goals: {financial_goals}, Current situation: {current_situation}", stream=False)
|
||||
st.write(response)
|
||||
st.write(response.content)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
streamlit
|
||||
phidata
|
||||
agno
|
||||
openai
|
||||
google-search-results
|
||||
61
ai_agent_tutorials/ai_real_estate_agent/README.md
Normal file
61
ai_agent_tutorials/ai_real_estate_agent/README.md
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
## 🏠 AI Real Estate Agent - Powered by Firecrawl's Extract Endpoint
|
||||
|
||||
The AI Real Estate Agent automates property search and market analysis using Firecrawl's Extract endpoint and Agno AI Agent's insights. It helps users find properties matching their criteria while providing detailed location trends and investment recommendations. This agent streamlines the property search process by combining data from multiple real estate websites and offering intelligent analysis.
|
||||
|
||||
### Features
|
||||
- **Smart Property Search**: Uses Firecrawl's Extract endpoint to find properties across multiple real estate websites
|
||||
- **Multi-Source Integration**: Aggregates data from 99acres, Housing.com, Square Yards, Nobroker, and MagicBricks
|
||||
- **Location Analysis**: Provides detailed price trends and investment insights for different localities
|
||||
- **AI-Powered Recommendations**: Uses GPT models to analyze properties and provide structured recommendations
|
||||
- **User-Friendly Interface**: Clean Streamlit UI for easy property search and results viewing
|
||||
- **Customizable Search**: Filter by city, property type, category, and budget
|
||||
|
||||
### How to Get Started
|
||||
1. **Clone the repository**:
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd ai_agent_tutorials/ai_real_estate_agent
|
||||
```
|
||||
|
||||
2. **Install the required packages**:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
3. **Set up your API keys**:
|
||||
- Get your Firecrawl API key from [Firecrawl's website](https://www.firecrawl.dev/app/api-keys)
|
||||
- Get your OpenAI API key from [OpenAI's website](https://platform.openai.com/api-keys)
|
||||
|
||||
4. **Run the application**:
|
||||
```bash
|
||||
streamlit run ai_real_estate_agent.py
|
||||
```
|
||||
|
||||
### Using the Agent
|
||||
1. **Enter API Keys**:
|
||||
- Input your Firecrawl and OpenAI API keys in the sidebar
|
||||
- Keys are securely stored in the session state
|
||||
|
||||
2. **Set Search Criteria**:
|
||||
- Enter the city name
|
||||
- Select property category (Residential/Commercial)
|
||||
- Choose property type (Flat/Individual House)
|
||||
- Set maximum budget in Crores
|
||||
|
||||
3. **View Results**:
|
||||
- Property recommendations with detailed analysis
|
||||
- Location trends with investment insights
|
||||
- Expandable sections for easy reading
|
||||
|
||||
### Features in Detail
|
||||
- **Property Finding**:
|
||||
- Searches across multiple real estate websites
|
||||
- Returns 3-6 properties matching criteria
|
||||
- Provides detailed property information and analysis
|
||||
|
||||
- **Location Analysis**:
|
||||
- Price trends for different localities
|
||||
- Rental yield analysis
|
||||
- Investment potential assessment
|
||||
- Top performing areas identification
|
||||
|
||||
321
ai_agent_tutorials/ai_real_estate_agent/ai_real_estate_agent.py
Normal file
321
ai_agent_tutorials/ai_real_estate_agent/ai_real_estate_agent.py
Normal file
|
|
@ -0,0 +1,321 @@
|
|||
from typing import Dict, List
|
||||
from pydantic import BaseModel, Field
|
||||
from agno.agent import Agent
|
||||
from agno.models.openai import OpenAIChat
|
||||
from firecrawl import FirecrawlApp
|
||||
import streamlit as st
|
||||
|
||||
class PropertyData(BaseModel):
|
||||
"""Schema for property data extraction"""
|
||||
building_name: str = Field(description="Name of the building/property", alias="Building_name")
|
||||
property_type: str = Field(description="Type of property (commercial, residential, etc)", alias="Property_type")
|
||||
location_address: str = Field(description="Complete address of the property")
|
||||
price: str = Field(description="Price of the property", alias="Price")
|
||||
description: str = Field(description="Detailed description of the property", alias="Description")
|
||||
|
||||
class PropertiesResponse(BaseModel):
|
||||
"""Schema for multiple properties response"""
|
||||
properties: List[PropertyData] = Field(description="List of property details")
|
||||
|
||||
class LocationData(BaseModel):
|
||||
"""Schema for location price trends"""
|
||||
location: str
|
||||
price_per_sqft: float
|
||||
percent_increase: float
|
||||
rental_yield: float
|
||||
|
||||
class LocationsResponse(BaseModel):
|
||||
"""Schema for multiple locations response"""
|
||||
locations: List[LocationData] = Field(description="List of location data points")
|
||||
|
||||
class FirecrawlResponse(BaseModel):
|
||||
"""Schema for Firecrawl API response"""
|
||||
success: bool
|
||||
data: Dict
|
||||
status: str
|
||||
expiresAt: str
|
||||
|
||||
class PropertyFindingAgent:
|
||||
"""Agent responsible for finding properties and providing recommendations"""
|
||||
|
||||
def __init__(self, firecrawl_api_key: str, openai_api_key: str, model_id: str = "o3-mini"):
|
||||
self.agent = Agent(
|
||||
model=OpenAIChat(id=model_id, api_key=openai_api_key),
|
||||
markdown=True,
|
||||
description="I am a real estate expert who helps find and analyze properties based on user preferences."
|
||||
)
|
||||
self.firecrawl = FirecrawlApp(api_key=firecrawl_api_key)
|
||||
|
||||
def find_properties(
|
||||
self,
|
||||
city: str,
|
||||
max_price: float,
|
||||
property_category: str = "Residential",
|
||||
property_type: str = "Flat"
|
||||
) -> str:
|
||||
"""Find and analyze properties based on user preferences"""
|
||||
formatted_location = city.lower()
|
||||
|
||||
urls = [
|
||||
f"https://www.squareyards.com/sale/property-for-sale-in-{formatted_location}/*",
|
||||
f"https://www.99acres.com/property-in-{formatted_location}-ffid/*",
|
||||
f"https://housing.com/in/buy/{formatted_location}/{formatted_location}",
|
||||
# f"https://www.nobroker.in/property/sale/{city}/{formatted_location}",
|
||||
]
|
||||
|
||||
property_type_prompt = "Flats" if property_type == "Flat" else "Individual Houses"
|
||||
|
||||
raw_response = self.firecrawl.extract(
|
||||
urls=urls,
|
||||
params={
|
||||
'prompt': f"""Extract ONLY 10 OR LESS different {property_category} {property_type_prompt} from {city} that cost less than {max_price} crores.
|
||||
|
||||
Requirements:
|
||||
- Property Category: {property_category} properties only
|
||||
- Property Type: {property_type_prompt} only
|
||||
- Location: {city}
|
||||
- Maximum Price: {max_price} crores
|
||||
- Include complete property details with exact location
|
||||
- IMPORTANT: Return data for at least 3 different properties. MAXIMUM 10.
|
||||
- Format as a list of properties with their respective details
|
||||
""",
|
||||
'schema': PropertiesResponse.model_json_schema()
|
||||
}
|
||||
)
|
||||
|
||||
print("Raw Property Response:", raw_response)
|
||||
|
||||
if isinstance(raw_response, dict) and raw_response.get('success'):
|
||||
properties = raw_response['data'].get('properties', [])
|
||||
else:
|
||||
properties = []
|
||||
|
||||
print("Processed Properties:", properties)
|
||||
|
||||
|
||||
analysis = self.agent.run(
|
||||
f"""As a real estate expert, analyze these properties and market trends:
|
||||
|
||||
Properties Found in json format:
|
||||
{properties}
|
||||
|
||||
**IMPORTANT INSTRUCTIONS:**
|
||||
1. ONLY analyze properties from the above JSON data that match the user's requirements:
|
||||
- Property Category: {property_category}
|
||||
- Property Type: {property_type}
|
||||
- Maximum Price: {max_price} crores
|
||||
2. DO NOT create new categories or property types
|
||||
3. From the matching properties, select 5-6 properties with prices closest to {max_price} crores
|
||||
|
||||
Please provide your analysis in this format:
|
||||
|
||||
🏠 SELECTED PROPERTIES
|
||||
• List only 5-6 best matching properties with prices closest to {max_price} crores
|
||||
• For each property include:
|
||||
- Name and Location
|
||||
- Price (with value analysis)
|
||||
- Key Features
|
||||
- Pros and Cons
|
||||
|
||||
💰 BEST VALUE ANALYSIS
|
||||
• Compare the selected properties based on:
|
||||
- Price per sq ft
|
||||
- Location advantage
|
||||
- Amenities offered
|
||||
|
||||
📍 LOCATION INSIGHTS
|
||||
• Specific advantages of the areas where selected properties are located
|
||||
|
||||
💡 RECOMMENDATIONS
|
||||
• Top 3 properties from the selection with reasoning
|
||||
• Investment potential
|
||||
• Points to consider before purchase
|
||||
|
||||
🤝 NEGOTIATION TIPS
|
||||
• Property-specific negotiation strategies
|
||||
|
||||
Format your response in a clear, structured way using the above sections.
|
||||
"""
|
||||
)
|
||||
|
||||
return analysis.content
|
||||
|
||||
def get_location_trends(self, city: str) -> str:
|
||||
"""Get price trends for different localities in the city"""
|
||||
raw_response = self.firecrawl.extract([
|
||||
f"https://www.99acres.com/property-rates-and-price-trends-in-{city.lower()}-prffid/*"
|
||||
], {
|
||||
'prompt': """Extract price trends data for ALL major localities in the city.
|
||||
IMPORTANT:
|
||||
- Return data for at least 5-10 different localities
|
||||
- Include both premium and affordable areas
|
||||
- Do not skip any locality mentioned in the source
|
||||
- Format as a list of locations with their respective data
|
||||
""",
|
||||
'schema': LocationsResponse.model_json_schema(),
|
||||
})
|
||||
|
||||
if isinstance(raw_response, dict) and raw_response.get('success'):
|
||||
locations = raw_response['data'].get('locations', [])
|
||||
|
||||
analysis = self.agent.run(
|
||||
f"""As a real estate expert, analyze these location price trends for {city}:
|
||||
|
||||
{locations}
|
||||
|
||||
Please provide:
|
||||
1. A bullet-point summary of the price trends for each location
|
||||
2. Identify the top 3 locations with:
|
||||
- Highest price appreciation
|
||||
- Best rental yields
|
||||
- Best value for money
|
||||
3. Investment recommendations:
|
||||
- Best locations for long-term investment
|
||||
- Best locations for rental income
|
||||
- Areas showing emerging potential
|
||||
4. Specific advice for investors based on these trends
|
||||
|
||||
Format the response as follows:
|
||||
|
||||
📊 LOCATION TRENDS SUMMARY
|
||||
• [Bullet points for each location]
|
||||
|
||||
🏆 TOP PERFORMING AREAS
|
||||
• [Bullet points for best areas]
|
||||
|
||||
💡 INVESTMENT INSIGHTS
|
||||
• [Bullet points with investment advice]
|
||||
|
||||
🎯 RECOMMENDATIONS
|
||||
• [Bullet points with specific recommendations]
|
||||
"""
|
||||
)
|
||||
|
||||
return analysis.content
|
||||
|
||||
return "No price trends data available"
|
||||
|
||||
def create_property_agent():
|
||||
"""Create PropertyFindingAgent with API keys from session state"""
|
||||
if 'property_agent' not in st.session_state:
|
||||
st.session_state.property_agent = PropertyFindingAgent(
|
||||
firecrawl_api_key=st.session_state.firecrawl_key,
|
||||
openai_api_key=st.session_state.openai_key,
|
||||
model_id=st.session_state.model_id
|
||||
)
|
||||
|
||||
def main():
|
||||
st.set_page_config(
|
||||
page_title="AI Real Estate Agent",
|
||||
page_icon="🏠",
|
||||
layout="wide"
|
||||
)
|
||||
|
||||
with st.sidebar:
|
||||
st.title("🔑 API Configuration")
|
||||
|
||||
st.subheader("🤖 Model Selection")
|
||||
model_id = st.selectbox(
|
||||
"Choose OpenAI Model",
|
||||
options=["o3-mini", "gpt-4o"],
|
||||
help="Select the AI model to use. Choose gpt-4o if your api doesn't have access to o3-mini"
|
||||
)
|
||||
st.session_state.model_id = model_id
|
||||
|
||||
st.divider()
|
||||
|
||||
st.subheader("🔐 API Keys")
|
||||
firecrawl_key = st.text_input(
|
||||
"Firecrawl API Key",
|
||||
type="password",
|
||||
help="Enter your Firecrawl API key"
|
||||
)
|
||||
openai_key = st.text_input(
|
||||
"OpenAI API Key",
|
||||
type="password",
|
||||
help="Enter your OpenAI API key"
|
||||
)
|
||||
|
||||
if firecrawl_key and openai_key:
|
||||
st.session_state.firecrawl_key = firecrawl_key
|
||||
st.session_state.openai_key = openai_key
|
||||
create_property_agent()
|
||||
|
||||
st.title("🏠 AI Real Estate Agent")
|
||||
st.info(
|
||||
"""
|
||||
Welcome to the AI Real Estate Agent!
|
||||
Enter your search criteria below to get property recommendations
|
||||
and location insights.
|
||||
"""
|
||||
)
|
||||
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
city = st.text_input(
|
||||
"City",
|
||||
placeholder="Enter city name (e.g., Bangalore)",
|
||||
help="Enter the city where you want to search for properties"
|
||||
)
|
||||
|
||||
property_category = st.selectbox(
|
||||
"Property Category",
|
||||
options=["Residential", "Commercial"],
|
||||
help="Select the type of property you're interested in"
|
||||
)
|
||||
|
||||
with col2:
|
||||
max_price = st.number_input(
|
||||
"Maximum Price (in Crores)",
|
||||
min_value=0.1,
|
||||
max_value=100.0,
|
||||
value=5.0,
|
||||
step=0.1,
|
||||
help="Enter your maximum budget in Crores"
|
||||
)
|
||||
|
||||
property_type = st.selectbox(
|
||||
"Property Type",
|
||||
options=["Flat", "Individual House"],
|
||||
help="Select the specific type of property"
|
||||
)
|
||||
|
||||
if st.button("🔍 Start Search", use_container_width=True):
|
||||
if 'property_agent' not in st.session_state:
|
||||
st.error("⚠️ Please enter your API keys in the sidebar first!")
|
||||
return
|
||||
|
||||
if not city:
|
||||
st.error("⚠️ Please enter a city name!")
|
||||
return
|
||||
|
||||
try:
|
||||
with st.spinner("🔍 Searching for properties..."):
|
||||
property_results = st.session_state.property_agent.find_properties(
|
||||
city=city,
|
||||
max_price=max_price,
|
||||
property_category=property_category,
|
||||
property_type=property_type
|
||||
)
|
||||
|
||||
st.success("✅ Property search completed!")
|
||||
|
||||
st.subheader("🏘️ Property Recommendations")
|
||||
st.markdown(property_results)
|
||||
|
||||
st.divider()
|
||||
|
||||
with st.spinner("📊 Analyzing location trends..."):
|
||||
location_trends = st.session_state.property_agent.get_location_trends(city)
|
||||
|
||||
st.success("✅ Location analysis completed!")
|
||||
|
||||
with st.expander("📈 Location Trends Analysis of the city"):
|
||||
st.markdown(location_trends)
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"❌ An error occurred: {str(e)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
5
ai_agent_tutorials/ai_real_estate_agent/requirements.txt
Normal file
5
ai_agent_tutorials/ai_real_estate_agent/requirements.txt
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
agno
|
||||
firecrawl-py==1.9.0
|
||||
pydantic
|
||||
streamlit
|
||||
openai
|
||||
51
ai_agent_tutorials/ai_reasoning_agent/README.md
Normal file
51
ai_agent_tutorials/ai_reasoning_agent/README.md
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
## AI Reasoning Agent
|
||||
|
||||
The AI Reasoning Agent leverages advanced AI models to provide insightful reasoning and decision-making capabilities. This agent is designed to assist users in various analytical tasks by processing information and generating structured outputs.
|
||||
|
||||
### Features
|
||||
- **Advanced Reasoning**: Utilizes the Ollama model to perform complex reasoning tasks
|
||||
- **Interactive Playground**: Provides a user-friendly interface for interacting with the reasoning agent
|
||||
- **Markdown Support**: Outputs results in markdown format for easy readability and sharing
|
||||
- **Customizable Agent**: Easily configurable to suit different reasoning scenarios
|
||||
|
||||
### How to Get Started
|
||||
1. **Clone the repository**:
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd ai_agent_tutorials/ai_reasoning_agent
|
||||
```
|
||||
|
||||
2. **Install the required packages**:
|
||||
#### For Local AI Reasoning Agent
|
||||
```bash
|
||||
pip install -r requirements_local_ai_reasoning_agent.txt
|
||||
```
|
||||
|
||||
3. **Run the application**:
|
||||
```bash
|
||||
python local_ai_reasoning_agent.py
|
||||
```
|
||||
|
||||
### Using the Agent
|
||||
1. **Access the Playground**:
|
||||
- Open the provided URL to access the interactive playground
|
||||
- The playground allows you to input queries and receive structured reasoning outputs
|
||||
|
||||
2. **Input Queries**:
|
||||
- Enter your queries in the provided input field
|
||||
- The agent processes the input and provides detailed reasoning and analysis
|
||||
|
||||
3. **View Results**:
|
||||
- Results are displayed in markdown format
|
||||
- Easily copy and share the outputs for further use
|
||||
|
||||
### Features in Detail
|
||||
- **Reasoning Capabilities**:
|
||||
- Handles a wide range of analytical tasks
|
||||
- Provides clear and structured outputs
|
||||
- Supports markdown for easy sharing and readability
|
||||
|
||||
- **Interactive Interface**:
|
||||
- User-friendly playground for seamless interaction
|
||||
- Real-time processing and output generation
|
||||
- Configurable settings to tailor the agent's behavior
|
||||
Binary file not shown.
|
|
@ -0,0 +1,12 @@
|
|||
from agno.agent import Agent
|
||||
from agno.models.ollama import Ollama
|
||||
from agno.playground import Playground, serve_playground_app
|
||||
|
||||
reasoning_agent = Agent(name="Reasoning Agent", model=Ollama(id="qwq:32b"), markdown=True)
|
||||
|
||||
# UI for Reasoning agent
|
||||
app = Playground(agents=[reasoning_agent]).get_app()
|
||||
|
||||
# Run the Playground app
|
||||
if __name__ == "__main__":
|
||||
serve_playground_app("local_ai_reasoning_agent:app", reload=True)
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
from phi.agent import Agent
|
||||
from phi.model.openai import OpenAIChat
|
||||
from phi.cli.console import console
|
||||
from agno.agent import Agent
|
||||
from agno.models.openai import OpenAIChat
|
||||
from rich.console import Console
|
||||
|
||||
regular_agent = Agent(model=OpenAIChat(id="gpt-4o-mini"), markdown=True)
|
||||
|
||||
console = Console()
|
||||
reasoning_agent = Agent(
|
||||
model=OpenAIChat(id="gpt-4o"),
|
||||
reasoning=True,
|
||||
|
|
|
|||
4
ai_agent_tutorials/ai_reasoning_agent/requirements.txt
Normal file
4
ai_agent_tutorials/ai_reasoning_agent/requirements.txt
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
agno
|
||||
ollama
|
||||
fastapi
|
||||
uvicorn
|
||||
101
ai_agent_tutorials/ai_recruitment_agent_team/README.md
Normal file
101
ai_agent_tutorials/ai_recruitment_agent_team/README.md
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
# 💼 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
|
||||
|
|
@ -0,0 +1,521 @@
|
|||
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()
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# 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
|
||||
80
ai_agent_tutorials/ai_services_agency/README.md
Normal file
80
ai_agent_tutorials/ai_services_agency/README.md
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
# 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!
|
||||
365
ai_agent_tutorials/ai_services_agency/agency.py
Normal file
365
ai_agent_tutorials/ai_services_agency/agency.py
Normal file
|
|
@ -0,0 +1,365 @@
|
|||
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()
|
||||
3
ai_agent_tutorials/ai_services_agency/requirements.txt
Normal file
3
ai_agent_tutorials/ai_services_agency/requirements.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
python-dotenv==1.0.1
|
||||
agency-swarm==0.4.1
|
||||
streamlit
|
||||
42
ai_agent_tutorials/ai_startup_trend_analysis_agent/README.md
Normal file
42
ai_agent_tutorials/ai_startup_trend_analysis_agent/README.md
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
## 📈 AI Startup Trend Analysis Agent
|
||||
The AI Startup Trend Analysis Agent is tool for budding entrepreneurs that generates actionable insights by identifying nascent trends, potential market gaps, and growth opportunities in specific sectors. Entrepreneurs can use these data-driven insights to validate ideas, spot market opportunities, and make informed decisions about their startup ventures. It combines Newspaper4k and DuckDuckGo to scan and analyze startup-focused articles and market data. Using Claude 3.5 Sonnet, it processes this information to extract emerging patterns and enable entrepreneurs to identify promising startup opportunities.
|
||||
|
||||
|
||||
### Features
|
||||
- **User Prompt**: Entrepreneurs can input specific startup sectors or technologies of interest for research.
|
||||
- **News Collection**: This agent gathers recent startup news, funding rounds, and market analyses using DuckDuckGo.
|
||||
- **Summary Generation**: Concise summaries of verified information are generated using Newspaper4k.
|
||||
- **Trend Analysis**: The system identifies emerging patterns in startup funding, technology adoption, and market opportunities across analyzed stories.
|
||||
- **Streamlit UI**: The application features a user-friendly interface built with Streamlit for easy interaction.
|
||||
|
||||
### How to Get Started
|
||||
1. **Clone the repository**:
|
||||
```bash
|
||||
git clone https://github.com/Shubhamsaboo/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/ai_agent_tutorials/ai_startup_trend_analysis_agent
|
||||
```
|
||||
|
||||
2. **Create and activate a virtual environment**:
|
||||
```bash
|
||||
# For macOS/Linux
|
||||
python -m venv venv
|
||||
source venv/bin/activate
|
||||
|
||||
# For Windows
|
||||
python -m venv venv
|
||||
.\venv\Scripts\activate
|
||||
```
|
||||
|
||||
3. **Install the required packages**:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
4. **Run the application**:
|
||||
```bash
|
||||
streamlit run startup_trends_agent.py
|
||||
```
|
||||
### Important Note
|
||||
- The system specifically uses Claude's API for advanced language processing. You can obtain your Anthropic API key from [Anthropic's website](https://www.anthropic.com/api).
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue