mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-17 19:22:55 +08:00
### What problem does this PR solve? Feat: Add LangfuseCard component. #6155 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -1,7 +1,3 @@
|
||||
.modelWrapper {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.modelContainer {
|
||||
width: 100%;
|
||||
.factoryOperationWrapper {
|
||||
|
||||
@ -49,6 +49,7 @@ import {
|
||||
} from './hooks';
|
||||
import HunyuanModal from './hunyuan-modal';
|
||||
import styles from './index.less';
|
||||
import { LangfuseCard } from './langfuse';
|
||||
import OllamaModal from './ollama-modal';
|
||||
import SparkModal from './spark-modal';
|
||||
import SystemModelSettingModal from './system-model-setting-modal';
|
||||
@ -358,7 +359,8 @@ const UserSettingModel = () => {
|
||||
];
|
||||
|
||||
return (
|
||||
<section id="xx" className={styles.modelWrapper}>
|
||||
<section id="xx" className="w-full space-y-6">
|
||||
<LangfuseCard></LangfuseCard>
|
||||
<Spin spinning={loading}>
|
||||
<section className={styles.modelContainer}>
|
||||
<SettingTitle
|
||||
|
||||
69
web/src/pages/user-setting/setting-model/langfuse/index.tsx
Normal file
69
web/src/pages/user-setting/setting-model/langfuse/index.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import SvgIcon from '@/components/svg-icon';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Card,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card';
|
||||
import { useFetchLangfuseConfig } from '@/hooks/user-setting-hooks';
|
||||
import { Eye, Settings2 } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LangfuseConfigurationDialog } from './langfuse-configuration-dialog';
|
||||
import { useSaveLangfuseConfiguration } from './use-save-langfuse-configuration';
|
||||
|
||||
export function LangfuseCard() {
|
||||
const {
|
||||
saveLangfuseConfigurationOk,
|
||||
showSaveLangfuseConfigurationModal,
|
||||
hideSaveLangfuseConfigurationModal,
|
||||
saveLangfuseConfigurationVisible,
|
||||
loading,
|
||||
} = useSaveLangfuseConfiguration();
|
||||
const { t } = useTranslation();
|
||||
const { data } = useFetchLangfuseConfig();
|
||||
|
||||
const handleView = useCallback(() => {
|
||||
window.open(
|
||||
`https://cloud.langfuse.com/project/${data?.project_id}`,
|
||||
'_blank',
|
||||
);
|
||||
}, [data?.project_id]);
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex justify-between">
|
||||
<div className="flex items-center gap-4">
|
||||
<SvgIcon name={'langfuse'} width={24} height={24}></SvgIcon>
|
||||
Langfuse
|
||||
</div>
|
||||
<div className="flex gap-4 items-center">
|
||||
{data && (
|
||||
<Button variant={'outline'} size={'sm'} onClick={handleView}>
|
||||
<Eye /> {t('setting.view')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
size={'sm'}
|
||||
onClick={showSaveLangfuseConfigurationModal}
|
||||
className="bg-blue-500 hover:bg-blue-400"
|
||||
>
|
||||
<Settings2 />
|
||||
{t('setting.configuration')}
|
||||
</Button>
|
||||
</div>
|
||||
</CardTitle>
|
||||
<CardDescription>{t('setting.langfuseDescription')}</CardDescription>
|
||||
</CardHeader>
|
||||
{saveLangfuseConfigurationVisible && (
|
||||
<LangfuseConfigurationDialog
|
||||
hideModal={hideSaveLangfuseConfigurationModal}
|
||||
onOk={saveLangfuseConfigurationOk}
|
||||
loading={loading}
|
||||
></LangfuseConfigurationDialog>
|
||||
)}
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from '@/components/ui/dialog';
|
||||
import { LoadingButton } from '@/components/ui/loading-button';
|
||||
import { useDeleteLangfuseConfig } from '@/hooks/user-setting-hooks';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { ExternalLink, Trash2 } from 'lucide-react';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
FormId,
|
||||
LangfuseConfigurationForm,
|
||||
} from './langfuse-configuration-form';
|
||||
|
||||
export function LangfuseConfigurationDialog({
|
||||
hideModal,
|
||||
loading,
|
||||
onOk,
|
||||
}: IModalProps<any>) {
|
||||
const { t } = useTranslation();
|
||||
const { deleteLangfuseConfig } = useDeleteLangfuseConfig();
|
||||
|
||||
const handleDelete = useCallback(async () => {
|
||||
const ret = await deleteLangfuseConfig();
|
||||
if (ret === 0) {
|
||||
hideModal?.();
|
||||
}
|
||||
}, [deleteLangfuseConfig, hideModal]);
|
||||
|
||||
return (
|
||||
<Dialog open onOpenChange={hideModal}>
|
||||
<DialogTrigger asChild>
|
||||
<Button variant="outline"></Button>
|
||||
</DialogTrigger>
|
||||
<DialogContent>
|
||||
<DialogHeader>
|
||||
<DialogTitle>{t('setting.configuration')} Langfuse</DialogTitle>
|
||||
</DialogHeader>
|
||||
<LangfuseConfigurationForm onOk={onOk}></LangfuseConfigurationForm>
|
||||
<DialogFooter className="!justify-between">
|
||||
<a
|
||||
href="https://langfuse.com/docs"
|
||||
className="flex items-center gap-2 underline text-blue-600 hover:text-blue-800 visited:text-purple-600"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
{t('setting.viewLangfuseSDocumentation')}
|
||||
<ExternalLink className="size-4" />
|
||||
</a>
|
||||
<div className="flex items-center gap-4">
|
||||
<ConfirmDeleteDialog onOk={handleDelete}>
|
||||
<Button variant={'outline'}>
|
||||
<Trash2 className="text-red-500" /> {t('common.delete')}
|
||||
</Button>
|
||||
</ConfirmDeleteDialog>
|
||||
|
||||
<LoadingButton type="submit" form={FormId} loading={loading}>
|
||||
{t('common.save')}
|
||||
</LoadingButton>
|
||||
</div>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
'use client';
|
||||
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { useFetchLangfuseConfig } from '@/hooks/user-setting-hooks';
|
||||
import { IModalProps } from '@/interfaces/common';
|
||||
import { useEffect } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const FormId = 'LangfuseConfigurationForm';
|
||||
|
||||
export function LangfuseConfigurationForm({ onOk }: IModalProps<any>) {
|
||||
const { t } = useTranslation();
|
||||
const { data } = useFetchLangfuseConfig();
|
||||
|
||||
const FormSchema = z.object({
|
||||
secret_key: z
|
||||
.string()
|
||||
.min(1, {
|
||||
message: t('setting.secretKeyMessage'),
|
||||
})
|
||||
.trim(),
|
||||
public_key: z
|
||||
.string()
|
||||
.min(1, {
|
||||
message: t('setting.publicKeyMessage'),
|
||||
})
|
||||
.trim(),
|
||||
host: z
|
||||
.string()
|
||||
.min(0, {
|
||||
message: t('setting.hostMessage'),
|
||||
})
|
||||
.trim(),
|
||||
});
|
||||
|
||||
const form = useForm<z.infer<typeof FormSchema>>({
|
||||
resolver: zodResolver(FormSchema),
|
||||
defaultValues: {},
|
||||
});
|
||||
|
||||
async function onSubmit(data: z.infer<typeof FormSchema>) {
|
||||
onOk?.(data);
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (data) {
|
||||
form.reset(data);
|
||||
}
|
||||
}, [data, form]);
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form
|
||||
onSubmit={form.handleSubmit(onSubmit)}
|
||||
className="space-y-6"
|
||||
id={FormId}
|
||||
>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="secret_key"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('setting.secretKey')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type={'password'}
|
||||
placeholder={t('setting.secretKeyMessage')}
|
||||
{...field}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="public_key"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('setting.publicKey')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
type={'password'}
|
||||
placeholder={t('setting.publicKeyMessage')}
|
||||
{...field}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="host"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>Host</FormLabel>
|
||||
<FormControl>
|
||||
<Input
|
||||
placeholder={'https://cloud.langfuse.com'}
|
||||
{...field}
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
import { useSetModalState } from '@/hooks/common-hooks';
|
||||
import { useSetLangfuseConfig } from '@/hooks/user-setting-hooks';
|
||||
import { ISetLangfuseConfigRequestBody } from '@/interfaces/request/system';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export const useSaveLangfuseConfiguration = () => {
|
||||
const {
|
||||
visible: saveLangfuseConfigurationVisible,
|
||||
hideModal: hideSaveLangfuseConfigurationModal,
|
||||
showModal: showSaveLangfuseConfigurationModal,
|
||||
} = useSetModalState();
|
||||
const { setLangfuseConfig, loading } = useSetLangfuseConfig();
|
||||
|
||||
const onSaveLangfuseConfigurationOk = useCallback(
|
||||
async (params: ISetLangfuseConfigRequestBody) => {
|
||||
const ret = await setLangfuseConfig(params);
|
||||
|
||||
if (ret === 0) {
|
||||
hideSaveLangfuseConfigurationModal();
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
[hideSaveLangfuseConfigurationModal],
|
||||
);
|
||||
|
||||
return {
|
||||
loading,
|
||||
saveLangfuseConfigurationOk: onSaveLangfuseConfigurationOk,
|
||||
saveLangfuseConfigurationVisible,
|
||||
hideSaveLangfuseConfigurationModal,
|
||||
showSaveLangfuseConfigurationModal,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user