@@ -90,9 +90,19 @@ impl LLMService for OpenRouter {
90
90
"max_tokens" : result. remaining_output_tokens,
91
91
} ) ;
92
92
93
- // Conditionally add functions to the payload if tools_json is not empty
93
+ // Conditionally add tools to the payload if tools_json is not empty
94
94
if !tools_json. is_empty ( ) {
95
- payload[ "functions" ] = serde_json:: Value :: Array ( tools_json. clone ( ) ) ;
95
+ // Remove tool_router_key from each tool before sending to OpenRouter
96
+ let tools_payload = tools_json
97
+ . clone ( )
98
+ . into_iter ( )
99
+ . map ( |mut tool| {
100
+ tool. as_object_mut ( ) . unwrap ( ) . remove ( "tool_router_key" ) ;
101
+ tool
102
+ } )
103
+ . collect :: < Vec < JsonValue > > ( ) ;
104
+
105
+ payload[ "tools" ] = serde_json:: Value :: Array ( tools_payload) ;
96
106
}
97
107
98
108
// Add options to payload
@@ -252,38 +262,44 @@ async fn handle_streaming_response(
252
262
if let Some ( content) = message. get ( "content" ) {
253
263
response_text. push_str ( content. as_str ( ) . unwrap_or ( "" ) ) ;
254
264
}
255
- if let Some ( fc) = message. get ( "function_call" ) {
256
- if let Some ( name) = fc. get ( "name" ) {
257
- let fc_arguments = fc
258
- . get ( "arguments" )
259
- . and_then ( |args| args. as_str ( ) )
260
- . and_then ( |args_str| serde_json:: from_str ( args_str) . ok ( ) )
261
- . and_then ( |args_value : serde_json:: Value | {
262
- args_value. as_object ( ) . cloned ( )
263
- } )
264
- . unwrap_or_else ( || serde_json:: Map :: new ( ) ) ;
265
-
266
- // Extract tool_router_key
267
- let tool_router_key = tools. as_ref ( ) . and_then ( |tools_array| {
268
- tools_array. iter ( ) . find_map ( |tool| {
269
- if tool. get ( "name" ) ?. as_str ( ) ? == name. as_str ( ) . unwrap_or ( "" ) {
270
- tool. get ( "tool_router_key" )
271
- . and_then ( |key| key. as_str ( ) . map ( |s| s. to_string ( ) ) )
272
- } else {
273
- None
265
+ if let Some ( tool_calls) = message. get ( "tool_calls" ) {
266
+ if let Some ( tool_calls_array) = tool_calls. as_array ( ) {
267
+ for tool_call in tool_calls_array {
268
+ if let Some ( function) = tool_call. get ( "function" ) {
269
+ if let Some ( name) = function. get ( "name" ) {
270
+ let fc_arguments = function
271
+ . get ( "arguments" )
272
+ . and_then ( |args| args. as_str ( ) )
273
+ . and_then ( |args_str| serde_json:: from_str ( args_str) . ok ( ) )
274
+ . and_then ( |args_value : serde_json:: Value | {
275
+ args_value. as_object ( ) . cloned ( )
276
+ } )
277
+ . unwrap_or_else ( || serde_json:: Map :: new ( ) ) ;
278
+
279
+ // Extract tool_router_key
280
+ let tool_router_key = tools. as_ref ( ) . and_then ( |tools_array| {
281
+ tools_array. iter ( ) . find_map ( |tool| {
282
+ if tool. get ( "name" ) ?. as_str ( ) ? == name. as_str ( ) . unwrap_or ( "" ) {
283
+ tool. get ( "tool_router_key" )
284
+ . and_then ( |key| key. as_str ( ) . map ( |s| s. to_string ( ) ) )
285
+ } else {
286
+ None
287
+ }
288
+ } )
289
+ } ) ;
290
+
291
+ function_calls. push ( FunctionCall {
292
+ name : name. as_str ( ) . unwrap_or ( "" ) . to_string ( ) ,
293
+ arguments : fc_arguments. clone ( ) ,
294
+ tool_router_key,
295
+ response : None ,
296
+ index : function_calls. len ( ) as u64 ,
297
+ id : tool_call. get ( "id" ) . and_then ( |id| id. as_str ( ) ) . map ( |s| s. to_string ( ) ) ,
298
+ call_type : tool_call. get ( "type" ) . and_then ( |t| t. as_str ( ) ) . map ( |s| s. to_string ( ) ) . or ( Some ( "function" . to_string ( ) ) ) ,
299
+ } ) ;
274
300
}
275
- } )
276
- } ) ;
277
-
278
- function_calls. push ( FunctionCall {
279
- name : name. as_str ( ) . unwrap_or ( "" ) . to_string ( ) ,
280
- arguments : fc_arguments. clone ( ) ,
281
- tool_router_key,
282
- response : None ,
283
- index : function_calls. len ( ) as u64 ,
284
- id : None ,
285
- call_type : Some ( "function" . to_string ( ) ) ,
286
- } ) ;
301
+ }
302
+ }
287
303
}
288
304
}
289
305
}
@@ -462,17 +478,17 @@ async fn handle_non_streaming_response(
462
478
. collect:: <Vec <String >>( )
463
479
. join( " " ) ;
464
480
465
- let function_call : Option <FunctionCall > = data. choices. iter( ) . find_map ( |choice| {
466
- choice. message. function_call . clone ( ) . map( |fc | {
467
- let arguments = serde_json:: from_str:: <serde_json:: Value >( & fc . arguments)
481
+ let function_calls : Vec <FunctionCall > = data. choices. iter( ) . flat_map ( |choice| {
482
+ choice. message. tool_calls . as_ref ( ) . unwrap_or ( & vec! [ ] ) . iter ( ) . map( |tool_call | {
483
+ let arguments = serde_json:: from_str:: <serde_json:: Value >( & tool_call . function . arguments)
468
484
. ok( )
469
485
. and_then( |args_value: serde_json:: Value | args_value. as_object( ) . cloned( ) )
470
486
. unwrap_or_else( || serde_json:: Map :: new( ) ) ;
471
487
472
488
// Extract tool_router_key
473
489
let tool_router_key = tools. as_ref( ) . and_then( |tools_array| {
474
490
tools_array. iter( ) . find_map( |tool| {
475
- if tool. get( "name" ) ?. as_str( ) ? == fc . name {
491
+ if tool. get( "name" ) ?. as_str( ) ? == tool_call . function . name {
476
492
tool. get( "tool_router_key" ) . and_then( |key| key. as_str( ) . map( |s| s. to_string( ) ) )
477
493
} else {
478
494
None
@@ -481,22 +497,22 @@ async fn handle_non_streaming_response(
481
497
} ) ;
482
498
483
499
FunctionCall {
484
- name: fc . name,
500
+ name: tool_call . function . name. clone ( ) ,
485
501
arguments,
486
502
tool_router_key,
487
503
response: None ,
488
504
index: 0 ,
489
- id: None ,
490
- call_type: Some ( "function" . to_string ( ) ) ,
505
+ id: Some ( tool_call . id . clone ( ) ) ,
506
+ call_type: Some ( tool_call . call_type . clone ( ) ) ,
491
507
}
492
- } )
493
- } ) ;
494
- eprintln!( "Function Call : {:?}" , function_call ) ;
508
+ } ) . collect :: < Vec <_>> ( )
509
+ } ) . collect ( ) ;
510
+ eprintln!( "Function Calls : {:?}" , function_calls ) ;
495
511
eprintln!( "Response String: {:?}" , response_string) ;
496
512
return Ok ( LLMInferenceResponse :: new(
497
513
response_string,
498
514
json!( { } ) ,
499
- function_call . map_or_else ( Vec :: new , |fc| vec! [ fc ] ) ,
515
+ function_calls ,
500
516
None ,
501
517
) ) ;
502
518
}
0 commit comments