@@ -52,7 +52,7 @@ public function convert(HttpResponse $response, array $options = []): LlmRespons
5252 }
5353
5454 /** @var Choice[] $choices */
55- $ choices = array_map ([$ this , 'convertChoice ' ], $ data ['choices ' ]);
55+ $ choices = \ array_map ([$ this , 'convertChoice ' ], $ data ['choices ' ]);
5656
5757 if (1 !== count ($ choices )) {
5858 return new ChoiceResponse (...$ choices );
@@ -65,14 +65,10 @@ public function convert(HttpResponse $response, array $options = []): LlmRespons
6565 return new TextResponse ($ choices [0 ]->getContent ());
6666 }
6767
68- private function convertStream (HttpResponse $ response ): ToolCallResponse | StreamResponse
68+ private function convertStream (HttpResponse $ response ): StreamResponse
6969 {
7070 $ stream = $ this ->streamResponse ($ response );
7171
72- if ($ this ->streamIsToolCall ($ stream )) {
73- return new ToolCallResponse (...$ this ->convertStreamToToolCalls ($ stream ));
74- }
75-
7672 return new StreamResponse ($ this ->convertStreamContent ($ stream ));
7773 }
7874
@@ -84,7 +80,9 @@ private function streamResponse(HttpResponse $response): \Generator
8480 }
8581
8682 try {
87- yield $ chunk ->getArrayData ();
83+ $ data = $ chunk ->getArrayData ();
84+
85+ yield $ data ;
8886 } catch (JsonException ) {
8987 // try catch only needed for Symfony 6.4
9088 continue ;
@@ -100,37 +98,46 @@ private function streamIsToolCall(\Generator $response): bool
10098 }
10199
102100 /**
103- * @return ToolCall[]
101+ * @param array<string, mixed> $toolCalls
102+ * @param array<string, mixed> $data
103+ *
104+ * @return array<string, mixed>
104105 */
105- private function convertStreamToToolCalls (\ Generator $ response ): array
106+ private function convertStreamToToolCalls (array $ toolCalls , array $ data ): array
106107 {
107- $ toolCalls = [];
108- foreach ($ response as $ data ) {
109- if (!isset ($ data ['choices ' ][0 ]['delta ' ]['tool_calls ' ])) {
108+ if (!isset ($ data ['choices ' ][0 ]['delta ' ]['tool_calls ' ])) {
109+ return $ toolCalls ;
110+ }
111+
112+ foreach ($ data ['choices ' ][0 ]['delta ' ]['tool_calls ' ] as $ i => $ toolCall ) {
113+ if (isset ($ toolCall ['id ' ])) {
114+ // initialize tool call
115+ $ toolCalls [$ i ] = [
116+ 'id ' => $ toolCall ['id ' ],
117+ 'function ' => $ toolCall ['function ' ],
118+ ];
110119 continue ;
111120 }
112121
113- foreach ($ data ['choices ' ][0 ]['delta ' ]['tool_calls ' ] as $ i => $ toolCall ) {
114- if (isset ($ toolCall ['id ' ])) {
115- // initialize tool call
116- $ toolCalls [$ i ] = [
117- 'id ' => $ toolCall ['id ' ],
118- 'function ' => $ toolCall ['function ' ],
119- ];
120- continue ;
121- }
122-
123- // add arguments delta to tool call
124- $ toolCalls [$ i ]['function ' ]['arguments ' ] .= $ toolCall ['function ' ]['arguments ' ];
125- }
122+ // add arguments delta to tool call
123+ $ toolCalls [$ i ]['function ' ]['arguments ' ] .= $ toolCall ['function ' ]['arguments ' ];
126124 }
127125
128- return array_map ([ $ this , ' convertToolCall ' ], $ toolCalls) ;
126+ return $ toolCalls ;
129127 }
130128
131129 private function convertStreamContent (\Generator $ generator ): \Generator
132130 {
131+ $ toolCalls = [];
133132 foreach ($ generator as $ data ) {
133+ if ($ this ->streamIsToolCall ($ generator )) {
134+ $ toolCalls = $ this ->convertStreamToToolCalls ($ toolCalls , $ data );
135+ }
136+
137+ if ([] !== $ toolCalls && $ this ->isToolCallsStreamFinished ($ data )) {
138+ yield new ToolCallResponse (...\array_map ([$ this , 'convertToolCall ' ], $ toolCalls ));
139+ }
140+
134141 if (!isset ($ data ['choices ' ][0 ]['delta ' ]['content ' ])) {
135142 continue ;
136143 }
@@ -139,6 +146,14 @@ private function convertStreamContent(\Generator $generator): \Generator
139146 }
140147 }
141148
149+ /**
150+ * @param array<string, mixed> $data
151+ */
152+ private function isToolCallsStreamFinished (array $ data ): bool
153+ {
154+ return isset ($ data ['choices ' ][0 ]['finish_reason ' ]) && 'tool_calls ' === $ data ['choices ' ][0 ]['finish_reason ' ];
155+ }
156+
142157 /**
143158 * @param array{
144159 * index: integer,
@@ -162,7 +177,7 @@ private function convertStreamContent(\Generator $generator): \Generator
162177 private function convertChoice (array $ choice ): Choice
163178 {
164179 if ('tool_calls ' === $ choice ['finish_reason ' ]) {
165- return new Choice (toolCalls: array_map ([$ this , 'convertToolCall ' ], $ choice ['message ' ]['tool_calls ' ]));
180+ return new Choice (toolCalls: \ array_map ([$ this , 'convertToolCall ' ], $ choice ['message ' ]['tool_calls ' ]));
166181 }
167182
168183 if (in_array ($ choice ['finish_reason ' ], ['stop ' , 'length ' ], true )) {
0 commit comments