import Input from '@/components/ui/Input' import Button from '@/components/ui/Button' import { useCallback, useEffect, useRef, useState } from 'react' import { queryText, queryTextStream, Message } from '@/api/lightrag' import { errorMessage } from '@/lib/utils' import { useSettingsStore } from '@/stores/settings' import { useDebounce } from '@/hooks/useDebounce' import QuerySettings from '@/components/retrieval/QuerySettings' import { ChatMessage, MessageWithError } from '@/components/retrieval/ChatMessage' import { EraserIcon, SendIcon } from 'lucide-react' import { useTranslation } from 'react-i18next' export default function RetrievalTesting() { const { t } = useTranslation() const [messages, setMessages] = useState( () => useSettingsStore.getState().retrievalHistory || [] ) const [inputValue, setInputValue] = useState('') const [isLoading, setIsLoading] = useState(false) const messagesEndRef = useRef(null) const scrollToBottom = useCallback(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) }, []) const handleSubmit = useCallback( async (e: React.FormEvent) => { e.preventDefault() if (!inputValue.trim() || isLoading) return // Create messages const userMessage: Message = { content: inputValue, role: 'user' } const assistantMessage: Message = { content: '', role: 'assistant' } const prevMessages = [...messages] // Add messages to chatbox setMessages([...prevMessages, userMessage, assistantMessage]) // Clear input and set loading setInputValue('') setIsLoading(true) // Create a function to update the assistant's message const updateAssistantMessage = (chunk: string, isError?: boolean) => { assistantMessage.content += chunk setMessages((prev) => { const newMessages = [...prev] const lastMessage = newMessages[newMessages.length - 1] if (lastMessage.role === 'assistant') { lastMessage.content = assistantMessage.content lastMessage.isError = isError } return newMessages }) } // Prepare query parameters const state = useSettingsStore.getState() const queryParams = { ...state.querySettings, query: userMessage.content, conversation_history: prevMessages .filter((m) => m.isError !== true) .map((m) => ({ role: m.role, content: m.content })) } try { // Run query if (state.querySettings.stream) { let errorMessage = '' await queryTextStream(queryParams, updateAssistantMessage, (error) => { errorMessage += error }) if (errorMessage) { if (assistantMessage.content) { errorMessage = assistantMessage.content + '\n' + errorMessage } updateAssistantMessage(errorMessage, true) } } else { const response = await queryText(queryParams) updateAssistantMessage(response.response) } } catch (err) { // Handle error updateAssistantMessage(`${t('retrievePanel.retrieval.error')}\n${errorMessage(err)}`, true) } finally { // Clear loading and add messages to state setIsLoading(false) useSettingsStore .getState() .setRetrievalHistory([...prevMessages, userMessage, assistantMessage]) } }, [inputValue, isLoading, messages, setMessages, t] ) const debouncedMessages = useDebounce(messages, 100) useEffect(() => scrollToBottom(), [debouncedMessages, scrollToBottom]) const clearMessages = useCallback(() => { setMessages([]) useSettingsStore.getState().setRetrievalHistory([]) }, [setMessages]) return (
{messages.length === 0 ? (
{t('retrievePanel.retrieval.startPrompt')}
) : ( messages.map((message, idx) => (
{}
)) )}
setInputValue(e.target.value)} placeholder={t('retrievePanel.retrieval.placeholder')} disabled={isLoading} />
) }