@@ -52,7 +52,7 @@ public function convert(HttpResponse $response, array $options = []): LlmRespons
52
52
}
53
53
54
54
/** @var Choice[] $choices */
55
- $ choices = array_map ([$ this , 'convertChoice ' ], $ data ['choices ' ]);
55
+ $ choices = \ array_map ([$ this , 'convertChoice ' ], $ data ['choices ' ]);
56
56
57
57
if (1 !== count ($ choices )) {
58
58
return new ChoiceResponse (...$ choices );
@@ -65,14 +65,10 @@ public function convert(HttpResponse $response, array $options = []): LlmRespons
65
65
return new TextResponse ($ choices [0 ]->getContent ());
66
66
}
67
67
68
- private function convertStream (HttpResponse $ response ): ToolCallResponse | StreamResponse
68
+ private function convertStream (HttpResponse $ response ): StreamResponse
69
69
{
70
70
$ stream = $ this ->streamResponse ($ response );
71
71
72
- if ($ this ->streamIsToolCall ($ stream )) {
73
- return new ToolCallResponse (...$ this ->convertStreamToToolCalls ($ stream ));
74
- }
75
-
76
72
return new StreamResponse ($ this ->convertStreamContent ($ stream ));
77
73
}
78
74
@@ -84,7 +80,9 @@ private function streamResponse(HttpResponse $response): \Generator
84
80
}
85
81
86
82
try {
87
- yield $ chunk ->getArrayData ();
83
+ $ data = $ chunk ->getArrayData ();
84
+
85
+ yield $ data ;
88
86
} catch (JsonException ) {
89
87
// try catch only needed for Symfony 6.4
90
88
continue ;
@@ -100,37 +98,46 @@ private function streamIsToolCall(\Generator $response): bool
100
98
}
101
99
102
100
/**
103
- * @return ToolCall[]
101
+ * @param array<string, mixed> $toolCalls
102
+ * @param array<string, mixed> $data
103
+ *
104
+ * @return array<string, mixed>
104
105
*/
105
- private function convertStreamToToolCalls (\ Generator $ response ): array
106
+ private function convertStreamToToolCalls (array $ toolCalls , array $ data ): array
106
107
{
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
+ ];
110
119
continue ;
111
120
}
112
121
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 ' ];
126
124
}
127
125
128
- return array_map ([ $ this , ' convertToolCall ' ], $ toolCalls) ;
126
+ return $ toolCalls ;
129
127
}
130
128
131
129
private function convertStreamContent (\Generator $ generator ): \Generator
132
130
{
131
+ $ toolCalls = [];
133
132
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
+
134
141
if (!isset ($ data ['choices ' ][0 ]['delta ' ]['content ' ])) {
135
142
continue ;
136
143
}
@@ -139,6 +146,14 @@ private function convertStreamContent(\Generator $generator): \Generator
139
146
}
140
147
}
141
148
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
+
142
157
/**
143
158
* @param array{
144
159
* index: integer,
@@ -162,7 +177,7 @@ private function convertStreamContent(\Generator $generator): \Generator
162
177
private function convertChoice (array $ choice ): Choice
163
178
{
164
179
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 ' ]));
166
181
}
167
182
168
183
if (in_array ($ choice ['finish_reason ' ], ['stop ' , 'length ' ], true )) {
0 commit comments