import { useState, useRef, useEffect } from 'react'; import ChatMessage from './components/ChatMessage'; import ChatInput from './components/ChatInput'; import { askQuestion } from './api/chat'; import './App.css'; const SUGGESTIONS = [ 'What is the capital of Australia?', 'Who developed the theory of relativity?', 'How does photosynthesis work?', ]; const PIPELINE_STEPS = [ { label: 'Load', model: 'Docling', color: '#7c3aed', icon: ( ), }, { label: 'Chunk', model: 'chonkie', color: '#dc2626', icon: ( ), }, { label: 'Embed', model: 'bge-m3', color: '#2563eb', icon: ( ), }, { label: 'Retrieve', model: 'Qdrant · bge-reranker-v2-m3', color: '#059669', icon: ( ), }, { label: 'Generate', model: 'Llama 3.3 70B', color: '#d97706', icon: ( ), }, ]; export default function App() { const [messages, setMessages] = useState([]); const [loading, setLoading] = useState(false); const [dark, setDark] = useState(true); const bottomRef = useRef(null); useEffect(() => { bottomRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages, loading]); const handleSubmit = async (query) => { if (!query.trim() || loading) return; setMessages((prev) => [...prev, { role: 'user', content: query }]); setLoading(true); try { const data = await askQuestion(query, false); if (data.needs_confirmation) { setMessages((prev) => [...prev, { role: 'assistant', type: 'confirmation', content: data.message, pendingQuery: query, }]); } else { setMessages((prev) => [...prev, { role: 'assistant', content: data.answer, sources: data.sources, }]); } } catch { setMessages((prev) => [...prev, { role: 'assistant', content: 'Could not reach the backend. Make sure the API server is running on port 8000.', sources: [], error: true, }]); } finally { setLoading(false); } }; const handleConfirm = async (pendingQuery) => { setMessages((prev) => prev.map((m) => m.type === 'confirmation' ? { ...m, type: 'confirmed', content: m.content } : m )); setMessages((prev) => [...prev, { role: 'user', content: 'Yes' }]); setLoading(true); try { const data = await askQuestion(pendingQuery, true); setMessages((prev) => [...prev, { role: 'assistant', content: data.answer, sources: data.sources, }]); } catch { setMessages((prev) => [...prev, { role: 'assistant', content: 'Could not reach the backend.', sources: [], error: true, }]); } finally { setLoading(false); } }; const handleDecline = () => { setMessages((prev) => prev.map((m) => m.type === 'confirmation' ? { ...m, type: 'declined', content: m.content } : m )); setMessages((prev) => [...prev, { role: 'user', content: 'No' }, { role: 'assistant', content: 'Okay, skipping this one.', sources: [] }, ]); }; const handleNewChat = () => setMessages([]); return (
{messages.length === 0 ? (

ChatJio

Ask anything about the mini-wikipedia knowledge base

{SUGGESTIONS.map((s, i) => ( ))}
) : (
{messages.map((msg, i) => ( handleConfirm(msg.pendingQuery) : undefined} onDecline={msg.type === 'confirmation' ? handleDecline : undefined} /> ))} {loading && (
J
)}
)}
); }