mirror of
https://github.com/labring/FastGPT.git
synced 2025-07-23 05:12:39 +00:00
4.7 doc update (#1068)
* fix: plugin update * feat: get current time plugin * fix: ts * perf: select app ux * fix: ts * perf: max w * move code * perf: inform tip * fix: inform * doc * fix: tool handle * perf: tmp file store * doc * fix: message file selector * feat: doc * perf: switch trigger * doc * fix: openapi import * rount the number * parse openapi schema * fix empty line after variables (#64) * doc image * image size * doc * doc * catch error --------- Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
@@ -84,7 +84,9 @@
|
||||
"charsPointsPrice": 0,
|
||||
"defaultToken": 700,
|
||||
"maxToken": 3000,
|
||||
"weight": 100
|
||||
"weight": 100,
|
||||
"dbConfig": {},
|
||||
"queryConfig": {}
|
||||
}
|
||||
],
|
||||
"reRankModels": [],
|
||||
|
@@ -9,7 +9,6 @@
|
||||
"lint": "next lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "^10.1.0",
|
||||
"@bany/curl-to-json": "^1.2.8",
|
||||
"@chakra-ui/anatomy": "2.2.1",
|
||||
"@chakra-ui/icons": "2.1.1",
|
||||
|
@@ -1,7 +1,13 @@
|
||||
### FastGPT V4.7
|
||||
|
||||
1. 新增 - 工具调用模块,可以让LLM模型根据用户意图,动态的选择其他模型或插件执行。
|
||||
2. 优化 - 高级编排性能
|
||||
3. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow/intro)
|
||||
4. [使用文档](https://doc.fastgpt.in/docs/intro/)
|
||||
5. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/)
|
||||
2. 新增 - 分类和内容提取支持 functionCall 模式。部分模型支持 functionCall 不支持 ToolCall,也可以使用了。需要把 LLM 模型配置文件里的 `functionCall` 设置为 `true`, `toolChoice`设置为 `false`。如果 `toolChoice` 为 true,会走 tool 模式。
|
||||
3. 新增 - HTTP插件,可实现OpenAPI快速生成插件。
|
||||
4. 优化 - 高级编排性能。
|
||||
5. 优化 - AI模型选择。
|
||||
6. 优化 - 手动输入知识库弹窗。
|
||||
7. 优化 - 变量输入弹窗。
|
||||
8. 优化 - 浏览器读取文件自动推断编码,减少乱码情况。
|
||||
9. [点击查看高级编排介绍文档](https://doc.fastgpt.in/docs/workflow/intro)
|
||||
10. [使用文档](https://doc.fastgpt.in/docs/intro/)
|
||||
11. [点击查看商业版](https://doc.fastgpt.in/docs/commercial/)
|
@@ -405,7 +405,7 @@ export const FlowProvider = ({
|
||||
toolInputs: inputs.filter((item) => isTool && item.toolDescription),
|
||||
commonInputs: inputs.filter((item) => {
|
||||
if (!isTool) return true;
|
||||
return !item.toolDescription && item.key !== ModuleInputKeyEnum.switch;
|
||||
return !item.toolDescription;
|
||||
})
|
||||
};
|
||||
},
|
||||
|
@@ -4,7 +4,7 @@ import { BoxProps } from '@chakra-ui/react';
|
||||
|
||||
const Container = ({ children, ...props }: BoxProps) => {
|
||||
return (
|
||||
<Box px={'16px'} py={'10px'} position={'relative'} {...props}>
|
||||
<Box px={4} py={'10px'} position={'relative'} {...props}>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
|
@@ -16,6 +16,7 @@ import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||
import { LOGO_ICON } from '@fastgpt/global/common/system/constants';
|
||||
import { ToolTargetHandle } from './ToolHandle';
|
||||
import { useEditTextarea } from '@fastgpt/web/hooks/useEditTextarea';
|
||||
import TriggerAndFinish from './RenderInput/templates/TriggerAndFinish';
|
||||
|
||||
type Props = FlowModuleItemType & {
|
||||
children?: React.ReactNode | React.ReactNode[] | string;
|
||||
@@ -208,6 +209,8 @@ const NodeCard = (props: Props) => {
|
||||
</Button>
|
||||
)}
|
||||
</Flex>
|
||||
{/* switch */}
|
||||
<TriggerAndFinish moduleId={moduleId} isTool={moduleIsTool} />
|
||||
</Box>
|
||||
);
|
||||
}, [
|
||||
|
@@ -13,10 +13,6 @@ const RenderList: {
|
||||
types: `${FlowNodeInputTypeEnum}`[];
|
||||
Component: React.ComponentType<RenderInputProps>;
|
||||
}[] = [
|
||||
{
|
||||
types: [FlowNodeInputTypeEnum.triggerAndFinish],
|
||||
Component: dynamic(() => import('./templates/TriggerAndFinish'))
|
||||
},
|
||||
{
|
||||
types: [FlowNodeInputTypeEnum.input],
|
||||
Component: dynamic(() => import('./templates/TextInput'))
|
||||
|
@@ -7,10 +7,18 @@ import SourceHandle from '../../SourceHandle';
|
||||
import { ModuleInputKeyEnum, ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
|
||||
import { useFlowProviderStore } from '../../../../FlowProvider';
|
||||
|
||||
const TriggerAndFinish = ({ moduleId }: RenderInputProps) => {
|
||||
const TriggerAndFinish = ({ moduleId, isTool }: { moduleId: string; isTool: boolean }) => {
|
||||
const { t } = useTranslation();
|
||||
const { nodes } = useFlowProviderStore();
|
||||
|
||||
const inputs = useMemo(
|
||||
() => nodes.find((node) => node.data.moduleId === moduleId)?.data?.inputs || [],
|
||||
[moduleId, nodes]
|
||||
);
|
||||
const hasSwitch = useMemo(
|
||||
() => inputs.some((input) => input.key === ModuleInputKeyEnum.switch),
|
||||
[inputs]
|
||||
);
|
||||
const outputs = useMemo(
|
||||
() => nodes.find((node) => node.data.moduleId === moduleId)?.data?.outputs || [],
|
||||
[moduleId, nodes]
|
||||
@@ -20,8 +28,8 @@ const TriggerAndFinish = ({ moduleId }: RenderInputProps) => {
|
||||
[outputs]
|
||||
);
|
||||
|
||||
const Render = useMemo(
|
||||
() => (
|
||||
const Render = useMemo(() => {
|
||||
return (
|
||||
<Flex
|
||||
className="nodrag"
|
||||
cursor={'default'}
|
||||
@@ -30,21 +38,24 @@ const TriggerAndFinish = ({ moduleId }: RenderInputProps) => {
|
||||
position={'relative'}
|
||||
>
|
||||
<Box position={'relative'}>
|
||||
<TargetHandle handleKey={ModuleInputKeyEnum.switch} valueType={'any'} />
|
||||
{t('core.module.input.label.switch')}
|
||||
{!isTool && (
|
||||
<Box mt={2}>
|
||||
<TargetHandle handleKey={ModuleInputKeyEnum.switch} valueType={'any'} />
|
||||
{t('core.module.input.label.switch')}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
{hasFinishOutput && (
|
||||
<Box position={'relative'}>
|
||||
<Box position={'relative'} mt={2}>
|
||||
{t('core.module.output.label.running done')}
|
||||
<SourceHandle handleKey={ModuleOutputKeyEnum.finish} valueType={'boolean'} />
|
||||
</Box>
|
||||
)}
|
||||
</Flex>
|
||||
),
|
||||
[hasFinishOutput, t]
|
||||
);
|
||||
);
|
||||
}, [hasFinishOutput, isTool, t]);
|
||||
|
||||
return Render;
|
||||
return hasSwitch ? Render : null;
|
||||
};
|
||||
|
||||
export default React.memo(TriggerAndFinish);
|
||||
|
@@ -28,8 +28,8 @@ const SourceHandle = ({ handleKey, valueType, ...props }: Props) => {
|
||||
<Box
|
||||
position={'absolute'}
|
||||
top={'50%'}
|
||||
right={'-20px'}
|
||||
transform={'translate(50%,-50%)'}
|
||||
right={'-18px'}
|
||||
transform={'translate(0,-50%)'}
|
||||
{...props}
|
||||
>
|
||||
<MyTooltip
|
||||
|
@@ -27,8 +27,8 @@ const TargetHandle = ({ handleKey, valueType, ...props }: Props) => {
|
||||
<Box
|
||||
position={'absolute'}
|
||||
top={'50%'}
|
||||
left={'-20px'}
|
||||
transform={'translate(50%,-50%)'}
|
||||
left={'-18px'}
|
||||
transform={'translate(0,-50%)'}
|
||||
{...props}
|
||||
>
|
||||
<MyTooltip
|
||||
|
@@ -41,6 +41,7 @@ export const ToolTargetHandle = ({ moduleId }: ToolHandleProps) => {
|
||||
h={'14px'}
|
||||
border={'4px solid #5E8FFF'}
|
||||
transform={'translate(-40%,-30%) rotate(45deg)'}
|
||||
pointerEvents={'none'}
|
||||
/>
|
||||
</Handle>
|
||||
</MyTooltip>
|
||||
@@ -98,6 +99,7 @@ export const ToolSourceHandle = ({ moduleId }: ToolHandleProps) => {
|
||||
h={'14px'}
|
||||
border={'4px solid #5E8FFF'}
|
||||
transform={'translate(-40%,-30%) rotate(45deg)'}
|
||||
pointerEvents={'none'}
|
||||
/>
|
||||
</Handle>
|
||||
</MyTooltip>
|
||||
|
@@ -4,7 +4,6 @@ import { connectToDatabase } from '@/service/mongo';
|
||||
import type { CreateOnePluginParams } from '@fastgpt/global/core/plugin/controller';
|
||||
import { authUserNotVisitor } from '@fastgpt/service/support/permission/auth/user';
|
||||
import { MongoPlugin } from '@fastgpt/service/core/plugin/schema';
|
||||
import { checkTeamPluginLimit } from '@fastgpt/service/support/permission/teamLimit';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
import { httpApiSchema2Plugins } from '@fastgpt/global/core/plugin/httpPlugin/utils';
|
||||
|
||||
@@ -31,7 +30,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
|
||||
{ session }
|
||||
);
|
||||
|
||||
const childrenPlugins = httpApiSchema2Plugins({
|
||||
const childrenPlugins = await httpApiSchema2Plugins({
|
||||
parentId,
|
||||
apiSchemaStr: body.metadata?.apiSchemaStr,
|
||||
customHeader: body.metadata?.customHeaders
|
||||
|
@@ -1,15 +1,13 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { jsonRes } from '@fastgpt/service/common/response';
|
||||
import SwaggerParser from '@apidevtools/swagger-parser';
|
||||
import { loadOpenAPISchemaFromUrl } from '@fastgpt/global/common/string/swagger';
|
||||
|
||||
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
|
||||
try {
|
||||
const apiURL = req.body.url as string;
|
||||
|
||||
const api = await SwaggerParser.validate(apiURL);
|
||||
|
||||
return jsonRes(res, {
|
||||
data: api
|
||||
data: await loadOpenAPISchemaFromUrl(apiURL)
|
||||
});
|
||||
} catch (err) {
|
||||
jsonRes(res, {
|
||||
|
@@ -75,7 +75,7 @@ const updateHttpChildrenPlugin = async ({
|
||||
'_id metadata'
|
||||
);
|
||||
|
||||
const schemaPlugins = httpApiSchema2Plugins({
|
||||
const schemaPlugins = await httpApiSchema2Plugins({
|
||||
parentId: parent.id,
|
||||
apiSchemaStr: parent.metadata?.apiSchemaStr,
|
||||
customHeader: parent.metadata?.customHeaders
|
||||
|
@@ -13,8 +13,7 @@ import {
|
||||
Tbody,
|
||||
Tr,
|
||||
Td,
|
||||
IconButton,
|
||||
useDisclosure
|
||||
IconButton
|
||||
} from '@chakra-ui/react';
|
||||
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
|
||||
import { useForm } from 'react-hook-form';
|
||||
@@ -37,12 +36,12 @@ import {
|
||||
import { str2OpenApiSchema } from '@fastgpt/global/core/plugin/httpPlugin/utils';
|
||||
import MyIcon from '@fastgpt/web/components/common/Icon';
|
||||
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
|
||||
import { AddIcon } from '@chakra-ui/icons';
|
||||
import MyModal from '@fastgpt/web/components/common/MyModal';
|
||||
import { EditFormType } from './type';
|
||||
import { FolderImgUrl } from '@fastgpt/global/common/file/image/constants';
|
||||
import HttpInput from '@fastgpt/web/components/common/Input/HttpInput';
|
||||
import { HttpHeaders } from '@/components/core/module/Flow/components/nodes/NodeHttp';
|
||||
import { OpenApiJsonSchema } from '@fastgpt/global/core/plugin/httpPlugin/type';
|
||||
|
||||
export const defaultHttpPlugin: CreateOnePluginParams = {
|
||||
avatar: FolderImgUrl,
|
||||
@@ -85,20 +84,7 @@ const HttpPluginEditModal = ({
|
||||
defaultValues: defaultPlugin
|
||||
});
|
||||
const apiSchemaStr = watch('metadata.apiSchemaStr');
|
||||
const apiData = useMemo(() => {
|
||||
if (!apiSchemaStr) {
|
||||
return { pathData: [], serverPath: '' };
|
||||
}
|
||||
try {
|
||||
return str2OpenApiSchema(apiSchemaStr);
|
||||
} catch (err) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('plugin.Invalid Schema')
|
||||
});
|
||||
return { pathData: [], serverPath: '' };
|
||||
}
|
||||
}, [apiSchemaStr, t, toast]);
|
||||
const [apiData, setApiData] = useState<OpenApiJsonSchema>({ pathData: [], serverPath: '' });
|
||||
|
||||
const { mutate: onCreate, isLoading: isCreating } = useRequest({
|
||||
mutationFn: async (data: CreateOnePluginParams) => {
|
||||
@@ -201,6 +187,23 @@ const HttpPluginEditModal = ({
|
||||
[customHeaders]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
if (!apiSchemaStr) {
|
||||
return setApiData({ pathData: [], serverPath: '' });
|
||||
}
|
||||
try {
|
||||
setApiData(await str2OpenApiSchema(apiSchemaStr));
|
||||
} catch (err) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('plugin.Invalid Schema')
|
||||
});
|
||||
setApiData({ pathData: [], serverPath: '' });
|
||||
}
|
||||
})();
|
||||
}, [apiSchemaStr, t, toast]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<MyModal
|
||||
|
@@ -39,6 +39,9 @@ const ExtraPlan = () => {
|
||||
const onclickBuyDatasetSize = useCallback(
|
||||
async ({ datasetSize, month }: { datasetSize: number; month: number }) => {
|
||||
try {
|
||||
datasetSize = Math.ceil(datasetSize);
|
||||
month = Math.ceil(month);
|
||||
|
||||
const datasetSizePayAmount = datasetSize * month * extraDatasetPrice;
|
||||
if (datasetSizePayAmount === 0) {
|
||||
return toast({
|
||||
@@ -80,6 +83,8 @@ const ExtraPlan = () => {
|
||||
const onclickBuyExtraPoints = useCallback(
|
||||
async ({ points }: { points: number }) => {
|
||||
try {
|
||||
points = Math.ceil(points);
|
||||
|
||||
const month = 1;
|
||||
const payAmount = points * month * extraPointsPrice;
|
||||
|
||||
|
@@ -11,6 +11,8 @@ import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
import { initGlobal } from './common/system';
|
||||
import { startMongoWatch } from './common/system/volumnMongoWatch';
|
||||
import { startTrainingQueue } from './core/dataset/training/utils';
|
||||
import { clearDirFiles } from '@fastgpt/service/common/file/utils';
|
||||
import { tmpFileDirPath } from '@fastgpt/service/common/file/constants';
|
||||
|
||||
/**
|
||||
* connect MongoDB and init data
|
||||
@@ -32,6 +34,9 @@ export function connectToDatabase(): Promise<void> {
|
||||
|
||||
// start queue
|
||||
startTrainingQueue(true);
|
||||
|
||||
// clear tmp files
|
||||
clearDirFiles(tmpFileDirPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@@ -23,6 +23,8 @@ type StreamResponseType = {
|
||||
responseText: string;
|
||||
[DispatchNodeResponseKeyEnum.nodeResponse]: ChatHistoryItemResType[];
|
||||
};
|
||||
class FatalError extends Error {}
|
||||
|
||||
export const streamFetch = ({
|
||||
url = '/api/v1/chat/completions',
|
||||
data,
|
||||
@@ -206,9 +208,12 @@ export const streamFetch = ({
|
||||
onclose() {
|
||||
finished = true;
|
||||
},
|
||||
onerror(e) {
|
||||
onerror(err) {
|
||||
if (err instanceof FatalError) {
|
||||
throw err;
|
||||
}
|
||||
clearTimeout(timeoutId);
|
||||
failedFinish(getErrText(e));
|
||||
failedFinish(getErrText(err));
|
||||
},
|
||||
openWhenHidden: true
|
||||
});
|
||||
|
@@ -15,7 +15,10 @@ export function checkChatSupportSelectFileByChatModels(models: string[] = []) {
|
||||
}
|
||||
|
||||
export function checkChatSupportSelectFileByModules(modules: ModuleItemType[] = []) {
|
||||
const chatModules = modules.filter((item) => item.flowType === FlowNodeTypeEnum.chatNode);
|
||||
const chatModules = modules.filter(
|
||||
(item) =>
|
||||
item.flowType === FlowNodeTypeEnum.chatNode || item.flowType === FlowNodeTypeEnum.tools
|
||||
);
|
||||
const models: string[] = chatModules.map(
|
||||
(item) => item.inputs.find((item) => item.key === 'model')?.value || ''
|
||||
);
|
||||
|
Reference in New Issue
Block a user