Skip to content

Commit

Permalink
feat(frontend): support edit chat engine knowledge graph options
Browse files Browse the repository at this point in the history
  • Loading branch information
634750802 committed Jul 25, 2024
1 parent eb9ac3d commit 741e842
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 22 deletions.
14 changes: 8 additions & 6 deletions frontend/app/src/api/chat-engines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export interface ChatEngineKnowledgeGraphOptions {
enabled: boolean;
include_meta: boolean;
with_degree: boolean;
using_intent_search: boolean;
}

export type ChatEngineLLMOptions = {
Expand All @@ -34,16 +35,17 @@ export type ChatEngineLLMOptions = {
intent_graph_knowledge: string
normal_graph_knowledge: string

provider: string;
reranker_provider: string;
reranker_top_k: number;
// provider: string;
// reranker_provider: string;
// reranker_top_k: number;
} & Record<`${string}_chat_model`, string | undefined>

const kgOptionsSchema = z.object({
depth: z.number(),
enabled: z.boolean(),
include_meta: z.boolean(),
with_degree: z.boolean(),
using_intent_search: z.boolean(),
}) satisfies ZodType<ChatEngineKnowledgeGraphOptions>;

const llmOptionsSchema =
Expand All @@ -53,9 +55,9 @@ const llmOptionsSchema =
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(),
// provider: z.string(),
// reranker_provider: z.string(),
// reranker_top_k: z.number(),
}).passthrough() as ZodType<ChatEngineLLMOptions, any, any>;

const chatEngineOptionsSchema = z.object({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { getChatEngine } from '@/api/chat-engines';
import { AdminPageHeading } from '@/components/admin-page-heading';
import { ChatEngineDetails } from '@/components/chat-engine/chat-engine-details';
import { Card, CardContent, CardTitle } from '@/components/ui/card';
import { Card, CardContent } from '@/components/ui/card';
import { requireAuth } from '@/lib/auth';

export default async function ChatEnginePage ({ params }: { params: { id: string } }) {
Expand All @@ -14,7 +14,7 @@ export default async function ChatEnginePage ({ params }: { params: { id: string
<AdminPageHeading title={`Chat Engine - ${chatEngine.name}`} />
<div className="xl:pr-side max-w-screen-lg">
<Card>
<CardContent className='pt-4'>
<CardContent className="pt-4">
<ChatEngineDetails chatEngine={chatEngine} />
</CardContent>
</Card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function ChatEngineOptionsDetails ({
<section className="space-y-2">
<div className="text-base font-medium">Knowledge Graph</div>
<div className="space-y-2 text-sm">
<ChatEngineKnowledgeGraphDetails detailed={detailed} options={options.knowledge_graph} />
<ChatEngineKnowledgeGraphDetails detailed={detailed} editable={editable} options={options.knowledge_graph} />
</div>
</section>
<Separator />
Expand Down
110 changes: 110 additions & 0 deletions frontend/app/src/components/chat-engine/edit-boolean-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
'use client';

import { type ChatEngine, type ChatEngineOptions, 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, FormMessage } from '@/components/ui/form';
import { Switch } from '@/components/ui/switch';
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({
enabled: z.boolean(),
});

type BooleanOptionConfig = {
name: string
get: (options: ChatEngineOptions) => boolean
set: (options: ChatEngineOptions, newValue: boolean) => void
}

const config = {
'kg.enabled': {
name: 'Enable KnowledgeGraph',
get: opt => opt.knowledge_graph.enabled,
set: (opt, nv) => opt.knowledge_graph.enabled = nv,
},
'kg.include_meta': {
name: 'KnowledgeGraph Include Meta',
get: opt => opt.knowledge_graph.include_meta,
set: (opt, nv) => opt.knowledge_graph.include_meta = nv,
},
'kg.with_degree': {
name: 'KnowledgeGraph With Degree',
get: opt => opt.knowledge_graph.with_degree,
set: (opt, nv) => opt.knowledge_graph.with_degree = nv,
},
'kg.using_intent_search': {
name: 'KnowledgeGraph Using Intent Search',
get: opt => opt.knowledge_graph.using_intent_search,
set: (opt, nv) => opt.knowledge_graph.using_intent_search = nv,
},
} satisfies Record<string, BooleanOptionConfig>;

export interface EditBooleanFormProps {
chatEngine: ChatEngine;
type: keyof typeof config;
}

export function EditBooleanForm ({ type, chatEngine }: EditBooleanFormProps) {
const router = useRouter();
const [transitioning, startTransition] = useTransition();
const { setOpen } = useManagedDialog();
const { name, get, set } = config[type];

const form = useForm<{ enabled: boolean }>({
resolver: zodResolver(schema),
defaultValues: {
enabled: get(chatEngine.engine_options),
},
});

const handleSubmit = form.handleSubmit(async (data) => {
const options: ChatEngineOptions = {
knowledge_graph: { ...chatEngine.engine_options.knowledge_graph },
llm: { ...chatEngine.engine_options.llm },
};
set(options, data.enabled);
await updateChatEngine(chatEngine.id, { engine_options: options });
startTransition(() => {
router.refresh();
});
toast(`ChatEngine's ${name} successfully updated.`);
setOpen(false);
});

return (
<>
<DialogHeader>
<DialogTitle>{name}</DialogTitle>
</DialogHeader>
<Form {...form}>
<form id="update-form" className="space-y-4" onSubmit={handleSubmit}>
<FormField
name="enabled"
render={({ field }) => (
<FormItem>
<FormControl>
<FormControl>
<Switch name={field.name} onBlur={field.onBlur} checked={field.value} onCheckedChange={field.onChange} disabled={field.disabled} />
</FormControl>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
<DialogFooter>
<Button type="submit" form="update-form" disabled={form.formState.disabled || form.formState.isSubmitting || transitioning}>
Update
</Button>
</DialogFooter>
</>
);
}
113 changes: 113 additions & 0 deletions frontend/app/src/components/chat-engine/edit-integer-form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
'use client';

import { type ChatEngine, type ChatEngineOptions, 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, FormMessage } from '@/components/ui/form';
import { Slider } from '@/components/ui/slider';
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({
value: z.coerce.number().int(),
});

type BooleanOptionConfig = {
name: string
get: (options: ChatEngineOptions) => number
set: (options: ChatEngineOptions, newValue: number) => void
min: number
max: number
}

const config = {
'kg.depth': {
name: 'KnowledgeGraph Depth',
get: opt => opt.knowledge_graph.depth,
set: (opt, nv) => opt.knowledge_graph.depth = nv,
min: 0,
max: 20,
},
} satisfies Record<string, BooleanOptionConfig>;

export interface EditIntFormProps {
chatEngine: ChatEngine;
type: keyof typeof config;
}

export function EditIntForm ({ type, chatEngine }: EditIntFormProps) {
const router = useRouter();
const [transitioning, startTransition] = useTransition();
const { setOpen } = useManagedDialog();
const { name, min, max, get, set } = config[type];

const form = useForm<{ value: number }>({
resolver: zodResolver(schema),
defaultValues: {
value: get(chatEngine.engine_options),
},
});

const handleSubmit = form.handleSubmit(async (data) => {
const options: ChatEngineOptions = {
knowledge_graph: { ...chatEngine.engine_options.knowledge_graph },
llm: { ...chatEngine.engine_options.llm },
};
set(options, data.value);
await updateChatEngine(chatEngine.id, { engine_options: options });
startTransition(() => {
router.refresh();
});
toast(`ChatEngine's ${name} successfully updated.`);
setOpen(false);
});

return (
<>
<DialogHeader>
<DialogTitle>{name}</DialogTitle>
</DialogHeader>
<Form {...form}>
<form id="update-form" className="space-y-4" onSubmit={handleSubmit}>
<FormField
name="value"
render={({ field }) => (
<FormItem>
<FormControl>
<FormControl>
<div className='flex gap-2 items-center'>
<Slider
min={min}
max={max}
step={1}
name={field.name}
onBlur={field.onBlur}
value={[field.value]}
onValueChange={([value]) => field.onChange(value)}
disabled={field.disabled}
/>
<span className='block flex-shrink-0 w-20 text-right font-mono'>
{field.value}
</span>
</div>
</FormControl>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
</form>
</Form>
<DialogFooter>
<Button type="submit" form="update-form" disabled={form.formState.disabled || form.formState.isSubmitting || transitioning}>
Update
</Button>
</DialogFooter>
</>
);
}
2 changes: 1 addition & 1 deletion frontend/app/src/components/chat-engine/edit-name-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function EditNameForm ({ chatEngine }: EditNameFormProps) {
</form>
</Form>
<DialogFooter>
<Button type="submit" form='update-form' disabled={form.formState.disabled || form.formState.isSubmitting || transitioning}>
<Button type="submit" form="update-form" disabled={form.formState.disabled || form.formState.isSubmitting || transitioning}>
Update
</Button>
</DialogFooter>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ 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';
Expand Down Expand Up @@ -68,7 +67,7 @@ export function EditOptionsLlmPromptForm ({ chatEngine, type }: EditOptionsLlmPr
<FormItem>
<FormLabel>{type}</FormLabel>
<FormControl>
<Textarea className='min-h-[50vh]' {...field} />
<Textarea className="min-h-[50vh]" {...field} />
</FormControl>
<FormMessage />
</FormItem>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
import type { ChatEngineKnowledgeGraphOptions } from '@/api/chat-engines';
import type { ChatEngine, ChatEngineKnowledgeGraphOptions } from '@/api/chat-engines';
import { EditBooleanForm } from '@/components/chat-engine/edit-boolean-form';
import { EditIntForm } from '@/components/chat-engine/edit-integer-form';
import { OptionDetail } from '@/components/option-detail';

export function ChatEngineKnowledgeGraphDetails ({ detailed, options }: { detailed: boolean, options: ChatEngineKnowledgeGraphOptions }) {
export function ChatEngineKnowledgeGraphDetails ({ detailed, editable, options }: { detailed: boolean, editable?: ChatEngine, options: ChatEngineKnowledgeGraphOptions }) {
return (
<div className="space-y-2 text-sm">
<OptionDetail title="Status" value={options.enabled ? 'Enabled' : 'Disabled'} valueClassName={options.enabled ? 'text-green-500' : 'text-muted-foreground'} />
<OptionDetail title="Status" value={options.enabled ? 'Enabled' : 'Disabled'} valueClassName={options.enabled ? 'text-green-500' : 'text-muted-foreground'} editPanel={editable && <EditBooleanForm chatEngine={editable} type="kg.enabled" />} />
{(detailed || options.enabled) && (
<>
<OptionDetail title="Depth" value={options.depth} />
<OptionDetail title="With Degree" value={options.with_degree ? 'Yes' : 'No'} />
<OptionDetail title="Include Meta" value={options.include_meta ? 'Yes' : 'No'} />
<OptionDetail title="Depth" value={options.depth} editPanel={editable && <EditIntForm chatEngine={editable} type="kg.depth" />} />
<OptionDetail title="With Degree" value={options.with_degree ? 'Yes' : 'No'} valueClassName={options.with_degree ? 'text-green-500' : 'text-muted-foreground'} editPanel={editable && <EditBooleanForm chatEngine={editable} type="kg.with_degree" />} />
<OptionDetail title="Include Meta" value={options.include_meta ? 'Yes' : 'No'} valueClassName={options.include_meta ? 'text-green-500' : 'text-muted-foreground'} editPanel={editable && <EditBooleanForm chatEngine={editable} type="kg.include_meta" />} />
<OptionDetail title="Using Intent Search" value={options.using_intent_search ? 'Yes' : 'No'} valueClassName={options.using_intent_search ? 'text-green-500' : 'text-muted-foreground'} editPanel={editable && <EditBooleanForm chatEngine={editable} type="kg.using_intent_search" />} />
</>
)}
</div>
Expand Down
4 changes: 0 additions & 4 deletions frontend/app/src/components/chat-engine/llm-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ import { ScrollArea } from '@/components/ui/scroll-area';
export function ChatEngineLLMDetails ({ editable, options }: { editable?: ChatEngine, options: ChatEngineLLMOptions }) {
return (
<div className="space-y-2 text-sm">
<OptionDetail title="Provider" value={options.provider} />
<OptionDetail title="Model" value={options[`${options.provider}_chat_model` as never]} />
<OptionDetail title="Reranker Provider" value={options.reranker_provider} />
<OptionDetail title="Reranker Top K" value={options.reranker_top_k} />
{options.condense_question_prompt && <OptionDetail title="Condense question prompt" value={<PromptPreviewDialog title="Condense question prompt" value={options.condense_question_prompt} />} editPanel={editable && <EditOptionsLlmPromptForm chatEngine={editable} type="condense_question_prompt" />} />}
{options.refine_prompt && <OptionDetail title="Refine prompt" value={<PromptPreviewDialog title="Refine prompt" value={options.refine_prompt} />} editPanel={editable && <EditOptionsLlmPromptForm chatEngine={editable} type="refine_prompt" />} />}
{options.text_qa_prompt && <OptionDetail title="Text QA prompt" value={<PromptPreviewDialog title="Text QA prompt" value={options.text_qa_prompt} />} editPanel={editable && <EditOptionsLlmPromptForm chatEngine={editable} type="text_qa_prompt" />} />}
Expand Down

0 comments on commit 741e842

Please sign in to comment.