perf: collection created response (#1947)

* perf: collection created response

* update openapi doc

* remove default collection

* perf: chat ui

* fix: system prompt concat

* perf: published check

* perf: update app
This commit is contained in:
Archer
2024-07-05 10:27:38 +08:00
committed by GitHub
parent 8a7bd689ae
commit 88d10451c9
26 changed files with 160 additions and 165 deletions

View File

@@ -13,7 +13,7 @@ weight: 853
## 创建训练订单(4.6.9地址发生改动) ## 创建训练订单
{{< tabs tabTotal="2" >}} {{< tabs tabTotal="2" >}}
{{< tab tabName="请求示例" >}} {{< tab tabName="请求示例" >}}
@@ -26,6 +26,7 @@ curl --location --request POST 'https://api.fastgpt.in/api/support/wallet/usage/
--header 'Authorization: Bearer {{apikey}}' \ --header 'Authorization: Bearer {{apikey}}' \
--header 'Content-Type: application/json' \ --header 'Content-Type: application/json' \
--data-raw '{ --data-raw '{
"datasetId": "知识库 ID",
"name": "可选,自定义订单名称,例如:文档训练-fastgpt.docx" "name": "可选,自定义订单名称,例如:文档训练-fastgpt.docx"
}' }'
``` ```

View File

@@ -38,5 +38,7 @@ curl --location --request POST 'https://{{host}}/api/admin/initv486' \
3. 新增 - 网页抓取和数学计算器系统插件 3. 新增 - 网页抓取和数学计算器系统插件
4. 新增 - 移动文本加工和自定义反馈到基础节点中 4. 新增 - 移动文本加工和自定义反馈到基础节点中
5. 优化 - Read file 默认选中从节点,实现 MongoDB 读写分离,减轻主节点压力 5. 优化 - Read file 默认选中从节点,实现 MongoDB 读写分离,减轻主节点压力
6. 修复 - 工作流中团队插件加载异常 6. 优化 - 知识库导入接口,返回值对齐
7. 修复 - 知识库集合目录导航失效 7. 修复 - 工作流中团队插件加载异常
8. 修复 - 知识库集合目录导航失效
9. 修复 - 通过 API 调用 chat 接口,传递 System 异常

View File

@@ -3,6 +3,17 @@ import { FlowNodeTypeEnum } from '../workflow/node/constant';
import { ChatItemValueTypeEnum, ChatRoleEnum } from './constants'; import { ChatItemValueTypeEnum, ChatRoleEnum } from './constants';
import { ChatHistoryItemResType, ChatItemType, UserChatItemValueItemType } from './type.d'; import { ChatHistoryItemResType, ChatItemType, UserChatItemValueItemType } from './type.d';
// Concat 2 -> 1, and sort by role
export const concatHistories = (histories1: ChatItemType[], histories2: ChatItemType[]) => {
const newHistories = [...histories1, ...histories2];
return newHistories.sort((a, b) => {
if (a.obj === ChatRoleEnum.System) {
return -1;
}
return 1;
});
};
export const getChatTitleFromChatMessage = (message?: ChatItemType, defaultValue = '新对话') => { export const getChatTitleFromChatMessage = (message?: ChatItemType, defaultValue = '新对话') => {
// @ts-ignore // @ts-ignore
const textMsg = message?.value.find((item) => item.type === ChatItemValueTypeEnum.text); const textMsg = message?.value.find((item) => item.type === ChatItemValueTypeEnum.text);

View File

@@ -88,7 +88,7 @@
"x": 1050.9890727421412, "x": 1050.9890727421412,
"y": -415.2085119990912 "y": -415.2085119990912
}, },
"version": "486", "version": "481",
"inputs": [ "inputs": [
{ {
"key": "system_addInputParam", "key": "system_addInputParam",

View File

@@ -13,24 +13,24 @@ export async function getChatItems({
chatId?: string; chatId?: string;
limit?: number; limit?: number;
field: string; field: string;
}): Promise<{ history: ChatItemType[] }> { }): Promise<{ histories: ChatItemType[] }> {
if (!chatId) { if (!chatId) {
return { history: [] }; return { histories: [] };
} }
const history = await MongoChatItem.find({ appId, chatId }, field) const histories = await MongoChatItem.find({ appId, chatId }, field)
.sort({ _id: -1 }) .sort({ _id: -1 })
.limit(limit) .limit(limit)
.lean(); .lean();
history.reverse(); histories.reverse();
history.forEach((item) => { histories.forEach((item) => {
// @ts-ignore // @ts-ignore
item.value = adaptStringValue(item.value); item.value = adaptStringValue(item.value);
}); });
return { history }; return { histories };
} }
/* 临时适配旧的对话记录 */ /* 临时适配旧的对话记录 */
export const adaptStringValue = (value: any): ChatItemValueItemType[] => { export const adaptStringValue = (value: any): ChatItemValueItemType[] => {

View File

@@ -75,54 +75,9 @@ export async function createOneCollection({
{ session } { session }
); );
// create default collection
if (type === DatasetCollectionTypeEnum.folder) {
await createDefaultCollection({
datasetId,
parentId: collection._id,
teamId,
tmbId,
session
});
}
return collection; return collection;
} }
// create default collection
export function createDefaultCollection({
name = '手动录入',
datasetId,
parentId,
teamId,
tmbId,
session
}: {
name?: '手动录入' | '手动标注';
datasetId: string;
parentId?: string;
teamId: string;
tmbId: string;
session?: ClientSession;
}) {
return MongoDatasetCollection.create(
[
{
name,
teamId,
tmbId,
datasetId,
parentId,
type: DatasetCollectionTypeEnum.virtual,
trainingType: TrainingModeEnum.chunk,
chunkSize: 0,
updateTime: new Date('2099')
}
],
{ session }
);
}
/* delete collection related images/files */ /* delete collection related images/files */
export const delCollectionRelatedSource = async ({ export const delCollectionRelatedSource = async ({
collections, collections,

View File

@@ -10,6 +10,7 @@ import {
} from '@fastgpt/global/core/dataset/constants'; } from '@fastgpt/global/core/dataset/constants';
import { hashStr } from '@fastgpt/global/common/string/tools'; import { hashStr } from '@fastgpt/global/common/string/tools';
import { ClientSession } from '../../../common/mongo'; import { ClientSession } from '../../../common/mongo';
import { PushDatasetDataResponse } from '@fastgpt/global/core/dataset/api';
/** /**
* get all collection by top collectionId * get all collection by top collectionId
@@ -138,7 +139,7 @@ export const reloadCollectionChunks = async ({
billId?: string; billId?: string;
rawText?: string; rawText?: string;
session: ClientSession; session: ClientSession;
}) => { }): Promise<PushDatasetDataResponse> => {
const { const {
title, title,
rawText: newRawText, rawText: newRawText,
@@ -149,7 +150,10 @@ export const reloadCollectionChunks = async ({
newRawText: rawText newRawText: rawText
}); });
if (isSameRawText) return; if (isSameRawText)
return {
insertLen: 0
};
// split data // split data
const { chunks } = splitText2Chunks({ const { chunks } = splitText2Chunks({
@@ -164,7 +168,7 @@ export const reloadCollectionChunks = async ({
return Promise.reject('Training model error'); return Promise.reject('Training model error');
})(); })();
await MongoDatasetTraining.insertMany( const result = await MongoDatasetTraining.insertMany(
chunks.map((item, i) => ({ chunks.map((item, i) => ({
teamId: col.teamId, teamId: col.teamId,
tmbId, tmbId,
@@ -191,4 +195,8 @@ export const reloadCollectionChunks = async ({
}, },
{ session } { session }
); );
return {
insertLen: result.length
};
}; };

View File

@@ -1,12 +1,11 @@
import { getErrText } from '@fastgpt/global/common/error/utils'; import { getErrText } from '@fastgpt/global/common/error/utils';
import { replaceSensitiveText } from '@fastgpt/global/common/string/tools'; import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d'; import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
import { import {
WorkflowIOValueTypeEnum, WorkflowIOValueTypeEnum,
NodeOutputKeyEnum NodeOutputKeyEnum
} from '@fastgpt/global/core/workflow/constants'; } from '@fastgpt/global/core/workflow/constants';
import { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/runtime/type'; import { RuntimeEdgeItemType } from '@fastgpt/global/core/workflow/runtime/type';
import { FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
export const filterToolNodeIdByEdges = ({ export const filterToolNodeIdByEdges = ({
nodeId, nodeId,
@@ -45,10 +44,16 @@ export const filterToolNodeIdByEdges = ({
export const getHistories = (history?: ChatItemType[] | number, histories: ChatItemType[] = []) => { export const getHistories = (history?: ChatItemType[] | number, histories: ChatItemType[] = []) => {
if (!history) return []; if (!history) return [];
if (typeof history === 'number') return histories.slice(-(history * 2));
if (Array.isArray(history)) return history;
return []; const systemHistories = histories.filter((item) => item.obj === ChatRoleEnum.System);
const filterHistories = (() => {
if (typeof history === 'number') return histories.slice(-(history * 2));
if (Array.isArray(history)) return history;
return [];
})();
return [...systemHistories, ...filterHistories];
}; };
/* value type format */ /* value type format */

View File

@@ -41,7 +41,6 @@ export const useChatBox = () => {
const map: Record<ExportChatType, () => void> = { const map: Record<ExportChatType, () => void> = {
md: () => { md: () => {
console.log(history);
fileDownload({ fileDownload({
text: history text: history
.map((item) => { .map((item) => {

View File

@@ -1,4 +1,7 @@
import { PushDatasetDataChunkProps } from '@fastgpt/global/core/dataset/api'; import {
PushDatasetDataChunkProps,
PushDatasetDataResponse
} from '@fastgpt/global/core/dataset/api';
import { import {
DatasetSearchModeEnum, DatasetSearchModeEnum,
DatasetSourceReadTypeEnum, DatasetSourceReadTypeEnum,
@@ -31,6 +34,10 @@ export type RebuildEmbeddingProps = {
}; };
/* ================= collection ===================== */ /* ================= collection ===================== */
export type CreateCollectionResponse = Promise<{
collectionId: string;
results: PushDatasetDataResponse;
}>;
/* ================= data ===================== */ /* ================= data ===================== */
export type InsertOneDatasetDataProps = PushDatasetDataChunkProps & { export type InsertOneDatasetDataProps = PushDatasetDataChunkProps & {

View File

@@ -154,10 +154,8 @@ async function handler(req: ApiRequestProps<AppUpdateParams, { appId: string }>)
return onUpdate(session); return onUpdate(session);
}); });
} } else if (isDefaultPermissionChanged) {
// Update default permission
// Update default permission
if (isDefaultPermissionChanged) {
await mongoSessionRun(async (session) => { await mongoSessionRun(async (session) => {
if (isFolder) { if (isFolder) {
// Sync children default permission // Sync children default permission
@@ -193,6 +191,8 @@ async function handler(req: ApiRequestProps<AppUpdateParams, { appId: string }>)
return onUpdate(session, defaultPermission); return onUpdate(session, defaultPermission);
}); });
} else {
return onUpdate();
} }
} }

View File

@@ -42,7 +42,7 @@ async function handler(
} }
// get app and history // get app and history
const [{ history }, { nodes }] = await Promise.all([ const [{ histories }, { nodes }] = await Promise.all([
getChatItems({ getChatItems({
appId, appId,
chatId, chatId,
@@ -60,7 +60,7 @@ async function handler(
title: chat?.title || '新对话', title: chat?.title || '新对话',
userAvatar: undefined, userAvatar: undefined,
variables: chat?.variables || {}, variables: chat?.variables || {},
history, history: histories,
app: { app: {
chatConfig: getAppChatConfig({ chatConfig: getAppChatConfig({
chatConfig: app.chatConfig, chatConfig: app.chatConfig,

View File

@@ -41,7 +41,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
throw new Error(ChatErrEnum.unAuthChat); throw new Error(ChatErrEnum.unAuthChat);
} }
const [{ history }, { nodes }] = await Promise.all([ const [{ histories }, { nodes }] = await Promise.all([
getChatItems({ getChatItems({
appId: app._id, appId: app._id,
chatId, chatId,
@@ -56,7 +56,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
]); ]);
// pick share response field // pick share response field
history.forEach((item) => { histories.forEach((item) => {
if (item.obj === ChatRoleEnum.AI) { if (item.obj === ChatRoleEnum.AI) {
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData }); item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
} }
@@ -70,7 +70,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
//@ts-ignore //@ts-ignore
userAvatar: tmb?.userId?.avatar, userAvatar: tmb?.userId?.avatar,
variables: chat?.variables || {}, variables: chat?.variables || {},
history, history: histories,
app: { app: {
chatConfig: getAppChatConfig({ chatConfig: getAppChatConfig({
chatConfig: app.chatConfig, chatConfig: app.chatConfig,

View File

@@ -47,7 +47,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
} }
// get app and history // get app and history
const [{ history }, { nodes }] = await Promise.all([ const [{ histories }, { nodes }] = await Promise.all([
getChatItems({ getChatItems({
appId, appId,
chatId, chatId,
@@ -58,7 +58,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
]); ]);
// pick share response field // pick share response field
history.forEach((item) => { histories.forEach((item) => {
if (item.obj === ChatRoleEnum.AI) { if (item.obj === ChatRoleEnum.AI) {
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData }); item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
} }
@@ -71,7 +71,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
title: chat?.title || '新对话', title: chat?.title || '新对话',
userAvatar: team?.avatar, userAvatar: team?.avatar,
variables: chat?.variables || {}, variables: chat?.variables || {},
history, history: histories,
app: { app: {
chatConfig: getAppChatConfig({ chatConfig: getAppChatConfig({
chatConfig: app.chatConfig, chatConfig: app.chatConfig,

View File

@@ -18,8 +18,9 @@ import { getLLMModel, getVectorModel } from '@fastgpt/service/core/ai/model';
import { rawText2Chunks } from '@fastgpt/service/core/dataset/read'; import { rawText2Chunks } from '@fastgpt/service/core/dataset/read';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { CreateCollectionResponse } from '@/global/core/dataset/api';
async function handler(req: NextApiRequest) { async function handler(req: NextApiRequest): CreateCollectionResponse {
const { datasetId, parentId, fileId } = req.body as FileIdCreateDatasetCollectionParams; const { datasetId, parentId, fileId } = req.body as FileIdCreateDatasetCollectionParams;
const trainingType = TrainingModeEnum.chunk; const trainingType = TrainingModeEnum.chunk;
const { teamId, tmbId, dataset } = await authDataset({ const { teamId, tmbId, dataset } = await authDataset({
@@ -50,7 +51,7 @@ async function handler(req: NextApiRequest) {
insertLen: predictDataLimitLength(trainingType, chunks) insertLen: predictDataLimitLength(trainingType, chunks)
}); });
await mongoSessionRun(async (session) => { return mongoSessionRun(async (session) => {
// 4. create collection // 4. create collection
const { _id: collectionId } = await createOneCollection({ const { _id: collectionId } = await createOneCollection({
teamId, teamId,
@@ -80,7 +81,7 @@ async function handler(req: NextApiRequest) {
}); });
// 6. insert to training queue // 6. insert to training queue
await pushDataListToTrainingQueue({ const insertResult = await pushDataListToTrainingQueue({
teamId, teamId,
tmbId, tmbId,
datasetId: dataset._id, datasetId: dataset._id,
@@ -97,7 +98,7 @@ async function handler(req: NextApiRequest) {
session session
}); });
return collectionId; return { collectionId, results: insertResult };
}); });
} }
export default NextAPI(handler); export default NextAPI(handler);

View File

@@ -15,8 +15,9 @@ import { reloadCollectionChunks } from '@fastgpt/service/core/dataset/collection
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { CreateCollectionResponse } from '@/global/core/dataset/api';
async function handler(req: NextApiRequest) { async function handler(req: NextApiRequest): CreateCollectionResponse {
const { const {
link, link,
trainingType = TrainingModeEnum.chunk, trainingType = TrainingModeEnum.chunk,
@@ -40,7 +41,7 @@ async function handler(req: NextApiRequest) {
insertLen: predictDataLimitLength(trainingType, new Array(10)) insertLen: predictDataLimitLength(trainingType, new Array(10))
}); });
await mongoSessionRun(async (session) => { return mongoSessionRun(async (session) => {
// 2. create collection // 2. create collection
const collection = await createOneCollection({ const collection = await createOneCollection({
...body, ...body,
@@ -70,7 +71,7 @@ async function handler(req: NextApiRequest) {
}); });
// load // load
await reloadCollectionChunks({ const result = await reloadCollectionChunks({
collection: { collection: {
...collection.toObject(), ...collection.toObject(),
datasetId: dataset datasetId: dataset
@@ -80,7 +81,12 @@ async function handler(req: NextApiRequest) {
session session
}); });
return collection; return {
collectionId: collection._id,
results: {
insertLen: result.insertLen
}
};
}); });
} }

View File

@@ -23,8 +23,9 @@ import { MongoImage } from '@fastgpt/service/common/file/image/schema';
import { readRawTextByLocalFile } from '@fastgpt/service/common/file/read/utils'; import { readRawTextByLocalFile } from '@fastgpt/service/common/file/read/utils';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { CreateCollectionResponse } from '@/global/core/dataset/api';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) { async function handler(req: NextApiRequest, res: NextApiResponse<any>): CreateCollectionResponse {
/** /**
* Creates the multer uploader * Creates the multer uploader
*/ */

View File

@@ -17,8 +17,9 @@ import { getLLMModel, getVectorModel } from '@fastgpt/service/core/ai/model';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun'; import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { CreateCollectionResponse } from '@/global/core/dataset/api';
async function handler(req: NextApiRequest) { async function handler(req: NextApiRequest): CreateCollectionResponse {
const { const {
name, name,
text, text,

View File

@@ -1,7 +1,6 @@
import type { NextApiRequest } from 'next'; import type { NextApiRequest } from 'next';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema'; import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import type { CreateDatasetParams } from '@/global/core/dataset/api.d'; import type { CreateDatasetParams } from '@/global/core/dataset/api.d';
import { createDefaultCollection } from '@fastgpt/service/core/dataset/collection/controller';
import { authUserPer } from '@fastgpt/service/support/permission/user/auth'; import { authUserPer } from '@fastgpt/service/support/permission/user/auth';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants'; import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import { getLLMModel, getVectorModel, getDatasetModel } from '@fastgpt/service/core/ai/model'; import { getLLMModel, getVectorModel, getDatasetModel } from '@fastgpt/service/core/ai/model';
@@ -50,14 +49,6 @@ async function handler(req: NextApiRequest) {
defaultPermission defaultPermission
}); });
if (type === DatasetTypeEnum.dataset) {
await createDefaultCollection({
datasetId: _id,
teamId,
tmbId
});
}
return _id; return _id;
} }

View File

@@ -26,6 +26,7 @@ import requestIp from 'request-ip';
import { getUsageSourceByAuthType } from '@fastgpt/global/support/wallet/usage/tools'; import { getUsageSourceByAuthType } from '@fastgpt/global/support/wallet/usage/tools';
import { authTeamSpaceToken } from '@/service/support/permission/auth/team'; import { authTeamSpaceToken } from '@/service/support/permission/auth/team';
import { import {
concatHistories,
filterPublicNodeResponseData, filterPublicNodeResponseData,
removeEmptyUserInput removeEmptyUserInput
} from '@fastgpt/global/core/chat/utils'; } from '@fastgpt/global/core/chat/utils';
@@ -119,6 +120,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
let startTime = Date.now(); let startTime = Date.now();
// Web chat params: [Human, AI]
const chatMessages = GPTMessages2Chats(messages); const chatMessages = GPTMessages2Chats(messages);
if (chatMessages[chatMessages.length - 1].obj !== ChatRoleEnum.Human) { if (chatMessages[chatMessages.length - 1].obj !== ChatRoleEnum.Human) {
chatMessages.pop(); chatMessages.pop();
@@ -170,7 +172,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
// 1. get and concat history; 2. get app workflow // 1. get and concat history; 2. get app workflow
const limit = getMaxHistoryLimitFromNodes(app.modules); const limit = getMaxHistoryLimitFromNodes(app.modules);
const [{ history }, { nodes, edges, chatConfig }] = await Promise.all([ const [{ histories }, { nodes, edges, chatConfig }] = await Promise.all([
getChatItems({ getChatItems({
appId: app._id, appId: app._id,
chatId, chatId,
@@ -179,7 +181,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
}), }),
getAppLatestVersion(app._id, app) getAppLatestVersion(app._id, app)
]); ]);
const concatHistories = history.concat(chatMessages); const newHistories = concatHistories(histories, chatMessages);
const responseChatItemId: string | undefined = messages[messages.length - 1].dataId; const responseChatItemId: string | undefined = messages[messages.length - 1].dataId;
/* start flow controller */ /* start flow controller */
@@ -198,7 +200,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
runtimeEdges: initWorkflowEdgeStatus(edges), runtimeEdges: initWorkflowEdgeStatus(edges),
variables, variables,
query: removeEmptyUserInput(question.value), query: removeEmptyUserInput(question.value),
histories: concatHistories, histories: newHistories,
stream, stream,
detail, detail,
maxRunTimes: 200 maxRunTimes: 200
@@ -217,7 +219,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
modules: setEntryEntries(app.modules), modules: setEntryEntries(app.modules),
variables, variables,
inputFiles: files, inputFiles: files,
histories: concatHistories, histories: newHistories,
startParams: { startParams: {
userChatInput: text userChatInput: text
}, },

View File

@@ -10,7 +10,6 @@ import {
Checkbox, Checkbox,
ModalFooter ModalFooter
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { DragHandleIcon } from '@chakra-ui/icons';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { AppSchema } from '@fastgpt/global/core/app/type.d'; import { AppSchema } from '@fastgpt/global/core/app/type.d';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
@@ -28,11 +27,13 @@ import MyModal from '@fastgpt/web/components/common/MyModal';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest'; import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { postTransition2Workflow } from '@/web/core/app/api/app'; import { postTransition2Workflow } from '@/web/core/app/api/app';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
const AppCard = () => { const AppCard = () => {
const router = useRouter(); const router = useRouter();
const { t } = useTranslation(); const { t } = useTranslation();
const { appT } = useI18n(); const { appT } = useI18n();
const { isPc } = useSystem();
const { appDetail, setAppDetail, onOpenInfoEdit, onDelApp } = useContextSelector( const { appDetail, setAppDetail, onOpenInfoEdit, onDelApp } = useContextSelector(
AppContext, AppContext,
@@ -68,7 +69,7 @@ const AppCard = () => {
return ( return (
<> <>
{/* basic info */} {/* basic info */}
<Box px={6} py={4} position={'relative'}> <Box px={[4, 6]} py={4} position={'relative'}>
<Flex alignItems={'center'}> <Flex alignItems={'center'}>
<Avatar src={appDetail.avatar} borderRadius={'md'} w={'28px'} /> <Avatar src={appDetail.avatar} borderRadius={'md'} w={'28px'} />
<Box ml={3} fontWeight={'bold'} fontSize={'md'} flex={'1 0 0'} color={'myGray.900'}> <Box ml={3} fontWeight={'bold'} fontSize={'md'} flex={'1 0 0'} color={'myGray.900'}>
@@ -149,13 +150,15 @@ const AppCard = () => {
/> />
)} )}
<Box flex={1} /> <Box flex={1} />
<MyTag {isPc && (
type="borderFill" <MyTag
colorSchema="gray" type="borderFill"
onClick={() => (appDetail.permission.hasManagePer ? onOpenInfoEdit() : undefined)} colorSchema="gray"
> onClick={() => (appDetail.permission.hasManagePer ? onOpenInfoEdit() : undefined)}
<PermissionIconText defaultPermission={appDetail.defaultPermission} /> >
</MyTag> <PermissionIconText defaultPermission={appDetail.defaultPermission} />
</MyTag>
)}
</HStack> </HStack>
</Box> </Box>
{TeamTagsSet && <TagsEditModal onClose={() => setTeamTagsSet(undefined)} />} {TeamTagsSet && <TagsEditModal onClose={() => setTeamTagsSet(undefined)} />}

View File

@@ -29,7 +29,6 @@ import type { SettingAIDataType } from '@fastgpt/global/core/app/type.d';
import DeleteIcon, { hoverDeleteStyles } from '@fastgpt/web/components/common/Icon/delete'; import DeleteIcon, { hoverDeleteStyles } from '@fastgpt/web/components/common/Icon/delete';
import { TTSTypeEnum } from '@/web/core/app/constants'; import { TTSTypeEnum } from '@/web/core/app/constants';
import { getSystemVariables } from '@/web/core/app/utils'; import { getSystemVariables } from '@/web/core/app/utils';
import { useUpdate } from 'ahooks';
import { useI18n } from '@/web/context/I18n'; import { useI18n } from '@/web/context/I18n';
import { useContextSelector } from 'use-context-selector'; import { useContextSelector } from 'use-context-selector';
import { AppContext } from '@/pages/app/detail/components/context'; import { AppContext } from '@/pages/app/detail/components/context';
@@ -49,7 +48,7 @@ const ScheduledTriggerConfig = dynamic(
const WelcomeTextConfig = dynamic(() => import('@/components/core/app/WelcomeTextConfig')); const WelcomeTextConfig = dynamic(() => import('@/components/core/app/WelcomeTextConfig'));
const BoxStyles: BoxProps = { const BoxStyles: BoxProps = {
px: 5, px: [4, 6],
py: '16px', py: '16px',
borderBottomWidth: '1px', borderBottomWidth: '1px',
borderBottomColor: 'borderColor.low' borderBottomColor: 'borderColor.low'

View File

@@ -140,7 +140,7 @@ const ChatHistorySlider = ({
fontSize={'sm'} fontSize={'sm'}
onClick={() => onClick={() =>
canRouteToDetail && canRouteToDetail &&
router.replace({ router.push({
pathname: '/app/detail', pathname: '/app/detail',
query: { appId } query: { appId }
}) })
@@ -156,27 +156,26 @@ const ChatHistorySlider = ({
{/* menu */} {/* menu */}
<Flex w={'100%'} px={[2, 5]} h={'36px'} my={5} alignItems={'center'}> <Flex w={'100%'} px={[2, 5]} h={'36px'} my={5} alignItems={'center'}>
<Box flex={'1 0 0'}> {!isPc && appId && (
{!isPc && appId && ( <LightRowTabs<TabEnum>
<LightRowTabs<TabEnum> flex={'1 0 0'}
mr={1} mr={1}
inlineStyles={{ inlineStyles={{
px: 1 px: 1
}} }}
list={[ list={[
{ label: t('core.chat.Recent use'), value: TabEnum.recently }, { label: t('core.chat.Recent use'), value: TabEnum.recently },
...(!isTeamChat ? [{ label: t('App'), value: TabEnum.app }] : []), ...(!isTeamChat ? [{ label: t('App'), value: TabEnum.app }] : []),
{ label: t('core.chat.History'), value: TabEnum.history } { label: t('core.chat.History'), value: TabEnum.history }
]} ]}
value={currentTab} value={currentTab}
onChange={setCurrentTab} onChange={setCurrentTab}
/> />
)} )}
</Box>
<Button <Button
variant={'whitePrimary'} variant={'whitePrimary'}
flex={['auto', 1]} flex={[appId ? '0 0 auto' : 1, 1]}
h={'100%'} h={'100%'}
color={'primary.600'} color={'primary.600'}
borderRadius={'xl'} borderRadius={'xl'}

View File

@@ -11,7 +11,7 @@ const ToolMenu = ({ history }: { history: ChatItemType[] }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { onExportChat } = useChatBox(); const { onExportChat } = useChatBox();
const router = useRouter(); const router = useRouter();
console.log(history);
return history.length > 0 ? ( return history.length > 0 ? (
<MyMenu <MyMenu
Button={ Button={

View File

@@ -34,7 +34,6 @@ export async function insertData2Dataset({
session?: ClientSession; session?: ClientSession;
}) { }) {
if (!q || !datasetId || !collectionId || !model) { if (!q || !datasetId || !collectionId || !model) {
console.log(q, a, datasetId, collectionId, model);
return Promise.reject('q, datasetId, collectionId, model is required'); return Promise.reject('q, datasetId, collectionId, model is required');
} }
if (String(teamId) === String(tmbId)) { if (String(teamId) === String(tmbId)) {
@@ -140,7 +139,7 @@ export async function updateData2Dataset({
formatIndexes.unshift(defaultIndex ? defaultIndex : getDefaultIndex({ q, a })); formatIndexes.unshift(defaultIndex ? defaultIndex : getDefaultIndex({ q, a }));
} }
formatIndexes = formatIndexes.slice(0, 6); formatIndexes = formatIndexes.slice(0, 6);
console.log(formatIndexes);
// patch indexes, create, update, delete // patch indexes, create, update, delete
const patchResult: PatchIndexesProps[] = []; const patchResult: PatchIndexesProps[] = [];

View File

@@ -441,41 +441,46 @@ export const compareWorkflow = (workflow1: WorkflowType, workflow2: WorkflowType
return false; return false;
} }
const node1 = clone1.nodes.filter(Boolean).map((node) => ({ const formatNodes = (nodes: StoreNodeItemType[]) => {
flowNodeType: node.flowNodeType, return nodes
inputs: node.inputs.map((input) => ({ .filter((node) => {
...input, if (!node) return;
value: input.value ?? undefined if ([FlowNodeTypeEnum.systemConfig].includes(node.flowNodeType)) return;
})),
outputs: node.outputs.map((input) => ({ return true;
...input, })
value: input.value ?? undefined .map((node) => ({
})), flowNodeType: node.flowNodeType,
name: node.name, inputs: node.inputs.map((input) => ({
intro: node.intro, key: input.key,
avatar: node.avatar, selectedTypeIndex: input.selectedTypeIndex ?? 0,
version: node.version, renderTypeLis: input.renderTypeList,
position: node.position valueType: input.valueType,
})); value: input.value ?? undefined
const node2 = clone2.nodes.filter(Boolean).map((node) => ({ })),
flowNodeType: node.flowNodeType, outputs: node.outputs.map((item) => ({
inputs: node.inputs.map((input) => ({ key: item.key,
...input, type: item.type,
value: input.value ?? undefined value: item.value ?? undefined
})), })),
outputs: node.outputs.map((input) => ({ name: node.name,
...input, intro: node.intro,
value: input.value ?? undefined avatar: node.avatar,
})), version: node.version,
name: node.name, position: node.position
intro: node.intro, }));
avatar: node.avatar, };
version: node.version, const node1 = formatNodes(clone1.nodes);
position: node.position const node2 = formatNodes(clone2.nodes);
}));
// console.log(node1); // console.log(node1);
// console.log(node2); // console.log(node2);
node1.forEach((node, i) => {
if (!isEqual(node, node2[i])) {
console.log('node not equal');
}
});
return isEqual(node1, node2); return isEqual(node1, node2);
}; };