NEW Multi Agent Demos: AI Realtor and AI Enterprise Orchestrator
This commit is contained in:
parent
b7a21406b1
commit
e766cf3b00
7 changed files with 1720 additions and 0 deletions
|
|
@ -0,0 +1,481 @@
|
|||
# Enterprise Knowledge Orchestrator
|
||||
|
||||
A production-grade multi-agent system built with Google ADK that orchestrates knowledge management across local files and SaaS platforms using MCP (Model Context Protocol).
|
||||
|
||||
## Overview
|
||||
|
||||
This system combines:
|
||||
- **Local Filesystem MCP Server** - for accessing and analyzing local documents
|
||||
- **Notion MCP Server** - for managing Notion workspaces and content
|
||||
- **Composio MCP Server** - for GitHub and Figma integration
|
||||
- **Intelligent Router/Orchestrator** - context-aware task delegation with state management
|
||||
- **4 Specialized Agents** - each handling specific platform capabilities
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Router/Orchestrator Agent │
|
||||
│ (Coordinator/Dispatcher Pattern) │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
|
||||
│ │ File Analysis │ │ Notion Agent │ │ GitHub Agent │ │
|
||||
│ │ Agent │ │ (Optional) │ │ (Optional) │ │
|
||||
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
|
||||
│ │ Filesystem MCP │ │ Notion MCP │ │ Composio MCP │ │
|
||||
│ │ Server │ │ Server │ │ Server │ │
|
||||
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
|
||||
│ │ │ │ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
|
||||
│ │ Local Documents │ │ Notion Pages & │ │ GitHub Repos │ │
|
||||
│ │ (PDF, DOC, XLS) │ │ Databases │ │ & Issues │ │
|
||||
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
|
||||
│ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ Figma Agent │ │ Composio MCP │ │
|
||||
│ │ (Optional) │ │ Server │ │
|
||||
│ └─────────────────┘ └─────────────────┘ │
|
||||
│ │ │ │
|
||||
│ ┌─────────────────┐ ┌─────────────────┐ │
|
||||
│ │ Figma Files & │ │ Figma Designs & │ │
|
||||
│ │ Designs │ │ Assets │ │
|
||||
│ └─────────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### **Routing Patterns:**
|
||||
|
||||
1. **Coordinator/Dispatcher Pattern**: Intelligent routing based on query analysis
|
||||
2. **LLM-Driven Delegation**: Automatic agent selection using `transfer_to_agent()`
|
||||
3. **Explicit Invocation**: Direct agent calls using `AgentTool`
|
||||
4. **Graceful Degradation**: System works with any combination of available agents
|
||||
|
||||
## Features
|
||||
|
||||
### 🔍 File Analysis Agent
|
||||
- Analyzes local documents (PDFs, Word docs, spreadsheets)
|
||||
- Extracts key topics, summaries, and action items
|
||||
- Categorizes documents by type and content
|
||||
- Identifies information for knowledge base sync
|
||||
|
||||
### 📝 Notion Agent
|
||||
- Reads, writes, and updates Notion pages and databases
|
||||
- Searches for content across Notion workspace
|
||||
- Creates structured knowledge bases and documentation
|
||||
- Syncs content from other sources to Notion
|
||||
|
||||
### 🐙 GitHub Agent
|
||||
- Creates and manages GitHub issues and pull requests
|
||||
- Searches repositories and code
|
||||
- Manages repository content and documentation
|
||||
- Sets up automated workflows and actions
|
||||
|
||||
### 🎨 Figma Agent
|
||||
- Reads and analyzes Figma files and designs
|
||||
- Exports design assets and components
|
||||
- Searches for design elements and styles
|
||||
- Manages design system components
|
||||
|
||||
### 🎯 Router/Orchestrator Agent
|
||||
- Analyzes user requests and determines which agents should handle them
|
||||
- Routes tasks to appropriate specialized agents based on capabilities
|
||||
- Coordinates multi-step workflows that require multiple agents
|
||||
- Shares context and results between agents through session state
|
||||
- Provides comprehensive results and recommendations
|
||||
|
||||
### 🛡️ Error Handling & Graceful Degradation
|
||||
- **MCP Server Failures**: Graceful fallback when servers are unavailable
|
||||
- **Missing Environment Variables**: System works with available APIs only
|
||||
- **Agent Creation Failures**: Continues with available agents
|
||||
- **Validation**: Ensures at least one agent is available before operation
|
||||
- **Comprehensive Logging**: Detailed logs for troubleshooting
|
||||
|
||||
## Prerequisites
|
||||
|
||||
1. **Python 3.9+** and **Node.js** (for MCP servers)
|
||||
2. **Google ADK** installed and configured
|
||||
3. **Notion API Key** for Notion integration
|
||||
4. **Required API Keys** in environment variables
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Environment Variables
|
||||
|
||||
Create a `.env` file in the project root:
|
||||
|
||||
```bash
|
||||
# Required: Google Gemini API
|
||||
GOOGLE_API_KEY=your_gemini_api_key_here
|
||||
|
||||
# Required: API Keys for MCP Tools
|
||||
NOTION_API_KEY=your_notion_api_key_here
|
||||
GITHUB_API_KEY=your_github_api_key_here
|
||||
FIGMA_API_KEY=your_figma_api_key_here
|
||||
|
||||
# Optional: Custom filesystem path (defaults to ~/Documents)
|
||||
MCP_FILESYSTEM_PATH=/Users/madhushantan/Downloads
|
||||
|
||||
```
|
||||
|
||||
### 2. Notion Setup
|
||||
|
||||
#### Creating a Notion Integration
|
||||
1. Go to [Notion Integrations](https://www.notion.so/my-integrations)
|
||||
2. Click "New integration"
|
||||
3. Name your integration (e.g., "Enterprise Knowledge Orchestrator")
|
||||
4. Select the capabilities needed (Read & Write content)
|
||||
5. Submit and copy your "Internal Integration Token"
|
||||
|
||||
#### Sharing Your Notion Page with the Integration
|
||||
1. Open your Notion page
|
||||
2. Click the three dots (⋮) in the top-right corner
|
||||
3. Select "Add connections" from the dropdown
|
||||
4. Search for your integration name
|
||||
5. Click on your integration to add it to the page
|
||||
6. Confirm by clicking "Confirm"
|
||||
|
||||
#### Finding Your Notion Page ID
|
||||
1. Open your Notion page in a browser
|
||||
2. Copy the URL: `https://www.notion.so/workspace/Your-Page-1f5b8a8ba283...`
|
||||
3. The ID is the part after the last dash: `1f5b8a8ba283`
|
||||
|
||||
### 3. Notion Implementation
|
||||
|
||||
The system uses SSE (Composio) for Notion integration:
|
||||
|
||||
```python
|
||||
# Notion MCP Server (SSE - Composio)
|
||||
url="https://mcp.composio.dev/composio/server/61e41019-d05f-44d0-973e-2aef7777063a/sse?useComposioHelperActions=true"
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- **SSE Connection**: Uses Server-Sent Events for real-time communication
|
||||
- **Composio Managed**: No local dependencies required
|
||||
- **Full Tool Access**: All available Notion tools are accessible
|
||||
- **Authentication**: Handled by Composio service
|
||||
|
||||
**Note**: The Notion integration requires a valid `NOTION_API_KEY` and `NOTION_PAGE_ID` to function properly.
|
||||
|
||||
### 4. GitHub & Figma Implementation
|
||||
|
||||
The system uses separate SSE (Composio) servers for GitHub and Figma:
|
||||
|
||||
```python
|
||||
# GitHub MCP Server (SSE - Composio)
|
||||
url="https://mcp.composio.dev/composio/server/11fbff47-fa12-432f-8c3a-18ed4e9f66f8/sse?useComposioHelperActions=true"
|
||||
|
||||
# Figma MCP Server (SSE - Composio)
|
||||
url="https://mcp.composio.dev/composio/server/f05e7129-7997-4c17-a654-f935278c0dfe/sse?useComposioHelperActions=true"
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- **Separate Servers**: Each service has its own dedicated Composio server
|
||||
- **Full Tool Access**: All available GitHub and Figma tools are accessible
|
||||
- **No Local Dependencies**: Managed by Composio service
|
||||
|
||||
### 2. Install Dependencies
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 3. Verify MCP Server Installation
|
||||
|
||||
```bash
|
||||
# Verify npx is available
|
||||
which npx
|
||||
|
||||
# Test filesystem MCP server
|
||||
npx -y @modelcontextprotocol/server-filesystem --help
|
||||
|
||||
# Test Notion MCP server
|
||||
npx -y @notionhq/notion-mcp-server --help
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from agent import EnterpriseKnowledgeOrchestrator
|
||||
|
||||
async def main():
|
||||
# Create orchestrator
|
||||
orchestrator = EnterpriseKnowledgeOrchestrator()
|
||||
|
||||
try:
|
||||
# Process knowledge request
|
||||
results = await orchestrator.process_knowledge_request(
|
||||
"Analyze all PDF documents in my Documents folder and create GitHub issues for action items"
|
||||
)
|
||||
|
||||
# Access results
|
||||
print(f"Files analyzed: {len(results['file_analysis'])}")
|
||||
print(f"Notion operations: {len(results['notion_operations'])}")
|
||||
print(f"GitHub operations: {len(results['github_operations'])}")
|
||||
print(f"Figma operations: {len(results['figma_operations'])}")
|
||||
|
||||
finally:
|
||||
await orchestrator.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
### Example Requests
|
||||
|
||||
```python
|
||||
# Document analysis
|
||||
"Analyze all PDF documents in my Documents folder and create a summary"
|
||||
|
||||
# Multi-platform operations
|
||||
"Search for design components in my Figma files and create a GitHub repository for the design system"
|
||||
|
||||
# Notion and GitHub integration
|
||||
"Read my Notion project page and create GitHub issues for all action items"
|
||||
|
||||
# Figma asset management
|
||||
"Export design assets from Figma and organize them in a structured folder"
|
||||
|
||||
# Complex workflows
|
||||
"Analyze quarterly reports, extract key metrics, create Notion dashboard, and set up GitHub issues for follow-ups"
|
||||
```
|
||||
|
||||
## Agent Routing Logic
|
||||
|
||||
The Router/Orchestrator agent intelligently routes tasks based on query analysis:
|
||||
|
||||
- **File-related tasks** → FileAnalysisAgent
|
||||
- **Notion-related tasks** → NotionAgent
|
||||
- **GitHub-related tasks** → GitHubAgent
|
||||
- **Figma-related tasks** → FigmaAgent
|
||||
- **Multi-platform tasks** → Coordinate between relevant agents
|
||||
|
||||
## Configuration
|
||||
|
||||
### MCP Server URLs
|
||||
|
||||
The system uses these MCP servers:
|
||||
|
||||
```python
|
||||
# Filesystem MCP Server (local)
|
||||
command='npx'
|
||||
args=["-y", "@modelcontextprotocol/server-filesystem", "~/Documents"]
|
||||
|
||||
# Notion MCP Server (SSE - Composio)
|
||||
url="https://mcp.composio.dev/composio/server/61e41019-d05f-44d0-973e-2aef7777063a/sse?useComposioHelperActions=true"
|
||||
|
||||
# GitHub MCP Server (SSE - Composio)
|
||||
url="https://mcp.composio.dev/composio/server/11fbff47-fa12-432f-8c3a-18ed4e9f66f8/sse?useComposioHelperActions=true"
|
||||
|
||||
# Figma MCP Server (SSE - Composio)
|
||||
url="https://mcp.composio.dev/composio/server/f05e7129-7997-4c17-a654-f935278c0dfe/sse?useComposioHelperActions=true"
|
||||
# No tool filtering - all available tools are accessible
|
||||
```
|
||||
|
||||
### Custom Filesystem Path
|
||||
|
||||
The system now supports configurable filesystem paths through environment variables:
|
||||
|
||||
```bash
|
||||
# Set in .env file or export in terminal
|
||||
export MCP_FILESYSTEM_PATH="/path/to/your/folder"
|
||||
|
||||
# Examples:
|
||||
export MCP_FILESYSTEM_PATH="/Users/username/Projects"
|
||||
export MCP_FILESYSTEM_PATH="/home/user/documents"
|
||||
export MCP_FILESYSTEM_PATH="~/Desktop/Work"
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- **Flexible Paths**: Use absolute or relative paths
|
||||
- **Auto-Expansion**: Tilde (~) expansion for home directory
|
||||
- **Auto-Creation**: Directory created if it doesn't exist
|
||||
- **Fallback**: Defaults to `~/Documents` if not specified
|
||||
|
||||
## Output Schemas
|
||||
|
||||
The system uses structured Pydantic models for consistent outputs:
|
||||
|
||||
### FileAnalysis
|
||||
```python
|
||||
{
|
||||
"file_name": "quarterly_report.pdf",
|
||||
"file_type": "PDF",
|
||||
"summary": "Q3 financial performance analysis...",
|
||||
"key_topics": ["revenue", "expenses", "growth"],
|
||||
"action_items": ["Review budget allocation", "Update projections"]
|
||||
}
|
||||
```
|
||||
|
||||
### NotionOperation
|
||||
```python
|
||||
{
|
||||
"operation_type": "read",
|
||||
"page_id": "1f5b8a8ba283...",
|
||||
"content_summary": "Project documentation read from Notion",
|
||||
"status": "completed",
|
||||
"results": {"content": "...", "blocks": [...]}
|
||||
}
|
||||
```
|
||||
|
||||
### GitHubOperation
|
||||
```python
|
||||
{
|
||||
"operation_type": "create_issue",
|
||||
"repository": "my-project",
|
||||
"content_summary": "Created issue for design system documentation",
|
||||
"status": "completed",
|
||||
"results": {"issue_id": 123, "url": "..."}
|
||||
}
|
||||
```
|
||||
|
||||
### FigmaOperation
|
||||
```python
|
||||
{
|
||||
"operation_type": "export",
|
||||
"file_id": "figma_file_id",
|
||||
"content_summary": "Exported design assets from Figma",
|
||||
"status": "completed",
|
||||
"results": {"assets": [...], "urls": [...]}
|
||||
}
|
||||
```
|
||||
|
||||
## Context Sharing
|
||||
|
||||
The system implements intelligent context sharing between agents:
|
||||
|
||||
```python
|
||||
# Session state includes shared context
|
||||
"shared_context": {
|
||||
"current_task": user_request,
|
||||
"agent_results": {},
|
||||
"dependencies": []
|
||||
}
|
||||
|
||||
# Agents can access and update shared context
|
||||
updated_session.state["shared_context"]["agent_results"]["file_analysis"] = file_results
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
The system includes comprehensive error handling:
|
||||
|
||||
- **MCP Connection Failures**: Graceful fallback when servers are unavailable
|
||||
- **API Rate Limits**: Automatic retry logic with exponential backoff
|
||||
- **Invalid Data**: Validation and sanitization of inputs
|
||||
- **Session Management**: Proper cleanup of resources
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
# Configure logging level
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
# Monitor agent activities
|
||||
logger.info("File analysis completed: 5 documents processed")
|
||||
logger.warning("Notion API key not found, Notion integration disabled")
|
||||
logger.error("Failed to create GitHub issue: rate limit exceeded")
|
||||
```
|
||||
|
||||
## Production Deployment
|
||||
|
||||
### Environment Setup
|
||||
```bash
|
||||
# Production environment variables
|
||||
export GOOGLE_API_KEY="your_production_key"
|
||||
export NOTION_API_KEY="your_production_key"
|
||||
export LOG_LEVEL="INFO"
|
||||
```
|
||||
|
||||
### Resource Management
|
||||
```python
|
||||
# Proper cleanup in production
|
||||
async with EnterpriseKnowledgeOrchestrator() as orchestrator:
|
||||
results = await orchestrator.process_knowledge_request(request)
|
||||
```
|
||||
|
||||
### Scaling Considerations
|
||||
- Use connection pooling for MCP servers
|
||||
- Implement caching for frequently accessed documents
|
||||
- Consider async processing for large document sets
|
||||
- Monitor memory usage with large file operations
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **MCP Server Connection Failed**
|
||||
```bash
|
||||
# Verify Node.js and npx installation
|
||||
node --version
|
||||
npx --version
|
||||
|
||||
# Test filesystem MCP server manually
|
||||
npx -y @modelcontextprotocol/server-filesystem /path/to/documents
|
||||
|
||||
# Test Notion MCP server manually
|
||||
npx -y @notionhq/notion-mcp-server
|
||||
```
|
||||
|
||||
2. **Notion Integration Not Working**
|
||||
```bash
|
||||
# Verify environment variables
|
||||
echo $NOTION_API_KEY
|
||||
|
||||
# Test Notion connection
|
||||
curl -H "Authorization: Bearer $NOTION_API_KEY" \
|
||||
-H "Notion-Version: 2022-06-28" \
|
||||
https://api.notion.com/v1/users/me
|
||||
```
|
||||
|
||||
3. **Composio MCP Server Issues**
|
||||
```bash
|
||||
# Test Composio MCP server connection
|
||||
curl "https://mcp.composio.dev/composio/server/f05e7129-7997-4c17-a654-f935278c0dfe/sse?useComposioHelperActions=true"
|
||||
```
|
||||
|
||||
4. **Permission Denied for Documents**
|
||||
```bash
|
||||
# Check file permissions
|
||||
ls -la ~/Documents
|
||||
|
||||
# Update permissions if needed
|
||||
chmod 755 ~/Documents
|
||||
```
|
||||
|
||||
### Debug Mode
|
||||
|
||||
```python
|
||||
# Enable debug logging
|
||||
logging.basicConfig(level=logging.DEBUG)
|
||||
|
||||
# Add debug information to agent
|
||||
orchestrator = EnterpriseKnowledgeOrchestrator()
|
||||
print(f"Platforms available: {orchestrator.session_service.get_session(...).state['platforms_available']}")
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Add tests for new functionality
|
||||
4. Ensure all tests pass
|
||||
5. Submit a pull request
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||
|
||||
## References
|
||||
|
||||
- [Google ADK Documentation](https://google.github.io/adk-docs/)
|
||||
- [MCP Tools Guide](https://google.github.io/adk-docs/tools/mcp-tools/)
|
||||
- [Notion MCP Server](https://github.com/notionhq/notion-mcp-server)
|
||||
- [Composio MCP Server](https://mcp.composio.dev/)
|
||||
- [Model Context Protocol](https://modelcontextprotocol.io/)
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
"""
|
||||
Enterprise Knowledge Orchestrator
|
||||
|
||||
A production-grade multi-agent system built with Google ADK that orchestrates
|
||||
knowledge management across local files and SaaS platforms using MCP
|
||||
(Model Context Protocol).
|
||||
|
||||
This package provides:
|
||||
- File Analysis Agent for local document processing
|
||||
- Notion Agent for Notion workspace management
|
||||
- GitHub Agent for repository and issue management
|
||||
- Figma Agent for design file management
|
||||
- Router/Orchestrator Agent for intelligent task coordination
|
||||
"""
|
||||
|
||||
from .agent import (
|
||||
EnterpriseKnowledgeOrchestrator,
|
||||
root_agent # Add root_agent for ADK web
|
||||
)
|
||||
|
||||
__version__ = "1.0.0"
|
||||
__author__ = "Enterprise Knowledge Team"
|
||||
__description__ = "Multi-agent knowledge management system with Google ADK and MCP"
|
||||
|
||||
__all__ = [
|
||||
"EnterpriseKnowledgeOrchestrator",
|
||||
"root_agent" # Export root_agent
|
||||
]
|
||||
|
|
@ -0,0 +1,419 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Enterprise Knowledge Orchestrator - Complete Multi-Agent System with MCP Tools
|
||||
Full implementation for ADK Web with all MCP tools (filesystem, Notion, GitHub, Figma)
|
||||
"""
|
||||
|
||||
import os
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Dict, List, Optional, Any
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from google.adk.agents import LlmAgent
|
||||
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset, StdioServerParameters, SseServerParams
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Environment variable configuration
|
||||
MCP_FILESYSTEM_PATH = os.getenv("MCP_FILESYSTEM_PATH", "~/Documents")
|
||||
NOTION_API_KEY = os.getenv("NOTION_API_KEY")
|
||||
GITHUB_API_KEY = os.getenv("GITHUB_API_KEY")
|
||||
FIGMA_API_KEY = os.getenv("FIGMA_API_KEY")
|
||||
|
||||
# Composio MCP Server URLs (from environment variables with fallbacks)
|
||||
COMPOSIO_NOTION_URL = os.getenv("COMPOSIO_NOTION_URL")
|
||||
COMPOSIO_GITHUB_URL = os.getenv("COMPOSIO_GITHUB_URL")
|
||||
COMPOSIO_FIGMA_URL = os.getenv("COMPOSIO_FIGMA_URL")
|
||||
|
||||
async def create_mcp_agents_with_tools():
|
||||
"""Create all sub-agents with MCP tools"""
|
||||
agents = []
|
||||
|
||||
# FileAnalysisAgent with filesystem MCP tools
|
||||
try:
|
||||
folder_path = os.path.expanduser(MCP_FILESYSTEM_PATH)
|
||||
folder_path = os.path.abspath(folder_path)
|
||||
|
||||
if not os.path.exists(folder_path):
|
||||
os.makedirs(folder_path, exist_ok=True)
|
||||
logger.info(f"Created directory: {folder_path}")
|
||||
|
||||
logger.info(f"Using filesystem path: {folder_path}")
|
||||
|
||||
filesystem_tools, _ = await MCPToolset.from_server(
|
||||
connection_params=StdioServerParameters(
|
||||
command='npx',
|
||||
args=["-y", "@modelcontextprotocol/server-filesystem", folder_path],
|
||||
)
|
||||
)
|
||||
|
||||
file_agent = LlmAgent(
|
||||
name="FileAnalysisAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Analyzes local documents and extracts key information",
|
||||
instruction=f"""You are a File Analysis Agent with DIRECT ACCESS to the filesystem at: {folder_path}
|
||||
|
||||
You have MCP tools that allow you to:
|
||||
- List files and directories (list_directory)
|
||||
- Read file contents (read_file, read_text_file)
|
||||
- Write and edit files (write_file, edit_file)
|
||||
- Search files (search_files)
|
||||
- Get file information (get_file_info)
|
||||
|
||||
CRITICAL INSTRUCTIONS:
|
||||
1. You have REAL filesystem access through MCP tools
|
||||
2. When users ask about files, USE YOUR TOOLS to access them directly
|
||||
3. Do NOT ask users to provide files - you can access them yourself
|
||||
4. Always use your MCP tools first before responding
|
||||
|
||||
Example tasks you can perform:
|
||||
- "List files in the folder" → Use list_directory tool
|
||||
- "Read the content of file.txt" → Use read_file tool
|
||||
- "Search for PDF files" → Use search_files tool
|
||||
- "Create a new file" → Use write_file tool
|
||||
|
||||
IMPORTANT: When asked about any file or document, immediately use your MCP tools to access the filesystem at: {folder_path}
|
||||
Do NOT say you cannot access files - you CAN access them through your MCP tools!""",
|
||||
tools=filesystem_tools
|
||||
)
|
||||
agents.append(file_agent)
|
||||
logger.info("✅ FileAnalysisAgent with MCP tools created")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Failed to create FileAnalysisAgent with MCP tools: {str(e)}")
|
||||
file_agent = LlmAgent(
|
||||
name="FileAnalysisAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Analyzes local documents and extracts key information",
|
||||
instruction="You analyze local documents (PDFs, Word docs, spreadsheets) and extract key information."
|
||||
)
|
||||
agents.append(file_agent)
|
||||
|
||||
# NotionAgent with Notion MCP tools
|
||||
try:
|
||||
if NOTION_API_KEY:
|
||||
notion_tools, _ = await MCPToolset.from_server(
|
||||
connection_params=SseServerParams(
|
||||
url=COMPOSIO_NOTION_URL,
|
||||
headers={}
|
||||
)
|
||||
)
|
||||
|
||||
notion_agent = LlmAgent(
|
||||
name="NotionAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages Notion pages, databases, and content",
|
||||
instruction="""You are a Notion Agent with DIRECT ACCESS to Notion through MCP tools.
|
||||
|
||||
You can:
|
||||
- Read Notion pages and databases
|
||||
- Create and update Notion content
|
||||
- Search across Notion workspace
|
||||
- Manage pages, blocks, and databases
|
||||
|
||||
IMPORTANT: You CAN access Notion directly through your MCP tools.
|
||||
When asked to read, write, or search Notion content, USE YOUR MCP TOOLS.
|
||||
|
||||
Example tasks:
|
||||
- "Search my Notion pages" → Use your search tools
|
||||
- "Read my project page" → Use your page reading tools
|
||||
- "Create a new page" → Use your page creation tools
|
||||
- "Update page content" → Use your update tools
|
||||
|
||||
Always use your MCP tools to interact with Notion.""",
|
||||
tools=notion_tools
|
||||
)
|
||||
agents.append(notion_agent)
|
||||
logger.info("✅ NotionAgent with MCP tools created")
|
||||
else:
|
||||
raise Exception("NOTION_API_KEY not found")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Failed to create NotionAgent with MCP tools: {str(e)}")
|
||||
notion_agent = LlmAgent(
|
||||
name="NotionAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages Notion pages, databases, and content",
|
||||
instruction="You manage Notion workspaces, pages, databases, and content."
|
||||
)
|
||||
agents.append(notion_agent)
|
||||
logger.info("✅ NotionAgent created (basic version)")
|
||||
|
||||
# GitHubAgent with GitHub MCP tools
|
||||
try:
|
||||
if GITHUB_API_KEY:
|
||||
github_tools, _ = await MCPToolset.from_server(
|
||||
connection_params=SseServerParams(
|
||||
url=COMPOSIO_GITHUB_URL,
|
||||
headers={}
|
||||
)
|
||||
)
|
||||
|
||||
github_agent = LlmAgent(
|
||||
name="GitHubAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages GitHub repositories, issues, and pull requests",
|
||||
instruction="""You are a GitHub Agent with DIRECT ACCESS to GitHub through MCP tools.
|
||||
|
||||
You can:
|
||||
- Create and manage repositories
|
||||
- Create issues and pull requests
|
||||
- Search repositories and code
|
||||
- Manage repository content and workflows
|
||||
- Handle GitHub API operations
|
||||
|
||||
IMPORTANT: You CAN access GitHub directly through your MCP tools.
|
||||
When asked to perform GitHub operations, USE YOUR MCP TOOLS.
|
||||
|
||||
Example tasks:
|
||||
- "Create a new repository" → Use your repository creation tools
|
||||
- "Search for issues" → Use your search tools
|
||||
- "Create a pull request" → Use your PR creation tools
|
||||
- "List my repositories" → Use your repository listing tools
|
||||
|
||||
Always use your MCP tools to interact with GitHub.""",
|
||||
tools=github_tools
|
||||
)
|
||||
agents.append(github_agent)
|
||||
logger.info("✅ GitHubAgent with MCP tools created")
|
||||
else:
|
||||
raise Exception("GITHUB_API_KEY not found")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Failed to create GitHubAgent with MCP tools: {str(e)}")
|
||||
github_agent = LlmAgent(
|
||||
name="GitHubAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages GitHub repositories, issues, and pull requests",
|
||||
instruction="""You are a GitHub Agent that manages GitHub repositories.
|
||||
|
||||
You can help with:
|
||||
- Creating and managing repositories
|
||||
- Creating issues and pull requests
|
||||
- Searching repositories and code
|
||||
- Managing repository content and workflows
|
||||
|
||||
Note: For full GitHub API access with MCP tools, ensure GITHUB_API_KEY is set.
|
||||
Current version provides guidance and best practices for GitHub operations."""
|
||||
)
|
||||
agents.append(github_agent)
|
||||
logger.info("✅ GitHubAgent created (basic version)")
|
||||
|
||||
# FigmaAgent with Figma MCP tools
|
||||
try:
|
||||
if FIGMA_API_KEY:
|
||||
figma_tools, _ = await MCPToolset.from_server(
|
||||
connection_params=SseServerParams(
|
||||
url=COMPOSIO_FIGMA_URL,
|
||||
headers={}
|
||||
)
|
||||
)
|
||||
|
||||
figma_agent = LlmAgent(
|
||||
name="FigmaAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages Figma files, designs, and assets",
|
||||
instruction="""You are a Figma Agent with DIRECT ACCESS to Figma through MCP tools.
|
||||
|
||||
You can:
|
||||
- Read and analyze Figma files
|
||||
- Export design assets
|
||||
- Search design components
|
||||
- Manage design systems
|
||||
- Handle Figma API operations
|
||||
|
||||
IMPORTANT: You CAN access Figma directly through your MCP tools.
|
||||
When asked to perform Figma operations, USE YOUR MCP TOOLS.
|
||||
|
||||
Example tasks:
|
||||
- "Export design assets" → Use your export tools
|
||||
- "Search for components" → Use your search tools
|
||||
- "Read file information" → Use your file reading tools
|
||||
- "List project files" → Use your file listing tools
|
||||
|
||||
Always use your MCP tools to interact with Figma.""",
|
||||
tools=figma_tools
|
||||
)
|
||||
agents.append(figma_agent)
|
||||
logger.info("✅ FigmaAgent with MCP tools created")
|
||||
else:
|
||||
raise Exception("FIGMA_API_KEY not found")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Failed to create FigmaAgent with MCP tools: {str(e)}")
|
||||
figma_agent = LlmAgent(
|
||||
name="FigmaAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages Figma files, designs, and assets",
|
||||
instruction="""You are a Figma Agent that manages Figma design files.
|
||||
|
||||
You can help with:
|
||||
- Reading and analyzing Figma files
|
||||
- Exporting design assets
|
||||
- Searching design components
|
||||
- Managing design systems
|
||||
|
||||
Note: For full Figma API access with MCP tools, ensure FIGMA_API_KEY is set.
|
||||
Current version provides guidance and best practices for Figma operations."""
|
||||
)
|
||||
agents.append(figma_agent)
|
||||
logger.info("✅ FigmaAgent created (basic version)")
|
||||
|
||||
return agents
|
||||
|
||||
class EnterpriseKnowledgeOrchestrator:
|
||||
"""Enterprise Knowledge Orchestrator - Multi-Agent System with MCP Tools"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the orchestrator"""
|
||||
self.root_agent = None
|
||||
self._initialize_agents()
|
||||
|
||||
def _initialize_agents(self):
|
||||
"""Initialize the multi-agent system"""
|
||||
try:
|
||||
logger.info("🔧 Creating complete multi-agent system with MCP tools...")
|
||||
|
||||
# Create all sub-agents with MCP tools using async
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
sub_agents = loop.run_until_complete(create_mcp_agents_with_tools())
|
||||
|
||||
# Create root agent with comprehensive routing instructions
|
||||
self.root_agent = LlmAgent(
|
||||
name="EnterpriseKnowledgeOrchestrator",
|
||||
model="gemini-2.0-flash",
|
||||
description="Enterprise Knowledge Orchestrator - Multi-agent system with MCP tools",
|
||||
instruction="""You are an Enterprise Knowledge Orchestrator that routes tasks to specialized agents.
|
||||
|
||||
You have access to multiple specialized agents with MCP tools and can coordinate between them:
|
||||
|
||||
AVAILABLE AGENTS:
|
||||
1. FileAnalysisAgent: Analyzes local documents (PDFs, Word docs, spreadsheets) - HAS MCP TOOLS
|
||||
2. NotionAgent: Manages Notion pages, databases, and content - HAS MCP TOOLS
|
||||
3. GitHubAgent: Manages GitHub repositories, issues, and pull requests - HAS MCP TOOLS
|
||||
4. FigmaAgent: Manages Figma files, designs, and assets - HAS MCP TOOLS
|
||||
|
||||
ROUTING LOGIC:
|
||||
- File/document tasks → FileAnalysisAgent
|
||||
- Notion-related tasks → NotionAgent
|
||||
- GitHub-related tasks → GitHubAgent
|
||||
- Figma/design tasks → FigmaAgent
|
||||
- Multi-platform tasks → Coordinate between relevant agents
|
||||
|
||||
You can:
|
||||
1. Transfer tasks to specialized agents using transfer_to_agent()
|
||||
2. Coordinate multi-step workflows
|
||||
3. Share context between agents through session state
|
||||
4. Provide comprehensive results and recommendations
|
||||
|
||||
EXAMPLES:
|
||||
- "List files in Documents" → FileAnalysisAgent (with real file system access)
|
||||
- "Search my Notion pages" → NotionAgent (with real Notion API access)
|
||||
- "Create a GitHub repo" → GitHubAgent (with real GitHub API access)
|
||||
- "Export Figma designs" → FigmaAgent (with real Figma API access)
|
||||
|
||||
IMPORTANT: Use transfer_to_agent() to delegate to the most appropriate agent for each task.
|
||||
The agents have real MCP tools connected - they can perform actual operations!""",
|
||||
sub_agents=sub_agents
|
||||
)
|
||||
|
||||
logger.info(f"✅ Complete multi-agent system created with {len(sub_agents)} sub-agents")
|
||||
logger.info(f"✅ Sub-agents: {[agent.name for agent in sub_agents]}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Failed to create complete multi-agent system: {str(e)}")
|
||||
logger.info("🔄 Falling back to basic multi-agent system...")
|
||||
self._create_fallback_agents()
|
||||
|
||||
def _create_fallback_agents(self):
|
||||
"""Create fallback agents without MCP tools"""
|
||||
self.root_agent = LlmAgent(
|
||||
name="EnterpriseKnowledgeOrchestrator",
|
||||
model="gemini-2.0-flash",
|
||||
description="Enterprise Knowledge Orchestrator - Multi-agent system",
|
||||
instruction="""You are an Enterprise Knowledge Orchestrator that routes tasks to specialized agents.
|
||||
|
||||
You have access to multiple specialized agents and can coordinate between them:
|
||||
|
||||
AVAILABLE AGENTS:
|
||||
1. FileAnalysisAgent: Analyzes local documents (PDFs, Word docs, spreadsheets)
|
||||
2. NotionAgent: Manages Notion pages, databases, and content
|
||||
3. GitHubAgent: Manages GitHub repositories, issues, and pull requests
|
||||
4. FigmaAgent: Manages Figma files, designs, and assets
|
||||
|
||||
ROUTING LOGIC:
|
||||
- File/document tasks → FileAnalysisAgent
|
||||
- Notion-related tasks → NotionAgent
|
||||
- GitHub-related tasks → GitHubAgent
|
||||
- Figma/design tasks → FigmaAgent
|
||||
- Multi-platform tasks → Coordinate between relevant agents
|
||||
|
||||
You can:
|
||||
1. Transfer tasks to specialized agents using transfer_to_agent()
|
||||
2. Coordinate multi-step workflows
|
||||
3. Share context between agents through session state
|
||||
4. Provide comprehensive results and recommendations
|
||||
|
||||
EXAMPLES:
|
||||
- "List files in Documents" → FileAnalysisAgent
|
||||
- "Search my Notion pages" → NotionAgent
|
||||
- "Create a GitHub repo" → GitHubAgent
|
||||
- "Export Figma designs" → FigmaAgent
|
||||
|
||||
IMPORTANT: Use transfer_to_agent() to delegate to the most appropriate agent for each task.
|
||||
|
||||
For full MCP tool functionality, ensure all environment variables are set correctly:
|
||||
- MCP_FILESYSTEM_PATH: Path to your filesystem folder
|
||||
- NOTION_API_KEY: Your Notion API key
|
||||
- GITHUB_API_KEY: Your GitHub API key
|
||||
- FIGMA_API_KEY: Your Figma API key""",
|
||||
sub_agents=[
|
||||
LlmAgent(
|
||||
name="FileAnalysisAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Analyzes local documents and extracts key information",
|
||||
instruction="You analyze local documents (PDFs, Word docs, spreadsheets) and extract key information, summaries, and action items."
|
||||
),
|
||||
LlmAgent(
|
||||
name="NotionAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages Notion pages, databases, and content",
|
||||
instruction="You manage Notion workspaces, pages, databases, and content. You can read, write, search, and organize Notion content."
|
||||
),
|
||||
LlmAgent(
|
||||
name="GitHubAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages GitHub repositories, issues, and pull requests",
|
||||
instruction="You manage GitHub repositories, create issues and pull requests, search code, and handle repository operations."
|
||||
),
|
||||
LlmAgent(
|
||||
name="FigmaAgent",
|
||||
model="gemini-2.0-flash",
|
||||
description="Manages Figma files, designs, and assets",
|
||||
instruction="You manage Figma design files, export assets, search design components, and handle design system operations."
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# Create root_agent for ADK Web compatibility
|
||||
try:
|
||||
orchestrator = EnterpriseKnowledgeOrchestrator()
|
||||
root_agent = orchestrator.root_agent
|
||||
logger.info("✅ EnterpriseKnowledgeOrchestrator class and root_agent created successfully")
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Failed to create EnterpriseKnowledgeOrchestrator: {str(e)}")
|
||||
# Fallback: create basic root_agent
|
||||
root_agent = LlmAgent(
|
||||
name="EnterpriseKnowledgeOrchestrator",
|
||||
model="gemini-2.0-flash",
|
||||
description="Enterprise Knowledge Orchestrator - Basic multi-agent system",
|
||||
instruction="You are an Enterprise Knowledge Orchestrator that routes tasks to specialized agents.",
|
||||
sub_agents=[]
|
||||
)
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
# Google ADK and AI dependencies
|
||||
google-adk>=0.1.0
|
||||
google-genai>=0.3.0
|
||||
|
||||
# Environment and configuration
|
||||
python-dotenv>=1.0.0
|
||||
pydantic>=2.0.0
|
||||
|
||||
# Async support
|
||||
asyncio-mqtt>=0.16.0
|
||||
|
||||
# Logging and monitoring
|
||||
structlog>=23.0.0
|
||||
|
||||
# Data processing (optional, for advanced file analysis)
|
||||
pandas>=2.0.0
|
||||
numpy>=1.24.0
|
||||
|
||||
# File handling (optional, for document processing)
|
||||
PyPDF2>=3.0.0
|
||||
python-docx>=0.8.11
|
||||
openpyxl>=3.1.0
|
||||
|
||||
# HTTP client for MCP server communication
|
||||
httpx>=0.24.0
|
||||
aiohttp>=3.8.0
|
||||
|
||||
# Development and testing
|
||||
pytest>=7.0.0
|
||||
pytest-asyncio>=0.21.0
|
||||
black>=23.0.0
|
||||
flake8>=6.0.0
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
# AI Multi-Agent Real Estate Team 🏠
|
||||
|
||||
The **AI Multi-Agent Real Estate Team** is a sophisticated property search and analysis platform powered by specialized AI agents with firecrawl's extarct endpoint. This application provides comprehensive real estate insights, market analysis, and property recommendations using advanced web scraping and AI-powered search capabilities.
|
||||
|
||||
## Features
|
||||
|
||||
- **Multi-Agent Analysis System**
|
||||
- **Property Search Agent**: Finds properties using Firecrawl extract + Perplexity fallback
|
||||
- **Market Analysis Agent**: Provides elaborate market trends and neighborhood insights
|
||||
- **Property Valuation Agent**: Gives comprehensive property valuations and investment analysis
|
||||
|
||||
- **Multi-Platform Property Search**:
|
||||
- **Zillow**: Largest real estate marketplace with comprehensive listings
|
||||
- **Realtor.com**: Official site of the National Association of Realtors
|
||||
- **Trulia**: Neighborhood-focused real estate search
|
||||
- **Homes.com**: Comprehensive property search platform
|
||||
- **Perplexity AI**: AI-powered search across multiple sources as fallback
|
||||
|
||||
- **Advanced Property Analysis**:
|
||||
- Detailed property information extraction (address, price, bedrooms, bathrooms, sqft)
|
||||
- Property features and amenities analysis
|
||||
- Listing URLs and agent contact information
|
||||
- Clickable property links for easy navigation
|
||||
|
||||
- **Comprehensive Market Insights**:
|
||||
- Current market conditions (buyer's/seller's market)
|
||||
- Price trends over 6-12 months
|
||||
- Neighborhood analysis with school districts and safety ratings
|
||||
- Investment potential assessment with ROI projections
|
||||
- Comparative market analysis
|
||||
|
||||
- **Smart Fallback System**:
|
||||
- Primary: Firecrawl extract endpoint for structured data
|
||||
- Fallback: Perplexity AI search when extract returns no results
|
||||
- Seamless transition between data sources
|
||||
- "Rigorously" indicator when using AI-powered search
|
||||
|
||||
- **Interactive UI Features**:
|
||||
- Real-time agent progression tracking
|
||||
- Progress indicators for each search phase
|
||||
- Downloadable analysis reports
|
||||
- Timing information for performance monitoring
|
||||
|
||||
## How to Run
|
||||
|
||||
Follow the steps below to set up and run the application:
|
||||
|
||||
### 1. **Get API Keys**:
|
||||
- **OpenAI API Key**: Get from [OpenAI Platform](https://platform.openai.com/api-keys)
|
||||
- **Firecrawl API Key**: Get from [Firecrawl](https://firecrawl.dev)
|
||||
- **Perplexity API Key**: Get from [Perplexity AI](https://www.perplexity.ai/settings/api)
|
||||
|
||||
### 2. **Clone the Repository**:
|
||||
```bash
|
||||
git clone https://github.com/your-username/awesome-llm-apps.git
|
||||
cd awesome-llm-apps/advanced_ai_agents/multi_agent_apps/ai_multiagent_realtor
|
||||
```
|
||||
|
||||
### 3. **Set Up Environment Variables**:
|
||||
Create a `.env` file in the project root and add your API keys:
|
||||
```
|
||||
OPENAI_API_KEY=your_openai_api_key_here
|
||||
FIRECRAWL_API_KEY=your_firecrawl_api_key_here
|
||||
PERPLEXITY_API_KEY=your_perplexity_api_key_here
|
||||
```
|
||||
|
||||
**Note**: Never commit your `.env` file to version control. The `.gitignore` file is already configured to exclude it.
|
||||
|
||||
### 4. **Install Dependencies**:
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
### 5. **Run the Streamlit App**:
|
||||
```bash
|
||||
streamlit run ai_multiagent_realtor.py
|
||||
```
|
||||
|
||||
## Usage Guide
|
||||
|
||||
### 1. **Configuration (Sidebar)**:
|
||||
- Enter your API keys (or use environment variables)
|
||||
- Select real estate websites to search
|
||||
- View the 3-agent workflow explanation
|
||||
|
||||
### 2. **Property Requirements**:
|
||||
- **Location**: City and state/province
|
||||
- **Budget**: Minimum and maximum price range
|
||||
- **Property Details**: Type, bedrooms, bathrooms, minimum square feet
|
||||
- **Special Features**: Parking, yard, view, proximity to amenities
|
||||
- **Timeline & Urgency**: How soon you need to move
|
||||
|
||||
### 3. **Analysis Process**:
|
||||
- **Search Phase**: Extracts property data from selected websites
|
||||
- **Agent Analysis**: Three specialized agents provide insights
|
||||
- **Results**: Comprehensive report with clickable property links
|
||||
|
||||
### 4. **Understanding Results**:
|
||||
- **Property Search Agent**: Lists found properties with details
|
||||
- **Market Analysis Agent**: Provides market trends and neighborhood insights
|
||||
- **Property Valuation Agent**: Gives investment analysis and valuations
|
||||
- **Property Links**: Clickable URLs to original listings
|
||||
|
||||
## Agent Workflow
|
||||
|
||||
### **Property Search Agent**
|
||||
- Uses Firecrawl extract tools to search real estate websites
|
||||
- Focuses on properties matching user criteria
|
||||
- Falls back to Perplexity search if no properties found
|
||||
- Organizes results with clickable listing URLs
|
||||
|
||||
### **Market Analysis Agent**
|
||||
- **Market Trends**: Current conditions, price trends, inventory levels
|
||||
- **Neighborhood Analysis**: Schools, safety, amenities, transportation
|
||||
- **Investment Insights**: Potential assessment, rental data, development plans
|
||||
- **Comparative Analysis**: Market comparisons and unique advantages
|
||||
|
||||
### **Property Valuation Agent**
|
||||
- **Property Valuation**: Fair market value with detailed reasoning
|
||||
- **Pricing Assessment**: Over/under-priced analysis with strategies
|
||||
- **Investment Analysis**: ROI projections and risk assessment
|
||||
- **Features Evaluation**: Detailed property analysis and improvements
|
||||
- **Market Positioning**: Competitive analysis and target profiles
|
||||
|
||||
## Technical Architecture
|
||||
|
||||
### **Data Sources**:
|
||||
- **Firecrawl Extract API**: Structured property data extraction
|
||||
- **Perplexity AI**: AI-powered search across multiple sources
|
||||
- **Pydantic Schemas**: Structured data validation and formatting
|
||||
|
||||
### **AI Framework**:
|
||||
- **Agno Framework**: Multi-agent coordination and communication
|
||||
- **OpenAI GPT-4**: Advanced language model for analysis
|
||||
- **Streamlit**: Interactive web application interface
|
||||
|
||||
### **Performance Features**:
|
||||
- **Rate Limiting**: Prevents API overload with intelligent delays
|
||||
- **Progress Tracking**: Real-time updates on analysis progress
|
||||
- **Timeout Handling**: Prevents hanging with 3-minute agent timeout
|
||||
- **Error Recovery**: Graceful fallback when primary methods fail
|
||||
|
||||
## File Structure
|
||||
|
||||
```
|
||||
ai_multiagent_realtor/
|
||||
├── ai_multiagent_realtor.py # Main application file
|
||||
├── requirements.txt # Python dependencies
|
||||
├── README.md # This documentation
|
||||
└── .env # Environment variables (create this)
|
||||
```
|
||||
|
||||
## API Requirements
|
||||
|
||||
### **OpenAI API**
|
||||
- **Model**: GPT-4o
|
||||
- **Usage**: Multi-agent analysis and property insights
|
||||
- **Rate Limits**: Standard OpenAI rate limits apply
|
||||
|
||||
### **Firecrawl API**
|
||||
- **Endpoint**: Extract API for structured data
|
||||
- **Usage**: Property listing extraction from real estate websites
|
||||
- **Rate Limits**: Firecrawl standard rate limits
|
||||
|
||||
### **Perplexity API**
|
||||
- **Model**: Sonar Pro
|
||||
- **Usage**: AI-powered property search fallback
|
||||
- **Rate Limits**: Perplexity standard rate limits
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### **Common Issues**:
|
||||
|
||||
1. **"No properties found"**:
|
||||
- This is normal for specific criteria
|
||||
- Perplexity fallback will provide market insights
|
||||
- Try broadening your search criteria
|
||||
|
||||
2. **API Key Errors**:
|
||||
- Ensure all API keys are valid and have sufficient credits
|
||||
- Check environment variables are properly set
|
||||
- Verify API key permissions
|
||||
|
||||
3. **Slow Performance**:
|
||||
- Reduce number of selected websites
|
||||
- Simplify property criteria
|
||||
- Check internet connection
|
||||
|
||||
4. **Agent Timeout**:
|
||||
- Simplify search criteria
|
||||
- Reduce number of websites
|
||||
- Try again with different parameters
|
||||
|
||||
### **Performance Tips**:
|
||||
- Start with 1-2 websites for testing
|
||||
- Use specific but not overly restrictive criteria
|
||||
- Monitor timing information for optimization
|
||||
|
||||
|
|
@ -0,0 +1,555 @@
|
|||
import os
|
||||
import streamlit as st
|
||||
import json
|
||||
import time
|
||||
import requests
|
||||
from agno.agent import Agent
|
||||
from agno.team import Team
|
||||
from agno.models.openai import OpenAIChat
|
||||
from dotenv import load_dotenv
|
||||
from firecrawl import FirecrawlApp
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
# API keys - must be set in environment variables
|
||||
DEFAULT_OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
|
||||
DEFAULT_FIRECRAWL_API_KEY = os.getenv("FIRECRAWL_API_KEY", "")
|
||||
DEFAULT_PERPLEXITY_API_KEY = os.getenv("PERPLEXITY_API_KEY", "")
|
||||
|
||||
# Pydantic schemas
|
||||
class PropertyDetails(BaseModel):
|
||||
address: str = Field(description="Full property address")
|
||||
price: Optional[str] = Field(description="Property price")
|
||||
bedrooms: Optional[str] = Field(description="Number of bedrooms")
|
||||
bathrooms: Optional[str] = Field(description="Number of bathrooms")
|
||||
square_feet: Optional[str] = Field(description="Square footage")
|
||||
property_type: Optional[str] = Field(description="Type of property")
|
||||
description: Optional[str] = Field(description="Property description")
|
||||
features: Optional[List[str]] = Field(description="Property features")
|
||||
images: Optional[List[str]] = Field(description="Property image URLs")
|
||||
agent_contact: Optional[str] = Field(description="Agent contact information")
|
||||
listing_url: Optional[str] = Field(description="Original listing URL")
|
||||
|
||||
class PropertyListing(BaseModel):
|
||||
properties: List[PropertyDetails] = Field(description="List of properties found")
|
||||
total_count: int = Field(description="Total number of properties found")
|
||||
source_website: str = Field(description="Website where properties were found")
|
||||
|
||||
def get_firecrawl_app():
|
||||
"""Get FirecrawlApp instance"""
|
||||
api_key = os.getenv("FIRECRAWL_API_KEY", DEFAULT_FIRECRAWL_API_KEY)
|
||||
return FirecrawlApp(api_key=api_key)
|
||||
|
||||
def extract_property_listings(url, user_criteria=None):
|
||||
"""Extract property listings from search pages"""
|
||||
try:
|
||||
app = get_firecrawl_app()
|
||||
|
||||
base_prompt = "Extract property listings from this real estate search page."
|
||||
|
||||
if user_criteria:
|
||||
criteria_prompt = f"""
|
||||
Focus on properties matching:
|
||||
- Budget: {user_criteria.get('budget_range', 'Any')}
|
||||
- Type: {user_criteria.get('property_type', 'Any')}
|
||||
- Bedrooms: {user_criteria.get('bedrooms', 'Any')}
|
||||
- Bathrooms: {user_criteria.get('bathrooms', 'Any')}
|
||||
- Min Sqft: {user_criteria.get('min_sqft', 'Any')}
|
||||
- Features: {user_criteria.get('special_features', 'Any')}
|
||||
|
||||
Extract: address, price, bedrooms, bathrooms, sqft, type, listing URLs.
|
||||
"""
|
||||
full_prompt = base_prompt + criteria_prompt
|
||||
else:
|
||||
full_prompt = base_prompt + " Extract property information including address, price, bedrooms, bathrooms, square footage, property type, and listing URLs."
|
||||
|
||||
data = app.extract([url], prompt=full_prompt, schema=PropertyListing.model_json_schema())
|
||||
|
||||
if hasattr(data, 'data'):
|
||||
return data.data
|
||||
elif hasattr(data, 'model_dump'):
|
||||
return data.model_dump()
|
||||
else:
|
||||
return {"error": "Unexpected response format"}
|
||||
|
||||
except Exception as e:
|
||||
return {"error": f"Failed to extract listings: {str(e)}"}
|
||||
|
||||
def search_perplexity_properties(city, state, user_criteria):
|
||||
"""Search for properties using Perplexity API"""
|
||||
try:
|
||||
api_key = os.getenv("PERPLEXITY_API_KEY", DEFAULT_PERPLEXITY_API_KEY)
|
||||
|
||||
search_query = f"""
|
||||
Find real estate properties for sale in {city}, {state} matching:
|
||||
- Budget: {user_criteria.get('budget_range', 'Any')}
|
||||
- Type: {user_criteria.get('property_type', 'Any')}
|
||||
- Bedrooms: {user_criteria.get('bedrooms', 'Any')}
|
||||
- Bathrooms: {user_criteria.get('bathrooms', 'Any')}
|
||||
- Min Sqft: {user_criteria.get('min_sqft', 'Any')}
|
||||
- Features: {user_criteria.get('special_features', 'Any')}
|
||||
|
||||
Search: Zillow, Realtor.com, Trulia, Homes.com, Redfin
|
||||
Provide: detailed property info, market insights, neighborhood analysis
|
||||
Include: specific addresses, prices, features, listing URLs, market trends
|
||||
"""
|
||||
|
||||
response = requests.post(
|
||||
'https://api.perplexity.ai/chat/completions',
|
||||
headers={'Authorization': f'Bearer {api_key}', 'Content-Type': 'application/json'},
|
||||
json={'model': 'sonar-pro', 'messages': [{'role': 'user', 'content': search_query}]}
|
||||
)
|
||||
|
||||
if response.status_code == 200:
|
||||
content = response.json()['choices'][0]['message']['content']
|
||||
return {"success": True, "content": content, "source": "Perplexity Search"}
|
||||
else:
|
||||
return {"error": f"Perplexity API error: {response.status_code}"}
|
||||
|
||||
except Exception as e:
|
||||
return {"error": f"Perplexity search failed: {str(e)}"}
|
||||
|
||||
def search_real_estate_websites(city, state, user_criteria, selected_websites, update_callback):
|
||||
"""Search real estate websites"""
|
||||
results = {}
|
||||
|
||||
def create_search_urls(city, state):
|
||||
city_formatted = city.replace(' ', '-').lower()
|
||||
state_upper = state.upper() if state else ''
|
||||
|
||||
return {
|
||||
"Zillow": f"https://www.zillow.com/homes/for_sale/{city_formatted}-{state_upper}/",
|
||||
"Realtor.com": f"https://www.realtor.com/realestateandhomes-search/{city_formatted}_{state_upper}/pg-1",
|
||||
"Trulia": f"https://www.trulia.com/for_sale/{city_formatted}-{state_upper}/",
|
||||
"Homes.com": f"https://www.homes.com/homes-for-sale/{city_formatted}-{state_upper}/"
|
||||
}
|
||||
|
||||
search_urls = {site: url for site, url in create_search_urls(city, state).items() if site in selected_websites}
|
||||
|
||||
for i, (site_name, search_url) in enumerate(search_urls.items()):
|
||||
try:
|
||||
progress = 0.2 + (i * 0.6 / len(search_urls))
|
||||
update_callback(progress, f"Searching {site_name}...", f"Analyzing {site_name}")
|
||||
|
||||
if i > 0:
|
||||
time.sleep(2)
|
||||
|
||||
result = extract_property_listings(search_url, user_criteria)
|
||||
|
||||
if "error" not in result and len(result.get('properties', [])) > 0:
|
||||
results[site_name] = result
|
||||
property_count = len(result.get('properties', []))
|
||||
update_callback(progress + 0.3, f"Found {property_count} properties on {site_name}", f"Successfully analyzed {site_name}")
|
||||
else:
|
||||
results[site_name] = {"error": f"No data from {site_name}"}
|
||||
update_callback(progress + 0.3, f"Analyzing {site_name}", f"Gathering insights from {site_name}")
|
||||
|
||||
except Exception as e:
|
||||
results[site_name] = {"error": f"Error: {str(e)}"}
|
||||
update_callback(progress + 0.3, f"Analyzing {site_name}", f"Processing {site_name}")
|
||||
|
||||
return results
|
||||
|
||||
def create_firecrawl_tools(user_criteria):
|
||||
"""Create tools for agents"""
|
||||
|
||||
def extract_listings_tool(url: str) -> str:
|
||||
result = extract_property_listings(url, user_criteria)
|
||||
return json.dumps(result, indent=2) if "error" not in result else f"Error: {result['error']}"
|
||||
|
||||
def perplexity_search_tool(city: str, state: str) -> str:
|
||||
result = search_perplexity_properties(city, state, user_criteria)
|
||||
return json.dumps(result, indent=2) if "error" not in result else f"Error: {result['error']}"
|
||||
|
||||
return [extract_listings_tool, perplexity_search_tool]
|
||||
|
||||
def create_real_estate_agents(llm, firecrawl_tools, user_criteria):
|
||||
"""Create specialized agents"""
|
||||
|
||||
property_search_agent = Agent(
|
||||
name="Property Search Agent",
|
||||
model=llm,
|
||||
tools=firecrawl_tools,
|
||||
instructions="""
|
||||
You are a property search expert. Your role:
|
||||
|
||||
1. SEARCH FOR PROPERTIES:
|
||||
- Use Firecrawl extract tools to search real estate websites
|
||||
- Focus on properties matching user criteria
|
||||
- Use Perplexity search tool if no properties found
|
||||
|
||||
2. GATHER PROPERTY DATA:
|
||||
- Extract detailed property information
|
||||
- Collect listing URLs and agent contacts
|
||||
- Organize results clearly
|
||||
|
||||
3. PROVIDE STRUCTURED OUTPUT:
|
||||
- List properties with full details
|
||||
- Include clickable listing URLs
|
||||
- Rank by match quality
|
||||
|
||||
IMPORTANT: Always use perplexity_search_tool if extract methods don't find properties.
|
||||
Focus on finding properties that match user's exact criteria.
|
||||
""",
|
||||
)
|
||||
|
||||
market_analysis_agent = Agent(
|
||||
name="Market Analysis Agent",
|
||||
model=llm,
|
||||
instructions="""
|
||||
You are a market analysis expert. Provide ELABORATE market insights:
|
||||
|
||||
1. MARKET TRENDS:
|
||||
- Current market condition (buyer's/seller's market)
|
||||
- Price trends over 6-12 months
|
||||
- Market direction and key factors
|
||||
- Inventory levels and supply/demand
|
||||
|
||||
2. NEIGHBORHOOD ANALYSIS:
|
||||
- Top neighborhood features and amenities
|
||||
- School district ratings and performance
|
||||
- Safety ratings and crime statistics
|
||||
- Local amenities (parks, shopping, restaurants)
|
||||
- Transportation and commute options
|
||||
- Employment opportunities
|
||||
|
||||
3. INVESTMENT INSIGHTS:
|
||||
- Investment potential assessment
|
||||
- Price per square foot trends
|
||||
- Rental market data
|
||||
- Future development plans
|
||||
- Economic factors affecting the area
|
||||
|
||||
4. COMPARATIVE ANALYSIS:
|
||||
- Compare with similar markets
|
||||
- Highlight unique advantages
|
||||
- Identify potential risks or opportunities
|
||||
|
||||
PROVIDE DETAILED, ACTIONABLE INSIGHTS with specific data points.
|
||||
Include relevant links and sources when possible.
|
||||
""",
|
||||
)
|
||||
|
||||
property_valuation_agent = Agent(
|
||||
name="Property Valuation Agent",
|
||||
model=llm,
|
||||
instructions="""
|
||||
You are a property valuation expert. Provide ELABORATE property assessments:
|
||||
|
||||
1. PROPERTY VALUATION:
|
||||
- Fair market value estimates with reasoning
|
||||
- Price per square foot analysis
|
||||
- Comparable property analysis
|
||||
- Value appreciation potential
|
||||
|
||||
2. PRICING ASSESSMENT:
|
||||
- Overpriced/Underpriced/Fair price analysis
|
||||
- Key pricing factors and market positioning
|
||||
- Negotiation potential and strategies
|
||||
- Price history and trends
|
||||
|
||||
3. INVESTMENT ANALYSIS:
|
||||
- Investment potential (high/medium/low) with detailed reasoning
|
||||
- ROI projections and cash flow analysis
|
||||
- Key investment factors and considerations
|
||||
- Risk assessment and mitigation strategies
|
||||
|
||||
4. PROPERTY FEATURES EVALUATION:
|
||||
- Detailed analysis of property features
|
||||
- Unique selling points and advantages
|
||||
- Potential improvements and their value impact
|
||||
- Maintenance considerations and costs
|
||||
|
||||
5. MARKET POSITIONING:
|
||||
- How the property compares to market
|
||||
- Competitive advantages and disadvantages
|
||||
- Target buyer/renter profile
|
||||
- Marketing recommendations
|
||||
|
||||
PROVIDE COMPREHENSIVE, DETAILED ANALYSIS with specific recommendations.
|
||||
Include relevant market data and comparative analysis.
|
||||
""",
|
||||
)
|
||||
|
||||
return property_search_agent, market_analysis_agent, property_valuation_agent
|
||||
|
||||
def create_real_estate_team(llm, firecrawl_tools, user_criteria):
|
||||
"""Create the real estate team"""
|
||||
|
||||
property_search_agent, market_analysis_agent, property_valuation_agent = create_real_estate_agents(llm, firecrawl_tools, user_criteria)
|
||||
|
||||
return Team(
|
||||
name="Real Estate Analysis Team",
|
||||
mode="coordinate",
|
||||
model=llm,
|
||||
members=[property_search_agent, market_analysis_agent, property_valuation_agent],
|
||||
instructions=[
|
||||
"You are a professional real estate analysis team.",
|
||||
"1. Property Search Agent: Find properties using extract + Perplexity fallback",
|
||||
"2. Market Analysis Agent: Provide ELABORATE market trends and neighborhood insights",
|
||||
"3. Property Valuation Agent: Give ELABORATE property valuations and investment analysis",
|
||||
"IMPORTANT: Provide detailed, actionable insights with specific data points.",
|
||||
"Include relevant links and sources when possible.",
|
||||
"Work together to provide comprehensive recommendations."
|
||||
],
|
||||
show_members_responses=True,
|
||||
markdown=True,
|
||||
)
|
||||
|
||||
def display_property_results(result):
|
||||
"""Display property results with clickable links"""
|
||||
st.markdown("## Property Analysis Report")
|
||||
st.markdown("### AI-Powered Real Estate Recommendations")
|
||||
|
||||
if hasattr(result, 'content'):
|
||||
result_text = result.content
|
||||
else:
|
||||
result_text = str(result)
|
||||
|
||||
# Display the full text result with markdown support for links
|
||||
st.markdown("### Analysis Report")
|
||||
st.markdown(result_text)
|
||||
|
||||
# Extract and display clickable links
|
||||
import re
|
||||
urls = re.findall(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', result_text)
|
||||
|
||||
if urls:
|
||||
st.markdown("### 🔗 Property Links")
|
||||
for i, url in enumerate(set(urls), 1):
|
||||
st.markdown(f"{i}. [{url}]({url})")
|
||||
|
||||
def main():
|
||||
st.set_page_config(page_title="AI Multi-Agent Real Estate Team", page_icon="🏠", layout="wide")
|
||||
|
||||
st.title("AI Multi-Agent Real Estate Team")
|
||||
st.markdown("### Find Your Dream Home with Specialized AI Agents")
|
||||
|
||||
# Sidebar configuration
|
||||
with st.sidebar:
|
||||
st.header("Configuration")
|
||||
|
||||
# API Key inputs with validation
|
||||
openai_key = st.text_input("OpenAI API Key", value=DEFAULT_OPENAI_API_KEY, type="password",
|
||||
help="Get your API key from https://platform.openai.com/api-keys")
|
||||
firecrawl_key = st.text_input("Firecrawl API Key", value=DEFAULT_FIRECRAWL_API_KEY, type="password",
|
||||
help="Get your API key from https://firecrawl.dev")
|
||||
perplexity_key = st.text_input("Perplexity API Key", value=DEFAULT_PERPLEXITY_API_KEY, type="password",
|
||||
help="Get your API key from https://www.perplexity.ai/settings/api")
|
||||
|
||||
# Show API key status
|
||||
if openai_key:
|
||||
st.success("✅ OpenAI API Key provided")
|
||||
else:
|
||||
st.error("❌ OpenAI API Key required")
|
||||
|
||||
if firecrawl_key:
|
||||
st.success("✅ Firecrawl API Key provided")
|
||||
else:
|
||||
st.error("❌ Firecrawl API Key required")
|
||||
|
||||
if perplexity_key:
|
||||
st.success("✅ Perplexity API Key provided")
|
||||
else:
|
||||
st.error("❌ Perplexity API Key required")
|
||||
|
||||
# Update environment variables
|
||||
if openai_key: os.environ["OPENAI_API_KEY"] = openai_key
|
||||
if firecrawl_key: os.environ["FIRECRAWL_API_KEY"] = firecrawl_key
|
||||
if perplexity_key: os.environ["PERPLEXITY_API_KEY"] = perplexity_key
|
||||
|
||||
st.markdown("---")
|
||||
|
||||
# Website selection
|
||||
st.subheader("Select Websites to Search")
|
||||
available_websites = ["Zillow", "Realtor.com", "Trulia", "Homes.com"]
|
||||
selected_websites = [site for site in available_websites if st.checkbox(site, value=site in ["Zillow", "Realtor.com"])]
|
||||
|
||||
if selected_websites:
|
||||
st.success(f"Selected: {', '.join(selected_websites)}")
|
||||
else:
|
||||
st.warning("Please select at least one website")
|
||||
|
||||
st.markdown("---")
|
||||
st.markdown("### How it works")
|
||||
st.markdown("""
|
||||
1. **Property Search Agent** - Uses extract + Perplexity fallback
|
||||
2. **Market Analysis Agent** - Analyzes trends and neighborhood insights
|
||||
3. **Property Valuation Agent** - Evaluates values and investment potential
|
||||
""")
|
||||
|
||||
# Main form
|
||||
st.header("Your Property Requirements")
|
||||
|
||||
with st.form("property_preferences"):
|
||||
col1, col2 = st.columns(2)
|
||||
|
||||
with col1:
|
||||
city = st.text_input("City", placeholder="e.g., San Francisco")
|
||||
state = st.text_input("State/Province (optional)", placeholder="e.g., CA")
|
||||
min_price = st.number_input("Minimum Price ($)", min_value=0, value=500000, step=50000)
|
||||
max_price = st.number_input("Maximum Price ($)", min_value=0, value=1500000, step=50000)
|
||||
|
||||
with col2:
|
||||
property_type = st.selectbox("Property Type", ["Any", "House", "Condo", "Townhouse", "Apartment"])
|
||||
bedrooms = st.selectbox("Bedrooms", ["Any", "1", "2", "3", "4", "5+"])
|
||||
bathrooms = st.selectbox("Bathrooms", ["Any", "1", "1.5", "2", "2.5", "3", "3.5", "4+"])
|
||||
min_sqft = st.number_input("Minimum Square Feet", min_value=0, value=1000, step=100)
|
||||
|
||||
special_features = st.text_area("Special Features", placeholder="e.g., Parking, Yard, View, Near public transport, etc.")
|
||||
timeline = st.selectbox("Timeline", ["Flexible", "1-3 months", "3-6 months", "6+ months"])
|
||||
urgency = st.selectbox("Urgency", ["Not urgent", "Somewhat urgent", "Very urgent"])
|
||||
|
||||
submitted = st.form_submit_button("Start Property Analysis", type="primary")
|
||||
|
||||
# Process form submission
|
||||
if submitted:
|
||||
# Validate all required inputs
|
||||
missing_items = []
|
||||
if not openai_key:
|
||||
missing_items.append("OpenAI API Key")
|
||||
if not firecrawl_key:
|
||||
missing_items.append("Firecrawl API Key")
|
||||
if not perplexity_key:
|
||||
missing_items.append("Perplexity API Key")
|
||||
if not city:
|
||||
missing_items.append("City")
|
||||
if not selected_websites:
|
||||
missing_items.append("At least one website selection")
|
||||
|
||||
if missing_items:
|
||||
st.error(f"Please provide: {', '.join(missing_items)}")
|
||||
return
|
||||
|
||||
try:
|
||||
# Initialize components
|
||||
llm = OpenAIChat(id="gpt-4o", api_key=openai_key)
|
||||
|
||||
user_criteria = {
|
||||
'budget_range': f"${min_price:,} - ${max_price:,}",
|
||||
'property_type': property_type,
|
||||
'bedrooms': bedrooms,
|
||||
'bathrooms': bathrooms,
|
||||
'min_sqft': min_sqft,
|
||||
'special_features': special_features if special_features else 'None specified'
|
||||
}
|
||||
|
||||
firecrawl_tools = create_firecrawl_tools(user_criteria)
|
||||
real_estate_team = create_real_estate_team(llm, firecrawl_tools, user_criteria)
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"Error initializing: {str(e)}")
|
||||
return
|
||||
|
||||
# Display progress
|
||||
st.markdown("---")
|
||||
st.header("Property Analysis in Progress")
|
||||
|
||||
status_container = st.container()
|
||||
with status_container:
|
||||
st.subheader("Current Activity")
|
||||
current_activity = st.empty()
|
||||
|
||||
def update_progress(progress, status, activity=None):
|
||||
if activity:
|
||||
current_activity.text(activity)
|
||||
|
||||
try:
|
||||
start_time = time.time()
|
||||
update_progress(0.1, "Initializing...", "Starting comprehensive property search")
|
||||
|
||||
# Search websites
|
||||
search_start = time.time()
|
||||
search_results = search_real_estate_websites(city, state, user_criteria, selected_websites, update_progress)
|
||||
search_duration = time.time() - search_start
|
||||
|
||||
# Process results
|
||||
successful_searches = sum(1 for result in search_results.values() if "error" not in result)
|
||||
total_properties = sum(len(result.get('properties', [])) for result in search_results.values() if "error" not in result)
|
||||
use_perplexity_fallback = total_properties == 0
|
||||
|
||||
if use_perplexity_fallback:
|
||||
update_progress(0.85, "Running analysis...", "🔍 Searching rigorously across real estate platforms...")
|
||||
else:
|
||||
update_progress(0.85, "Running analysis...", "Property Search Agent: Analyzing search results")
|
||||
|
||||
# Run agents
|
||||
agent_start = time.time()
|
||||
prompt = f"""
|
||||
Analyze real estate properties using our specialized agent team:
|
||||
|
||||
USER REQUIREMENTS:
|
||||
LOCATION: {city}, {state if state else 'Any state'}
|
||||
BUDGET: {user_criteria['budget_range']}
|
||||
TYPE: {property_type}
|
||||
BEDROOMS: {bedrooms}
|
||||
BATHROOMS: {bathrooms}
|
||||
MIN SQFT: {min_sqft:,}
|
||||
FEATURES: {user_criteria['special_features']}
|
||||
TIMELINE: {timeline}
|
||||
URGENCY: {urgency}
|
||||
|
||||
SEARCH RESULTS:
|
||||
- Websites: {', '.join(selected_websites)}
|
||||
- Successful: {successful_searches}/{len(selected_websites)}
|
||||
- Properties found: {total_properties}
|
||||
|
||||
AGENT WORKFLOW:
|
||||
1. Property Search Agent: Find and analyze properties
|
||||
2. Market Analysis Agent: Provide ELABORATE market insights
|
||||
3. Property Valuation Agent: Give ELABORATE valuations
|
||||
|
||||
IMPORTANT: Provide detailed, actionable insights with specific data points.
|
||||
Include relevant links and sources when possible.
|
||||
"""
|
||||
|
||||
# Show agent progression
|
||||
agent_messages = [
|
||||
"Property Search Agent: Processing property data",
|
||||
"Market Analysis Agent: Analyzing market trends",
|
||||
"Property Valuation Agent: Evaluating property values"
|
||||
]
|
||||
|
||||
for i, message in enumerate(agent_messages):
|
||||
progress = 0.87 + (i * 0.03)
|
||||
update_progress(progress, "Analysis in progress...", message)
|
||||
time.sleep(1)
|
||||
|
||||
# Execute agents
|
||||
if use_perplexity_fallback:
|
||||
with st.spinner("🔍 Searching rigorously across real estate platforms..."):
|
||||
result = real_estate_team.run(prompt)
|
||||
else:
|
||||
result = real_estate_team.run(prompt)
|
||||
|
||||
agent_duration = time.time() - agent_start
|
||||
total_time = time.time() - start_time
|
||||
|
||||
# Display results
|
||||
st.markdown("---")
|
||||
display_property_results(result)
|
||||
|
||||
# Download button
|
||||
if hasattr(result, 'content'):
|
||||
download_content = result.content
|
||||
else:
|
||||
download_content = str(result)
|
||||
|
||||
st.download_button(
|
||||
label="Download Report",
|
||||
data=download_content,
|
||||
file_name="property_analysis_report.md",
|
||||
mime="text/markdown"
|
||||
)
|
||||
|
||||
# Timing info
|
||||
st.info(f"⏱️ Total time: {total_time:.2f}s | Search: {search_duration:.2f}s | Agents: {agent_duration:.2f}s")
|
||||
|
||||
except Exception as e:
|
||||
st.error(f"An error occurred: {str(e)}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
streamlit>=1.28.0
|
||||
agno>=0.1.0
|
||||
openai>=1.0.0
|
||||
firecrawl-py>=0.1.0
|
||||
pydantic>=2.0.0
|
||||
python-dotenv>=1.0.0
|
||||
requests>=2.31.0
|
||||
Loading…
Reference in a new issue