Skip to content

Commit 48d0f8d

Browse files
fix: handle non-streaming responses after tool execution for sequential tool calling
- Fixed issue where tool outputs were returned directly to user when stream=False - Added proper handling for non-streaming responses after tool calls - Maintains backward compatibility with existing streaming behavior Fixes #824 Co-authored-by: Mervin Praison <[email protected]>
1 parent 246744c commit 48d0f8d

File tree

2 files changed

+75
-12
lines changed

2 files changed

+75
-12
lines changed

src/praisonai-agents/praisonaiagents/llm/llm.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -945,9 +945,26 @@ def get_response(
945945

946946
# Otherwise do the existing streaming approach if not already handled
947947
elif not ollama_handled:
948-
# Get response after tool calls with streaming
949-
if verbose:
950-
with Live(display_generating("", current_time), console=console, refresh_per_second=4) as live:
948+
# Get response after tool calls
949+
if stream:
950+
# Streaming approach
951+
if verbose:
952+
with Live(display_generating("", current_time), console=console, refresh_per_second=4) as live:
953+
final_response_text = ""
954+
for chunk in litellm.completion(
955+
**self._build_completion_params(
956+
messages=messages,
957+
tools=formatted_tools,
958+
temperature=temperature,
959+
stream=True,
960+
**kwargs
961+
)
962+
):
963+
if chunk and chunk.choices and chunk.choices[0].delta.content:
964+
content = chunk.choices[0].delta.content
965+
final_response_text += content
966+
live.update(display_generating(final_response_text, current_time))
967+
else:
951968
final_response_text = ""
952969
for chunk in litellm.completion(
953970
**self._build_completion_params(
@@ -959,22 +976,19 @@ def get_response(
959976
)
960977
):
961978
if chunk and chunk.choices and chunk.choices[0].delta.content:
962-
content = chunk.choices[0].delta.content
963-
final_response_text += content
964-
live.update(display_generating(final_response_text, current_time))
979+
final_response_text += chunk.choices[0].delta.content
965980
else:
966-
final_response_text = ""
967-
for chunk in litellm.completion(
981+
# Non-streaming approach
982+
resp = litellm.completion(
968983
**self._build_completion_params(
969984
messages=messages,
970985
tools=formatted_tools,
971986
temperature=temperature,
972-
stream=stream,
987+
stream=False,
973988
**kwargs
974989
)
975-
):
976-
if chunk and chunk.choices and chunk.choices[0].delta.content:
977-
final_response_text += chunk.choices[0].delta.content
990+
)
991+
final_response_text = resp["choices"][0]["message"]["content"]
978992

979993
final_response_text = final_response_text.strip()
980994

test_sequential_tool_calling.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
"""Test sequential tool calling fix"""
2+
from praisonaiagents import Agent
3+
4+
def get_stock_price(company_name: str) -> str:
5+
"""
6+
Get the stock price of a company
7+
8+
Args:
9+
company_name (str): The name of the company
10+
11+
Returns:
12+
str: The stock price of the company
13+
"""
14+
print(f"Tool called: get_stock_price({company_name})")
15+
return f"The stock price of {company_name} is 100"
16+
17+
def multiply(a: int, b: int) -> int:
18+
"""
19+
Multiply two numbers
20+
"""
21+
print(f"Tool called: multiply({a}, {b})")
22+
return a * b
23+
24+
# Test with streaming disabled to verify the fix
25+
print("Testing sequential tool calling with stream=False...")
26+
agent = Agent(
27+
instructions="You are a helpful assistant. You can use the tools provided to you to help the user.",
28+
llm="gemini/gemini-2.5-flash-lite-preview-06-17",
29+
self_reflect=False,
30+
verbose=True,
31+
tools=[get_stock_price, multiply],
32+
llm_config={"stream": False} # Force non-streaming mode
33+
)
34+
35+
result = agent.chat("Get the stock price of Google and multiply it by 2")
36+
print(f"\nFinal result: {result}")
37+
38+
# Test with default streaming mode
39+
print("\n\nTesting sequential tool calling with default streaming...")
40+
agent2 = Agent(
41+
instructions="You are a helpful assistant. You can use the tools provided to you to help the user.",
42+
llm="gemini/gemini-2.5-flash-lite-preview-06-17",
43+
self_reflect=False,
44+
verbose=True,
45+
tools=[get_stock_price, multiply]
46+
)
47+
48+
result2 = agent2.chat("Get the stock price of Google and multiply it by 2")
49+
print(f"\nFinal result: {result2}")

0 commit comments

Comments
 (0)