@@ -197,24 +197,25 @@ pub async fn gemini_chat_completions_streaming(
197
197
let handle = |value : & str | -> Result < ( ) > {
198
198
let data: Value = serde_json:: from_str ( value) ?;
199
199
debug ! ( "stream-data: {data}" ) ;
200
- if let Some ( text) = data[ "candidates" ] [ 0 ] [ "content" ] [ "parts" ] [ 0 ] [ "text" ] . as_str ( ) {
201
- if !text. is_empty ( ) {
202
- handler. text ( text) ?;
203
- }
204
- } else if let Some ( "SAFETY" ) = data[ "promptFeedback" ] [ "blockReason" ]
205
- . as_str ( )
206
- . or_else ( || data[ "candidates" ] [ 0 ] [ "finishReason" ] . as_str ( ) )
207
- {
208
- bail ! ( "Content Blocked" )
209
- } else if let Some ( parts) = data[ "candidates" ] [ 0 ] [ "content" ] [ "parts" ] . as_array ( ) {
210
- for part in parts {
211
- if let ( Some ( name) , Some ( args) ) = (
200
+ if let Some ( parts) = data[ "candidates" ] [ 0 ] [ "content" ] [ "parts" ] . as_array ( ) {
201
+ for ( i, part) in parts. iter ( ) . enumerate ( ) {
202
+ if let Some ( text) = part[ "text" ] . as_str ( ) {
203
+ if i > 0 {
204
+ handler. text ( "\n \n " ) ?;
205
+ }
206
+ handler. text ( text) ?;
207
+ } else if let ( Some ( name) , Some ( args) ) = (
212
208
part[ "functionCall" ] [ "name" ] . as_str ( ) ,
213
209
part[ "functionCall" ] [ "args" ] . as_object ( ) ,
214
210
) {
215
211
handler. tool_call ( ToolCall :: new ( name. to_string ( ) , json ! ( args) , None ) ) ?;
216
212
}
217
213
}
214
+ } else if let Some ( "SAFETY" ) = data[ "promptFeedback" ] [ "blockReason" ]
215
+ . as_str ( )
216
+ . or_else ( || data[ "candidates" ] [ 0 ] [ "finishReason" ] . as_str ( ) )
217
+ {
218
+ bail ! ( "Blocked due to safety" )
218
219
}
219
220
220
221
Ok ( ( ) )
@@ -257,38 +258,35 @@ struct EmbeddingsResBodyPredictionEmbeddings {
257
258
}
258
259
259
260
fn gemini_extract_chat_completions_text ( data : & Value ) -> Result < ChatCompletionsOutput > {
260
- let text = data[ "candidates" ] [ 0 ] [ "content" ] [ "parts" ] [ 0 ] [ "text" ]
261
- . as_str ( )
262
- . unwrap_or_default ( ) ;
263
-
261
+ let mut text_parts = vec ! [ ] ;
264
262
let mut tool_calls = vec ! [ ] ;
265
263
if let Some ( parts) = data[ "candidates" ] [ 0 ] [ "content" ] [ "parts" ] . as_array ( ) {
266
- tool_calls = parts
267
- . iter ( )
268
- . filter_map ( |part| {
269
- if let ( Some ( name) , Some ( args) ) = (
270
- part[ "functionCall" ] [ "name" ] . as_str ( ) ,
271
- part[ "functionCall" ] [ "args" ] . as_object ( ) ,
272
- ) {
273
- Some ( ToolCall :: new ( name. to_string ( ) , json ! ( args) , None ) )
274
- } else {
275
- None
276
- }
277
- } )
278
- . collect ( )
264
+ for part in parts {
265
+ if let Some ( text) = part[ "text" ] . as_str ( ) {
266
+ text_parts. push ( text) ;
267
+ }
268
+ if let ( Some ( name) , Some ( args) ) = (
269
+ part[ "functionCall" ] [ "name" ] . as_str ( ) ,
270
+ part[ "functionCall" ] [ "args" ] . as_object ( ) ,
271
+ ) {
272
+ tool_calls. push ( ToolCall :: new ( name. to_string ( ) , json ! ( args) , None ) ) ;
273
+ }
274
+ }
279
275
}
276
+
277
+ let text = text_parts. join ( "\n \n " ) ;
280
278
if text. is_empty ( ) && tool_calls. is_empty ( ) {
281
279
if let Some ( "SAFETY" ) = data[ "promptFeedback" ] [ "blockReason" ]
282
280
. as_str ( )
283
281
. or_else ( || data[ "candidates" ] [ 0 ] [ "finishReason" ] . as_str ( ) )
284
282
{
285
- bail ! ( "Content Blocked" )
283
+ bail ! ( "Blocked due to safety " )
286
284
} else {
287
285
bail ! ( "Invalid response data: {data}" ) ;
288
286
}
289
287
}
290
288
let output = ChatCompletionsOutput {
291
- text : text . to_string ( ) ,
289
+ text,
292
290
tool_calls,
293
291
id : None ,
294
292
input_tokens : data[ "usageMetadata" ] [ "promptTokenCount" ] . as_u64 ( ) ,
0 commit comments