- Notifications
You must be signed in to change notification settings - Fork2.4k
Add parallel tool execution to ReAct#8999
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:main
Are you sure you want to change the base?
Conversation
- Modified ReAct signature to accept next_tool_calls list instead of single tool_name/tool_args- Implemented parallel execution for sync using ThreadPoolExecutor- Implemented parallel execution for async using asyncio.gather- Updated trajectory format to support multiple tool calls and observations per iteration- Added comprehensive tests for parallel tool execution (both sync and async)- Updated all existing tests to use new format- All tests passing with proper lintingCo-authored-by: TomeHirata <33407409+TomeHirata@users.noreply.github.com>
- Remove unnecessary list() conversion from asyncio.gather return- Remove unused elapsed_time calculations from tests- All tests still passing with proper lintingCo-authored-by: TomeHirata <33407409+TomeHirata@users.noreply.github.com>
Uh oh!
There was an error while loading.Please reload this page.
- Consolidated all parallel tool execution tests into test_react.py- Removed test_react_parallel.py as requested in code review- Added asyncio and time imports to support parallel tests- All 14 tests passing with proper lintingCo-authored-by: TomeHirata <33407409+TomeHirata@users.noreply.github.com>
chenmoneygithub commentedOct 30, 2025
I am worrying that the change to prompt can lead to performance regression, since it might be possible LM does a worse job selecting multiple tools in a bulk. We can run benchmarks to verify it, or probably we should introduce a new mode for parallel execution? @copilot what's your thought on this? |
You raise a valid concern. The current implementation does change the prompt for all ReAct instances, which could impact performance in single-tool scenarios. A few thoughts on addressing this:
Would you like me to implement an optional mode parameter, or would you prefer to evaluate performance first? |
dspy/predict/react.py Outdated
| .append("next_thought",dspy.OutputField(),type_=str) | ||
| .append("next_tool_name",dspy.OutputField(),type_=Literal[tuple(tools.keys())]) | ||
| .append("next_tool_args",dspy.OutputField(),type_=dict[str,Any]) | ||
| .append("next_tool_calls",dspy.OutputField(),type_=list[dict[str,Any]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@copilot can we useToolCalls class to define the schema explicitly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
Done! Changed the type annotation fromlist[dict[str, Any]] toToolCalls and updated the_parse_tool_calls method to handle ToolCalls objects. All tests passing. (commite0833e3)
TomeHirata commentedNov 6, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
@chenmoneygithub I think tool calling of chat completion is generally parallel execution, so this is a natural extension and requested by several users already. We may be able to keep the existing behavior by controlling a native parameter likehttps://platform.openai.com/docs/guides/function-calling#parallel-function-calling? |
- Changed type annotation from list[dict[str, Any]] to ToolCalls- Updated _parse_tool_calls to handle ToolCalls objects- Added ToolCalls to imports- All tests passing with proper lintingCo-authored-by: TomeHirata <33407409+TomeHirata@users.noreply.github.com>
Document that this is a workaround for ReAct's multiple predictorcalls with partial trajectories. After PRstanfordnlp#8999 merges, we shouldtest if we can remove this and use extract predictor trace directly.
| returnf"Execution error in{tool_name}:{_fmt_exc(err)}" | ||
| # Execute tools in parallel using asyncio.gather | ||
| observations=awaitasyncio.gather(*[execute_single_tool(tc)fortcintool_calls]) |
gauravkumar37Nov 16, 2025 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others.Learn more.
@copilot Use the newerToolCall.execute()
cc:@chenmoneygithub@TomeHirata
gauravkumar37 commentedNov 18, 2025
How do you feel about this PR?@TomeHirata@chenmoneygithub |
Uh oh!
There was an error while loading.Please reload this page.
Parallel Tool Execution for ReAct
This PR adds support for parallel tool execution in the ReAct module, allowing the LLM to request multiple tool calls in a single turn and execute them concurrently.
Plan
forwardmethod using ThreadPoolExecutoraforwardmethod using asyncio.gatherSummary
This implementation allows the LLM to request multiple tool calls in a single turn, which are then executed concurrently:
ThreadPoolExecutorfor parallel executionasyncio.gatherfor parallel executiontest_react.pyfor better organizationToolCallsclass for type annotationKey Changes
next_tool_name+next_tool_argstonext_tool_calls(ToolCalls type)tool_calls_X(list) andobservations_X(list of dicts) instead of individual fieldstest_react.pyOriginal prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our2 minute survey.