Spaces:
Runtime error
Runtime error
| "use client"; | |
| import React, { useState } from 'react'; | |
| import { | |
| Database, Upload, Search, Zap, Brain, | |
| Settings, CheckCircle, Activity, ArrowRight, | |
| FileUp, BarChart3, Eye, Download, Play | |
| } from 'lucide-react'; | |
| import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; | |
| import { Button } from "@/components/ui/button"; | |
| import { Input } from "@/components/ui/input"; | |
| import { Textarea } from "@/components/ui/textarea"; | |
| import { Badge } from "@/components/ui/badge"; | |
| export default function DatasetArchitect() { | |
| const [searchQuery, setSearchQuery] = useState(''); | |
| const [isSearching, setIsSearching] = useState(false); | |
| const [uploadedFiles, setUploadedFiles] = useState<File[]>([]); | |
| const [architectAnalysis, setArchitectAnalysis] = useState<any>(null); | |
| const [wizardConfig, setWizardConfig] = useState<any>(null); | |
| const [customDataPriority, setCustomDataPriority] = useState(0.7); | |
| // Option 1: Find matching data from portal | |
| const handlePortalSearch = async () => { | |
| if (!searchQuery.trim()) return | |
| setIsSearching(true) | |
| try { | |
| const response = await fetch(`${process.env.NEXT_PUBLIC_TRAINING_API_BASE || 'http://localhost:9006'}/api/dataset-architect/option-1/find-data`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| query: searchQuery, | |
| task_type: null | |
| }) | |
| }) | |
| const result = await response.json() | |
| setArchitectAnalysis(result) | |
| } catch (error) { | |
| console.error('Portal search failed:', error) | |
| } finally { | |
| setIsSearching(false) | |
| } | |
| } | |
| // Option 2: Upload data | |
| const handleFileUpload = async (files: FileList) => { | |
| const fileArray = Array.from(files) | |
| setUploadedFiles(fileArray) | |
| const formData = new FormData() | |
| fileArray.forEach(file => formData.append('files', file)) | |
| formData.append('dataset_name', 'Uploaded Dataset') | |
| formData.append('dataset_description', 'User uploaded dataset for analysis') | |
| try { | |
| const response = await fetch(`${process.env.NEXT_PUBLIC_TRAINING_API_BASE || 'http://localhost:9006'}/api/dataset-architect/option-2/upload-data`, { | |
| method: 'POST', | |
| body: formData | |
| }) | |
| const result = await response.json() | |
| setArchitectAnalysis(result) | |
| } catch (error) { | |
| console.error('Upload failed:', error) | |
| } | |
| } | |
| // Option 3: Hybrid approach | |
| const handleHybridApproach = async () => { | |
| if (!searchQuery.trim() && uploadedFiles.length === 0) return | |
| try { | |
| const formData = new FormData() | |
| uploadedFiles.forEach(file => formData.append('files', file)) | |
| const response = await fetch(`${process.env.NEXT_PUBLIC_TRAINING_API_BASE || 'http://localhost:9006'}/api/dataset-architect/option-3/hybrid-approach`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| query: searchQuery, | |
| custom_data_priority: customDataPriority, | |
| metadata: { | |
| name: 'Hybrid Dataset', | |
| description: 'Combined portal and custom data' | |
| } | |
| }) | |
| }) | |
| const result = await response.json() | |
| setArchitectAnalysis(result) | |
| } catch (error) { | |
| console.error('Hybrid approach failed:', error) | |
| } | |
| } | |
| // Open preprocessing wizard | |
| const openPreprocessingWizard = async () => { | |
| if (!architectAnalysis) return | |
| try { | |
| const response = await fetch(`${process.env.NEXT_PUBLIC_TRAINING_API_BASE || 'http://localhost:9006'}/api/dataset-architect/open-wizard`, { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ | |
| architect_analysis: architectAnalysis, | |
| dataset_info: { name: 'Current Dataset' } | |
| }) | |
| }) | |
| const result = await response.json() | |
| setWizardConfig(result) | |
| } catch (error) { | |
| console.error('Wizard open failed:', error) | |
| } | |
| } | |
| return ( | |
| <div className="h-screen w-full flex flex-col bg-black/95 relative overflow-hidden"> | |
| {/* Neon grid overlay */} | |
| <div className="absolute inset-0 pointer-events-none z-0"> | |
| <div className="instrument-grid-overlay w-full h-full" /> | |
| </div> | |
| {/* Custom scrollbar styles */} | |
| <style dangerouslySetInnerHTML={{ | |
| __html: ` | |
| .cyber-scrollbar { | |
| scrollbar-width: thin; | |
| scrollbar-color: #00ffe7 rgba(0, 255, 231, 0.1); | |
| } | |
| .cyber-scrollbar::-webkit-scrollbar { | |
| width: 8px; | |
| height: 8px; | |
| } | |
| .cyber-scrollbar::-webkit-scrollbar-track { | |
| background: rgba(0, 0, 0, 0.3); | |
| border-radius: 4px; | |
| } | |
| .cyber-scrollbar::-webkit-scrollbar-thumb { | |
| background: linear-gradient(180deg, #00ffe7, #00b8a3); | |
| border-radius: 4px; | |
| border: 1px solid rgba(0, 255, 231, 0.3); | |
| } | |
| .cyber-scrollbar::-webkit-scrollbar-thumb:hover { | |
| background: linear-gradient(180deg, #39ff14, #00ffe7); | |
| box-shadow: 0 0 8px rgba(0, 255, 231, 0.5); | |
| } | |
| .cyber-scrollbar::-webkit-scrollbar-corner { | |
| background: rgba(0, 0, 0, 0.3); | |
| } | |
| ` | |
| }} /> | |
| {/* Header */} | |
| <div className="w-full p-4 z-10 flex-shrink-0"> | |
| <Card className="bg-black/80 border-[#00ffe7]/30 shadow-[#00ffe7]/20"> | |
| <CardHeader className="py-3"> | |
| <div className="flex items-center justify-between"> | |
| <div className="flex items-center gap-3"> | |
| <Database className="h-8 w-8 text-[#00ffe7] animate-pulse" /> | |
| <div> | |
| <CardTitle className="text-2xl font-mono tracking-tight text-[#00ffe7]"> | |
| Dataset Architect | |
| </CardTitle> | |
| <CardDescription className="text-sm text-[#00ffe7]/80"> | |
| AI-powered dataset discovery, analysis, and preprocessing with specialized meta models | |
| </CardDescription> | |
| </div> | |
| </div> | |
| <Badge className="bg-[#39ff14]/20 text-[#39ff14] border-[#39ff14]/30"> | |
| The Hardest Part | |
| </Badge> | |
| </div> | |
| </CardHeader> | |
| </Card> | |
| </div> | |
| {/* Main Content */} | |
| <div className="flex-1 flex flex-col p-4 pt-0 z-10 min-h-0 overflow-y-auto cyber-scrollbar"> | |
| {/* Data Source Options */} | |
| <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-6"> | |
| {/* Option 1: Data Portal Search */} | |
| <Card className="bg-black/80 border-[#00ffe7]/30 hover:border-[#00ffe7]/50 transition-all duration-300"> | |
| <CardHeader className="pb-3"> | |
| <div className="flex items-center gap-2"> | |
| <Search className="h-5 w-5 text-[#00ffe7]" /> | |
| <CardTitle className="text-lg text-[#00ffe7]">Find Data Portal</CardTitle> | |
| </div> | |
| <CardDescription className="text-[#00ffe7]/70"> | |
| Search using AI intelligence across Kaggle, HuggingFace, GitHub, and academic portals | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent className="space-y-3"> | |
| <textarea | |
| placeholder="Enter your data requirements (e.g., 'medical images', 'sentiment analysis', 'time series')" | |
| value={searchQuery} | |
| onChange={(e) => setSearchQuery(e.target.value)} | |
| className="w-full min-h-[80px] max-h-[120px] p-3 bg-black/60 border border-[#00ffe7]/30 text-[#00ffe7] placeholder:text-[#00ffe7]/50 rounded-md resize-none overflow-y-auto cyber-scrollbar focus:outline-none focus:ring-2 focus:ring-[#00ffe7]/50 focus:border-[#00ffe7]" | |
| /> | |
| <Button | |
| onClick={handlePortalSearch} | |
| disabled={isSearching || !searchQuery.trim()} | |
| className="w-full bg-[#00ffe7]/20 text-[#00ffe7] border border-[#00ffe7]/30 hover:bg-[#00ffe7]/30 hover:text-white" | |
| > | |
| {isSearching ? ( | |
| <> | |
| <Activity className="w-4 h-4 mr-2 animate-spin" /> | |
| Searching Portal... | |
| </> | |
| ) : ( | |
| <> | |
| <Search className="w-4 h-4 mr-2" /> | |
| Search Portal | |
| </> | |
| )} | |
| </Button> | |
| </CardContent> | |
| </Card> | |
| {/* Option 2: Upload Data */} | |
| <Card className="bg-black/80 border-[#00ffe7]/30 hover:border-[#00ffe7]/50 transition-all duration-300"> | |
| <CardHeader className="pb-3"> | |
| <div className="flex items-center gap-2"> | |
| <Upload className="h-5 w-5 text-[#00ffe7]" /> | |
| <CardTitle className="text-lg text-[#00ffe7]">Upload Data</CardTitle> | |
| </div> | |
| <CardDescription className="text-[#00ffe7]/70"> | |
| Upload your custom dataset for AI analysis and preprocessing recommendations | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent className="space-y-3"> | |
| <div className="border-2 border-dashed border-[#00ffe7]/30 rounded-lg p-6 text-center hover:border-[#00ffe7]/50 transition-colors min-h-[120px] max-h-[200px] overflow-y-auto cyber-scrollbar flex flex-col justify-center"> | |
| <FileUp className="h-8 w-8 text-[#00ffe7]/60 mx-auto mb-2" /> | |
| <p className="text-sm text-[#00ffe7]/70 mb-2"> | |
| Drop files here or click to browse | |
| </p> | |
| <input | |
| type="file" | |
| multiple | |
| onChange={(e) => e.target.files && handleFileUpload(e.target.files)} | |
| className="hidden" | |
| id="file-upload" | |
| /> | |
| <Button | |
| variant="ghost" | |
| size="sm" | |
| onClick={() => document.getElementById('file-upload')?.click()} | |
| className="text-[#00ffe7] border border-[#00ffe7]/30 hover:bg-[#00ffe7]/10" | |
| > | |
| Choose Files | |
| </Button> | |
| </div> | |
| {uploadedFiles.length > 0 && ( | |
| <div className="text-xs text-[#00ffe7]/80"> | |
| {uploadedFiles.length} file(s) uploaded | |
| </div> | |
| )} | |
| </CardContent> | |
| </Card> | |
| {/* Option 3: Hybrid Approach */} | |
| <Card className="bg-black/80 border-[#00ffe7]/30 hover:border-[#00ffe7]/50 transition-all duration-300"> | |
| <CardHeader className="pb-3"> | |
| <div className="flex items-center gap-2"> | |
| <Zap className="h-5 w-5 text-[#00ffe7]" /> | |
| <CardTitle className="text-lg text-[#00ffe7]">Hybrid Approach</CardTitle> | |
| </div> | |
| <CardDescription className="text-[#00ffe7]/70"> | |
| Intelligent mix using custom data as priority with portal data augmentation | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent className="space-y-3"> | |
| <div className="space-y-2"> | |
| <label className="text-sm text-[#00ffe7]/80">Custom Data Priority: {(customDataPriority * 100).toFixed(0)}%</label> | |
| <input | |
| type="range" | |
| min="0" | |
| max="1" | |
| step="0.1" | |
| value={customDataPriority} | |
| onChange={(e) => setCustomDataPriority(parseFloat(e.target.value))} | |
| className="w-full accent-[#00ffe7]" | |
| /> | |
| </div> | |
| <Button | |
| onClick={handleHybridApproach} | |
| disabled={!searchQuery.trim() && uploadedFiles.length === 0} | |
| className="w-full bg-[#00ffe7]/20 text-[#00ffe7] border border-[#00ffe7]/30 hover:bg-[#00ffe7]/30 hover:text-white" | |
| > | |
| <Zap className="w-4 h-4 mr-2" /> | |
| Create Hybrid Dataset | |
| </Button> | |
| </CardContent> | |
| </Card> | |
| </div> | |
| {/* Meta Models Status */} | |
| <Card className="bg-black/80 border-[#00ffe7]/30 mb-4"> | |
| <CardHeader className="py-3"> | |
| <CardTitle className="text-[#00ffe7] flex items-center gap-2"> | |
| <Brain className="h-5 w-5" /> | |
| Meta Models Status | |
| </CardTitle> | |
| </CardHeader> | |
| <CardContent> | |
| <div className="grid grid-cols-1 md:grid-cols-2 gap-4"> | |
| <Card className="bg-black/60 border-[#00ffe7]/20"> | |
| <CardHeader className="pb-2"> | |
| <CardTitle className="text-sm text-[#00ffe7]">Dataset Architect Model</CardTitle> | |
| <CardDescription className="text-xs text-[#00ffe7]/60"> | |
| Extreme expertise in data preprocessing, vectorization, and feature engineering | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent className="pt-2"> | |
| <div className="flex items-center gap-2"> | |
| <CheckCircle className="h-4 w-4 text-[#39ff14]" /> | |
| <Badge className="bg-[#39ff14]/20 text-[#39ff14] border-[#39ff14]/30 text-xs"> | |
| Loaded & Ready | |
| </Badge> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| <Card className="bg-black/60 border-[#00ffe7]/20"> | |
| <CardHeader className="pb-2"> | |
| <CardTitle className="text-sm text-[#00ffe7]">Data Science Expert Model</CardTitle> | |
| <CardDescription className="text-xs text-[#00ffe7]/60"> | |
| PhD-level analysis, t-SNE visualizations, and comprehensive insights | |
| </CardDescription> | |
| </CardHeader> | |
| <CardContent className="pt-2"> | |
| <div className="flex items-center gap-2"> | |
| <CheckCircle className="h-4 w-4 text-[#39ff14]" /> | |
| <Badge className="bg-[#39ff14]/20 text-[#39ff14] border-[#39ff14]/30 text-xs"> | |
| Loaded & Ready | |
| </Badge> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| {/* Analysis Results */} | |
| {architectAnalysis && ( | |
| <Card className="bg-black/80 border-[#00ffe7]/30 mb-4"> | |
| <CardHeader className="py-3"> | |
| <CardTitle className="text-[#00ffe7] flex items-center gap-2"> | |
| <BarChart3 className="h-5 w-5" /> | |
| Dataset Architect Analysis | |
| </CardTitle> | |
| </CardHeader> | |
| <CardContent className="space-y-4 max-h-[300px] overflow-y-auto cyber-scrollbar"> | |
| <div className="text-sm text-[#00ffe7]/80 font-mono"> | |
| Analysis completed successfully. Dataset ready for preprocessing. | |
| </div> | |
| <Button | |
| onClick={openPreprocessingWizard} | |
| className="bg-[#00ffe7]/20 text-[#00ffe7] border border-[#00ffe7]/30 hover:bg-[#00ffe7]/30 hover:text-white" | |
| > | |
| <Play className="w-4 h-4 mr-2" /> | |
| Open Preprocessing Wizard | |
| </Button> | |
| </CardContent> | |
| </Card> | |
| )} | |
| {/* Wizard Interface */} | |
| {wizardConfig && ( | |
| <Card className="bg-black/80 border-[#00ffe7]/30"> | |
| <CardHeader className="py-3"> | |
| <CardTitle className="text-[#00ffe7] flex items-center gap-2"> | |
| <Settings className="h-5 w-5" /> | |
| Dataset Preprocessing Wizard | |
| </CardTitle> | |
| </CardHeader> | |
| <CardContent className="space-y-4 max-h-[400px] overflow-y-auto cyber-scrollbar"> | |
| <div className="grid grid-cols-2 md:grid-cols-4 gap-2"> | |
| {['Tokenize', 'Normalize', 'Vectorize', 'Visualize'].map((step) => ( | |
| <Button | |
| key={step} | |
| size="sm" | |
| className="bg-[#00ffe7]/20 text-[#00ffe7] border border-[#00ffe7]/30 hover:bg-[#00ffe7]/30 hover:text-white" | |
| > | |
| {step} | |
| </Button> | |
| ))} | |
| </div> | |
| <div className="flex gap-2"> | |
| <Button | |
| size="sm" | |
| className="bg-[#39ff14]/20 text-[#39ff14] border border-[#39ff14]/30 hover:bg-[#39ff14]/30" | |
| > | |
| <Eye className="w-4 h-4 mr-2" /> | |
| Generate Visualizations | |
| </Button> | |
| <Button | |
| size="sm" | |
| className="bg-[#00ffe7]/20 text-[#00ffe7] border border-[#00ffe7]/30 hover:bg-[#00ffe7]/30 hover:text-white" | |
| > | |
| <Download className="w-4 h-4 mr-2" /> | |
| Export Analysis | |
| </Button> | |
| </div> | |
| </CardContent> | |
| </Card> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } |