v4.6.4-Outlink (#589)

This commit is contained in:
Archer
2023-12-12 14:42:20 +08:00
committed by GitHub
parent d2d7eac9e0
commit e18c79ca71
79 changed files with 1094 additions and 762 deletions

View File

@@ -10,13 +10,13 @@ import React, {
} from 'react';
import { Box, Flex, IconButton } from '@chakra-ui/react';
import MyIcon from '@/components/Icon';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { streamFetch } from '@/web/common/api/fetch';
import MyTooltip from '@/components/MyTooltip';
import { useUserStore } from '@/web/support/user/useUserStore';
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
import { getGuideModule } from '@fastgpt/global/core/module/utils';
import { checkChatSupportSelectFileByModules } from '@/web/core/chat/utils';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
export type ChatTestComponentRef = {
resetChatTest: () => void;
@@ -40,10 +40,18 @@ const ChatTest = (
const startChat = useCallback(
async ({ chatList, controller, generatingMessage, variables }: StartChatFnProps) => {
const historyMaxLen =
modules
?.find((item) => item.flowType === FlowNodeTypeEnum.historyNode)
?.inputs?.find((item) => item.key === 'maxContext')?.value || 0;
let historyMaxLen = 6;
modules.forEach((module) => {
module.inputs.forEach((input) => {
if (
(input.key === ModuleInputKeyEnum.history ||
input.key === ModuleInputKeyEnum.historyMaxAmount) &&
typeof input.value === 'number'
) {
historyMaxLen = Math.max(historyMaxLen, input.value);
}
});
});
const history = chatList.slice(-historyMaxLen - 2, -2);
// 流请求,获取数据

View File

@@ -28,7 +28,7 @@ import React, {
import { customAlphabet } from 'nanoid';
import { appModule2FlowEdge, appModule2FlowNode } from '@/utils/adapt';
import { useToast } from '@/web/common/hooks/useToast';
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { ModuleDataTypeEnum } from '@fastgpt/global/core/module/constants';
import { useTranslation } from 'next-i18next';
import { ModuleItemType } from '@fastgpt/global/core/module/type.d';
@@ -449,9 +449,9 @@ export function flowNode2Modules({
flowType: item.data.flowType,
showStatus: item.data.showStatus,
position: item.position,
inputs: item.data.inputs.map((item) => ({
...item,
connected: Boolean(item.value ?? item.connected ?? item.type !== FlowNodeInputTypeEnum.target)
inputs: item.data.inputs.map((input) => ({
...input,
connected: false
})),
outputs: item.data.outputs.map((item) => ({
...item,
@@ -462,10 +462,11 @@ export function flowNode2Modules({
// update inputs and outputs
modules.forEach((module) => {
module.inputs.forEach((input) => {
input.connected =
input.connected ||
!!edges.find((edge) => edge.target === module.moduleId && edge.targetHandle === input.key);
input.connected = !!edges.find(
(edge) => edge.target === module.moduleId && edge.targetHandle === input.key
);
});
module.outputs.forEach((output) => {
output.targets = edges
.filter(

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useState } from 'react';
import React, { useMemo, useState } from 'react';
import {
Box,
Button,
@@ -12,9 +12,7 @@ import {
Flex,
Switch,
Input,
Grid,
FormControl,
useTheme,
Image,
Table,
Thead,
@@ -39,6 +37,7 @@ import MyTooltip from '@/components/MyTooltip';
import { variableTip } from '@fastgpt/global/core/module/template/tip';
import { useTranslation } from 'next-i18next';
import { useToast } from '@/web/common/hooks/useToast';
import MyRadio from '@/components/common/MyRadio';
const VariableEdit = ({
variables,
@@ -49,26 +48,28 @@ const VariableEdit = ({
}) => {
const { t } = useTranslation();
const { toast } = useToast();
const theme = useTheme();
const [refresh, setRefresh] = useState(false);
const VariableTypeList = [
{
label: t('core.module.variable.input type'),
icon: 'core/app/variable/input',
key: VariableInputEnum.input
},
{
label: t('core.module.variable.textarea type'),
icon: 'core/app/variable/textarea',
key: VariableInputEnum.textarea
},
{
label: t('core.module.variable.select type'),
icon: 'core/app/variable/select',
key: VariableInputEnum.select
}
];
const VariableTypeList = useMemo(
() => [
{
title: t('core.module.variable.input type'),
icon: 'core/app/variable/input',
value: VariableInputEnum.input
},
{
title: t('core.module.variable.textarea type'),
icon: 'core/app/variable/textarea',
value: VariableInputEnum.textarea
},
{
title: t('core.module.variable.select type'),
icon: 'core/app/variable/select',
value: VariableInputEnum.select
}
],
[t]
);
const { isOpen: isOpenEdit, onOpen: onOpenEdit, onClose: onCloseEdit } = useDisclosure();
const {
@@ -102,9 +103,9 @@ const VariableEdit = ({
const formatVariables = useMemo(() => {
return variables.map((item) => ({
...item,
icon: VariableTypeList.find((type) => type.key === item.type)?.icon
icon: VariableTypeList.find((type) => type.value === item.type)?.icon
}));
}, [variables]);
}, [VariableTypeList, variables]);
return (
<Box>
@@ -206,38 +207,18 @@ const VariableEdit = ({
<Box mt={5} mb={2}>
{t('core.module.Field Type')}
</Box>
<Grid gridTemplateColumns={'repeat(3,1fr)'} gridGap={4}>
{VariableTypeList.map((item) => (
<Flex
key={item.key}
px={3}
py={3}
border={theme.borders.base}
borderRadius={'md'}
cursor={'pointer'}
{...(item.key === getValuesEdit('variable.type')
? {
bg: 'myBlue.100',
borderColor: 'myBlue.600',
color: 'myBlue.600',
fontWeight: 'bold'
}
: {
color: 'myGray.600',
_hover: {
boxShadow: 'md'
},
onClick: () => {
setValuesEdit('variable.type', item.key);
setRefresh(!refresh);
}
})}
>
<MyIcon name={item.icon as any} w={'16px'} />
<Box ml={2}>{item.label}</Box>
</Flex>
))}
</Grid>
<MyRadio
gridGap={4}
gridTemplateColumns={'repeat(3,1fr)'}
value={getValuesEdit('variable.type')}
list={VariableTypeList}
color={'myGray.600'}
hiddenCircle
onChange={(e) => {
setValuesEdit('variable.type', e as any);
setRefresh(!refresh);
}}
/>
{getValuesEdit('variable.type') === VariableInputEnum.input && (
<>

View File

@@ -97,7 +97,7 @@ const NodeCQNode = ({ data }: NodeProps<FlowModuleItemType>) => {
});
}}
/>
<SourceHandle handleKey={item.key} valueType={ModuleDataTypeEnum.boolean} />
<SourceHandle handleKey={item.key} valueType={ModuleDataTypeEnum.string} />
</Box>
</Box>
))}

View File

@@ -29,7 +29,7 @@ import TargetHandle from './TargetHandle';
import MyIcon from '@/components/Icon';
import { useTranslation } from 'next-i18next';
import type { AIChatModuleProps } from '@fastgpt/global/core/module/node/type.d';
import { chatModelList } from '@/web/common/system/staticData';
import { chatModelList, cqModelList } from '@/web/common/system/staticData';
import { formatPrice } from '@fastgpt/global/support/wallet/bill/tools';
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
import type { SelectedDatasetType } from '@fastgpt/global/core/module/api.d';
@@ -229,8 +229,11 @@ const RenderInput = ({
{item.type === FlowNodeInputTypeEnum.aiSettings && (
<AISetting inputs={sortInputs} item={item} moduleId={moduleId} />
)}
{item.type === FlowNodeInputTypeEnum.selectChatModel && (
<SelectChatModelRender inputs={sortInputs} item={item} moduleId={moduleId} />
{[
FlowNodeInputTypeEnum.selectChatModel,
FlowNodeInputTypeEnum.selectCQModel
].includes(item.type as any) && (
<SelectAIModelRender inputs={sortInputs} item={item} moduleId={moduleId} />
)}
{item.type === FlowNodeInputTypeEnum.selectDataset && (
<SelectDatasetRender item={item} moduleId={moduleId} />
@@ -446,12 +449,21 @@ const AISetting = React.memo(function AISetting({ inputs = [], moduleId }: Rende
);
});
const SelectChatModelRender = React.memo(function SelectChatModelRender({
const SelectAIModelRender = React.memo(function SelectAIModelRender({
inputs = [],
item,
moduleId
}: RenderProps) {
const modelList = chatModelList || [];
const modelList = (() => {
if (item.type === FlowNodeInputTypeEnum.selectChatModel) return chatModelList;
if (item.type === FlowNodeInputTypeEnum.selectCQModel) return cqModelList;
return [];
})().map((item) => ({
model: item.model,
name: item.name,
maxResponse: item.maxResponse,
price: item.price
}));
const onChangeModel = useCallback(
(e: string) => {