'use client'; import { useEffect, useRef, useState, useCallback } from 'react'; import Progress from './components/Progress'; import { modelConfigMap } from './components/modelConfig'; import { ModelInput } from './components/ModelInput'; export default function Home() { const [result, setResult] = useState(null); const [ready, setReady] = useState(null); const [progressItems, setProgressItems] = useState([]); const [input, setInput] = useState(''); const [task, setTask] = useState('text-classification'); const [modelName, setModelName] = useState(() => modelConfigMap['text-classification'].defaultModel); const [currentModel, setCurrentModel] = useState(modelName); const worker = useRef(null); const [image, setImage] = useState(null); // Update modelName and currentModel when task changes useEffect(() => { const defaultModel = modelConfigMap[task].defaultModel; setModelName(defaultModel); setCurrentModel(defaultModel); }, [task]); useEffect(() => { if (!worker.current) { worker.current = new Worker(new URL('./worker.js', import.meta.url), { type: 'module' }); } const onMessageReceived = (e: MessageEvent) => { switch (e.data.status) { case 'initiate': setReady(false); setProgressItems(prev => [...prev, { ...e.data, progress: 0 }]); break; case 'progress': setProgressItems(prev => prev.map(item => { if (item.file === e.data.file) { return { ...item, progress: e.data.progress, loaded: e.data.loaded, total: e.data.total, name: e.data.name }; } return item; })); break; case 'done': setProgressItems(prev => { const updated = prev.map(item => item.file === e.data.file ? { ...item, done: true, progress: 100 } : item ); setTimeout(() => { setProgressItems(current => current.filter(item => item.file !== e.data.file) ); }, 1000); return updated; }); break; case 'ready': setReady(true); setCurrentModel(e.data.file || modelName); setProgressItems(prev => prev.filter(item => item.file !== e.data.file)); break; case 'complete': setResult(e.data.output); break; case 'error': setResult({ label: 'Error', score: 0, error: e.data.error }); break; } }; worker.current.addEventListener('message', onMessageReceived); return () => worker.current?.removeEventListener('message', onMessageReceived); }, [modelName]); const classify = useCallback((inputValue: string | Blob) => { if (worker.current) { worker.current.postMessage({ input: inputValue, modelName: currentModel, task, }); } }, [currentModel, task]); const handleLoadModel = () => { setReady(false); setResult(null); setProgressItems([]); setCurrentModel(modelName); if (worker.current) { worker.current.postMessage({ action: 'load-model', modelName, task }); } }; useEffect(() => { setResult(null); setInput(''); setImage(null); setModelName(modelConfigMap[task].defaultModel); }, [task]); const InputComponent = modelConfigMap[task].inputComponent; const OutputComponent = modelConfigMap[task].outputComponent; return (

Transformers.js Playground

Powered by Transformers.js & Next.js (Local browser inference)

Result

{ready === false && (

Loading Model

{progressItems.map((data, i) => (
))}
)}
); }