diff --git a/frontend/app/src/api/chat-engines.ts b/frontend/app/src/api/chat-engines.ts index 86997cb4..e1724750 100644 --- a/frontend/app/src/api/chat-engines.ts +++ b/frontend/app/src/api/chat-engines.ts @@ -31,6 +31,9 @@ export type ChatEngineLLMOptions = { text_qa_prompt: string; refine_prompt: string; + intent_graph_knowledge: string + normal_graph_knowledge: string + provider: string; reranker_provider: string; reranker_top_k: number; @@ -48,6 +51,8 @@ const llmOptionsSchema = condense_question_prompt: z.string(), text_qa_prompt: z.string(), refine_prompt: z.string(), + intent_graph_knowledge: z.string(), + normal_graph_knowledge: z.string(), provider: z.string(), reranker_provider: z.string(), reranker_top_k: z.number(), @@ -95,3 +100,26 @@ export async function updateChatEngine (id: number, partial: Partial) { + return await fetch(BASE_URL + `/api/v1/admin/chat-engines`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...await opaqueCookieHeader(), + }, + body: JSON.stringify(create), + }) + .then(handleResponse(chatEngineSchema)); +} + + +export async function deleteChatEngine (id: number): Promise { + await fetch(BASE_URL + `/api/v1/admin/chat-engines/${id}`, { + method: 'DELETE', + headers: { + ...await opaqueCookieHeader(), + }, + }) + .then(handleErrors); +} diff --git a/frontend/app/src/app/(main)/(admin)/chat-engines/page.tsx b/frontend/app/src/app/(main)/(admin)/chat-engines/page.tsx index 5b28bf38..01ae174a 100644 --- a/frontend/app/src/app/(main)/(admin)/chat-engines/page.tsx +++ b/frontend/app/src/app/(main)/(admin)/chat-engines/page.tsx @@ -1,12 +1,19 @@ 'use client'; -import { type ChatEngine, listChatEngines } from '@/api/chat-engines'; +import { type ChatEngine, createChatEngine, deleteChatEngine, listChatEngines } from '@/api/chat-engines'; import { AdminPageHeading } from '@/components/admin-page-heading'; import { datetime } from '@/components/cells/datetime'; +import { DangerousActionButton } from '@/components/dangerous-action-button'; import { DataTableRemote } from '@/components/data-table-remote'; +import { Button } from '@/components/ui/button'; +import { useDataTable } from '@/components/use-data-table'; import type { CellContext, ColumnDef } from '@tanstack/react-table'; import { createColumnHelper } from '@tanstack/table-core'; +import { CopyIcon, TrashIcon } from 'lucide-react'; import Link from 'next/link'; +import { useRouter } from 'next/navigation'; +import { useState, useTransition } from 'react'; +import { toast } from 'sonner'; const helper = createColumnHelper(); @@ -18,6 +25,15 @@ const columns = [ helper.accessor('created_at', { cell: datetime }), helper.accessor('updated_at', { cell: datetime }), helper.accessor('is_default', { cell: (ctx) => ctx.getValue() ? 'Yes' : '' }), + helper.display({ + header: 'Actions', + cell: ({ row }) => ( + + + + + ), + }), // { // id: 'actions', // cell: ({ row }) => , @@ -44,3 +60,52 @@ export default function ChatEnginesPage () { ); } +function CloneButton ({ chatEngine }: { chatEngine: ChatEngine }) { + const [cloning, setCloning] = useState(false); + const [transitioning, startTransition] = useTransition(); + const router = useRouter(); + + return ( + + ); +} + +function DeleteButton ({ chatEngine }: { chatEngine: ChatEngine }) { + const { reload } = useDataTable(); + + return ( + { + await deleteChatEngine(chatEngine.id); + reload?.(); + }} + variant="ghost" + className="text-xs text-destructive hover:text-destructive hover:bg-destructive/20" + > + + Delete + + ); +} diff --git a/frontend/app/src/components/chat-engine/chat-engine-details.tsx b/frontend/app/src/components/chat-engine/chat-engine-details.tsx index 818513cf..b974f1da 100644 --- a/frontend/app/src/components/chat-engine/chat-engine-details.tsx +++ b/frontend/app/src/components/chat-engine/chat-engine-details.tsx @@ -21,7 +21,7 @@ export function ChatEngineDetails ({ chatEngine }: { chatEngine: ChatEngine }) { } /> - + ); } diff --git a/frontend/app/src/components/chat-engine/chat-engine-options-details.tsx b/frontend/app/src/components/chat-engine/chat-engine-options-details.tsx index 1fee7e38..9125a4a3 100644 --- a/frontend/app/src/components/chat-engine/chat-engine-options-details.tsx +++ b/frontend/app/src/components/chat-engine/chat-engine-options-details.tsx @@ -1,9 +1,17 @@ -import type { ChatEngineOptions } from '@/api/chat-engines'; +import type { ChatEngine, ChatEngineOptions } from '@/api/chat-engines'; import { ChatEngineKnowledgeGraphDetails } from '@/components/chat-engine/knowledge-graph-details'; import { ChatEngineLLMDetails } from '@/components/chat-engine/llm-details'; import { Separator } from '@/components/ui/separator'; -export function ChatEngineOptionsDetails ({ detailed = true, options }: { detailed?: boolean, options: ChatEngineOptions }) { +export function ChatEngineOptionsDetails ({ + detailed = true, + editable, + options, +}: { + detailed?: boolean + editable?: ChatEngine + options: ChatEngineOptions +}) { return ( <>
@@ -16,7 +24,7 @@ export function ChatEngineOptionsDetails ({ detailed = true, options }: { detail
LLM
- +
diff --git a/frontend/app/src/components/chat-engine/edit-options-llm-prompt-form.tsx b/frontend/app/src/components/chat-engine/edit-options-llm-prompt-form.tsx new file mode 100644 index 00000000..d5bc87fc --- /dev/null +++ b/frontend/app/src/components/chat-engine/edit-options-llm-prompt-form.tsx @@ -0,0 +1,86 @@ +'use client'; + +import { type ChatEngine, updateChatEngine } from '@/api/chat-engines'; +import { useManagedDialog } from '@/components/managed-dialog'; +import { Button } from '@/components/ui/button'; +import { DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'; +import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form'; +import { Input } from '@/components/ui/input'; +import { Textarea } from '@/components/ui/textarea'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { useRouter } from 'next/navigation'; +import { useTransition } from 'react'; +import { useForm } from 'react-hook-form'; +import { toast } from 'sonner'; +import { z } from 'zod'; + +const schema = z.object({ + prompt: z.string().min(1), +}); + +export interface EditOptionsLlmPromptFormProps { + chatEngine: ChatEngine; + type: 'intent_graph_knowledge' + | 'normal_graph_knowledge' + | 'condense_question_prompt' + | 'refine_prompt' + | 'text_qa_prompt'; +} + +export function EditOptionsLlmPromptForm ({ chatEngine, type }: EditOptionsLlmPromptFormProps) { + const router = useRouter(); + const [transitioning, startTransition] = useTransition(); + const { setOpen } = useManagedDialog(); + + const form = useForm<{ prompt: string }>({ + resolver: zodResolver(schema), + defaultValues: { + prompt: chatEngine.engine_options.llm[type], + }, + }); + + const handleSubmit = form.handleSubmit(async (data) => { + const chatEngineOptions = { + ...chatEngine.engine_options, + llm: { + ...chatEngine.engine_options.llm, + [type]: data.prompt, + }, + }; + await updateChatEngine(chatEngine.id, { engine_options: chatEngineOptions }); + startTransition(() => { + router.refresh(); + }); + toast(`ChatEngine's ${type} successfully updated.`); + setOpen(false); + }); + + return ( + <> + + Update chat engine's {type} + +
+ + ( + + {type} + +