mirror of
https://git.mirrors.martin98.com/https://github.com/infiniflow/ragflow.git
synced 2025-05-29 01:28:42 +08:00
### What problem does this PR solve? Feat: Use shadcn-ui to build GenerateForm. #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
parent
651422127c
commit
244cf49ba4
@ -1,5 +1,14 @@
|
||||
import { Form, InputNumber } from 'antd';
|
||||
import { useFormContext } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from './ui/form';
|
||||
import { Input } from './ui/input';
|
||||
|
||||
const MessageHistoryWindowSizeItem = ({
|
||||
initialValue,
|
||||
@ -21,3 +30,24 @@ const MessageHistoryWindowSizeItem = ({
|
||||
};
|
||||
|
||||
export default MessageHistoryWindowSizeItem;
|
||||
|
||||
export function MessageHistoryWindowSizeFormField() {
|
||||
const form = useFormContext();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<FormField
|
||||
control={form.control}
|
||||
name={'message_history_window_size'}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('flow.messageHistoryWindowSize')}</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} type={'number'}></Input>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -52,10 +52,12 @@ export default SimilaritySlider;
|
||||
|
||||
interface SimilaritySliderFormFieldProps {
|
||||
vectorSimilarityWeightName?: string;
|
||||
isTooltipShown?: boolean;
|
||||
}
|
||||
|
||||
export function SimilaritySliderFormField({
|
||||
vectorSimilarityWeightName = 'vector_similarity_weight',
|
||||
isTooltipShown,
|
||||
}: SimilaritySliderFormFieldProps) {
|
||||
const form = useFormContext();
|
||||
const { t } = useTranslate('knowledgeDetails');
|
||||
@ -67,7 +69,9 @@ export function SimilaritySliderFormField({
|
||||
name={'similarity_threshold'}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('similarityThreshold')}</FormLabel>
|
||||
<FormLabel tooltip={isTooltipShown && t('similarityThresholdTip')}>
|
||||
{t('similarityThreshold')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<SingleFormSlider
|
||||
{...field}
|
||||
@ -84,7 +88,11 @@ export function SimilaritySliderFormField({
|
||||
name={vectorSimilarityWeightName}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{t('vectorSimilarityWeight')}</FormLabel>
|
||||
<FormLabel
|
||||
tooltip={isTooltipShown && t('vectorSimilarityWeightTip')}
|
||||
>
|
||||
{t('vectorSimilarityWeight')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<SingleFormSlider
|
||||
{...field}
|
||||
|
@ -14,6 +14,8 @@ import {
|
||||
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { Info } from 'lucide-react';
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from './tooltip';
|
||||
|
||||
const Form = FormProvider;
|
||||
|
||||
@ -88,17 +90,31 @@ FormItem.displayName = 'FormItem';
|
||||
|
||||
const FormLabel = React.forwardRef<
|
||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
|
||||
>(({ className, ...props }, ref) => {
|
||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & {
|
||||
tooltip?: React.ReactNode;
|
||||
}
|
||||
>(({ className, tooltip, ...props }, ref) => {
|
||||
const { error, formItemId } = useFormField();
|
||||
|
||||
return (
|
||||
<Label
|
||||
ref={ref}
|
||||
className={cn(error && 'text-destructive', className)}
|
||||
className={cn(error && 'text-destructive', className, 'flex')}
|
||||
htmlFor={formItemId}
|
||||
{...props}
|
||||
/>
|
||||
>
|
||||
{props.children}
|
||||
{tooltip && (
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<Info className="size-3 ml-2" />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>{tooltip}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Label>
|
||||
);
|
||||
});
|
||||
FormLabel.displayName = 'FormLabel';
|
||||
|
@ -122,7 +122,7 @@ const FormSheet = ({
|
||||
<span>{t(`${lowerFirst(operatorName)}Description`)}</span>
|
||||
</section>
|
||||
</SheetHeader>
|
||||
<section>
|
||||
<section className="pt-4">
|
||||
{visible && (
|
||||
<FlowFormContext.Provider value={node}>
|
||||
<OperatorForm
|
||||
|
@ -82,8 +82,15 @@ export function useFormConfigMap() {
|
||||
},
|
||||
[Operator.Generate]: {
|
||||
component: GenerateForm,
|
||||
defaultValues: {},
|
||||
schema: z.object({}),
|
||||
defaultValues: {
|
||||
cite: true,
|
||||
prompt: t('flow.promptText'),
|
||||
},
|
||||
schema: z.object({
|
||||
prompt: z.string().min(1, {
|
||||
message: t('flow.promptMessage'),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
[Operator.Answer]: {
|
||||
component: AnswerForm,
|
||||
|
@ -121,7 +121,7 @@ export function DynamicInputVariable({ node }: IProps) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Collapsible defaultOpen className="group/collapsible pt-4">
|
||||
<Collapsible defaultOpen className="group/collapsible">
|
||||
<CollapsibleTrigger className="flex justify-between w-full pb-2">
|
||||
<span className="font-bold text-2xl text-colors-text-neutral-strong">
|
||||
{t('flow.input')}
|
||||
|
@ -1,101 +0,0 @@
|
||||
import { EditableCell, EditableRow } from '@/components/editable-cell';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { RAGFlowNodeType } from '@/interfaces/database/flow';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import { Button, Flex, Select, Table, TableProps } from 'antd';
|
||||
import { useBuildComponentIdSelectOptions } from '../../hooks/use-get-begin-query';
|
||||
import { IGenerateParameter } from '../../interface';
|
||||
import { useHandleOperateParameters } from './hooks';
|
||||
|
||||
import styles from './index.less';
|
||||
interface IProps {
|
||||
node?: RAGFlowNodeType;
|
||||
}
|
||||
|
||||
const components = {
|
||||
body: {
|
||||
row: EditableRow,
|
||||
cell: EditableCell,
|
||||
},
|
||||
};
|
||||
|
||||
const DynamicParameters = ({ node }: IProps) => {
|
||||
const nodeId = node?.id;
|
||||
const { t } = useTranslate('flow');
|
||||
|
||||
const options = useBuildComponentIdSelectOptions(nodeId, node?.parentId);
|
||||
const {
|
||||
dataSource,
|
||||
handleAdd,
|
||||
handleRemove,
|
||||
handleSave,
|
||||
handleComponentIdChange,
|
||||
} = useHandleOperateParameters(nodeId!);
|
||||
|
||||
const columns: TableProps<IGenerateParameter>['columns'] = [
|
||||
{
|
||||
title: t('key'),
|
||||
dataIndex: 'key',
|
||||
key: 'key',
|
||||
width: '40%',
|
||||
onCell: (record: IGenerateParameter) => ({
|
||||
record,
|
||||
editable: true,
|
||||
dataIndex: 'key',
|
||||
title: 'key',
|
||||
handleSave,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: t('value'),
|
||||
dataIndex: 'component_id',
|
||||
key: 'component_id',
|
||||
align: 'center',
|
||||
width: '40%',
|
||||
render(text, record) {
|
||||
return (
|
||||
<Select
|
||||
style={{ width: '100%' }}
|
||||
allowClear
|
||||
options={options}
|
||||
value={text}
|
||||
onChange={handleComponentIdChange(record)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: t('operation'),
|
||||
dataIndex: 'operation',
|
||||
width: 20,
|
||||
key: 'operation',
|
||||
align: 'center',
|
||||
fixed: 'right',
|
||||
render(_, record) {
|
||||
return <DeleteOutlined onClick={handleRemove(record.id)} />;
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<section>
|
||||
<Flex justify="end">
|
||||
<Button size="small" onClick={handleAdd}>
|
||||
{t('add')}
|
||||
</Button>
|
||||
</Flex>
|
||||
<Table
|
||||
dataSource={dataSource}
|
||||
columns={columns}
|
||||
rowKey={'id'}
|
||||
className={styles.variableTable}
|
||||
components={components}
|
||||
rowClassName={() => styles.editableRow}
|
||||
scroll={{ x: true }}
|
||||
bordered
|
||||
/>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default DynamicParameters;
|
@ -1,70 +0,0 @@
|
||||
import get from 'lodash/get';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
import { IGenerateParameter } from '../../interface';
|
||||
import useGraphStore from '../../store';
|
||||
|
||||
export const useHandleOperateParameters = (nodeId: string) => {
|
||||
const { getNode, updateNodeForm } = useGraphStore((state) => state);
|
||||
const node = getNode(nodeId);
|
||||
const dataSource: IGenerateParameter[] = useMemo(
|
||||
() => get(node, 'data.form.parameters', []) as IGenerateParameter[],
|
||||
[node],
|
||||
);
|
||||
|
||||
const handleComponentIdChange = useCallback(
|
||||
(row: IGenerateParameter) => (value: string) => {
|
||||
const newData = [...dataSource];
|
||||
const index = newData.findIndex((item) => row.id === item.id);
|
||||
const item = newData[index];
|
||||
newData.splice(index, 1, {
|
||||
...item,
|
||||
component_id: value,
|
||||
});
|
||||
|
||||
updateNodeForm(nodeId, { parameters: newData });
|
||||
},
|
||||
[updateNodeForm, nodeId, dataSource],
|
||||
);
|
||||
|
||||
const handleRemove = useCallback(
|
||||
(id?: string) => () => {
|
||||
const newData = dataSource.filter((item) => item.id !== id);
|
||||
updateNodeForm(nodeId, { parameters: newData });
|
||||
},
|
||||
[updateNodeForm, nodeId, dataSource],
|
||||
);
|
||||
|
||||
const handleAdd = useCallback(() => {
|
||||
updateNodeForm(nodeId, {
|
||||
parameters: [
|
||||
...dataSource,
|
||||
{
|
||||
id: uuid(),
|
||||
key: '',
|
||||
component_id: undefined,
|
||||
},
|
||||
],
|
||||
});
|
||||
}, [dataSource, nodeId, updateNodeForm]);
|
||||
|
||||
const handleSave = (row: IGenerateParameter) => {
|
||||
const newData = [...dataSource];
|
||||
const index = newData.findIndex((item) => row.id === item.id);
|
||||
const item = newData[index];
|
||||
newData.splice(index, 1, {
|
||||
...item,
|
||||
...row,
|
||||
});
|
||||
|
||||
updateNodeForm(nodeId, { parameters: newData });
|
||||
};
|
||||
|
||||
return {
|
||||
handleAdd,
|
||||
handleRemove,
|
||||
handleComponentIdChange,
|
||||
handleSave,
|
||||
dataSource,
|
||||
};
|
||||
};
|
@ -1,21 +0,0 @@
|
||||
.variableTable {
|
||||
margin-top: 14px;
|
||||
}
|
||||
.editableRow {
|
||||
:global(.editable-cell) {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
:global(.editable-cell-value-wrap) {
|
||||
padding: 5px 12px;
|
||||
cursor: pointer;
|
||||
height: 30px !important;
|
||||
}
|
||||
&:hover {
|
||||
:global(.editable-cell-value-wrap) {
|
||||
padding: 4px 11px;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,55 +1,76 @@
|
||||
import LLMSelect from '@/components/llm-select';
|
||||
import MessageHistoryWindowSizeItem from '@/components/message-history-window-size-item';
|
||||
import { MessageHistoryWindowSizeFormField } from '@/components/message-history-window-size-item';
|
||||
import { PromptEditor } from '@/components/prompt-editor';
|
||||
import { useTranslate } from '@/hooks/common-hooks';
|
||||
import { Form, Switch } from 'antd';
|
||||
import { IOperatorForm } from '../../interface';
|
||||
import {
|
||||
Form,
|
||||
FormControl,
|
||||
FormField,
|
||||
FormItem,
|
||||
FormLabel,
|
||||
FormMessage,
|
||||
} from '@/components/ui/form';
|
||||
import { Switch } from '@/components/ui/switch';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { INextOperatorForm } from '../../interface';
|
||||
|
||||
const GenerateForm = ({ onValuesChange, form }: IOperatorForm) => {
|
||||
const { t } = useTranslate('flow');
|
||||
const GenerateForm = ({ form }: INextOperatorForm) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Form
|
||||
name="basic"
|
||||
autoComplete="off"
|
||||
form={form}
|
||||
onValuesChange={onValuesChange}
|
||||
layout={'vertical'}
|
||||
>
|
||||
<Form.Item
|
||||
name={'llm_id'}
|
||||
label={t('model', { keyPrefix: 'chat' })}
|
||||
tooltip={t('modelTip', { keyPrefix: 'chat' })}
|
||||
<Form {...form}>
|
||||
<form
|
||||
className="space-y-6"
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
}}
|
||||
>
|
||||
<LLMSelect></LLMSelect>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={['prompt']}
|
||||
label={t('systemPrompt')}
|
||||
initialValue={t('promptText')}
|
||||
tooltip={t('promptTip', { keyPrefix: 'knowledgeConfiguration' })}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: t('promptMessage'),
|
||||
},
|
||||
]}
|
||||
>
|
||||
{/* <Input.TextArea rows={8}></Input.TextArea> */}
|
||||
<PromptEditor></PromptEditor>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={['cite']}
|
||||
label={t('cite')}
|
||||
initialValue={true}
|
||||
valuePropName="checked"
|
||||
tooltip={t('citeTip')}
|
||||
>
|
||||
<Switch />
|
||||
</Form.Item>
|
||||
<MessageHistoryWindowSizeItem
|
||||
initialValue={12}
|
||||
></MessageHistoryWindowSizeItem>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="llm_id"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel tooltip={t('chat.modelTip')}>
|
||||
{t('chat.model')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<LLMSelect {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="prompt"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel tooltip={t('knowledgeConfiguration.promptTip')}>
|
||||
{t('flow.systemPrompt')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<PromptEditor {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="cite"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel tooltip={t('flow.citeTip')}>
|
||||
{t('flow.cite')}
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<Switch {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<MessageHistoryWindowSizeFormField></MessageHistoryWindowSizeFormField>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
@ -26,7 +26,10 @@ const RetrievalForm = ({ form, node }: INextOperatorForm) => {
|
||||
}}
|
||||
>
|
||||
<DynamicInputVariable node={node}></DynamicInputVariable>
|
||||
<SimilaritySliderFormField vectorSimilarityWeightName="keywords_similarity_weight"></SimilaritySliderFormField>
|
||||
<SimilaritySliderFormField
|
||||
vectorSimilarityWeightName="keywords_similarity_weight"
|
||||
isTooltipShown
|
||||
></SimilaritySliderFormField>
|
||||
<TopNFormField></TopNFormField>
|
||||
<RerankFormFields></RerankFormFields>
|
||||
<KnowledgeBaseFormField></KnowledgeBaseFormField>
|
||||
|
Loading…
x
Reference in New Issue
Block a user