Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
b75e807f
authored
Dec 31, 2024
by
Archer
Committed by
GitHub
Dec 31, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: tool choice run same tool will error (#3502)
parent
b2fdefdc
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
90 additions
and
60 deletions
+90
-60
packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts
+86
-57
packages/service/core/workflow/dispatch/index.ts
+4
-3
No files found.
packages/service/core/workflow/dispatch/agent/runTool/toolChoice.ts
View file @
b75e807f
...
@@ -27,9 +27,10 @@ import { getNanoid, sliceStrStartEnd } from '@fastgpt/global/common/string/tools
...
@@ -27,9 +27,10 @@ import { getNanoid, sliceStrStartEnd } from '@fastgpt/global/common/string/tools
import
{
toolValueTypeList
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
toolValueTypeList
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
WorkflowInteractiveResponseType
}
from
'@fastgpt/global/core/workflow/template/system/interactive/type'
;
import
{
WorkflowInteractiveResponseType
}
from
'@fastgpt/global/core/workflow/template/system/interactive/type'
;
import
{
ChatItemValueTypeEnum
}
from
'@fastgpt/global/core/chat/constants'
;
import
{
ChatItemValueTypeEnum
}
from
'@fastgpt/global/core/chat/constants'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
type
ToolRunResponseType
=
{
type
ToolRunResponseType
=
{
toolRunResponse
:
DispatchFlowResponse
;
toolRunResponse
?
:
DispatchFlowResponse
;
toolMsgParams
:
ChatCompletionToolMessageParam
;
toolMsgParams
:
ChatCompletionToolMessageParam
;
}[];
}[];
...
@@ -344,59 +345,87 @@ export const runToolWithToolChoice = async (
...
@@ -344,59 +345,87 @@ export const runToolWithToolChoice = async (
return
Promise
.
reject
(
getEmptyResponseTip
());
return
Promise
.
reject
(
getEmptyResponseTip
());
}
}
// Run the selected tool by LLM.
/* Run the selected tool by LLM.
const
toolsRunResponse
=
(
Since only reference parameters are passed, if the same tool is run in parallel, it will get the same run parameters
await
Promise
.
all
(
*/
toolCalls
.
map
(
async
(
tool
)
=>
{
const
toolsRunResponse
:
ToolRunResponseType
=
[];
const
toolNode
=
toolNodes
.
find
((
item
)
=>
item
.
nodeId
===
tool
.
function
?.
name
);
for
await
(
const
tool
of
toolCalls
)
{
try
{
const
toolNode
=
toolNodes
.
find
((
item
)
=>
item
.
nodeId
===
tool
.
function
?.
name
);
if
(
!
toolNode
)
continue
;
const
startParams
=
(()
=>
{
try
{
return
json5
.
parse
(
tool
.
function
.
arguments
);
}
catch
(
error
)
{
return
{};
}
})();
if
(
!
toolNode
)
return
;
initToolNodes
(
runtimeNodes
,
[
toolNode
.
nodeId
],
startParams
);
const
toolRunResponse
=
await
dispatchWorkFlow
({
...
workflowProps
,
isToolCall
:
true
});
const
startParams
=
(()
=>
{
const
stringToolResponse
=
formatToolResponse
(
toolRunResponse
.
toolResponses
);
try
{
return
json5
.
parse
(
tool
.
function
.
arguments
);
}
catch
(
error
)
{
return
{};
}
})();
initToolNodes
(
runtimeNodes
,
[
toolNode
.
nodeId
],
startParams
);
const
toolMsgParams
:
ChatCompletionToolMessageParam
=
{
const
toolRunResponse
=
await
dispatchWorkFlow
({
tool_call_id
:
tool
.
id
,
...
workflowProps
,
role
:
ChatCompletionRequestMessageRoleEnum
.
Tool
,
isToolCall
:
true
name
:
tool
.
function
.
name
,
});
content
:
stringToolResponse
};
const
stringToolResponse
=
formatToolResponse
(
toolRunResponse
.
toolResponses
);
workflowStreamResponse
?.({
event
:
SseResponseEventEnum
.
toolResponse
,
data
:
{
tool
:
{
id
:
tool
.
id
,
toolName
:
''
,
toolAvatar
:
''
,
params
:
''
,
response
:
sliceStrStartEnd
(
stringToolResponse
,
5000
,
5000
)
}
}
});
const
toolMsgParams
:
ChatCompletionToolMessageParam
=
{
toolsRunResponse
.
push
({
toolRunResponse
,
toolMsgParams
});
}
catch
(
error
)
{
const
err
=
getErrText
(
error
);
workflowStreamResponse
?.({
event
:
SseResponseEventEnum
.
toolResponse
,
data
:
{
tool
:
{
id
:
tool
.
id
,
toolName
:
''
,
toolAvatar
:
''
,
params
:
''
,
response
:
sliceStrStartEnd
(
err
,
5000
,
5000
)
}
}
});
toolsRunResponse
.
push
({
toolRunResponse
:
undefined
,
toolMsgParams
:
{
tool_call_id
:
tool
.
id
,
tool_call_id
:
tool
.
id
,
role
:
ChatCompletionRequestMessageRoleEnum
.
Tool
,
role
:
ChatCompletionRequestMessageRoleEnum
.
Tool
,
name
:
tool
.
function
.
name
,
name
:
tool
.
function
.
name
,
content
:
stringToolResponse
content
:
sliceStrStartEnd
(
err
,
5000
,
5000
)
};
}
});
workflowStreamResponse
?.({
}
event
:
SseResponseEventEnum
.
toolResponse
,
}
data
:
{
tool
:
{
id
:
tool
.
id
,
toolName
:
''
,
toolAvatar
:
''
,
params
:
''
,
response
:
sliceStrStartEnd
(
stringToolResponse
,
5000
,
5000
)
}
}
});
return
{
toolRunResponse
,
toolMsgParams
};
})
)
).
filter
(
Boolean
)
as
ToolRunResponseType
;
const
flatToolsResponseData
=
toolsRunResponse
.
map
((
item
)
=>
item
.
toolRunResponse
).
flat
();
const
flatToolsResponseData
=
toolsRunResponse
.
map
((
item
)
=>
item
.
toolRunResponse
)
.
flat
()
.
filter
(
Boolean
)
as
DispatchFlowResponse
[];
// concat tool responses
// concat tool responses
const
dispatchFlowResponse
=
response
const
dispatchFlowResponse
=
response
?
response
.
dispatchFlowResponse
.
concat
(
flatToolsResponseData
)
?
response
.
dispatchFlowResponse
.
concat
(
flatToolsResponseData
)
...
@@ -434,22 +463,22 @@ export const runToolWithToolChoice = async (
...
@@ -434,22 +463,22 @@ export const runToolWithToolChoice = async (
const
outputTokens
=
await
countGptMessagesTokens
(
assistantToolMsgParams
);
const
outputTokens
=
await
countGptMessagesTokens
(
assistantToolMsgParams
);
/*
/*
...
...
user
user
assistant: tool data
assistant: tool data
tool: tool response
tool: tool response
*/
*/
const
completeMessages
=
[
const
completeMessages
=
[
...
concatToolMessages
,
...
concatToolMessages
,
...
toolsRunResponse
.
map
((
item
)
=>
item
?.
toolMsgParams
)
...
toolsRunResponse
.
map
((
item
)
=>
item
?.
toolMsgParams
)
];
];
/*
/*
Get tool node assistant response
Get tool node assistant response
history assistant
history assistant
current tool assistant
current tool assistant
tool child assistant
tool child assistant
*/
*/
const
toolNodeAssistant
=
GPTMessages2Chats
([
const
toolNodeAssistant
=
GPTMessages2Chats
([
...
assistantToolMsgParams
,
...
assistantToolMsgParams
,
...
toolsRunResponse
.
map
((
item
)
=>
item
?.
toolMsgParams
)
...
toolsRunResponse
.
map
((
item
)
=>
item
?.
toolMsgParams
)
...
@@ -478,12 +507,12 @@ export const runToolWithToolChoice = async (
...
@@ -478,12 +507,12 @@ export const runToolWithToolChoice = async (
);
);
// Check interactive response(Only 1 interaction is reserved)
// Check interactive response(Only 1 interaction is reserved)
const
workflowInteractiveResponseItem
=
toolsRunResponse
.
find
(
const
workflowInteractiveResponseItem
=
toolsRunResponse
.
find
(
(
item
)
=>
item
.
toolRunResponse
.
workflowInteractiveResponse
(
item
)
=>
item
.
toolRunResponse
?
.
workflowInteractiveResponse
);
);
if
(
hasStopSignal
||
workflowInteractiveResponseItem
)
{
if
(
hasStopSignal
||
workflowInteractiveResponseItem
)
{
// Get interactive tool data
// Get interactive tool data
const
workflowInteractiveResponse
=
const
workflowInteractiveResponse
=
workflowInteractiveResponseItem
?.
toolRunResponse
.
workflowInteractiveResponse
;
workflowInteractiveResponseItem
?.
toolRunResponse
?
.
workflowInteractiveResponse
;
// Flashback traverses completeMessages, intercepting messages that know the first user
// Flashback traverses completeMessages, intercepting messages that know the first user
const
firstUserIndex
=
completeMessages
.
findLastIndex
((
item
)
=>
item
.
role
===
'user'
);
const
firstUserIndex
=
completeMessages
.
findLastIndex
((
item
)
=>
item
.
role
===
'user'
);
...
...
packages/service/core/workflow/dispatch/index.ts
View file @
b75e807f
...
@@ -72,6 +72,7 @@ import { dispatchLoopEnd } from './loop/runLoopEnd';
...
@@ -72,6 +72,7 @@ import { dispatchLoopEnd } from './loop/runLoopEnd';
import
{
dispatchLoopStart
}
from
'./loop/runLoopStart'
;
import
{
dispatchLoopStart
}
from
'./loop/runLoopStart'
;
import
{
dispatchFormInput
}
from
'./interactive/formInput'
;
import
{
dispatchFormInput
}
from
'./interactive/formInput'
;
import
{
dispatchToolParams
}
from
'./agent/runTool/toolParams'
;
import
{
dispatchToolParams
}
from
'./agent/runTool/toolParams'
;
import
{
getErrText
}
from
'@fastgpt/global/common/error/utils'
;
const
callbackMap
:
Record
<
FlowNodeTypeEnum
,
Function
>
=
{
const
callbackMap
:
Record
<
FlowNodeTypeEnum
,
Function
>
=
{
[
FlowNodeTypeEnum
.
workflowStart
]:
dispatchWorkflowStart
,
[
FlowNodeTypeEnum
.
workflowStart
]:
dispatchWorkflowStart
,
...
@@ -231,9 +232,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
...
@@ -231,9 +232,7 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
if
(
toolResponses
!==
undefined
)
{
if
(
toolResponses
!==
undefined
)
{
if
(
Array
.
isArray
(
toolResponses
)
&&
toolResponses
.
length
===
0
)
return
;
if
(
Array
.
isArray
(
toolResponses
)
&&
toolResponses
.
length
===
0
)
return
;
if
(
typeof
toolResponses
===
'object'
&&
Object
.
keys
(
toolResponses
).
length
===
0
)
{
if
(
typeof
toolResponses
===
'object'
&&
Object
.
keys
(
toolResponses
).
length
===
0
)
return
;
return
;
}
toolRunResponse
=
toolResponses
;
toolRunResponse
=
toolResponses
;
}
}
...
@@ -565,6 +564,8 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
...
@@ -565,6 +564,8 @@ export async function dispatchWorkFlow(data: Props): Promise<DispatchFlowRespons
const
targetEdges
=
runtimeEdges
.
filter
((
item
)
=>
item
.
source
===
node
.
nodeId
);
const
targetEdges
=
runtimeEdges
.
filter
((
item
)
=>
item
.
source
===
node
.
nodeId
);
const
skipHandleIds
=
targetEdges
.
map
((
item
)
=>
item
.
sourceHandle
);
const
skipHandleIds
=
targetEdges
.
map
((
item
)
=>
item
.
sourceHandle
);
toolRunResponse
=
getErrText
(
error
);
// Skip all edges and return error
// Skip all edges and return error
return
{
return
{
[
DispatchNodeResponseKeyEnum
.
nodeResponse
]:
{
[
DispatchNodeResponseKeyEnum
.
nodeResponse
]:
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment