Feat: Add a prefix to the name of the FormField associated with the chat. (#16178)

Fix: Add a prefix to the `name` of the `FormField` associated with the chat.
This commit is contained in:
balibabu
2026-06-22 19:18:11 +08:00
committed by GitHub
parent 0e6b28a7fe
commit c849c76f8a
6 changed files with 122 additions and 43 deletions

View File

@@ -1,5 +1,6 @@
import { ModelTreeSelect } from '@/components/model-tree-select';
import { useTranslate } from '@/hooks/common-hooks';
import { prefixName } from '@/utils/form';
import { useFormContext } from 'react-hook-form';
import { z } from 'zod';
import { SliderInputFormField } from './slider-input-form-field';
@@ -19,16 +20,21 @@ export const initialTopKValue = {
top_k: 1024,
};
const RerankId = 'rerank_id';
const DefaultRerankId = 'rerank_id';
const DefaultTopK = 'top_k';
function RerankFormField() {
interface RerankFormFieldProps {
name?: string;
}
function RerankFormField({ name = DefaultRerankId }: RerankFormFieldProps) {
const form = useFormContext();
const { t } = useTranslate('knowledgeDetails');
return (
<FormField
control={form.control}
name={RerankId}
name={name}
render={({ field }) => (
<FormItem>
<FormLabel tooltip={t('rerankTip')}>{t('rerankModel')}</FormLabel>
@@ -48,21 +54,28 @@ function RerankFormField() {
}
export const rerankFormSchema = {
[RerankId]: z.string().optional(),
[DefaultRerankId]: z.string().optional(),
top_k: z.coerce.number().optional(),
};
export function RerankFormFields() {
interface RerankFormFieldsProps {
prefix?: string;
}
export function RerankFormFields({ prefix = '' }: RerankFormFieldsProps) {
const { watch } = useFormContext();
const { t } = useTranslate('knowledgeDetails');
const rerankId = watch(RerankId);
const rerankIdName = prefixName(prefix, DefaultRerankId);
const topKName = prefixName(prefix, DefaultTopK);
const rerankId = watch(rerankIdName);
return (
<>
<RerankFormField></RerankFormField>
<RerankFormField name={rerankIdName}></RerankFormField>
{rerankId && (
<SliderInputFormField
name={'top_k'}
name={topKName}
label={t('topK')}
max={2048}
min={1}

View File

@@ -5,18 +5,22 @@ import { SliderInputFormField } from './slider-input-form-field';
interface SimilaritySliderFormFieldProps {
max?: number;
name?: string;
}
export const topnSchema = {
top_n: z.number().optional(),
};
export function TopNFormField({ max = 30 }: SimilaritySliderFormFieldProps) {
export function TopNFormField({
max = 30,
name = 'top_n',
}: SimilaritySliderFormFieldProps) {
const { t } = useTranslate('chat');
return (
<SliderInputFormField
name={'top_n'}
name={name}
label={t('topN')}
max={max}
tooltip={t('topNTip')}

View File

@@ -12,21 +12,33 @@ import {
} from '@/components/ui/form';
import { Textarea } from '@/components/ui/textarea';
import { useTranslate } from '@/hooks/common-hooks';
import { prefixName } from '@/utils/form';
import { getDirAttribute } from '@/utils/text-direction';
import { useFormContext, useWatch } from 'react-hook-form';
export default function ChatBasicSetting() {
interface ChatBasicSettingProps {
prefix?: string;
option?: Record<string, any>;
}
export default function ChatBasicSetting({
prefix = '',
}: ChatBasicSettingProps) {
const { t } = useTranslate('chat');
const form = useFormContext();
const prologueValue = useWatch({
control: form.control,
name: 'prompt_config.prologue',
name: prefixName(prefix, 'prompt_config.prologue'),
});
return (
<div className="space-y-8">
<AvatarNameDescription />
<AvatarNameDescription
avatarField={prefixName(prefix, 'icon')}
nameField={prefixName(prefix, 'name')}
descriptionField={prefixName(prefix, 'description')}
/>
<LlmSettingFieldItems
prefix="llm_setting"
llmId="llm_id"
@@ -35,7 +47,7 @@ export default function ChatBasicSetting() {
<FormField
control={form.control}
name={'prompt_config.prologue'}
name={prefixName(prefix, 'prompt_config.prologue')}
render={({ field }) => (
<FormItem>
<FormLabel tooltip={t('setAnOpenerTip')}>
@@ -51,8 +63,9 @@ export default function ChatBasicSetting() {
</FormItem>
)}
/>
<KnowledgeBaseFormField></KnowledgeBaseFormField>
<KnowledgeBaseFormField
name={prefixName(prefix, 'dataset_ids')}
></KnowledgeBaseFormField>
</div>
);
}

View File

@@ -21,21 +21,30 @@ import { Switch } from '@/components/ui/switch';
import { Textarea } from '@/components/ui/textarea';
import { UseKnowledgeGraphFormField } from '@/components/use-knowledge-graph-item';
import { useFetchKnowledgeMetadataKeys } from '@/hooks/use-knowledge-request';
import { prefixName } from '@/utils/form';
import { getDirAttribute } from '@/utils/text-direction';
import { useEffect, useMemo } from 'react';
import { useFormContext, useWatch } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
import { DynamicVariableForm } from './dynamic-variable';
export function ChatPromptEngine() {
interface ChatPromptEngineProps {
prefix?: string;
}
export function ChatPromptEngine({ prefix = '' }: ChatPromptEngineProps) {
const { t } = useTranslation();
const form = useFormContext();
const systemPromptValue = form.watch('prompt_config.system');
const systemPromptValue = form.watch(
prefixName(prefix, 'prompt_config.system'),
);
const emptyResponseValue = form.watch('prompt_config.empty_response');
const emptyResponseValue = form.watch(
prefixName(prefix, 'prompt_config.empty_response'),
);
const rawDatasetIds = useWatch({
control: form.control,
name: 'dataset_ids',
name: prefixName(prefix, 'dataset_ids'),
});
const kbIds = useMemo(
() => (rawDatasetIds || []) as string[],
@@ -43,7 +52,7 @@ export function ChatPromptEngine() {
);
const metadataInclude = useWatch({
control: form.control,
name: 'prompt_config.reference_metadata.include',
name: prefixName(prefix, 'prompt_config.reference_metadata.include'),
});
const { data: metadataKeys, loading: metadataKeysLoading } =
useFetchKnowledgeMetadataKeys(kbIds);
@@ -56,7 +65,7 @@ export function ChatPromptEngine() {
useEffect(() => {
const currentFields = form.getValues(
'prompt_config.reference_metadata.fields',
prefixName(prefix, 'prompt_config.reference_metadata.fields'),
);
if (
metadataInclude &&
@@ -68,19 +77,25 @@ export function ChatPromptEngine() {
metadataKeys.includes(field),
);
if (validFields.length !== currentFields.length) {
form.setValue('prompt_config.reference_metadata.fields', validFields);
form.setValue(
prefixName(prefix, 'prompt_config.reference_metadata.fields'),
validFields,
);
}
} else if (!metadataInclude) {
form.setValue('prompt_config.reference_metadata.fields', undefined);
form.setValue(
prefixName(prefix, 'prompt_config.reference_metadata.fields'),
undefined,
);
}
}, [kbIds, metadataKeys, metadataKeysLoading, metadataInclude, form]);
}, [kbIds, metadataKeys, metadataKeysLoading, metadataInclude, form, prefix]);
return (
<Collapse title={t('flow.advancedSettings')}>
<div className="space-y-8">
<FormField
control={form.control}
name={'prompt_config.empty_response'}
name={prefixName(prefix, 'prompt_config.empty_response')}
render={({ field }) => (
<FormItem>
<FormLabel tooltip={t('chat.emptyResponseTip')}>
@@ -98,26 +113,28 @@ export function ChatPromptEngine() {
)}
/>
<SwitchFormField
name={'prompt_config.quote'}
name={prefixName(prefix, 'prompt_config.quote')}
label={t('chat.quote')}
tooltip={t('chat.quoteTip')}
></SwitchFormField>
<SwitchFormField
name={'prompt_config.keyword'}
name={prefixName(prefix, 'prompt_config.keyword')}
label={t('chat.keyword')}
tooltip={t('chat.keywordTip')}
></SwitchFormField>
<SwitchFormField
name={'prompt_config.tts'}
name={prefixName(prefix, 'prompt_config.tts')}
label={t('chat.tts')}
tooltip={t('chat.ttsTip')}
></SwitchFormField>
<TOCEnhanceFormField name="prompt_config.toc_enhance"></TOCEnhanceFormField>
<TOCEnhanceFormField
name={prefixName(prefix, 'prompt_config.toc_enhance')}
></TOCEnhanceFormField>
<TavilyFormField></TavilyFormField>
<MetadataFilter></MetadataFilter>
<FormField
control={form.control}
name={'prompt_config.reference_metadata.include'}
name={prefixName(prefix, 'prompt_config.reference_metadata.include')}
render={({ field }) => (
<FormItem className="flex flex-row items-start space-x-3 space-y-0">
<FormControl>
@@ -127,7 +144,10 @@ export function ChatPromptEngine() {
field.onChange(value);
if (!value) {
form.setValue(
'prompt_config.reference_metadata.fields',
prefixName(
prefix,
'prompt_config.reference_metadata.fields',
),
undefined,
);
}
@@ -143,7 +163,7 @@ export function ChatPromptEngine() {
{metadataInclude && (
<FormField
control={form.control}
name={'prompt_config.reference_metadata.fields'}
name={prefixName(prefix, 'prompt_config.reference_metadata.fields')}
render={({ field }) => (
<FormItem>
<FormLabel tooltip="Select which metadata fields to display with each chunk">
@@ -170,7 +190,7 @@ export function ChatPromptEngine() {
)}
<FormField
control={form.control}
name="prompt_config.system"
name={prefixName(prefix, 'prompt_config.system')}
render={({ field }) => (
<FormItem>
<FormLabel>{t('chat.system')}</FormLabel>
@@ -187,17 +207,28 @@ export function ChatPromptEngine() {
</FormItem>
)}
/>
<SimilaritySliderFormField isTooltipShown></SimilaritySliderFormField>
<TopNFormField></TopNFormField>
<SimilaritySliderFormField
isTooltipShown
similarityName={prefixName(prefix, 'similarity_threshold')}
similarityWeightName={prefixName(prefix, 'vector_similarity_weight')}
></SimilaritySliderFormField>
<TopNFormField name={prefixName(prefix, 'top_n')}></TopNFormField>
<SwitchFormField
name={'prompt_config.refine_multiturn'}
name={prefixName(prefix, 'prompt_config.refine_multiturn')}
label={t('chat.multiTurn')}
tooltip={t('chat.multiTurnTip')}
></SwitchFormField>
<UseKnowledgeGraphFormField name="prompt_config.use_kg"></UseKnowledgeGraphFormField>
<RerankFormFields></RerankFormFields>
<CrossLanguageFormField></CrossLanguageFormField>
<DynamicVariableForm></DynamicVariableForm>
<UseKnowledgeGraphFormField
name={prefixName(prefix, 'prompt_config.use_kg')}
></UseKnowledgeGraphFormField>
<RerankFormFields prefix={prefix}></RerankFormFields>
<CrossLanguageFormField
name={prefixName(prefix, 'prompt_config.cross_languages')}
></CrossLanguageFormField>
<DynamicVariableForm
name={prefixName(prefix, 'prompt_config.parameters')}
></DynamicVariableForm>
</div>
</Collapse>
);

View File

@@ -15,10 +15,15 @@ import { useCallback } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form';
import { useTranslation } from 'react-i18next';
export function DynamicVariableForm() {
interface DynamicVariableFormProps {
name?: string;
}
export function DynamicVariableForm({
name = 'prompt_config.parameters',
}: DynamicVariableFormProps) {
const { t } = useTranslation();
const form = useFormContext();
const name = 'prompt_config.parameters';
const { fields, remove, append } = useFieldArray({
name,

View File

@@ -64,3 +64,16 @@ export function setLLMSettingEnabledValues(
}, {});
return values;
}
/**
* Add prefix to form field name
* @param prefix - The prefix to add (e.g., 'chat.', 'settings.')
* @param name - The field name
* @returns The prefixed field name
* @example
* prefixName('chat.', 'icon') // returns 'chat.icon'
* prefixName('', 'name') // returns 'name'
*/
export function prefixName(prefix: string, name: string): string {
return `${prefix}${name}`;
}