mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-13 14:29:40 +00:00
fix: toolset rewrite
This commit is contained in:
@@ -65,7 +65,7 @@ import type { SystemToolInputTypeEnum } from '@fastgpt/global/core/app/systemToo
|
||||
import type { StoreSecretValueType } from '@fastgpt/global/common/secret/type';
|
||||
import type { appConfigType } from './sub/app';
|
||||
import type { DatasetConfigType } from './sub/dataset';
|
||||
import { getSubApps } from './sub';
|
||||
import { getSubApps, rewriteSubAppsToolset } from './sub';
|
||||
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
|
||||
import { dispatchRunTool } from '../../child/runTool';
|
||||
import { dispatchRunAppNode } from '../../child/runApp';
|
||||
@@ -123,23 +123,26 @@ export const dispatchRunAgent = async (props: DispatchAgentModuleProps): Promise
|
||||
}
|
||||
} = props;
|
||||
|
||||
const runtimeSubApps = subApps.map<RuntimeNodeItemType>((node) => {
|
||||
return {
|
||||
nodeId: node.id,
|
||||
name: node.name,
|
||||
avatar: node.avatar,
|
||||
intro: node.intro,
|
||||
toolDescription: node.toolDescription,
|
||||
flowNodeType: node.flowNodeType,
|
||||
showStatus: node.showStatus,
|
||||
isEntry: false,
|
||||
inputs: node.inputs,
|
||||
outputs: node.outputs,
|
||||
pluginId: node.pluginId,
|
||||
version: node.version,
|
||||
toolConfig: node.toolConfig,
|
||||
catchError: node.catchError
|
||||
};
|
||||
const runtimeSubApps = await rewriteSubAppsToolset({
|
||||
subApps: subApps.map<RuntimeNodeItemType>((node) => {
|
||||
return {
|
||||
nodeId: node.id,
|
||||
name: node.name,
|
||||
avatar: node.avatar,
|
||||
intro: node.intro,
|
||||
toolDescription: node.toolDescription,
|
||||
flowNodeType: node.flowNodeType,
|
||||
showStatus: node.showStatus,
|
||||
isEntry: false,
|
||||
inputs: node.inputs,
|
||||
outputs: node.outputs,
|
||||
pluginId: node.pluginId,
|
||||
version: node.version,
|
||||
toolConfig: node.toolConfig,
|
||||
catchError: node.catchError
|
||||
};
|
||||
}),
|
||||
lang
|
||||
});
|
||||
|
||||
try {
|
||||
@@ -151,6 +154,9 @@ export const dispatchRunAgent = async (props: DispatchAgentModuleProps): Promise
|
||||
fileLinks = undefined;
|
||||
}
|
||||
|
||||
const subAppList = getSubApps({ subApps: runtimeSubApps, urls: fileLinks });
|
||||
console.log(JSON.stringify(subAppList, null, 2));
|
||||
|
||||
// Init tool params
|
||||
const toolNodesMap = new Map(runtimeSubApps.map((item) => [item.nodeId, item]));
|
||||
const getToolInfo = (id: string) => {
|
||||
@@ -161,8 +167,6 @@ export const dispatchRunAgent = async (props: DispatchAgentModuleProps): Promise
|
||||
};
|
||||
};
|
||||
|
||||
const subAppList = await getSubApps({ subApps: runtimeSubApps, urls: fileLinks, lang });
|
||||
console.log(JSON.stringify(subAppList, null, 2));
|
||||
// const combinedSystemPrompt = `${parseAgentSystem({ systemPrompt, toolNodesMap })}\n\n${getTopAgentConstantPrompt()}`;
|
||||
|
||||
// TODO: 把 files 加入 query 中。
|
||||
|
@@ -18,15 +18,59 @@ import { getMCPChildren } from '../../../../../app/mcp';
|
||||
import { getMCPToolRuntimeNode } from '@fastgpt/global/core/app/mcpTools/utils';
|
||||
import type { localeType } from '@fastgpt/global/common/i18n/type';
|
||||
|
||||
export const getSubApps = async ({
|
||||
export const rewriteSubAppsToolset = ({
|
||||
subApps,
|
||||
lang,
|
||||
urls
|
||||
lang
|
||||
}: {
|
||||
subApps: RuntimeNodeItemType[];
|
||||
lang?: localeType;
|
||||
}) => {
|
||||
return Promise.all(
|
||||
subApps.map(async (node) => {
|
||||
if (node.flowNodeType === FlowNodeTypeEnum.toolSet) {
|
||||
const systemToolId = node.toolConfig?.systemToolSet?.toolId;
|
||||
const mcpToolsetVal = node.toolConfig?.mcpToolSet ?? node.inputs[0].value;
|
||||
if (systemToolId) {
|
||||
const children = await getSystemToolRunTimeNodeFromSystemToolset({
|
||||
toolSetNode: node,
|
||||
lang
|
||||
});
|
||||
return children;
|
||||
} else if (mcpToolsetVal) {
|
||||
const app = await MongoApp.findOne({ _id: node.pluginId }).lean();
|
||||
if (!app) return [];
|
||||
const toolList = await getMCPChildren(app);
|
||||
|
||||
const parentId = mcpToolsetVal.toolId ?? node.pluginId;
|
||||
const children = toolList.map((tool, index) => {
|
||||
const newToolNode = getMCPToolRuntimeNode({
|
||||
avatar: node.avatar,
|
||||
tool,
|
||||
// New ?? Old
|
||||
parentId
|
||||
});
|
||||
newToolNode.nodeId = `${parentId}${index}`; // ID 不能随机,否则下次生成时候就和之前的记录对不上
|
||||
newToolNode.name = `${node.name}/${tool.name}`;
|
||||
|
||||
return newToolNode;
|
||||
});
|
||||
|
||||
return children;
|
||||
}
|
||||
return [];
|
||||
} else {
|
||||
return [node];
|
||||
}
|
||||
})
|
||||
).then((res) => res.flat());
|
||||
};
|
||||
export const getSubApps = ({
|
||||
subApps,
|
||||
urls
|
||||
}: {
|
||||
subApps: RuntimeNodeItemType[];
|
||||
urls?: string[];
|
||||
}): Promise<ChatCompletionTool[]> => {
|
||||
}): ChatCompletionTool[] => {
|
||||
// System Tools: Plan Agent, stop sign, model agent.
|
||||
const systemTools: ChatCompletionTool[] = [
|
||||
PlanAgentTool,
|
||||
@@ -36,105 +80,63 @@ export const getSubApps = async ({
|
||||
];
|
||||
|
||||
// Node Tools
|
||||
const getToolNode = (nodes: RuntimeNodeItemType[]) => {
|
||||
return nodes.map<ChatCompletionTool>((item) => {
|
||||
const toolParams: FlowNodeInputItemType[] = [];
|
||||
let jsonSchema: JSONSchemaInputType | undefined;
|
||||
const nodeTools = subApps.map<ChatCompletionTool>((item) => {
|
||||
const toolParams: FlowNodeInputItemType[] = [];
|
||||
let jsonSchema: JSONSchemaInputType | undefined;
|
||||
|
||||
for (const input of item.inputs) {
|
||||
if (input.toolDescription) {
|
||||
toolParams.push(input);
|
||||
}
|
||||
|
||||
if (input.key === NodeInputKeyEnum.toolData) {
|
||||
jsonSchema = (input.value as McpToolDataType).inputSchema;
|
||||
}
|
||||
for (const input of item.inputs) {
|
||||
if (input.toolDescription) {
|
||||
toolParams.push(input);
|
||||
}
|
||||
|
||||
const description = JSON.stringify({
|
||||
type: item.flowNodeType,
|
||||
name: item.name,
|
||||
intro: item.toolDescription || item.intro
|
||||
});
|
||||
|
||||
if (jsonSchema) {
|
||||
return {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: item.nodeId,
|
||||
description,
|
||||
parameters: jsonSchema
|
||||
}
|
||||
};
|
||||
if (input.key === NodeInputKeyEnum.toolData) {
|
||||
jsonSchema = (input.value as McpToolDataType).inputSchema;
|
||||
}
|
||||
}
|
||||
|
||||
const properties: Record<string, any> = {};
|
||||
toolParams.forEach((param) => {
|
||||
const jsonSchema = param.valueType
|
||||
? valueTypeJsonSchemaMap[param.valueType] || toolValueTypeList[0].jsonSchema
|
||||
: toolValueTypeList[0].jsonSchema;
|
||||
|
||||
properties[param.key] = {
|
||||
...jsonSchema,
|
||||
description: param.toolDescription || '',
|
||||
enum: param.enum?.split('\n').filter(Boolean) || undefined
|
||||
};
|
||||
});
|
||||
const description = JSON.stringify({
|
||||
type: item.flowNodeType,
|
||||
name: item.name,
|
||||
intro: item.toolDescription || item.intro
|
||||
});
|
||||
|
||||
if (jsonSchema) {
|
||||
return {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: item.nodeId,
|
||||
description,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties,
|
||||
required: toolParams.filter((param) => param.required).map((param) => param.key)
|
||||
}
|
||||
parameters: jsonSchema
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const properties: Record<string, any> = {};
|
||||
toolParams.forEach((param) => {
|
||||
const jsonSchema = param.valueType
|
||||
? valueTypeJsonSchemaMap[param.valueType] || toolValueTypeList[0].jsonSchema
|
||||
: toolValueTypeList[0].jsonSchema;
|
||||
|
||||
properties[param.key] = {
|
||||
...jsonSchema,
|
||||
description: param.toolDescription || '',
|
||||
enum: param.enum?.split('\n').filter(Boolean) || undefined
|
||||
};
|
||||
});
|
||||
};
|
||||
const nodeTools = (
|
||||
await Promise.all(
|
||||
subApps.map(async (node) => {
|
||||
if (node.flowNodeType === FlowNodeTypeEnum.toolSet) {
|
||||
const systemToolId = node.toolConfig?.systemToolSet?.toolId;
|
||||
const mcpToolsetVal = node.toolConfig?.mcpToolSet ?? node.inputs[0].value;
|
||||
if (systemToolId) {
|
||||
const children = await getSystemToolRunTimeNodeFromSystemToolset({
|
||||
toolSetNode: node,
|
||||
lang
|
||||
});
|
||||
return getToolNode(children);
|
||||
} else if (mcpToolsetVal) {
|
||||
const app = await MongoApp.findOne({ _id: node.pluginId }).lean();
|
||||
if (!app) return [];
|
||||
const toolList = await getMCPChildren(app);
|
||||
|
||||
const parentId = mcpToolsetVal.toolId ?? node.pluginId;
|
||||
const children = toolList.map((tool, index) => {
|
||||
const newToolNode = getMCPToolRuntimeNode({
|
||||
avatar: node.avatar,
|
||||
tool,
|
||||
// New ?? Old
|
||||
parentId
|
||||
});
|
||||
newToolNode.nodeId = `${parentId}${index}`; // ID 不能随机,否则下次生成时候就和之前的记录对不上
|
||||
newToolNode.name = `${node.name}/${tool.name}`;
|
||||
|
||||
return newToolNode;
|
||||
});
|
||||
|
||||
return getToolNode(children);
|
||||
}
|
||||
return [];
|
||||
} else {
|
||||
return getToolNode([node]);
|
||||
return {
|
||||
type: 'function',
|
||||
function: {
|
||||
name: item.nodeId,
|
||||
description,
|
||||
parameters: {
|
||||
type: 'object',
|
||||
properties,
|
||||
required: toolParams.filter((param) => param.required).map((param) => param.key)
|
||||
}
|
||||
})
|
||||
)
|
||||
).flat();
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
return [...systemTools, ...nodeTools];
|
||||
};
|
||||
|
Reference in New Issue
Block a user