diff --git a/auto-analyst-backend/DEFAULT_AGENTS_SETUP.md b/auto-analyst-backend/DEFAULT_AGENTS_SETUP.md deleted file mode 100644 index 1242c834..00000000 --- a/auto-analyst-backend/DEFAULT_AGENTS_SETUP.md +++ /dev/null @@ -1,237 +0,0 @@ -# Default Agents Setup Guide - -This guide explains how to set up and use the default agents system in the Auto-Analyst backend. - -## Overview - -The system now includes 4 default agents that are stored in the database as templates: - -1. **Data Preprocessing Agent** (`preprocessing_agent`) - Data cleaning and preparation -2. **Statistical Analytics Agent** (`statistical_analytics_agent`) - Statistical analysis using statsmodels -3. **Machine Learning Agent** (`sk_learn_agent`) - ML modeling using scikit-learn -4. **Data Visualization Agent** (`data_viz_agent`) - Interactive visualizations using Plotly - -## Setup Instructions - -### 1. Load Default Agents into Database - -Run the setup script to populate the database with default agents: - -```bash -cd Auto-Analyst-CS/auto-analyst-backend -python load_default_agents.py -``` - -**Or** use the API endpoint: - -```bash -curl -X POST "http://localhost:8000/templates/load-default-agents" \ - -H "Content-Type: application/json" \ - -d '{"force_update": false}' -``` - -### 2. Agent Properties - -All default agents are created with: -- `is_active = True` (available for use) -- `is_premium_only = False` (free to use) -- Proper categories (Data Manipulation, Statistical Analysis, Modelling, Visualization) - -## User Preferences System - -### Default Behavior -- **Default agents (preprocessing, statistical_analytics, sk_learn, data_viz) are ENABLED by default** for all users -- **Other templates are DISABLED by default** and must be explicitly enabled -- Templates can be used directly via `@template_name` regardless of preferences - -### Managing User Preferences - -#### Enable/Disable Templates -```bash -# Enable a template for a user -curl -X POST "http://localhost:8000/templates/user/1/template/1/toggle" \ - -H "Content-Type: application/json" \ - -d '{"is_enabled": true}' - -# Disable a template for a user -curl -X POST "http://localhost:8000/templates/user/1/template/1/toggle" \ - -H "Content-Type: application/json" \ - -d '{"is_enabled": false}' -``` - -#### Bulk Enable/Disable -```bash -# Enable multiple templates at once -curl -X POST "http://localhost:8000/templates/user/1/bulk-toggle" \ - -H "Content-Type: application/json" \ - -d '{ - "template_preferences": { - "1": true, - "2": true, - "3": false - } - }' -``` - -#### Get User's Template Preferences -```bash -# Get all templates with user's enabled/disabled status -curl "http://localhost:8000/templates/user/1" - -# Get only enabled templates for user -curl "http://localhost:8000/templates/user/1/enabled" - -# Get enabled templates for planner (max 10, ordered by usage) -curl "http://localhost:8000/templates/user/1/enabled/planner" -``` - -## Planner Integration - -### How It Works -1. **Template Loading**: Only user-enabled templates are loaded into the planner -2. **No Agents Available**: If no templates are enabled, planner returns a helpful message -3. **Usage Tracking**: Template usage is tracked for prioritization - -### Planner Response When No Agents Enabled -```json -{ - "complexity": "no_agents_available", - "plan": "no_agents_available", - "plan_instructions": { - "message": "No agents are currently enabled for analysis. Please enable at least one agent (preprocessing, statistical analysis, machine learning, or visualization) in your template preferences to proceed with data analysis." - } -} -``` - -## API Endpoints - -### Template Management -- `GET /templates/` - Get all available templates -- `GET /templates/template/{template_id}` - Get specific template -- `POST /templates/load-default-agents` - Load default agents into database - -### User Preferences -- `GET /templates/user/{user_id}` - Get user's template preferences -- `GET /templates/user/{user_id}/enabled` - Get user's enabled templates -- `GET /templates/user/{user_id}/enabled/planner` - Get templates for planner (max 10) -- `POST /templates/user/{user_id}/template/{template_id}/toggle` - Toggle template preference -- `POST /templates/user/{user_id}/bulk-toggle` - Bulk toggle preferences - -### Categories -- `GET /templates/categories/list` - Get all categories -- `GET /templates/categories` - Get templates grouped by category -- `GET /templates/category/{category}` - Get templates in specific category - -## Usage Examples - -### Frontend Integration -```typescript -// Enable preprocessing and visualization agents for user -const enableAgents = async (userId: number) => { - await fetch(`/templates/user/${userId}/bulk-toggle`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ - template_preferences: { - "1": true, // preprocessing_agent - "4": true // data_viz_agent - } - }) - }); -}; - -// Get user's enabled templates -const getUserTemplates = async (userId: number) => { - const response = await fetch(`/templates/user/${userId}/enabled`); - return await response.json(); -}; -``` - -### Direct Agent Usage -Users can still use any agent directly regardless of preferences: -``` -@preprocessing_agent clean this data -@data_viz_agent create a scatter plot of sales vs price -``` - -### Planner Usage -Only enabled agents will be available to the planner: -``` -User: "Clean the data and create a visualization" -System: Uses only enabled agents to create the plan -``` - -## Database Schema - -### AgentTemplate Table -```sql -CREATE TABLE agent_templates ( - template_id SERIAL PRIMARY KEY, - template_name VARCHAR UNIQUE NOT NULL, - display_name VARCHAR, - description TEXT, - prompt_template TEXT, - category VARCHAR, - is_premium_only BOOLEAN DEFAULT FALSE, - is_active BOOLEAN DEFAULT TRUE, - created_at TIMESTAMP, - updated_at TIMESTAMP -); -``` - -### UserTemplatePreference Table -```sql -CREATE TABLE user_template_preferences ( - user_id INTEGER, - template_id INTEGER, - is_enabled BOOLEAN DEFAULT FALSE, - usage_count INTEGER DEFAULT 0, - last_used_at TIMESTAMP, - created_at TIMESTAMP, - updated_at TIMESTAMP, - PRIMARY KEY (user_id, template_id), - FOREIGN KEY (user_id) REFERENCES users(user_id), - FOREIGN KEY (template_id) REFERENCES agent_templates(template_id) -); -``` - -## Troubleshooting - -### Common Issues - -1. **No agents available in planner** - - Check if user has enabled any templates: `GET /templates/user/{user_id}/enabled` - - Enable templates using the toggle endpoint - -2. **Default agents not found** - - Run the load script: `python load_default_agents.py` - - Check if agents exist: `GET /templates/` - -3. **Import errors in load script** - - Ensure you're in the backend directory - - Check that all dependencies are installed - - Verify database connection - -### Logs -Check the application logs for detailed error messages: -```bash -tail -f logs/templates_routes.log -tail -f logs/agents.log -``` - -## Migration from Old System - -If migrating from the previous custom agents system: - -1. **Data Migration**: Existing custom agents should be migrated to the new template system -2. **User Preferences**: Users will need to re-enable their preferred agents -3. **API Updates**: Update frontend code to use new template endpoints -4. **Testing**: Verify planner works with enabled templates only - -## Support - -For issues or questions: -1. Check the logs for error messages -2. Verify database connections -3. Ensure proper API endpoint usage -4. Test with the load script first \ No newline at end of file diff --git a/auto-analyst-backend/app.py b/auto-analyst-backend/app.py index bfe73b8b..749b2342 100644 --- a/auto-analyst-backend/app.py +++ b/auto-analyst-backend/app.py @@ -1069,6 +1069,7 @@ def _get_model_name_for_provider(provider: str) -> str: async def _execute_plan_with_timeout(ai_system, enhanced_query, plan_response): """Execute the plan with timeout handling for each step""" try: + logger.log_message(f"Plan response: {plan_response}", level=logging.INFO) # Use the async generator from execute_plan directly async for agent_name, inputs, response in ai_system.execute_plan(enhanced_query, plan_response): # Yield results as they come diff --git a/auto-analyst-backend/chat_database.db b/auto-analyst-backend/chat_database.db index e99a3734..d78194e9 100644 --- a/auto-analyst-backend/chat_database.db +++ b/auto-analyst-backend/chat_database.db @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:061a038faca46d439d7178af5bc140ee7a523d4ef00cf57ca75d2d9e708fcdb2 -size 69632 +oid sha256:4e0854398016042fe9083a6fad651f974078fd1c502b035192601e7de9d913ab +size 147456 diff --git a/auto-analyst-backend/scripts/populate_agent_templates.py b/auto-analyst-backend/scripts/populate_agent_templates.py index d1d7b87d..8244562e 100644 --- a/auto-analyst-backend/scripts/populate_agent_templates.py +++ b/auto-analyst-backend/scripts/populate_agent_templates.py @@ -25,7 +25,6 @@ def get_database_type(): else: return "unknown" -# Default agents (free for all users) DEFAULT_AGENTS = { "Data Manipulation": [ { @@ -203,7 +202,6 @@ def statistical_model(X, y, goal, period=None): ] } -# Premium template agent definitions PREMIUM_TEMPLATES = { "Data Visualization": [ { diff --git a/auto-analyst-backend/src/agents/agents.py b/auto-analyst-backend/src/agents/agents.py index 8de9d96f..215863a3 100644 --- a/auto-analyst-backend/src/agents/agents.py +++ b/auto-analyst-backend/src/agents/agents.py @@ -1582,7 +1582,7 @@ def __init__(self, agents, retrievers, user_id=None, db_session=None): try: # For planner use, load planner-enabled templates (max 10, prioritized by usage) template_signatures = load_user_enabled_templates_for_planner_from_db(user_id, db_session) - logger.log_message(f"Loaded {len(template_signatures)} templates for planner use", level=logging.INFO) + logger.log_message(f"Loaded {template_signatures} templates for planner use", level=logging.INFO) for template_name, signature in template_signatures.items(): # Skip if this is a core agent - we'll load it separately @@ -1861,6 +1861,7 @@ async def get_plan(self, query): else: complexity = 'basic' plan_dict['complexity'] = complexity + logger.log_message(f"Plan dict: {plan_dict}", level=logging.INFO) return plan_dict @@ -1880,7 +1881,8 @@ async def execute_plan(self, query, plan): import json # Clean and split the plan string into agent names - plan_text = plan.get("plan", "").replace("Plan", "").replace(":", "").strip() + plan_text = plan.get("plan", "").lower().replace("plan", "").replace(":", "").strip() + logger.log_message(f"Plan text: {plan_text}", level=logging.INFO) if "basic_qa_agent" in plan_text: inputs = dict(goal=query) diff --git a/auto-analyst-backend/src/routes/templates_routes.py b/auto-analyst-backend/src/routes/templates_routes.py index 06394a17..ca81096d 100644 --- a/auto-analyst-backend/src/routes/templates_routes.py +++ b/auto-analyst-backend/src/routes/templates_routes.py @@ -355,6 +355,46 @@ async def toggle_template_preference(user_id: int, template_id: int, request: To if not user: raise HTTPException(status_code=404, detail="User not found") + # If trying to disable, check if this would leave user with no enabled templates + if not request.is_enabled: + # Get list of default agent names that should be enabled by default + default_agent_names = [ + "preprocessing_agent", + "statistical_analytics_agent", + "sk_learn_agent", + "data_viz_agent" + ] + + # Get all active templates + all_templates = session.query(AgentTemplate).filter( + AgentTemplate.is_active == True + ).all() + + enabled_count = 0 + for template in all_templates: + # Check if user has a preference record for this template + preference = session.query(UserTemplatePreference).filter( + UserTemplatePreference.user_id == user_id, + UserTemplatePreference.template_id == template.template_id + ).first() + + # Determine if template should be enabled by default + is_default_agent = template.template_name in default_agent_names + default_enabled = is_default_agent + + # Template is enabled by default for default agents, disabled for others + is_enabled = preference.is_enabled if preference else default_enabled + + if is_enabled: + enabled_count += 1 + + # If disabling this template would leave the user with 0 enabled templates, reject + if enabled_count <= 1: + raise HTTPException( + status_code=400, + detail="Cannot disable the last active agent. At least one agent must remain active." + ) + success, message = toggle_user_template_preference( user_id, template_id, request.is_enabled, session ) @@ -391,19 +431,51 @@ async def bulk_toggle_template_preferences(user_id: int, request: dict): if not template_preferences: raise HTTPException(status_code=400, detail="No preferences provided") - # Check current enabled count for limit enforcement - current_enabled_count = session.query(UserTemplatePreference).filter( - UserTemplatePreference.user_id == user_id, - UserTemplatePreference.is_enabled == True - ).count() + # Get list of default agent names that should be enabled by default + default_agent_names = [ + "preprocessing_agent", + "statistical_analytics_agent", + "sk_learn_agent", + "data_viz_agent" + ] + + # Calculate current enabled count properly (including defaults) + all_templates = session.query(AgentTemplate).filter( + AgentTemplate.is_active == True + ).all() + + current_enabled_count = 0 + for template in all_templates: + # Check if user has a preference record for this template + preference = session.query(UserTemplatePreference).filter( + UserTemplatePreference.user_id == user_id, + UserTemplatePreference.template_id == template.template_id + ).first() + + # Determine if template should be enabled by default + is_default_agent = template.template_name in default_agent_names + default_enabled = is_default_agent + + # Template is enabled by default for default agents, disabled for others + is_enabled = preference.is_enabled if preference else default_enabled + + if is_enabled: + current_enabled_count += 1 - # Count how many templates we're trying to enable + # Count how many templates we're trying to enable/disable enabling_count = sum(1 for pref in template_preferences if pref.get("is_enabled", False)) disabling_count = sum(1 for pref in template_preferences if not pref.get("is_enabled", False)) # Calculate what the new count would be projected_enabled_count = current_enabled_count + enabling_count - disabling_count + # Check if the bulk operation would leave user with 0 enabled templates + if projected_enabled_count < 1: + raise HTTPException( + status_code=400, + detail="Cannot disable all agents. At least one agent must remain active." + ) + results = [] for pref in template_preferences: template_id = pref.get("template_id") diff --git a/auto-analyst-frontend/components/chat/AgentSuggestions.tsx b/auto-analyst-frontend/components/chat/AgentSuggestions.tsx index f1af1018..7e812afc 100644 --- a/auto-analyst-frontend/components/chat/AgentSuggestions.tsx +++ b/auto-analyst-frontend/components/chat/AgentSuggestions.tsx @@ -65,7 +65,7 @@ export default function AgentSuggestions({ return null } - // Fetch agents from the main agents endpoint (includes both standard and custom) + // Fetch agents from the main agents endpoint (now all are templates in DB) const fetchAllAgents = async (): Promise => { const currentUserId = getUserId() @@ -82,34 +82,23 @@ export default function AgentSuggestions({ const data = await response.json() const allAgents: AgentSuggestion[] = [] - // // Add standard agents - // if (data.standard_agents) { - // data.standard_agents.forEach((agentName: string) => { - // const standardAgent = standardAgents.find(agent => agent.name === agentName) - // if (standardAgent) { - // allAgents.push(standardAgent) - // } - // }) - // } - - // Add template agents (only for users with custom agents access) - if (data.template_agents && data.template_agents.length > 0 && customAgentsAccess.hasAccess) { + // All agents are now template agents from the database + // Load all template agents, filtering will be done based on premium access + if (data.template_agents && data.template_agents.length > 0) { const templateAgents = await fetchTemplateAgents() allAgents.push(...templateAgents) } - // Custom agents are deprecated - using templates only - return allAgents } else { console.error('Failed to fetch agents:', response.status, await response.text()) - // Fallback to standard agents only - return standardAgents + // Fallback to empty array since all agents should be in DB now + return [] } } catch (error) { console.error('Error fetching agents:', error) - // Fallback to standard agents only - return standardAgents + // Fallback to empty array since all agents should be in DB now + return [] } } @@ -129,10 +118,14 @@ export default function AgentSuggestions({ const mappedTemplates = category.templates.map((template: any) => ({ name: template.agent_name, description: template.description, - // isTemplate: true, + isTemplate: true, isPremium: template.is_premium_only })) - allTemplates.push(...mappedTemplates) + // Filter out premium agents if user doesn't have access + const filteredTemplates = customAgentsAccess.hasAccess + ? mappedTemplates + : mappedTemplates.filter((template: any) => !template.isPremium) + allTemplates.push(...filteredTemplates) } }) @@ -304,7 +297,7 @@ export default function AgentSuggestions({
{agent.name}
{agent.isPremium && ( - + Template )} diff --git a/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx b/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx index 0b3e6b34..33855719 100644 --- a/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx +++ b/auto-analyst-frontend/components/custom-templates/TemplateCard.tsx @@ -9,6 +9,7 @@ interface TemplateCardProps { preference?: TemplatePreference isEnabled: boolean hasAccess: boolean + isLastTemplate?: boolean onToggleChange: (templateId: number, enabled: boolean) => void } @@ -17,11 +18,13 @@ export default function TemplateCard({ preference, isEnabled, hasAccess, + isLastTemplate = false, onToggleChange }: TemplateCardProps) { // User can only toggle if they have access (covers both free and premium users) // Premium-only templates are only toggleable by premium users (hasAccess = true for premium) - const canToggle = hasAccess + // Also cannot disable if this is the last template + const canToggle = hasAccess && !(isEnabled && isLastTemplate) const handleClick = () => { if (canToggle) { @@ -29,6 +32,22 @@ export default function TemplateCard({ } } + // Determine the status text and color + const getStatusInfo = () => { + if (!hasAccess) { + return { text: 'Premium', color: 'text-gray-400' } + } + if (isEnabled && isLastTemplate) { + return { text: 'Required', color: 'text-orange-600' } + } + if (isEnabled) { + return { text: 'Active', color: 'text-green-600' } + } + return { text: 'Inactive', color: 'text-gray-400' } + } + + const statusInfo = getStatusInfo() + return ( {/* Lock overlay for free users */} {!canToggle && ( @@ -88,6 +108,11 @@ export default function TemplateCard({ Premium )} + {/* {isEnabled && isLastTemplate && ( + + Required + + )} */}
@@ -113,26 +138,23 @@ export default function TemplateCard({ disabled={!canToggle} className={`w-6 h-6 rounded-md border-2 flex items-center justify-center transition-all duration-200 ${ isEnabled - ? 'bg-[#FF7F7F] border-[#FF7F7F] text-white' + ? isLastTemplate + ? 'bg-orange-500 border-orange-500 text-white' + : 'bg-[#FF7F7F] border-[#FF7F7F] text-white' : 'border-gray-300 hover:border-[#FF7F7F] bg-white' } ${!canToggle ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer hover:scale-105'}`} + title={isEnabled && isLastTemplate ? 'At least one agent must remain active' : undefined} > {isEnabled && } - - {!canToggle - ? 'Premium' - : isEnabled - ? 'Active' - : 'Inactive' - } + + {statusInfo.text} + {isEnabled && isLastTemplate && ( + + Min required + + )} diff --git a/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx b/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx index 89fab668..67549cdb 100644 --- a/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx +++ b/auto-analyst-frontend/components/custom-templates/TemplatesModal.tsx @@ -64,31 +64,20 @@ export default function TemplatesModal({ const loadTemplatesForFreeUsers = async () => { setLoading(true) try { - console.log('Loading templates for free users...', { API_URL }) - // Fetch all templates (no user-specific data needed) const response = await fetch(`${API_URL}/templates/`).catch(err => { - console.error('Free user templates fetch error:', err) throw new Error(`Templates endpoint failed: ${err.message}`) }) - console.log('Free user templates response:', { status: response.status }) - if (!response.ok) { const errorText = await response.text() - console.error('Free user templates response error:', { status: response.status, errorText }) throw new Error(`Failed to load templates: ${response.status} ${response.statusText} - ${errorText}`) } const templatesData = await response.json().catch(err => { - console.error('Free user templates JSON parse error:', err) throw new Error(`Failed to parse templates response: ${err.message}`) }) - console.log('Free user templates data parsed successfully:', { - templatesCount: templatesData.length - }) - setTemplates(templatesData) setPreferences([]) // No preferences for free users setChanges({}) @@ -108,42 +97,30 @@ export default function TemplatesModal({ const loadData = async () => { setLoading(true) try { - console.log('Loading templates data for modal...', { API_URL, userId }) - // Fetch global template data with global usage counts const [templatesResponse, preferencesResponse] = await Promise.all([ fetch(`${API_URL}/templates/`).catch(err => { - console.error('Templates fetch error:', err) throw new Error(`Templates endpoint failed: ${err.message}`) }), // Global templates with global usage counts fetch(`${API_URL}/templates/user/${userId}`).catch(err => { - console.error('Preferences fetch error:', err) throw new Error(`Preferences endpoint failed: ${err.message}`) }) // User preferences with per-user usage ]) - console.log('Modal responses received:', { - templatesStatus: templatesResponse.status, - preferencesStatus: preferencesResponse.status - }) - // Check templates response if (!templatesResponse.ok) { const errorText = await templatesResponse.text() - console.error('Templates response error:', { status: templatesResponse.status, errorText }) throw new Error(`Failed to load templates: ${templatesResponse.status} ${templatesResponse.statusText} - ${errorText}`) } // Check preferences response if (!preferencesResponse.ok) { const errorText = await preferencesResponse.text() - console.error('Preferences response error:', { status: preferencesResponse.status, errorText }) throw new Error(`Failed to load preferences: ${preferencesResponse.status} ${preferencesResponse.statusText} - ${errorText}`) } // Parse templates response const globalTemplatesData = await templatesResponse.json().catch(err => { - console.error('Templates JSON parse error:', err) throw new Error(`Failed to parse templates response: ${err.message}`) }) @@ -165,7 +142,6 @@ export default function TemplatesModal({ // Parse preferences response const userPreferencesData = await preferencesResponse.json().catch(err => { - console.error('Preferences JSON parse error:', err) throw new Error(`Failed to parse preferences response: ${err.message}`) }) @@ -183,11 +159,6 @@ export default function TemplatesModal({ })) setPreferences(preferencesData) - console.log('Modal data parsed successfully:', { - templatesCount: templatesData.length, - preferencesCount: preferencesData.length - }) - // Reset changes when loading data setChanges({}) } catch (error) { @@ -339,7 +310,7 @@ export default function TemplatesModal({ if (response.ok) { toast({ title: "Settings Saved!", - description: `Updated ${preferencesToUpdate.length} template preferences`, + description: `Updated template preferences`, duration: 3000, }) setChanges({}) @@ -368,8 +339,29 @@ export default function TemplatesModal({ return { preference, isEnabled } } + // Calculate enabled count including pending changes + const getEnabledCountWithChanges = () => { + let count = 0 + templates.forEach(template => { + const isCurrentlyEnabled = getTemplateEnabledState(template) + if (isCurrentlyEnabled) { + count++ + } + }) + return count + } + + // Check if disabling this template would leave user with 0 templates + const wouldLeaveZeroTemplates = (templateId: number) => { + const currentEnabledCount = getEnabledCountWithChanges() + const templateCurrentlyEnabled = getTemplateEnabledState(templates.find(t => t.template_id === templateId)!) + + // If this template is currently enabled and it's the only one, disabling it would leave 0 + return templateCurrentlyEnabled && currentEnabledCount === 1 + } + const enabledCount = hasAccess - ? templates.filter(template => getTemplateEnabledState(template)).length + ? getEnabledCountWithChanges() : 0 return ( @@ -535,6 +527,8 @@ export default function TemplatesModal({
{filteredTemplates.map(template => { const { preference, isEnabled } = getTemplateData(template) + const isLastTemplate = wouldLeaveZeroTemplates(template.template_id) + return ( ) @@ -563,6 +558,12 @@ export default function TemplatesModal({ <> Use the toggle switches to enable/disable agents to be used by planner. You can use any agent directly with @agent_name. +
+ {enabledCount === 1 && ( + + {' '}Note: At least one agent must remain active. + + )}
{Object.keys(changes).length > 0 && ( diff --git a/auto-analyst-frontend/components/custom-templates/useTemplates.ts b/auto-analyst-frontend/components/custom-templates/useTemplates.ts index f958d116..6caab3c2 100644 --- a/auto-analyst-frontend/components/custom-templates/useTemplates.ts +++ b/auto-analyst-frontend/components/custom-templates/useTemplates.ts @@ -34,54 +34,36 @@ export function useTemplates({ userId, enabled = true }: UseTemplatesProps): Use setError(null) try { - console.log('Loading templates data...', { API_URL, userId }) - const [templatesResponse, preferencesResponse] = await Promise.all([ fetch(`${API_URL}/templates/`).catch(err => { - console.error('Templates fetch error:', err) throw new Error(`Templates endpoint failed: ${err.message}`) }), fetch(`${API_URL}/templates/user/${userId}`).catch(err => { - console.error('Preferences fetch error:', err) throw new Error(`Preferences endpoint failed: ${err.message}`) }) ]) - console.log('Responses received:', { - templatesStatus: templatesResponse.status, - preferencesStatus: preferencesResponse.status - }) - // Check templates response if (!templatesResponse.ok) { const errorText = await templatesResponse.text() - console.error('Templates response error:', { status: templatesResponse.status, errorText }) throw new Error(`Failed to load templates: ${templatesResponse.status} ${templatesResponse.statusText} - ${errorText}`) } // Check preferences response if (!preferencesResponse.ok) { const errorText = await preferencesResponse.text() - console.error('Preferences response error:', { status: preferencesResponse.status, errorText }) throw new Error(`Failed to load preferences: ${preferencesResponse.status} ${preferencesResponse.statusText} - ${errorText}`) } // Parse responses const templatesData = await templatesResponse.json().catch(err => { - console.error('Templates JSON parse error:', err) throw new Error(`Failed to parse templates response: ${err.message}`) }) const preferencesData = await preferencesResponse.json().catch(err => { - console.error('Preferences JSON parse error:', err) throw new Error(`Failed to parse preferences response: ${err.message}`) }) - console.log('Data parsed successfully:', { - templatesCount: templatesData.length, - preferencesCount: preferencesData.length - }) - setTemplates(templatesData) setPreferences(preferencesData) diff --git a/auto-analyst-frontend/components/landing/AgentsSection.tsx b/auto-analyst-frontend/components/landing/AgentsSection.tsx index 1b36547d..69fcb0e8 100644 --- a/auto-analyst-frontend/components/landing/AgentsSection.tsx +++ b/auto-analyst-frontend/components/landing/AgentsSection.tsx @@ -1,10 +1,30 @@ "use client" import { motion } from "framer-motion" -import { agents } from "./FnT" +import { templateCategories } from "./FnT" import { Badge } from "@/components/ui/badge" -import { CheckCircle } from "lucide-react" +import { CheckCircle, Plus } from "lucide-react" +import Image from "next/image" export default function AgentsSection() { + // Library showcase for each category + const libraryShowcase = { + "Data Manipulation": [ + { name: "Pandas", icon: "/icons/templates/preprocessing_agent.svg" }, + { name: "NumPy", icon: "/icons/templates/numpy.svg" }, + { name: "Polars", icon: "/icons/templates/polars.svg" } + ], + "Data Modelling": [ + { name: "Scikit-Learn", icon: "/icons/templates/sk_learn_agent.svg" }, + { name: "XGBoost", icon: "/icons/templates/xgboost.png" }, + { name: "Statistical Models", icon: "/icons/templates/statsmodel.svg" } + ], + "Data Visualization": [ + { name: "Plotly", icon: "/icons/templates/data_viz_agent.svg" }, + { name: "Matplotlib", icon: "/icons/templates/matplotlib.svg" }, + { name: "Seaborn", icon: "/icons/templates/seaborn.svg" } + ] + } + return (
@@ -16,66 +36,124 @@ export default function AgentsSection() { className="text-center mb-10 sm:mb-16" >

- Four Specialized AI Agents + Powered by Industry-Leading Libraries

- Unlike ChatGPT's general-purpose approach, Auto-Analyst uses four specialized agents that work together to handle complex data science workflows with precision and reliability. + Auto-Analyst harnesses the power of the most trusted data science libraries, organized into three specialized categories for maximum efficiency.

-
- {agents.map((agent, index) => ( + {/* Library Icons Showcase */} + +

Major Libraries Integrated

+
+ {Object.values(libraryShowcase).flat().map((library, index) => ( + +
+ {library.name} +
+ {library.name} +
+ ))} +
+
+ +
+ {templateCategories.map((category, index) => ( {/* Gradient Background */} -
+
- {/* Agent Header */} -
-
- + {/* Category Header */} +
+
+
-

{agent.name}

-

{agent.description}

+

{category.name}

+

{category.description}

+
+
+ + {/* Featured Libraries for this Category */} +
+

Featured Libraries:

+
+ {libraryShowcase[category.name as keyof typeof libraryShowcase]?.map((library, libIndex) => ( + +
+ {library.name} +
+ {library.name} +
+ ))}
{/* Capabilities */}
-

Key Capabilities:

- {agent.capabilities.map((capability, capIndex) => ( +

What You Can Do:

+ {category.capabilities.slice(0, 3).map((capability, capIndex) => ( - - {capability} + + {capability} ))} -
- - {/* Agent Usage Indicator */} -
- - @{agent.name.toLowerCase().replace(/\s+/g, '_')} - -

- Direct your queries to this agent using @mentions + {category.capabilities.length > 3 && ( +

+ + {category.capabilities.length - 3} more capabilities

+ )}
+ + {/* Hover Effect Border */} +
))}
@@ -88,21 +166,24 @@ export default function AgentsSection() { viewport={{ once: true }} className="text-center mt-10 sm:mt-16" > -
+

- Intelligent Agent Orchestration + Smart Agent Selection

- Our planner automatically selects and coordinates the right agents for your specific query, - or you can direct questions to specific agents using @mentions for precise control. + Our AI planner automatically chooses the best libraries and agents for your task. + Use @mentions to call specific agents directly.

-
- {agents.map((agent, index) => ( - - @{agent.name.toLowerCase().replace(/\s+/g, '_')} +
+ {templateCategories.map((category, index) => ( + + {category.name} ))}
+

+ We are continuously adding new templates for you. +

diff --git a/auto-analyst-frontend/components/landing/FnT.tsx b/auto-analyst-frontend/components/landing/FnT.tsx index a528f8e9..4e43f015 100644 --- a/auto-analyst-frontend/components/landing/FnT.tsx +++ b/auto-analyst-frontend/components/landing/FnT.tsx @@ -1,5 +1,5 @@ "use client" -import { Brain, LineChart, Database, BarChart2, Lock, Zap, FileText, TrendingUp, Cog, BarChart3, Github, Server, Cpu, Globe } from "lucide-react" +import { Brain, LineChart, Database, BarChart2, Lock, Zap, FileText, TrendingUp, Cog, BarChart3, Github, Server, Cpu, Globe, Wrench, Target, ScatterChart, Table2 } from "lucide-react" export const features = [ { @@ -34,6 +34,49 @@ export const features = [ }, ] +export const templateCategories = [ + { + icon: Table2, + name: "Data Manipulation", + description: "Transform, clean, and prepare your data for analysis", + capabilities: [ + "Clean and preprocess datasets with advanced techniques", + "Handle missing values and data quality issues", + "Transform and reshape data structures", + ], + color: "from-red-300 to-red-400", + bgGradient: "from-red-50 to-red-100", + examples: "Pandas preprocessing, Polars optimization, data cleaning specialists" + }, + { + icon: Target, + name: "Data Modelling", + description: "Build statistical models and machine learning algorithms", + capabilities: [ + "Statistical analysis and hypothesis testing", + "Predictive analytics and forecasting", + "Sophisticated ML techniques for advanced modelling", + ], + color: "from-red-400 to-red-500", + bgGradient: "from-red-100 to-red-200", + examples: "Statistical analysis, ML algorithms, predictive modeling" + }, + { + icon: ScatterChart, + name: "Data Visualization", + description: "Create compelling charts and interactive visualizations", + capabilities: [ + "Interactive and static chart creation", + "Multi-dimensional data visualization", + "Publication-ready visual outputs" + ], + color: "from-red-500 to-red-600", + bgGradient: "from-red-200 to-red-300", + examples: "Plotly interactives, Matplotlib static plots, Seaborn statistical charts" + } +] + +// Legacy agents array for backward compatibility export const agents = [ { icon: Database, @@ -56,8 +99,6 @@ export const agents = [ "Correlation and regression analysis", "Hypothesis testing and A/B tests", "Time series analysis", - "Statistical modeling", - "Confidence intervals and p-values" ], color: "from-green-500 to-green-600" }, @@ -66,11 +107,9 @@ export const agents = [ name: "Scikit-Learn Agent", description: "Machine learning specialist for predictive modeling", capabilities: [ - "Random Forest and ensemble methods", "K-means clustering analysis", "Classification and regression", "Feature selection and engineering", - "Model evaluation and validation" ], color: "from-purple-500 to-purple-600" }, @@ -80,7 +119,6 @@ export const agents = [ description: "Interactive visualizations using Plotly", capabilities: [ "Interactive charts and graphs", - "Statistical plot recommendations", "Multi-dimensional visualizations", "Custom styling and formatting", "Export-ready visualizations" @@ -89,6 +127,18 @@ export const agents = [ } ] +export const majorLibraries = [ + { name: "Pandas", category: "Data Manipulation", icon: "/icons/templates/preprocessing_agent.svg", description: "Data cleaning & preprocessing" }, + { name: "NumPy", category: "Data Manipulation", icon: "/icons/templates/numpy.svg", description: "Numerical computing foundation" }, + { name: "Polars", category: "Data Manipulation", icon: "/icons/templates/polars.svg", description: "High-performance data processing" }, + { name: "Scikit-Learn", category: "Data Modelling", icon: "/icons/templates/sk_learn_agent.svg", description: "Machine learning algorithms" }, + { name: "XGBoost", category: "Data Modelling", icon: "/icons/templates/xgboost.svg", description: "Gradient boosting framework" }, + { name: "Statistical Models", category: "Data Modelling", icon: "/icons/templates/statsmodels.svg", description: "Statistical analysis tools" }, + { name: "Plotly", category: "Data Visualization", icon: "/icons/templates/data_viz_agent.svg", description: "Interactive visualizations" }, + { name: "Matplotlib", category: "Data Visualization", icon: "/icons/templates/matplotlib.svg", description: "Static publication plots" }, + { name: "Seaborn", category: "Data Visualization", icon: "/icons/templates/seaborn.svg", description: "Statistical visualizations" } +] + export const supportedConnectors = [ { category: "File Formats", diff --git a/auto-analyst-frontend/components/landing/LandingPage.tsx b/auto-analyst-frontend/components/landing/LandingPage.tsx index 22ad4cb7..03c55cc4 100644 --- a/auto-analyst-frontend/components/landing/LandingPage.tsx +++ b/auto-analyst-frontend/components/landing/LandingPage.tsx @@ -101,8 +101,8 @@ export default function LandingPage() {
- + diff --git a/auto-analyst-frontend/lib/utils/logger.ts b/auto-analyst-frontend/lib/utils/logger.ts index 282b9f0b..405abb3a 100644 --- a/auto-analyst-frontend/lib/utils/logger.ts +++ b/auto-analyst-frontend/lib/utils/logger.ts @@ -6,7 +6,7 @@ */ // Set this to true to disable all non-error logs -const DISABLE_LOGS = false; +const DISABLE_LOGS = true; const logger = { log: (...args: any[]) => { diff --git a/auto-analyst-frontend/public/icons/templates/numpy.svg b/auto-analyst-frontend/public/icons/templates/numpy.svg new file mode 100644 index 00000000..262f0301 --- /dev/null +++ b/auto-analyst-frontend/public/icons/templates/numpy.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/auto-analyst-frontend/public/icons/templates/statsmodel.svg b/auto-analyst-frontend/public/icons/templates/statsmodel.svg new file mode 100644 index 00000000..ac9aabbc --- /dev/null +++ b/auto-analyst-frontend/public/icons/templates/statsmodel.svg @@ -0,0 +1,74 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + diff --git a/auto-analyst-frontend/public/icons/templates/xgboost.png b/auto-analyst-frontend/public/icons/templates/xgboost.png new file mode 100644 index 00000000..fab1fbf9 Binary files /dev/null and b/auto-analyst-frontend/public/icons/templates/xgboost.png differ