Skip to content

Commit b13d787

Browse files
zly2006c121914yu
authored andcommitted
fix: respect json structure while truncating tool call strings
1 parent 4af4f65 commit b13d787

File tree

2 files changed

+71
-12
lines changed

2 files changed

+71
-12
lines changed

packages/global/common/string/tools.ts

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,66 @@ export const sliceStrStartEnd = (str: string, start: number, end: number) => {
187187
return `${startContent}${overSize ? `\n\n...[hide ${str.length - start - end} chars]...\n\n` : ''}${endContent}`;
188188
};
189189

190-
/*
190+
/**
191+
* Slice string while respecting JSON structure
192+
*/
193+
export const truncateStrRespectingJson = (str: string, start: number, end: number) => {
194+
const overSize = str.length > start + end;
195+
196+
if (!overSize) return str;
197+
198+
let obj: any;
199+
try {
200+
obj = JSON.parse(str);
201+
} catch (e) {
202+
// Not a valid JSON, fallback to normal slicing
203+
return sliceStrStartEnd(str, start, end);
204+
}
205+
206+
let tooLongStrings = 0;
207+
208+
function forEachString(obj: any, operation: (s: string) => string): any {
209+
if (typeof obj === 'string') {
210+
return operation(obj);
211+
} else if (Array.isArray(obj)) {
212+
return obj.map((item) => forEachString(item, operation));
213+
} else if (typeof obj === 'object' && obj) {
214+
const newObj: any = {};
215+
for (const key in obj) {
216+
newObj[key] = forEachString(obj[key], operation);
217+
}
218+
return newObj;
219+
}
220+
return obj;
221+
}
222+
223+
forEachString(obj, (s) => {
224+
if (s.length > 200) {
225+
tooLongStrings++;
226+
return s;
227+
}
228+
return s;
229+
});
230+
231+
if (tooLongStrings === 0) {
232+
return str;
233+
}
234+
235+
forEachString(obj, (s) => {
236+
if (s.length > (start + end) / tooLongStrings) {
237+
return sliceStrStartEnd(
238+
s,
239+
Math.floor(start / tooLongStrings),
240+
Math.floor(end / tooLongStrings)
241+
);
242+
}
243+
return s;
244+
});
245+
246+
return JSON.stringify(obj);
247+
};
248+
249+
/*
191250
Parse file extension from url
192251
Test:
193252
1. https://xxx.com/file.pdf?token=123

packages/service/core/workflow/dispatch/ai/agent/toolCall.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
1616
import type { AIChatItemType } from '@fastgpt/global/core/chat/type';
1717
import { formatToolResponse, initToolCallEdges, initToolNodes } from './utils';
1818
import { computedMaxToken } from '../../../../ai/utils';
19-
import { sliceStrStartEnd } from '@fastgpt/global/common/string/tools';
19+
import { truncateStrRespectingJson } from '@fastgpt/global/common/string/tools';
2020
import type { WorkflowInteractiveResponseType } from '@fastgpt/global/core/workflow/template/system/interactive/type';
2121
import { ChatItemValueTypeEnum } from '@fastgpt/global/core/chat/constants';
2222
import { getErrText } from '@fastgpt/global/common/error/utils';
@@ -28,23 +28,23 @@ type ToolRunResponseType = {
2828
toolMsgParams: ChatCompletionToolMessageParam;
2929
}[];
3030

31-
/*
31+
/*
3232
调用思路:
3333
先Check 是否是交互节点触发
34-
34+
3535
交互模式:
3636
1. 从缓存中获取工作流运行数据
3737
2. 运行工作流
3838
3. 检测是否有停止信号或交互响应
3939
- 无:汇总结果,递归运行工具
4040
- 有:缓存结果,结束调用
41-
41+
4242
非交互模式:
4343
1. 组合 tools
4444
2. 过滤 messages
4545
3. Load request llm messages: system prompt, histories, human question, (assistant responses, tool responses, assistant responses....)
4646
4. 请求 LLM 获取结果
47-
47+
4848
- 有工具调用
4949
1. 批量运行工具的工作流,获取结果(工作流原生结果,工具执行结果)
5050
2. 合并递归中,所有工具的原生运行结果
@@ -126,7 +126,7 @@ export const runToolCall = async (
126126
toolName: '',
127127
toolAvatar: '',
128128
params: '',
129-
response: sliceStrStartEnd(stringToolResponse, 5000, 5000)
129+
response: truncateStrRespectingJson(stringToolResponse, 5000, 5000)
130130
}
131131
}
132132
});
@@ -407,7 +407,7 @@ export const runToolCall = async (
407407
toolName: '',
408408
toolAvatar: '',
409409
params: '',
410-
response: sliceStrStartEnd(stringToolResponse, 5000, 5000)
410+
response: truncateStrRespectingJson(stringToolResponse, 5000, 5000)
411411
}
412412
}
413413
});
@@ -426,7 +426,7 @@ export const runToolCall = async (
426426
toolName: '',
427427
toolAvatar: '',
428428
params: '',
429-
response: sliceStrStartEnd(err, 5000, 5000)
429+
response: truncateStrRespectingJson(err, 5000, 5000)
430430
}
431431
}
432432
});
@@ -437,7 +437,7 @@ export const runToolCall = async (
437437
tool_call_id: tool.id,
438438
role: ChatCompletionRequestMessageRoleEnum.Tool,
439439
name: tool.function.name,
440-
content: sliceStrStartEnd(err, 5000, 5000)
440+
content: truncateStrRespectingJson(err, 5000, 5000)
441441
}
442442
});
443443
}
@@ -460,7 +460,7 @@ export const runToolCall = async (
460460
: usage.outputTokens;
461461

462462
if (toolCalls.length > 0) {
463-
/*
463+
/*
464464
...
465465
user
466466
assistant: tool data
@@ -471,7 +471,7 @@ export const runToolCall = async (
471471
...toolsRunResponse.map((item) => item?.toolMsgParams)
472472
];
473473

474-
/*
474+
/*
475475
Get tool node assistant response
476476
- history assistant
477477
- current tool assistant

0 commit comments

Comments
 (0)