diff --git a/web/src/components/large-model-form-field.tsx b/web/src/components/large-model-form-field.tsx
index f6b2a4314..58d58f385 100644
--- a/web/src/components/large-model-form-field.tsx
+++ b/web/src/components/large-model-form-field.tsx
@@ -7,7 +7,7 @@ import {
} from '@/components/ui/form';
import { useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
-import { NextLLMSelect } from './llm-select';
+import { NextLLMSelect } from './llm-select/next';
export function LargeModelFormField() {
const form = useFormContext();
diff --git a/web/src/components/llm-select/index.tsx b/web/src/components/llm-select/index.tsx
index fc31f3a6c..fa65b95c3 100644
--- a/web/src/components/llm-select/index.tsx
+++ b/web/src/components/llm-select/index.tsx
@@ -1,12 +1,7 @@
import { LlmModelType } from '@/constants/knowledge';
import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks';
-import * as SelectPrimitive from '@radix-ui/react-select';
import { Popover as AntPopover, Select as AntSelect } from 'antd';
-import { forwardRef, useState } from 'react';
import LlmSettingItems from '../llm-setting-items';
-import { LlmSettingFieldItems } from '../llm-setting-items/next';
-import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
-import { Select, SelectTrigger, SelectValue } from '../ui/select';
interface IProps {
id?: string;
@@ -16,7 +11,13 @@ interface IProps {
disabled?: boolean;
}
-const LLMSelect = ({ id, value, onInitialValue, onChange, disabled }: IProps) => {
+const LLMSelect = ({
+ id,
+ value,
+ onInitialValue,
+ onChange,
+ disabled,
+}: IProps) => {
const modelOptions = useComposeLlmOptionsByModelTypes([
LlmModelType.Chat,
LlmModelType.Image2text,
@@ -31,11 +32,12 @@ const LLMSelect = ({ id, value, onInitialValue, onChange, disabled }: IProps) =>
}
}
}
- }
+ }
const content = (
-
@@ -63,43 +65,3 @@ const LLMSelect = ({ id, value, onInitialValue, onChange, disabled }: IProps) =>
};
export default LLMSelect;
-
-export const NextLLMSelect = forwardRef<
- React.ElementRef,
- IProps
->(({ value, disabled }, ref) => {
- const [isPopoverOpen, setIsPopoverOpen] = useState(false);
- const modelOptions = useComposeLlmOptionsByModelTypes([
- LlmModelType.Chat,
- LlmModelType.Image2text,
- ]);
-
- return (
-
- );
-});
-
-NextLLMSelect.displayName = 'LLMSelect';
diff --git a/web/src/components/llm-select/next.tsx b/web/src/components/llm-select/next.tsx
new file mode 100644
index 000000000..9e1141a59
--- /dev/null
+++ b/web/src/components/llm-select/next.tsx
@@ -0,0 +1,55 @@
+import { LlmModelType } from '@/constants/knowledge';
+import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks';
+import * as SelectPrimitive from '@radix-ui/react-select';
+import { forwardRef, useState } from 'react';
+import { LlmSettingFieldItems } from '../llm-setting-items/next';
+import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';
+import { Select, SelectTrigger, SelectValue } from '../ui/select';
+
+interface IProps {
+ id?: string;
+ value?: string;
+ onInitialValue?: (value: string, option: any) => void;
+ onChange?: (value: string, option: any) => void;
+ disabled?: boolean;
+}
+
+export const NextLLMSelect = forwardRef<
+ React.ElementRef,
+ IProps
+>(({ value, disabled }, ref) => {
+ const [isPopoverOpen, setIsPopoverOpen] = useState(false);
+ const modelOptions = useComposeLlmOptionsByModelTypes([
+ LlmModelType.Chat,
+ LlmModelType.Image2text,
+ ]);
+
+ return (
+
+ );
+});
+
+NextLLMSelect.displayName = 'LLMSelect';
diff --git a/web/src/components/llm-setting-items/next.tsx b/web/src/components/llm-setting-items/next.tsx
index 31e63068b..351916d86 100644
--- a/web/src/components/llm-setting-items/next.tsx
+++ b/web/src/components/llm-setting-items/next.tsx
@@ -4,6 +4,7 @@ import { useComposeLlmOptionsByModelTypes } from '@/hooks/llm-hooks';
import { camelCase } from 'lodash';
import { useCallback } from 'react';
import { useFormContext } from 'react-hook-form';
+import { z } from 'zod';
import {
FormControl,
FormField,
@@ -11,7 +12,6 @@ import {
FormLabel,
FormMessage,
} from '../ui/form';
-import { Input } from '../ui/input';
import {
Select,
SelectContent,
@@ -21,86 +21,20 @@ import {
SelectTrigger,
SelectValue,
} from '../ui/select';
-import { FormSlider } from '../ui/slider';
-import { Switch } from '../ui/switch';
-
-interface SliderWithInputNumberFormFieldProps {
- name: string;
- label: string;
- checkName: string;
- max: number;
- min?: number;
- step?: number;
-}
-
-function SliderWithInputNumberFormField({
- name,
- label,
- checkName,
- max,
- min = 0,
- step = 1,
-}: SliderWithInputNumberFormFieldProps) {
- const { control, watch } = useFormContext();
- const { t } = useTranslate('chat');
- const disabled = !watch(checkName);
-
- return (
- (
-
-
- {t(label)}
- (
-
-
-
-
-
-
- )}
- />
-
-
-
-
-
-
-
-
-
- )}
- />
- );
-}
+import { SliderInputSwitchFormField } from './slider';
interface LlmSettingFieldItemsProps {
prefix?: string;
}
+export const LlmSettingSchema = {
+ llm_id: z.string(),
+ temperature: z.coerce.number(),
+ top_p: z.string(),
+ presence_penalty: z.coerce.number(),
+ frequency_penalty: z.coerce.number(),
+};
+
export function LlmSettingFieldItems({ prefix }: LlmSettingFieldItemsProps) {
const form = useFormContext();
const { t } = useTranslate('chat');
@@ -122,7 +56,7 @@ export function LlmSettingFieldItems({ prefix }: LlmSettingFieldItemsProps) {
);
return (
-
+
)}
/>
-
-
+
-
+
-
+
-
+
+ >
);
}
diff --git a/web/src/components/llm-setting-items/slider.tsx b/web/src/components/llm-setting-items/slider.tsx
new file mode 100644
index 000000000..a9137b353
--- /dev/null
+++ b/web/src/components/llm-setting-items/slider.tsx
@@ -0,0 +1,92 @@
+import { useTranslate } from '@/hooks/common-hooks';
+import { cn } from '@/lib/utils';
+import { useFormContext } from 'react-hook-form';
+import { SingleFormSlider } from '../ui/dual-range-slider';
+import {
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from '../ui/form';
+import { Input } from '../ui/input';
+import { Switch } from '../ui/switch';
+
+type SliderInputSwitchFormFieldProps = {
+ max?: number;
+ min?: number;
+ step?: number;
+ name: string;
+ label: string;
+ defaultValue?: number;
+ className?: string;
+ checkName: string;
+};
+
+export function SliderInputSwitchFormField({
+ max,
+ min,
+ step,
+ label,
+ name,
+ defaultValue,
+ className,
+ checkName,
+}: SliderInputSwitchFormFieldProps) {
+ const form = useFormContext();
+ const disabled = !form.watch(checkName);
+ const { t } = useTranslate('chat');
+
+ return (
+
(
+
+ {t(label)}
+
+ (
+
+
+
+
+
+
+ )}
+ />
+
+
+
+
+
+
+
+
+
+ )}
+ />
+ );
+}
diff --git a/web/src/components/originui/select-with-search.tsx b/web/src/components/originui/select-with-search.tsx
new file mode 100644
index 000000000..c5b0c853e
--- /dev/null
+++ b/web/src/components/originui/select-with-search.tsx
@@ -0,0 +1,163 @@
+'use client';
+
+import { CheckIcon, ChevronDownIcon } from 'lucide-react';
+import { Fragment, useCallback, useEffect, useId, useState } from 'react';
+
+import { Button } from '@/components/ui/button';
+import {
+ Command,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+} from '@/components/ui/command';
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from '@/components/ui/popover';
+import { RAGFlowSelectOptionType } from '../ui/select';
+
+const countries = [
+ {
+ label: 'America',
+ options: [
+ { value: 'United States', label: '🇺🇸' },
+ { value: 'Canada', label: '🇨🇦' },
+ { value: 'Mexico', label: '🇲🇽' },
+ ],
+ },
+ {
+ label: 'Africa',
+ options: [
+ { value: 'South Africa', label: '🇿🇦' },
+ { value: 'Nigeria', label: '🇳🇬' },
+ { value: 'Morocco', label: '🇲🇦' },
+ ],
+ },
+ {
+ label: 'Asia',
+ options: [
+ { value: 'China', label: '🇨🇳' },
+ { value: 'Japan', label: '🇯🇵' },
+ { value: 'India', label: '🇮🇳' },
+ ],
+ },
+ {
+ label: 'Europe',
+ options: [
+ { value: 'United Kingdom', label: '🇬🇧' },
+ { value: 'France', label: '🇫🇷' },
+ { value: 'Germany', label: '🇩🇪' },
+ ],
+ },
+ {
+ label: 'Oceania',
+ options: [
+ { value: 'Australia', label: '🇦🇺' },
+ { value: 'New Zealand', label: '🇳🇿' },
+ ],
+ },
+];
+
+export type SelectWithSearchFlagOptionType = {
+ label: string;
+ options: RAGFlowSelectOptionType[];
+};
+
+export type SelectWithSearchFlagProps = {
+ options?: SelectWithSearchFlagOptionType[];
+ value?: string;
+ onChange?(value: string): void;
+};
+
+export function SelectWithSearch({
+ value: val = '',
+ onChange,
+ options = countries,
+}: SelectWithSearchFlagProps) {
+ const id = useId();
+ const [open, setOpen] = useState(false);
+ const [value, setValue] = useState('');
+
+ const handleSelect = useCallback(
+ (val: string) => {
+ setValue(val);
+ setOpen(false);
+ onChange?.(val);
+ },
+ [onChange],
+ );
+
+ useEffect(() => {
+ setValue(val);
+ }, [val]);
+
+ return (
+
+
+
+
+
+
+
+
+ No data found.
+ {options.map((group) => (
+
+
+ {group.options.map((option) => (
+
+
+ {option.label}
+
+ {option.value}
+ {value === option.value && (
+
+ )}
+
+ ))}
+
+
+ ))}
+
+
+
+
+ );
+}
diff --git a/web/src/pages/agent/form-sheet/use-form-config-map.tsx b/web/src/pages/agent/form-sheet/use-form-config-map.tsx
index e3175ac65..5d075e393 100644
--- a/web/src/pages/agent/form-sheet/use-form-config-map.tsx
+++ b/web/src/pages/agent/form-sheet/use-form-config-map.tsx
@@ -1,3 +1,4 @@
+import { LlmSettingSchema } from '@/components/llm-setting-items/next';
import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent';
import { useTranslation } from 'react-i18next';
import { z } from 'zod';
@@ -116,6 +117,7 @@ export function useFormConfigMap() {
component: CategorizeForm,
defaultValues: { message_history_window_size: 1 },
schema: z.object({
+ ...LlmSettingSchema,
message_history_window_size: z.number(),
items: z.array(
z.object({
diff --git a/web/src/pages/agent/form/categorize-form/index.tsx b/web/src/pages/agent/form/categorize-form/index.tsx
index 220c17ded..eb1067fc0 100644
--- a/web/src/pages/agent/form/categorize-form/index.tsx
+++ b/web/src/pages/agent/form/categorize-form/index.tsx
@@ -1,20 +1,45 @@
import { LargeModelFormField } from '@/components/large-model-form-field';
import { MessageHistoryWindowSizeFormField } from '@/components/message-history-window-size-item';
-import { Form } from '@/components/ui/form';
+import { SelectWithSearch } from '@/components/originui/select-with-search';
+import {
+ Form,
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from '@/components/ui/form';
+import { useTranslation } from 'react-i18next';
import { INextOperatorForm } from '../../interface';
-import { DynamicInputVariable } from '../components/next-dynamic-input-variable';
import DynamicCategorize from './dynamic-categorize';
const CategorizeForm = ({ form, node }: INextOperatorForm) => {
+ const { t } = useTranslation();
+
return (