Skip to content

Commit 8e64653

Browse files
committed
fix(streaming): align finish_reason logic with non-streaming path
The streaming path (ChatCompletionsStreamingAdapter) now correctly maps TOOL_SUSPENDED and MAX_ITERATIONS to finish_reason, matching the behavior of the non-streaming path (ChatCompletionsResponseBuilder). Previously, the streaming path only checked for ToolUseBlock presence, which could lead to inconsistent behavior: - TOOL_SUSPENDED was typically unaffected (ToolUseBlock always present) - MAX_ITERATIONS would incorrectly return 'stop' instead of 'length' Changes: - Check event.getMessage().getGenerateReason() in isLast branch - Map TOOL_SUSPENDED -> 'tool_calls' - Map MAX_ITERATIONS -> 'length' - Fall back to ToolUseBlock check for other cases This ensures consistent finish_reason behavior between streaming and non-streaming responses. Resolves review comment from LearningGp.
1 parent cfbe7d0 commit 8e64653

1 file changed

Lines changed: 18 additions & 3 deletions

File tree

agentscope-extensions/agentscope-extensions-chat-completions-web/src/main/java/io/agentscope/core/chat/completions/streaming/ChatCompletionsStreamingAdapter.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import io.agentscope.core.chat.completions.model.ChatCompletionsChunk;
2525
import io.agentscope.core.chat.completions.model.ToolCall;
2626
import io.agentscope.core.message.ContentBlock;
27+
import io.agentscope.core.message.GenerateReason;
2728
import io.agentscope.core.message.Msg;
2829
import io.agentscope.core.message.TextBlock;
2930
import io.agentscope.core.message.ToolResultBlock;
@@ -250,9 +251,23 @@ private Flux<ChatCompletionsChunk> convertEventToChunksInternal(
250251

251252
// Add finish chunk if this is the last event
252253
if (event.isLast()) {
253-
boolean hasToolCalls =
254-
contentBlocks.stream().anyMatch(block -> block instanceof ToolUseBlock);
255-
String finishReason = hasToolCalls ? "tool_calls" : "stop";
254+
// Determine finish reason based on GenerateReason or tool calls
255+
// This mirrors the logic in ChatCompletionsResponseBuilder
256+
String finishReason;
257+
GenerateReason generateReason =
258+
event.getMessage() != null ? event.getMessage().getGenerateReason() : null;
259+
260+
if (generateReason == GenerateReason.TOOL_SUSPENDED) {
261+
finishReason = "tool_calls";
262+
} else if (generateReason == GenerateReason.MAX_ITERATIONS) {
263+
finishReason = "length";
264+
} else {
265+
// Fall back to checking for tool calls in content
266+
boolean hasToolCalls =
267+
contentBlocks.stream().anyMatch(block -> block instanceof ToolUseBlock);
268+
finishReason = hasToolCalls ? "tool_calls" : "stop";
269+
}
270+
256271
chunks.add(ChatCompletionsChunk.finishChunk(requestId, model, finishReason));
257272
}
258273

0 commit comments

Comments
 (0)