mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-21 11:43:56 +00:00
v4.4.5-2 (#355)
This commit is contained in:
23
docSite/content/docs/installation/upgrading/445.md
Normal file
23
docSite/content/docs/installation/upgrading/445.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: '升级到 V4.4.5'
|
||||
description: 'FastGPT 从旧版本升级到 V4.4.5 操作指南'
|
||||
icon: 'upgrade'
|
||||
draft: false
|
||||
toc: true
|
||||
weight: 992
|
||||
---
|
||||
|
||||
## 执行初始化 API
|
||||
|
||||
发起 1 个 HTTP 请求(记得携带 `headers.rootkey`,这个值是环境变量里的)
|
||||
|
||||
1. https://xxxxx/api/admin/initv445
|
||||
|
||||
```bash
|
||||
curl --location --request POST 'https://{{host}}/api/admin/initv445' \
|
||||
--header 'rootkey: {{rootkey}}' \
|
||||
--header 'Content-Type: application/json'
|
||||
```
|
||||
|
||||
初始化了 variable 模块,将其合并到用户引导模块中。
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { UserModelSchema } from '@/types/mongoSchema';
|
||||
import { UserModelSchema } from '../user/type';
|
||||
import { Configuration, OpenAIApi } from 'openai';
|
||||
|
||||
export const openaiBaseUrl = process.env.OPENAI_BASE_URL || 'https://api.openai.com/v1';
|
1
packages/core/aiApi/constant.ts
Normal file
1
packages/core/aiApi/constant.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { ChatCompletionRequestMessageRoleEnum } from 'openai';
|
1
packages/core/aiApi/type.d.ts
vendored
Normal file
1
packages/core/aiApi/type.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
||||
export type { CreateChatCompletionRequest, ChatCompletionRequestMessage } from 'openai';
|
13
packages/core/init.ts
Normal file
13
packages/core/init.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import tunnel from 'tunnel';
|
||||
|
||||
export function initHttpAgent() {
|
||||
// proxy obj
|
||||
if (process.env.AXIOS_PROXY_HOST && process.env.AXIOS_PROXY_PORT) {
|
||||
global.httpsAgent = tunnel.httpsOverHttp({
|
||||
proxy: {
|
||||
host: process.env.AXIOS_PROXY_HOST,
|
||||
port: +process.env.AXIOS_PROXY_PORT
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@@ -1,4 +1,11 @@
|
||||
{
|
||||
"name": "@fastgpt/core",
|
||||
"version": "1.0.0"
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"openai": "^3.3.0",
|
||||
"tunnel": "^0.0.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/tunnel": "^0.0.4"
|
||||
}
|
||||
}
|
||||
|
5
packages/core/types/index.d.ts
vendored
Normal file
5
packages/core/types/index.d.ts
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
import type { Agent } from 'http';
|
||||
|
||||
declare global {
|
||||
var httpsAgent: Agent;
|
||||
}
|
19
packages/core/user/type.d.ts
vendored
Normal file
19
packages/core/user/type.d.ts
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
export type UserModelSchema = {
|
||||
_id: string;
|
||||
username: string;
|
||||
password: string;
|
||||
avatar: string;
|
||||
balance: number;
|
||||
promotionRate: number;
|
||||
inviterId?: string;
|
||||
openaiKey: string;
|
||||
createTime: number;
|
||||
timezone: string;
|
||||
openaiAccount?: {
|
||||
key: string;
|
||||
baseUrl: string;
|
||||
};
|
||||
limit: {
|
||||
exportKbTime?: Date;
|
||||
};
|
||||
};
|
28
pnpm-lock.yaml
generated
28
pnpm-lock.yaml
generated
@@ -29,7 +29,18 @@ importers:
|
||||
|
||||
packages/common: {}
|
||||
|
||||
packages/core: {}
|
||||
packages/core:
|
||||
dependencies:
|
||||
openai:
|
||||
specifier: ^3.3.0
|
||||
version: registry.npmmirror.com/openai@3.3.0
|
||||
tunnel:
|
||||
specifier: ^0.0.6
|
||||
version: registry.npmmirror.com/tunnel@0.0.6
|
||||
devDependencies:
|
||||
'@types/tunnel':
|
||||
specifier: ^0.0.4
|
||||
version: registry.npmmirror.com/@types/tunnel@0.0.4
|
||||
|
||||
packages/support: {}
|
||||
|
||||
@@ -152,9 +163,6 @@ importers:
|
||||
nprogress:
|
||||
specifier: ^0.2.0
|
||||
version: registry.npmmirror.com/nprogress@0.2.0
|
||||
openai:
|
||||
specifier: ^3.3.0
|
||||
version: registry.npmmirror.com/openai@3.3.0
|
||||
papaparse:
|
||||
specifier: ^5.4.1
|
||||
version: registry.npmmirror.com/papaparse@5.4.1
|
||||
@@ -209,9 +217,6 @@ importers:
|
||||
timezones-list:
|
||||
specifier: ^3.0.2
|
||||
version: registry.npmmirror.com/timezones-list@3.0.2
|
||||
tunnel:
|
||||
specifier: ^0.0.6
|
||||
version: registry.npmmirror.com/tunnel@0.0.6
|
||||
winston:
|
||||
specifier: ^3.10.0
|
||||
version: registry.npmmirror.com/winston@3.10.0
|
||||
@@ -270,9 +275,6 @@ importers:
|
||||
'@types/request-ip':
|
||||
specifier: ^0.0.37
|
||||
version: registry.npmmirror.com/@types/request-ip@0.0.37
|
||||
'@types/tunnel':
|
||||
specifier: ^0.0.3
|
||||
version: registry.npmmirror.com/@types/tunnel@0.0.3
|
||||
eslint:
|
||||
specifier: 8.34.0
|
||||
version: registry.npmmirror.com/eslint@8.34.0
|
||||
@@ -5611,10 +5613,10 @@ packages:
|
||||
version: 1.3.3
|
||||
dev: false
|
||||
|
||||
registry.npmmirror.com/@types/tunnel@0.0.3:
|
||||
resolution: {integrity: sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/tunnel/-/tunnel-0.0.3.tgz}
|
||||
registry.npmmirror.com/@types/tunnel@0.0.4:
|
||||
resolution: {integrity: sha512-bQgDBL5XiqrrPUaZd9bZ2esOXcU4GTmgg0n6LHDqoMJezO3VFRZsW8qN6Gp64/LAmjtzNU3iAHBfV3Z2ht5DSg==, registry: https://registry.npm.taobao.org/, tarball: https://registry.npmmirror.com/@types/tunnel/-/tunnel-0.0.4.tgz}
|
||||
name: '@types/tunnel'
|
||||
version: 0.0.3
|
||||
version: 0.0.4
|
||||
dependencies:
|
||||
'@types/node': registry.npmmirror.com/@types/node@18.14.0
|
||||
dev: true
|
||||
|
@@ -14,6 +14,9 @@
|
||||
"@chakra-ui/system": "^2.5.8",
|
||||
"@emotion/react": "^11.10.6",
|
||||
"@emotion/styled": "^11.10.6",
|
||||
"@fastgpt/common": "workspace:*",
|
||||
"@fastgpt/core": "workspace:*",
|
||||
"@fastgpt/support": "workspace:*",
|
||||
"@mozilla/readability": "^0.4.4",
|
||||
"@tanstack/react-query": "^4.24.10",
|
||||
"@types/nprogress": "^0.2.0",
|
||||
@@ -45,7 +48,6 @@
|
||||
"next-i18next": "^14.0.3",
|
||||
"nextjs-cors": "^2.1.2",
|
||||
"nprogress": "^0.2.0",
|
||||
"openai": "^3.3.0",
|
||||
"papaparse": "^5.4.1",
|
||||
"pg": "^8.10.0",
|
||||
"pg-query-stream": "^4.5.3",
|
||||
@@ -64,13 +66,9 @@
|
||||
"request-ip": "^3.3.0",
|
||||
"sass": "^1.58.3",
|
||||
"timezones-list": "^3.0.2",
|
||||
"tunnel": "^0.0.6",
|
||||
"winston": "^3.10.0",
|
||||
"winston-mongodb": "^5.1.1",
|
||||
"zustand": "^4.3.5",
|
||||
"@fastgpt/support": "workspace:*",
|
||||
"@fastgpt/common": "workspace:*",
|
||||
"@fastgpt/core": "workspace:*"
|
||||
"zustand": "^4.3.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@svgr/webpack": "^6.5.1",
|
||||
@@ -89,7 +87,6 @@
|
||||
"@types/react-dom": "18.0.11",
|
||||
"@types/react-syntax-highlighter": "^15.5.6",
|
||||
"@types/request-ip": "^0.0.37",
|
||||
"@types/tunnel": "^0.0.3",
|
||||
"eslint": "8.34.0",
|
||||
"eslint-config-next": "13.1.6",
|
||||
"typescript": "4.9.5"
|
||||
|
@@ -237,8 +237,10 @@
|
||||
"outlink": {
|
||||
"Copy Iframe": "Copy Iframe",
|
||||
"Copy Link": "Copy",
|
||||
"Create API Key": "Create Key",
|
||||
"Create Link": "Create Link",
|
||||
"Delete Link": "Delete",
|
||||
"Edit API Key": "Edit Key",
|
||||
"Edit Ifrme Link": "Edit Iframe Link",
|
||||
"Edit Link": "Edit",
|
||||
"Edit Share Window": "Edit Share Window",
|
||||
|
@@ -230,15 +230,17 @@
|
||||
"Tools": "工具"
|
||||
},
|
||||
"openapi": {
|
||||
"app key tips": "这些 Key 已有当前应用标识,可以直接外部接入使用。",
|
||||
"app key tips": "这些 key 已有当前应用标识,具体使用可参考文档",
|
||||
"key alias": "key 的别名,仅用于展示",
|
||||
"key tips": "你可以使用 API 秘钥访问一些特定的接口"
|
||||
},
|
||||
"outlink": {
|
||||
"Copy Iframe": "复制嵌入",
|
||||
"Copy Link": "复制",
|
||||
"Create API Key": "创建新 Key",
|
||||
"Create Link": "创建链接",
|
||||
"Delete Link": "删除链接",
|
||||
"Edit API Key": "编辑 Key 信息",
|
||||
"Edit Ifrme Link": "更新嵌入链接",
|
||||
"Edit Link": "编辑",
|
||||
"Edit Share Window": "更新分享窗口",
|
||||
|
@@ -3,16 +3,14 @@ import { FlowModuleTypeEnum } from '@/constants/flow';
|
||||
import { getChatModel } from '@/service/utils/data';
|
||||
import { AppModuleItemType, VariableItemType } from '@/types/app';
|
||||
|
||||
export const getSpecialModule = (modules: AppModuleItemType[]) => {
|
||||
export const getGuideModules = (modules: AppModuleItemType[]) => {
|
||||
const guideModules = modules.find((item) => item.flowType === FlowModuleTypeEnum.userGuide);
|
||||
|
||||
const welcomeText: string =
|
||||
modules
|
||||
.find((item) => item.flowType === FlowModuleTypeEnum.userGuide)
|
||||
?.inputs?.find((item) => item.key === SystemInputEnum.welcomeText)?.value || '';
|
||||
guideModules?.inputs?.find((item) => item.key === SystemInputEnum.welcomeText)?.value || '';
|
||||
|
||||
const variableModules: VariableItemType[] =
|
||||
modules
|
||||
.find((item) => item.flowType === FlowModuleTypeEnum.variable)
|
||||
?.inputs.find((item) => item.key === SystemInputEnum.variables)?.value || [];
|
||||
guideModules?.inputs.find((item) => item.key === SystemInputEnum.variables)?.value || [];
|
||||
|
||||
return {
|
||||
welcomeText,
|
||||
|
@@ -1,12 +1,20 @@
|
||||
import React from 'react';
|
||||
import { Spinner, Flex, Box } from '@chakra-ui/react';
|
||||
|
||||
const Loading = ({ fixed = true, text = '' }: { fixed?: boolean; text?: string }) => {
|
||||
const Loading = ({
|
||||
fixed = true,
|
||||
text = '',
|
||||
bg = 'rgba(255,255,255,0.5)'
|
||||
}: {
|
||||
fixed?: boolean;
|
||||
text?: string;
|
||||
bg?: string;
|
||||
}) => {
|
||||
return (
|
||||
<Flex
|
||||
position={fixed ? 'fixed' : 'absolute'}
|
||||
zIndex={1000}
|
||||
backgroundColor={'rgba(255,255,255,0.5)'}
|
||||
bg={bg}
|
||||
top={0}
|
||||
left={0}
|
||||
right={0}
|
||||
|
@@ -106,7 +106,7 @@ const ApiKeyTable = ({ tips, appId }: { tips: string; appId?: string }) => {
|
||||
onClick={() => copyData(baseUrl, '已复制 API 地址')}
|
||||
>
|
||||
<Box border={theme.borders.md} px={2} borderRadius={'md'} fontSize={'sm'}>
|
||||
API地址
|
||||
API根地址
|
||||
</Box>
|
||||
<Box ml={2} color={'myGray.900'} fontSize={['sm', 'md']}>
|
||||
{baseUrl}
|
||||
@@ -292,7 +292,7 @@ function EditKeyModal({
|
||||
});
|
||||
|
||||
return (
|
||||
<MyModal isOpen={true} title={isEdit ? t('outlink.Edit Link') : t('outlink.Create Link')}>
|
||||
<MyModal isOpen={true} title={isEdit ? t('outlink.Edit API Key') : t('outlink.Create API Key')}>
|
||||
<ModalBody>
|
||||
<Flex alignItems={'center'}>
|
||||
<Box flex={'0 0 90px'}>{t('Name')}:</Box>
|
||||
|
@@ -24,12 +24,14 @@ export const ChatModelLimitTip =
|
||||
export const userGuideTip = '可以添加特殊的对话前后引导模块,更好的让用户进行对话';
|
||||
export const welcomeTextTip =
|
||||
'每次对话开始前,发送一个初始内容。支持标准 Markdown 语法,可使用的额外标记:\n[快捷按键]: 用户点击后可以直接发送该问题';
|
||||
export const variableTip =
|
||||
'可以在对话开始前,要求用户填写一些内容作为本轮对话的特定变量。该模块位于开场引导之后。\n变量可以通过 {{变量key}} 的形式注入到其他模块 string 类型的输入中,例如:提示词、限定词等';
|
||||
|
||||
export const VariableModule: FlowModuleTemplateType = {
|
||||
flowType: FlowModuleTypeEnum.variable,
|
||||
logo: '/imgs/module/variable.png',
|
||||
name: '全局变量',
|
||||
intro: '可以在对话开始前,要求用户填写一些内容作为本轮对话的变量。该模块位于开场引导之后。',
|
||||
intro: variableTip,
|
||||
description:
|
||||
'全局变量可以通过 {{变量key}} 的形式注入到其他模块 string 类型的输入中,例如:提示词、限定词等',
|
||||
inputs: [
|
||||
@@ -52,6 +54,12 @@ export const UserGuideModule: FlowModuleTemplateType = {
|
||||
key: SystemInputEnum.welcomeText,
|
||||
type: FlowInputItemTypeEnum.input,
|
||||
label: '开场白'
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.variables,
|
||||
type: FlowInputItemTypeEnum.systemInput,
|
||||
label: '对话框变量',
|
||||
value: []
|
||||
}
|
||||
],
|
||||
outputs: []
|
||||
@@ -476,7 +484,7 @@ export const ModuleTemplates = [
|
||||
},
|
||||
{
|
||||
label: '引导模块',
|
||||
list: [UserGuideModule, VariableModule]
|
||||
list: [UserGuideModule]
|
||||
},
|
||||
{
|
||||
label: '内容生成',
|
||||
@@ -491,7 +499,19 @@ export const ModuleTemplates = [
|
||||
list: [ClassifyQuestionModule, ContextExtractModule, HttpModule]
|
||||
}
|
||||
];
|
||||
export const ModuleTemplatesFlat = ModuleTemplates.map((templates) => templates.list)?.flat();
|
||||
export const ModuleTemplatesFlat = [
|
||||
VariableModule,
|
||||
UserGuideModule,
|
||||
UserInputModule,
|
||||
HistoryModule,
|
||||
ChatModule,
|
||||
KBSearchModule,
|
||||
AnswerModule,
|
||||
ClassifyQuestionModule,
|
||||
ContextExtractModule,
|
||||
HttpModule,
|
||||
EmptyModule
|
||||
];
|
||||
|
||||
// template
|
||||
export const appTemplates: (AppItemType & { avatar: string; intro: string })[] = [
|
||||
|
@@ -1,58 +0,0 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { connectToDatabase, Chat } from '@/service/mongo';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await authUser({ req, authRoot: true });
|
||||
await connectToDatabase();
|
||||
|
||||
const { limit = 1000 } = req.body as { limit: number };
|
||||
let skip = 0;
|
||||
const total = await Chat.countDocuments({
|
||||
chatId: { $exists: false }
|
||||
});
|
||||
let promise = Promise.resolve();
|
||||
console.log(total);
|
||||
|
||||
for (let i = 0; i < total; i += limit) {
|
||||
const skipVal = skip;
|
||||
skip += limit;
|
||||
promise = promise
|
||||
.then(() => init(limit, skipVal))
|
||||
.then(() => {
|
||||
console.log(skipVal);
|
||||
});
|
||||
}
|
||||
|
||||
await promise;
|
||||
|
||||
jsonRes(res, {});
|
||||
} catch (error) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function init(limit: number, skip: number) {
|
||||
// 遍历 app
|
||||
const chats = await Chat.find(
|
||||
{
|
||||
chatId: { $exists: false }
|
||||
},
|
||||
'_id'
|
||||
).limit(limit);
|
||||
|
||||
await Promise.all(
|
||||
chats.map((chat) =>
|
||||
Chat.findByIdAndUpdate(chat._id, {
|
||||
chatId: String(chat._id),
|
||||
source: 'online'
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
@@ -1,98 +0,0 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { connectToDatabase, Chat, ChatItem } from '@/service/mongo';
|
||||
import { customAlphabet } from 'nanoid';
|
||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await authUser({ req, authRoot: true });
|
||||
await connectToDatabase();
|
||||
|
||||
const { limit = 100 } = req.body as { limit: number };
|
||||
let skip = 0;
|
||||
|
||||
const total = await Chat.countDocuments({
|
||||
content: { $exists: true, $not: { $size: 0 } },
|
||||
isInit: { $ne: true }
|
||||
});
|
||||
const totalChat = await Chat.aggregate([
|
||||
{
|
||||
$project: {
|
||||
contentLength: { $size: '$content' }
|
||||
}
|
||||
},
|
||||
{
|
||||
$group: {
|
||||
_id: null,
|
||||
totalLength: { $sum: '$contentLength' }
|
||||
}
|
||||
}
|
||||
]);
|
||||
|
||||
console.log('chatLen:', total, totalChat);
|
||||
|
||||
let promise = Promise.resolve();
|
||||
|
||||
for (let i = 0; i < total; i += limit) {
|
||||
const skipVal = skip;
|
||||
skip += limit;
|
||||
promise = promise
|
||||
.then(() => init(limit))
|
||||
.then(() => {
|
||||
console.log(skipVal);
|
||||
});
|
||||
}
|
||||
|
||||
await promise;
|
||||
|
||||
jsonRes(res, {});
|
||||
} catch (error) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function init(limit: number) {
|
||||
// 遍历 app
|
||||
const chats = await Chat.find(
|
||||
{
|
||||
content: { $exists: true, $not: { $size: 0 } },
|
||||
isInit: { $ne: true }
|
||||
},
|
||||
'_id userId appId chatId content'
|
||||
)
|
||||
.sort({ updateTime: -1 })
|
||||
.limit(limit);
|
||||
|
||||
await Promise.all(
|
||||
chats.map(async (chat) => {
|
||||
const inserts = chat.content
|
||||
.map((item) => ({
|
||||
dataId: nanoid(),
|
||||
chatId: chat.chatId,
|
||||
userId: chat.userId,
|
||||
appId: chat.appId,
|
||||
obj: item.obj,
|
||||
value: item.value,
|
||||
responseData: item.responseData
|
||||
}))
|
||||
.filter((item) => item.chatId && item.userId && item.appId && item.obj && item.value);
|
||||
|
||||
try {
|
||||
await Promise.all(inserts.map((item) => ChatItem.create(item)));
|
||||
await Chat.findByIdAndUpdate(chat._id, {
|
||||
isInit: true
|
||||
});
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
|
||||
await ChatItem.deleteMany({ chatId: chat.chatId });
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
@@ -1,27 +0,0 @@
|
||||
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { connectToDatabase, OutLink } from '@/service/mongo';
|
||||
import { OutLinkTypeEnum } from '@/constants/chat';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await authUser({ req, authRoot: true });
|
||||
await connectToDatabase();
|
||||
|
||||
await OutLink.updateMany(
|
||||
{},
|
||||
{
|
||||
$set: { type: OutLinkTypeEnum.share }
|
||||
}
|
||||
);
|
||||
|
||||
jsonRes(res, {});
|
||||
} catch (error) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error
|
||||
});
|
||||
}
|
||||
}
|
104
projects/app/src/pages/api/admin/initv445.ts
Normal file
104
projects/app/src/pages/api/admin/initv445.ts
Normal file
@@ -0,0 +1,104 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { connectToDatabase, App } from '@/service/mongo';
|
||||
import { FlowInputItemTypeEnum, FlowModuleTypeEnum } from '@/constants/flow';
|
||||
import { SystemInputEnum } from '@/constants/app';
|
||||
|
||||
const limit = 300;
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||
try {
|
||||
await connectToDatabase();
|
||||
await authUser({ req, authRoot: true });
|
||||
|
||||
const totalApps = await App.countDocuments();
|
||||
|
||||
// init app
|
||||
await App.updateMany({}, { $set: { inited: false } });
|
||||
|
||||
for (let i = 0; i < totalApps; i += limit) {
|
||||
await initVariable();
|
||||
console.log(i + limit);
|
||||
}
|
||||
|
||||
jsonRes(res, {
|
||||
data: {
|
||||
total: totalApps
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
jsonRes(res, {
|
||||
code: 500,
|
||||
error
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function initVariable(): Promise<any> {
|
||||
try {
|
||||
const apps = await App.find({ inited: false }).limit(limit);
|
||||
await Promise.all(
|
||||
apps.map(async (app) => {
|
||||
const jsonAPP = app.toObject();
|
||||
// @ts-ignore
|
||||
app.inited = true;
|
||||
const modules = jsonAPP.modules;
|
||||
|
||||
// 找到 variable
|
||||
const variable = modules.find((item) => item.flowType === FlowModuleTypeEnum.variable);
|
||||
if (!variable) return await app.save();
|
||||
|
||||
// 找到 guide 模块
|
||||
const userGuideModule = modules.find(
|
||||
(item) => item.flowType === FlowModuleTypeEnum.userGuide
|
||||
);
|
||||
if (userGuideModule) {
|
||||
userGuideModule.inputs = [
|
||||
userGuideModule.inputs[0],
|
||||
{
|
||||
key: SystemInputEnum.variables,
|
||||
type: FlowInputItemTypeEnum.systemInput,
|
||||
label: '对话框变量',
|
||||
value: variable.inputs[0]?.value
|
||||
}
|
||||
];
|
||||
} else {
|
||||
modules.unshift({
|
||||
moduleId: 'userGuide',
|
||||
flowType: FlowModuleTypeEnum.userGuide,
|
||||
name: '用户引导',
|
||||
position: {
|
||||
x: 447.98520778293346,
|
||||
y: 721.4016845336229
|
||||
},
|
||||
inputs: [
|
||||
{
|
||||
key: SystemInputEnum.welcomeText,
|
||||
type: FlowInputItemTypeEnum.input,
|
||||
label: '开场白'
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.variables,
|
||||
type: FlowInputItemTypeEnum.systemInput,
|
||||
label: '对话框变量',
|
||||
value: variable.inputs[0]?.value
|
||||
}
|
||||
],
|
||||
outputs: []
|
||||
});
|
||||
}
|
||||
|
||||
jsonAPP.modules = jsonAPP.modules.filter(
|
||||
(item) => item.flowType !== FlowModuleTypeEnum.variable
|
||||
);
|
||||
|
||||
app.modules = JSON.parse(JSON.stringify(jsonAPP.modules));
|
||||
|
||||
await app.save();
|
||||
})
|
||||
);
|
||||
} catch (error) {
|
||||
return initVariable();
|
||||
}
|
||||
}
|
@@ -6,7 +6,7 @@ import { authUser } from '@/service/utils/auth';
|
||||
import { ChatItemType } from '@/types/chat';
|
||||
import { authApp } from '@/service/utils/auth';
|
||||
import type { ChatSchema } from '@/types/mongoSchema';
|
||||
import { getSpecialModule, getChatModelNameList } from '@/components/ChatBox/utils';
|
||||
import { getGuideModules, getChatModelNameList } from '@/components/ChatBox/utils';
|
||||
import { TaskResponseKeyEnum } from '@/constants/chat';
|
||||
|
||||
/* 初始化我的聊天框,需要身份验证 */
|
||||
@@ -81,7 +81,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
chatId,
|
||||
appId,
|
||||
app: {
|
||||
...getSpecialModule(app.modules),
|
||||
...getGuideModules(app.modules),
|
||||
chatModels: getChatModelNameList(app.modules),
|
||||
name: app.name,
|
||||
avatar: app.avatar,
|
||||
|
@@ -18,7 +18,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
|
||||
await collection.updateMany(
|
||||
{
|
||||
_id: { $in: fileIds.map((id) => new Types.ObjectId(id)) },
|
||||
_id: { $in: fileIds.filter((id) => !!id).map((id) => new Types.ObjectId(id)) },
|
||||
['metadata.userId']: userId
|
||||
},
|
||||
{
|
||||
|
@@ -2,7 +2,7 @@ import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@/service/response';
|
||||
import { authBalanceByUid, authUser } from '@/service/utils/auth';
|
||||
import { withNextCors } from '@/service/utils/tools';
|
||||
import { getAIChatApi, axiosConfig } from '@/service/lib/openai';
|
||||
import { getAIChatApi, axiosConfig } from '@fastgpt/core/aiApi/config';
|
||||
import { pushGenerateVectorBill } from '@/service/common/bill/push';
|
||||
|
||||
type Props = {
|
||||
|
@@ -14,12 +14,14 @@ import {
|
||||
dispatchContentExtract,
|
||||
dispatchHttpRequest
|
||||
} from '@/service/moduleDispatch';
|
||||
import type { CreateChatCompletionRequest } from 'openai';
|
||||
import type {
|
||||
CreateChatCompletionRequest,
|
||||
ChatCompletionRequestMessage
|
||||
} from '@fastgpt/core/aiApi/type';
|
||||
import { gptMessage2ChatType, textAdaptGptResponse } from '@/utils/adapt';
|
||||
import { getChatHistory } from './getHistory';
|
||||
import { saveChat } from '@/service/utils/chat/saveChat';
|
||||
import { sseResponse } from '@/service/utils/tools';
|
||||
import { type ChatCompletionRequestMessage } from 'openai';
|
||||
import { TaskResponseKeyEnum } from '@/constants/chat';
|
||||
import { FlowModuleTypeEnum, initModuleType } from '@/constants/flow';
|
||||
import { AppModuleItemType, RunningModuleItemType } from '@/types/app';
|
||||
|
@@ -4,7 +4,7 @@ import { connectToDatabase, OutLink, User } from '@/service/mongo';
|
||||
import type { InitShareChatResponse } from '@/api/response/chat';
|
||||
import { authApp } from '@/service/utils/auth';
|
||||
import { HUMAN_ICON } from '@/constants/chat';
|
||||
import { getChatModelNameList, getSpecialModule } from '@/components/ChatBox/utils';
|
||||
import { getChatModelNameList, getGuideModules } from '@/components/ChatBox/utils';
|
||||
import { authShareChatInit } from '@/service/support/outLink/auth';
|
||||
|
||||
/* init share chat window */
|
||||
@@ -46,7 +46,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
||||
data: {
|
||||
userAvatar: user?.avatar || HUMAN_ICON,
|
||||
app: {
|
||||
...getSpecialModule(app.modules),
|
||||
...getGuideModules(app.modules),
|
||||
chatModels: getChatModelNameList(app.modules),
|
||||
name: app.name,
|
||||
avatar: app.avatar,
|
||||
|
@@ -5,7 +5,7 @@ import { User } from '@/service/models/user';
|
||||
import { connectToDatabase } from '@/service/mongo';
|
||||
import { authUser } from '@/service/utils/auth';
|
||||
import { UserUpdateParams } from '@/types/user';
|
||||
import { axiosConfig, getAIChatApi, openaiBaseUrl } from '@/service/lib/openai';
|
||||
import { axiosConfig, getAIChatApi, openaiBaseUrl } from '@fastgpt/core/aiApi/config';
|
||||
|
||||
/* update user info */
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
@@ -34,7 +34,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
...axiosConfig(openaiAccount)
|
||||
}
|
||||
);
|
||||
if (!response?.data?.choices?.[0]?.message?.content) {
|
||||
if (response?.data?.choices?.[0]?.message?.content === undefined) {
|
||||
throw new Error(JSON.stringify(response?.data));
|
||||
}
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ import { streamFetch } from '@/api/fetch';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { useUserStore } from '@/store/user';
|
||||
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
|
||||
import { getSpecialModule } from '@/components/ChatBox/utils';
|
||||
import { getGuideModules } from '@/components/ChatBox/utils';
|
||||
|
||||
export type ChatTestComponentRef = {
|
||||
resetChatTest: () => void;
|
||||
@@ -114,7 +114,7 @@ const ChatTest = (
|
||||
appAvatar={app.avatar}
|
||||
userAvatar={userInfo?.avatar}
|
||||
showMarkIcon
|
||||
{...getSpecialModule(modules)}
|
||||
{...getGuideModules(modules)}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={() => {}}
|
||||
/>
|
||||
|
@@ -1,17 +1,49 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { NodeProps } from 'reactflow';
|
||||
import { Box, Flex, Textarea } from '@chakra-ui/react';
|
||||
import {
|
||||
Box,
|
||||
Flex,
|
||||
Textarea,
|
||||
Button,
|
||||
Table,
|
||||
Thead,
|
||||
Tbody,
|
||||
Tr,
|
||||
Th,
|
||||
Td,
|
||||
TableContainer
|
||||
} from '@chakra-ui/react';
|
||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||
import NodeCard from '../modules/NodeCard';
|
||||
import { FlowModuleItemType } from '@/types/flow';
|
||||
import Container from '../modules/Container';
|
||||
import { SystemInputEnum } from '@/constants/app';
|
||||
import { welcomeTextTip, variableTip } from '@/constants/flow/ModuleTemplate';
|
||||
|
||||
import VariableEditModal, { addVariable } from '../../../VariableEditModal';
|
||||
import MyIcon from '@/components/Icon';
|
||||
import MyTooltip from '@/components/MyTooltip';
|
||||
import { welcomeTextTip } from '@/constants/flow/ModuleTemplate';
|
||||
import Container from '../modules/Container';
|
||||
import NodeCard from '../modules/NodeCard';
|
||||
import { VariableItemType } from '@/types/app';
|
||||
|
||||
const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||
return (
|
||||
<>
|
||||
<NodeCard minW={'300px'} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||
<WelcomeText data={data} />
|
||||
<Box mt={3}>
|
||||
<ChatStartVariable data={data} />
|
||||
</Box>
|
||||
</Container>
|
||||
</NodeCard>
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default React.memo(NodeUserGuide);
|
||||
|
||||
export function WelcomeText({ data }: { data: FlowModuleItemType }) {
|
||||
const { inputs, moduleId, onChangeNode } = data;
|
||||
|
||||
const welcomeText = useMemo(
|
||||
() => inputs.find((item) => item.key === SystemInputEnum.welcomeText),
|
||||
[inputs]
|
||||
@@ -19,41 +51,148 @@ const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<NodeCard minW={'300px'} {...data}>
|
||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||
<>
|
||||
<Flex mb={1} alignItems={'center'}>
|
||||
<MyIcon name={'welcomeText'} mr={2} w={'16px'} color={'#E74694'} />
|
||||
<Box>开场白</Box>
|
||||
<MyTooltip label={welcomeTextTip} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
{welcomeText && (
|
||||
<Textarea
|
||||
className="nodrag"
|
||||
rows={6}
|
||||
resize={'both'}
|
||||
defaultValue={welcomeText.value}
|
||||
bg={'myWhite.500'}
|
||||
placeholder={welcomeTextTip}
|
||||
onChange={(e) => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
key: SystemInputEnum.welcomeText,
|
||||
type: 'inputs',
|
||||
value: {
|
||||
...welcomeText,
|
||||
value: e.target.value
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</Container>
|
||||
</NodeCard>
|
||||
<Flex mb={1} alignItems={'center'}>
|
||||
<MyIcon name={'welcomeText'} mr={2} w={'16px'} color={'#E74694'} />
|
||||
<Box>开场白</Box>
|
||||
<MyTooltip label={welcomeTextTip} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
</Flex>
|
||||
{welcomeText && (
|
||||
<Textarea
|
||||
className="nodrag"
|
||||
rows={6}
|
||||
resize={'both'}
|
||||
defaultValue={welcomeText.value}
|
||||
bg={'myWhite.500'}
|
||||
placeholder={welcomeTextTip}
|
||||
onChange={(e) => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
key: SystemInputEnum.welcomeText,
|
||||
type: 'inputs',
|
||||
value: {
|
||||
...welcomeText,
|
||||
value: e.target.value
|
||||
}
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
export default React.memo(NodeUserGuide);
|
||||
}
|
||||
|
||||
function ChatStartVariable({ data }: { data: FlowModuleItemType }) {
|
||||
const { inputs, moduleId, onChangeNode } = data;
|
||||
const variables = useMemo(
|
||||
() =>
|
||||
(inputs.find((item) => item.key === SystemInputEnum.variables)
|
||||
?.value as VariableItemType[]) || [],
|
||||
[inputs]
|
||||
);
|
||||
|
||||
const [editVariable, setEditVariable] = useState<VariableItemType>();
|
||||
|
||||
const updateVariables = useCallback(
|
||||
(value: VariableItemType[]) => {
|
||||
onChangeNode({
|
||||
moduleId,
|
||||
key: SystemInputEnum.variables,
|
||||
type: 'inputs',
|
||||
value: {
|
||||
...inputs.find((item) => item.key === SystemInputEnum.variables),
|
||||
value
|
||||
}
|
||||
});
|
||||
},
|
||||
[inputs, onChangeNode, moduleId]
|
||||
);
|
||||
|
||||
const onclickSubmit = useCallback(
|
||||
({ variable }: { variable: VariableItemType }) => {
|
||||
updateVariables(variables.map((item) => (item.id === variable.id ? variable : item)));
|
||||
setEditVariable(undefined);
|
||||
},
|
||||
[updateVariables, variables]
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex mb={1} alignItems={'center'}>
|
||||
<MyIcon name={'variable'} mr={2} w={'16px'} color={'#fb7c3d'} />
|
||||
<Box>对话框变量</Box>
|
||||
<MyTooltip label={variableTip} forceShow>
|
||||
<QuestionOutlineIcon display={['none', 'inline']} ml={1} />
|
||||
</MyTooltip>
|
||||
<Box flex={1} />
|
||||
<Flex
|
||||
ml={2}
|
||||
textAlign={'right'}
|
||||
cursor={'pointer'}
|
||||
px={3}
|
||||
py={'2px'}
|
||||
borderRadius={'md'}
|
||||
_hover={{ bg: 'myGray.200' }}
|
||||
onClick={() => {
|
||||
const newVariable = addVariable();
|
||||
updateVariables(variables.concat(newVariable));
|
||||
setEditVariable(newVariable);
|
||||
}}
|
||||
>
|
||||
+ 新增
|
||||
</Flex>
|
||||
</Flex>
|
||||
{variables.length > 0 && (
|
||||
<TableContainer borderWidth={'1px'} borderBottom="none" borderRadius={'lg'}>
|
||||
<Table>
|
||||
<Thead>
|
||||
<Tr>
|
||||
<Th>变量名</Th>
|
||||
<Th>变量 key</Th>
|
||||
<Th>必填</Th>
|
||||
<Th></Th>
|
||||
</Tr>
|
||||
</Thead>
|
||||
<Tbody>
|
||||
{variables.map((item, index) => (
|
||||
<Tr key={index}>
|
||||
<Td>{item.label} </Td>
|
||||
<Td>{item.key}</Td>
|
||||
<Td>{item.required ? '✔' : ''}</Td>
|
||||
<Td>
|
||||
<MyIcon
|
||||
mr={3}
|
||||
name={'settingLight'}
|
||||
w={'16px'}
|
||||
cursor={'pointer'}
|
||||
onClick={() => {
|
||||
setEditVariable(item);
|
||||
}}
|
||||
/>
|
||||
<MyIcon
|
||||
name={'delete'}
|
||||
w={'16px'}
|
||||
cursor={'pointer'}
|
||||
onClick={() =>
|
||||
updateVariables(variables.filter((variable) => variable.id !== item.id))
|
||||
}
|
||||
/>
|
||||
</Td>
|
||||
</Tr>
|
||||
))}
|
||||
</Tbody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
)}
|
||||
|
||||
{!!editVariable && (
|
||||
<VariableEditModal
|
||||
defaultVariable={editVariable}
|
||||
onClose={() => setEditVariable(undefined)}
|
||||
onSubmit={onclickSubmit}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@@ -109,7 +109,7 @@ const ModuleTemplateList = ({
|
||||
<Avatar src={item.logo} w={'34px'} objectFit={'contain'} borderRadius={'0'} />
|
||||
<Box ml={5} flex={'1 0 0'}>
|
||||
<Box color={'black'}>{item.name}</Box>
|
||||
<Box color={'myGray.500'} fontSize={'sm'}>
|
||||
<Box className="textEllipsis3" color={'myGray.500'} fontSize={'sm'}>
|
||||
{item.intro}
|
||||
</Box>
|
||||
</Box>
|
||||
|
@@ -46,7 +46,7 @@ import { useToast } from '@/hooks/useToast';
|
||||
import { AppSchema } from '@/types/mongoSchema';
|
||||
import { delModelById } from '@/api/app';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { getSpecialModule } from '@/components/ChatBox/utils';
|
||||
import { getGuideModules } from '@/components/ChatBox/utils';
|
||||
|
||||
import dynamic from 'next/dynamic';
|
||||
import MySelect from '@/components/Select';
|
||||
@@ -410,20 +410,22 @@ const Settings = ({ appId }: { appId: string }) => {
|
||||
|
||||
<Flex alignItems={'center'} mt={5}>
|
||||
<Box {...LabelStyles}>对话模型</Box>
|
||||
<MySelect
|
||||
width={['100%', '300px']}
|
||||
value={getValues('chatModel.model')}
|
||||
list={chatModelSelectList}
|
||||
onchange={(val: any) => {
|
||||
setValue('chatModel.model', val);
|
||||
const maxToken =
|
||||
chatModelList.find((item) => item.model === getValues('chatModel.model'))
|
||||
?.contextMaxToken || 4000;
|
||||
const token = maxToken / 2;
|
||||
setValue('chatModel.maxToken', token);
|
||||
setRefresh(!refresh);
|
||||
}}
|
||||
/>
|
||||
<Box flex={'1 0 0'}>
|
||||
<MySelect
|
||||
width={'100%'}
|
||||
value={getValues('chatModel.model')}
|
||||
list={chatModelSelectList}
|
||||
onchange={(val: any) => {
|
||||
setValue('chatModel.model', val);
|
||||
const maxToken =
|
||||
chatModelList.find((item) => item.model === getValues('chatModel.model'))
|
||||
?.contextMaxToken || 4000;
|
||||
const token = maxToken / 2;
|
||||
setValue('chatModel.maxToken', token);
|
||||
setRefresh(!refresh);
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
</Flex>
|
||||
<Flex alignItems={'center'} my={10}>
|
||||
<Box {...LabelStyles}>温度</Box>
|
||||
@@ -676,7 +678,7 @@ const ChatTest = ({ appId }: { appId: string }) => {
|
||||
appAvatar={appDetail.avatar}
|
||||
userAvatar={userInfo?.avatar}
|
||||
showMarkIcon
|
||||
{...getSpecialModule(modules)}
|
||||
{...getGuideModules(modules)}
|
||||
onStartChat={startChat}
|
||||
onDelMessage={() => {}}
|
||||
/>
|
||||
|
@@ -29,27 +29,24 @@ const Home = ({ homeUrl = '/' }: { homeUrl: string }) => {
|
||||
<Head>
|
||||
<title>{feConfigs?.systemTitle || 'FastGPT'}</title>
|
||||
</Head>
|
||||
{homeUrl === '/' ? (
|
||||
<Box id="home" bg={'myWhite.600'} h={'100vh'} overflowY={'auto'} overflowX={'hidden'}>
|
||||
<Box position={'fixed'} zIndex={10} top={0} left={0} right={0}>
|
||||
<Navbar />
|
||||
</Box>
|
||||
<Box maxW={'1200px'} pt={'70px'} m={'auto'}>
|
||||
<Hero />
|
||||
<Ability />
|
||||
<Box my={[4, 6]}>
|
||||
<Choice />
|
||||
</Box>
|
||||
</Box>
|
||||
{feConfigs?.show_git && (
|
||||
<Box bg={'white'}>
|
||||
<Footer />
|
||||
</Box>
|
||||
)}
|
||||
<Box id="home" bg={'myWhite.600'} h={'100vh'} overflowY={'auto'} overflowX={'hidden'}>
|
||||
<Box position={'fixed'} zIndex={10} top={0} left={0} right={0}>
|
||||
<Navbar />
|
||||
</Box>
|
||||
) : (
|
||||
<Loading />
|
||||
)}
|
||||
<Box maxW={'1200px'} pt={'70px'} m={'auto'}>
|
||||
<Hero />
|
||||
<Ability />
|
||||
<Box my={[4, 6]}>
|
||||
<Choice />
|
||||
</Box>
|
||||
</Box>
|
||||
{feConfigs?.show_git && (
|
||||
<Box bg={'white'}>
|
||||
<Footer />
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
{homeUrl !== '/' && <Loading bg={'white'} />}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@@ -113,7 +113,7 @@ const ChunkImport = ({ kbId }: { kbId: string }) => {
|
||||
chunks: splitRes.chunks.map((chunk) => ({
|
||||
a: '',
|
||||
source: file.filename,
|
||||
file_id: file.id,
|
||||
file_id: file.chunks[0]?.file_id,
|
||||
q: chunk
|
||||
}))
|
||||
};
|
||||
|
@@ -20,7 +20,7 @@ const CreateFileModal = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<MyModal title={t('file.Create File')} isOpen onClose={() => {}} w={'600px'} top={'15vh'}>
|
||||
<MyModal title={t('file.Create File')} isOpen w={'600px'} top={'15vh'}>
|
||||
<ModalBody>
|
||||
<Box mb={1} fontSize={'sm'}>
|
||||
文件名
|
||||
|
@@ -113,7 +113,7 @@ const QAImport = ({ kbId }: { kbId: string }) => {
|
||||
chunks: splitRes.chunks.map((chunk) => ({
|
||||
a: '',
|
||||
source: file.filename,
|
||||
file_id: file.id,
|
||||
file_id: file.chunks[0]?.file_id,
|
||||
q: chunk
|
||||
}))
|
||||
};
|
||||
|
@@ -4,8 +4,8 @@ import { TrainingModeEnum } from '@/constants/plugin';
|
||||
import { ERROR_ENUM } from '../errorCode';
|
||||
import { sendInform } from '@/pages/api/user/inform/send';
|
||||
import { authBalanceByUid } from '../utils/auth';
|
||||
import { axiosConfig, getAIChatApi } from '../lib/openai';
|
||||
import { ChatCompletionRequestMessage } from 'openai';
|
||||
import { axiosConfig, getAIChatApi } from '@fastgpt/core/aiApi/config';
|
||||
import type { ChatCompletionRequestMessage } from '@fastgpt/core/aiApi/type';
|
||||
import { addLog } from '../utils/tools';
|
||||
import { splitText2Chunks } from '@/utils/file';
|
||||
import { replaceVariable } from '@/utils/common/tools/text';
|
||||
|
@@ -56,6 +56,9 @@ const AppSchema = new Schema({
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
inited: {
|
||||
type: Boolean
|
||||
},
|
||||
// 弃
|
||||
chat: Object
|
||||
});
|
||||
|
@@ -2,7 +2,7 @@ import { adaptChat2GptMessages } from '@/utils/common/adapt/message';
|
||||
import { ChatContextFilter } from '@/service/common/tiktoken';
|
||||
import type { ChatHistoryItemResType, ChatItemType } from '@/types/chat';
|
||||
import { ChatRoleEnum, TaskResponseKeyEnum } from '@/constants/chat';
|
||||
import { getAIChatApi, axiosConfig } from '@/service/lib/openai';
|
||||
import { getAIChatApi, axiosConfig } from '@fastgpt/core/aiApi/config';
|
||||
import type { ClassifyQuestionAgentItemType } from '@/types/app';
|
||||
import { SystemInputEnum } from '@/constants/app';
|
||||
import { SpecialInputKeyEnum } from '@/constants/flow';
|
||||
@@ -46,7 +46,7 @@ export const dispatchClassifyQuestion = async (props: Props): Promise<CQResponse
|
||||
return completions(props);
|
||||
})();
|
||||
|
||||
const result = agents.find((item) => item.key === arg?.type) || agents[0];
|
||||
const result = agents.find((item) => item.key === arg?.type) || agents[agents.length - 1];
|
||||
|
||||
return {
|
||||
[result.key]: 1,
|
||||
@@ -120,12 +120,21 @@ async function functionCall({
|
||||
}
|
||||
);
|
||||
|
||||
const arg = JSON.parse(response.data.choices?.[0]?.message?.function_call?.arguments || '');
|
||||
try {
|
||||
const arg = JSON.parse(response.data.choices?.[0]?.message?.function_call?.arguments || '');
|
||||
|
||||
return {
|
||||
arg,
|
||||
tokens: response.data.usage?.total_tokens || 0
|
||||
};
|
||||
return {
|
||||
arg,
|
||||
tokens: response.data.usage?.total_tokens || 0
|
||||
};
|
||||
} catch (error) {
|
||||
console.log('Your model may not support function_call');
|
||||
|
||||
return {
|
||||
arg: {},
|
||||
tokens: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async function completions({
|
||||
|
@@ -2,7 +2,7 @@ import { adaptChat2GptMessages } from '@/utils/common/adapt/message';
|
||||
import { ChatContextFilter } from '@/service/common/tiktoken';
|
||||
import type { ChatHistoryItemResType, ChatItemType } from '@/types/chat';
|
||||
import { ChatRoleEnum, TaskResponseKeyEnum } from '@/constants/chat';
|
||||
import { getAIChatApi, axiosConfig } from '@/service/lib/openai';
|
||||
import { getAIChatApi, axiosConfig } from '@fastgpt/core/aiApi/config';
|
||||
import type { ContextExtractAgentItemType } from '@/types/app';
|
||||
import { ContextExtractEnum } from '@/constants/flow/flowField';
|
||||
import { FlowModuleTypeEnum } from '@/constants/flow';
|
||||
|
@@ -5,13 +5,13 @@ import type { ChatHistoryItemResType } from '@/types/chat';
|
||||
import { ChatRoleEnum, sseResponseEventEnum } from '@/constants/chat';
|
||||
import { SSEParseData, parseStreamChunk } from '@/utils/sse';
|
||||
import { textAdaptGptResponse } from '@/utils/adapt';
|
||||
import { getAIChatApi, axiosConfig } from '@/service/lib/openai';
|
||||
import { getAIChatApi, axiosConfig } from '@fastgpt/core/aiApi/config';
|
||||
import { TaskResponseKeyEnum } from '@/constants/chat';
|
||||
import { getChatModel } from '@/service/utils/data';
|
||||
import { countModelPrice } from '@/service/common/bill/push';
|
||||
import { ChatModelItemType } from '@/types/model';
|
||||
import { textCensor } from '@/api/service/plugins';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from 'openai';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/core/aiApi/constant';
|
||||
import { AppModuleItemType } from '@/types/app';
|
||||
import { countMessagesTokens, sliceMessagesTB } from '@/utils/common/tiktoken';
|
||||
import { adaptChat2GptMessages } from '@/utils/common/adapt/message';
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import mongoose from 'mongoose';
|
||||
import tunnel from 'tunnel';
|
||||
import { startQueue } from './utils/tools';
|
||||
import { getInitConfig } from '@/pages/api/system/getInitData';
|
||||
import { User } from './models/user';
|
||||
@@ -9,6 +8,7 @@ import { createHashPassword } from '@/utils/tools';
|
||||
import { createLogger, format, transports } from 'winston';
|
||||
import 'winston-mongodb';
|
||||
import { getTikTokenEnc } from '@/utils/common/tiktoken';
|
||||
import { initHttpAgent } from '@fastgpt/core/init';
|
||||
|
||||
/**
|
||||
* connect MongoDB and init data
|
||||
@@ -24,15 +24,6 @@ export async function connectToDatabase(): Promise<void> {
|
||||
global.vectorQueueLen = 0;
|
||||
global.sendInformQueue = [];
|
||||
global.sendInformQueueLen = 0;
|
||||
// proxy obj
|
||||
if (process.env.AXIOS_PROXY_HOST && process.env.AXIOS_PROXY_PORT) {
|
||||
global.httpsAgent = tunnel.httpsOverHttp({
|
||||
proxy: {
|
||||
host: process.env.AXIOS_PROXY_HOST,
|
||||
port: +process.env.AXIOS_PROXY_PORT
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// logger
|
||||
initLogger();
|
||||
@@ -41,6 +32,7 @@ export async function connectToDatabase(): Promise<void> {
|
||||
getInitConfig();
|
||||
// init tikToken
|
||||
getTikTokenEnc();
|
||||
initHttpAgent();
|
||||
|
||||
try {
|
||||
mongoose.set('strictQuery', true);
|
||||
|
@@ -19,6 +19,7 @@ export const connectPg = async (): Promise<Pool> => {
|
||||
|
||||
global.pgClient.on('error', (err) => {
|
||||
console.log(err);
|
||||
global.pgClient?.end();
|
||||
global.pgClient = null;
|
||||
connectPg();
|
||||
});
|
||||
|
2
projects/app/src/types/index.d.ts
vendored
2
projects/app/src/types/index.d.ts
vendored
@@ -1,5 +1,4 @@
|
||||
import type { Mongoose } from 'mongoose';
|
||||
import type { Agent } from 'http';
|
||||
import type { Pool } from 'pg';
|
||||
import type { Tiktoken } from 'js-tiktoken';
|
||||
import type { Logger } from 'winston';
|
||||
@@ -55,7 +54,6 @@ export type SystemEnvType = {
|
||||
declare global {
|
||||
var mongodb: Mongoose | string | null;
|
||||
var pgClient: Pool | null;
|
||||
var httpsAgent: Agent;
|
||||
var qaQueueLen: number;
|
||||
var vectorQueueLen: number;
|
||||
var TikToken: Tiktoken;
|
||||
|
@@ -2,7 +2,7 @@ import { formatPrice } from '@fastgpt/common/bill/index';
|
||||
import type { BillSchema } from '@/types/common/bill';
|
||||
import type { UserBillType } from '@/types/user';
|
||||
import { ChatItemType } from '@/types/chat';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from 'openai';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/core/aiApi/constant';
|
||||
import { ChatRoleEnum } from '@/constants/chat';
|
||||
import type { MessageItemType } from '@/pages/api/openapi/v1/chat/completions';
|
||||
import type { AppModuleItemType } from '@/types/app';
|
||||
|
@@ -10,6 +10,7 @@ import { SystemInputEnum } from '@/constants/app';
|
||||
import type { SelectedDatasetType } from '@/types/core/dataset';
|
||||
import { FlowInputItemType } from '@/types/flow';
|
||||
import type { AIChatProps } from '@/types/core/aiChat';
|
||||
import { getGuideModules } from '@/components/ChatBox/utils';
|
||||
|
||||
export type EditFormType = {
|
||||
chatModel: AIChatProps;
|
||||
@@ -136,16 +137,13 @@ export const appModules2Form = (modules: AppModuleItemType[]) => {
|
||||
target?.inputs?.find((item) => item.key === SpecialInputKeyEnum.answerText)?.value || '';
|
||||
}
|
||||
} else if (module.flowType === FlowModuleTypeEnum.userGuide) {
|
||||
const val =
|
||||
module.inputs.find((item) => item.key === SystemInputEnum.welcomeText)?.value || '';
|
||||
if (val) {
|
||||
const { welcomeText, variableModules } = getGuideModules(modules);
|
||||
if (welcomeText) {
|
||||
defaultAppForm.guide.welcome = {
|
||||
text: val
|
||||
text: welcomeText
|
||||
};
|
||||
}
|
||||
} else if (module.flowType === FlowModuleTypeEnum.variable) {
|
||||
defaultAppForm.variables =
|
||||
module.inputs.find((item) => item.key === SystemInputEnum.variables)?.value || [];
|
||||
defaultAppForm.variables = variableModules;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -220,54 +218,32 @@ const chatModelInput = (formData: EditFormType): FlowInputItemType[] => [
|
||||
connected: true
|
||||
}
|
||||
];
|
||||
const welcomeTemplate = (formData: EditFormType): AppModuleItemType[] =>
|
||||
formData.guide?.welcome?.text
|
||||
? [
|
||||
{
|
||||
name: '用户引导',
|
||||
flowType: FlowModuleTypeEnum.userGuide,
|
||||
inputs: [
|
||||
{
|
||||
key: 'welcomeText',
|
||||
type: 'input',
|
||||
label: '开场白',
|
||||
value: formData.guide.welcome.text,
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
position: {
|
||||
x: 447.98520778293346,
|
||||
y: 721.4016845336229
|
||||
},
|
||||
moduleId: 'userGuide'
|
||||
}
|
||||
]
|
||||
: [];
|
||||
const variableTemplate = (formData: EditFormType): AppModuleItemType[] =>
|
||||
formData.variables.length > 0
|
||||
? [
|
||||
{
|
||||
name: '全局变量',
|
||||
flowType: FlowModuleTypeEnum.variable,
|
||||
inputs: [
|
||||
{
|
||||
key: 'variables',
|
||||
value: formData.variables,
|
||||
type: 'systemInput',
|
||||
label: '变量输入',
|
||||
connected: true
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
position: {
|
||||
x: 444.0369195277651,
|
||||
y: 1008.5185781784537
|
||||
},
|
||||
moduleId: 'variable'
|
||||
}
|
||||
]
|
||||
: [];
|
||||
const userGuideTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
||||
{
|
||||
name: '用户引导',
|
||||
flowType: FlowModuleTypeEnum.userGuide,
|
||||
inputs: [
|
||||
{
|
||||
key: SystemInputEnum.welcomeText,
|
||||
type: FlowInputItemTypeEnum.input,
|
||||
label: '开场白',
|
||||
value: formData.guide.welcome.text
|
||||
},
|
||||
{
|
||||
key: SystemInputEnum.variables,
|
||||
type: FlowInputItemTypeEnum.systemInput,
|
||||
label: '对话框变量',
|
||||
value: formData.variables
|
||||
}
|
||||
],
|
||||
outputs: [],
|
||||
position: {
|
||||
x: 447.98520778293346,
|
||||
y: 721.4016845336229
|
||||
},
|
||||
moduleId: 'userGuide'
|
||||
}
|
||||
];
|
||||
const simpleChatTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
||||
{
|
||||
name: '用户问题(对话入口)',
|
||||
@@ -572,8 +548,7 @@ const kbTemplate = (formData: EditFormType): AppModuleItemType[] => [
|
||||
|
||||
export const appForm2Modules = (formData: EditFormType) => {
|
||||
const modules = [
|
||||
...welcomeTemplate(formData),
|
||||
...variableTemplate(formData),
|
||||
...userGuideTemplate(formData),
|
||||
...(formData.kb.list.length > 0 ? kbTemplate(formData) : simpleChatTemplate(formData))
|
||||
];
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import type { ChatItemType } from '@/types/chat';
|
||||
import { ChatRoleEnum } from '@/constants/chat';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from 'openai';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/core/aiApi/constant';
|
||||
import type { MessageItemType } from '@/pages/api/openapi/v1/chat/completions';
|
||||
|
||||
const chat2Message = {
|
||||
|
@@ -2,7 +2,7 @@
|
||||
import { ChatItemType } from '@/types/chat';
|
||||
import { Tiktoken } from 'js-tiktoken/lite';
|
||||
import { adaptChat2GptMessages } from '../adapt/message';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from 'openai';
|
||||
import { ChatCompletionRequestMessageRoleEnum } from '@fastgpt/core/aiApi/constant';
|
||||
import encodingJson from './cl100k_base.json';
|
||||
|
||||
/* init tikToken obj */
|
||||
|
@@ -11,7 +11,7 @@ export const splitText2Chunks = ({ text, maxLen }: { text: string; maxLen: numbe
|
||||
const overlapLen = Math.floor(maxLen * 0.25); // Overlap length
|
||||
|
||||
try {
|
||||
const splitTexts = text.split(/(?<=[。!?;.!?;])/g);
|
||||
const splitTexts = text.split(/(?<=[。!?;.!?;\n])/g);
|
||||
const chunks: string[] = [];
|
||||
|
||||
let preChunk = '';
|
||||
|
@@ -19,6 +19,6 @@
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts"],
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.d.ts","../../packages/**/*.d.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
Reference in New Issue
Block a user