mirror of
https://github.com/infiniflow/ragflow.git
synced 2025-12-08 20:42:30 +08:00
### What problem does this PR solve? Feat: Add type card to create agent dialog #9869 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
@ -15,6 +15,7 @@ type RAGFlowFormItemProps = {
|
|||||||
tooltip?: ReactNode;
|
tooltip?: ReactNode;
|
||||||
children: ReactNode | ((field: ControllerRenderProps) => ReactNode);
|
children: ReactNode | ((field: ControllerRenderProps) => ReactNode);
|
||||||
horizontal?: boolean;
|
horizontal?: boolean;
|
||||||
|
required?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function RAGFlowFormItem({
|
export function RAGFlowFormItem({
|
||||||
@ -23,6 +24,7 @@ export function RAGFlowFormItem({
|
|||||||
tooltip,
|
tooltip,
|
||||||
children,
|
children,
|
||||||
horizontal = false,
|
horizontal = false,
|
||||||
|
required = false,
|
||||||
}: RAGFlowFormItemProps) {
|
}: RAGFlowFormItemProps) {
|
||||||
const form = useFormContext();
|
const form = useFormContext();
|
||||||
return (
|
return (
|
||||||
@ -35,7 +37,11 @@ export function RAGFlowFormItem({
|
|||||||
'flex items-center': horizontal,
|
'flex items-center': horizontal,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<FormLabel tooltip={tooltip} className={cn({ 'w-1/4': horizontal })}>
|
<FormLabel
|
||||||
|
required={required}
|
||||||
|
tooltip={tooltip}
|
||||||
|
className={cn({ 'w-1/4': horizontal })}
|
||||||
|
>
|
||||||
{label}
|
{label}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
|
|||||||
@ -38,7 +38,7 @@ const DialogContent = React.forwardRef<
|
|||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-colors-background-neutral-standard p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-xl translate-x-[-50%] translate-y-[-50%] gap-4 border bg-bg-base p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@ -934,7 +934,7 @@ This auto-tagging feature enhances retrieval by adding another layer of domain-s
|
|||||||
exceptionMethod: 'Exception method',
|
exceptionMethod: 'Exception method',
|
||||||
maxRounds: 'Max reflection rounds',
|
maxRounds: 'Max reflection rounds',
|
||||||
delayEfterError: 'Delay after error',
|
delayEfterError: 'Delay after error',
|
||||||
maxRetries: 'Max retries',
|
maxRetries: 'Max reflection rounds',
|
||||||
advancedSettings: 'Advanced Settings',
|
advancedSettings: 'Advanced Settings',
|
||||||
addTools: 'Add Tools',
|
addTools: 'Add Tools',
|
||||||
sysPromptDefultValue: `
|
sysPromptDefultValue: `
|
||||||
|
|||||||
@ -892,7 +892,7 @@ General:实体和关系提取提示来自 GitHub - microsoft/graphrag:基于
|
|||||||
exceptionMethod: '异常处理方法',
|
exceptionMethod: '异常处理方法',
|
||||||
maxRounds: '最大反思轮数',
|
maxRounds: '最大反思轮数',
|
||||||
delayEfterError: '错误后延迟',
|
delayEfterError: '错误后延迟',
|
||||||
maxRetries: '最大重试次数',
|
maxRetries: '最大反思轮数',
|
||||||
advancedSettings: '高级设置',
|
advancedSettings: '高级设置',
|
||||||
addTools: '添加工具',
|
addTools: '添加工具',
|
||||||
sysPromptDefultValue: `
|
sysPromptDefultValue: `
|
||||||
|
|||||||
@ -27,9 +27,11 @@ export default function AgentTemplates() {
|
|||||||
const [selectMenuItem, setSelectMenuItem] = useState<string>(
|
const [selectMenuItem, setSelectMenuItem] = useState<string>(
|
||||||
MenuItemKey.Recommended,
|
MenuItemKey.Recommended,
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTemplateList(list);
|
setTemplateList(list);
|
||||||
}, [list]);
|
}, [list]);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
visible: creatingVisible,
|
visible: creatingVisible,
|
||||||
hideModal: hideCreatingModal,
|
hideModal: hideCreatingModal,
|
||||||
|
|||||||
@ -6,16 +6,18 @@ import {
|
|||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
import { IModalProps } from '@/interfaces/common';
|
|
||||||
import { TagRenameId } from '@/pages/add-knowledge/constant';
|
import { TagRenameId } from '@/pages/add-knowledge/constant';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { CreateAgentForm } from './create-agent-form';
|
import { CreateAgentForm, CreateAgentFormProps } from './create-agent-form';
|
||||||
|
|
||||||
|
type CreateAgentDialogProps = CreateAgentFormProps;
|
||||||
|
|
||||||
export function CreateAgentDialog({
|
export function CreateAgentDialog({
|
||||||
hideModal,
|
hideModal,
|
||||||
onOk,
|
onOk,
|
||||||
loading,
|
loading,
|
||||||
}: IModalProps<any>) {
|
shouldChooseAgent,
|
||||||
|
}: CreateAgentDialogProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -24,7 +26,11 @@ export function CreateAgentDialog({
|
|||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>{t('flow.createGraph')}</DialogTitle>
|
<DialogTitle>{t('flow.createGraph')}</DialogTitle>
|
||||||
</DialogHeader>
|
</DialogHeader>
|
||||||
<CreateAgentForm hideModal={hideModal} onOk={onOk}></CreateAgentForm>
|
<CreateAgentForm
|
||||||
|
hideModal={hideModal}
|
||||||
|
onOk={onOk}
|
||||||
|
shouldChooseAgent={shouldChooseAgent}
|
||||||
|
></CreateAgentForm>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<ButtonLoading type="submit" form={TagRenameId} loading={loading}>
|
<ButtonLoading type="submit" form={TagRenameId} loading={loading}>
|
||||||
{t('common.save')}
|
{t('common.save')}
|
||||||
|
|||||||
@ -4,6 +4,8 @@ import { zodResolver } from '@hookform/resolvers/zod';
|
|||||||
import { useForm } from 'react-hook-form';
|
import { useForm } from 'react-hook-form';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
|
import { RAGFlowFormItem } from '@/components/ragflow-form';
|
||||||
|
import { Card, CardContent } from '@/components/ui/card';
|
||||||
import {
|
import {
|
||||||
Form,
|
Form,
|
||||||
FormControl,
|
FormControl,
|
||||||
@ -14,10 +16,76 @@ import {
|
|||||||
} from '@/components/ui/form';
|
} from '@/components/ui/form';
|
||||||
import { Input } from '@/components/ui/input';
|
import { Input } from '@/components/ui/input';
|
||||||
import { IModalProps } from '@/interfaces/common';
|
import { IModalProps } from '@/interfaces/common';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
import { TagRenameId } from '@/pages/add-knowledge/constant';
|
import { TagRenameId } from '@/pages/add-knowledge/constant';
|
||||||
|
import { BrainCircuit, Check, Route } from 'lucide-react';
|
||||||
|
import { useCallback } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
export function CreateAgentForm({ hideModal, onOk }: IModalProps<any>) {
|
export type CreateAgentFormProps = IModalProps<any> & {
|
||||||
|
shouldChooseAgent?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FlowType {
|
||||||
|
Agent = 'agent',
|
||||||
|
Flow = 'flow',
|
||||||
|
}
|
||||||
|
|
||||||
|
type FlowTypeCardProps = {
|
||||||
|
value?: FlowType;
|
||||||
|
onChange?: (value: FlowType) => void;
|
||||||
|
};
|
||||||
|
function FlowTypeCards({ value, onChange }: FlowTypeCardProps) {
|
||||||
|
const handleChange = useCallback(
|
||||||
|
(value: FlowType) => () => {
|
||||||
|
onChange?.(value);
|
||||||
|
},
|
||||||
|
[onChange],
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="flex gap-10">
|
||||||
|
{Object.values(FlowType).map((val) => {
|
||||||
|
const isActive = value === val;
|
||||||
|
return (
|
||||||
|
<Card
|
||||||
|
key={val}
|
||||||
|
className={cn('flex-1 rounded-lg border bg-transparent', {
|
||||||
|
'border-bg-base': isActive,
|
||||||
|
'border-border-default': !isActive,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<CardContent
|
||||||
|
onClick={handleChange(val)}
|
||||||
|
className={cn(
|
||||||
|
'cursor-pointer p-5 text-text-secondary flex justify-between items-center',
|
||||||
|
{
|
||||||
|
'text-text-primary': isActive,
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<div className="flex gap-2">
|
||||||
|
{val === FlowType.Agent ? (
|
||||||
|
<BrainCircuit className="size-6" />
|
||||||
|
) : (
|
||||||
|
<Route className="size-6" />
|
||||||
|
)}
|
||||||
|
<p>{val}</p>
|
||||||
|
</div>
|
||||||
|
{isActive && <Check />}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CreateAgentForm({
|
||||||
|
hideModal,
|
||||||
|
onOk,
|
||||||
|
shouldChooseAgent = false,
|
||||||
|
}: CreateAgentFormProps) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
name: z
|
name: z
|
||||||
@ -28,11 +96,12 @@ export function CreateAgentForm({ hideModal, onOk }: IModalProps<any>) {
|
|||||||
.trim(),
|
.trim(),
|
||||||
tag: z.string().trim().optional(),
|
tag: z.string().trim().optional(),
|
||||||
description: z.string().trim().optional(),
|
description: z.string().trim().optional(),
|
||||||
|
type: z.nativeEnum(FlowType).optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const form = useForm<z.infer<typeof FormSchema>>({
|
const form = useForm<z.infer<typeof FormSchema>>({
|
||||||
resolver: zodResolver(FormSchema),
|
resolver: zodResolver(FormSchema),
|
||||||
defaultValues: { name: '' },
|
defaultValues: { name: '', type: FlowType.Agent },
|
||||||
});
|
});
|
||||||
|
|
||||||
async function onSubmit(data: z.infer<typeof FormSchema>) {
|
async function onSubmit(data: z.infer<typeof FormSchema>) {
|
||||||
@ -49,12 +118,17 @@ export function CreateAgentForm({ hideModal, onOk }: IModalProps<any>) {
|
|||||||
className="space-y-6"
|
className="space-y-6"
|
||||||
id={TagRenameId}
|
id={TagRenameId}
|
||||||
>
|
>
|
||||||
|
{shouldChooseAgent && (
|
||||||
|
<RAGFlowFormItem required name="type" label={t('common.type')}>
|
||||||
|
<FlowTypeCards></FlowTypeCards>
|
||||||
|
</RAGFlowFormItem>
|
||||||
|
)}
|
||||||
<FormField
|
<FormField
|
||||||
control={form.control}
|
control={form.control}
|
||||||
name="name"
|
name="name"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<FormItem>
|
<FormItem>
|
||||||
<FormLabel>{t('common.name')}</FormLabel>
|
<FormLabel required>{t('common.name')}</FormLabel>
|
||||||
<FormControl>
|
<FormControl>
|
||||||
<Input
|
<Input
|
||||||
placeholder={t('common.namePlaceholder')}
|
placeholder={t('common.namePlaceholder')}
|
||||||
@ -66,40 +140,6 @@ export function CreateAgentForm({ hideModal, onOk }: IModalProps<any>) {
|
|||||||
</FormItem>
|
</FormItem>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
{/* <FormField
|
|
||||||
control={form.control}
|
|
||||||
name="tag"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>{t('flow.tag')}</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
placeholder={t('flow.tagPlaceholder')}
|
|
||||||
{...field}
|
|
||||||
autoComplete="off"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<FormField
|
|
||||||
control={form.control}
|
|
||||||
name="description"
|
|
||||||
render={({ field }) => (
|
|
||||||
<FormItem>
|
|
||||||
<FormLabel>{t('flow.description')}</FormLabel>
|
|
||||||
<FormControl>
|
|
||||||
<Input
|
|
||||||
placeholder={t('flow.descriptionPlaceholder')}
|
|
||||||
{...field}
|
|
||||||
autoComplete="off"
|
|
||||||
/>
|
|
||||||
</FormControl>
|
|
||||||
<FormMessage />
|
|
||||||
</FormItem>
|
|
||||||
)}
|
|
||||||
/> */}
|
|
||||||
</form>
|
</form>
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,14 +1,22 @@
|
|||||||
import ListFilterBar from '@/components/list-filter-bar';
|
import ListFilterBar from '@/components/list-filter-bar';
|
||||||
import { RenameDialog } from '@/components/rename-dialog';
|
import { RenameDialog } from '@/components/rename-dialog';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
|
import {
|
||||||
|
DropdownMenu,
|
||||||
|
DropdownMenuContent,
|
||||||
|
DropdownMenuItem,
|
||||||
|
DropdownMenuTrigger,
|
||||||
|
} from '@/components/ui/dropdown-menu';
|
||||||
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
import { RAGFlowPagination } from '@/components/ui/ragflow-pagination';
|
||||||
|
import { useSetModalState } from '@/hooks/common-hooks';
|
||||||
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
|
||||||
import { useFetchAgentListByPage } from '@/hooks/use-agent-request';
|
import { useFetchAgentListByPage } from '@/hooks/use-agent-request';
|
||||||
import { t } from 'i18next';
|
import { t } from 'i18next';
|
||||||
import { pick } from 'lodash';
|
import { pick } from 'lodash';
|
||||||
import { Plus } from 'lucide-react';
|
import { Clipboard, ClipboardPlus, FileInput, Plus } from 'lucide-react';
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { AgentCard } from './agent-card';
|
import { AgentCard } from './agent-card';
|
||||||
|
import { CreateAgentDialog } from './create-agent-dialog';
|
||||||
import { useRenameAgent } from './use-rename-agent';
|
import { useRenameAgent } from './use-rename-agent';
|
||||||
|
|
||||||
export default function Agents() {
|
export default function Agents() {
|
||||||
@ -25,6 +33,12 @@ export default function Agents() {
|
|||||||
showAgentRenameModal,
|
showAgentRenameModal,
|
||||||
} = useRenameAgent();
|
} = useRenameAgent();
|
||||||
|
|
||||||
|
const {
|
||||||
|
visible: creatingVisible,
|
||||||
|
hideModal: hideCreatingModal,
|
||||||
|
showModal: showCreatingModal,
|
||||||
|
} = useSetModalState();
|
||||||
|
|
||||||
const handlePageChange = useCallback(
|
const handlePageChange = useCallback(
|
||||||
(page: number, pageSize?: number) => {
|
(page: number, pageSize?: number) => {
|
||||||
setPagination({ page, pageSize });
|
setPagination({ page, pageSize });
|
||||||
@ -41,10 +55,34 @@ export default function Agents() {
|
|||||||
onSearchChange={handleInputChange}
|
onSearchChange={handleInputChange}
|
||||||
icon="agent"
|
icon="agent"
|
||||||
>
|
>
|
||||||
<Button onClick={navigateToAgentTemplates}>
|
<DropdownMenu>
|
||||||
<Plus className="mr-2 h-4 w-4" />
|
<DropdownMenuTrigger>
|
||||||
{t('flow.createGraph')}
|
<Button>
|
||||||
</Button>
|
<Plus className="mr-2 h-4 w-4" />
|
||||||
|
{t('flow.createGraph')}
|
||||||
|
</Button>
|
||||||
|
</DropdownMenuTrigger>
|
||||||
|
<DropdownMenuContent>
|
||||||
|
<DropdownMenuItem
|
||||||
|
justifyBetween={false}
|
||||||
|
onClick={showCreatingModal}
|
||||||
|
>
|
||||||
|
<Clipboard />
|
||||||
|
Create from Blank
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem
|
||||||
|
justifyBetween={false}
|
||||||
|
onClick={navigateToAgentTemplates}
|
||||||
|
>
|
||||||
|
<ClipboardPlus />
|
||||||
|
Create from Template
|
||||||
|
</DropdownMenuItem>
|
||||||
|
<DropdownMenuItem justifyBetween={false}>
|
||||||
|
<FileInput />
|
||||||
|
Import json file
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</DropdownMenuContent>
|
||||||
|
</DropdownMenu>
|
||||||
</ListFilterBar>
|
</ListFilterBar>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 overflow-auto">
|
<div className="flex-1 overflow-auto">
|
||||||
@ -75,6 +113,15 @@ export default function Agents() {
|
|||||||
loading={agentRenameLoading}
|
loading={agentRenameLoading}
|
||||||
></RenameDialog>
|
></RenameDialog>
|
||||||
)}
|
)}
|
||||||
|
{creatingVisible && (
|
||||||
|
<CreateAgentDialog
|
||||||
|
loading={false}
|
||||||
|
visible={creatingVisible}
|
||||||
|
hideModal={hideCreatingModal}
|
||||||
|
shouldChooseAgent
|
||||||
|
onOk={() => {}}
|
||||||
|
></CreateAgentDialog>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user