Skip to content

Commit dae1093

Browse files
c121914yuctrlz526
andauthored
Feat: system tool support stream response (#5206)
* Match SSE for FastGPT (#5168) * Match SSE for FastGPT * Modify the judgment * Optimize logic for SSE transmission * Refactor imports * directly use workflowStreamResponse from props * improve error handling and streamline onStreamData logic * Refactor API client configuration * perf: system tool support sse * update doc --------- Co-authored-by: Zhuangzai fa <[email protected]>
1 parent b591a16 commit dae1093

File tree

11 files changed

+111
-66
lines changed

11 files changed

+111
-66
lines changed

docSite/content/zh-cn/docs/development/upgrading/4101.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ curl --location --request POST 'https://{{host}}/api/admin/initv4101' \
3232

3333
- 给自动同步的知识库加入新的定时任务。
3434

35+
## 🚀 新增内容
36+
37+
1. 系统工具支持流输出。
38+
3539
## ⚙️ 优化
3640

3741
1. 定时任务报错日志记录到对话日志。

docSite/content/zh-cn/docs/guide/dashboard/workflow/tool.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,5 +82,5 @@ weight: 236
8282

8383
### **相关示例**
8484

85-
- [谷歌搜索](https://doc.fastgpt.in/docs/use-cases/app-cases/google_search/)
86-
- [发送飞书webhook](https://doc.fastgpt.in/docs/use-cases/app-cases/feishu_webhook/)
85+
- [谷歌搜索](https://doc.fastgpt.io/docs/use-cases/app-cases/google_search/)
86+
- [发送飞书webhook](https://doc.fastgpt.io/docs/use-cases/app-cases/feishu_webhook/)

docSite/content/zh-cn/docs/use-cases/app-cases/submit_application_template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ weight: 602
2222

2323
需要在 dev 环境下执行下面的操作。
2424

25-
> 可参照 [FastGPT|快速开始本地开发](https://doc.fastgpt.in/docs/development/intro/)
25+
> 可参照 [FastGPT|快速开始本地开发](https://doc.fastgpt.io/docs/development/intro/)
2626
2727
1. ### 在 FastGPT 工作台中,创建一个应用
2828

docSite/hugo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
baseURL = "https://doc.tryfastgpt.ai"
1+
baseURL = "https://doc.fastgpt.io"
22
languageCode = "en-GB"
33
contentDir = "content"
44
enableEmoji = true
@@ -114,7 +114,7 @@ defaultContentLanguageInSubdir = false
114114
# Link behaviour
115115
intLinkTooltip = true # Enable a tooltip for internal links that displays info about the destination? default false
116116
# extLinkNewTab = false # Open external links in a new Tab? default true
117-
logoLinkURL = "https://tryfastgpt.ai/" # Set a custom URL destination for the top header logo link.
117+
logoLinkURL = "https://fastgpt.io/" # Set a custom URL destination for the top header logo link.
118118

119119
[params.flexsearch] # Parameters for FlexSearch
120120
# enabled = true

docSite/static/llms-full.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12768,8 +12768,8 @@ function main({secret}){
1276812768

1276912769
### **相关示例**
1277012770

12771-
- [谷歌搜索](https://doc.fastgpt.in/docs/use-cases/app-cases/google_search/)
12772-
- [发送飞书webhook](https://doc.fastgpt.in/docs/use-cases/app-cases/feishu_webhook/)
12771+
- [谷歌搜索](https://doc.fastgpt.io/docs/use-cases/app-cases/google_search/)
12772+
- [发送飞书webhook](https://doc.fastgpt.io/docs/use-cases/app-cases/feishu_webhook/)
1277312773

1277412774
# 用户选择
1277512775
## FastGPT 用户选择模块的使用说明
@@ -18332,7 +18332,7 @@ Fastgpt 提供了工作流线路可以返回去执行的功能,所以我们可
1833218332

1833318333
需要在 dev 环境下执行下面的操作。
1833418334

18335-
> 可参照 [FastGPT|快速开始本地开发](https://doc.fastgpt.in/docs/development/intro/)
18335+
> 可参照 [FastGPT|快速开始本地开发](https://doc.fastgpt.io/docs/development/intro/)
1833618336

1833718337
1. ### 在 FastGPT 工作台中,创建一个应用
1833818338

packages/global/common/middle/tracks/constants.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@ export enum TrackEnum {
33
createApp = 'createApp',
44
useAppTemplate = 'useAppTemplate',
55
createDataset = 'createDataset',
6-
appNodes = 'appNodes'
6+
appNodes = 'appNodes',
7+
runSystemTool = 'runSystemTool'
78
}

packages/service/common/middle/tracks/utils.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { type ShortUrlParams } from '@fastgpt/global/support/marketing/type';
1010

1111
const createTrack = ({ event, data }: { event: TrackEnum; data: Record<string, any> }) => {
1212
if (!global.feConfigs?.isPlus) return;
13-
addLog.info('Push tracks', {
13+
addLog.debug('Push tracks', {
1414
event,
1515
...data
1616
});
@@ -65,5 +65,13 @@ export const pushTrack = {
6565
}
6666
});
6767
} catch (error) {}
68+
},
69+
runSystemTool: (
70+
data: PushTrackCommonType & { toolId: string; result: 1 | 0; usagePoint?: number; msg?: string }
71+
) => {
72+
return createTrack({
73+
event: TrackEnum.runSystemTool,
74+
data
75+
});
6876
}
6977
};

packages/service/core/app/tool/api.ts

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import createClient, { type SystemVarType } from '@fastgpt-sdk/plugin';
1+
import createClient, { RunToolWithStream } from '@fastgpt-sdk/plugin';
22
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
33

4+
const BASE_URL = process.env.PLUGIN_BASE_URL || '';
5+
const TOKEN = process.env.PLUGIN_TOKEN || '';
6+
47
const client = createClient({
5-
baseUrl: process.env.PLUGIN_BASE_URL || '',
6-
token: process.env.PLUGIN_TOKEN || ''
8+
baseUrl: BASE_URL,
9+
token: TOKEN
710
});
811

912
export async function getSystemToolList() {
@@ -26,26 +29,8 @@ export async function getSystemToolList() {
2629
return Promise.reject(res.body);
2730
}
2831

29-
export async function runTool({
30-
toolId,
31-
inputs,
32-
systemVar
33-
}: {
34-
toolId: string;
35-
inputs: Record<string, any>;
36-
systemVar: SystemVarType;
37-
}) {
38-
const res = await client.tool.run({
39-
body: {
40-
toolId,
41-
inputs,
42-
systemVar
43-
}
44-
});
45-
46-
if (res.status === 200 && res.body.output) {
47-
return res.body.output;
48-
} else {
49-
return Promise.reject(res.body);
50-
}
51-
}
32+
const runToolInstance = new RunToolWithStream({
33+
baseUrl: BASE_URL,
34+
token: TOKEN
35+
});
36+
export const runSystemTool = runToolInstance.run.bind(runToolInstance);

packages/service/core/workflow/dispatch/plugin/runTool.ts

Lines changed: 69 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { getErrText } from '@fastgpt/global/common/error/utils';
22
import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
3+
import type { SseResponseEventEnum } from '@fastgpt/global/core/workflow/runtime/constants';
34
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
45
import {
56
type DispatchNodeResultType,
@@ -9,11 +10,13 @@ import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
910
import { MCPClient } from '../../../app/mcp';
1011
import { getSecretValue } from '../../../../common/secret/utils';
1112
import type { McpToolDataType } from '@fastgpt/global/core/app/mcpTools/type';
12-
import { runTool } from '../../../app/tool/api';
13+
import { runSystemTool } from '../../../app/tool/api';
1314
import { MongoSystemPlugin } from '../../../app/plugin/systemPluginSchema';
1415
import { SystemToolInputTypeEnum } from '@fastgpt/global/core/app/systemTool/constants';
1516
import type { StoreSecretValueType } from '@fastgpt/global/common/secret/type';
16-
import { getSystemPluginById, splitCombinePluginId } from '../../../app/plugin/controller';
17+
import { getSystemPluginById } from '../../../app/plugin/controller';
18+
import { textAdaptGptResponse } from '@fastgpt/global/core/workflow/runtime/utils';
19+
import { pushTrack } from '../../../../common/middle/tracks/utils';
1720

1821
type SystemInputConfigType = {
1922
type: SystemToolInputTypeEnum;
@@ -39,13 +42,16 @@ export const dispatchRunTool = async (props: RunToolProps): Promise<RunToolRespo
3942
runningUserInfo,
4043
runningAppInfo,
4144
variables,
45+
workflowStreamResponse,
4246
node: { name, avatar, toolConfig, version }
4347
} = props;
4448

49+
const systemToolId = toolConfig?.systemTool?.toolId;
50+
4551
try {
4652
// run system tool
47-
if (toolConfig?.systemTool?.toolId) {
48-
const tool = await getSystemPluginById(toolConfig.systemTool!.toolId);
53+
if (systemToolId) {
54+
const tool = await getSystemPluginById(systemToolId);
4955

5056
const inputConfigParams = await (async () => {
5157
switch (params.system_input_config?.type) {
@@ -73,28 +79,47 @@ export const dispatchRunTool = async (props: RunToolProps): Promise<RunToolRespo
7379
};
7480

7581
const formatToolId = tool.id.split('-')[1];
76-
const result = await runTool({
77-
toolId: formatToolId,
78-
inputs,
79-
systemVar: {
80-
user: {
81-
id: variables.userId,
82-
teamId: runningUserInfo.teamId,
83-
name: runningUserInfo.tmbId
84-
},
85-
app: {
86-
id: runningAppInfo.id,
87-
name: runningAppInfo.id
88-
},
89-
tool: {
90-
id: formatToolId,
91-
version
82+
83+
const result = await (async () => {
84+
const res = await runSystemTool({
85+
toolId: formatToolId,
86+
inputs,
87+
systemVar: {
88+
user: {
89+
id: variables.userId,
90+
teamId: runningUserInfo.teamId,
91+
name: runningUserInfo.tmbId
92+
},
93+
app: {
94+
id: runningAppInfo.id,
95+
name: runningAppInfo.id
96+
},
97+
tool: {
98+
id: formatToolId,
99+
version
100+
},
101+
time: variables.cTime
92102
},
93-
time: variables.cTime
103+
onMessage: ({ type, content }) => {
104+
if (workflowStreamResponse && content) {
105+
workflowStreamResponse({
106+
event: type as unknown as SseResponseEventEnum,
107+
data: textAdaptGptResponse({
108+
text: content
109+
})
110+
});
111+
}
112+
}
113+
});
114+
if (res.error) {
115+
return Promise.reject(res.error);
94116
}
95-
});
117+
if (!res.output) return {};
96118

97-
const usagePoints = await (async () => {
119+
return res.output;
120+
})();
121+
122+
const usagePoints = (() => {
98123
if (
99124
params.system_input_config?.type !== SystemToolInputTypeEnum.system ||
100125
result[NodeOutputKeyEnum.systemError]
@@ -104,6 +129,16 @@ export const dispatchRunTool = async (props: RunToolProps): Promise<RunToolRespo
104129
return tool.currentCost ?? 0;
105130
})();
106131

132+
pushTrack.runSystemTool({
133+
teamId: runningUserInfo.teamId,
134+
tmbId: runningUserInfo.tmbId,
135+
uid: runningUserInfo.tmbId,
136+
toolId: tool.id,
137+
result: 1,
138+
usagePoint: usagePoints,
139+
msg: result[NodeOutputKeyEnum.systemError]
140+
});
141+
107142
return {
108143
[DispatchNodeResponseKeyEnum.nodeResponse]: {
109144
toolRes: result,
@@ -142,6 +177,17 @@ export const dispatchRunTool = async (props: RunToolProps): Promise<RunToolRespo
142177
};
143178
}
144179
} catch (error) {
180+
if (systemToolId) {
181+
pushTrack.runSystemTool({
182+
teamId: runningUserInfo.teamId,
183+
tmbId: runningUserInfo.tmbId,
184+
uid: runningUserInfo.tmbId,
185+
toolId: systemToolId,
186+
result: 0,
187+
msg: getErrText(error)
188+
});
189+
}
190+
145191
return {
146192
[DispatchNodeResponseKeyEnum.nodeResponse]: {
147193
moduleLogo: avatar,

packages/service/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": "1.0.0",
44
"type": "module",
55
"dependencies": {
6-
"@fastgpt-sdk/plugin": "^0.1.0",
6+
"@fastgpt-sdk/plugin": "^0.1.1",
77
"@fastgpt/global": "workspace:*",
88
"@modelcontextprotocol/sdk": "^1.12.1",
99
"@node-rs/jieba": "2.0.1",

0 commit comments

Comments
 (0)