Spaces:
Runtime error
Runtime error
| 'use client'; | |
| import React, { useState, useEffect } from 'react'; | |
| import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; | |
| import { Button } from '@/components/ui/button'; | |
| import { Badge } from '@/components/ui/badge'; | |
| import { Input } from '@/components/ui/input'; | |
| import { Textarea } from '@/components/ui/textarea'; | |
| import { Progress } from '@/components/ui/progress'; | |
| import { | |
| Rocket, | |
| Eye, | |
| Image, | |
| MessageSquare, | |
| TrendingUp, | |
| Volume2, | |
| Zap, | |
| Code2, | |
| Brain, | |
| Search, | |
| Filter, | |
| Star, | |
| Clock, | |
| Target, | |
| Lightbulb | |
| } from 'lucide-react'; | |
| interface Template { | |
| id: string; | |
| name: string; | |
| description: string; | |
| domain: string; | |
| task: string; | |
| example_request: string; | |
| estimated_consciousness: number; | |
| estimated_accuracy: number; | |
| } | |
| interface TemplateCategory { | |
| name: string; | |
| icon: React.ComponentType<any>; | |
| color: string; | |
| templates: Template[]; | |
| } | |
| export default function QuickTemplates() { | |
| const [templates, setTemplates] = useState<Template[]>([]); | |
| const [categories, setCategories] = useState<TemplateCategory[]>([]); | |
| const [selectedTemplate, setSelectedTemplate] = useState<Template | null>(null); | |
| const [customization, setCustomization] = useState(''); | |
| const [isGenerating, setIsGenerating] = useState(false); | |
| const [searchTerm, setSearchTerm] = useState(''); | |
| const [selectedCategory, setSelectedCategory] = useState<string>('all'); | |
| const [isLoading, setIsLoading] = useState(true); | |
| useEffect(() => { | |
| fetchTemplates(); | |
| }, []); | |
| useEffect(() => { | |
| if (templates.length > 0) { | |
| organizeTemplates(); | |
| } | |
| }, [templates, searchTerm, selectedCategory]); | |
| const fetchTemplates = async () => { | |
| try { | |
| const response = await fetch('/api/ai-architect/templates'); | |
| if (response.ok) { | |
| const data = await response.json(); | |
| setTemplates(data.templates); | |
| } | |
| } catch (error) { | |
| console.error('Failed to fetch templates:', error); | |
| } finally { | |
| setIsLoading(false); | |
| } | |
| }; | |
| const organizeTemplates = () => { | |
| let filteredTemplates = templates; | |
| // Apply search filter | |
| if (searchTerm) { | |
| filteredTemplates = templates.filter(template => | |
| template.name.toLowerCase().includes(searchTerm.toLowerCase()) || | |
| template.description.toLowerCase().includes(searchTerm.toLowerCase()) || | |
| template.domain.toLowerCase().includes(searchTerm.toLowerCase()) | |
| ); | |
| } | |
| // Apply category filter | |
| if (selectedCategory !== 'all') { | |
| filteredTemplates = filteredTemplates.filter(template => | |
| template.domain === selectedCategory | |
| ); | |
| } | |
| // Group by domain | |
| const domainCategories: Record<string, Template[]> = {}; | |
| filteredTemplates.forEach(template => { | |
| if (!domainCategories[template.domain]) { | |
| domainCategories[template.domain] = []; | |
| } | |
| domainCategories[template.domain].push(template); | |
| }); | |
| // Create category objects with icons and colors | |
| const categoryConfig = { | |
| computer_vision: { icon: Eye, color: 'blue' }, | |
| natural_language_processing: { icon: MessageSquare, color: 'green' }, | |
| time_series: { icon: TrendingUp, color: 'purple' }, | |
| audio: { icon: Volume2, color: 'orange' }, | |
| multimodal: { icon: Zap, color: 'pink' }, | |
| }; | |
| const organizedCategories: TemplateCategory[] = Object.entries(domainCategories).map(([domain, domainTemplates]) => ({ | |
| name: domain.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase()), | |
| icon: categoryConfig[domain as keyof typeof categoryConfig]?.icon || Code2, | |
| color: categoryConfig[domain as keyof typeof categoryConfig]?.color || 'gray', | |
| templates: domainTemplates.sort((a, b) => b.estimated_consciousness - a.estimated_consciousness) | |
| })); | |
| setCategories(organizedCategories); | |
| }; | |
| const generateFromTemplate = async (template: Template) => { | |
| setIsGenerating(true); | |
| try { | |
| const response = await fetch('/api/ai-architect/quick-architecture', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| template_id: template.id, | |
| customization: customization || undefined | |
| }) | |
| }); | |
| if (response.ok) { | |
| const result = await response.json(); | |
| // This could trigger a callback to parent component or navigate to results | |
| console.log('Template generation result:', result); | |
| alert('Architecture generated successfully! Check the AI Architect panel for results.'); | |
| } else { | |
| throw new Error('Generation failed'); | |
| } | |
| } catch (error) { | |
| console.error('Template generation failed:', error); | |
| alert('Failed to generate architecture. Please try again.'); | |
| } finally { | |
| setIsGenerating(false); | |
| } | |
| }; | |
| const getDomainIcon = (domain: string) => { | |
| const icons = { | |
| computer_vision: Eye, | |
| natural_language_processing: MessageSquare, | |
| time_series: TrendingUp, | |
| audio: Volume2, | |
| multimodal: Zap, | |
| }; | |
| const IconComponent = icons[domain as keyof typeof icons] || Code2; | |
| return <IconComponent className="w-4 h-4" />; | |
| }; | |
| const getDomainColor = (domain: string) => { | |
| const colors = { | |
| computer_vision: 'text-blue-400 border-blue-400', | |
| natural_language_processing: 'text-green-400 border-green-400', | |
| time_series: 'text-purple-400 border-purple-400', | |
| audio: 'text-orange-400 border-orange-400', | |
| multimodal: 'text-pink-400 border-pink-400', | |
| }; | |
| return colors[domain as keyof typeof colors] || 'text-gray-400 border-gray-400'; | |
| }; | |
| const getUniqueCategories = () => { | |
| const uniqueDomains = Array.from(new Set(templates.map(t => t.domain))); | |
| return uniqueDomains.map(domain => ({ | |
| value: domain, | |
| label: domain.replace('_', ' ').replace(/\b\w/g, l => l.toUpperCase()) | |
| })); | |
| }; | |
| if (isLoading) { | |
| return ( | |
| <div className="w-full h-full flex items-center justify-center"> | |
| <div className="text-center space-y-4"> | |
| <Rocket className="w-12 h-12 text-muted-foreground mx-auto animate-pulse" /> | |
| <p className="text-muted-foreground">Loading templates...</p> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| return ( | |
| <div className="w-full h-full flex flex-col space-y-6"> | |
| {/* Header */} | |
| <Card className="border-purple-500/20 bg-gradient-to-r from-purple-900/20 to-pink-900/20"> | |
| <CardHeader> | |
| <CardTitle className="flex items-center space-x-2"> | |
| <Rocket className="w-6 h-6 text-purple-400" /> | |
| <span>Quick Start Templates</span> | |
| <Badge variant="secondary" className="bg-purple-500/20 text-purple-300"> | |
| {templates.length} Available | |
| </Badge> | |
| </CardTitle> | |
| </CardHeader> | |
| </Card> | |
| {/* Search and Filters */} | |
| <Card> | |
| <CardContent className="p-4"> | |
| <div className="flex items-center space-x-4"> | |
| <div className="flex items-center space-x-2 flex-1"> | |
| <Search className="w-4 h-4 text-muted-foreground" /> | |
| <Input | |
| placeholder="Search templates..." | |
| value={searchTerm} | |
| onChange={(e) => setSearchTerm(e.target.value)} | |
| className="flex-1" | |
| /> | |
| </div> | |
| <div className="flex items-center space-x-2"> | |
| <Filter className="w-4 h-4 text-muted-foreground" /> | |
| <select | |
| value={selectedCategory} | |
| onChange={(e) => setSelectedCategory(e.target.value)} | |
| className="px-3 py-2 border rounded-md bg-background" | |
| > | |
| <option value="all">All Categories</option> | |
| {getUniqueCategories().map(category => ( | |
| <option key={category.value} value={category.value}> | |
| {category.label} | |
| </option> | |
| ))} | |
| </select> | |
| </div> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| {/* Template Categories */} | |
| <div className="flex-1 space-y-6 overflow-auto"> | |
| {categories.length === 0 ? ( | |
| <Card> | |
| <CardContent className="p-8 text-center"> | |
| <Lightbulb className="w-12 h-12 text-muted-foreground mx-auto mb-4" /> | |
| <h3 className="text-lg font-semibold mb-2">No templates found</h3> | |
| <p className="text-muted-foreground"> | |
| Try adjusting your search criteria or check back later for new templates. | |
| </p> | |
| </CardContent> | |
| </Card> | |
| ) : ( | |
| categories.map((category, categoryIndex) => ( | |
| <Card key={categoryIndex}> | |
| <CardHeader> | |
| <CardTitle className="flex items-center space-x-2"> | |
| <category.icon className={`w-5 h-5 text-${category.color}-400`} /> | |
| <span>{category.name}</span> | |
| <Badge variant="outline" className="text-xs"> | |
| {category.templates.length} templates | |
| </Badge> | |
| </CardTitle> | |
| </CardHeader> | |
| <CardContent> | |
| <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> | |
| {category.templates.map((template) => ( | |
| <Card | |
| key={template.id} | |
| className="hover:shadow-lg transition-all duration-200 cursor-pointer border-border/50 hover:border-purple-500/50" | |
| onClick={() => setSelectedTemplate(template)} | |
| > | |
| <CardContent className="p-4 space-y-3"> | |
| {/* Template Header */} | |
| <div className="flex items-start justify-between"> | |
| <div className="flex items-center space-x-2"> | |
| {getDomainIcon(template.domain)} | |
| <span className="font-medium text-sm">{template.name}</span> | |
| </div> | |
| <Badge | |
| variant="outline" | |
| className={`text-xs ${getDomainColor(template.domain)}`} | |
| > | |
| {template.task} | |
| </Badge> | |
| </div> | |
| {/* Description */} | |
| <p className="text-xs text-muted-foreground line-clamp-2"> | |
| {template.description} | |
| </p> | |
| {/* Metrics */} | |
| <div className="space-y-2"> | |
| <div className="flex items-center justify-between text-xs"> | |
| <span className="text-muted-foreground">Consciousness</span> | |
| <span className="font-medium"> | |
| {(template.estimated_consciousness * 100).toFixed(0)}% | |
| </span> | |
| </div> | |
| <Progress | |
| value={template.estimated_consciousness * 100} | |
| className="h-1" | |
| /> | |
| <div className="flex items-center justify-between text-xs"> | |
| <span className="text-muted-foreground">Est. Accuracy</span> | |
| <span className="font-medium"> | |
| {(template.estimated_accuracy * 100).toFixed(0)}% | |
| </span> | |
| </div> | |
| <Progress | |
| value={template.estimated_accuracy * 100} | |
| className="h-1" | |
| /> | |
| </div> | |
| {/* Action Buttons */} | |
| <div className="flex items-center space-x-2 pt-2"> | |
| <Button | |
| variant="outline" | |
| size="sm" | |
| className="flex-1 text-xs" | |
| onClick={(e) => { | |
| e.stopPropagation(); | |
| setSelectedTemplate(template); | |
| }} | |
| > | |
| <Eye className="w-3 h-3 mr-1" /> | |
| Preview | |
| </Button> | |
| <Button | |
| size="sm" | |
| className="flex-1 text-xs bg-purple-600 hover:bg-purple-700" | |
| onClick={(e) => { | |
| e.stopPropagation(); | |
| generateFromTemplate(template); | |
| }} | |
| disabled={isGenerating} | |
| > | |
| <Rocket className="w-3 h-3 mr-1" /> | |
| Use | |
| </Button> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| ))} | |
| </div> | |
| </CardContent> | |
| </Card> | |
| )) | |
| )} | |
| </div> | |
| {/* Template Detail Modal */} | |
| {selectedTemplate && ( | |
| <Card className="fixed inset-4 z-50 bg-background/95 backdrop-blur-sm border shadow-lg overflow-auto"> | |
| <CardHeader> | |
| <div className="flex items-center justify-between"> | |
| <CardTitle className="flex items-center space-x-2"> | |
| {getDomainIcon(selectedTemplate.domain)} | |
| <span>{selectedTemplate.name}</span> | |
| <Badge | |
| variant="outline" | |
| className={getDomainColor(selectedTemplate.domain)} | |
| > | |
| {selectedTemplate.task} | |
| </Badge> | |
| </CardTitle> | |
| <Button | |
| variant="outline" | |
| size="sm" | |
| onClick={() => setSelectedTemplate(null)} | |
| > | |
| Close | |
| </Button> | |
| </div> | |
| </CardHeader> | |
| <CardContent className="space-y-6"> | |
| {/* Description */} | |
| <div> | |
| <h3 className="font-semibold mb-2">Description</h3> | |
| <p className="text-muted-foreground">{selectedTemplate.description}</p> | |
| </div> | |
| {/* Example Request */} | |
| <div> | |
| <h3 className="font-semibold mb-2">Example Request</h3> | |
| <div className="p-3 bg-muted rounded-lg"> | |
| <p className="text-sm italic">"{selectedTemplate.example_request}"</p> | |
| </div> | |
| </div> | |
| {/* Performance Metrics */} | |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <div> | |
| <h4 className="font-medium mb-3 flex items-center space-x-2"> | |
| <Brain className="w-4 h-4 text-purple-400" /> | |
| <span>ZPE Consciousness</span> | |
| </h4> | |
| <div className="space-y-2"> | |
| <div className="flex justify-between text-sm"> | |
| <span>Estimated Score</span> | |
| <span className="font-medium"> | |
| {(selectedTemplate.estimated_consciousness * 100).toFixed(1)}% | |
| </span> | |
| </div> | |
| <Progress value={selectedTemplate.estimated_consciousness * 100} /> | |
| <p className="text-xs text-muted-foreground"> | |
| Higher consciousness scores indicate more sophisticated AI awareness and adaptability. | |
| </p> | |
| </div> | |
| </div> | |
| <div> | |
| <h4 className="font-medium mb-3 flex items-center space-x-2"> | |
| <Target className="w-4 h-4 text-green-400" /> | |
| <span>Model Accuracy</span> | |
| </h4> | |
| <div className="space-y-2"> | |
| <div className="flex justify-between text-sm"> | |
| <span>Estimated Accuracy</span> | |
| <span className="font-medium"> | |
| {(selectedTemplate.estimated_accuracy * 100).toFixed(1)}% | |
| </span> | |
| </div> | |
| <Progress value={selectedTemplate.estimated_accuracy * 100} /> | |
| <p className="text-xs text-muted-foreground"> | |
| Expected performance on typical datasets for this domain and task. | |
| </p> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Customization */} | |
| <div> | |
| <h3 className="font-semibold mb-2">Customization (Optional)</h3> | |
| <Textarea | |
| placeholder="Add any specific requirements or modifications to the base template..." | |
| value={customization} | |
| onChange={(e) => setCustomization(e.target.value)} | |
| rows={3} | |
| className="resize-none" | |
| /> | |
| <p className="text-xs text-muted-foreground mt-2"> | |
| Describe any additional features, constraints, or modifications you'd like to apply to this template. | |
| </p> | |
| </div> | |
| {/* Actions */} | |
| <div className="flex items-center justify-end space-x-4 pt-4 border-t"> | |
| <Button | |
| variant="outline" | |
| onClick={() => setSelectedTemplate(null)} | |
| > | |
| Cancel | |
| </Button> | |
| <Button | |
| onClick={() => generateFromTemplate(selectedTemplate)} | |
| disabled={isGenerating} | |
| className="bg-purple-600 hover:bg-purple-700" | |
| > | |
| {isGenerating ? ( | |
| <> | |
| <Clock className="w-4 h-4 mr-2 animate-spin" /> | |
| Generating... | |
| </> | |
| ) : ( | |
| <> | |
| <Rocket className="w-4 h-4 mr-2" /> | |
| Generate Architecture | |
| </> | |
| )} | |
| </Button> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| )} | |
| </div> | |
| ); | |
| } |