mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-24 22:03:54 +00:00
feat: chat status
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
"Cancel": "No",
|
"Cancel": "No",
|
||||||
"Confirm": "Yes",
|
"Confirm": "Yes",
|
||||||
"Warning": "Warning",
|
"Warning": "Warning",
|
||||||
|
"Running": "Running",
|
||||||
"app": {
|
"app": {
|
||||||
"App Detail": "App Detail",
|
"App Detail": "App Detail",
|
||||||
"Confirm Del App Tip": "Confirm to delete the app and all its chats",
|
"Confirm Del App Tip": "Confirm to delete the app and all its chats",
|
||||||
|
@@ -3,6 +3,7 @@
|
|||||||
"Cancel": "取消",
|
"Cancel": "取消",
|
||||||
"Confirm": "确认",
|
"Confirm": "确认",
|
||||||
"Warning": "提示",
|
"Warning": "提示",
|
||||||
|
"Running": "运行中",
|
||||||
"app": {
|
"app": {
|
||||||
"App Detail": "应用详情",
|
"App Detail": "应用详情",
|
||||||
"Confirm Del App Tip": "确认删除该应用及其所有聊天记录?",
|
"Confirm Del App Tip": "确认删除该应用及其所有聊天记录?",
|
||||||
|
@@ -2,11 +2,12 @@ import { sseResponseEventEnum, TaskResponseKeyEnum } from '@/constants/chat';
|
|||||||
import { getErrText } from '@/utils/tools';
|
import { getErrText } from '@/utils/tools';
|
||||||
import { parseStreamChunk, SSEParseData } from '@/utils/sse';
|
import { parseStreamChunk, SSEParseData } from '@/utils/sse';
|
||||||
import type { ChatHistoryItemResType } from '@/types/chat';
|
import type { ChatHistoryItemResType } from '@/types/chat';
|
||||||
|
import { StartChatFnProps } from '@/components/ChatBox';
|
||||||
|
|
||||||
interface StreamFetchProps {
|
interface StreamFetchProps {
|
||||||
url?: string;
|
url?: string;
|
||||||
data: Record<string, any>;
|
data: Record<string, any>;
|
||||||
onMessage: (text: string) => void;
|
onMessage: StartChatFnProps['generatingMessage'];
|
||||||
abortSignal: AbortController;
|
abortSignal: AbortController;
|
||||||
}
|
}
|
||||||
export const streamFetch = ({
|
export const streamFetch = ({
|
||||||
@@ -71,8 +72,14 @@ export const streamFetch = ({
|
|||||||
|
|
||||||
if (eventName === sseResponseEventEnum.answer && data !== '[DONE]') {
|
if (eventName === sseResponseEventEnum.answer && data !== '[DONE]') {
|
||||||
const answer: string = data?.choices?.[0].delta.content || '';
|
const answer: string = data?.choices?.[0].delta.content || '';
|
||||||
onMessage(answer);
|
onMessage({ text: answer });
|
||||||
responseText += answer;
|
responseText += answer;
|
||||||
|
} else if (
|
||||||
|
eventName === sseResponseEventEnum.moduleStatus &&
|
||||||
|
data?.name &&
|
||||||
|
data?.status
|
||||||
|
) {
|
||||||
|
onMessage(data);
|
||||||
} else if (
|
} else if (
|
||||||
eventName === sseResponseEventEnum.appStreamResponse &&
|
eventName === sseResponseEventEnum.appStreamResponse &&
|
||||||
Array.isArray(data)
|
Array.isArray(data)
|
||||||
|
@@ -28,3 +28,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.statusAnimation {
|
||||||
|
animation: statusBox 0.8s linear infinite alternate;
|
||||||
|
}
|
||||||
|
@keyframes statusBox {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0.11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -39,6 +39,7 @@ import { htmlTemplate } from '@/constants/common';
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useGlobalStore } from '@/store/global';
|
import { useGlobalStore } from '@/store/global';
|
||||||
import { TaskResponseKeyEnum, getDefaultChatVariables } from '@/constants/chat';
|
import { TaskResponseKeyEnum, getDefaultChatVariables } from '@/constants/chat';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
@@ -51,11 +52,12 @@ const ResponseDetailModal = dynamic(() => import('./ResponseDetailModal'));
|
|||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const textareaMinH = '22px';
|
const textareaMinH = '22px';
|
||||||
|
type generatingMessageProps = { text?: string; name?: string; status?: 'running' | 'finish' };
|
||||||
export type StartChatFnProps = {
|
export type StartChatFnProps = {
|
||||||
messages: MessageItemType[];
|
messages: MessageItemType[];
|
||||||
controller: AbortController;
|
controller: AbortController;
|
||||||
variables: Record<string, any>;
|
variables: Record<string, any>;
|
||||||
generatingMessage: (text: string) => void;
|
generatingMessage: (e: generatingMessageProps) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ComponentRef = {
|
export type ComponentRef = {
|
||||||
@@ -153,6 +155,7 @@ const ChatBox = (
|
|||||||
const ChatBoxRef = useRef<HTMLDivElement>(null);
|
const ChatBoxRef = useRef<HTMLDivElement>(null);
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { t } = useTranslation();
|
||||||
const { copyData } = useCopyData();
|
const { copyData } = useCopyData();
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
const { isPc } = useGlobalStore();
|
const { isPc } = useGlobalStore();
|
||||||
@@ -164,7 +167,9 @@ const ChatBox = (
|
|||||||
const [chatHistory, setChatHistory] = useState<ChatSiteItemType[]>([]);
|
const [chatHistory, setChatHistory] = useState<ChatSiteItemType[]>([]);
|
||||||
|
|
||||||
const isChatting = useMemo(
|
const isChatting = useMemo(
|
||||||
() => chatHistory[chatHistory.length - 1]?.status === 'loading',
|
() =>
|
||||||
|
chatHistory[chatHistory.length - 1] &&
|
||||||
|
chatHistory[chatHistory.length - 1]?.status !== 'finish',
|
||||||
[chatHistory]
|
[chatHistory]
|
||||||
);
|
);
|
||||||
const variableIsFinish = useMemo(() => {
|
const variableIsFinish = useMemo(() => {
|
||||||
@@ -209,13 +214,23 @@ const ChatBox = (
|
|||||||
);
|
);
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
const generatingMessage = useCallback(
|
const generatingMessage = useCallback(
|
||||||
(text: string) => {
|
({ text = '', status, name }: generatingMessageProps) => {
|
||||||
setChatHistory((state) =>
|
setChatHistory((state) =>
|
||||||
state.map((item, index) => {
|
state.map((item, index) => {
|
||||||
if (index !== state.length - 1) return item;
|
if (index !== state.length - 1) return item;
|
||||||
return {
|
return {
|
||||||
...item,
|
...item,
|
||||||
value: item.value + text
|
...(text
|
||||||
|
? {
|
||||||
|
value: item.value + text
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...(status && name
|
||||||
|
? {
|
||||||
|
status,
|
||||||
|
moduleName: name
|
||||||
|
}
|
||||||
|
: {})
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -418,6 +433,21 @@ const ChatBox = (
|
|||||||
!welcomeText,
|
!welcomeText,
|
||||||
[chatHistory.length, showEmptyIntro, variableModules, welcomeText]
|
[chatHistory.length, showEmptyIntro, variableModules, welcomeText]
|
||||||
);
|
);
|
||||||
|
const statusBoxData = useMemo(() => {
|
||||||
|
const colorMap = {
|
||||||
|
loading: '#67c13b',
|
||||||
|
running: '#67c13b',
|
||||||
|
finish: 'myBlue.600'
|
||||||
|
};
|
||||||
|
if (!isChatting) return;
|
||||||
|
const chatContent = chatHistory[chatHistory.length - 1];
|
||||||
|
if (!chatContent) return;
|
||||||
|
|
||||||
|
return {
|
||||||
|
bg: colorMap[chatContent.status] || colorMap.loading,
|
||||||
|
name: t(chatContent.moduleName || 'Running')
|
||||||
|
};
|
||||||
|
}, [chatHistory, isChatting, t]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
@@ -595,7 +625,7 @@ const ChatBox = (
|
|||||||
)}
|
)}
|
||||||
{item.obj === 'AI' && (
|
{item.obj === 'AI' && (
|
||||||
<>
|
<>
|
||||||
<Flex w={'100%'} alignItems={'center'}>
|
<Flex w={'100%'} alignItems={'flex-end'}>
|
||||||
<ChatAvatar src={appAvatar} type={'AI'} />
|
<ChatAvatar src={appAvatar} type={'AI'} />
|
||||||
<Flex {...controlContainerStyle} ml={3}>
|
<Flex {...controlContainerStyle} ml={3}>
|
||||||
<MyTooltip label={'复制'}>
|
<MyTooltip label={'复制'}>
|
||||||
@@ -635,6 +665,28 @@ const ChatBox = (
|
|||||||
</MyTooltip>
|
</MyTooltip>
|
||||||
)}
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
{statusBoxData && index === chatHistory.length - 1 && (
|
||||||
|
<Flex
|
||||||
|
ml={3}
|
||||||
|
alignItems={'center'}
|
||||||
|
px={3}
|
||||||
|
py={'1px'}
|
||||||
|
borderRadius="md"
|
||||||
|
border={theme.borders.base}
|
||||||
|
>
|
||||||
|
<Box
|
||||||
|
className={styles.statusAnimation}
|
||||||
|
bg={statusBoxData.bg}
|
||||||
|
w="8px"
|
||||||
|
h="8px"
|
||||||
|
borderRadius={'50%'}
|
||||||
|
mt={'1px'}
|
||||||
|
></Box>
|
||||||
|
<Box ml={2} color={'myGray.600'}>
|
||||||
|
{statusBoxData.name}
|
||||||
|
</Box>
|
||||||
|
</Flex>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box position={'relative'} maxW={messageCardMaxW} mt={['6px', 2]}>
|
<Box position={'relative'} maxW={messageCardMaxW} mt={['6px', 2]}>
|
||||||
<Card bg={'white'} {...MessageCardStyle}>
|
<Card bg={'white'} {...MessageCardStyle}>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import React, { useMemo, useRef } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import ReactMarkdown from 'react-markdown';
|
import ReactMarkdown from 'react-markdown';
|
||||||
import RemarkGfm from 'remark-gfm';
|
import RemarkGfm from 'remark-gfm';
|
||||||
import RemarkMath from 'remark-math';
|
import RemarkMath from 'remark-math';
|
||||||
|
@@ -3,9 +3,8 @@ import dayjs from 'dayjs';
|
|||||||
export enum sseResponseEventEnum {
|
export enum sseResponseEventEnum {
|
||||||
error = 'error',
|
error = 'error',
|
||||||
answer = 'answer',
|
answer = 'answer',
|
||||||
chatResponse = 'chatResponse', //
|
moduleStatus = 'moduleStatus',
|
||||||
appStreamResponse = 'appStreamResponse', // sse response request
|
appStreamResponse = 'appStreamResponse' // sse response request
|
||||||
moduleFetchResponse = 'moduleFetchResponse' // http module sse response
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ChatRoleEnum {
|
export enum ChatRoleEnum {
|
||||||
|
@@ -114,6 +114,7 @@ export const ChatModule: FlowModuleTemplateType = {
|
|||||||
name: 'AI 对话',
|
name: 'AI 对话',
|
||||||
intro: 'AI 大模型对话',
|
intro: 'AI 大模型对话',
|
||||||
flowType: FlowModuleTypeEnum.chatNode,
|
flowType: FlowModuleTypeEnum.chatNode,
|
||||||
|
showStatus: true,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
key: 'model',
|
key: 'model',
|
||||||
@@ -203,6 +204,7 @@ export const KBSearchModule: FlowModuleTemplateType = {
|
|||||||
name: '知识库搜索',
|
name: '知识库搜索',
|
||||||
intro: '去知识库中搜索对应的答案。可作为 AI 对话引用参考。',
|
intro: '去知识库中搜索对应的答案。可作为 AI 对话引用参考。',
|
||||||
flowType: FlowModuleTypeEnum.kbSearchNode,
|
flowType: FlowModuleTypeEnum.kbSearchNode,
|
||||||
|
showStatus: true,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
key: 'kbList',
|
key: 'kbList',
|
||||||
@@ -321,6 +323,7 @@ export const ClassifyQuestionModule: FlowModuleTemplateType = {
|
|||||||
description:
|
description:
|
||||||
'根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于 laf 通用问题\n类型3: 关于 laf 代码问题\n类型4: 其他问题',
|
'根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于 laf 通用问题\n类型3: 关于 laf 代码问题\n类型4: 其他问题',
|
||||||
flowType: FlowModuleTypeEnum.classifyQuestion,
|
flowType: FlowModuleTypeEnum.classifyQuestion,
|
||||||
|
showStatus: true,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
key: 'systemPrompt',
|
key: 'systemPrompt',
|
||||||
@@ -381,6 +384,7 @@ export const ContextExtractModule: FlowModuleTemplateType = {
|
|||||||
intro: '从文本中提取出指定格式的数据',
|
intro: '从文本中提取出指定格式的数据',
|
||||||
description: '可从文本中提取指定的数据,例如:sql语句、搜索关键词、代码等',
|
description: '可从文本中提取指定的数据,例如:sql语句、搜索关键词、代码等',
|
||||||
flowType: FlowModuleTypeEnum.contentExtract,
|
flowType: FlowModuleTypeEnum.contentExtract,
|
||||||
|
showStatus: true,
|
||||||
inputs: [
|
inputs: [
|
||||||
Input_Template_TFSwitch,
|
Input_Template_TFSwitch,
|
||||||
{
|
{
|
||||||
@@ -441,6 +445,7 @@ export const HttpModule: FlowModuleTemplateType = {
|
|||||||
intro: '可以发出一个 HTTP POST 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
|
intro: '可以发出一个 HTTP POST 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
|
||||||
description: '可以发出一个 HTTP POST 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
|
description: '可以发出一个 HTTP POST 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
|
||||||
flowType: FlowModuleTypeEnum.httpRequest,
|
flowType: FlowModuleTypeEnum.httpRequest,
|
||||||
|
showStatus: true,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
key: HttpPropsEnum.url,
|
key: HttpPropsEnum.url,
|
||||||
@@ -507,10 +512,11 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
modules: [
|
modules: [
|
||||||
{
|
{
|
||||||
moduleId: 'userChatInput',
|
moduleId: 'userChatInput',
|
||||||
|
name: '用户问题(对话入口)',
|
||||||
flowType: 'questionInput',
|
flowType: 'questionInput',
|
||||||
position: {
|
position: {
|
||||||
x: 506.7143912167368,
|
x: 464.32198615344566,
|
||||||
y: 1601.0230108651226
|
y: 1602.2698463081606
|
||||||
},
|
},
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -537,6 +543,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'history',
|
moduleId: 'history',
|
||||||
|
name: '聊天记录',
|
||||||
flowType: 'historyNode',
|
flowType: 'historyNode',
|
||||||
position: {
|
position: {
|
||||||
x: 452.5466249541586,
|
x: 452.5466249541586,
|
||||||
@@ -576,17 +583,19 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'chatModule',
|
moduleId: 'chatModule',
|
||||||
|
name: 'AI 对话',
|
||||||
flowType: 'chatNode',
|
flowType: 'chatNode',
|
||||||
|
showStatus: true,
|
||||||
position: {
|
position: {
|
||||||
x: 998.0312473867093,
|
x: 1150.8317145593148,
|
||||||
y: 803.8586941051353
|
y: 957.9676672880053
|
||||||
},
|
},
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
key: 'model',
|
key: 'model',
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
label: '对话模型',
|
label: '对话模型',
|
||||||
value: 'gpt-3.5-turbo',
|
value: 'gpt-3.5-turbo-16k',
|
||||||
list: [],
|
list: [],
|
||||||
connected: true
|
connected: true
|
||||||
},
|
},
|
||||||
@@ -614,9 +623,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
key: 'maxToken',
|
key: 'maxToken',
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
label: '回复上限',
|
label: '回复上限',
|
||||||
value: 2000,
|
value: 8000,
|
||||||
min: 100,
|
min: 100,
|
||||||
max: 4000,
|
max: 16000,
|
||||||
step: 50,
|
step: 50,
|
||||||
markList: [
|
markList: [
|
||||||
{
|
{
|
||||||
@@ -624,8 +633,8 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
value: 100
|
value: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '4000',
|
label: '16000',
|
||||||
value: 4000
|
value: 16000
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
connected: true
|
connected: true
|
||||||
@@ -712,6 +721,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
modules: [
|
modules: [
|
||||||
{
|
{
|
||||||
moduleId: 'userGuide',
|
moduleId: 'userGuide',
|
||||||
|
name: '用户引导',
|
||||||
flowType: 'userGuide',
|
flowType: 'userGuide',
|
||||||
position: {
|
position: {
|
||||||
x: 454.98510354678695,
|
x: 454.98510354678695,
|
||||||
@@ -730,6 +740,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'userChatInput',
|
moduleId: 'userChatInput',
|
||||||
|
name: '用户问题(对话入口)',
|
||||||
flowType: 'questionInput',
|
flowType: 'questionInput',
|
||||||
position: {
|
position: {
|
||||||
x: 464.32198615344566,
|
x: 464.32198615344566,
|
||||||
@@ -764,6 +775,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'history',
|
moduleId: 'history',
|
||||||
|
name: '聊天记录',
|
||||||
flowType: 'historyNode',
|
flowType: 'historyNode',
|
||||||
position: {
|
position: {
|
||||||
x: 452.5466249541586,
|
x: 452.5466249541586,
|
||||||
@@ -803,7 +815,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'kbSearch',
|
moduleId: 'kbSearch',
|
||||||
|
name: '知识库搜索',
|
||||||
flowType: 'kbSearchNode',
|
flowType: 'kbSearchNode',
|
||||||
|
showStatus: true,
|
||||||
position: {
|
position: {
|
||||||
x: 956.0838440206068,
|
x: 956.0838440206068,
|
||||||
y: 887.462827870246
|
y: 887.462827870246
|
||||||
@@ -916,7 +930,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'chatModule',
|
moduleId: 'chatModule',
|
||||||
|
name: 'AI 对话',
|
||||||
flowType: 'chatNode',
|
flowType: 'chatNode',
|
||||||
|
showStatus: true,
|
||||||
position: {
|
position: {
|
||||||
x: 1546.0823206390796,
|
x: 1546.0823206390796,
|
||||||
y: 1008.9827344021824
|
y: 1008.9827344021824
|
||||||
@@ -926,7 +942,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
key: 'model',
|
key: 'model',
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
label: '对话模型',
|
label: '对话模型',
|
||||||
value: 'gpt-3.5-turbo',
|
value: 'gpt-3.5-turbo-16k',
|
||||||
list: [],
|
list: [],
|
||||||
connected: true
|
connected: true
|
||||||
},
|
},
|
||||||
@@ -954,9 +970,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
key: 'maxToken',
|
key: 'maxToken',
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
label: '回复上限',
|
label: '回复上限',
|
||||||
value: 2000,
|
value: 8000,
|
||||||
min: 100,
|
min: 100,
|
||||||
max: 4000,
|
max: 16000,
|
||||||
step: 50,
|
step: 50,
|
||||||
markList: [
|
markList: [
|
||||||
{
|
{
|
||||||
@@ -964,8 +980,8 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
value: 100
|
value: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '4000',
|
label: '16000',
|
||||||
value: 4000
|
value: 16000
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
connected: true
|
connected: true
|
||||||
@@ -1044,6 +1060,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: '2752oj',
|
moduleId: '2752oj',
|
||||||
|
name: '指定回复',
|
||||||
flowType: 'answerNode',
|
flowType: 'answerNode',
|
||||||
position: {
|
position: {
|
||||||
x: 1542.9271243684725,
|
x: 1542.9271243684725,
|
||||||
@@ -1080,6 +1097,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
modules: [
|
modules: [
|
||||||
{
|
{
|
||||||
moduleId: 'userGuide',
|
moduleId: 'userGuide',
|
||||||
|
name: '用户引导',
|
||||||
flowType: 'userGuide',
|
flowType: 'userGuide',
|
||||||
position: {
|
position: {
|
||||||
x: 447.98520778293346,
|
x: 447.98520778293346,
|
||||||
@@ -1098,6 +1116,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'variable',
|
moduleId: 'variable',
|
||||||
|
name: '全局变量',
|
||||||
flowType: 'variable',
|
flowType: 'variable',
|
||||||
position: {
|
position: {
|
||||||
x: 444.0369195277651,
|
x: 444.0369195277651,
|
||||||
@@ -1146,6 +1165,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'userChatInput',
|
moduleId: 'userChatInput',
|
||||||
|
name: '用户问题(对话入口)',
|
||||||
flowType: 'questionInput',
|
flowType: 'questionInput',
|
||||||
position: {
|
position: {
|
||||||
x: 464.32198615344566,
|
x: 464.32198615344566,
|
||||||
@@ -1176,6 +1196,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'history',
|
moduleId: 'history',
|
||||||
|
name: '聊天记录',
|
||||||
flowType: 'historyNode',
|
flowType: 'historyNode',
|
||||||
position: {
|
position: {
|
||||||
x: 452.5466249541586,
|
x: 452.5466249541586,
|
||||||
@@ -1215,7 +1236,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'chatModule',
|
moduleId: 'chatModule',
|
||||||
|
name: 'AI 对话',
|
||||||
flowType: 'chatNode',
|
flowType: 'chatNode',
|
||||||
|
showStatus: true,
|
||||||
position: {
|
position: {
|
||||||
x: 981.9682828103937,
|
x: 981.9682828103937,
|
||||||
y: 890.014595014464
|
y: 890.014595014464
|
||||||
@@ -1225,7 +1248,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
key: 'model',
|
key: 'model',
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
label: '对话模型',
|
label: '对话模型',
|
||||||
value: 'gpt-3.5-turbo',
|
value: 'gpt-3.5-turbo-16k',
|
||||||
list: [],
|
list: [],
|
||||||
connected: true
|
connected: true
|
||||||
},
|
},
|
||||||
@@ -1253,9 +1276,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
key: 'maxToken',
|
key: 'maxToken',
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
label: '回复上限',
|
label: '回复上限',
|
||||||
value: 2000,
|
value: 8000,
|
||||||
min: 100,
|
min: 100,
|
||||||
max: 4000,
|
max: 16000,
|
||||||
step: 50,
|
step: 50,
|
||||||
markList: [
|
markList: [
|
||||||
{
|
{
|
||||||
@@ -1263,8 +1286,8 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
value: 100
|
value: 100
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: '4000',
|
label: '16000',
|
||||||
value: 4000
|
value: 16000
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
connected: true
|
connected: true
|
||||||
@@ -1351,6 +1374,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
modules: [
|
modules: [
|
||||||
{
|
{
|
||||||
moduleId: '7z5g5h',
|
moduleId: '7z5g5h',
|
||||||
|
name: '用户问题(对话入口)',
|
||||||
flowType: 'questionInput',
|
flowType: 'questionInput',
|
||||||
position: {
|
position: {
|
||||||
x: 198.56612928723575,
|
x: 198.56612928723575,
|
||||||
@@ -1389,6 +1413,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'xj0c9p',
|
moduleId: 'xj0c9p',
|
||||||
|
name: '聊天记录',
|
||||||
flowType: 'historyNode',
|
flowType: 'historyNode',
|
||||||
position: {
|
position: {
|
||||||
x: 194.99102398958047,
|
x: 194.99102398958047,
|
||||||
@@ -1428,7 +1453,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'remuj3',
|
moduleId: 'remuj3',
|
||||||
|
name: '问题分类',
|
||||||
flowType: 'classifyQuestion',
|
flowType: 'classifyQuestion',
|
||||||
|
showStatus: true,
|
||||||
position: {
|
position: {
|
||||||
x: 672.9092284362648,
|
x: 672.9092284362648,
|
||||||
y: 1077.557793775116
|
y: 1077.557793775116
|
||||||
@@ -1535,6 +1562,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'a99p6z',
|
moduleId: 'a99p6z',
|
||||||
|
name: '指定回复',
|
||||||
flowType: 'answerNode',
|
flowType: 'answerNode',
|
||||||
position: {
|
position: {
|
||||||
x: 1304.2886011902247,
|
x: 1304.2886011902247,
|
||||||
@@ -1563,6 +1591,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'iejcou',
|
moduleId: 'iejcou',
|
||||||
|
name: '指定回复',
|
||||||
flowType: 'answerNode',
|
flowType: 'answerNode',
|
||||||
position: {
|
position: {
|
||||||
x: 1294.2531189034548,
|
x: 1294.2531189034548,
|
||||||
@@ -1591,7 +1620,9 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'nlfwkc',
|
moduleId: 'nlfwkc',
|
||||||
|
name: 'AI 对话',
|
||||||
flowType: 'chatNode',
|
flowType: 'chatNode',
|
||||||
|
showStatus: true,
|
||||||
position: {
|
position: {
|
||||||
x: 1821.979893659983,
|
x: 1821.979893659983,
|
||||||
y: 1104.6583548423682
|
y: 1104.6583548423682
|
||||||
@@ -1720,6 +1751,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 's4v9su',
|
moduleId: 's4v9su',
|
||||||
|
name: '聊天记录',
|
||||||
flowType: 'historyNode',
|
flowType: 'historyNode',
|
||||||
position: {
|
position: {
|
||||||
x: 193.3803955457983,
|
x: 193.3803955457983,
|
||||||
@@ -1759,22 +1791,20 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'fljhzy',
|
moduleId: 'fljhzy',
|
||||||
|
name: '知识库搜索',
|
||||||
flowType: 'kbSearchNode',
|
flowType: 'kbSearchNode',
|
||||||
|
showStatus: true,
|
||||||
position: {
|
position: {
|
||||||
x: 1305.5374262228029,
|
x: 1305.5374262228029,
|
||||||
y: 1120.0404921820218
|
y: 1120.0404921820218
|
||||||
},
|
},
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
key: 'kbList',
|
|
||||||
type: 'custom',
|
type: 'custom',
|
||||||
label: '关联的知识库',
|
label: '关联的知识库',
|
||||||
value: [
|
|
||||||
{
|
|
||||||
kbId: '646627f4f7b896cfd8910e24'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
list: [],
|
list: [],
|
||||||
|
key: 'kbList',
|
||||||
|
value: [],
|
||||||
connected: true
|
connected: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1876,6 +1906,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'q9equb',
|
moduleId: 'q9equb',
|
||||||
|
name: '用户引导',
|
||||||
flowType: 'userGuide',
|
flowType: 'userGuide',
|
||||||
position: {
|
position: {
|
||||||
x: 191.4857498376603,
|
x: 191.4857498376603,
|
||||||
@@ -1895,6 +1926,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: 'tc90wz',
|
moduleId: 'tc90wz',
|
||||||
|
name: '指定回复',
|
||||||
flowType: 'answerNode',
|
flowType: 'answerNode',
|
||||||
position: {
|
position: {
|
||||||
x: 1828.4596416688908,
|
x: 1828.4596416688908,
|
||||||
@@ -1923,6 +1955,7 @@ export const appTemplates: (AppItemType & { avatar: string; intro: string })[] =
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
moduleId: '5v78ap',
|
moduleId: '5v78ap',
|
||||||
|
name: '指定回复',
|
||||||
flowType: 'answerNode',
|
flowType: 'answerNode',
|
||||||
position: {
|
position: {
|
||||||
x: 1294.814522053934,
|
x: 1294.814522053934,
|
||||||
|
@@ -116,10 +116,12 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建响应流
|
// 创建响应流
|
||||||
res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');
|
if (stream) {
|
||||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
res.setHeader('Content-Type', 'text/event-stream;charset=utf-8');
|
||||||
res.setHeader('X-Accel-Buffering', 'no');
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
res.setHeader('Cache-Control', 'no-cache, no-transform');
|
res.setHeader('X-Accel-Buffering', 'no');
|
||||||
|
res.setHeader('Cache-Control', 'no-cache, no-transform');
|
||||||
|
}
|
||||||
|
|
||||||
/* start process */
|
/* start process */
|
||||||
const { responseData, answerText } = await dispatchModules({
|
const { responseData, answerText } = await dispatchModules({
|
||||||
@@ -320,6 +322,14 @@ export async function dispatchModules({
|
|||||||
if (res.closed) return Promise.resolve();
|
if (res.closed) return Promise.resolve();
|
||||||
console.log('run=========', module.flowType);
|
console.log('run=========', module.flowType);
|
||||||
|
|
||||||
|
if (stream && module.showStatus) {
|
||||||
|
responseStatus({
|
||||||
|
res,
|
||||||
|
name: module.name,
|
||||||
|
status: 'running'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// get fetch params
|
// get fetch params
|
||||||
const params: Record<string, any> = {};
|
const params: Record<string, any> = {};
|
||||||
module.inputs.forEach((item: any) => {
|
module.inputs.forEach((item: any) => {
|
||||||
@@ -370,7 +380,9 @@ function loadModules(
|
|||||||
return modules.map((module) => {
|
return modules.map((module) => {
|
||||||
return {
|
return {
|
||||||
moduleId: module.moduleId,
|
moduleId: module.moduleId,
|
||||||
|
name: module.name,
|
||||||
flowType: module.flowType,
|
flowType: module.flowType,
|
||||||
|
showStatus: module.showStatus,
|
||||||
inputs: module.inputs
|
inputs: module.inputs
|
||||||
.filter((item) => item.connected) // filter unconnected target input
|
.filter((item) => item.connected) // filter unconnected target input
|
||||||
.map((item) => {
|
.map((item) => {
|
||||||
@@ -401,3 +413,23 @@ function loadModules(
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function responseStatus({
|
||||||
|
res,
|
||||||
|
status,
|
||||||
|
name
|
||||||
|
}: {
|
||||||
|
res: NextApiResponse;
|
||||||
|
status: 'running' | 'finish';
|
||||||
|
name?: string;
|
||||||
|
}) {
|
||||||
|
if (!name) return;
|
||||||
|
sseResponse({
|
||||||
|
res,
|
||||||
|
event: sseResponseEventEnum.moduleStatus,
|
||||||
|
data: JSON.stringify({
|
||||||
|
status,
|
||||||
|
name
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@@ -1,10 +1,9 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Box, Flex } from '@chakra-ui/react';
|
import { Box, Flex } from '@chakra-ui/react';
|
||||||
import { ModuleTemplates } from '@/constants/flow/ModuleTemplate';
|
import { ModuleTemplates } from '@/constants/flow/ModuleTemplate';
|
||||||
import { FlowModuleTemplateType } from '@/types/flow';
|
import { FlowModuleItemType, FlowModuleTemplateType } from '@/types/flow';
|
||||||
import type { Node, XYPosition } from 'reactflow';
|
import type { Node, XYPosition } from 'reactflow';
|
||||||
import { useGlobalStore } from '@/store/global';
|
import { useGlobalStore } from '@/store/global';
|
||||||
import type { AppModuleItemType } from '@/types/app';
|
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
import { FlowModuleTypeEnum } from '@/constants/flow';
|
import { FlowModuleTypeEnum } from '@/constants/flow';
|
||||||
|
|
||||||
@@ -14,7 +13,7 @@ const ModuleTemplateList = ({
|
|||||||
onAddNode,
|
onAddNode,
|
||||||
onClose
|
onClose
|
||||||
}: {
|
}: {
|
||||||
nodes?: Node<AppModuleItemType>[];
|
nodes?: Node<FlowModuleItemType>[];
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onAddNode: (e: { template: FlowModuleTemplateType; position: XYPosition }) => void;
|
onAddNode: (e: { template: FlowModuleTemplateType; position: XYPosition }) => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
@@ -158,7 +158,9 @@ const AppEdit = ({ app, fullScreen, onFullScreen }: Props) => {
|
|||||||
const flow2AppModules = useCallback(() => {
|
const flow2AppModules = useCallback(() => {
|
||||||
const modules: AppModuleItemType[] = nodes.map((item) => ({
|
const modules: AppModuleItemType[] = nodes.map((item) => ({
|
||||||
moduleId: item.data.moduleId,
|
moduleId: item.data.moduleId,
|
||||||
|
name: item.data.name,
|
||||||
flowType: item.data.flowType,
|
flowType: item.data.flowType,
|
||||||
|
showStatus: item.data.showStatus,
|
||||||
position: item.position,
|
position: item.position,
|
||||||
inputs: item.data.inputs.map((item) => ({
|
inputs: item.data.inputs.map((item) => ({
|
||||||
...item,
|
...item,
|
||||||
|
@@ -34,6 +34,9 @@ export async function dispatchContentExtract({
|
|||||||
history = [],
|
history = [],
|
||||||
description
|
description
|
||||||
}: Props): Promise<Response> {
|
}: Props): Promise<Response> {
|
||||||
|
if (!content) {
|
||||||
|
return Promise.reject('Input is empty');
|
||||||
|
}
|
||||||
const messages: ChatItemType[] = [
|
const messages: ChatItemType[] = [
|
||||||
...history,
|
...history,
|
||||||
{
|
{
|
||||||
|
9
client/src/types/app.d.ts
vendored
9
client/src/types/app.d.ts
vendored
@@ -69,9 +69,11 @@ export type VariableItemType = {
|
|||||||
|
|
||||||
/* app module */
|
/* app module */
|
||||||
export type AppModuleItemType = {
|
export type AppModuleItemType = {
|
||||||
|
name: string;
|
||||||
moduleId: string;
|
moduleId: string;
|
||||||
position?: XYPosition;
|
position?: XYPosition;
|
||||||
flowType: `${FlowModuleTypeEnum}`;
|
flowType: `${FlowModuleTypeEnum}`;
|
||||||
|
showStatus?: boolean;
|
||||||
inputs: FlowInputItemType[];
|
inputs: FlowInputItemType[];
|
||||||
outputs: FlowOutputItemType[];
|
outputs: FlowOutputItemType[];
|
||||||
};
|
};
|
||||||
@@ -83,8 +85,11 @@ export type AppItemType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type RunningModuleItemType = {
|
export type RunningModuleItemType = {
|
||||||
moduleId: string;
|
name: AppModuleItemType['name'];
|
||||||
flowType: `${FlowModuleTypeEnum}`;
|
moduleId: AppModuleItemType['moduleId'];
|
||||||
|
flowType: AppModuleItemType['flowType'];
|
||||||
|
showStatus?: AppModuleItemType['showStatus'];
|
||||||
|
} & {
|
||||||
inputs: {
|
inputs: {
|
||||||
key: string;
|
key: string;
|
||||||
value?: any;
|
value?: any;
|
||||||
|
3
client/src/types/chat.d.ts
vendored
3
client/src/types/chat.d.ts
vendored
@@ -13,7 +13,8 @@ export type ChatItemType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type ChatSiteItemType = {
|
export type ChatSiteItemType = {
|
||||||
status: 'loading' | 'finish';
|
status: 'loading' | 'running' | 'finish';
|
||||||
|
moduleName?: string;
|
||||||
} & ChatItemType;
|
} & ChatItemType;
|
||||||
|
|
||||||
export type HistoryItemType = {
|
export type HistoryItemType = {
|
||||||
|
1
client/src/types/flow.d.ts
vendored
1
client/src/types/flow.d.ts
vendored
@@ -55,6 +55,7 @@ export type FlowModuleTemplateType = {
|
|||||||
flowType: `${FlowModuleTypeEnum}`;
|
flowType: `${FlowModuleTypeEnum}`;
|
||||||
inputs: FlowInputItemType[];
|
inputs: FlowInputItemType[];
|
||||||
outputs: FlowOutputItemType[];
|
outputs: FlowOutputItemType[];
|
||||||
|
showStatus?: boolean;
|
||||||
};
|
};
|
||||||
export type FlowModuleItemType = FlowModuleTemplateType & {
|
export type FlowModuleItemType = FlowModuleTemplateType & {
|
||||||
moduleId: string;
|
moduleId: string;
|
||||||
|
@@ -219,6 +219,7 @@ const welcomeTemplate = (formData: EditFormType): AppModuleItemType[] =>
|
|||||||
formData.guide?.welcome?.text
|
formData.guide?.welcome?.text
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
|
name: '用户引导',
|
||||||
flowType: FlowModuleTypeEnum.userGuide,
|
flowType: FlowModuleTypeEnum.userGuide,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -242,6 +243,7 @@ const variableTemplate = (formData: EditFormType): AppModuleItemType[] =>
|
|||||||
formData.variables.length > 0
|
formData.variables.length > 0
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
|
name: '全局变量',
|
||||||
flowType: FlowModuleTypeEnum.variable,
|
flowType: FlowModuleTypeEnum.variable,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -263,6 +265,7 @@ const variableTemplate = (formData: EditFormType): AppModuleItemType[] =>
|
|||||||
: [];
|
: [];
|
||||||
const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
||||||
{
|
{
|
||||||
|
name: '用户问题(对话入口)',
|
||||||
flowType: FlowModuleTypeEnum.questionInput,
|
flowType: FlowModuleTypeEnum.questionInput,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -290,6 +293,7 @@ const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
|||||||
moduleId: 'userChatInput'
|
moduleId: 'userChatInput'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: '聊天记录',
|
||||||
flowType: FlowModuleTypeEnum.historyNode,
|
flowType: FlowModuleTypeEnum.historyNode,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -324,6 +328,7 @@ const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
|||||||
moduleId: 'history'
|
moduleId: 'history'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: 'AI 对话',
|
||||||
flowType: FlowModuleTypeEnum.chatNode,
|
flowType: FlowModuleTypeEnum.chatNode,
|
||||||
inputs: chatModelInput(formData),
|
inputs: chatModelInput(formData),
|
||||||
outputs: [
|
outputs: [
|
||||||
@@ -352,6 +357,7 @@ const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
|||||||
];
|
];
|
||||||
const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
||||||
{
|
{
|
||||||
|
name: '用户问题(对话入口)',
|
||||||
flowType: FlowModuleTypeEnum.questionInput,
|
flowType: FlowModuleTypeEnum.questionInput,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -383,6 +389,7 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
|||||||
moduleId: 'userChatInput'
|
moduleId: 'userChatInput'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: '聊天记录',
|
||||||
flowType: FlowModuleTypeEnum.historyNode,
|
flowType: FlowModuleTypeEnum.historyNode,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -417,6 +424,7 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
|||||||
moduleId: 'history'
|
moduleId: 'history'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
name: '知识库搜索',
|
||||||
flowType: FlowModuleTypeEnum.kbSearchNode,
|
flowType: FlowModuleTypeEnum.kbSearchNode,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -498,6 +506,7 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
|||||||
...(formData.kb.searchEmptyText
|
...(formData.kb.searchEmptyText
|
||||||
? [
|
? [
|
||||||
{
|
{
|
||||||
|
name: '指定回复',
|
||||||
flowType: FlowModuleTypeEnum.answerNode,
|
flowType: FlowModuleTypeEnum.answerNode,
|
||||||
inputs: [
|
inputs: [
|
||||||
{
|
{
|
||||||
@@ -525,6 +534,7 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
|||||||
]
|
]
|
||||||
: []),
|
: []),
|
||||||
{
|
{
|
||||||
|
name: 'AI 对话',
|
||||||
flowType: FlowModuleTypeEnum.chatNode,
|
flowType: FlowModuleTypeEnum.chatNode,
|
||||||
inputs: chatModelInput(formData),
|
inputs: chatModelInput(formData),
|
||||||
outputs: [
|
outputs: [
|
||||||
|
Reference in New Issue
Block a user