import { useState, useRef, useEffect, useCallback } from 'react' import { Send, Settings, Trash2, Loader2, X } from 'lucide-react' import { Dialog, Transition, Switch } from '@headlessui/react' import { Fragment } from 'react' import { ChatMessage, TextGenerationWorkerInput, WorkerMessage } from '../types' import { useModel } from '../contexts/ModelContext' function TextGeneration() { const [messages, setMessages] = useState([ { role: 'system', content: 'You are a helpful assistant.' } ]) const [currentMessage, setCurrentMessage] = useState('') const [showSettings, setShowSettings] = useState(false) // For simple text generation const [prompt, setPrompt] = useState('') const [generatedText, setGeneratedText] = useState('') // Generation parameters const [temperature, setTemperature] = useState(0.7) const [maxTokens, setMaxTokens] = useState(100) const [topP, setTopP] = useState(0.9) const [topK, setTopK] = useState(50) const [doSample, setDoSample] = useState(true) // Generation state const [isGenerating, setIsGenerating] = useState(false) const { activeWorker, status, modelInfo, hasBeenLoaded } = useModel() const messagesEndRef = useRef(null) const scrollToBottom = () => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) } useEffect(() => { scrollToBottom() }, [messages, generatedText]) const stopGeneration = useCallback(() => { if (activeWorker && isGenerating) { activeWorker.postMessage({ type: 'stop' }) setIsGenerating(false) } }, [activeWorker, isGenerating]) const handleSendMessage = useCallback(() => { if (!currentMessage.trim() || !modelInfo || !activeWorker || isGenerating) { return } const userMessage: ChatMessage = { role: 'user', content: currentMessage.trim() } const updatedMessages = [...messages, userMessage] setMessages(updatedMessages) setCurrentMessage('') setIsGenerating(true) const message: TextGenerationWorkerInput = { type: 'generate', messages: updatedMessages, hasChatTemplate: modelInfo.hasChatTemplate, model: modelInfo.id, temperature, max_new_tokens: maxTokens, top_p: topP, top_k: topK, do_sample: doSample, } activeWorker.postMessage(message) }, [currentMessage, messages, modelInfo, activeWorker, temperature, maxTokens, topP, topK, doSample, isGenerating]) const handleGenerateText = useCallback(() => { if (!prompt.trim() || !modelInfo || !activeWorker || isGenerating) { return } setIsGenerating(true) const message: TextGenerationWorkerInput = { type: 'generate', prompt: prompt.trim(), hasChatTemplate: modelInfo.hasChatTemplate, model: modelInfo.id, temperature, max_new_tokens: maxTokens, top_p: topP, top_k: topK, do_sample: doSample } activeWorker.postMessage(message) }, [prompt, modelInfo, activeWorker, temperature, maxTokens, topP, topK, doSample, isGenerating]) useEffect(() => { if (!activeWorker) return const onMessageReceived = (e: MessageEvent) => { const { status, output } = e.data if (status === 'output' && output) { setIsGenerating(false) if (modelInfo?.hasChatTemplate) { // Chat mode const assistantMessage: ChatMessage = { role: 'assistant', content: output.content } setMessages(prev => [...prev, assistantMessage]) } else { // Simple text generation mode setGeneratedText(output.content) } } else if (status === 'ready') { setIsGenerating(false) } else if (status === 'error') { setIsGenerating(false) } } activeWorker.addEventListener('message', onMessageReceived) return () => { activeWorker.removeEventListener('message', onMessageReceived) } }, [activeWorker, modelInfo?.hasChatTemplate]) const handleKeyPress = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault() if (modelInfo?.hasChatTemplate) { handleSendMessage() } else { handleGenerateText() } } } const clearChat = () => { if (modelInfo?.hasChatTemplate) { setMessages([{ role: 'system', content: 'You are a helpful assistant.' }]) } else { setPrompt('') setGeneratedText('') } } const updateSystemMessage = (content: string) => { setMessages(prev => [ { role: 'system', content }, ...prev.filter(msg => msg.role !== 'system') ]) } const busy = status !== 'ready' || isGenerating const hasChatTemplate = modelInfo?.hasChatTemplate return (

{hasChatTemplate ? 'Chat with AI' : 'Text Generation'}

{isGenerating && ( )}
{/* Settings Dialog using Headless UI */} setShowSettings(false)}>
Generation Settings
{/* Generation Parameters */}

Parameters

setTemperature(parseFloat(e.target.value))} className="w-full" />
setMaxTokens(parseInt(e.target.value))} className="w-full" />
setTopP(parseFloat(e.target.value))} className="w-full" />
setTopK(parseInt(e.target.value))} className="w-full" />
Enable sampling
{/* System Message for Chat */} {hasChatTemplate && (

System Message