diff --git a/client/public/imgs/loading.gif b/client/public/imgs/loading.gif
deleted file mode 100644
index e5e62462d..000000000
Binary files a/client/public/imgs/loading.gif and /dev/null differ
diff --git a/client/public/imgs/modelAvatar.png b/client/public/imgs/modelAvatar.png
deleted file mode 100644
index 58cf2b218..000000000
Binary files a/client/public/imgs/modelAvatar.png and /dev/null differ
diff --git a/client/public/imgs/module/AI.png b/client/public/imgs/module/AI.png
new file mode 100644
index 000000000..800ee763c
Binary files /dev/null and b/client/public/imgs/module/AI.png differ
diff --git a/client/public/imgs/module/cq.png b/client/public/imgs/module/cq.png
new file mode 100644
index 000000000..9101f3880
Binary files /dev/null and b/client/public/imgs/module/cq.png differ
diff --git a/client/public/imgs/module/db.png b/client/public/imgs/module/db.png
new file mode 100644
index 000000000..4c048f896
Binary files /dev/null and b/client/public/imgs/module/db.png differ
diff --git a/client/public/imgs/module/history.png b/client/public/imgs/module/history.png
new file mode 100644
index 000000000..3fd4b5140
Binary files /dev/null and b/client/public/imgs/module/history.png differ
diff --git a/client/public/imgs/module/reply.png b/client/public/imgs/module/reply.png
new file mode 100644
index 000000000..bb8ed28f8
Binary files /dev/null and b/client/public/imgs/module/reply.png differ
diff --git a/client/public/imgs/module/userChatInput.png b/client/public/imgs/module/userChatInput.png
new file mode 100644
index 000000000..8eaf9a66a
Binary files /dev/null and b/client/public/imgs/module/userChatInput.png differ
diff --git a/client/src/components/Icon/icons/minus.svg b/client/src/components/Icon/icons/minus.svg
new file mode 100644
index 000000000..3dccbb1a0
--- /dev/null
+++ b/client/src/components/Icon/icons/minus.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/src/components/Icon/index.tsx b/client/src/components/Icon/index.tsx
index 4ef827685..62d4b9c40 100644
--- a/client/src/components/Icon/index.tsx
+++ b/client/src/components/Icon/index.tsx
@@ -35,7 +35,8 @@ const map = {
kbTest: require('./icons/kbTest.svg').default,
date: require('./icons/date.svg').default,
apikey: require('./icons/apikey.svg').default,
- save: require('./icons/save.svg').default
+ save: require('./icons/save.svg').default,
+ minus: require('./icons/minus.svg').default
};
export type IconName = keyof typeof map;
diff --git a/client/src/components/Layout/navbar.tsx b/client/src/components/Layout/navbar.tsx
index 45b335e75..f36764e4f 100644
--- a/client/src/components/Layout/navbar.tsx
+++ b/client/src/components/Layout/navbar.tsx
@@ -1,5 +1,5 @@
import React, { useMemo } from 'react';
-import { Box, Flex, Tooltip, Link } from '@chakra-ui/react';
+import { Box, Flex, Link } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import MyIcon from '../Icon';
import { useUserStore } from '@/store/user';
diff --git a/client/src/components/Markdown/img/Loading.tsx b/client/src/components/Markdown/img/Loading.tsx
deleted file mode 100644
index 4e454a1d9..000000000
--- a/client/src/components/Markdown/img/Loading.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React, { memo } from 'react';
-import { Box } from '@chakra-ui/react';
-
-const Loading = ({ text }: { text?: string }) => {
- return (
-
-
- {text && (
-
- {text}
-
- )}
-
- );
-};
-
-export default memo(Loading);
diff --git a/client/src/components/MyTooltip/index.tsx b/client/src/components/MyTooltip/index.tsx
new file mode 100644
index 000000000..d51261c56
--- /dev/null
+++ b/client/src/components/MyTooltip/index.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { Tooltip, TooltipProps } from '@chakra-ui/react';
+
+const MyTooltip = ({ children, ...props }: TooltipProps) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export default MyTooltip;
diff --git a/client/src/constants/app.ts b/client/src/constants/app.ts
index 007d01c34..aed39f7bf 100644
--- a/client/src/constants/app.ts
+++ b/client/src/constants/app.ts
@@ -155,145 +155,145 @@ export const chatAppDemo: AppItemType = {
modules: [chatModule({ id: 'chat' })]
};
-export const kbChatAppDemo: AppItemType = {
- id: 'kbchat',
- name: 'kbchat',
- // 标记字段
- modules: [
- {
- moduleId: 'kbsearch',
- flowType: FlowModuleTypeEnum.kbSearchNode,
- type: AppModuleItemTypeEnum.http,
- url: '/openapi/modules/kb/search',
- position: { x: -500, y: 0 },
- inputs: [
- {
- key: 'kb_ids',
- type: FlowInputItemTypeEnum.custom,
- label: '关联的知识库',
- value: ['646627f4f7b896cfd8910e38'],
- list: []
- },
+// export const kbChatAppDemo: AppItemType = {
+// id: 'kbchat',
+// name: 'kbchat',
+// // 标记字段
+// modules: [
+// {
+// moduleId: 'kbsearch',
+// flowType: FlowModuleTypeEnum.kbSearchNode,
+// type: AppModuleItemTypeEnum.http,
+// url: '/openapi/modules/kb/search',
+// position: { x: -500, y: 0 },
+// inputs: [
+// {
+// key: 'kb_ids',
+// type: FlowInputItemTypeEnum.custom,
+// label: '关联的知识库',
+// value: ['646627f4f7b896cfd8910e38'],
+// list: []
+// },
- {
- key: 'similarity',
- type: FlowInputItemTypeEnum.slider,
- label: '相似度',
- value: 0.8,
- min: 0,
- max: 1,
- step: 0.01,
- markList: [
- { label: '0', value: 0 },
- { label: '1', value: 1 }
- ]
- },
- {
- key: 'limit',
- type: FlowInputItemTypeEnum.slider,
- label: '单次搜索上限',
- value: 5,
- min: 1,
- max: 20,
- step: 1,
- markList: [
- { label: '1', value: 1 },
- { label: '20', value: 20 }
- ]
- },
- {
- key: SystemInputEnum.history,
- type: FlowInputItemTypeEnum.hidden,
- label: '引用复用数量',
- value: 1
- },
- {
- key: SystemInputEnum.userChatInput,
- type: FlowInputItemTypeEnum.none,
- label: '用户输入(系统自动填写)',
- description: ''
- }
- ],
- outputs: [
- {
- key: 'rawSearch',
- label: '源搜索数据',
- type: FlowOutputItemTypeEnum.none,
- response: true,
- targets: []
- },
- {
- key: 'isEmpty',
- label: '无搜索结果',
- type: FlowOutputItemTypeEnum.source,
- targets: [
- {
- moduleId: 'tfswitch',
- key: SystemInputEnum.switch
- }
- ]
- },
- {
- key: 'quotePrompt',
- label: '引用内容(字符串)',
- type: FlowOutputItemTypeEnum.source,
- targets: [
- {
- moduleId: 'chat',
- key: 'quotePrompt'
- }
- ]
- }
- ]
- },
- {
- moduleId: 'tfswitch',
- type: AppModuleItemTypeEnum.switch,
- flowType: FlowModuleTypeEnum.tfSwitchNode,
- position: { x: 0, y: 510 },
- inputs: [
- {
- key: SystemInputEnum.switch,
- type: FlowInputItemTypeEnum.target,
- label: '触发器',
- connected: true
- }
- ],
- outputs: [
- {
- key: 'true',
- label: '无搜索数据',
- type: FlowOutputItemTypeEnum.source,
- targets: [
- {
- moduleId: 'answer',
- key: SystemInputEnum.switch
- }
- ]
- },
- {
- key: 'false',
- label: '有搜索数据',
- type: FlowOutputItemTypeEnum.source,
- targets: [
- {
- moduleId: 'chat',
- key: SystemInputEnum.switch
- }
- ]
- }
- ]
- },
- {
- ...chatModule({ id: 'chat', limitPrompt: '参考知识库内容进行回答', history: 5 }),
- position: { x: 300, y: 240 }
- },
- {
- ...answerModule({ id: 'answer' }),
- position: { x: 300, y: 0 }
- }
- ]
-};
+// {
+// key: 'similarity',
+// type: FlowInputItemTypeEnum.slider,
+// label: '相似度',
+// value: 0.8,
+// min: 0,
+// max: 1,
+// step: 0.01,
+// markList: [
+// { label: '0', value: 0 },
+// { label: '1', value: 1 }
+// ]
+// },
+// {
+// key: 'limit',
+// type: FlowInputItemTypeEnum.slider,
+// label: '单次搜索上限',
+// value: 5,
+// min: 1,
+// max: 20,
+// step: 1,
+// markList: [
+// { label: '1', value: 1 },
+// { label: '20', value: 20 }
+// ]
+// },
+// {
+// key: SystemInputEnum.history,
+// type: FlowInputItemTypeEnum.hidden,
+// label: '引用复用数量',
+// value: 1
+// },
+// {
+// key: SystemInputEnum.userChatInput,
+// type: FlowInputItemTypeEnum.none,
+// label: '用户输入(系统自动填写)',
+// description: ''
+// }
+// ],
+// outputs: [
+// {
+// key: 'rawSearch',
+// label: '源搜索数据',
+// type: FlowOutputItemTypeEnum.none,
+// response: true,
+// targets: []
+// },
+// {
+// key: 'isEmpty',
+// label: '无搜索结果',
+// type: FlowOutputItemTypeEnum.source,
+// targets: [
+// {
+// moduleId: 'tfswitch',
+// key: SystemInputEnum.switch
+// }
+// ]
+// },
+// {
+// key: 'quotePrompt',
+// label: '引用内容(字符串)',
+// type: FlowOutputItemTypeEnum.source,
+// targets: [
+// {
+// moduleId: 'chat',
+// key: 'quotePrompt'
+// }
+// ]
+// }
+// ]
+// },
+// {
+// moduleId: 'tfswitch',
+// type: AppModuleItemTypeEnum.switch,
+// flowType: FlowModuleTypeEnum.tfSwitchNode,
+// position: { x: 0, y: 510 },
+// inputs: [
+// {
+// key: SystemInputEnum.switch,
+// type: FlowInputItemTypeEnum.target,
+// label: '触发器',
+// connected: true
+// }
+// ],
+// outputs: [
+// {
+// key: 'true',
+// label: '无搜索数据',
+// type: FlowOutputItemTypeEnum.source,
+// targets: [
+// {
+// moduleId: 'answer',
+// key: SystemInputEnum.switch
+// }
+// ]
+// },
+// {
+// key: 'false',
+// label: '有搜索数据',
+// type: FlowOutputItemTypeEnum.source,
+// targets: [
+// {
+// moduleId: 'chat',
+// key: SystemInputEnum.switch
+// }
+// ]
+// }
+// ]
+// },
+// {
+// ...chatModule({ id: 'chat', limitPrompt: '参考知识库内容进行回答', history: 5 }),
+// position: { x: 300, y: 240 }
+// },
+// {
+// ...answerModule({ id: 'answer' }),
+// position: { x: 300, y: 0 }
+// }
+// ]
+// };
// export const classifyQuestionDemo: AppItemType = {
// id: 'classifyQuestionDemo',
diff --git a/client/src/constants/chat.ts b/client/src/constants/chat.ts
index f51641db5..f1bc61234 100644
--- a/client/src/constants/chat.ts
+++ b/client/src/constants/chat.ts
@@ -25,4 +25,4 @@ export const ChatRoleMap = {
};
export const HUMAN_ICON = `https://fastgpt.run/icon/human.png`;
-export const LOGO_ICON = `https://fastgpt.run/imgs/modelAvatar.png`;
+export const LOGO_ICON = `https://fastgpt.run/icon/logo.png`;
diff --git a/client/src/constants/flow/ModuleTemplate.ts b/client/src/constants/flow/ModuleTemplate.ts
index 42d5d70cd..ee102433b 100644
--- a/client/src/constants/flow/ModuleTemplate.ts
+++ b/client/src/constants/flow/ModuleTemplate.ts
@@ -1,4 +1,4 @@
-import { AppModuleItemTypeEnum, SystemInputEnum } from '../app';
+import { AppModuleItemTypeEnum, SystemInputEnum, SpecificInputEnum } from '../app';
import { FlowModuleTypeEnum, FlowInputItemTypeEnum, FlowOutputItemTypeEnum } from './index';
import type { AppModuleTemplateItemType } from '@/types/app';
import { chatModelList } from '../data';
@@ -9,7 +9,7 @@ import {
} from './inputTemplate';
export const UserInputModule: AppModuleTemplateItemType = {
- logo: '',
+ logo: '/imgs/module/userChatInput.png',
name: '用户问题',
intro: '用户输入的内容。该模块通常作为应用的入口,用户在发送消息后会首先执行该模块。',
type: AppModuleItemTypeEnum.initInput,
@@ -32,7 +32,7 @@ export const UserInputModule: AppModuleTemplateItemType = {
]
};
export const HistoryModule: AppModuleTemplateItemType = {
- logo: '',
+ logo: '/imgs/module/history.png',
name: '聊天记录',
intro: '用户输入的内容。该模块通常作为应用的入口,用户在发送消息后会首先执行该模块。',
type: AppModuleItemTypeEnum.initInput,
@@ -64,7 +64,7 @@ export const HistoryModule: AppModuleTemplateItemType = {
};
export const ChatModule: AppModuleTemplateItemType = {
- logo: '',
+ logo: '/imgs/module/AI.png',
name: 'AI 对话',
intro: 'OpenAI GPT 大模型对话。',
flowType: FlowModuleTypeEnum.chatNode,
@@ -135,7 +135,7 @@ export const ChatModule: AppModuleTemplateItemType = {
],
outputs: [
{
- key: 'answer',
+ key: SpecificInputEnum.answerText,
label: '模型回复',
description: '直接响应,无需配置',
type: FlowOutputItemTypeEnum.hidden,
@@ -145,7 +145,7 @@ export const ChatModule: AppModuleTemplateItemType = {
};
export const KBSearchModule: AppModuleTemplateItemType = {
- logo: '',
+ logo: '/imgs/module/db.png',
name: '知识库搜索',
intro: '去知识库中搜索对应的答案。可作为 AI 对话引用参考。',
flowType: FlowModuleTypeEnum.kbSearchNode,
@@ -205,7 +205,7 @@ export const KBSearchModule: AppModuleTemplateItemType = {
{
key: 'quotePrompt',
label: '引用内容',
- description: '搜索结果为空时不触发',
+ description: '搜索结果为空时不返回',
type: FlowOutputItemTypeEnum.source,
targets: []
}
@@ -213,7 +213,7 @@ export const KBSearchModule: AppModuleTemplateItemType = {
};
export const AnswerModule: AppModuleTemplateItemType = {
- logo: '',
+ logo: '/imgs/module/reply.png',
name: '指定回复',
intro: '该模块可以直接回复一段指定的内容。常用于引导、提示。',
type: AppModuleItemTypeEnum.answer,
@@ -221,7 +221,7 @@ export const AnswerModule: AppModuleTemplateItemType = {
inputs: [
Input_Template_TFSwitch,
{
- key: 'answerText',
+ key: SpecificInputEnum.answerText,
value: '',
type: FlowInputItemTypeEnum.input,
label: '回复的内容'
@@ -257,31 +257,52 @@ export const TFSwitchModule: AppModuleTemplateItemType = {
}
]
};
-
export const ClassifyQuestionModule: AppModuleTemplateItemType = {
- logo: '',
+ logo: '/imgs/module/cq.png',
name: '意图识别',
intro: '可以判断用户问题属于哪方面问题,从而执行不同的操作。',
- type: AppModuleItemTypeEnum.switch,
- flowType: FlowModuleTypeEnum.tfSwitchNode,
+ type: AppModuleItemTypeEnum.http,
+ url: '/openapi/modules/agent/classifyQuestion',
+ flowType: FlowModuleTypeEnum.classifyQuestionNode,
inputs: [
{
- key: SystemInputEnum.switch,
- type: FlowInputItemTypeEnum.target,
- label: '输入'
+ key: 'systemPrompt',
+ type: FlowInputItemTypeEnum.textarea,
+ label: '系统提示词',
+ description:
+ '你可以添加一些特定内容的介绍,从而更好的识别用户的问题类型。这个内容通常是给模型介绍一个它不知道的内容。',
+ placeholder: '例如: \n1. Laf 是一个云函数开发平台……\n2. Sealos 是一个集群操作系统',
+ value: ''
+ },
+ Input_Template_History,
+ Input_Template_UserChatInput,
+ {
+ key: 'agents',
+ type: FlowInputItemTypeEnum.custom,
+ label: '',
+ value: [
+ {
+ value: '',
+ key: 'a'
+ },
+ {
+ value: '',
+ key: 'b'
+ }
+ ]
}
],
outputs: [
{
- key: 'true',
- label: 'True',
- type: FlowOutputItemTypeEnum.source,
+ key: 'a',
+ label: '',
+ type: FlowOutputItemTypeEnum.hidden,
targets: []
},
{
- key: 'false',
- label: 'False',
- type: FlowOutputItemTypeEnum.source,
+ key: 'b',
+ label: '',
+ type: FlowOutputItemTypeEnum.hidden,
targets: []
}
]
@@ -302,7 +323,7 @@ export const ModuleTemplates = [
},
{
label: '工具',
- list: [AnswerModule, TFSwitchModule]
+ list: [AnswerModule]
},
{
label: 'Agent',
diff --git a/client/src/constants/flow/index.ts b/client/src/constants/flow/index.ts
index db6e6c6f8..5184e713f 100644
--- a/client/src/constants/flow/index.ts
+++ b/client/src/constants/flow/index.ts
@@ -24,7 +24,8 @@ export enum FlowModuleTypeEnum {
chatNode = 'chatNode',
kbSearchNode = 'kbSearchNode',
tfSwitchNode = 'tfSwitchNode',
- answerNode = 'answerNode'
+ answerNode = 'answerNode',
+ classifyQuestionNode = 'classifyQuestionNode'
}
export const edgeOptions = {
diff --git a/client/src/constants/theme.ts b/client/src/constants/theme.ts
index f98ae0026..99c06f554 100644
--- a/client/src/constants/theme.ts
+++ b/client/src/constants/theme.ts
@@ -202,6 +202,16 @@ const Select = selectMultiStyle({
}
});
+const Tooltip = defineStyleConfig({
+ baseStyle: {
+ p: 3,
+ bg: 'white',
+ color: 'blackAlpha.800',
+ borderRadius: '8px',
+ boxShadow: '1px 1px 10px rgba(0,0,0,0.2)'
+ }
+});
+
// 全局主题
export const theme = extendTheme({
styles: {
@@ -297,6 +307,7 @@ export const theme = extendTheme({
Textarea,
Switch,
Select,
+ Tooltip,
NumberInput
}
});
diff --git a/client/src/pages/api/openapi/modules/agent/classifyQuestion.ts b/client/src/pages/api/openapi/modules/agent/classifyQuestion.ts
index 330bb1a30..9c5af1e8b 100644
--- a/client/src/pages/api/openapi/modules/agent/classifyQuestion.ts
+++ b/client/src/pages/api/openapi/modules/agent/classifyQuestion.ts
@@ -79,7 +79,7 @@ export async function classifyQuestion({
properties: {
type: {
type: 'string',
- description: agents.map((item) => `${item.desc},返回: '${item.key}'`).join('; '),
+ description: agents.map((item) => `${item.value},返回: '${item.key}'`).join('; '),
enum: agents.map((item) => item.key)
}
},
@@ -106,7 +106,10 @@ export async function classifyQuestion({
if (!arg.type) {
throw new Error('');
}
- console.log(arg.type);
+ console.log(
+ '意图结果',
+ agents.findIndex((item) => item.key === arg.type)
+ );
return {
[arg.type]: 1
diff --git a/client/src/pages/api/openapi/modules/chat/gpt.ts b/client/src/pages/api/openapi/modules/chat/gpt.ts
index eb5ccee70..3cc3eebb8 100644
--- a/client/src/pages/api/openapi/modules/chat/gpt.ts
+++ b/client/src/pages/api/openapi/modules/chat/gpt.ts
@@ -10,6 +10,7 @@ import type { ChatItemType } from '@/types/chat';
import { ChatRoleEnum, sseResponseEventEnum } from '@/constants/chat';
import { parseStreamChunk, textAdaptGptResponse } from '@/utils/adapt';
import { getOpenAIApi, axiosConfig } from '@/service/ai/openai';
+import { SpecificInputEnum } from '@/constants/app';
export type Props = {
model: `${OpenAiChatEnum}`;
@@ -22,7 +23,7 @@ export type Props = {
systemPrompt?: string;
limitPrompt?: string;
};
-export type Response = { answer: string };
+export type Response = { [SpecificInputEnum.answerText]: string };
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -132,7 +133,8 @@ export async function chatCompletion({
const chatAPI = getOpenAIApi();
/* count response max token */
- const promptsToken = modelToolMap[model].countTokens({
+ const promptsToken = modelToolMap.countTokens({
+ model,
messages: filterMessages
});
maxToken = maxToken + promptsToken > modelTokenLimit ? modelTokenLimit - promptsToken : maxToken;
@@ -143,8 +145,8 @@ export async function chatCompletion({
temperature: Number(temperature || 0),
max_tokens: maxToken,
messages: adaptMessages,
- frequency_penalty: 0.5, // 越大,重复内容越少
- presence_penalty: -0.5, // 越大,越容易出现新内容
+ // frequency_penalty: 0.5, // 越大,重复内容越少
+ // presence_penalty: -0.5, // 越大,越容易出现新内容
stream
},
{
@@ -184,7 +186,7 @@ export async function chatCompletion({
})();
return {
- answer
+ answerText: answer
};
}
diff --git a/client/src/pages/api/openapi/modules/kb/search.ts b/client/src/pages/api/openapi/modules/kb/search.ts
index 983fa5758..21ed9cf5f 100644
--- a/client/src/pages/api/openapi/modules/kb/search.ts
+++ b/client/src/pages/api/openapi/modules/kb/search.ts
@@ -92,8 +92,9 @@ export async function kbSearch({
const searchRes: QuoteItemType[] = res?.[2]?.rows || [];
// filter part quote by maxToken
- const sliceResult = modelToolMap['gpt-3.5-turbo']
+ const sliceResult = modelToolMap
.tokenSlice({
+ model: 'gpt-3.5-turbo',
maxToken,
messages: searchRes.map((item, i) => ({
obj: ChatRoleEnum.System,
diff --git a/client/src/pages/api/openapi/v1/chat/completions2.ts b/client/src/pages/api/openapi/v1/chat/completions2.ts
index 37a7daabb..e6b3703f5 100644
--- a/client/src/pages/api/openapi/v1/chat/completions2.ts
+++ b/client/src/pages/api/openapi/v1/chat/completions2.ts
@@ -10,12 +10,7 @@ import { getChatHistory } from './getHistory';
import { saveChat } from '@/pages/api/chat/saveChat';
import { sseResponse } from '@/service/utils/tools';
import { type ChatCompletionRequestMessage } from 'openai';
-import {
- kbChatAppDemo,
- chatAppDemo,
- SpecificInputEnum,
- AppModuleItemTypeEnum
-} from '@/constants/app';
+import { SpecificInputEnum, AppModuleItemTypeEnum } from '@/constants/app';
import { model, Types } from 'mongoose';
import { moduleFetch } from '@/service/api/request';
import { AppModuleItemType, RunningModuleItemType } from '@/types/app';
@@ -42,7 +37,6 @@ export type ChatResponseType = {
quoteLen?: number;
};
-/* 发送提示词 */
export default withNextCors(async function handler(req: NextApiRequest, res: NextApiResponse) {
res.on('close', () => {
res.end();
@@ -117,7 +111,6 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
},
stream
});
- console.log(responseData, answerText);
// save chat
if (typeof chatId === 'string') {
@@ -354,7 +347,7 @@ function loadModules(modules: AppModuleItemType[]): RunningModuleItemType[] {
})),
outputs: module.outputs.map((item) => ({
key: item.key,
- answer: item.type === FlowOutputItemTypeEnum.answer,
+ answer: item.key === SpecificInputEnum.answerText,
response: item.response,
value: undefined,
targets: item.targets
diff --git a/client/src/pages/app/detail/components/Kb.tsx b/client/src/pages/app/detail/components/Kb.tsx
deleted file mode 100644
index af27644f8..000000000
--- a/client/src/pages/app/detail/components/Kb.tsx
+++ /dev/null
@@ -1,394 +0,0 @@
-import React, { useState, useCallback } from 'react';
-import { useRouter } from 'next/router';
-import {
- Card,
- Flex,
- Box,
- Button,
- useDisclosure,
- Modal,
- ModalOverlay,
- ModalContent,
- ModalBody,
- ModalHeader,
- ModalFooter,
- ModalCloseButton,
- Grid,
- useTheme,
- IconButton,
- Tooltip,
- Textarea
-} from '@chakra-ui/react';
-import { useUserStore } from '@/store/user';
-import { useQuery } from '@tanstack/react-query';
-import Avatar from '@/components/Avatar';
-import { AddIcon, DeleteIcon, QuestionOutlineIcon } from '@chakra-ui/icons';
-import { putAppById } from '@/api/app';
-import { useToast } from '@/hooks/useToast';
-import { useLoading } from '@/hooks/useLoading';
-import { useForm } from 'react-hook-form';
-import MyIcon from '@/components/Icon';
-import MySlider from '@/components/Slider';
-
-const Kb = ({ modelId }: { modelId: string }) => {
- const theme = useTheme();
- const router = useRouter();
- const { toast } = useToast();
- const { appDetail, loadKbList, loadAppDetail } = useUserStore();
- const { Loading, setIsLoading } = useLoading();
- const [selectedIdList, setSelectedIdList] = useState([]);
- const [refresh, setRefresh] = useState(false);
- const { register, reset, getValues, setValue } = useForm({
- defaultValues: {
- searchSimilarity: appDetail.chat.searchSimilarity,
- searchLimit: appDetail.chat.searchLimit,
- searchEmptyText: appDetail.chat.searchEmptyText
- }
- });
-
- const {
- isOpen: isOpenKbSelect,
- onOpen: onOpenKbSelect,
- onClose: onCloseKbSelect
- } = useDisclosure();
- const {
- isOpen: isOpenEditParams,
- onOpen: onOpenEditParams,
- onClose: onCloseEditParams
- } = useDisclosure();
-
- const onchangeKb = useCallback(
- async (
- data: {
- relatedKbs?: string[];
- searchSimilarity?: number;
- searchLimit?: number;
- searchEmptyText?: string;
- } = {}
- ) => {
- setIsLoading(true);
- try {
- await putAppById(modelId, {
- chat: {
- ...appDetail.chat,
- ...data
- }
- });
- loadAppDetail(modelId, true);
- } catch (err: any) {
- toast({
- title: err?.message || '更新失败',
- status: 'error'
- });
- }
- setIsLoading(false);
- },
- [setIsLoading, modelId, appDetail.chat, loadAppDetail, toast]
- );
-
- // init kb select list
- const { isLoading, data: kbList = [] } = useQuery(['loadKbList'], () => loadKbList());
-
- return (
-
- 关联的知识库({appDetail.chat?.relatedKbs.length})
- {(() => {
- const kbs =
- appDetail.chat?.relatedKbs
- ?.map((id) => kbList.find((kb) => kb._id === id))
- .filter((item) => item) || [];
- return (
-
- {
- reset({
- searchSimilarity: appDetail.chat.searchSimilarity,
- searchLimit: appDetail.chat.searchLimit,
- searchEmptyText: appDetail.chat.searchEmptyText
- });
- onOpenEditParams();
- }}
- >
-
- }
- aria-label={''}
- variant={'base'}
- />
- 调整搜索参数
-
-
- 相似度: {appDetail.chat.searchSimilarity}, 单次搜索数量:{' '}
- {appDetail.chat.searchLimit}, 空搜索时拒绝回复:{' '}
- {appDetail.chat.searchEmptyText !== '' ? 'true' : 'false'}
-
-
- {
- setSelectedIdList(
- appDetail.chat?.relatedKbs ? [...appDetail.chat?.relatedKbs] : []
- );
- onOpenKbSelect();
- }}
- >
-
- }
- aria-label={''}
- variant={'base'}
- />
- 选择关联知识库
-
-
- 关联知识库,让 AI 应用回答你的特有内容。
-
-
- {kbs.map((item) =>
- item ? (
-
-
-
-
- {item.name}
-
-
-
-
- }
- variant={'outline'}
- aria-label={'delete'}
- size={'sm'}
- _hover={{ color: 'red.600' }}
- onClick={() => {
- const ids = appDetail.chat?.relatedKbs
- ? [...appDetail.chat.relatedKbs]
- : [];
- const i = ids.findIndex((id) => id === item._id);
- ids.splice(i, 1);
- onchangeKb({ relatedKbs: ids });
- }}
- />
-
-
- ) : null
- )}
-
- );
- })()}
- {/* select kb modal */}
-
-
-
- 关联的知识库({selectedIdList.length})
-
-
- {kbList.map((item) => (
- {
- let ids = [...selectedIdList];
- if (!selectedIdList.includes(item._id)) {
- ids = ids.concat(item._id);
- } else {
- const i = ids.findIndex((id) => id === item._id);
- ids.splice(i, 1);
- }
-
- ids = ids.filter((id) => kbList.find((item) => item._id === id));
- setSelectedIdList(ids);
- }}
- >
-
-
-
- {item.name}
-
-
-
- ))}
-
-
-
-
-
-
-
- {/* edit mode */}
-
-
-
- 搜索参数调整
-
-
-
-
- 相似度
-
-
-
-
- {
- setValue('searchSimilarity', val);
- setRefresh(!refresh);
- }}
- />
-
-
- 单次搜索数量
-
- {
- setValue('searchLimit', val);
- setRefresh(!refresh);
- }}
- />
-
-
-
- 空搜索回复
-
-
-
-
-
-
-
-
-
-
-
-
-
- );
-};
-
-export default Kb;
diff --git a/client/src/pages/app/detail/components/Share.tsx b/client/src/pages/app/detail/components/Share.tsx
index ada868683..112e706c4 100644
--- a/client/src/pages/app/detail/components/Share.tsx
+++ b/client/src/pages/app/detail/components/Share.tsx
@@ -2,7 +2,6 @@ import React, { useCallback, useState } from 'react';
import {
Flex,
Box,
- Tooltip,
Button,
TableContainer,
Table,
@@ -37,6 +36,7 @@ import { formatTimeToChatTime, useCopyData, getErrText } from '@/utils/tools';
import { useForm } from 'react-hook-form';
import { defaultShareChat } from '@/constants/model';
import type { ShareChatEditType } from '@/types/app';
+import MyTooltip from '@/components/MyTooltip';
const Share = ({ modelId }: { modelId: string }) => {
const { toast } = useToast();
@@ -112,9 +112,9 @@ ${e.password ? `密码为: ${e.password}` : ''}`;
免登录聊天窗口
-
+
-
+
+ >
);
};
diff --git a/client/src/pages/app/detail/components/edit/components/modules/Label.tsx b/client/src/pages/app/detail/components/edit/components/modules/Label.tsx
index f46d7f1a8..043af54f6 100644
--- a/client/src/pages/app/detail/components/edit/components/modules/Label.tsx
+++ b/client/src/pages/app/detail/components/edit/components/modules/Label.tsx
@@ -1,6 +1,7 @@
import React from 'react';
-import { Box, Tooltip } from '@chakra-ui/react';
+import { Box } from '@chakra-ui/react';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
+import MyTooltip from '@/components/MyTooltip';
const Label = ({
required = false,
@@ -19,9 +20,9 @@ const Label = ({
)}
{description && (
-
+
-
+
)}
);
diff --git a/client/src/pages/app/detail/components/edit/components/render/RenderInput.tsx b/client/src/pages/app/detail/components/edit/components/render/RenderInput.tsx
index 0095f3c58..81635078a 100644
--- a/client/src/pages/app/detail/components/edit/components/render/RenderInput.tsx
+++ b/client/src/pages/app/detail/components/edit/components/render/RenderInput.tsx
@@ -4,7 +4,6 @@ import {
Box,
Textarea,
Input,
- Tooltip,
NumberInput,
NumberInputField,
NumberInputStepper,
@@ -16,6 +15,7 @@ import { QuestionOutlineIcon } from '@chakra-ui/icons';
import { Handle, Position } from 'reactflow';
import MySelect from '@/components/Select';
import MySlider from '@/components/Slider';
+import MyTooltip from '@/components/MyTooltip';
const Label = ({
required = false,
@@ -34,9 +34,9 @@ const Label = ({
)}
{description && (
-
+
-
+
)}
);
@@ -49,14 +49,7 @@ const RenderBody = ({
}: {
flowInputList: FlowInputItemType[];
moduleId: string;
- CustomComponent?: Record<
- string,
- (e: {
- key: string;
- value: any;
- onChangeNode: FlowModuleItemType['onChangeNode'];
- }) => React.ReactNode
- >;
+ CustomComponent?: Record React.ReactNode>;
onChangeNode: FlowModuleItemType['onChangeNode'];
}) => {
return (
@@ -65,9 +58,11 @@ const RenderBody = ({
(item) =>
item.type !== FlowInputItemTypeEnum.hidden && (
-
+ {!!item.label && (
+
+ )}
{item.type === FlowInputItemTypeEnum.numberInput && (
)}
{item.type === FlowInputItemTypeEnum.custom && CustomComponent[item.key] && (
- <>
- {CustomComponent[item.key]({ key: item.key, value: item.value, onChangeNode })}
- >
+ <>{CustomComponent[item.key]({ ...item })}>
)}
{item.type === FlowInputItemTypeEnum.target && (
(
{description && (
-
+
-
+
)}
{children}
diff --git a/client/src/pages/app/detail/components/edit/index.tsx b/client/src/pages/app/detail/components/edit/index.tsx
index 15d6de586..b8a1b2897 100644
--- a/client/src/pages/app/detail/components/edit/index.tsx
+++ b/client/src/pages/app/detail/components/edit/index.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useEffect } from 'react';
+import React, { useCallback, useEffect, useRef } from 'react';
import ReactFlow, {
Background,
Controls,
@@ -7,7 +7,8 @@ import ReactFlow, {
useNodesState,
useEdgesState,
XYPosition,
- Connection
+ Connection,
+ useViewport
} from 'reactflow';
import { Box, Flex, IconButton, useTheme, useDisclosure } from '@chakra-ui/react';
import { SmallCloseIcon } from '@chakra-ui/icons';
@@ -47,6 +48,9 @@ const NodeQuestionInput = dynamic(() => import('./components/NodeQuestionInput')
const TemplateList = dynamic(() => import('./components/TemplateList'), {
ssr: false
});
+const NodeCQNode = dynamic(() => import('./components/NodeCQNode'), {
+ ssr: false
+});
import 'reactflow/dist/style.css';
import styles from './index.module.scss';
@@ -60,14 +64,18 @@ const nodeTypes = {
[FlowModuleTypeEnum.chatNode]: NodeChat,
[FlowModuleTypeEnum.kbSearchNode]: NodeKbSearch,
[FlowModuleTypeEnum.tfSwitchNode]: NodeTFSwitch,
- [FlowModuleTypeEnum.answerNode]: NodeAnswer
+ [FlowModuleTypeEnum.answerNode]: NodeAnswer,
+ [FlowModuleTypeEnum.classifyQuestionNode]: NodeCQNode
};
const edgeTypes = {
buttonedge: ButtonEdge
};
+type Props = { app: AppSchema; onBack: () => void };
-const AppEdit = ({ app, onBack }: { app: AppSchema; onBack: () => void }) => {
+const AppEdit = ({ app, onBack }: Props) => {
+ const reactFlowWrapper = useRef(null);
const theme = useTheme();
+ const { x, y, zoom } = useViewport();
const [nodes, setNodes, onNodesChange] = useNodesState([]);
const [edges, setEdges, onEdgesChange] = useEdgesState([]);
const {
@@ -77,24 +85,33 @@ const AppEdit = ({ app, onBack }: { app: AppSchema; onBack: () => void }) => {
} = useDisclosure();
const onChangeNode = useCallback(
- ({ moduleId, key, value, valueKey = 'value' }: FlowModuleItemChangeProps) => {
+ ({ moduleId, key, type = 'inputs', value, valueKey = 'value' }: FlowModuleItemChangeProps) => {
setNodes((nodes) =>
nodes.map((node) => {
if (node.id !== moduleId) return node;
+ if (type === 'inputs') {
+ return {
+ ...node,
+ data: {
+ ...node.data,
+ inputs: node.data.inputs.map((item) => {
+ if (item.key === key) {
+ return {
+ ...item,
+ [valueKey]: value
+ };
+ }
+ return item;
+ })
+ }
+ };
+ }
return {
...node,
data: {
...node.data,
- inputs: node.data.inputs.map((item) => {
- if (item.key === key) {
- return {
- ...item,
- [valueKey]: value
- };
- }
- return item;
- })
+ outputs: value
}
};
})
@@ -111,12 +128,17 @@ const AppEdit = ({ app, onBack }: { app: AppSchema; onBack: () => void }) => {
);
const onAddNode = useCallback(
({ template, position }: { template: AppModuleTemplateItemType; position: XYPosition }) => {
+ if (!reactFlowWrapper.current) return;
+ const reactFlowBounds = reactFlowWrapper.current.getBoundingClientRect();
+ const mouseX = (position.x - reactFlowBounds.left - x) / zoom - 100;
+ const mouseY = (position.y - reactFlowBounds.top - y) / zoom;
+
setNodes((state) =>
state.concat(
appModule2FlowNode({
item: {
...template,
- position,
+ position: { x: mouseX, y: mouseY },
moduleId: nanoid()
},
onChangeNode,
@@ -125,7 +147,7 @@ const AppEdit = ({ app, onBack }: { app: AppSchema; onBack: () => void }) => {
)
);
},
- [onChangeNode, onDelNode, setNodes]
+ [onChangeNode, onDelNode, setNodes, x, y, zoom]
);
const onDelConnect = useCallback(
@@ -245,6 +267,13 @@ const AppEdit = ({ app, onBack }: { app: AppSchema; onBack: () => void }) => {
borderRadius={'lg'}
isLoading={isLoading}
aria-label={'save'}
+ bg={'myBlue.200'}
+ variant={'base'}
+ border={'none'}
+ color={'myGray.900'}
+ _hover={{
+ bg: 'myBlue.300'
+ }}
onClick={onclickSave}
/>
@@ -270,43 +299,50 @@ const AppEdit = ({ app, onBack }: { app: AppSchema; onBack: () => void }) => {
transition={'0.2s ease'}
aria-label={''}
zIndex={1}
- boxShadow={'1px 1px 6px #4e83fd'}
- onClick={() => (isOpenTemplate ? onCloseTemplate() : onOpenTemplate())}
+ boxShadow={'2px 2px 6px #85b1ff'}
+ onClick={() => {
+ isOpenTemplate ? onCloseTemplate() : onOpenTemplate();
+ }}
/>
-
- {
- connect.sourceHandle &&
- connect.targetHandle &&
- onConnect({
- connect
- });
- }}
- >
-
-
-
-
-
+ {
+ connect.sourceHandle &&
+ connect.targetHandle &&
+ onConnect({
+ connect
+ });
+ }}
+ >
+
+
+
+
);
};
-export default AppEdit;
+const Flow = (data: Props) => (
+
+
+
+);
+
+export default Flow;
diff --git a/client/src/pages/app/list/component/CreateModal.tsx b/client/src/pages/app/list/component/CreateModal.tsx
index 79750916a..3570569d5 100644
--- a/client/src/pages/app/list/component/CreateModal.tsx
+++ b/client/src/pages/app/list/component/CreateModal.tsx
@@ -173,7 +173,7 @@ const CreateModal = ({ onClose, onSuccess }: { onClose: () => void; onSuccess: (
boxShadow={'sm'}
{...(getValues('templateId') === item.id
? {
- bg: 'myBlue.300'
+ bg: 'myWhite.600'
}
: {
_hover: {
diff --git a/client/src/pages/app/list/index.tsx b/client/src/pages/app/list/index.tsx
index 22b0fd5b9..69964c6e7 100644
--- a/client/src/pages/app/list/index.tsx
+++ b/client/src/pages/app/list/index.tsx
@@ -120,7 +120,13 @@ const MyApps = () => {
}}
/>
-
+
{app.intro || '这个应用还没写介绍~'}
diff --git a/client/src/pages/appStore/components/list.tsx b/client/src/pages/appStore/components/list.tsx
index f7e118bd3..ee42104bc 100644
--- a/client/src/pages/appStore/components/list.tsx
+++ b/client/src/pages/appStore/components/list.tsx
@@ -1,10 +1,11 @@
import React from 'react';
-import { Box, Flex, Button, Tooltip, Card } from '@chakra-ui/react';
+import { Box, Flex, Button, Card } from '@chakra-ui/react';
import type { ShareAppItem } from '@/types/app';
import { useRouter } from 'next/router';
import MyIcon from '@/components/Icon';
import styles from '../index.module.scss';
import Avatar from '@/components/Avatar';
+import MyTooltip from '@/components/MyTooltip';
const ShareModelList = ({
models = [],
@@ -44,7 +45,7 @@ const ShareModelList = ({
{model.name}
-
+
{model.intro || '这个应用还没有介绍~'}
-
+
await import('@/components/Markdown'));
const PhoneSliderBar = dynamic(() => import('./components/PhoneSliderBar'), {
@@ -701,7 +701,7 @@ const Chat = () => {
{item.obj === 'Human' && }
{/* avatar */}
{/* message */}
diff --git a/client/src/pages/chat/share.tsx b/client/src/pages/chat/share.tsx
index 10b89cf33..5ec1f2a9e 100644
--- a/client/src/pages/chat/share.tsx
+++ b/client/src/pages/chat/share.tsx
@@ -22,7 +22,6 @@ import {
DrawerOverlay,
DrawerContent,
Card,
- Tooltip,
useOutsideClick,
useTheme,
Input,
@@ -49,6 +48,7 @@ import SideBar from '@/components/SideBar';
import Avatar from '@/components/Avatar';
import Empty from './components/Empty';
import { HUMAN_ICON } from '@/constants/chat';
+import MyTooltip from '@/components/MyTooltip';
const ShareHistory = dynamic(() => import('./components/ShareHistory'), {
loading: () => ,
@@ -619,7 +619,7 @@ const Chat = () => {
{item.obj === 'Human' && }
{/* avatar */}
{/* message */}
diff --git a/client/src/pages/kb/components/Info.tsx b/client/src/pages/kb/components/Info.tsx
index 2cbf399a9..2920464ba 100644
--- a/client/src/pages/kb/components/Info.tsx
+++ b/client/src/pages/kb/components/Info.tsx
@@ -7,7 +7,7 @@ import React, {
ForwardedRef
} from 'react';
import { useRouter } from 'next/router';
-import { Box, Flex, Button, FormControl, IconButton, Tooltip, Input, Card } from '@chakra-ui/react';
+import { Box, Flex, Button, FormControl, IconButton, Input, Card } from '@chakra-ui/react';
import { QuestionOutlineIcon, DeleteIcon } from '@chakra-ui/icons';
import { delKbById, putKbById } from '@/api/plugins/kb';
import { useSelectFile } from '@/hooks/useSelectFile';
@@ -19,6 +19,7 @@ import { compressImg } from '@/utils/file';
import type { KbItemType } from '@/types/plugin';
import Avatar from '@/components/Avatar';
import Tag from '@/components/Tag';
+import MyTooltip from '@/components/MyTooltip';
export interface ComponentRef {
initInput: (tags: string) => void;
@@ -173,9 +174,9 @@ const Info = (
分类标签
-
+
-
+
{
const theme = useTheme();
@@ -78,7 +79,7 @@ const KbList = ({ kbId }: { kbId: string }) => {
/>
)}
-
+
}
@@ -86,7 +87,7 @@ const KbList = ({ kbId }: { kbId: string }) => {
variant={'base'}
onClick={handleCreateModel}
/>
-
+
{kbs.map((item) => (
diff --git a/client/src/pages/model/components/detail/components/Settings.tsx b/client/src/pages/model/components/detail/components/Settings.tsx
deleted file mode 100644
index ec39c0cdb..000000000
--- a/client/src/pages/model/components/detail/components/Settings.tsx
+++ /dev/null
@@ -1,388 +0,0 @@
-import React, { useCallback, useState, useMemo } from 'react';
-import {
- Box,
- Flex,
- Button,
- FormControl,
- Input,
- Textarea,
- Divider,
- Tooltip
-} from '@chakra-ui/react';
-import { QuestionOutlineIcon } from '@chakra-ui/icons';
-import { useQuery } from '@tanstack/react-query';
-import { useForm } from 'react-hook-form';
-import { useRouter } from 'next/router';
-import { useUserStore } from '@/store/user';
-import { useToast } from '@/hooks/useToast';
-import { useLoading } from '@/hooks/useLoading';
-import { delModelById, putAppById } from '@/api/app';
-import { useSelectFile } from '@/hooks/useSelectFile';
-import { compressImg } from '@/utils/file';
-import { getErrText } from '@/utils/tools';
-import { useConfirm } from '@/hooks/useConfirm';
-import { ChatModelMap, chatModelList } from '@/constants/model';
-import { formatPrice } from '@/utils/user';
-
-import type { AppSchema } from '@/types/mongoSchema';
-
-import Avatar from '@/components/Avatar';
-import MySelect from '@/components/Select';
-import MySlider from '@/components/Slider';
-
-const systemPromptTip =
- '模型固定的引导词,通过调整该内容,可以引导模型聊天方向。该内容会被固定在上下文的开头。';
-const limitPromptTip =
- '限定模型对话范围,会被放置在本次提问前,拥有强引导和限定性。例如:\n1. 知识库是关于 Laf 的介绍,参考知识库回答问题,与 "Laf" 无关内容,直接回复: "我不知道"。\n2. 你仅回答关于 "xxx" 的问题,其他问题回复: "xxxx"';
-
-const Settings = ({ modelId }: { modelId: string }) => {
- const { toast } = useToast();
- const router = useRouter();
- const { Loading, setIsLoading } = useLoading();
- const { userInfo, appDetail, myApps, loadAppDetail, refreshModel, setLastModelId } =
- useUserStore();
- const { File, onOpen: onOpenSelectFile } = useSelectFile({
- fileType: '.jpg,.png',
- multiple: false
- });
- const { openConfirm, ConfirmChild } = useConfirm({
- content: '确认删除该应用?'
- });
-
- const [btnLoading, setBtnLoading] = useState(false);
- const [refresh, setRefresh] = useState(false);
-
- const {
- register,
- setValue,
- getValues,
- formState: { errors },
- reset,
- handleSubmit
- } = useForm({
- defaultValues: appDetail
- });
-
- const isOwner = useMemo(
- () => appDetail.userId === userInfo?._id,
- [appDetail.userId, userInfo?._id]
- );
- const tokenLimit = useMemo(() => {
- const max = ChatModelMap[getValues('chat.chatModel')]?.contextMaxToken || 4000;
-
- if (max < getValues('chat.maxToken')) {
- setValue('chat.maxToken', max);
- }
-
- return max;
- }, [getValues, setValue, refresh]);
-
- // 提交保存模型修改
- const saveSubmitSuccess = useCallback(
- async (data: AppSchema) => {
- setBtnLoading(true);
- try {
- await putAppById(data._id, {
- name: data.name,
- avatar: data.avatar,
- intro: data.intro,
- chat: data.chat,
- share: data.share
- });
-
- refreshModel.updateModelDetail(data);
- } catch (err: any) {
- toast({
- title: err?.message || '更新失败',
- status: 'error'
- });
- }
- setBtnLoading(false);
- },
- [refreshModel, toast]
- );
- // 提交保存表单失败
- const saveSubmitError = useCallback(() => {
- // deep search message
- const deepSearch = (obj: any): string => {
- if (!obj) return '提交表单错误';
- if (!!obj.message) {
- return obj.message;
- }
- return deepSearch(Object.values(obj)[0]);
- };
- toast({
- title: deepSearch(errors),
- status: 'error',
- duration: 4000,
- isClosable: true
- });
- }, [errors, toast]);
-
- const saveUpdateModel = useCallback(
- () => handleSubmit(saveSubmitSuccess, saveSubmitError)(),
- [handleSubmit, saveSubmitError, saveSubmitSuccess]
- );
-
- /* 点击删除 */
- const handleDelModel = useCallback(async () => {
- if (!appDetail) return;
- setIsLoading(true);
- try {
- await delModelById(appDetail._id);
- toast({
- title: '删除成功',
- status: 'success'
- });
- refreshModel.removeModelDetail(appDetail._id);
- router.replace(`/model?modelId=${myApps[1]?._id}`);
- } catch (err: any) {
- toast({
- title: err?.message || '删除失败',
- status: 'error'
- });
- }
- setIsLoading(false);
- }, [appDetail, setIsLoading, toast, refreshModel, router, myApps]);
-
- const onSelectFile = useCallback(
- async (e: File[]) => {
- const file = e[0];
- if (!file) return;
- try {
- const src = await compressImg({
- file,
- maxW: 100,
- maxH: 100
- });
- setValue('avatar', src);
- setRefresh((state) => !state);
- } catch (err: any) {
- toast({
- title: getErrText(err, '头像选择异常'),
- status: 'warning'
- });
- }
- },
- [setValue, toast]
- );
-
- // load model data
- const { isLoading } = useQuery([modelId], () => loadAppDetail(modelId, true), {
- onSuccess(res) {
- res && reset(res);
- modelId && setLastModelId(modelId);
- setRefresh(!refresh);
- },
- onError(err: any) {
- toast({
- title: err?.message || '获取应用异常',
- status: 'error'
- });
- setLastModelId('');
- refreshModel.freshMyModels();
- router.replace('/model');
- }
- });
-
- return (
-
-
-
- 头像
-
- isOwner && onOpenSelectFile()}
- />
-
-
-
-
- 名称
-
-
-
-
-
-
- 介绍
-
-
-
-
-
-
-
-
- 对话模型
-
- ({
- value: item.chatModel,
- label: `${item.name} (${formatPrice(
- ChatModelMap[item.chatModel]?.price,
- 1000
- )} 元/1k tokens)`
- }))}
- onchange={(val: any) => {
- setValue('chat.chatModel', val);
- setRefresh(!refresh);
- }}
- />
-
-
-
- 温度
-
-
- {
- setValue('chat.temperature', val);
- setRefresh(!refresh);
- }}
- />
-
-
-
-
- 回复上限
-
-
- {
- setValue('chat.maxToken', val);
- setRefresh(!refresh);
- }}
- />
-
-
-
-
- 提示词
-
-
-
-
-
-
-
-
- 限定词
-
-
-
-
-
-
-
-
-
- {
- try {
- await saveUpdateModel();
- toast({
- title: '更新成功',
- status: 'success'
- });
- } catch (error) {
- console.log(error);
- error;
- }
- }}
- >
- {isOwner ? '保存' : '仅读,无法修改'}
-
- {
- try {
- router.prefetch('/chat');
- await saveUpdateModel();
- } catch (error) {}
- router.push(`/chat?modelId=${modelId}`);
- }}
- >
- 对话
-
- {isOwner && (
-
- 删除
-
- )}
-
-
-
-
-
-
- );
-};
-
-export default Settings;
diff --git a/client/src/types/app.d.ts b/client/src/types/app.d.ts
index 217c442cd..1a50685f5 100644
--- a/client/src/types/app.d.ts
+++ b/client/src/types/app.d.ts
@@ -40,7 +40,7 @@ export type ShareChatEditType = {
/* agent */
/* question classify */
export type ClassifyQuestionAgentItemType = {
- desc: string;
+ value: string;
key: string;
};
diff --git a/client/src/types/flow.d.ts b/client/src/types/flow.d.ts
index 40631d4a0..99e66540e 100644
--- a/client/src/types/flow.d.ts
+++ b/client/src/types/flow.d.ts
@@ -37,6 +37,7 @@ export type FlowOutputItemType = {
export type FlowModuleItemChangeProps = {
moduleId: string;
+ type?: 'inputs' | 'outputs';
key: string;
value: any;
valueKey?: keyof FlowInputItemType & keyof FlowBodyItemType;
diff --git a/client/src/utils/adapt.ts b/client/src/utils/adapt.ts
index 6819e1431..b0ae8d658 100644
--- a/client/src/utils/adapt.ts
+++ b/client/src/utils/adapt.ts
@@ -109,8 +109,6 @@ export const appModule2FlowEdge = ({
modules: AppModuleItemType[];
onDelete: (id: string) => void;
}) => {
- console.log(modules);
-
const edges: Edge[] = [];
modules.forEach((module) =>
module.outputs.forEach((output) =>
diff --git a/client/src/utils/plugin/index.ts b/client/src/utils/plugin/index.ts
index 96153f7d8..d70a066e7 100644
--- a/client/src/utils/plugin/index.ts
+++ b/client/src/utils/plugin/index.ts
@@ -1,6 +1,3 @@
-import { OpenAiChatEnum } from '@/constants/model';
-import type { ChatModelType } from '@/constants/model';
-import type { ChatItemType } from '@/types/chat';
import { countOpenAIToken, openAiSliceTextByToken } from './openai';
import { gpt_chatItemTokenSlice } from '@/pages/api/openapi/text/gptMessagesSlice';