-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
modularized admin page - Adithya S K
- Loading branch information
1 parent
ccf3e1f
commit be0fabd
Showing
4 changed files
with
487 additions
and
448 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<File | null>(null); | ||
const [isUploading, setIsUploading] = useState(false); | ||
const [uploadResult, setUploadResult] = useState<string | null>(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 ( | ||
<Card> | ||
<CardHeader> | ||
<CardTitle>Data Ingestion</CardTitle> | ||
<CardDescription>Manage data ingestion processes.</CardDescription> | ||
</CardHeader> | ||
<CardContent> | ||
<div className="space-y-4"> | ||
<div className="w-full mx-auto min-h-96 border border-dashed bg-white dark:bg-black border-neutral-200 dark:border-neutral-800 rounded-lg"> | ||
<FileUpload onChange={handleFileUpload} /> | ||
</div> | ||
{file && ( | ||
<div className="flex items-center space-x-2"> | ||
<Button | ||
onClick={uploadFile} | ||
disabled={isUploading} | ||
variant="default" | ||
className="flex items-center w-full" | ||
> | ||
{isUploading ? ( | ||
<LoaderIcon className="mr-2 h-4 w-4 animate-spin" /> | ||
) : ( | ||
<Upload className="mr-2 h-4 w-4" /> | ||
)} | ||
{isUploading ? 'Uploading and Ingesting...' : 'Ingest File'} | ||
</Button> | ||
</div> | ||
)} | ||
{uploadResult && ( | ||
<div className="mt-2 text-sm text-gray-600 dark:text-gray-400"> | ||
{uploadResult} | ||
</div> | ||
)} | ||
<div> | ||
<Label htmlFor="ingestionStrategy"> | ||
Ingestion Strategy (Coming Soon) | ||
</Label> | ||
<Select disabled> | ||
<SelectTrigger> | ||
<SelectValue placeholder="Select a strategy" /> | ||
</SelectTrigger> | ||
<SelectContent> | ||
<SelectItem value="fixed">Fixed Size Chunking</SelectItem> | ||
<SelectItem value="semantic">Semantic Chunking</SelectItem> | ||
</SelectContent> | ||
</Select> | ||
</div> | ||
<div> | ||
<Label htmlFor="parser">Parser (Coming Soon)</Label> | ||
<Select disabled> | ||
<SelectTrigger> | ||
<SelectValue placeholder="Select a parser" /> | ||
</SelectTrigger> | ||
<SelectContent> | ||
<SelectItem value="llama">Llama Parse</SelectItem> | ||
<SelectItem value="omni">Omniparse</SelectItem> | ||
</SelectContent> | ||
</Select> | ||
</div> | ||
</div> | ||
</CardContent> | ||
</Card> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<string>(''); | ||
const [suggestedQuestions, setSuggestedQuestions] = useState<string[]>([]); | ||
const [configLoading, setConfigLoading] = useState<boolean>(true); | ||
const [configError, setConfigError] = useState<string | null>(null); | ||
const [systemPromptLoading, setSystemPromptLoading] = useState(false); | ||
const [startersLoading, setStartersLoading] = useState(false); | ||
const [initialSystemPrompt, setInitialSystemPrompt] = useState<string>(''); | ||
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 <div>Loading configuration...</div>; | ||
if (configError) return <div>Error: {configError}</div>; | ||
|
||
return ( | ||
<Card> | ||
<CardHeader> | ||
<CardTitle>RAG Configuration</CardTitle> | ||
<CardDescription> | ||
Configure Retrieval-Augmented Generation settings. | ||
</CardDescription> | ||
</CardHeader> | ||
<CardContent className="space-y-4"> | ||
<div> | ||
<Label htmlFor="systemPrompt">System Prompt</Label> | ||
<Textarea | ||
id="systemPrompt" | ||
value={systemPrompt} | ||
onChange={(e) => setSystemPrompt(e.target.value)} | ||
placeholder="Enter system prompt here..." | ||
/> | ||
<Button | ||
onClick={updateSystemPrompt} | ||
className="mt-2 w-full" | ||
variant={isSystemPromptChanged ? 'default' : 'secondary'} | ||
disabled={systemPromptLoading || !isSystemPromptChanged} | ||
> | ||
{systemPromptLoading ? 'Updating...' : 'Update System Prompt'} | ||
</Button> | ||
</div> | ||
<Separator /> | ||
<div> | ||
<Label>Suggested Questions</Label> | ||
{suggestedQuestions.map((question, index) => ( | ||
<div key={index} className="flex items-center space-x-2 mt-2"> | ||
<Input | ||
value={question} | ||
onChange={(e) => updateSuggestedQuestion(index, e.target.value)} | ||
placeholder="Enter a suggested question..." | ||
/> | ||
<Button | ||
variant="outline" | ||
size="icon" | ||
onClick={() => deleteSuggestedQuestion(index)} | ||
> | ||
<Trash2 className="h-4 w-4" /> | ||
</Button> | ||
</div> | ||
))} | ||
<div className="w-full flex justify-between items-center mt-2"> | ||
<Button | ||
variant="outline" | ||
className="mt-2" | ||
onClick={addSuggestedQuestion} | ||
> | ||
<PlusCircle className="h-4 w-4 mr-2" /> | ||
Add Question | ||
</Button> | ||
<Button | ||
variant={areSuggestedQuestionsChanged ? 'default' : 'secondary'} | ||
onClick={updateConversationStarters} | ||
className="mt-2 ml-2" | ||
disabled={startersLoading || !areSuggestedQuestionsChanged} | ||
> | ||
{startersLoading ? 'Updating...' : 'Update Conversation Starters'} | ||
</Button> | ||
</div> | ||
</div> | ||
</CardContent> | ||
</Card> | ||
); | ||
} |
Oops, something went wrong.