mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-22 12:20:34 +00:00
v4.1 (#183)
* chat item table * perf: chat item save * docs * limit * docs * docs * perf: node card * docs * docs
This commit is contained in:
29
README.md
29
README.md
@@ -27,14 +27,6 @@ FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开
|
|||||||
|  |  |
|
|  |  |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
||||||
## ⚡快速部署
|
|
||||||
|
|
||||||
> Sealos 的服务器在国外,不需要额外处理网络问题,无需服务器、无需魔法、无需域名,支持高并发 & 动态伸缩。点击以下按钮即可一键部署 👇
|
|
||||||
|
|
||||||
[](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt)
|
|
||||||
|
|
||||||
由于需要部署数据库,部署完后需要等待 2~4 分钟才能正常访问。默认用了最低配置,首次访问时会有些慢。
|
|
||||||
|
|
||||||
## 💡 功能
|
## 💡 功能
|
||||||
|
|
||||||
1. 强大的可视化编排,轻松构建 AI 应用
|
1. 强大的可视化编排,轻松构建 AI 应用
|
||||||
@@ -76,12 +68,21 @@ FastGPT 是一个基于 LLM 大语言模型的知识库问答系统,提供开
|
|||||||
|
|
||||||
项目技术栈: NextJs + TS + ChakraUI + Mongo + Postgres(Vector 插件)
|
项目技术栈: NextJs + TS + ChakraUI + Mongo + Postgres(Vector 插件)
|
||||||
|
|
||||||
- [快开始本地开发](https://doc.fastgpt.run/docs/develop/dev)
|
- **⚡ 快速部署**
|
||||||
- [部署 FastGPT](https://doc.fastgpt.run/docs/category/deploy)
|
|
||||||
- [系统配置文件说明](https://doc.fastgpt.run/docs/category/data-config)
|
> Sealos 的服务器在国外,不需要额外处理网络问题,无需服务器、无需魔法、无需域名,支持高并发 & 动态伸缩。点击以下按钮即可一键部署 👇
|
||||||
- [多模型配置](https://doc.fastgpt.run/docs/develop/data_config/chat_models)
|
|
||||||
- [V3 升级 V4 初始化](https://doc.fastgpt.run/docs/develop/deploy/v4init)
|
[](https://cloud.sealos.io/?openapp=system-fastdeploy%3FtemplateName%3Dfastgpt)
|
||||||
- [API 文档](https://kjqvjse66l.feishu.cn/docx/DmLedTWtUoNGX8xui9ocdUEjnNh?pre_pathname=%2Fdrive%2Fhome%2F)
|
|
||||||
|
由于需要部署数据库,部署完后需要等待 2~4 分钟才能正常访问。默认用了最低配置,首次访问时会有些慢。
|
||||||
|
|
||||||
|
* [快开始本地开发](https://doc.fastgpt.run/docs/develop/dev)
|
||||||
|
* [部署 FastGPT](https://doc.fastgpt.run/docs/category/deploy)
|
||||||
|
* [系统配置文件说明](https://doc.fastgpt.run/docs/category/data-config)
|
||||||
|
* [多模型配置](https://doc.fastgpt.run/docs/develop/data_config/chat_models)
|
||||||
|
* [V3 升级 V4 初始化](https://doc.fastgpt.run/docs/develop/deploy/v4init)
|
||||||
|
* [升级 v4.1 初始化](https://doc.fastgpt.run/docs/develop/deploy/initv4.1)
|
||||||
|
* [API 文档](https://kjqvjse66l.feishu.cn/docx/DmLedTWtUoNGX8xui9ocdUEjnNh?pre_pathname=%2Fdrive%2Fhome%2F)
|
||||||
|
|
||||||
## 🏘️ 社区交流群
|
## 🏘️ 社区交流群
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
"Confirm Save App Tip": "The application may be in advanced orchestration mode, and the advanced orchestration configuration will be overwritten after saving, please confirm!",
|
"Confirm Save App Tip": "The application may be in advanced orchestration mode, and the advanced orchestration configuration will be overwritten after saving, please confirm!",
|
||||||
"Connection is invalid": "Connecting is invalid",
|
"Connection is invalid": "Connecting is invalid",
|
||||||
"Connection type is different": "Connection type is different",
|
"Connection type is different": "Connection type is different",
|
||||||
|
"Copy Module Config": "Copy config",
|
||||||
"Export Config Successful": "The configuration has been copied. Please check for important data",
|
"Export Config Successful": "The configuration has been copied. Please check for important data",
|
||||||
"Export Configs": "Export Configs",
|
"Export Configs": "Export Configs",
|
||||||
"Import Config": "Import Config",
|
"Import Config": "Import Config",
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
"Confirm Save App Tip": "该应用可能为高级编排模式,保存后将会覆盖高级编排配置,请确认!",
|
"Confirm Save App Tip": "该应用可能为高级编排模式,保存后将会覆盖高级编排配置,请确认!",
|
||||||
"Connection is invalid": "连接无效",
|
"Connection is invalid": "连接无效",
|
||||||
"Connection type is different": "连接的类型不一致",
|
"Connection type is different": "连接的类型不一致",
|
||||||
|
"Copy Module Config": "复制配置",
|
||||||
"Export Config Successful": "已复制配置,请注意检查是否有重要数据",
|
"Export Config Successful": "已复制配置,请注意检查是否有重要数据",
|
||||||
"Export Configs": "导出配置",
|
"Export Configs": "导出配置",
|
||||||
"Import Config": "导入配置",
|
"Import Config": "导入配置",
|
||||||
|
@@ -27,20 +27,10 @@ export const delChatHistoryById = (chatId: string) => DELETE(`/chat/removeHistor
|
|||||||
*/
|
*/
|
||||||
export const clearChatHistoryByAppId = (appId: string) => DELETE(`/chat/removeHistory`, { appId });
|
export const clearChatHistoryByAppId = (appId: string) => DELETE(`/chat/removeHistory`, { appId });
|
||||||
|
|
||||||
/**
|
|
||||||
* update history quote status
|
|
||||||
*/
|
|
||||||
export const updateHistoryQuote = (params: {
|
|
||||||
chatId: string;
|
|
||||||
contentId: string;
|
|
||||||
quoteId: string;
|
|
||||||
sourceText: string;
|
|
||||||
}) => PUT(`/chat/history/updateHistoryQuote`, params);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除一句对话
|
* 删除一句对话
|
||||||
*/
|
*/
|
||||||
export const delChatRecordByIndex = (data: { chatId: string; contentId: string }) =>
|
export const delChatRecordById = (data: { chatId: string; contentId: string }) =>
|
||||||
DELETE(`/chat/delChatRecordByContentId`, data);
|
DELETE(`/chat/delChatRecordByContentId`, data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -40,6 +40,7 @@ import { useRouter } from 'next/router';
|
|||||||
import { useGlobalStore } from '@/store/global';
|
import { useGlobalStore } from '@/store/global';
|
||||||
import { TaskResponseKeyEnum, getDefaultChatVariables } from '@/constants/chat';
|
import { TaskResponseKeyEnum, getDefaultChatVariables } from '@/constants/chat';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { customAlphabet } from 'nanoid';
|
||||||
|
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
@@ -51,6 +52,8 @@ const ResponseTags = dynamic(() => import('./ResponseTags'));
|
|||||||
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
|
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
|
||||||
|
|
||||||
const textareaMinH = '22px';
|
const textareaMinH = '22px';
|
||||||
type generatingMessageProps = { text?: string; name?: string; status?: 'running' | 'finish' };
|
type generatingMessageProps = { text?: string; name?: string; status?: 'running' | 'finish' };
|
||||||
export type StartChatFnProps = {
|
export type StartChatFnProps = {
|
||||||
@@ -282,13 +285,13 @@ const ChatBox = (
|
|||||||
const newChatList: ChatSiteItemType[] = [
|
const newChatList: ChatSiteItemType[] = [
|
||||||
...chatHistory,
|
...chatHistory,
|
||||||
{
|
{
|
||||||
_id: String(new Types.ObjectId()),
|
dataId: nanoid(),
|
||||||
obj: 'Human',
|
obj: 'Human',
|
||||||
value: val,
|
value: val,
|
||||||
status: 'finish'
|
status: 'finish'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
_id: String(new Types.ObjectId()),
|
dataId: nanoid(),
|
||||||
obj: 'AI',
|
obj: 'AI',
|
||||||
value: '',
|
value: '',
|
||||||
status: 'loading'
|
status: 'loading'
|
||||||
@@ -552,7 +555,7 @@ const ChatBox = (
|
|||||||
{chatHistory.map((item, index) => (
|
{chatHistory.map((item, index) => (
|
||||||
<Flex
|
<Flex
|
||||||
position={'relative'}
|
position={'relative'}
|
||||||
key={item._id}
|
key={item.dataId}
|
||||||
flexDirection={'column'}
|
flexDirection={'column'}
|
||||||
alignItems={item.obj === 'Human' ? 'flex-end' : 'flex-start'}
|
alignItems={item.obj === 'Human' ? 'flex-end' : 'flex-start'}
|
||||||
py={5}
|
py={5}
|
||||||
@@ -583,10 +586,10 @@ const ChatBox = (
|
|||||||
_hover={{ color: 'red.600' }}
|
_hover={{ color: 'red.600' }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setChatHistory((state) =>
|
setChatHistory((state) =>
|
||||||
state.filter((chat) => chat._id !== item._id)
|
state.filter((chat) => chat.dataId !== item.dataId)
|
||||||
);
|
);
|
||||||
onDelMessage({
|
onDelMessage({
|
||||||
contentId: item._id,
|
contentId: item.dataId,
|
||||||
index
|
index
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -630,10 +633,10 @@ const ChatBox = (
|
|||||||
_hover={{ color: 'red.600' }}
|
_hover={{ color: 'red.600' }}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setChatHistory((state) =>
|
setChatHistory((state) =>
|
||||||
state.filter((chat) => chat._id !== item._id)
|
state.filter((chat) => chat.dataId !== item.dataId)
|
||||||
);
|
);
|
||||||
onDelMessage({
|
onDelMessage({
|
||||||
contentId: item._id,
|
contentId: item.dataId,
|
||||||
index
|
index
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
@@ -682,7 +685,7 @@ const ChatBox = (
|
|||||||
/>
|
/>
|
||||||
<ResponseTags
|
<ResponseTags
|
||||||
chatId={chatId}
|
chatId={chatId}
|
||||||
contentId={item._id}
|
contentId={item.dataId}
|
||||||
responseData={item.responseData}
|
responseData={item.responseData}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
@@ -45,9 +45,7 @@ async function init(limit: number, skip: number) {
|
|||||||
chatId: { $exists: false }
|
chatId: { $exists: false }
|
||||||
},
|
},
|
||||||
'_id'
|
'_id'
|
||||||
)
|
).limit(limit);
|
||||||
.limit(limit)
|
|
||||||
.skip(skip);
|
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
chats.map((chat) =>
|
chats.map((chat) =>
|
||||||
|
98
client/src/pages/api/admin/initChatItem.ts
Normal file
98
client/src/pages/api/admin/initChatItem.ts
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// 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 });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
@@ -408,9 +408,7 @@ async function init(limit: number, skip: number) {
|
|||||||
// userId: '63f9a14228d2a688d8dc9e1b'
|
// userId: '63f9a14228d2a688d8dc9e1b'
|
||||||
},
|
},
|
||||||
'_id chat'
|
'_id chat'
|
||||||
)
|
).limit(limit);
|
||||||
.limit(limit)
|
|
||||||
.skip(skip);
|
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
apps.map(async (app) => {
|
apps.map(async (app) => {
|
||||||
|
@@ -1,35 +1,23 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { connectToDatabase, Chat } from '@/service/mongo';
|
import { connectToDatabase, ChatItem } from '@/service/mongo';
|
||||||
import { authUser } from '@/service/utils/auth';
|
import { authUser } from '@/service/utils/auth';
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
try {
|
try {
|
||||||
const { chatId, contentId } = req.query as { chatId: string; contentId: string };
|
const { chatId, contentId } = req.query as { chatId: string; contentId: string };
|
||||||
|
|
||||||
if (!chatId || !contentId) {
|
|
||||||
throw new Error('缺少参数');
|
|
||||||
}
|
|
||||||
|
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
|
|
||||||
// 凭证校验
|
// 凭证校验
|
||||||
const { userId } = await authUser({ req, authToken: true });
|
const { userId } = await authUser({ req, authToken: true });
|
||||||
|
|
||||||
const chatRecord = await Chat.findOne({ chatId });
|
|
||||||
|
|
||||||
if (!chatRecord) {
|
|
||||||
throw new Error('找不到对话');
|
|
||||||
}
|
|
||||||
|
|
||||||
// 删除一条数据库记录
|
// 删除一条数据库记录
|
||||||
await Chat.updateOne(
|
await ChatItem.deleteOne({
|
||||||
{
|
dataId: contentId,
|
||||||
chatId,
|
chatId,
|
||||||
userId
|
userId
|
||||||
},
|
});
|
||||||
{ $pull: { content: { _id: contentId } } }
|
|
||||||
);
|
|
||||||
|
|
||||||
jsonRes(res);
|
jsonRes(res);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@@ -1,57 +0,0 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
|
||||||
import { jsonRes } from '@/service/response';
|
|
||||||
import { connectToDatabase, Chat } from '@/service/mongo';
|
|
||||||
import { authUser } from '@/service/utils/auth';
|
|
||||||
import { Types } from 'mongoose';
|
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
|
||||||
try {
|
|
||||||
let {
|
|
||||||
chatId,
|
|
||||||
contentId,
|
|
||||||
quoteId,
|
|
||||||
sourceText = ''
|
|
||||||
} = req.body as {
|
|
||||||
chatId: string;
|
|
||||||
contentId: string;
|
|
||||||
quoteId: string;
|
|
||||||
sourceText: string;
|
|
||||||
};
|
|
||||||
await connectToDatabase();
|
|
||||||
|
|
||||||
const { userId } = await authUser({ req, authToken: true });
|
|
||||||
|
|
||||||
if (!contentId || !chatId || !quoteId) {
|
|
||||||
throw new Error('params is error');
|
|
||||||
}
|
|
||||||
|
|
||||||
await Chat.updateOne(
|
|
||||||
{
|
|
||||||
chatId,
|
|
||||||
userId: new Types.ObjectId(userId),
|
|
||||||
'content._id': new Types.ObjectId(contentId)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
$set: {
|
|
||||||
'content.$.rawSearch.$[quoteElem].source': sourceText
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
arrayFilters: [
|
|
||||||
{
|
|
||||||
'quoteElem.id': quoteId
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
jsonRes(res, {
|
|
||||||
data: ''
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
jsonRes(res, {
|
|
||||||
code: 500,
|
|
||||||
error: err
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,11 +1,10 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { connectToDatabase, Chat } from '@/service/mongo';
|
import { Chat, ChatItem } from '@/service/mongo';
|
||||||
import type { InitChatResponse } from '@/api/response/chat';
|
import type { InitChatResponse } from '@/api/response/chat';
|
||||||
import { authUser } from '@/service/utils/auth';
|
import { authUser } from '@/service/utils/auth';
|
||||||
import { ChatItemType } from '@/types/chat';
|
import { ChatItemType } from '@/types/chat';
|
||||||
import { authApp } from '@/service/utils/auth';
|
import { authApp } from '@/service/utils/auth';
|
||||||
import mongoose from 'mongoose';
|
|
||||||
import type { ChatSchema } from '@/types/mongoSchema';
|
import type { ChatSchema } from '@/types/mongoSchema';
|
||||||
import { getSpecialModule, getChatModelNameList } from '@/components/ChatBox/utils';
|
import { getSpecialModule, getChatModelNameList } from '@/components/ChatBox/utils';
|
||||||
import { TaskResponseKeyEnum } from '@/constants/chat';
|
import { TaskResponseKeyEnum } from '@/constants/chat';
|
||||||
@@ -27,8 +26,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
await connectToDatabase();
|
|
||||||
|
|
||||||
// 校验使用权限
|
// 校验使用权限
|
||||||
const app = (
|
const app = (
|
||||||
await authApp({
|
await authApp({
|
||||||
@@ -39,49 +36,42 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
})
|
})
|
||||||
).app;
|
).app;
|
||||||
|
|
||||||
// 历史记录
|
// get app and history
|
||||||
const { chat, history = [] }: { chat?: ChatSchema; history?: ChatItemType[] } =
|
const { chat, history = [] }: { chat?: ChatSchema; history?: ChatItemType[] } =
|
||||||
await (async () => {
|
await (async () => {
|
||||||
if (chatId) {
|
if (chatId) {
|
||||||
// auth chatId
|
// auth chatId
|
||||||
const [chat, history] = await Promise.all([
|
const [chat, history] = await Promise.all([
|
||||||
Chat.findOne({
|
Chat.findOne(
|
||||||
chatId,
|
|
||||||
userId
|
|
||||||
}),
|
|
||||||
Chat.aggregate([
|
|
||||||
{
|
{
|
||||||
$match: {
|
chatId,
|
||||||
chatId,
|
userId
|
||||||
userId: new mongoose.Types.ObjectId(userId)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
'title variables'
|
||||||
|
),
|
||||||
|
ChatItem.find(
|
||||||
{
|
{
|
||||||
$project: {
|
chatId,
|
||||||
content: {
|
userId
|
||||||
$slice: ['$content', -30] // 返回 content 数组的最后 30 个元素
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{ $unwind: '$content' },
|
`dataId obj value ${TaskResponseKeyEnum.responseData}`
|
||||||
{
|
)
|
||||||
$project: {
|
.sort({ _id: -1 })
|
||||||
_id: '$content._id',
|
.limit(30)
|
||||||
obj: '$content.obj',
|
|
||||||
value: '$content.value',
|
|
||||||
[TaskResponseKeyEnum.responseData]: `$content.${TaskResponseKeyEnum.responseData}`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
])
|
|
||||||
]);
|
]);
|
||||||
if (!chat) {
|
if (!chat) {
|
||||||
throw new Error('聊天框不存在');
|
throw new Error('聊天框不存在');
|
||||||
}
|
}
|
||||||
return { history, chat };
|
history.reverse();
|
||||||
|
return { app, history, chat };
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
if (!app) {
|
||||||
|
throw new Error('Auth App Error');
|
||||||
|
}
|
||||||
|
|
||||||
const isOwner = String(app.userId) === userId;
|
const isOwner = String(app.userId) === userId;
|
||||||
|
|
||||||
jsonRes<InitChatResponse>(res, {
|
jsonRes<InitChatResponse>(res, {
|
||||||
@@ -108,3 +98,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
api: {
|
||||||
|
bodyParser: {
|
||||||
|
sizeLimit: '10mb'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { connectToDatabase, Chat } from '@/service/mongo';
|
import { connectToDatabase, Chat, ChatItem } from '@/service/mongo';
|
||||||
import { authUser } from '@/service/utils/auth';
|
import { authUser } from '@/service/utils/auth';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -17,16 +17,28 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
|
|
||||||
if (chatId) {
|
if (chatId) {
|
||||||
await Chat.findOneAndRemove({
|
await Promise.all([
|
||||||
chatId,
|
Chat.findOneAndRemove({
|
||||||
userId
|
chatId,
|
||||||
});
|
userId
|
||||||
|
}),
|
||||||
|
ChatItem.deleteMany({
|
||||||
|
userId,
|
||||||
|
chatId
|
||||||
|
})
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
if (appId) {
|
if (appId) {
|
||||||
await Chat.deleteMany({
|
await Promise.all([
|
||||||
appId,
|
Chat.deleteMany({
|
||||||
userId
|
appId,
|
||||||
});
|
userId
|
||||||
|
}),
|
||||||
|
ChatItem.deleteMany({
|
||||||
|
userId,
|
||||||
|
appId
|
||||||
|
})
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
jsonRes(res);
|
jsonRes(res);
|
||||||
|
@@ -28,7 +28,7 @@ import { BillSourceEnum } from '@/constants/user';
|
|||||||
import { ChatHistoryItemResType } from '@/types/chat';
|
import { ChatHistoryItemResType } from '@/types/chat';
|
||||||
import { UserModelSchema } from '@/types/mongoSchema';
|
import { UserModelSchema } from '@/types/mongoSchema';
|
||||||
|
|
||||||
export type MessageItemType = ChatCompletionRequestMessage & { _id?: string };
|
export type MessageItemType = ChatCompletionRequestMessage & { dataId?: string };
|
||||||
type FastGptWebChatProps = {
|
type FastGptWebChatProps = {
|
||||||
chatId?: string; // undefined: nonuse history, '': new chat, 'xxxxx': use history
|
chatId?: string; // undefined: nonuse history, '': new chat, 'xxxxx': use history
|
||||||
appId?: string;
|
appId?: string;
|
||||||
@@ -172,7 +172,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
|
|||||||
content: [
|
content: [
|
||||||
prompt,
|
prompt,
|
||||||
{
|
{
|
||||||
_id: messages[messages.length - 1]._id,
|
dataId: messages[messages.length - 1].dataId,
|
||||||
obj: ChatRoleEnum.AI,
|
obj: ChatRoleEnum.AI,
|
||||||
value: answerText,
|
value: answerText,
|
||||||
responseData
|
responseData
|
||||||
|
@@ -2,10 +2,9 @@
|
|||||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||||
import { jsonRes } from '@/service/response';
|
import { jsonRes } from '@/service/response';
|
||||||
import { authUser } from '@/service/utils/auth';
|
import { authUser } from '@/service/utils/auth';
|
||||||
import { connectToDatabase, Chat } from '@/service/mongo';
|
import { connectToDatabase, ChatItem } from '@/service/mongo';
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import type { ChatItemType } from '@/types/chat';
|
import type { ChatItemType } from '@/types/chat';
|
||||||
import { TaskResponseKeyEnum } from '@/constants/chat';
|
|
||||||
|
|
||||||
export type Props = {
|
export type Props = {
|
||||||
chatId?: string;
|
chatId?: string;
|
||||||
@@ -37,30 +36,37 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
export async function getChatHistory({
|
export async function getChatHistory({
|
||||||
chatId,
|
chatId,
|
||||||
userId,
|
userId,
|
||||||
limit = 20
|
limit = 30
|
||||||
}: Props & { userId: string }): Promise<Response> {
|
}: Props & { userId: string }): Promise<Response> {
|
||||||
if (!chatId) {
|
if (!chatId) {
|
||||||
return { history: [] };
|
return { history: [] };
|
||||||
}
|
}
|
||||||
|
|
||||||
const history = await Chat.aggregate([
|
const history = await ChatItem.aggregate([
|
||||||
{ $match: { chatId, userId: new Types.ObjectId(userId) } },
|
|
||||||
{
|
{
|
||||||
$project: {
|
$match: {
|
||||||
content: {
|
chatId,
|
||||||
$slice: ['$content', -limit] // 返回 content 数组的最后20个元素
|
userId: new Types.ObjectId(userId)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ $unwind: '$content' },
|
{
|
||||||
|
$sort: {
|
||||||
|
_id: -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
$limit: limit
|
||||||
|
},
|
||||||
{
|
{
|
||||||
$project: {
|
$project: {
|
||||||
obj: '$content.obj',
|
dataId: 1,
|
||||||
value: '$content.value',
|
obj: 1,
|
||||||
[TaskResponseKeyEnum.responseData]: `$content.responseData`
|
value: 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
history.reverse();
|
||||||
|
|
||||||
return { history };
|
return { history };
|
||||||
}
|
}
|
||||||
|
@@ -2,15 +2,13 @@ import React from 'react';
|
|||||||
import { NodeProps } from 'reactflow';
|
import { NodeProps } from 'reactflow';
|
||||||
import NodeCard from '../modules/NodeCard';
|
import NodeCard from '../modules/NodeCard';
|
||||||
import { FlowModuleItemType } from '@/types/flow';
|
import { FlowModuleItemType } from '@/types/flow';
|
||||||
import Divider from '../modules/Divider';
|
|
||||||
import Container from '../modules/Container';
|
import Container from '../modules/Container';
|
||||||
import RenderInput from '../render/RenderInput';
|
import RenderInput from '../render/RenderInput';
|
||||||
|
|
||||||
const NodeAnswer = ({
|
const NodeAnswer = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { moduleId, inputs, outputs, onChangeNode, ...props }
|
const { moduleId, inputs, outputs, onChangeNode } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'400px'} moduleId={moduleId} {...props}>
|
<NodeCard minW={'400px'} {...data}>
|
||||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||||
<RenderInput moduleId={moduleId} onChangeNode={onChangeNode} flowInputList={inputs} />
|
<RenderInput moduleId={moduleId} onChangeNode={onChangeNode} flowInputList={inputs} />
|
||||||
</Container>
|
</Container>
|
||||||
|
@@ -13,11 +13,10 @@ import MyIcon from '@/components/Icon';
|
|||||||
import { FlowOutputItemTypeEnum, FlowValueTypeEnum, SpecialInputKeyEnum } from '@/constants/flow';
|
import { FlowOutputItemTypeEnum, FlowValueTypeEnum, SpecialInputKeyEnum } from '@/constants/flow';
|
||||||
import SourceHandle from '../render/SourceHandle';
|
import SourceHandle from '../render/SourceHandle';
|
||||||
|
|
||||||
const NodeCQNode = ({
|
const NodeCQNode = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { moduleId, inputs, outputs, onChangeNode, ...props }
|
const { moduleId, inputs, outputs, onChangeNode } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'400px'} moduleId={moduleId} {...props}>
|
<NodeCard minW={'400px'} {...data}>
|
||||||
<Divider text="Input" />
|
<Divider text="Input" />
|
||||||
<Container>
|
<Container>
|
||||||
<RenderInput
|
<RenderInput
|
||||||
|
@@ -13,16 +13,15 @@ import MySlider from '@/components/Slider';
|
|||||||
import { Box } from '@chakra-ui/react';
|
import { Box } from '@chakra-ui/react';
|
||||||
import { formatPrice } from '@/utils/user';
|
import { formatPrice } from '@/utils/user';
|
||||||
|
|
||||||
const NodeChat = ({
|
const NodeChat = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { moduleId, inputs, outputs, onChangeNode, ...props }
|
const { moduleId, inputs, outputs, onChangeNode } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
const outputsLen = useMemo(
|
const outputsLen = useMemo(
|
||||||
() => outputs.filter((item) => item.type !== FlowOutputItemTypeEnum.hidden).length,
|
() => outputs.filter((item) => item.type !== FlowOutputItemTypeEnum.hidden).length,
|
||||||
[outputs]
|
[outputs]
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'400px'} moduleId={moduleId} {...props}>
|
<NodeCard minW={'400px'} {...data}>
|
||||||
<Divider text="Input" />
|
<Divider text="Input" />
|
||||||
<Container>
|
<Container>
|
||||||
<RenderInput
|
<RenderInput
|
||||||
|
@@ -3,7 +3,7 @@ import { NodeProps } from 'reactflow';
|
|||||||
import NodeCard from '../modules/NodeCard';
|
import NodeCard from '../modules/NodeCard';
|
||||||
import { FlowModuleItemType } from '@/types/flow';
|
import { FlowModuleItemType } from '@/types/flow';
|
||||||
|
|
||||||
const NodeAnswer = ({ data: { ...props } }: NodeProps<FlowModuleItemType>) => {
|
const NodeAnswer = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
return <NodeCard {...props}></NodeCard>;
|
return <NodeCard {...data}></NodeCard>;
|
||||||
};
|
};
|
||||||
export default React.memo(NodeAnswer);
|
export default React.memo(NodeAnswer);
|
||||||
|
@@ -15,14 +15,13 @@ import ExtractFieldModal from '../modules/ExtractFieldModal';
|
|||||||
import { ContextExtractEnum } from '@/constants/flow/flowField';
|
import { ContextExtractEnum } from '@/constants/flow/flowField';
|
||||||
import { FlowOutputItemTypeEnum, FlowValueTypeEnum } from '@/constants/flow';
|
import { FlowOutputItemTypeEnum, FlowValueTypeEnum } from '@/constants/flow';
|
||||||
|
|
||||||
const NodeExtract = ({
|
const NodeExtract = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { inputs, outputs, moduleId, onChangeNode, onDelEdge, ...props }
|
const { inputs, outputs, moduleId, onChangeNode, onDelEdge } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [editExtractFiled, setEditExtractField] = useState<ContextExtractAgentItemType>();
|
const [editExtractFiled, setEditExtractField] = useState<ContextExtractAgentItemType>();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'400px'} moduleId={moduleId} {...props}>
|
<NodeCard minW={'400px'} {...data}>
|
||||||
<Divider text="Input" />
|
<Divider text="Input" />
|
||||||
<Container>
|
<Container>
|
||||||
<RenderInput
|
<RenderInput
|
||||||
|
@@ -7,22 +7,17 @@ import Container from '../modules/Container';
|
|||||||
import RenderInput from '../render/RenderInput';
|
import RenderInput from '../render/RenderInput';
|
||||||
import RenderOutput from '../render/RenderOutput';
|
import RenderOutput from '../render/RenderOutput';
|
||||||
|
|
||||||
const NodeHistory = ({
|
const NodeHistory = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { inputs, outputs, onChangeNode, ...props }
|
const { inputs, outputs, moduleId, onChangeNode } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'300px'} {...props}>
|
<NodeCard minW={'300px'} {...data}>
|
||||||
<Divider text="Input" />
|
<Divider text="Input" />
|
||||||
<Container>
|
<Container>
|
||||||
<RenderInput moduleId={props.moduleId} onChangeNode={onChangeNode} flowInputList={inputs} />
|
<RenderInput moduleId={moduleId} onChangeNode={onChangeNode} flowInputList={inputs} />
|
||||||
</Container>
|
</Container>
|
||||||
<Divider text="Output" />
|
<Divider text="Output" />
|
||||||
<Container>
|
<Container>
|
||||||
<RenderOutput
|
<RenderOutput onChangeNode={onChangeNode} moduleId={moduleId} flowOutputList={outputs} />
|
||||||
onChangeNode={onChangeNode}
|
|
||||||
moduleId={props.moduleId}
|
|
||||||
flowOutputList={outputs}
|
|
||||||
/>
|
|
||||||
</Container>
|
</Container>
|
||||||
</NodeCard>
|
</NodeCard>
|
||||||
);
|
);
|
||||||
|
@@ -13,11 +13,10 @@ import { FlowInputItemTypeEnum, FlowOutputItemTypeEnum, FlowValueTypeEnum } from
|
|||||||
import { customAlphabet } from 'nanoid';
|
import { customAlphabet } from 'nanoid';
|
||||||
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 6);
|
||||||
|
|
||||||
const NodeHttp = ({
|
const NodeHttp = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { moduleId, inputs, outputs, onChangeNode, ...props }
|
const { moduleId, inputs, outputs, onChangeNode } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'350px'} moduleId={moduleId} {...props}>
|
<NodeCard minW={'350px'} {...data}>
|
||||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||||
<RenderInput moduleId={moduleId} onChangeNode={onChangeNode} flowInputList={inputs} />
|
<RenderInput moduleId={moduleId} onChangeNode={onChangeNode} flowInputList={inputs} />
|
||||||
<Button
|
<Button
|
||||||
|
@@ -69,11 +69,10 @@ const KBSelect = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const NodeKbSearch = ({
|
const NodeKbSearch = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { moduleId, inputs, outputs, onChangeNode, ...props }
|
const { moduleId, inputs, outputs, onChangeNode } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'400px'} moduleId={moduleId} {...props}>
|
<NodeCard minW={'400px'} {...data}>
|
||||||
<Divider text="Input" />
|
<Divider text="Input" />
|
||||||
<Container>
|
<Container>
|
||||||
<RenderInput
|
<RenderInput
|
||||||
|
@@ -8,11 +8,9 @@ import { SystemInputEnum } from '@/constants/app';
|
|||||||
import { FlowValueTypeEnum } from '@/constants/flow';
|
import { FlowValueTypeEnum } from '@/constants/flow';
|
||||||
import SourceHandle from '../render/SourceHandle';
|
import SourceHandle from '../render/SourceHandle';
|
||||||
|
|
||||||
const QuestionInputNode = ({
|
const QuestionInputNode = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { inputs, outputs, ...props }
|
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'240px'} {...props}>
|
<NodeCard minW={'240px'} {...data}>
|
||||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'} textAlign={'end'}>
|
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'} textAlign={'end'}>
|
||||||
<Box position={'relative'}>
|
<Box position={'relative'}>
|
||||||
用户问题
|
用户问题
|
||||||
|
@@ -8,9 +8,9 @@ import Divider from '../modules/Divider';
|
|||||||
import Container from '../modules/Container';
|
import Container from '../modules/Container';
|
||||||
import Label from '../modules/Label';
|
import Label from '../modules/Label';
|
||||||
|
|
||||||
const NodeTFSwitch = ({ data: { inputs, outputs, ...props } }: NodeProps<FlowModuleItemType>) => {
|
const NodeTFSwitch = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
return (
|
return (
|
||||||
<NodeCard minW={'220px'} {...props}>
|
<NodeCard minW={'220px'} {...data}>
|
||||||
<Divider text="输入输出" />
|
<Divider text="输入输出" />
|
||||||
<Container h={'100px'} py={0} px={0} display={'flex'} alignItems={'center'}>
|
<Container h={'100px'} py={0} px={0} display={'flex'} alignItems={'center'}>
|
||||||
<Box flex={1} pl={'12px'}>
|
<Box flex={1} pl={'12px'}>
|
||||||
|
@@ -10,9 +10,8 @@ import MyIcon from '@/components/Icon';
|
|||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import { welcomeTextTip } from '@/constants/flow/ModuleTemplate';
|
import { welcomeTextTip } from '@/constants/flow/ModuleTemplate';
|
||||||
|
|
||||||
const NodeUserGuide = ({
|
const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { inputs, outputs, onChangeNode, ...props }
|
const { inputs, moduleId, onChangeNode } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
const welcomeText = useMemo(
|
const welcomeText = useMemo(
|
||||||
() => inputs.find((item) => item.key === SystemInputEnum.welcomeText),
|
() => inputs.find((item) => item.key === SystemInputEnum.welcomeText),
|
||||||
[inputs]
|
[inputs]
|
||||||
@@ -20,7 +19,7 @@ const NodeUserGuide = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NodeCard minW={'300px'} {...props}>
|
<NodeCard minW={'300px'} {...data}>
|
||||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||||
<>
|
<>
|
||||||
<Flex mb={1} alignItems={'center'}>
|
<Flex mb={1} alignItems={'center'}>
|
||||||
@@ -40,7 +39,7 @@ const NodeUserGuide = ({
|
|||||||
placeholder={welcomeTextTip}
|
placeholder={welcomeTextTip}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
onChangeNode({
|
onChangeNode({
|
||||||
moduleId: props.moduleId,
|
moduleId,
|
||||||
key: SystemInputEnum.welcomeText,
|
key: SystemInputEnum.welcomeText,
|
||||||
type: 'inputs',
|
type: 'inputs',
|
||||||
value: {
|
value: {
|
||||||
|
@@ -22,9 +22,8 @@ export const defaultVariable: VariableItemType = {
|
|||||||
enums: [{ value: '' }]
|
enums: [{ value: '' }]
|
||||||
};
|
};
|
||||||
|
|
||||||
const NodeUserGuide = ({
|
const NodeUserGuide = ({ data }: NodeProps<FlowModuleItemType>) => {
|
||||||
data: { inputs, outputs, onChangeNode, ...props }
|
const { inputs, moduleId, onChangeNode } = data;
|
||||||
}: NodeProps<FlowModuleItemType>) => {
|
|
||||||
const variables = useMemo(
|
const variables = useMemo(
|
||||||
() =>
|
() =>
|
||||||
(inputs.find((item) => item.key === SystemInputEnum.variables)
|
(inputs.find((item) => item.key === SystemInputEnum.variables)
|
||||||
@@ -37,7 +36,7 @@ const NodeUserGuide = ({
|
|||||||
const updateVariables = useCallback(
|
const updateVariables = useCallback(
|
||||||
(value: VariableItemType[]) => {
|
(value: VariableItemType[]) => {
|
||||||
onChangeNode({
|
onChangeNode({
|
||||||
moduleId: props.moduleId,
|
moduleId,
|
||||||
key: SystemInputEnum.variables,
|
key: SystemInputEnum.variables,
|
||||||
type: 'inputs',
|
type: 'inputs',
|
||||||
value: {
|
value: {
|
||||||
@@ -46,7 +45,7 @@ const NodeUserGuide = ({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[inputs, onChangeNode, props.moduleId]
|
[inputs, onChangeNode, moduleId]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onclickSubmit = useCallback(
|
const onclickSubmit = useCallback(
|
||||||
@@ -59,7 +58,7 @@ const NodeUserGuide = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<NodeCard minW={'300px'} {...props}>
|
<NodeCard minW={'300px'} {...data}>
|
||||||
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
<Container borderTop={'2px solid'} borderTopColor={'myGray.200'}>
|
||||||
<TableContainer>
|
<TableContainer>
|
||||||
<Table>
|
<Table>
|
||||||
|
@@ -6,29 +6,25 @@ import type { FlowModuleItemType } from '@/types/flow';
|
|||||||
import MyTooltip from '@/components/MyTooltip';
|
import MyTooltip from '@/components/MyTooltip';
|
||||||
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
import { QuestionOutlineIcon } from '@chakra-ui/icons';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
|
import { useCopyData } from '@/utils/tools';
|
||||||
|
|
||||||
type Props = {
|
type Props = FlowModuleItemType & {
|
||||||
children?: React.ReactNode | React.ReactNode[] | string;
|
children?: React.ReactNode | React.ReactNode[] | string;
|
||||||
logo: string;
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
intro: string;
|
|
||||||
minW?: string | number;
|
minW?: string | number;
|
||||||
moduleId: string;
|
|
||||||
onDelNode: FlowModuleItemType['onDelNode'];
|
|
||||||
onCopyNode: FlowModuleItemType['onCopyNode'];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const NodeCard = ({
|
const NodeCard = (props: Props) => {
|
||||||
children,
|
const {
|
||||||
logo = '/icon/logo.svg',
|
children,
|
||||||
name = '未知模块',
|
logo = '/icon/logo.svg',
|
||||||
description,
|
name = '未知模块',
|
||||||
minW = '300px',
|
description,
|
||||||
onCopyNode,
|
minW = '300px',
|
||||||
onDelNode,
|
onCopyNode,
|
||||||
moduleId
|
onDelNode,
|
||||||
}: Props) => {
|
moduleId
|
||||||
|
} = props;
|
||||||
|
const { copyData } = useCopyData();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
|
||||||
@@ -39,16 +35,22 @@ const NodeCard = ({
|
|||||||
label: t('common.Copy'),
|
label: t('common.Copy'),
|
||||||
onClick: () => onCopyNode(moduleId)
|
onClick: () => onCopyNode(moduleId)
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// icon: 'settingLight',
|
||||||
|
// label: t('app.Copy Module Config'),
|
||||||
|
// onClick: () => {
|
||||||
|
// const copyProps = { ...props };
|
||||||
|
// delete copyProps.children;
|
||||||
|
// delete copyProps.children;
|
||||||
|
// console.log(copyProps);
|
||||||
|
// }
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
icon: 'delete',
|
icon: 'delete',
|
||||||
label: t('common.Delete'),
|
label: t('common.Delete'),
|
||||||
onClick: () => onDelNode(moduleId)
|
onClick: () => onDelNode(moduleId)
|
||||||
},
|
},
|
||||||
// {
|
|
||||||
// icon: 'collectionLight',
|
|
||||||
// label: t('common.Collect'),
|
|
||||||
// onClick: () => {}
|
|
||||||
// },
|
|
||||||
{
|
{
|
||||||
icon: 'back',
|
icon: 'back',
|
||||||
label: t('common.Cancel'),
|
label: t('common.Cancel'),
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import React, { useCallback, useRef } from 'react';
|
import React, { useCallback, useRef } from 'react';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { getInitChatSiteInfo, delChatRecordByIndex, putChatHistory } from '@/api/chat';
|
import { getInitChatSiteInfo, delChatRecordById, putChatHistory } from '@/api/chat';
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Flex,
|
Flex,
|
||||||
@@ -128,7 +128,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
|
|||||||
...state,
|
...state,
|
||||||
history: state.history.filter((_, i) => i !== index)
|
history: state.history.filter((_, i) => i !== index)
|
||||||
}));
|
}));
|
||||||
await delChatRecordByIndex({ chatId, contentId });
|
await delChatRecordById({ chatId, contentId });
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
|
@@ -147,10 +147,6 @@ const LoginForm = ({ setPageType, loginSuccess }: Props) => {
|
|||||||
onClick={onclickGit}
|
onClick={onclickGit}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box mt={3} textAlign={'center'} fontSize={'sm'} color={'myGray.600'}>
|
|
||||||
由于 Git 登录设计缺陷,我们重新设计了 Git 登录,已使用 Git
|
|
||||||
注册的账号将会丢失关联,如果你希望重新绑定原来的账号,可以点击右下角的【联系方式】,我们会手动为你重新绑定。不需要重新关联的,将会注册新的账号。
|
|
||||||
</Box>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Schema, model, models, Model } from 'mongoose';
|
import { Schema, model, models, Model } from 'mongoose';
|
||||||
import { ChatSchema as ChatType } from '@/types/mongoSchema';
|
import { ChatSchema as ChatType } from '@/types/mongoSchema';
|
||||||
import { ChatRoleMap, TaskResponseKeyEnum } from '@/constants/chat';
|
import { ChatRoleMap, TaskResponseKeyEnum } from '@/constants/chat';
|
||||||
import { ChatSourceEnum, ChatSourceMap } from '@/constants/chat';
|
import { ChatSourceMap } from '@/constants/chat';
|
||||||
|
|
||||||
const ChatSchema = new Schema({
|
const ChatSchema = new Schema({
|
||||||
chatId: {
|
chatId: {
|
||||||
@@ -45,6 +45,10 @@ const ChatSchema = new Schema({
|
|||||||
shareId: {
|
shareId: {
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
|
isInit: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
content: {
|
content: {
|
||||||
type: [
|
type: [
|
||||||
{
|
{
|
||||||
|
72
client/src/service/models/chatItem.ts
Normal file
72
client/src/service/models/chatItem.ts
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import { Schema, model, models, Model } from 'mongoose';
|
||||||
|
import { ChatItemSchema as ChatItemType } from '@/types/mongoSchema';
|
||||||
|
import { ChatRoleMap, TaskResponseKeyEnum } from '@/constants/chat';
|
||||||
|
import { customAlphabet } from 'nanoid';
|
||||||
|
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 24);
|
||||||
|
|
||||||
|
const ChatItemSchema = new Schema({
|
||||||
|
dataId: {
|
||||||
|
type: String,
|
||||||
|
require: true,
|
||||||
|
default: () => nanoid()
|
||||||
|
},
|
||||||
|
chatId: {
|
||||||
|
type: String,
|
||||||
|
require: true
|
||||||
|
},
|
||||||
|
userId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: 'user',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
appId: {
|
||||||
|
type: Schema.Types.ObjectId,
|
||||||
|
ref: 'model',
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
time: {
|
||||||
|
type: Date,
|
||||||
|
default: () => new Date()
|
||||||
|
},
|
||||||
|
obj: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
enum: Object.keys(ChatRoleMap)
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
[TaskResponseKeyEnum.responseData]: {
|
||||||
|
type: [
|
||||||
|
{
|
||||||
|
moduleName: String,
|
||||||
|
price: String,
|
||||||
|
model: String,
|
||||||
|
tokens: Number,
|
||||||
|
question: String,
|
||||||
|
answer: String,
|
||||||
|
temperature: Number,
|
||||||
|
maxToken: Number,
|
||||||
|
quoteList: Array,
|
||||||
|
completeMessages: Array,
|
||||||
|
similarity: Number,
|
||||||
|
limit: Number,
|
||||||
|
cqList: Array,
|
||||||
|
cqResult: String
|
||||||
|
}
|
||||||
|
],
|
||||||
|
default: []
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
ChatItemSchema.index({ time: -1 });
|
||||||
|
ChatItemSchema.index({ userId: 1 });
|
||||||
|
ChatItemSchema.index({ appId: 1 });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ChatItem: Model<ChatItemType> =
|
||||||
|
models['chatItem'] || model('chatItem', ChatItemSchema);
|
@@ -63,7 +63,6 @@ export const dispatchChatCompletion = async (props: Record<string, any>): Promis
|
|||||||
}
|
}
|
||||||
|
|
||||||
const { filterQuoteQA, quotePrompt } = filterQuote({
|
const { filterQuoteQA, quotePrompt } = filterQuote({
|
||||||
history,
|
|
||||||
quoteQA,
|
quoteQA,
|
||||||
model: modelConstantsData
|
model: modelConstantsData
|
||||||
});
|
});
|
||||||
@@ -91,6 +90,7 @@ export const dispatchChatCompletion = async (props: Record<string, any>): Promis
|
|||||||
maxToken,
|
maxToken,
|
||||||
filterMessages
|
filterMessages
|
||||||
});
|
});
|
||||||
|
// console.log(messages);
|
||||||
|
|
||||||
// FastGpt temperature range: 1~10
|
// FastGpt temperature range: 1~10
|
||||||
temperature = +(modelConstantsData.maxTemperature * (temperature / 10)).toFixed(2);
|
temperature = +(modelConstantsData.maxTemperature * (temperature / 10)).toFixed(2);
|
||||||
@@ -182,32 +182,23 @@ export const dispatchChatCompletion = async (props: Record<string, any>): Promis
|
|||||||
};
|
};
|
||||||
|
|
||||||
function filterQuote({
|
function filterQuote({
|
||||||
history = [],
|
|
||||||
quoteQA = [],
|
quoteQA = [],
|
||||||
model
|
model
|
||||||
}: {
|
}: {
|
||||||
history: ChatProps['history'];
|
|
||||||
quoteQA: ChatProps['quoteQA'];
|
quoteQA: ChatProps['quoteQA'];
|
||||||
model: ChatModelItemType;
|
model: ChatModelItemType;
|
||||||
}) {
|
}) {
|
||||||
// concat history quote
|
|
||||||
const historyQuote =
|
|
||||||
history[history.length - 1]?.responseData
|
|
||||||
?.find((item) => item.moduleName === ChatModuleEnum.AIChat)
|
|
||||||
?.quoteList?.filter((item) => !quoteQA.find((quote) => quote.id === item.id)) || [];
|
|
||||||
const concatQuote = quoteQA.concat(historyQuote.slice(0, 3));
|
|
||||||
|
|
||||||
const sliceResult = modelToolMap.tokenSlice({
|
const sliceResult = modelToolMap.tokenSlice({
|
||||||
model: model.model,
|
model: model.model,
|
||||||
maxToken: model.quoteMaxToken,
|
maxToken: model.quoteMaxToken,
|
||||||
messages: concatQuote.map((item, i) => ({
|
messages: quoteQA.map((item) => ({
|
||||||
obj: ChatRoleEnum.System,
|
obj: ChatRoleEnum.System,
|
||||||
value: item.a ? `{instruction:${item.q},output:${item.a}}` : `{instruction:${item.q}}`
|
value: item.a ? `{instruction:${item.q},output:${item.a}}` : `{instruction:${item.q}}`
|
||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
// slice filterSearch
|
// slice filterSearch
|
||||||
const filterQuoteQA = concatQuote.slice(0, sliceResult.length);
|
const filterQuoteQA = quoteQA.slice(0, sliceResult.length);
|
||||||
|
|
||||||
const quotePrompt =
|
const quotePrompt =
|
||||||
filterQuoteQA.length > 0
|
filterQuoteQA.length > 0
|
||||||
|
@@ -113,6 +113,7 @@ async function initPg() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export * from './models/chat';
|
export * from './models/chat';
|
||||||
|
export * from './models/chatItem';
|
||||||
export * from './models/app';
|
export * from './models/app';
|
||||||
export * from './models/user';
|
export * from './models/user';
|
||||||
export * from './models/bill';
|
export * from './models/bill';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { ChatItemType } from '@/types/chat';
|
import { ChatItemType } from '@/types/chat';
|
||||||
import { Chat, App } from '@/service/mongo';
|
import { Chat, App, ChatItem } from '@/service/mongo';
|
||||||
import { ChatSourceEnum } from '@/constants/chat';
|
import { ChatSourceEnum } from '@/constants/chat';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@@ -32,36 +32,40 @@ export async function saveChat({
|
|||||||
'_id'
|
'_id'
|
||||||
);
|
);
|
||||||
|
|
||||||
const promise = [];
|
const promise: any[] = [
|
||||||
|
ChatItem.insertMany(
|
||||||
|
content.map((item) => ({
|
||||||
|
chatId,
|
||||||
|
userId,
|
||||||
|
appId,
|
||||||
|
...item
|
||||||
|
}))
|
||||||
|
)
|
||||||
|
];
|
||||||
|
|
||||||
if (chatHistory) {
|
if (chatHistory) {
|
||||||
promise.push(
|
promise.push([
|
||||||
Chat.updateOne(
|
Chat.updateOne(
|
||||||
{ chatId, userId },
|
{ chatId, userId },
|
||||||
{
|
{
|
||||||
$push: {
|
|
||||||
content: {
|
|
||||||
$each: content,
|
|
||||||
$slice: -40
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title: content[0].value.slice(0, 20),
|
title: content[0].value.slice(0, 20),
|
||||||
updateTime: new Date()
|
updateTime: new Date()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
]);
|
||||||
} else {
|
} else {
|
||||||
promise.push(
|
promise.push(
|
||||||
Chat.create({
|
...[
|
||||||
chatId,
|
Chat.create({
|
||||||
userId,
|
chatId,
|
||||||
appId,
|
userId,
|
||||||
variables,
|
appId,
|
||||||
title: content[0].value.slice(0, 20),
|
variables,
|
||||||
source,
|
title: content[0].value.slice(0, 20),
|
||||||
shareId,
|
source,
|
||||||
content: content
|
shareId
|
||||||
})
|
})
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
2
client/src/types/chat.d.ts
vendored
2
client/src/types/chat.d.ts
vendored
@@ -6,7 +6,7 @@ import { ClassifyQuestionAgentItemType } from './app';
|
|||||||
export type ExportChatType = 'md' | 'pdf' | 'html';
|
export type ExportChatType = 'md' | 'pdf' | 'html';
|
||||||
|
|
||||||
export type ChatItemType = {
|
export type ChatItemType = {
|
||||||
_id?: string;
|
dataId?: string;
|
||||||
obj: `${ChatRoleEnum}`;
|
obj: `${ChatRoleEnum}`;
|
||||||
value: string;
|
value: string;
|
||||||
[TaskResponseKeyEnum.responseData]?: ChatHistoryItemResType[];
|
[TaskResponseKeyEnum.responseData]?: ChatHistoryItemResType[];
|
||||||
|
2
client/src/types/flow.d.ts
vendored
2
client/src/types/flow.d.ts
vendored
@@ -53,9 +53,9 @@ export type FlowModuleTemplateType = {
|
|||||||
description?: string;
|
description?: string;
|
||||||
intro: string;
|
intro: string;
|
||||||
flowType: `${FlowModuleTypeEnum}`;
|
flowType: `${FlowModuleTypeEnum}`;
|
||||||
|
showStatus?: boolean;
|
||||||
inputs: FlowInputItemType[];
|
inputs: FlowInputItemType[];
|
||||||
outputs: FlowOutputItemType[];
|
outputs: FlowOutputItemType[];
|
||||||
showStatus?: boolean;
|
|
||||||
};
|
};
|
||||||
export type FlowModuleItemType = FlowModuleTemplateType & {
|
export type FlowModuleItemType = FlowModuleTemplateType & {
|
||||||
moduleId: string;
|
moduleId: string;
|
||||||
|
9
client/src/types/mongoSchema.d.ts
vendored
9
client/src/types/mongoSchema.d.ts
vendored
@@ -92,9 +92,18 @@ export interface ChatSchema {
|
|||||||
variables: Record<string, any>;
|
variables: Record<string, any>;
|
||||||
source: `${ChatSourceEnum}`;
|
source: `${ChatSourceEnum}`;
|
||||||
shareId?: string;
|
shareId?: string;
|
||||||
|
isInit: boolean;
|
||||||
content: ChatItemType[];
|
content: ChatItemType[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ChatItemSchema extends ChatItemType {
|
||||||
|
dataId: string;
|
||||||
|
chatId: string;
|
||||||
|
userId: string;
|
||||||
|
appId: string;
|
||||||
|
time: Date;
|
||||||
|
}
|
||||||
|
|
||||||
export type BillListItemType = {
|
export type BillListItemType = {
|
||||||
moduleName: string;
|
moduleName: string;
|
||||||
amount: number;
|
amount: number;
|
||||||
|
@@ -33,7 +33,7 @@ export const gptMessage2ChatType = (messages: MessageItemType[]): ChatItemType[]
|
|||||||
};
|
};
|
||||||
|
|
||||||
return messages.map((item) => ({
|
return messages.map((item) => ({
|
||||||
_id: item._id,
|
dataId: item.dataId,
|
||||||
obj: roleMap[item.role],
|
obj: roleMap[item.role],
|
||||||
value: item.content || ''
|
value: item.content || ''
|
||||||
}));
|
}));
|
||||||
|
@@ -41,7 +41,7 @@ export const adaptChatItem_openAI = ({
|
|||||||
[ChatRoleEnum.System]: ChatCompletionRequestMessageRoleEnum.System
|
[ChatRoleEnum.System]: ChatCompletionRequestMessageRoleEnum.System
|
||||||
};
|
};
|
||||||
return messages.map((item) => ({
|
return messages.map((item) => ({
|
||||||
...(reserveId && { _id: item._id }),
|
...(reserveId && { dataId: item.dataId }),
|
||||||
role: map[item.obj] || ChatCompletionRequestMessageRoleEnum.System,
|
role: map[item.obj] || ChatCompletionRequestMessageRoleEnum.System,
|
||||||
content: item.value || ''
|
content: item.value || ''
|
||||||
}));
|
}));
|
||||||
|
@@ -1,7 +1,3 @@
|
|||||||
---
|
|
||||||
sidebar_position: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
# Config Chat Model
|
# Config Chat Model
|
||||||
|
|
||||||
By default, FastGPT is only configured with 3 models of GPT. If you need to integrate other models, you need to do some additional configuration.
|
By default, FastGPT is only configured with 3 models of GPT. If you need to integrate other models, you need to do some additional configuration.
|
||||||
|
72
docSite/docs/develop/data_config/default.md
Normal file
72
docSite/docs/develop/data_config/default.md
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
sidebar_position: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
# Default Config.json
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FeConfig": {
|
||||||
|
"show_emptyChat": true,
|
||||||
|
"show_register": false,
|
||||||
|
"show_appStore": false,
|
||||||
|
"show_userDetail": false,
|
||||||
|
"show_git": true,
|
||||||
|
"systemTitle": "FastGPT",
|
||||||
|
"authorText": "Made by FastGPT Team.",
|
||||||
|
"gitLoginKey": "",
|
||||||
|
"scripts": []
|
||||||
|
},
|
||||||
|
"SystemParams": {
|
||||||
|
"gitLoginSecret": "",
|
||||||
|
"vectorMaxProcess": 15,
|
||||||
|
"qaMaxProcess": 15,
|
||||||
|
"pgIvfflatProbe": 20
|
||||||
|
},
|
||||||
|
"plugins": {},
|
||||||
|
"ChatModels": [
|
||||||
|
{
|
||||||
|
"model": "gpt-3.5-turbo",
|
||||||
|
"name": "GPT35-4k",
|
||||||
|
"contextMaxToken": 4000,
|
||||||
|
"quoteMaxToken": 2000,
|
||||||
|
"maxTemperature": 1.2,
|
||||||
|
"price": 0,
|
||||||
|
"defaultSystem": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "gpt-3.5-turbo-16k",
|
||||||
|
"name": "GPT35-16k",
|
||||||
|
"contextMaxToken": 16000,
|
||||||
|
"quoteMaxToken": 8000,
|
||||||
|
"maxTemperature": 1.2,
|
||||||
|
"price": 0,
|
||||||
|
"defaultSystem": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "gpt-4",
|
||||||
|
"name": "GPT4-8k",
|
||||||
|
"contextMaxToken": 8000,
|
||||||
|
"quoteMaxToken": 4000,
|
||||||
|
"maxTemperature": 1.2,
|
||||||
|
"price": 0,
|
||||||
|
"defaultSystem": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"QAModels": [
|
||||||
|
{
|
||||||
|
"model": "gpt-3.5-turbo-16k",
|
||||||
|
"name": "GPT35-16k",
|
||||||
|
"maxToken": 16000,
|
||||||
|
"price": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"VectorModels": [
|
||||||
|
{
|
||||||
|
"model": "text-embedding-ada-002",
|
||||||
|
"name": "Embedding-2",
|
||||||
|
"price": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
@@ -10,6 +10,8 @@ In the development environment, you need to make a copy of `config.json` as `con
|
|||||||
|
|
||||||
This configuration file contains customization of the frontend page, system-level parameters, and AI dialogue models, etc.
|
This configuration file contains customization of the frontend page, system-level parameters, and AI dialogue models, etc.
|
||||||
|
|
||||||
|
**Note: The configuration instructions below are only a partial introduction. You need to mount the entire config.json file and not just a part of it. You can directly modify the provided config.json file based on the instructions below.**
|
||||||
|
|
||||||
## Brief Explanation of Basic Fields
|
## Brief Explanation of Basic Fields
|
||||||
|
|
||||||
Here are some basic configuration fields.
|
Here are some basic configuration fields.
|
||||||
|
@@ -70,7 +70,7 @@ services:
|
|||||||
fastgpt:
|
fastgpt:
|
||||||
container_name: fastgpt
|
container_name: fastgpt
|
||||||
# image: c121914yu/fast-gpt:latest # docker hub
|
# image: c121914yu/fast-gpt:latest # docker hub
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
|
image: ghcr.io/labring/fastgpt:latest # 阿里云
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
networks:
|
networks:
|
||||||
@@ -89,7 +89,8 @@ services:
|
|||||||
- TOKEN_KEY=any
|
- TOKEN_KEY=any
|
||||||
- ROOT_KEY=root_key
|
- ROOT_KEY=root_key
|
||||||
# mongo 配置,不需要改
|
# mongo 配置,不需要改
|
||||||
- MONGODB_URI=mongodb://username:password@mongo:27017/?authSource=admin
|
- MONGODB_URI=mongodb://username:password@mongo:27017
|
||||||
|
# - MONGODB_URI=mongodb://username:password@mongo:27017/?authSource=admin
|
||||||
- MONGODB_NAME=fastgpt
|
- MONGODB_NAME=fastgpt
|
||||||
# pg配置.
|
# pg配置.
|
||||||
- PG_HOST=pg
|
- PG_HOST=pg
|
||||||
@@ -105,61 +106,58 @@ networks:
|
|||||||
# host 版本, 不推荐。
|
# host 版本, 不推荐。
|
||||||
version: '3.3'
|
version: '3.3'
|
||||||
services:
|
services:
|
||||||
pg:
|
pg:
|
||||||
image: ankane/pgvector:v0.4.2 # dockerhub
|
image: ankane/pgvector:v0.4.2 # dockerhub
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.4.2 # 阿里云
|
container_name: pg
|
||||||
container_name: pg
|
restart: always
|
||||||
restart: always
|
ports: # 生产环境建议不要暴露
|
||||||
ports: # 生产环境建议不要暴露
|
- 5432:5432
|
||||||
- 5432:5432
|
environment:
|
||||||
environment:
|
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
|
||||||
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
|
- POSTGRES_USER=username
|
||||||
- POSTGRES_USER=username
|
- POSTGRES_PASSWORD=password
|
||||||
- POSTGRES_PASSWORD=password
|
- POSTGRES_DB=postgres
|
||||||
- POSTGRES_DB=postgres
|
volumes:
|
||||||
volumes:
|
- ./pg/data:/var/lib/postgresql/data
|
||||||
- ./pg/data:/var/lib/postgresql/data
|
mongo:
|
||||||
mongo:
|
image: mongo:5.0.18
|
||||||
image: mongo:5.0.18
|
container_name: mongo
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/mongo:5.0.18 # 阿里云
|
restart: always
|
||||||
container_name: mongo
|
ports: # 生产环境建议不要暴露
|
||||||
restart: always
|
- 27017:27017
|
||||||
ports: # 生产环境建议不要暴露
|
environment:
|
||||||
- 27017:27017
|
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
|
||||||
environment:
|
- MONGO_INITDB_ROOT_USERNAME=username
|
||||||
# 这里的配置只有首次运行生效。修改后,重启镜像是不会生效的。需要把持久化数据删除再重启,才有效果
|
- MONGO_INITDB_ROOT_PASSWORD=password
|
||||||
- MONGO_INITDB_ROOT_USERNAME=username
|
volumes:
|
||||||
- MONGO_INITDB_ROOT_PASSWORD=password
|
- ./mongo/data:/data/db
|
||||||
volumes:
|
- ./mongo/logs:/var/log/mongodb
|
||||||
- ./mongo/data:/data/db
|
fastgpt:
|
||||||
- ./mongo/logs:/var/log/mongodb
|
image: ghcr.io/c121914yu/fastgpt:latest # github
|
||||||
fastgpt:
|
network_mode: host
|
||||||
# image: ghcr.io/c121914yu/fastgpt:latest # github
|
restart: always
|
||||||
# image: c121914yu/fast-gpt:latest # docker hub
|
container_name: fastgpt
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
|
environment:
|
||||||
network_mode: host
|
# root 密码,用户名为: root
|
||||||
restart: always
|
- DEFAULT_ROOT_PSW=1234
|
||||||
container_name: fastgpt
|
# 中转地址,如果是用官方号,不需要管
|
||||||
environment:
|
- OPENAI_BASE_URL=https://api.openai.com/v1
|
||||||
# root 密码,用户名为: root
|
- CHAT_API_KEY=sk-xxxx
|
||||||
- DEFAULT_ROOT_PSW=1234
|
- DB_MAX_LINK=5 # database max link
|
||||||
# 中转地址,如果是用官方号,不需要管
|
# token加密凭证(随便填,作为登录凭证)
|
||||||
- OPENAI_BASE_URL=https://api.openai.com/v1
|
- TOKEN_KEY=any
|
||||||
- CHAT_API_KEY=sk-xxxx
|
# root key, 最高权限,可以内部接口互相调用
|
||||||
- DB_MAX_LINK=5 # database max link
|
- ROOT_KEY=root_key
|
||||||
# token加密凭证(随便填,作为登录凭证)
|
# mongo 配置,不需要改
|
||||||
- TOKEN_KEY=any
|
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017
|
||||||
# root key, 最高权限,可以内部接口互相调用
|
# - MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
|
||||||
- ROOT_KEY=root_key
|
- MONGODB_NAME=fastgpt
|
||||||
# mongo 配置,不需要改
|
# pg 配置
|
||||||
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
|
- PG_HOST=0.0.0.0
|
||||||
- MONGODB_NAME=fastgpt
|
- PG_PORT=5432
|
||||||
# pg 配置
|
- PG_USER=username
|
||||||
- PG_HOST=0.0.0.0
|
- PG_PASSWORD=password
|
||||||
- PG_PORT=5432
|
- PG_DB_NAME=postgres
|
||||||
- PG_USER=username
|
|
||||||
- PG_PASSWORD=password
|
|
||||||
- PG_DB_NAME=postgres
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 四、运行 docker-compose
|
## 四、运行 docker-compose
|
||||||
|
9
docSite/docs/develop/deploy/initv4.1.md
Normal file
9
docSite/docs/develop/deploy/initv4.1.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# V4.1 版本初始化
|
||||||
|
|
||||||
|
新版重新设置了对话存储结构,需要初始化原来的存储内容
|
||||||
|
|
||||||
|
## 执行初始化 API
|
||||||
|
|
||||||
|
部署新版项目,并发起 3 个 HTTP 请求(记得携带 headers.rootkey,这个值是环境变量里的)
|
||||||
|
|
||||||
|
https://xxxxx/api/admin/initChatItem
|
@@ -1,7 +1,3 @@
|
|||||||
---
|
|
||||||
sidebar_position: 2
|
|
||||||
---
|
|
||||||
|
|
||||||
# 配置其他对话模型
|
# 配置其他对话模型
|
||||||
|
|
||||||
默认情况下,FastGPT 只配置了 GPT 的 3 个模型,如果你需要接入其他模型,需要进行一些额外配置。
|
默认情况下,FastGPT 只配置了 GPT 的 3 个模型,如果你需要接入其他模型,需要进行一些额外配置。
|
||||||
|
@@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
sidebar_position: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
# 默认配置文件
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"FeConfig": {
|
||||||
|
"show_emptyChat": true,
|
||||||
|
"show_register": false,
|
||||||
|
"show_appStore": false,
|
||||||
|
"show_userDetail": false,
|
||||||
|
"show_git": true,
|
||||||
|
"systemTitle": "FastGPT",
|
||||||
|
"authorText": "Made by FastGPT Team.",
|
||||||
|
"gitLoginKey": "",
|
||||||
|
"scripts": []
|
||||||
|
},
|
||||||
|
"SystemParams": {
|
||||||
|
"gitLoginSecret": "",
|
||||||
|
"vectorMaxProcess": 15,
|
||||||
|
"qaMaxProcess": 15,
|
||||||
|
"pgIvfflatProbe": 20
|
||||||
|
},
|
||||||
|
"plugins": {},
|
||||||
|
"ChatModels": [
|
||||||
|
{
|
||||||
|
"model": "gpt-3.5-turbo",
|
||||||
|
"name": "GPT35-4k",
|
||||||
|
"contextMaxToken": 4000,
|
||||||
|
"quoteMaxToken": 2000,
|
||||||
|
"maxTemperature": 1.2,
|
||||||
|
"price": 0,
|
||||||
|
"defaultSystem": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "gpt-3.5-turbo-16k",
|
||||||
|
"name": "GPT35-16k",
|
||||||
|
"contextMaxToken": 16000,
|
||||||
|
"quoteMaxToken": 8000,
|
||||||
|
"maxTemperature": 1.2,
|
||||||
|
"price": 0,
|
||||||
|
"defaultSystem": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "gpt-4",
|
||||||
|
"name": "GPT4-8k",
|
||||||
|
"contextMaxToken": 8000,
|
||||||
|
"quoteMaxToken": 4000,
|
||||||
|
"maxTemperature": 1.2,
|
||||||
|
"price": 0,
|
||||||
|
"defaultSystem": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"QAModels": [
|
||||||
|
{
|
||||||
|
"model": "gpt-3.5-turbo-16k",
|
||||||
|
"name": "GPT35-16k",
|
||||||
|
"maxToken": 16000,
|
||||||
|
"price": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"VectorModels": [
|
||||||
|
{
|
||||||
|
"model": "text-embedding-ada-002",
|
||||||
|
"name": "Embedding-2",
|
||||||
|
"price": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
@@ -1,5 +1,5 @@
|
|||||||
---
|
---
|
||||||
sidebar_position: 1
|
sidebar_position: 2
|
||||||
---
|
---
|
||||||
|
|
||||||
# 快速介绍
|
# 快速介绍
|
||||||
@@ -10,6 +10,8 @@ sidebar_position: 1
|
|||||||
|
|
||||||
这个配置文件中包含了前端页面定制、系统级参数、AI 对话的模型等……
|
这个配置文件中包含了前端页面定制、系统级参数、AI 对话的模型等……
|
||||||
|
|
||||||
|
**注意:下面的配置介绍仅是局部介绍,你需要完整挂载整个 config.jso ,不能仅挂载一部分。你可以直接在给的 config.json 基础上根据下面的介绍进行修改。**
|
||||||
|
|
||||||
## 基础字段粗略说明
|
## 基础字段粗略说明
|
||||||
|
|
||||||
这里会介绍一些基础的配置字段。
|
这里会介绍一些基础的配置字段。
|
||||||
|
@@ -37,7 +37,7 @@ docker-compose -v
|
|||||||
version: '3.3'
|
version: '3.3'
|
||||||
services:
|
services:
|
||||||
pg:
|
pg:
|
||||||
image: ankane/pgvector:v0.4.2 # git
|
image: ankane/pgvector:v0.4.2 # docker
|
||||||
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.4.2 # 阿里云
|
# image: registry.cn-hangzhou.aliyuncs.com/fastgpt/pgvector:v0.4.2 # 阿里云
|
||||||
container_name: pg
|
container_name: pg
|
||||||
restart: always
|
restart: always
|
||||||
@@ -70,7 +70,7 @@ services:
|
|||||||
fastgpt:
|
fastgpt:
|
||||||
container_name: fastgpt
|
container_name: fastgpt
|
||||||
# image: c121914yu/fast-gpt:latest # docker hub
|
# image: c121914yu/fast-gpt:latest # docker hub
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
|
image: ghcr.io/labring/fastgpt:latest # 阿里云
|
||||||
ports:
|
ports:
|
||||||
- 3000:3000
|
- 3000:3000
|
||||||
networks:
|
networks:
|
||||||
@@ -89,7 +89,8 @@ services:
|
|||||||
- TOKEN_KEY=any
|
- TOKEN_KEY=any
|
||||||
- ROOT_KEY=root_key
|
- ROOT_KEY=root_key
|
||||||
# mongo 配置,不需要改
|
# mongo 配置,不需要改
|
||||||
- MONGODB_URI=mongodb://username:password@mongo:27017/?authSource=admin
|
- MONGODB_URI=mongodb://username:password@mongo:27017 # 如果这个连不上,尝试下面的
|
||||||
|
# - MONGODB_URI=mongodb://username:password@mongo:27017/?authSource=admin
|
||||||
- MONGODB_NAME=fastgpt
|
- MONGODB_NAME=fastgpt
|
||||||
# pg配置.
|
# pg配置.
|
||||||
- PG_HOST=pg
|
- PG_HOST=pg
|
||||||
@@ -136,7 +137,7 @@ volumes:
|
|||||||
fastgpt:
|
fastgpt:
|
||||||
# image: ghcr.io/c121914yu/fastgpt:latest # github
|
# image: ghcr.io/c121914yu/fastgpt:latest # github
|
||||||
# image: c121914yu/fast-gpt:latest # docker hub
|
# image: c121914yu/fast-gpt:latest # docker hub
|
||||||
image: registry.cn-hangzhou.aliyuncs.com/fastgpt/fastgpt:latest # 阿里云
|
image: ghcr.io/labring/fastgpt:latest # 阿里云
|
||||||
network_mode: host
|
network_mode: host
|
||||||
restart: always
|
restart: always
|
||||||
container_name: fastgpt
|
container_name: fastgpt
|
||||||
@@ -152,7 +153,8 @@ environment:
|
|||||||
# root key, 最高权限,可以内部接口互相调用
|
# root key, 最高权限,可以内部接口互相调用
|
||||||
- ROOT_KEY=root_key
|
- ROOT_KEY=root_key
|
||||||
# mongo 配置,不需要改
|
# mongo 配置,不需要改
|
||||||
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
|
- MONGODB_URI=mongodb://username:password@0.0.0.0:27017
|
||||||
|
# - MONGODB_URI=mongodb://username:password@0.0.0.0:27017/?authSource=admin
|
||||||
- MONGODB_NAME=fastgpt
|
- MONGODB_NAME=fastgpt
|
||||||
# pg 配置
|
# pg 配置
|
||||||
- PG_HOST=0.0.0.0
|
- PG_HOST=0.0.0.0
|
||||||
|
@@ -0,0 +1,9 @@
|
|||||||
|
# V4.1 版本初始化
|
||||||
|
|
||||||
|
新版重新设置了对话存储结构,需要初始化原来的存储内容
|
||||||
|
|
||||||
|
## 执行初始化 API
|
||||||
|
|
||||||
|
部署新版项目,并发起 3 个 HTTP 请求(记得携带 headers.rootkey,这个值是环境变量里的)
|
||||||
|
|
||||||
|
https://xxxxx/api/admin/initChatItem
|
Reference in New Issue
Block a user