@@ -556,6 +556,7 @@ async def _stream_generator(
556556
557557 full_text = ""
558558 full_reasoning = ""
559+ accumulated_tool_calls : Dict [int , Dict [str , Any ]] = {}
559560
560561 async for chunk in stream :
561562 if chunk .usage :
@@ -583,27 +584,71 @@ async def _stream_generator(
583584 if delta_reasoning :
584585 full_reasoning += delta_reasoning
585586
586- tool_calls = None
587+ current_tool_calls_payload = None
588+
587589 if delta and delta .tool_calls :
588- tool_calls = [tc .model_dump () for tc in delta .tool_calls ]
590+ # 只有 is_incremental=True 才直接发送 delta,否则我们发送完整列表
591+ if is_incremental :
592+ current_tool_calls_payload = [
593+ tc .model_dump () for tc in delta .tool_calls
594+ ]
595+
596+ # 始终进行聚合,以备 incremental_output=False 使用
597+ for tc in delta .tool_calls :
598+ idx = tc .index
599+ if idx not in accumulated_tool_calls :
600+ accumulated_tool_calls [idx ] = {
601+ "index" : idx ,
602+ "id" : tc .id ,
603+ "type" : tc .type ,
604+ "function" : {
605+ "name" : tc .function .name or "" ,
606+ "arguments" : "" ,
607+ },
608+ }
609+ else :
610+ # 合并字段
611+ if tc .id :
612+ accumulated_tool_calls [idx ]["id" ] = tc .id
613+ if tc .function .name :
614+ accumulated_tool_calls [idx ]["function" ][
615+ "name"
616+ ] = tc .function .name
617+
618+ # 拼接参数
619+ if tc .function .arguments :
620+ accumulated_tool_calls [idx ]["function" ][
621+ "arguments"
622+ ] += tc .function .arguments
589623
590624 if chunk .choices and chunk .choices [0 ].finish_reason :
591625 finish_reason = chunk .choices [0 ].finish_reason
592626
593627 if is_incremental :
594628 content_to_send = delta_content
595629 reasoning_to_send = delta_reasoning
630+ # 如果是增量模式,使用上面提取的 delta payload
631+ final_tool_calls = current_tool_calls_payload
596632 else :
597633 content_to_send = full_text
598634 reasoning_to_send = full_reasoning
635+ # 如果是非增量模式,发送当前聚合的所有工具调用的列表
636+ if accumulated_tool_calls :
637+ # 将字典转回列表并按 index 排序
638+ final_tool_calls = sorted (
639+ accumulated_tool_calls .values (), key = lambda x : x ["index" ]
640+ )
641+ else :
642+ final_tool_calls = None
599643
600644 message_body = {
601645 "role" : "assistant" ,
602646 "content" : content_to_send ,
603647 "reasoning_content" : reasoning_to_send ,
604648 }
605- if tool_calls :
606- message_body ["tool_calls" ] = tool_calls
649+
650+ if final_tool_calls :
651+ message_body ["tool_calls" ] = final_tool_calls
607652
608653 response_body = {
609654 "output" : {
0 commit comments