### What problem does this PR solve? feat: add DynamicCategorize #918 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.8.0
| @@ -10,12 +10,7 @@ const LLMSelect = () => { | |||
| return ( | |||
| <Popover content={content} trigger="click" placement="left" arrow={false}> | |||
| {/* <Button>Click me</Button> */} | |||
| <Select | |||
| defaultValue="lucy" | |||
| style={{ width: '100%' }} | |||
| dropdownStyle={{ display: 'none' }} | |||
| /> | |||
| <Select style={{ width: '100%' }} dropdownStyle={{ display: 'none' }} /> | |||
| </Popover> | |||
| ); | |||
| }; | |||
| @@ -25,7 +25,9 @@ const handleGithubCLick = () => { | |||
| const RightToolBar = () => { | |||
| const { t } = useTranslate('common'); | |||
| const changeLanguage = useChangeLanguage(); | |||
| const { language = '' } = useSelector((state) => state.settingModel.userInfo); | |||
| const { language = 'en' } = useSelector( | |||
| (state) => state.settingModel.userInfo, | |||
| ); | |||
| const handleItemClick: MenuProps['onClick'] = ({ key }) => { | |||
| changeLanguage(key); | |||
| @@ -505,6 +505,7 @@ export default { | |||
| preview: '預覽', | |||
| fileError: '文件錯誤', | |||
| }, | |||
| flow: { cite: '引用', citeTip: 'citeTip' }, | |||
| footer: { | |||
| profile: '“保留所有權利 @ react”', | |||
| }, | |||
| @@ -523,6 +523,7 @@ export default { | |||
| preview: '预览', | |||
| fileError: '文件错误', | |||
| }, | |||
| flow: { cite: '引用', citeTip: 'citeTip' }, | |||
| footer: { | |||
| profile: 'All rights reserved @ React', | |||
| }, | |||
| @@ -7,6 +7,7 @@ import { Flex, MenuProps, Space, Typography } from 'antd'; | |||
| import { useCallback } from 'react'; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { Operator, operatorMap } from '../../constant'; | |||
| import { NodeData } from '../../interface'; | |||
| import OperatorIcon from '../../operator-icon'; | |||
| import useGraphStore from '../../store'; | |||
| import styles from './index.less'; | |||
| @@ -18,7 +19,7 @@ export function RagNode({ | |||
| data, | |||
| isConnectable = true, | |||
| selected, | |||
| }: NodeProps<{ label: string }>) { | |||
| }: NodeProps<NodeData>) { | |||
| const { t } = useTranslation(); | |||
| const deleteNodeById = useGraphStore((store) => store.deleteNodeById); | |||
| const duplicateNodeById = useGraphStore((store) => store.duplicateNode); | |||
| @@ -78,7 +79,7 @@ export function RagNode({ | |||
| name={data.label as Operator} | |||
| fontSize={12} | |||
| ></OperatorIcon> | |||
| <span>{data.label}</span> | |||
| <span>{id}</span> | |||
| </Space> | |||
| <OperateDropdown | |||
| iconFontSize={14} | |||
| @@ -0,0 +1,69 @@ | |||
| import { CloseOutlined } from '@ant-design/icons'; | |||
| import { Button, Card, Form, Input, Select, Typography } from 'antd'; | |||
| import { useBuildCategorizeToOptions } from './hooks'; | |||
| const DynamicCategorize = () => { | |||
| const form = Form.useFormInstance(); | |||
| const options = useBuildCategorizeToOptions(); | |||
| return ( | |||
| <> | |||
| <Form.List name="items"> | |||
| {(fields, { add, remove }) => ( | |||
| <div style={{ display: 'flex', rowGap: 16, flexDirection: 'column' }}> | |||
| {fields.map((field) => ( | |||
| <Card | |||
| size="small" | |||
| key={field.key} | |||
| extra={ | |||
| <CloseOutlined | |||
| onClick={() => { | |||
| remove(field.name); | |||
| }} | |||
| /> | |||
| } | |||
| > | |||
| <Form.Item | |||
| label="name" | |||
| name={[field.name, 'name']} | |||
| initialValue={`Categorize ${field.name + 1}`} | |||
| rules={[ | |||
| { required: true, message: 'Please input your name!' }, | |||
| ]} | |||
| > | |||
| <Input /> | |||
| </Form.Item> | |||
| <Form.Item | |||
| label="description" | |||
| name={[field.name, 'description']} | |||
| > | |||
| <Input.TextArea rows={3} /> | |||
| </Form.Item> | |||
| <Form.Item label="examples" name={[field.name, 'examples']}> | |||
| <Input.TextArea rows={3} /> | |||
| </Form.Item> | |||
| <Form.Item label="to" name={[field.name, 'to']}> | |||
| <Select options={options} /> | |||
| </Form.Item> | |||
| </Card> | |||
| ))} | |||
| <Button type="dashed" onClick={() => add()} block> | |||
| + Add Item | |||
| </Button> | |||
| </div> | |||
| )} | |||
| </Form.List> | |||
| <Form.Item noStyle shouldUpdate> | |||
| {() => ( | |||
| <Typography> | |||
| <pre>{JSON.stringify(form.getFieldsValue(), null, 2)}</pre> | |||
| </Typography> | |||
| )} | |||
| </Form.Item> | |||
| </> | |||
| ); | |||
| }; | |||
| export default DynamicCategorize; | |||
| @@ -0,0 +1,13 @@ | |||
| import { Operator } from '../constant'; | |||
| import useGraphStore from '../store'; | |||
| // exclude some nodes downstream of the classification node | |||
| const excludedNodes = [Operator.Categorize, Operator.Answer, Operator.Begin]; | |||
| export const useBuildCategorizeToOptions = () => { | |||
| const nodes = useGraphStore((state) => state.nodes); | |||
| return nodes | |||
| .filter((x) => excludedNodes.every((y) => y !== x.data.label)) | |||
| .map((x) => ({ label: x.id, value: x.id })); | |||
| }; | |||
| @@ -1,10 +1,28 @@ | |||
| import LLMSelect from '@/components/llm-select'; | |||
| import { useTranslate } from '@/hooks/commonHooks'; | |||
| import { Form } from 'antd'; | |||
| import { IOperatorForm } from '../interface'; | |||
| import DynamicCategorize from './dynamic-categorize'; | |||
| const CategorizeForm = ({ form, onValuesChange }: IOperatorForm) => { | |||
| const { t } = useTranslate('flow'); | |||
| const CategorizeForm = () => { | |||
| return ( | |||
| <section> | |||
| <LLMSelect></LLMSelect> | |||
| </section> | |||
| <Form | |||
| name="basic" | |||
| labelCol={{ span: 9 }} | |||
| wrapperCol={{ span: 15 }} | |||
| autoComplete="off" | |||
| form={form} | |||
| onValuesChange={onValuesChange} | |||
| initialValues={{ items: [{}] }} | |||
| // layout={'vertical'} | |||
| > | |||
| <Form.Item name={['cite']} label={t('cite')} tooltip={t('citeTip')}> | |||
| <LLMSelect></LLMSelect> | |||
| </Form.Item> | |||
| <DynamicCategorize></DynamicCategorize> | |||
| </Form> | |||
| ); | |||
| }; | |||
| @@ -80,4 +80,5 @@ export const initialFormValuesMap = { | |||
| [Operator.Retrieval]: initialRetrievalValues, | |||
| [Operator.Generate]: initialGenerateValues, | |||
| [Operator.Answer]: {}, | |||
| [Operator.Categorize]: {}, | |||
| }; | |||