mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-21 03:10:50 +00:00
perf: config fe
This commit is contained in:
9
client/data/FeConfig.json
Normal file
9
client/data/FeConfig.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"show_emptyChat": false,
|
||||||
|
"show_register": false,
|
||||||
|
"show_appStore": false,
|
||||||
|
"show_promotion": false,
|
||||||
|
"show_userDetail": false,
|
||||||
|
"show_git": false,
|
||||||
|
"authorText": "Made by FastGpt Team."
|
||||||
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
### 常见问题
|
### 常见问题
|
||||||
|
|
||||||
**反馈问卷**: 如果你遇到任何使用问题或有期望的功能,可以[填写该问卷](https://www.wjx.cn/vm/rLIw1uD.aspx#)
|
**反馈问卷**: 如果你遇到任何使用问题或有期望的功能,可以[填写该问卷](https://www.wjx.cn/vm/rLIw1uD.aspx#)
|
||||||
**Git 地址**: [项目地址。V4-preview 暂未开源,在正式版发布后会开源。](https://github.com/c121914yu/FastGPT)
|
**Git 地址**: [项目地址。V4-preview 暂未开源,在正式版发布后会开源。](https://github.com/labring/FastGPT)
|
||||||
**问题文档**: [先看文档,再提问](https://kjqvjse66l.feishu.cn/docx/HtrgdT0pkonP4kxGx8qcu6XDnGh)
|
**问题文档**: [先看文档,再提问](https://kjqvjse66l.feishu.cn/docx/HtrgdT0pkonP4kxGx8qcu6XDnGh)
|
||||||
**价格表**
|
**价格表**
|
||||||
| 计费项 | 价格: 元/ 1K tokens(包含上下文)|
|
| 计费项 | 价格: 元/ 1K tokens(包含上下文)|
|
||||||
|
@@ -14,13 +14,10 @@ import { useToast } from '@/hooks/useToast';
|
|||||||
import { useCopyData, voiceBroadcast, hasVoiceApi, getErrText } from '@/utils/tools';
|
import { useCopyData, voiceBroadcast, hasVoiceApi, getErrText } from '@/utils/tools';
|
||||||
import { Box, Card, Flex, Input, Textarea, Button, useTheme } from '@chakra-ui/react';
|
import { Box, Card, Flex, Input, Textarea, Button, useTheme } from '@chakra-ui/react';
|
||||||
import { useUserStore } from '@/store/user';
|
import { useUserStore } from '@/store/user';
|
||||||
|
import { feConfigs } from '@/store/static';
|
||||||
import { Types } from 'mongoose';
|
import { Types } from 'mongoose';
|
||||||
import { HUMAN_ICON, quoteLenKey, rawSearchKey } from '@/constants/chat';
|
import { HUMAN_ICON, quoteLenKey, rawSearchKey } from '@/constants/chat';
|
||||||
import Markdown from '@/components/Markdown';
|
|
||||||
import { EventNameEnum } from '../Markdown/constant';
|
import { EventNameEnum } from '../Markdown/constant';
|
||||||
import MyIcon from '@/components/Icon';
|
|
||||||
import Avatar from '@/components/Avatar';
|
|
||||||
|
|
||||||
import { adaptChatItem_openAI } from '@/utils/plugin/openai';
|
import { adaptChatItem_openAI } from '@/utils/plugin/openai';
|
||||||
import { useMarkdown } from '@/hooks/useMarkdown';
|
import { useMarkdown } from '@/hooks/useMarkdown';
|
||||||
@@ -32,14 +29,17 @@ import { fileDownload } from '@/utils/file';
|
|||||||
import { htmlTemplate } from '@/constants/common';
|
import { htmlTemplate } from '@/constants/common';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useGlobalStore } from '@/store/global';
|
import { useGlobalStore } from '@/store/global';
|
||||||
import dynamic from 'next/dynamic';
|
|
||||||
|
|
||||||
const QuoteModal = dynamic(() => import('./QuoteModal'));
|
|
||||||
|
|
||||||
import { QuoteItemType } from '@/pages/api/app/modules/kb/search';
|
import { QuoteItemType } from '@/pages/api/app/modules/kb/search';
|
||||||
import { FlowModuleTypeEnum } from '@/constants/flow';
|
import { FlowModuleTypeEnum } from '@/constants/flow';
|
||||||
import MyTooltip from '../MyTooltip';
|
|
||||||
|
import dynamic from 'next/dynamic';
|
||||||
|
const QuoteModal = dynamic(() => import('./QuoteModal'));
|
||||||
|
|
||||||
|
import MyIcon from '@/components/Icon';
|
||||||
|
import Avatar from '@/components/Avatar';
|
||||||
|
import Markdown from '@/components/Markdown';
|
||||||
import MySelect from '@/components/Select';
|
import MySelect from '@/components/Select';
|
||||||
|
import MyTooltip from '../MyTooltip';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const textareaMinH = '22px';
|
const textareaMinH = '22px';
|
||||||
@@ -393,7 +393,12 @@ const ChatBox = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const showEmpty = useMemo(
|
const showEmpty = useMemo(
|
||||||
() => showEmptyIntro && chatHistory.length === 0 && !variableModules?.length && !welcomeText,
|
() =>
|
||||||
|
feConfigs.show_emptyChat &&
|
||||||
|
showEmptyIntro &&
|
||||||
|
chatHistory.length === 0 &&
|
||||||
|
!variableModules?.length &&
|
||||||
|
!welcomeText,
|
||||||
[chatHistory.length, showEmptyIntro, variableModules, welcomeText]
|
[chatHistory.length, showEmptyIntro, variableModules, welcomeText]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { Box, Flex, Link } from '@chakra-ui/react';
|
import { Box, Flex, Link } from '@chakra-ui/react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import MyIcon from '../Icon';
|
|
||||||
import { useUserStore } from '@/store/user';
|
import { useUserStore } from '@/store/user';
|
||||||
import { useChatStore } from '@/store/chat';
|
import { useChatStore } from '@/store/chat';
|
||||||
import Avatar from '../Avatar';
|
|
||||||
import { HUMAN_ICON } from '@/constants/chat';
|
import { HUMAN_ICON } from '@/constants/chat';
|
||||||
|
import { feConfigs } from '@/store/static';
|
||||||
import NextLink from 'next/link';
|
import NextLink from 'next/link';
|
||||||
import Badge from '../Badge';
|
import Badge from '../Badge';
|
||||||
|
import Avatar from '../Avatar';
|
||||||
|
import MyIcon from '../Icon';
|
||||||
|
|
||||||
export enum NavbarTypeEnum {
|
export enum NavbarTypeEnum {
|
||||||
normal = 'normal',
|
normal = 'normal',
|
||||||
@@ -41,13 +42,17 @@ const Navbar = ({ unread }: { unread: number }) => {
|
|||||||
link: `/kb/list`,
|
link: `/kb/list`,
|
||||||
activeLink: ['/kb/list', '/kb/detail']
|
activeLink: ['/kb/list', '/kb/detail']
|
||||||
},
|
},
|
||||||
{
|
...(feConfigs.show_appStore
|
||||||
label: '市场',
|
? [
|
||||||
icon: 'appStoreLight',
|
{
|
||||||
activeIcon: 'appStoreFill',
|
label: '市场',
|
||||||
link: '/appStore',
|
icon: 'appStoreLight',
|
||||||
activeLink: ['/appStore']
|
activeIcon: 'appStoreFill',
|
||||||
},
|
link: '/appStore',
|
||||||
|
activeLink: ['/appStore']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
: []),
|
||||||
{
|
{
|
||||||
label: '账号',
|
label: '账号',
|
||||||
icon: 'meLight',
|
icon: 'meLight',
|
||||||
@@ -138,17 +143,19 @@ const Navbar = ({ unread }: { unread: number }) => {
|
|||||||
</Link>
|
</Link>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<Box>
|
{feConfigs.show_git && (
|
||||||
<Link
|
<Box>
|
||||||
as={NextLink}
|
<Link
|
||||||
href="https://github.com/labring/FastGPT"
|
as={NextLink}
|
||||||
target={'_blank'}
|
href="https://github.com/labring/FastGPT"
|
||||||
{...itemStyles}
|
target={'_blank'}
|
||||||
color={'#9096a5'}
|
{...itemStyles}
|
||||||
>
|
color={'#9096a5'}
|
||||||
<MyIcon name={'git'} width={'22px'} height={'22px'} />
|
>
|
||||||
</Link>
|
<MyIcon name={'git'} width={'22px'} height={'22px'} />
|
||||||
</Box>
|
</Link>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import React, { useMemo } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import MyIcon from '../Icon';
|
|
||||||
import { Flex, Box } from '@chakra-ui/react';
|
import { Flex, Box } from '@chakra-ui/react';
|
||||||
import { useChatStore } from '@/store/chat';
|
import { useChatStore } from '@/store/chat';
|
||||||
import Badge from '../Badge';
|
import Badge from '../Badge';
|
||||||
|
import MyIcon from '../Icon';
|
||||||
|
|
||||||
const NavbarPhone = ({ unread }: { unread: number }) => {
|
const NavbarPhone = ({ unread }: { unread: number }) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
@@ -17,5 +17,6 @@ export const Input_Template_History: FlowInputItemType = {
|
|||||||
export const Input_Template_UserChatInput: FlowInputItemType = {
|
export const Input_Template_UserChatInput: FlowInputItemType = {
|
||||||
key: SystemInputEnum.userChatInput,
|
key: SystemInputEnum.userChatInput,
|
||||||
type: FlowInputItemTypeEnum.target,
|
type: FlowInputItemTypeEnum.target,
|
||||||
label: '用户问题'
|
label: '用户问题',
|
||||||
|
required: true
|
||||||
};
|
};
|
||||||
|
@@ -6,7 +6,7 @@ import {
|
|||||||
type ChatModelItemType,
|
type ChatModelItemType,
|
||||||
type VectorModelItemType
|
type VectorModelItemType
|
||||||
} from '@/types/model';
|
} from '@/types/model';
|
||||||
import { readFileSync } from 'fs';
|
import type { FeConfigsType } from '@/types';
|
||||||
|
|
||||||
export type InitDateResponse = {
|
export type InitDateResponse = {
|
||||||
beianText: string;
|
beianText: string;
|
||||||
@@ -15,48 +15,7 @@ export type InitDateResponse = {
|
|||||||
chatModels: ChatModelItemType[];
|
chatModels: ChatModelItemType[];
|
||||||
qaModels: QAModelItemType[];
|
qaModels: QAModelItemType[];
|
||||||
vectorModels: VectorModelItemType[];
|
vectorModels: VectorModelItemType[];
|
||||||
};
|
feConfigs: FeConfigsType;
|
||||||
|
|
||||||
const defaultmodels = {
|
|
||||||
'FastAI-4k': {
|
|
||||||
model: 'gpt-3.5-turbo',
|
|
||||||
name: 'FastAI-4k',
|
|
||||||
contextMaxToken: 4000,
|
|
||||||
systemMaxToken: 2400,
|
|
||||||
maxTemperature: 1.2,
|
|
||||||
price: 1.5
|
|
||||||
},
|
|
||||||
'FastAI-16k': {
|
|
||||||
model: 'gpt-3.5-turbo',
|
|
||||||
name: 'FastAI-16k',
|
|
||||||
contextMaxToken: 16000,
|
|
||||||
systemMaxToken: 8000,
|
|
||||||
maxTemperature: 1.2,
|
|
||||||
price: 3
|
|
||||||
},
|
|
||||||
'FastAI-Plus': {
|
|
||||||
model: 'gpt-4',
|
|
||||||
name: 'FastAI-Plus',
|
|
||||||
contextMaxToken: 8000,
|
|
||||||
systemMaxToken: 4000,
|
|
||||||
maxTemperature: 1.2,
|
|
||||||
price: 45
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const defaultQaModels = {
|
|
||||||
'FastAI-16k': {
|
|
||||||
model: 'gpt-3.5-turbo',
|
|
||||||
name: 'FastAI-16k',
|
|
||||||
maxToken: 16000,
|
|
||||||
price: 3
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const defaultVectorModels = {
|
|
||||||
'text-embedding-ada-002': {
|
|
||||||
model: 'text-embedding-ada-002',
|
|
||||||
name: 'Embedding-2',
|
|
||||||
price: 0.2
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
@@ -69,46 +28,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
jsonRes<InitDateResponse>(res, {
|
jsonRes<InitDateResponse>(res, {
|
||||||
data: {
|
data: {
|
||||||
...envs,
|
...envs,
|
||||||
...initSystemModels()
|
chatModels: global.chatModels,
|
||||||
|
qaModels: global.qaModels,
|
||||||
|
vectorModels: global.vectorModels,
|
||||||
|
feConfigs: global.feConfigs
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initSystemModels() {
|
|
||||||
const { chatModels, qaModels, vectorModels } = (() => {
|
|
||||||
try {
|
|
||||||
const chatModels = Object.values(JSON.parse(readFileSync('data/ChatModels.json', 'utf-8')));
|
|
||||||
const qaModels = Object.values(JSON.parse(readFileSync('data/QAModels.json', 'utf-8')));
|
|
||||||
const vectorModels = Object.values(
|
|
||||||
JSON.parse(readFileSync('data/VectorModels.json', 'utf-8'))
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
|
||||||
chatModels,
|
|
||||||
qaModels,
|
|
||||||
vectorModels
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
|
|
||||||
return {
|
|
||||||
chatModels: Object.values(defaultmodels),
|
|
||||||
qaModels: Object.values(defaultQaModels),
|
|
||||||
vectorModels: Object.values(defaultVectorModels)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
})() as {
|
|
||||||
chatModels: ChatModelItemType[];
|
|
||||||
qaModels: QAModelItemType[];
|
|
||||||
vectorModels: VectorModelItemType[];
|
|
||||||
};
|
|
||||||
global.chatModels = chatModels;
|
|
||||||
global.qaModels = qaModels;
|
|
||||||
global.vectorModels = vectorModels;
|
|
||||||
|
|
||||||
return {
|
|
||||||
chatModels,
|
|
||||||
qaModels,
|
|
||||||
vectorModels
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@@ -2,6 +2,11 @@ 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 { readFileSync } from 'fs';
|
import { readFileSync } from 'fs';
|
||||||
|
import {
|
||||||
|
type QAModelItemType,
|
||||||
|
type ChatModelItemType,
|
||||||
|
type VectorModelItemType
|
||||||
|
} from '@/types/model';
|
||||||
|
|
||||||
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
|
||||||
await authUser({ req, authRoot: true });
|
await authUser({ req, authRoot: true });
|
||||||
@@ -22,3 +27,97 @@ export async function updateSystemEnv() {
|
|||||||
console.log('update system env error');
|
console.log('update system env error');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultmodels = {
|
||||||
|
'FastAI-4k': {
|
||||||
|
model: 'gpt-3.5-turbo',
|
||||||
|
name: 'FastAI-4k',
|
||||||
|
contextMaxToken: 4000,
|
||||||
|
systemMaxToken: 2400,
|
||||||
|
maxTemperature: 1.2,
|
||||||
|
price: 1.5
|
||||||
|
},
|
||||||
|
'FastAI-16k': {
|
||||||
|
model: 'gpt-3.5-turbo',
|
||||||
|
name: 'FastAI-16k',
|
||||||
|
contextMaxToken: 16000,
|
||||||
|
systemMaxToken: 8000,
|
||||||
|
maxTemperature: 1.2,
|
||||||
|
price: 3
|
||||||
|
},
|
||||||
|
'FastAI-Plus': {
|
||||||
|
model: 'gpt-4',
|
||||||
|
name: 'FastAI-Plus',
|
||||||
|
contextMaxToken: 8000,
|
||||||
|
systemMaxToken: 4000,
|
||||||
|
maxTemperature: 1.2,
|
||||||
|
price: 45
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const defaultQaModels = {
|
||||||
|
'FastAI-16k': {
|
||||||
|
model: 'gpt-3.5-turbo',
|
||||||
|
name: 'FastAI-16k',
|
||||||
|
maxToken: 16000,
|
||||||
|
price: 3
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const defaultVectorModels = {
|
||||||
|
'text-embedding-ada-002': {
|
||||||
|
model: 'text-embedding-ada-002',
|
||||||
|
name: 'Embedding-2',
|
||||||
|
price: 0.2
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export function initSystemModels() {
|
||||||
|
const { chatModels, qaModels, vectorModels } = (() => {
|
||||||
|
try {
|
||||||
|
const chatModels = Object.values(JSON.parse(readFileSync('data/ChatModels.json', 'utf-8')));
|
||||||
|
const qaModels = Object.values(JSON.parse(readFileSync('data/QAModels.json', 'utf-8')));
|
||||||
|
const vectorModels = Object.values(
|
||||||
|
JSON.parse(readFileSync('data/VectorModels.json', 'utf-8'))
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
chatModels,
|
||||||
|
qaModels,
|
||||||
|
vectorModels
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
return {
|
||||||
|
chatModels: Object.values(defaultmodels),
|
||||||
|
qaModels: Object.values(defaultQaModels),
|
||||||
|
vectorModels: Object.values(defaultVectorModels)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})() as {
|
||||||
|
chatModels: ChatModelItemType[];
|
||||||
|
qaModels: QAModelItemType[];
|
||||||
|
vectorModels: VectorModelItemType[];
|
||||||
|
};
|
||||||
|
global.chatModels = chatModels;
|
||||||
|
global.qaModels = qaModels;
|
||||||
|
global.vectorModels = vectorModels;
|
||||||
|
console.log({
|
||||||
|
chatModels,
|
||||||
|
qaModels,
|
||||||
|
vectorModels
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
chatModels,
|
||||||
|
qaModels,
|
||||||
|
vectorModels
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function initFeConfig() {
|
||||||
|
const feConfig = JSON.parse(readFileSync('data/FeConfig.json', 'utf-8'));
|
||||||
|
|
||||||
|
global.feConfigs = feConfig;
|
||||||
|
console.log(feConfig);
|
||||||
|
|
||||||
|
return feConfig;
|
||||||
|
}
|
||||||
|
@@ -32,6 +32,11 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
|
|||||||
|
|
||||||
await connectToDatabase();
|
await connectToDatabase();
|
||||||
|
|
||||||
|
// register switch
|
||||||
|
if (type === UserAuthTypeEnum.register && !global.feConfigs.show_register) {
|
||||||
|
throw new Error('Register is closed');
|
||||||
|
}
|
||||||
|
|
||||||
const code = nanoid();
|
const code = nanoid();
|
||||||
|
|
||||||
// 判断 1 分钟内是否有重复数据
|
// 判断 1 分钟内是否有重复数据
|
||||||
|
@@ -25,8 +25,8 @@ const ChatHeader = ({
|
|||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
alignItems={'center'}
|
alignItems={'center'}
|
||||||
py={[3, 5]}
|
|
||||||
px={[3, 5]}
|
px={[3, 5]}
|
||||||
|
h={['46px', '60px']}
|
||||||
borderBottom={theme.borders.base}
|
borderBottom={theme.borders.base}
|
||||||
borderBottomColor={'gray.200'}
|
borderBottomColor={'gray.200'}
|
||||||
color={'myGray.900'}
|
color={'myGray.900'}
|
||||||
|
@@ -5,6 +5,7 @@ import { useMarkdown } from '@/hooks/useMarkdown';
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useGlobalStore } from '@/store/global';
|
import { useGlobalStore } from '@/store/global';
|
||||||
import { beianText } from '@/store/static';
|
import { beianText } from '@/store/static';
|
||||||
|
import { feConfigs } from '@/store/static';
|
||||||
|
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
@@ -209,17 +210,19 @@ const Home = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Box w={'100%'} mt={'100vh'} px={[5, 10]} pb={[5, 10]}>
|
{feConfigs?.authorText && (
|
||||||
<Card p={5} mt={4} textAlign={'center'}>
|
<Box w={'100%'} mt={'100vh'} px={[5, 10]} pb={[5, 10]}>
|
||||||
{beianText && (
|
<Card p={5} mt={4} textAlign={'center'}>
|
||||||
<Link href="https://beian.miit.gov.cn/" target="_blank">
|
{beianText && (
|
||||||
{beianText}
|
<Link href="https://beian.miit.gov.cn/" target="_blank">
|
||||||
</Link>
|
{beianText}
|
||||||
)}
|
</Link>
|
||||||
|
)}
|
||||||
|
|
||||||
<Box>Made by FastGpt Team.</Box>
|
<Box>{feConfigs?.authorText}</Box>
|
||||||
</Card>
|
</Card>
|
||||||
</Box>
|
</Box>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -14,6 +14,7 @@ import dynamic from 'next/dynamic';
|
|||||||
import { useSelectFile } from '@/hooks/useSelectFile';
|
import { useSelectFile } from '@/hooks/useSelectFile';
|
||||||
import { compressImg } from '@/utils/file';
|
import { compressImg } from '@/utils/file';
|
||||||
import { getErrText, useCopyData } from '@/utils/tools';
|
import { getErrText, useCopyData } from '@/utils/tools';
|
||||||
|
import { feConfigs } from '@/store/static';
|
||||||
|
|
||||||
import Loading from '@/components/Loading';
|
import Loading from '@/components/Loading';
|
||||||
import Avatar from '@/components/Avatar';
|
import Avatar from '@/components/Avatar';
|
||||||
@@ -58,7 +59,7 @@ const NumberSetting = ({ tableType }: { tableType: `${TableEnum}` }) => {
|
|||||||
const { copyData } = useCopyData();
|
const { copyData } = useCopyData();
|
||||||
const { userInfo, updateUserInfo, initUserInfo, setUserInfo } = useUserStore();
|
const { userInfo, updateUserInfo, initUserInfo, setUserInfo } = useUserStore();
|
||||||
const { setLoading } = useGlobalStore();
|
const { setLoading } = useGlobalStore();
|
||||||
const { register, handleSubmit, reset } = useForm<UserUpdateParams>({
|
const { reset } = useForm<UserUpdateParams>({
|
||||||
defaultValues: userInfo as UserType
|
defaultValues: userInfo as UserType
|
||||||
});
|
});
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
@@ -146,105 +147,117 @@ const NumberSetting = ({ tableType }: { tableType: `${TableEnum}` }) => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box py={[5, 10]} px={'5vw'}>
|
<>
|
||||||
<Grid gridTemplateColumns={['1fr', '3fr 300px']} gridGap={4}>
|
<Box py={[5, 10]} px={'5vw'}>
|
||||||
<Card px={6} py={4}>
|
<Grid gridTemplateColumns={['1fr', '3fr 300px']} gridGap={4}>
|
||||||
<Flex justifyContent={'space-between'}>
|
<Card px={6} py={4}>
|
||||||
<Box fontSize={'xl'} fontWeight={'bold'}>
|
<Flex justifyContent={'space-between'}>
|
||||||
账号信息
|
<Box fontSize={'xl'} fontWeight={'bold'}>
|
||||||
</Box>
|
账号信息
|
||||||
<Button variant={'base'} size={'xs'} onClick={onclickLogOut}>
|
|
||||||
退出登录
|
|
||||||
</Button>
|
|
||||||
</Flex>
|
|
||||||
<Flex mt={6} alignItems={'center'}>
|
|
||||||
<Box flex={'0 0 50px'}>头像:</Box>
|
|
||||||
<Avatar
|
|
||||||
src={userInfo?.avatar}
|
|
||||||
w={['28px', '36px']}
|
|
||||||
h={['28px', '36px']}
|
|
||||||
cursor={'pointer'}
|
|
||||||
title={'点击切换头像'}
|
|
||||||
onClick={onOpenSelectFile}
|
|
||||||
/>
|
|
||||||
</Flex>
|
|
||||||
<Flex mt={6} alignItems={'center'}>
|
|
||||||
<Box flex={'0 0 50px'}>账号:</Box>
|
|
||||||
<Box>{userInfo?.username}</Box>
|
|
||||||
</Flex>
|
|
||||||
<Box mt={6}>
|
|
||||||
<Flex alignItems={'center'}>
|
|
||||||
<Box flex={'0 0 50px'}>余额:</Box>
|
|
||||||
<Box>
|
|
||||||
<strong>{userInfo?.balance}</strong> 元
|
|
||||||
</Box>
|
</Box>
|
||||||
<Button size={['xs', 'sm']} w={['70px', '80px']} ml={5} onClick={onOpenPayModal}>
|
<Button variant={'base'} size={'xs'} onClick={onclickLogOut}>
|
||||||
充值
|
退出登录
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
<Flex mt={6} alignItems={'center'}>
|
||||||
</Card>
|
<Box flex={'0 0 50px'}>头像:</Box>
|
||||||
<Card px={6} py={4}>
|
<Avatar
|
||||||
<Box fontSize={'xl'} fontWeight={'bold'}>
|
src={userInfo?.avatar}
|
||||||
我的邀请
|
w={['28px', '36px']}
|
||||||
</Box>
|
h={['28px', '36px']}
|
||||||
{[
|
cursor={'pointer'}
|
||||||
{ label: '佣金比例', value: `${userInfo?.promotion.rate || 15}%` },
|
title={'点击切换头像'}
|
||||||
{ label: '已注册用户数', value: `${invitedAmount}人` },
|
onClick={onOpenSelectFile}
|
||||||
{ label: '可用佣金', value: `¥${residueAmount}` }
|
/>
|
||||||
].map((item) => (
|
|
||||||
<Flex key={item.label} alignItems={'center'} mt={4} justifyContent={'space-between'}>
|
|
||||||
<Box w={'120px'}>{item.label}</Box>
|
|
||||||
<Box fontWeight={'bold'}>{item.value}</Box>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
))}
|
<Flex mt={6} alignItems={'center'}>
|
||||||
<Button
|
<Box flex={'0 0 50px'}>账号:</Box>
|
||||||
mt={4}
|
<Box>{userInfo?.username}</Box>
|
||||||
variant={'base'}
|
</Flex>
|
||||||
w={'100%'}
|
{feConfigs.show_userDetail && (
|
||||||
onClick={() =>
|
<Box mt={6}>
|
||||||
copyData(`${location.origin}/?inviterId=${userInfo?._id}`, '已复制邀请链接')
|
<Flex alignItems={'center'}>
|
||||||
}
|
<Box flex={'0 0 50px'}>余额:</Box>
|
||||||
>
|
<Box>
|
||||||
复制邀请链接
|
<strong>{userInfo?.balance}</strong> 元
|
||||||
</Button>
|
</Box>
|
||||||
<Button
|
<Button size={['xs', 'sm']} w={['70px', '80px']} ml={5} onClick={onOpenPayModal}>
|
||||||
mt={4}
|
充值
|
||||||
leftIcon={<MyIcon name="withdraw" w={'22px'} />}
|
</Button>
|
||||||
px={4}
|
</Flex>
|
||||||
title={residueAmount < 50 ? '最低提现额度为50元' : ''}
|
</Box>
|
||||||
isDisabled={residueAmount < 50}
|
)}
|
||||||
variant={'base'}
|
</Card>
|
||||||
colorScheme={'myBlue'}
|
{feConfigs.show_userDetail && (
|
||||||
onClick={onOpenWxConcat}
|
<Card px={6} py={4}>
|
||||||
>
|
<Box fontSize={'xl'} fontWeight={'bold'}>
|
||||||
{residueAmount < 50 ? '50元起提' : '提现'}
|
我的邀请
|
||||||
</Button>
|
</Box>
|
||||||
</Card>
|
{[
|
||||||
</Grid>
|
{ label: '佣金比例', value: `${userInfo?.promotion.rate || 15}%` },
|
||||||
|
{ label: '已注册用户数', value: `${invitedAmount}人` },
|
||||||
|
{ label: '可用佣金', value: `¥${residueAmount}` }
|
||||||
|
].map((item) => (
|
||||||
|
<Flex
|
||||||
|
key={item.label}
|
||||||
|
alignItems={'center'}
|
||||||
|
mt={4}
|
||||||
|
justifyContent={'space-between'}
|
||||||
|
>
|
||||||
|
<Box w={'120px'}>{item.label}</Box>
|
||||||
|
<Box fontWeight={'bold'}>{item.value}</Box>
|
||||||
|
</Flex>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
mt={4}
|
||||||
|
variant={'base'}
|
||||||
|
w={'100%'}
|
||||||
|
onClick={() =>
|
||||||
|
copyData(`${location.origin}/?inviterId=${userInfo?._id}`, '已复制邀请链接')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
复制邀请链接
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
mt={4}
|
||||||
|
leftIcon={<MyIcon name="withdraw" w={'22px'} />}
|
||||||
|
px={4}
|
||||||
|
title={residueAmount < 50 ? '最低提现额度为50元' : ''}
|
||||||
|
isDisabled={residueAmount < 50}
|
||||||
|
variant={'base'}
|
||||||
|
colorScheme={'myBlue'}
|
||||||
|
onClick={onOpenWxConcat}
|
||||||
|
>
|
||||||
|
{residueAmount < 50 ? '50元起提' : '提现'}
|
||||||
|
</Button>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
|
||||||
<Card mt={4} px={[3, 6]} py={4}>
|
{feConfigs.show_userDetail && (
|
||||||
<Tabs
|
<Card mt={4} px={[3, 6]} py={4}>
|
||||||
m={'auto'}
|
<Tabs
|
||||||
w={'200px'}
|
m={'auto'}
|
||||||
list={tableList.current}
|
w={'200px'}
|
||||||
activeId={tableType}
|
list={tableList.current}
|
||||||
size={'sm'}
|
activeId={tableType}
|
||||||
onChange={(id: any) => router.replace(`/number?type=${id}`)}
|
size={'sm'}
|
||||||
/>
|
onChange={(id: any) => router.replace(`/number?type=${id}`)}
|
||||||
<Box minH={'300px'}>
|
/>
|
||||||
{(() => {
|
<Box minH={'300px'}>
|
||||||
const item = tableList.current.find((item) => item.id === tableType);
|
{(() => {
|
||||||
|
const item = tableList.current.find((item) => item.id === tableType);
|
||||||
return item ? item.Component : null;
|
|
||||||
})()}
|
|
||||||
</Box>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
|
return item ? item.Component : null;
|
||||||
|
})()}
|
||||||
|
</Box>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
{isOpenPayModal && <PayModal onClose={onClosePayModal} />}
|
{isOpenPayModal && <PayModal onClose={onClosePayModal} />}
|
||||||
{isOpenWxConcat && <WxConcat onClose={onCloseWxConcat} />}
|
{isOpenWxConcat && <WxConcat onClose={onCloseWxConcat} />}
|
||||||
<File onSelect={onSelectFile} />
|
<File onSelect={onSelectFile} />
|
||||||
</Box>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -3,6 +3,7 @@ import { Box, Flex } from '@chakra-ui/react';
|
|||||||
import { ChevronRightIcon } from '@chakra-ui/icons';
|
import { ChevronRightIcon } from '@chakra-ui/icons';
|
||||||
import MyIcon from '@/components/Icon';
|
import MyIcon from '@/components/Icon';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
import { feConfigs } from '@/store/static';
|
||||||
|
|
||||||
const list = [
|
const list = [
|
||||||
{
|
{
|
||||||
@@ -10,16 +11,24 @@ const list = [
|
|||||||
label: '我的知识库',
|
label: '我的知识库',
|
||||||
link: '/kb/list'
|
link: '/kb/list'
|
||||||
},
|
},
|
||||||
{
|
...(feConfigs.show_appStore
|
||||||
icon: 'appStoreLight',
|
? [
|
||||||
label: 'AI应用市场',
|
{
|
||||||
link: '/appStore'
|
icon: 'appStoreLight',
|
||||||
},
|
label: 'AI应用市场',
|
||||||
{
|
link: '/appStore'
|
||||||
icon: 'git',
|
}
|
||||||
label: 'Git项目地址',
|
]
|
||||||
link: 'https://github.com/labring/FastGPT'
|
: []),
|
||||||
}
|
...(feConfigs.show_git
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
icon: 'git',
|
||||||
|
label: 'Git项目地址',
|
||||||
|
link: 'https://github.com/labring/FastGPT'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
: [])
|
||||||
];
|
];
|
||||||
|
|
||||||
const Tools = () => {
|
const Tools = () => {
|
||||||
|
@@ -1,8 +1,7 @@
|
|||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import tunnel from 'tunnel';
|
import tunnel from 'tunnel';
|
||||||
import { startQueue } from './utils/tools';
|
import { startQueue } from './utils/tools';
|
||||||
import { updateSystemEnv } from '@/pages/api/system/updateEnv';
|
import { updateSystemEnv, initSystemModels, initFeConfig } from '@/pages/api/system/updateEnv';
|
||||||
import { initSystemModels } from '@/pages/api/system/getInitData';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 连接 MongoDB 数据库
|
* 连接 MongoDB 数据库
|
||||||
@@ -24,6 +23,7 @@ export async function connectToDatabase(): Promise<void> {
|
|||||||
};
|
};
|
||||||
global.sendInformQueue = [];
|
global.sendInformQueue = [];
|
||||||
global.sendInformQueueLen = 0;
|
global.sendInformQueueLen = 0;
|
||||||
|
global.feConfigs = {};
|
||||||
// proxy obj
|
// proxy obj
|
||||||
if (process.env.AXIOS_PROXY_HOST && process.env.AXIOS_PROXY_PORT) {
|
if (process.env.AXIOS_PROXY_HOST && process.env.AXIOS_PROXY_PORT) {
|
||||||
global.httpsAgent = tunnel.httpsOverHttp({
|
global.httpsAgent = tunnel.httpsOverHttp({
|
||||||
@@ -33,7 +33,10 @@ export async function connectToDatabase(): Promise<void> {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init function
|
||||||
initSystemModels();
|
initSystemModels();
|
||||||
|
initFeConfig();
|
||||||
updateSystemEnv();
|
updateSystemEnv();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@@ -6,6 +6,7 @@ import {
|
|||||||
import type { InitDateResponse } from '@/pages/api/system/getInitData';
|
import type { InitDateResponse } from '@/pages/api/system/getInitData';
|
||||||
import { getInitData } from '@/api/system';
|
import { getInitData } from '@/api/system';
|
||||||
import { delay } from '@/utils/tools';
|
import { delay } from '@/utils/tools';
|
||||||
|
import { FeConfigsType } from '@/types';
|
||||||
|
|
||||||
export let beianText = '';
|
export let beianText = '';
|
||||||
export let googleVerKey = '';
|
export let googleVerKey = '';
|
||||||
@@ -13,6 +14,7 @@ export let baiduTongji = '';
|
|||||||
export let chatModelList: ChatModelItemType[] = [];
|
export let chatModelList: ChatModelItemType[] = [];
|
||||||
export let qaModelList: QAModelItemType[] = [];
|
export let qaModelList: QAModelItemType[] = [];
|
||||||
export let vectorModelList: VectorModelItemType[] = [];
|
export let vectorModelList: VectorModelItemType[] = [];
|
||||||
|
export let feConfigs: FeConfigsType = {};
|
||||||
|
|
||||||
let retryTimes = 3;
|
let retryTimes = 3;
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@ export const clientInitData = async (): Promise<InitDateResponse> => {
|
|||||||
chatModelList = res.chatModels;
|
chatModelList = res.chatModels;
|
||||||
qaModelList = res.qaModels;
|
qaModelList = res.qaModels;
|
||||||
vectorModelList = res.vectorModels;
|
vectorModelList = res.vectorModels;
|
||||||
|
feConfigs = res.feConfigs;
|
||||||
beianText = res.beianText;
|
beianText = res.beianText;
|
||||||
googleVerKey = res.googleVerKey;
|
googleVerKey = res.googleVerKey;
|
||||||
baiduTongji = res.baiduTongji;
|
baiduTongji = res.baiduTongji;
|
||||||
|
11
client/src/types/index.d.ts
vendored
11
client/src/types/index.d.ts
vendored
@@ -13,6 +13,16 @@ export type PagingData<T> = {
|
|||||||
|
|
||||||
export type RequestPaging = { pageNum: number; pageSize: number; [key]: any };
|
export type RequestPaging = { pageNum: number; pageSize: number; [key]: any };
|
||||||
|
|
||||||
|
export type FeConfigsType = {
|
||||||
|
show_emptyChat?: boolean;
|
||||||
|
show_register?: boolean;
|
||||||
|
show_appStore?: boolean;
|
||||||
|
show_promotion?: boolean;
|
||||||
|
show_userDetail?: boolean;
|
||||||
|
show_git?: false;
|
||||||
|
authorText?: string;
|
||||||
|
};
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
var mongodb: Mongoose | string | null;
|
var mongodb: Mongoose | string | null;
|
||||||
var pgClient: Pool | null;
|
var pgClient: Pool | null;
|
||||||
@@ -31,6 +41,7 @@ declare global {
|
|||||||
var chatModels: ChatModelItemType[];
|
var chatModels: ChatModelItemType[];
|
||||||
var qaModels: QAModelItemType[];
|
var qaModels: QAModelItemType[];
|
||||||
var vectorModels: VectorModelItemType[];
|
var vectorModels: VectorModelItemType[];
|
||||||
|
var feConfigs: FeConfigsType;
|
||||||
|
|
||||||
interface Window {
|
interface Window {
|
||||||
['pdfjs-dist/build/pdf']: any;
|
['pdfjs-dist/build/pdf']: any;
|
||||||
|
BIN
docs/zh/modules/imgs/intro1.png
Normal file
BIN
docs/zh/modules/imgs/intro1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 413 KiB |
19
docs/zh/modules/intro.md
Normal file
19
docs/zh/modules/intro.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# 模块编排介绍
|
||||||
|
|
||||||
|
FastGpt V4 后将采用新的交互方式来构建 AI 应用。使用了“节点”编排的方式去掉原先的表单方式。提高可玩性和扩展性的同时也提高了上手的门槛,这篇文章就来简单介绍一下 “预览版” 的模块编排基本使用方法。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
预览版仅包含了 8 个模块,你可以利用它们来完全实现 V3 的知识库功能。此外,预览版还加入了问题分类模块,可以实现多路线任务。
|
||||||
|
|
||||||
|
## 基础知识
|
||||||
|
|
||||||
|
### 什么是模块
|
||||||
|
|
||||||
|
在程序中,模块可以理解为一个个 function 或者接口。对于非技术背景同学,可以理解为它就是一个**步骤**。将多个模块一个个拼接起来,即可一步步的去实现最终的 AI 输出。
|
||||||
|
|
||||||
|
### 如何阅读和理解
|
||||||
|
|
||||||
|
1. 建议从左往右阅读。
|
||||||
|
2. 从 **用户问题** 模块开始。用户问题模块,代表的是用户发送了一段文本,触发任务开始。
|
||||||
|
3.
|
Reference in New Issue
Block a user