diff --git a/frontend/app/admin/DataIngestion.tsx b/frontend/app/admin/DataIngestion.tsx new file mode 100644 index 0000000..a184198 --- /dev/null +++ b/frontend/app/admin/DataIngestion.tsx @@ -0,0 +1,129 @@ +'use client'; +import React, { useState } from 'react'; +import { useAuth } from '@/app/authProvider'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Label } from '@/components/ui/label'; +import { Input } from '@/components/ui/input'; +import { LoaderIcon, Upload } from 'lucide-react'; +import { FileUpload } from '@/components/ui/file-upload'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; + +export default function DataIngestion() { + const { axiosInstance } = useAuth(); + const [file, setFile] = useState(null); + const [isUploading, setIsUploading] = useState(false); + const [uploadResult, setUploadResult] = useState(null); + + const handleFileUpload = (files: File[]) => { + if (files.length > 0) { + setFile(files[0]); + } + }; + + const uploadFile = async () => { + if (!file) return; + + setIsUploading(true); + setUploadResult(null); + + const formData = new FormData(); + formData.append('file', file); + + try { + const response = await axiosInstance.post( + '/api/admin/upload_data', + formData, + { + headers: { + 'Content-Type': 'multipart/form-data', + }, + } + ); + + setUploadResult(`File uploaded successfully. ${response.data.message}`); + } catch (error) { + console.error('Error uploading file:', error); + setUploadResult('Error uploading file. Please try again.'); + } finally { + setIsUploading(false); + setFile(null); + } + }; + + return ( + + + Data Ingestion + Manage data ingestion processes. + + +
+
+ +
+ {file && ( +
+ +
+ )} + {uploadResult && ( +
+ {uploadResult} +
+ )} +
+ + +
+
+ + +
+
+
+
+ ); +} diff --git a/frontend/app/admin/RAGConfiguration.tsx b/frontend/app/admin/RAGConfiguration.tsx new file mode 100644 index 0000000..a89f8de --- /dev/null +++ b/frontend/app/admin/RAGConfiguration.tsx @@ -0,0 +1,184 @@ +'use client'; +import React, { useEffect, useState } from 'react'; +import { useAuth } from '@/app/authProvider'; +import { + Card, + CardContent, + CardDescription, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +import { Button } from '@/components/ui/button'; +import { Label } from '@/components/ui/label'; +import { Input } from '@/components/ui/input'; +import { Textarea } from '@/components/ui/textarea'; +import { Separator } from '@/components/ui/separator'; +import { PlusCircle, Trash2 } from 'lucide-react'; + +export default function RAGConfiguration() { + const { axiosInstance } = useAuth(); + const [systemPrompt, setSystemPrompt] = useState(''); + const [suggestedQuestions, setSuggestedQuestions] = useState([]); + const [configLoading, setConfigLoading] = useState(true); + const [configError, setConfigError] = useState(null); + const [systemPromptLoading, setSystemPromptLoading] = useState(false); + const [startersLoading, setStartersLoading] = useState(false); + const [initialSystemPrompt, setInitialSystemPrompt] = useState(''); + const [initialSuggestedQuestions, setInitialSuggestedQuestions] = useState< + string[] + >([]); + + useEffect(() => { + fetchConfig(); + }, [axiosInstance]); + + const fetchConfig = async () => { + setConfigLoading(true); + setConfigError(null); + try { + const [configResponse, systemPromptResponse] = await Promise.all([ + axiosInstance.get('/api/chat/config'), + axiosInstance.get('/api/admin/system-prompt'), + ]); + + const config = configResponse.data; + const systemPromptData = systemPromptResponse.data; + + setSystemPrompt(systemPromptData.system_prompt || ''); + setInitialSystemPrompt(systemPromptData.system_prompt || ''); + setSuggestedQuestions(config.starterQuestions || []); + setInitialSuggestedQuestions(config.starterQuestions || []); + setConfigLoading(false); + } catch (err: any) { + setConfigError(err.message || 'Failed to fetch configuration'); + setConfigLoading(false); + } + }; + + const updateSystemPrompt = async () => { + setSystemPromptLoading(true); + try { + const response = await axiosInstance.put('/api/admin/system-prompt', { + new_prompt: systemPrompt, + }); + if (response.status === 200) { + console.log('System prompt updated successfully'); + setInitialSystemPrompt(systemPrompt); + } + } catch (error) { + console.error('Failed to update system prompt:', error); + } finally { + setSystemPromptLoading(false); + } + }; + + const updateConversationStarters = async () => { + setStartersLoading(true); + try { + const newStarters = suggestedQuestions.filter((q) => q.trim() !== ''); + const response = await axiosInstance.put( + '/api/admin/conversation-starters', + { new_starters: newStarters } + ); + if (response.status === 200) { + console.log('Conversation starters updated successfully'); + setInitialSuggestedQuestions(newStarters); + } + } catch (error) { + console.error('Failed to update conversation starters:', error); + } finally { + setStartersLoading(false); + } + }; + + const addSuggestedQuestion = () => { + setSuggestedQuestions([...suggestedQuestions, '']); + }; + + const updateSuggestedQuestion = (index: number, value: string) => { + const updatedQuestions = [...suggestedQuestions]; + updatedQuestions[index] = value; + setSuggestedQuestions(updatedQuestions); + }; + + const deleteSuggestedQuestion = (index: number) => { + const updatedQuestions = suggestedQuestions.filter((_, i) => i !== index); + setSuggestedQuestions(updatedQuestions); + }; + + const isSystemPromptChanged = systemPrompt !== initialSystemPrompt; + const areSuggestedQuestionsChanged = + JSON.stringify(suggestedQuestions) !== + JSON.stringify(initialSuggestedQuestions); + + if (configLoading) return
Loading configuration...
; + if (configError) return
Error: {configError}
; + + return ( + + + RAG Configuration + + Configure Retrieval-Augmented Generation settings. + + + +
+ +