diff --git a/api/db/services/dialog_service.py b/api/db/services/dialog_service.py
index cbbc8ba9e4..62372c7c3d 100644
--- a/api/db/services/dialog_service.py
+++ b/api/db/services/dialog_service.py
@@ -121,6 +121,7 @@ class DialogService(CommonService):
cls.model.do_refer,
cls.model.rerank_id,
cls.model.kb_ids,
+ cls.model.icon,
cls.model.status,
User.nickname,
User.avatar.alias("tenant_avatar"),
diff --git a/web/src/components/llm-setting-items/next.tsx b/web/src/components/llm-setting-items/next.tsx
index ac582657ca..51a332dd4a 100644
--- a/web/src/components/llm-setting-items/next.tsx
+++ b/web/src/components/llm-setting-items/next.tsx
@@ -30,15 +30,16 @@ interface LlmSettingFieldItemsProps {
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(),
- temperatureEnabled: z.boolean(),
- topPEnabled: z.boolean(),
- presencePenaltyEnabled: z.boolean(),
- frequencyPenaltyEnabled: z.boolean(),
- maxTokensEnabled: z.boolean(),
+ temperature: z.coerce.number().optional(),
+ top_p: z.number().optional(),
+ presence_penalty: z.coerce.number().optional(),
+ frequency_penalty: z.coerce.number().optional(),
+ temperatureEnabled: z.boolean().optional(),
+ topPEnabled: z.boolean().optional(),
+ presencePenaltyEnabled: z.boolean().optional(),
+ frequencyPenaltyEnabled: z.boolean().optional(),
+ maxTokensEnabled: z.boolean().optional(),
+ max_tokens: z.number().optional(),
};
export function LlmSettingFieldItems({
@@ -53,13 +54,6 @@ export function LlmSettingFieldItems({
LlmModelType.Image2text,
]);
- const handleChange = useHandleFreedomChange();
-
- const parameterOptions = Object.values(ModelVariableType).map((x) => ({
- label: t(camelCase(x)),
- value: x,
- }));
-
const getFieldWithPrefix = useCallback(
(name: string) => {
return prefix ? `${prefix}.${name}` : name;
@@ -67,6 +61,13 @@ export function LlmSettingFieldItems({
[prefix],
);
+ const handleChange = useHandleFreedomChange(getFieldWithPrefix);
+
+ const parameterOptions = Object.values(ModelVariableType).map((x) => ({
+ label: t(camelCase(x)),
+ value: x,
+ }));
+
return (
{t('model')}
diff --git a/web/src/components/llm-setting-items/slider.tsx b/web/src/components/llm-setting-items/slider.tsx
index a9137b3538..baea5ea31f 100644
--- a/web/src/components/llm-setting-items/slider.tsx
+++ b/web/src/components/llm-setting-items/slider.tsx
@@ -9,7 +9,7 @@ import {
FormLabel,
FormMessage,
} from '../ui/form';
-import { Input } from '../ui/input';
+import { NumberInput } from '../ui/input';
import { Switch } from '../ui/switch';
type SliderInputSwitchFormFieldProps = {
@@ -73,15 +73,14 @@ export function SliderInputSwitchFormField({
>
-
+ >
diff --git a/web/src/components/llm-setting-items/use-watch-change.ts b/web/src/components/llm-setting-items/use-watch-change.ts
index bf3fa595c1..5731a98eff 100644
--- a/web/src/components/llm-setting-items/use-watch-change.ts
+++ b/web/src/components/llm-setting-items/use-watch-change.ts
@@ -4,7 +4,9 @@ import useGraphStore from '@/pages/agent/store';
import { useCallback, useContext } from 'react';
import { useFormContext } from 'react-hook-form';
-export function useHandleFreedomChange() {
+export function useHandleFreedomChange(
+ getFieldWithPrefix: (name: string) => string,
+) {
const form = useFormContext();
const node = useContext(AgentFormContext);
const updateNodeForm = useGraphStore((state) => state.updateNodeForm);
@@ -25,13 +27,14 @@ export function useHandleFreedomChange() {
for (const key in values) {
if (Object.prototype.hasOwnProperty.call(values, key)) {
- const element = values[key];
+ const realKey = getFieldWithPrefix(key);
+ const element = values[key as keyof typeof values];
- form.setValue(key, element);
+ form.setValue(realKey, element);
}
}
},
- [form, node, updateNodeForm],
+ [form, getFieldWithPrefix, node?.id, updateNodeForm],
);
return handleChange;
diff --git a/web/src/components/rerank.tsx b/web/src/components/rerank.tsx
index c872a92388..ca7f3bc2c3 100644
--- a/web/src/components/rerank.tsx
+++ b/web/src/components/rerank.tsx
@@ -5,6 +5,7 @@ import { Select as AntSelect, Form, message, Slider } from 'antd';
import { useCallback } from 'react';
import { useFormContext } from 'react-hook-form';
import { z } from 'zod';
+import { SelectWithSearch } from './originui/select-with-search';
import { SliderInputFormField } from './slider-input-form-field';
import {
FormControl,
@@ -13,7 +14,6 @@ import {
FormLabel,
FormMessage,
} from './ui/form';
-import { RAGFlowSelect } from './ui/select';
type FieldType = {
rerank_id?: string;
@@ -109,11 +109,11 @@ function RerankFormField() {
{t('rerankModel')}
-
+ >
@@ -122,6 +122,11 @@ function RerankFormField() {
);
}
+export const rerankFormSchema = {
+ [RerankId]: z.string().optional(),
+ top_k: z.coerce.number().optional(),
+};
+
export function RerankFormFields() {
const { watch } = useFormContext();
const { t } = useTranslate('knowledgeDetails');
diff --git a/web/src/components/similarity-slider/index.tsx b/web/src/components/similarity-slider/index.tsx
index 4dbab5e74f..796d2415e3 100644
--- a/web/src/components/similarity-slider/index.tsx
+++ b/web/src/components/similarity-slider/index.tsx
@@ -61,11 +61,20 @@ export const keywordsSimilarityWeightSchema = {
keywords_similarity_weight: z.number(),
};
+export const vectorSimilarityWeightSchema = {
+ vector_similarity_weight: z.number(),
+};
+
+export const initialVectorSimilarityWeightValue = {
+ vector_similarity_weight: 0.3,
+};
+
export function SimilaritySliderFormField({
vectorSimilarityWeightName = 'vector_similarity_weight',
isTooltipShown,
}: SimilaritySliderFormFieldProps) {
const { t } = useTranslate('knowledgeDetails');
+ const isVector = vectorSimilarityWeightName === 'vector_similarity_weight';
return (
<>
@@ -78,10 +87,19 @@ export function SimilaritySliderFormField({
>
>
);
diff --git a/web/src/components/slider-input-form-field.tsx b/web/src/components/slider-input-form-field.tsx
index 7e08a9c8dc..5986a30754 100644
--- a/web/src/components/slider-input-form-field.tsx
+++ b/web/src/components/slider-input-form-field.tsx
@@ -10,7 +10,7 @@ import {
FormLabel,
FormMessage,
} from './ui/form';
-import { Input } from './ui/input';
+import { NumberInput } from './ui/input';
export type FormLayoutType = {
layout?: FormLayout;
@@ -79,19 +79,14 @@ export function SliderInputFormField({
>
- {
- const value = ev.target.value;
- field.onChange(value === '' ? 0 : Number(value)); // convert to number
- }}
// defaultValue={defaultValue}
- >
+ >
diff --git a/web/src/components/top-n-item.tsx b/web/src/components/top-n-item.tsx
index f433771d24..c826c37005 100644
--- a/web/src/components/top-n-item.tsx
+++ b/web/src/components/top-n-item.tsx
@@ -1,5 +1,6 @@
import { useTranslate } from '@/hooks/common-hooks';
import { Form, Slider } from 'antd';
+import { z } from 'zod';
import { SliderInputFormField } from './slider-input-form-field';
type FieldType = {
@@ -32,6 +33,10 @@ interface SimilaritySliderFormFieldProps {
max?: number;
}
+export const topnSchema = {
+ top_n: z.number().optional(),
+};
+
export function TopNFormField({ max = 30 }: SimilaritySliderFormFieldProps) {
const { t } = useTranslate('chat');
diff --git a/web/src/locales/en.ts b/web/src/locales/en.ts
index df297aaa8c..3250a36744 100644
--- a/web/src/locales/en.ts
+++ b/web/src/locales/en.ts
@@ -124,9 +124,11 @@ export default {
similarityThreshold: 'Similarity threshold',
similarityThresholdTip:
'RAGFlow employs either a combination of weighted keyword similarity and weighted vector cosine similarity, or a combination of weighted keyword similarity and weighted reranking score during retrieval. This parameter sets the threshold for similarities between the user query and chunks. Any chunk with a similarity score below this threshold will be excluded from the results. By default, the threshold is set to 0.2. This means that only chunks with hybrid similarity score of 20 or higher will be retrieved.',
- vectorSimilarityWeight: 'Keyword similarity weight',
+ vectorSimilarityWeight: 'Vector similarity weight',
vectorSimilarityWeightTip:
'This sets the weight of keyword similarity in the combined similarity score, either used with vector cosine similarity or with reranking score. The total of the two weights must equal 1.0.',
+ keywordSimilarityWeight: 'Keyword similarity weight',
+ keywordSimilarityWeightTip: '',
testText: 'Test text',
testTextPlaceholder: 'Input your question here!',
testingLabel: 'Testing',
diff --git a/web/src/locales/zh.ts b/web/src/locales/zh.ts
index 031e22496b..833d5d6b06 100644
--- a/web/src/locales/zh.ts
+++ b/web/src/locales/zh.ts
@@ -115,7 +115,7 @@ export default {
similarityThreshold: '相似度阈值',
similarityThresholdTip:
'我们使用混合相似度得分来评估两行文本之间的距离。 它是加权关键词相似度和向量余弦相似度。 如果查询和块之间的相似度小于此阈值,则该块将被过滤掉。默认设置为 0.2,也就是说文本块的混合相似度得分至少 20 才会被召回。',
- vectorSimilarityWeight: '关键字相似度权重',
+ vectorSimilarityWeight: '相似度相似度权重',
vectorSimilarityWeightTip:
'我们使用混合相似性评分来评估两行文本之间的距离。它是加权关键字相似性和矢量余弦相似性或rerank得分(0〜1)。两个权重的总和为1.0。',
testText: '测试文本',
diff --git a/web/src/pages/next-chats/chat/app-settings/chat-model-settings.tsx b/web/src/pages/next-chats/chat/app-settings/chat-model-settings.tsx
index c8d54d03af..99629c4363 100644
--- a/web/src/pages/next-chats/chat/app-settings/chat-model-settings.tsx
+++ b/web/src/pages/next-chats/chat/app-settings/chat-model-settings.tsx
@@ -1,38 +1,8 @@
import { LlmSettingFieldItems } from '@/components/llm-setting-items/next';
-import {
- FormControl,
- FormField,
- FormItem,
- FormLabel,
- FormMessage,
-} from '@/components/ui/form';
-import { Textarea } from '@/components/ui/textarea';
-import { useTranslate } from '@/hooks/common-hooks';
-import { useFormContext } from 'react-hook-form';
export function ChatModelSettings() {
- const { t } = useTranslate('chat');
- const form = useFormContext();
-
return (
- (
-
- {t('system')}
-
-
-
-
-
- )}
- />
);
diff --git a/web/src/pages/next-chats/chat/app-settings/chat-prompt-engine.tsx b/web/src/pages/next-chats/chat/app-settings/chat-prompt-engine.tsx
index ec7ed82355..8a817b125a 100644
--- a/web/src/pages/next-chats/chat/app-settings/chat-prompt-engine.tsx
+++ b/web/src/pages/next-chats/chat/app-settings/chat-prompt-engine.tsx
@@ -15,6 +15,7 @@ import { Textarea } from '@/components/ui/textarea';
import { UseKnowledgeGraphFormField } from '@/components/use-knowledge-graph-item';
import { useTranslate } from '@/hooks/common-hooks';
import { useFormContext } from 'react-hook-form';
+import { DynamicVariableForm } from './dynamic-variable';
export function ChatPromptEngine() {
const { t } = useTranslate('chat');
@@ -29,11 +30,7 @@ export function ChatPromptEngine() {
{t('system')}
-
+
@@ -47,6 +44,7 @@ export function ChatPromptEngine() {
>
+
);
}
diff --git a/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx b/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx
index d2a86cf96f..18f051b064 100644
--- a/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx
+++ b/web/src/pages/next-chats/chat/app-settings/chat-settings.tsx
@@ -1,11 +1,13 @@
-import { Button } from '@/components/ui/button';
+import { ButtonLoading } from '@/components/ui/button';
+import { Form } from '@/components/ui/form';
import { Separator } from '@/components/ui/separator';
-import { useFetchDialog } from '@/hooks/use-chat-request';
-import { transformBase64ToFile } from '@/utils/file-util';
+import { useFetchDialog, useSetDialog } from '@/hooks/use-chat-request';
+import { transformBase64ToFile, transformFile2Base64 } from '@/utils/file-util';
import { zodResolver } from '@hookform/resolvers/zod';
-import { PanelRightClose } from 'lucide-react';
+import { X } from 'lucide-react';
import { useEffect } from 'react';
-import { FormProvider, useForm } from 'react-hook-form';
+import { useForm } from 'react-hook-form';
+import { useParams } from 'umi';
import { z } from 'zod';
import ChatBasicSetting from './chat-basic-settings';
import { ChatModelSettings } from './chat-model-settings';
@@ -16,8 +18,12 @@ type ChatSettingsProps = { switchSettingVisible(): void };
export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) {
const formSchema = useChatSettingSchema();
const { data } = useFetchDialog();
+ const { setDialog, loading } = useSetDialog();
+ const { id } = useParams();
- const form = useForm>({
+ type FormSchemaType = z.infer;
+
+ const form = useForm({
resolver: zodResolver(formSchema),
defaultValues: {
name: '',
@@ -35,8 +41,22 @@ export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) {
},
});
- function onSubmit(values: z.infer) {
- console.log(values);
+ async function onSubmit(values: FormSchemaType) {
+ const icon = values.icon;
+ const avatar =
+ Array.isArray(icon) && icon.length > 0
+ ? await transformFile2Base64(icon[0])
+ : '';
+ setDialog({
+ ...data,
+ ...values,
+ icon: avatar,
+ dialog_id: id,
+ });
+ }
+
+ function onInvalid(errors: any) {
+ console.log('Form validation failed:', errors);
}
useEffect(() => {
@@ -44,32 +64,33 @@ export function ChatSettings({ switchSettingVisible }: ChatSettingsProps) {
...data,
icon: data.icon ? [transformBase64ToFile(data.icon)] : [],
};
- form.reset(nextData as z.infer);
+ form.reset(nextData as FormSchemaType);
}, [data, form]);
return (
-
+
);
}
diff --git a/web/src/pages/next-chats/chat/app-settings/dynamic-variable.tsx b/web/src/pages/next-chats/chat/app-settings/dynamic-variable.tsx
new file mode 100644
index 0000000000..87ebc0c27f
--- /dev/null
+++ b/web/src/pages/next-chats/chat/app-settings/dynamic-variable.tsx
@@ -0,0 +1,89 @@
+import { Button } from '@/components/ui/button';
+import {
+ FormControl,
+ FormField,
+ FormItem,
+ FormLabel,
+ FormMessage,
+} from '@/components/ui/form';
+import { BlurInput } from '@/components/ui/input';
+import { Separator } from '@/components/ui/separator';
+import { Switch } from '@/components/ui/switch';
+import { Plus, X } from 'lucide-react';
+import { useCallback } from 'react';
+import { useFieldArray, useFormContext } from 'react-hook-form';
+import { useTranslation } from 'react-i18next';
+
+export function DynamicVariableForm() {
+ const { t } = useTranslation();
+ const form = useFormContext();
+ const name = 'prompt_config.parameters';
+
+ const { fields, remove, append } = useFieldArray({
+ name,
+ control: form.control,
+ });
+
+ const add = useCallback(() => {
+ append({
+ key: undefined,
+ optional: false,
+ });
+ }, [append]);
+
+ return (
+
+
+
+ {t('chat.variable')}
+
+
+
+
+ {fields.map((field, index) => {
+ const typeField = `${name}.${index}.key`;
+ return (
+
+ (
+
+
+
+
+
+
+ )}
+ />
+
+ (
+
+
+
+
+
+
+ )}
+ />
+
+
+ );
+ })}
+
+
+ );
+}
diff --git a/web/src/pages/next-chats/chat/app-settings/use-chat-setting-schema.tsx b/web/src/pages/next-chats/chat/app-settings/use-chat-setting-schema.tsx
index f536155145..0edf3ce47d 100644
--- a/web/src/pages/next-chats/chat/app-settings/use-chat-setting-schema.tsx
+++ b/web/src/pages/next-chats/chat/app-settings/use-chat-setting-schema.tsx
@@ -1,5 +1,9 @@
import { LlmSettingSchema } from '@/components/llm-setting-items/next';
+import { rerankFormSchema } from '@/components/rerank';
+import { vectorSimilarityWeightSchema } from '@/components/similarity-slider';
+import { topnSchema } from '@/components/top-n-item';
import { useTranslate } from '@/hooks/common-hooks';
+import { omit } from 'lodash';
import { z } from 'zod';
export function useChatSettingSchema() {
@@ -9,13 +13,17 @@ export function useChatSettingSchema() {
quote: z.boolean(),
keyword: z.boolean(),
tts: z.boolean(),
- empty_response: z.string().min(1, {
- message: t('emptyResponse'),
- }),
- prologue: z.string().min(1, {}),
+ empty_response: z.string().optional(),
+ prologue: z.string().optional(),
system: z.string().min(1, { message: t('systemMessage') }),
refine_multiturn: z.boolean(),
use_kg: z.boolean(),
+ parameters: z.array(
+ z.object({
+ key: z.string(),
+ optional: z.boolean(),
+ }),
+ ),
});
const formSchema = z.object({
@@ -29,10 +37,11 @@ export function useChatSettingSchema() {
message: 'Username must be at least 1 characters.',
}),
prompt_config: promptConfigSchema,
- top_n: z.number(),
- vector_similarity_weight: z.number(),
- top_k: z.number(),
- llm_setting: z.object(LlmSettingSchema),
+ ...rerankFormSchema,
+ llm_setting: z.object(omit(LlmSettingSchema, 'llm_id')),
+ llm_id: z.string().optional(),
+ ...vectorSimilarityWeightSchema,
+ ...topnSchema,
});
return formSchema;
diff --git a/web/src/pages/next-chats/chat/sessions.tsx b/web/src/pages/next-chats/chat/sessions.tsx
index 6bc59f412f..6562f8b506 100644
--- a/web/src/pages/next-chats/chat/sessions.tsx
+++ b/web/src/pages/next-chats/chat/sessions.tsx
@@ -47,7 +47,7 @@ export function Sessions({
}
return (
-