File input (#2270)

* doc

* feat: file upload  config

* perf: chat box file params

* feat: markdown show file

* feat: chat file store and clear

* perf: read file contentType

* feat: llm vision config

* feat: file url output

* perf: plugin error text

* perf: image load

* feat: ai chat document

* perf: file block ui

* feat: read file node

* feat: file read response field

* feat: simple mode support read files

* feat: tool call

* feat: read file histories

* perf: select file

* perf: select file config

* i18n

* i18n

* fix: ts; feat: tool response preview result
This commit is contained in:
Archer
2024-08-06 10:00:22 +08:00
committed by GitHub
parent 10dcdb5491
commit e36d9d794f
121 changed files with 2600 additions and 1142 deletions

View File

@@ -38,7 +38,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
})();
res.setHeader('Content-Type', `${file.contentType}; charset=${encoding}`);
res.setHeader('Cache-Control', 'public, max-age=3600');
res.setHeader('Cache-Control', 'public, max-age=31536000');
res.setHeader('Content-Disposition', `inline; filename="${encodeURIComponent(file.filename)}"`);
stream.pipe(res);

View File

@@ -1,12 +1,14 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { uploadFile } from '@fastgpt/service/common/file/gridfs/controller';
import { getUploadModel } from '@fastgpt/service/common/file/multer';
import { removeFilesByPaths } from '@fastgpt/service/common/file/utils';
import { NextAPI } from '@/service/middleware/entry';
import { createFileToken } from '@fastgpt/service/support/permission/controller';
import { ReadFileBaseUrl } from '@fastgpt/global/common/file/constants';
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
/* Creates the multer uploader */
const upload = getUploadModel({
maxSize: (global.feConfigs?.uploadFileMaxSize || 500) * 1024 * 1024
@@ -14,11 +16,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const filePaths: string[] = [];
try {
await connectToDatabase();
const { file, bucketName, metadata } = await upload.doUpload(req, res);
filePaths.push(file.path);
const { teamId, tmbId } = await authCert({ req, authToken: true });
if (!bucketName) {
@@ -35,8 +34,21 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
metadata: metadata
});
jsonRes(res, {
data: fileId
jsonRes<{
fileId: string;
previewUrl: string;
}>(res, {
data: {
fileId,
previewUrl: `${ReadFileBaseUrl}?filename=${file.originalname}&token=${await createFileToken(
{
bucketName,
teamId,
tmbId,
fileId
}
)}`
}
});
} catch (error) {
jsonRes(res, {
@@ -48,6 +60,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
removeFilesByPaths(filePaths);
}
export default NextAPI(handler);
export const config = {
api: {
bodyParser: false

View File

@@ -15,6 +15,7 @@ import {
import { findAppAndAllChildren } from '@fastgpt/service/core/app/controller';
import { MongoResourcePermission } from '@fastgpt/service/support/permission/schema';
import { ClientSession } from '@fastgpt/service/common/mongo';
import { deleteChatFiles } from '@fastgpt/service/core/chat/controller';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
const { appId } = req.query as { appId: string };
@@ -53,6 +54,7 @@ export const onDelOneApp = async ({
for await (const app of apps) {
const appId = app._id;
// Chats
await deleteChatFiles({ appId });
await MongoChatItem.deleteMany(
{
appId

View File

@@ -21,6 +21,7 @@ import {
import { NextAPI } from '@/service/middleware/entry';
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
import { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type';
import { AppChatConfigType } from '@fastgpt/global/core/app/type';
export type Props = {
messages: ChatCompletionMessageParam[];
@@ -29,6 +30,7 @@ export type Props = {
variables: Record<string, any>;
appId: string;
appName: string;
chatConfig: AppChatConfigType;
};
async function handler(req: NextApiRequest, res: NextApiResponse) {
@@ -40,7 +42,15 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
res.end();
});
let { nodes = [], edges = [], messages = [], variables = {}, appName, appId } = req.body as Props;
let {
nodes = [],
edges = [],
messages = [],
variables = {},
appName,
appId,
chatConfig
} = req.body as Props;
try {
// [histories, user]
const chatMessages = GPTMessages2Chats(messages);
@@ -79,6 +89,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
/* start process */
const { flowResponses, flowUsages } = await dispatchWorkFlow({
res,
requestOrigin: req.headers.origin,
mode: 'test',
teamId,
tmbId,
@@ -88,6 +99,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
runtimeEdges: edges,
variables,
query: removeEmptyUserInput(userInput),
chatConfig,
histories: chatMessages,
stream: true,
detail: true,

View File

@@ -1,6 +1,5 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
@@ -8,64 +7,71 @@ import { ClearHistoriesProps } from '@/global/core/chat/api';
import { authOutLink } from '@/service/support/permission/auth/outLink';
import { ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
import { authTeamSpaceToken } from '@/service/support/permission/auth/team';
import { NextAPI } from '@/service/middleware/entry';
import { deleteChatFiles } from '@fastgpt/service/core/chat/controller';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
/* clear chat history */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
const { appId, shareId, outLinkUid, teamId, teamToken } = req.query as ClearHistoriesProps;
async function handler(req: NextApiRequest, res: NextApiResponse) {
const { appId, shareId, outLinkUid, teamId, teamToken } = req.query as ClearHistoriesProps;
let chatAppId = appId;
let chatAppId = appId!;
const match = await (async () => {
if (shareId && outLinkUid) {
const { appId, uid } = await authOutLink({ shareId, outLinkUid });
const match = await (async () => {
if (shareId && outLinkUid) {
const { appId, uid } = await authOutLink({ shareId, outLinkUid });
chatAppId = appId;
return {
shareId,
outLinkUid: uid
};
}
if (teamId && teamToken) {
const { uid } = await authTeamSpaceToken({ teamId, teamToken });
return {
teamId,
appId,
outLinkUid: uid
};
}
if (appId) {
const { tmbId } = await authCert({ req, authToken: true });
chatAppId = appId;
return {
shareId,
outLinkUid: uid
};
}
if (teamId && teamToken) {
const { uid } = await authTeamSpaceToken({ teamId, teamToken });
return {
teamId,
appId,
outLinkUid: uid
};
}
if (appId) {
const { tmbId } = await authCert({ req, authToken: true });
return {
tmbId,
appId,
source: ChatSourceEnum.online
};
}
return {
tmbId,
appId,
source: ChatSourceEnum.online
};
}
return Promise.reject('Param are error');
})();
return Promise.reject('Param are error');
})();
// find chatIds
const list = await MongoChat.find(match, 'chatId').lean();
const idList = list.map((item) => item.chatId);
// find chatIds
const list = await MongoChat.find(match, 'chatId').lean();
const idList = list.map((item) => item.chatId);
await MongoChatItem.deleteMany({
appId: chatAppId,
chatId: { $in: idList }
});
await MongoChat.deleteMany({
appId: chatAppId,
chatId: { $in: idList }
});
await deleteChatFiles({ chatIdList: idList });
jsonRes(res);
} catch (err) {
jsonRes(res, {
code: 500,
error: err
});
}
await mongoSessionRun(async (session) => {
await MongoChatItem.deleteMany(
{
appId: chatAppId,
chatId: { $in: idList }
},
{ session }
);
await MongoChat.deleteMany(
{
appId: chatAppId,
chatId: { $in: idList }
},
{ session }
);
});
jsonRes(res);
}
export default NextAPI(handler);

View File

@@ -1,4 +1,4 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import type { NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoChatItem } from '@fastgpt/service/core/chat/chatItemSchema';
@@ -8,6 +8,7 @@ import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { NextAPI } from '@/service/middleware/entry';
import { ApiRequestProps } from '@fastgpt/service/type/next';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { deleteChatFiles } from '@fastgpt/service/core/chat/controller';
/* clear chat history */
async function handler(req: ApiRequestProps<{}, DelHistoryProps>, res: NextApiResponse) {
@@ -20,6 +21,7 @@ async function handler(req: ApiRequestProps<{}, DelHistoryProps>, res: NextApiRe
per: WritePermissionVal
});
await deleteChatFiles({ chatIdList: [chatId] });
await mongoSessionRun(async (session) => {
await MongoChatItem.deleteMany(
{
@@ -28,7 +30,7 @@ async function handler(req: ApiRequestProps<{}, DelHistoryProps>, res: NextApiRe
},
{ session }
);
await MongoChat.findOneAndRemove(
await MongoChat.deleteOne(
{
appId,
chatId

View File

@@ -41,6 +41,7 @@ async function handler(
/* start process */
const { flowUsages, flowResponses, debugResponse } = await dispatchWorkFlow({
res,
requestOrigin: req.headers.origin,
mode: 'debug',
teamId,
tmbId,
@@ -50,6 +51,7 @@ async function handler(
runtimeEdges: edges,
variables,
query: [],
chatConfig: defaultApp.chatConfig,
histories: [],
stream: false,
detail: true,

View File

@@ -249,6 +249,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
if (app.version === 'v2') {
return dispatchWorkFlow({
res,
requestOrigin: req.headers.origin,
mode: 'chat',
user,
teamId: String(teamId),
@@ -260,6 +261,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
runtimeEdges: initWorkflowEdgeStatus(edges),
variables: runtimeVariables,
query: removeEmptyUserInput(userQuestion.value),
chatConfig,
histories: newHistories,
stream,
detail,