feat: add plugin instruction config (#2579)

* feat: add plugin instruction config

* fix build
This commit is contained in:
heheer
2024-08-30 17:12:57 +08:00
committed by GitHub
parent 2ef98c24be
commit 903f39fe17
20 changed files with 278 additions and 12 deletions

View File

@@ -11,18 +11,18 @@ enum FnTypeEnum {
variable = 'variable',
welcome = 'welcome',
file = 'file',
visionModel = 'visionModel'
visionModel = 'visionModel',
instruction = 'instruction'
}
const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => {
const { t } = useTranslation();
const { chatT } = useI18n();
const map = useRef({
[FnTypeEnum.inputGuide]: {
icon: '/imgs/app/inputGuide-icon.svg',
title: chatT('input_guide'),
desc: chatT('input_guide_tip'),
title: t('chat:input_guide'),
desc: t('chat:input_guide_tip'),
imgUrl: '/imgs/app/inputGuide.svg'
},
[FnTypeEnum.nextQuestion]: {
@@ -60,6 +60,12 @@ const ChatFunctionTip = ({ type }: { type: `${FnTypeEnum}` }) => {
title: t('app:vision_model_title'),
desc: t('app:llm_use_vision_tip'),
imgUrl: '/imgs/app/visionModel.png'
},
[FnTypeEnum.instruction]: {
icon: '/imgs/app/help.svg',
title: t('workflow:plugin.Instructions'),
desc: t('workflow:plugin.Instruction_Tip'),
imgUrl: '/imgs/app/instruction.svg'
}
});
const data = map.current[type];

View File

@@ -1,16 +1,26 @@
import React, { useEffect, useMemo } from 'react';
import { Controller } from 'react-hook-form';
import RenderPluginInput from './renderPluginInput';
import { Button, Flex } from '@chakra-ui/react';
import { Box, Button, Flex } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import { useContextSelector } from 'use-context-selector';
import { PluginRunContext } from '../context';
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
import { isEqual } from 'lodash';
import { AppChatConfigType } from '@fastgpt/global/core/app/type';
import Markdown from '@/components/Markdown';
const RenderInput = () => {
const { pluginInputs, variablesForm, histories, onStartChat, onNewChat, onSubmit, isChatting } =
useContextSelector(PluginRunContext, (v) => v);
const {
pluginInputs,
variablesForm,
histories,
onStartChat,
onNewChat,
onSubmit,
isChatting,
chatConfig
} = useContextSelector(PluginRunContext, (v) => v);
const { t } = useTranslation();
const {
@@ -64,6 +74,20 @@ const RenderInput = () => {
return (
<>
{/* instruction */}
{chatConfig?.instruction && (
<Box
border={'1px solid'}
borderColor={'myGray.250'}
p={4}
rounded={'md'}
fontSize={'sm'}
color={'myGray.600'}
>
<Markdown source={chatConfig.instruction} />
</Box>
)}
{pluginInputs.map((input) => {
return (
<Controller

View File

@@ -19,4 +19,5 @@ export type PluginRunBoxProps = OutLinkChatAuthProps & {
chatId?: string;
tab: PluginRunBoxTabEnum;
setTab: React.Dispatch<React.SetStateAction<PluginRunBoxTabEnum>>;
chatConfig?: AppChatConfigType;
};

View File

@@ -28,6 +28,7 @@ const nodeTypes: Record<FlowNodeTypeEnum, any> = {
[FlowNodeTypeEnum.textEditor]: NodeSimple,
[FlowNodeTypeEnum.customFeedback]: NodeSimple,
[FlowNodeTypeEnum.systemConfig]: dynamic(() => import('./nodes/NodeSystemConfig')),
[FlowNodeTypeEnum.pluginConfig]: dynamic(() => import('./nodes/NodePluginIO/NodePluginConfig')),
[FlowNodeTypeEnum.workflowStart]: dynamic(() => import('./nodes/NodeWorkflowStart')),
[FlowNodeTypeEnum.chatNode]: NodeSimple,
[FlowNodeTypeEnum.readFiles]: NodeSimple,

View File

@@ -0,0 +1,103 @@
import React, { Dispatch, useMemo, useState } from 'react';
import { NodeProps } from 'reactflow';
import NodeCard from '../render/NodeCard';
import { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node.d';
import { Box, Flex } from '@chakra-ui/react';
import Container from '../../components/Container';
import { useTranslation } from 'next-i18next';
import { useContextSelector } from 'use-context-selector';
import MyTextarea from '@/components/common/Textarea/MyTextarea';
import { AppContext } from '../../../../context';
import { AppChatConfigType, AppDetailType } from '@fastgpt/global/core/app/type';
import { getAppChatConfig } from '@fastgpt/global/core/workflow/utils';
import { useCreation } from 'ahooks';
import ChatFunctionTip from '@/components/core/app/Tip';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
type ComponentProps = {
chatConfig: AppChatConfigType;
setAppDetail: Dispatch<React.SetStateAction<AppDetailType>>;
};
const NodePluginConfig = ({ data, selected }: NodeProps<FlowNodeItemType>) => {
const { appDetail, setAppDetail } = useContextSelector(AppContext, (v) => v);
const chatConfig = useMemo<AppChatConfigType>(() => {
return getAppChatConfig({
chatConfig: appDetail.chatConfig,
systemConfigNode: data,
isPublicFetch: true
});
}, [data, appDetail]);
useCreation(() => {
setAppDetail((state) => ({
...state,
chatConfig: {
...state.chatConfig,
...chatConfig
}
}));
}, []);
const componentsProps = useMemo(
() => ({
chatConfig,
setAppDetail
}),
[chatConfig, setAppDetail]
);
return (
<NodeCard
selected={selected}
menuForbid={{
debug: true,
rename: true,
copy: true,
delete: true
}}
{...data}
>
<Container w={'360px'}>
<Instruction {...componentsProps} />
</Container>
</NodeCard>
);
};
export default React.memo(NodePluginConfig);
function Instruction({ chatConfig: { instruction }, setAppDetail }: ComponentProps) {
const { t } = useTranslation();
return (
<>
<Flex>
<FormLabel color={'myGray.600'} fontWeight={'medium'} fontSize={'14px'}>
{t('workflow:plugin.Instructions')}
</FormLabel>
<ChatFunctionTip type={'instruction'} />
</Flex>
<MyTextarea
iconSrc={'core/app/simpleMode/chat'}
title={t('workflow:plugin.Instructions')}
mt={2}
rows={6}
fontSize={'14px'}
bg={'white'}
resize={'both'}
placeholder={t('workflow:plugin.Instruction_Tip')}
value={instruction}
onChange={(e) => {
setAppDetail((state) => ({
...state,
chatConfig: {
...state.chatConfig,
instruction: e.target.value
}
}));
}}
/>
</>
);
}

View File

@@ -77,6 +77,7 @@ export const useChatTest = ({
histories={chatRecords}
setHistories={setChatRecords}
appId={appDetail._id}
chatConfig={appDetail.chatConfig}
tab={pluginRunTab}
setTab={setPluginRunTab}
onNewChat={clearChatRecords}

View File

@@ -240,6 +240,7 @@ const Chat = ({
histories={chatRecords}
setHistories={setChatRecords}
appId={chatData.appId}
chatConfig={chatData.app.chatConfig}
tab={pluginRunTab}
setTab={setPluginRunTab}
onNewChat={() => onChangeChatId(getNanoid())}

View File

@@ -260,6 +260,7 @@ export const checkWorkflowNodeAndConnection = ({
if (
data.flowNodeType === FlowNodeTypeEnum.systemConfig ||
data.flowNodeType === FlowNodeTypeEnum.pluginConfig ||
data.flowNodeType === FlowNodeTypeEnum.pluginInput ||
data.flowNodeType === FlowNodeTypeEnum.workflowStart
) {
@@ -554,7 +555,8 @@ export const compareSnapshot = (
whisperConfig: clone1.chatConfig?.whisperConfig || undefined,
scheduledTriggerConfig: clone1.chatConfig?.scheduledTriggerConfig || undefined,
chatInputGuide: clone1.chatConfig?.chatInputGuide || undefined,
fileSelectConfig: clone1.chatConfig?.fileSelectConfig || undefined
fileSelectConfig: clone1.chatConfig?.fileSelectConfig || undefined,
instruction: clone1.chatConfig?.instruction || ''
},
{
welcomeText: clone2.chatConfig?.welcomeText || '',
@@ -564,7 +566,8 @@ export const compareSnapshot = (
whisperConfig: clone2.chatConfig?.whisperConfig || undefined,
scheduledTriggerConfig: clone2.chatConfig?.scheduledTriggerConfig || undefined,
chatInputGuide: clone2.chatConfig?.chatInputGuide || undefined,
fileSelectConfig: clone2.chatConfig?.fileSelectConfig || undefined
fileSelectConfig: clone2.chatConfig?.fileSelectConfig || undefined,
instruction: clone2.chatConfig?.instruction || ''
}
)
) {