QuantumAI / frontend /src /App.js
Abhroneel's picture
Stage 2
32ba82b
Raw
History Blame Contribute Delete
4.4 kB
import React, { useState, useEffect, useRef, useCallback } from 'react';
import Sidebar from './components/Sidebar';
import Header from './components/Header';
import ChatArea from './components/ChatArea';
import InputBar from './components/InputBar';
import ParticleCanvas from './components/ParticleCanvas';
import './App.css';
const MODELS = [
{ id: 'llama-3.1-8b-instant', label: 'Llama 3.1 8B' },
{ id: 'llama-3.3-70b-versatile', label: 'Llama 3.3 70B' },
{ id: 'mixtral-8x7b-32768', label: 'Mixtral 8x7B' },
];
const SUGGESTED_QUERIES = [
'What is quantum entanglement?',
"Explain Bell's theorem",
'How does quantum teleportation work?',
'Can entanglement transmit information faster than light?',
'What are Bell states?',
'What causes quantum decoherence?',
];
export default function App() {
const [messages, setMessages] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [config, setConfig] = useState({
model: MODELS[0].id,
temperature: 0.1,
topK: 3,
});
const [status, setStatus] = useState('idle');
const [sidebarOpen, setSidebarOpen] = useState(true);
const [chatHistory, setChatHistory] = useState([
{ id: 1, title: 'Current Session', active: true, time: 'Now' },
]);
const abortRef = useRef(null);
useEffect(() => {
fetch('/health')
.then(r => r.json())
.then(() => setStatus('ready'))
.catch(() => setStatus('error'));
}, []);
const sendMessage = useCallback(async (query) => {
if (!query.trim() || isLoading) return;
const userMsg = {
id: Date.now(),
role: 'user',
content: query,
timestamp: new Date(),
};
setMessages(prev => [...prev, userMsg]);
setIsLoading(true);
setStatus('processing');
try {
const res = await fetch('/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
query,
top_k: config.topK,
model: config.model,
temperature: config.temperature,
}),
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(err?.detail || `HTTP ${res.status}`);
}
const data = await res.json();
const aiMsg = {
id: Date.now() + 1,
role: 'assistant',
content: data.answer,
chunksRetrieved: data.chunks_retrieved,
chunksPreview: data.chunks_preview,
timestamp: new Date(),
};
setMessages(prev => [...prev, aiMsg]);
if (messages.length === 0) {
setChatHistory(prev =>
prev.map(c => c.active ? { ...c, title: query.slice(0, 40) + (query.length > 40 ? '…' : '') } : c)
);
}
} catch (err) {
const errMsg = {
id: Date.now() + 1,
role: 'assistant',
content: `**Error:** ${err.message}`,
isError: true,
timestamp: new Date(),
};
setMessages(prev => [...prev, errMsg]);
} finally {
setIsLoading(false);
setStatus('ready');
}
}, [isLoading, config, messages.length]);
const newChat = () => {
setMessages([]);
setStatus('ready');
const newId = Date.now();
setChatHistory(prev => [
{ id: newId, title: 'New Chat', active: true, time: 'Now' },
...prev.map(c => ({ ...c, active: false })),
]);
};
return (
<div className="app">
<ParticleCanvas />
<div className="app-layout">
<Sidebar
open={sidebarOpen}
chatHistory={chatHistory}
onNewChat={newChat}
onSelectChat={() => {}}
config={config}
setConfig={setConfig}
models={MODELS}
/>
<div className="app-main">
<Header
status={status}
model={config.model}
models={MODELS}
onToggleSidebar={() => setSidebarOpen(o => !o)}
sidebarOpen={sidebarOpen}
/>
<ChatArea
messages={messages}
isLoading={isLoading}
suggestedQueries={SUGGESTED_QUERIES}
onSuggestedQuery={sendMessage}
/>
<InputBar
onSend={sendMessage}
isLoading={isLoading}
config={config}
setConfig={setConfig}
models={MODELS}
/>
</div>
</div>
</div>
);
}