@@ -21,27 +21,20 @@ pub(crate) fn is_tools_select_name(name: &str) -> bool {
2121pub struct ToolsSearchArgs {
2222 /// Search terms, or `*` to enumerate every available callable name.
2323 pub query : String ,
24- /// Maximum number of results to return. `0` means all .
24+ /// Maximum number of results to return. Defaults to `10` .
2525 #[ serde( default ) ]
2626 pub limit : usize ,
2727}
2828
2929#[ derive( Debug , Clone , Default , Deserialize , Serialize ) ]
30- pub struct ToolsSearchOutput {
30+ pub struct ToolsOutput {
3131 /// Matching callable names and descriptions.
32- pub tools : Vec < ToolsSearchItem > ,
32+ pub tools : Vec < FunctionDefinition > , // tool 只要出现在上下文即可能被调用,不一定要求在请求的 tools 列表中,所以这里返回完整定义,防止大模型瞎编请求参数。
3333 /// Total number of callables to the current model turn.
34+ #[ serde( default ) ]
3435 pub total_tools : usize ,
3536}
3637
37- #[ derive( Debug , Clone , Default , Deserialize , Serialize ) ]
38- pub struct ToolsSearchItem {
39- /// Callable name to pass back into `tools_select` or a direct tool call.
40- pub name : String ,
41- /// Short description exposed to the model.
42- pub description : String ,
43- }
44-
4538/// Searches the callable surface currently available to the model.
4639/// The "tools_search" tool has been registered as a built-in agent with label "flash".
4740pub struct ToolsSearch {
@@ -60,35 +53,25 @@ impl ToolsSearch {
6053 Self { tokenizer }
6154 }
6255
63- pub fn search (
64- & self ,
65- candidates : & [ FunctionDefinition ] ,
66- args : & ToolsSearchArgs ,
67- ) -> ToolsSearchOutput {
56+ pub fn search ( & self , candidates : & [ FunctionDefinition ] , args : & ToolsSearchArgs ) -> ToolsOutput {
6857 let normalized_query = args. query . trim ( ) . to_lowercase ( ) ;
69- let tools: Vec < ToolsSearchItem > = candidates
70- . iter ( )
71- . map ( |def| ToolsSearchItem {
72- name : def. name . clone ( ) ,
73- description : def. description . clone ( ) ,
74- } )
75- . collect ( ) ;
58+ let tools: Vec < FunctionDefinition > = candidates. iter ( ) . cloned ( ) . collect ( ) ;
7659
7760 let total_tools = tools. len ( ) ;
7861 if normalized_query == "*" {
79- return ToolsSearchOutput { tools, total_tools } ;
62+ return ToolsOutput { tools, total_tools } ;
8063 }
8164
8265 let normalized_tokens: Vec < ( String , usize ) > =
8366 collect_tokens ( & mut self . tokenizer . clone ( ) , & normalized_query, None )
8467 . into_iter ( )
8568 . collect ( ) ;
8669
87- let mut tools = rank_search_items ( tools , & normalized_query , & normalized_tokens , false ) ;
88- if args . limit > 0 {
89- tools . truncate ( args. limit ) ;
90- }
91- ToolsSearchOutput { tools, total_tools }
70+ let mut tools_name =
71+ rank_search_items ( & tools , & normalized_query , & normalized_tokens , false ) ;
72+ tools_name . truncate ( if args . limit == 0 { 10 } else { args. limit } ) ;
73+ let tools = select_requested_definitions ( tools , & tools_name ) ;
74+ ToolsOutput { tools, total_tools }
9275 }
9376}
9477
@@ -116,8 +99,8 @@ impl Agent<AgentCtx> for ToolsSearch {
11699 } ,
117100 "limit" : {
118101 "type" : "integer" ,
119- "description" : "Maximum number of matches to return (default: 0, all matching tools) ." ,
120- "default" : 0 ,
102+ "description" : "Maximum number of matches to return. Defaults to `10` ." ,
103+ "default" : 10 ,
121104 "minimum" : 0
122105 }
123106 } ,
@@ -147,7 +130,7 @@ impl Agent<AgentCtx> for ToolsSearch {
147130 let definitions = ctx. definitions ( None ) . await ;
148131 if args. query . trim ( ) . is_empty ( ) || definitions. is_empty ( ) {
149132 return Ok ( AgentOutput {
150- content : serde_json:: to_string ( & ToolsSearchOutput {
133+ content : serde_json:: to_string ( & ToolsOutput {
151134 tools : Vec :: new ( ) ,
152135 total_tools : definitions. len ( ) ,
153136 } ) ?,
@@ -170,17 +153,11 @@ pub struct ToolsSelectArgs {
170153 /// Natural-language intent used to select tools when exact names are unknown.
171154 #[ serde( default ) ]
172155 pub query : String ,
173- /// Maximum number of resolved definitions to load. `0` lets the selector choose a bounded set .
156+ /// Maximum number of resolved definitions to load. Defaults to `5`, and is capped at `16` to prevent overloading the next model turn .
174157 #[ serde( default ) ]
175158 pub limit : usize ,
176159}
177160
178- #[ derive( Debug , Clone , Default , Deserialize , Serialize ) ]
179- pub struct ToolsSelectOutput {
180- /// Resolved function definitions that should be available to the next model turn.
181- pub tools : Vec < FunctionDefinition > ,
182- }
183-
184161#[ derive( Debug , Clone , Default , Deserialize , Serialize ) ]
185162struct ToolsSelectNamesOutput {
186163 #[ serde( default ) ]
@@ -219,64 +196,58 @@ impl ToolsSelect {
219196 let limit = if args. limit > 0 {
220197 args. limit . min ( MAX_SELECTOR_LIMIT )
221198 } else {
222- MAX_SELECTOR_LIMIT / 2
199+ 5
223200 } ;
224201
225- let items: Vec < ToolsSearchItem > = definitions
226- . iter ( )
227- . map ( |def| ToolsSearchItem {
228- name : def. name . clone ( ) ,
229- description : def. description . clone ( ) ,
230- } )
231- . collect ( ) ;
232-
233- let candidates =
234- self . collect_query_candidates ( items, & normalized_query, MAX_SELECTOR_CANDIDATE_LIMIT ) ;
202+ let mut candidates = self . collect_query_candidates (
203+ & definitions,
204+ & normalized_query,
205+ MAX_SELECTOR_CANDIDATE_LIMIT ,
206+ ) ;
235207
236208 if candidates. is_empty ( ) {
237209 return Vec :: new ( ) ;
238210 }
239211
240212 if normalized_query. len ( ) <= 3 {
241- let names: Vec < String > = candidates
242- . into_iter ( )
243- . take ( limit)
244- . map ( |item| item. name )
245- . collect ( ) ;
246- return select_requested_definitions ( definitions, & names) ;
213+ candidates. truncate ( limit) ;
214+ return select_requested_definitions ( definitions, & candidates) ;
247215 }
248216
249217 let mut requested =
250- select_requested_names_with_model ( ctx, & candidates , & normalized_query, limit) . await ;
218+ select_requested_names_with_model ( ctx, & definitions , & normalized_query, limit) . await ;
251219 if requested. is_empty ( ) {
252- requested = candidates
253- . iter ( )
254- . take ( limit)
255- . map ( |item| item. name . clone ( ) )
256- . collect ( ) ;
220+ candidates. truncate ( limit) ;
221+ requested = candidates;
257222 }
258223
259224 select_requested_definitions ( definitions, & requested)
260225 }
261226
262227 fn collect_query_candidates (
263228 & self ,
264- mut items : Vec < ToolsSearchItem > ,
229+ items : & [ FunctionDefinition ] ,
265230 query : & str ,
266231 candidate_limit : usize ,
267- ) -> Vec < ToolsSearchItem > {
268- if !query. is_empty ( ) && query != "*" {
232+ ) -> Vec < String > {
233+ let mut rt = if !query. is_empty ( ) && query != "*" {
269234 // (lowercase token, weight)
270235 let normalized_tokens: Vec < ( String , usize ) > =
271236 collect_tokens ( & mut self . tokenizer . clone ( ) , query, None )
272237 . into_iter ( )
273238 . collect ( ) ;
274239
275- items = rank_search_items ( items, query, & normalized_tokens, true ) ;
276- }
240+ rank_search_items ( items, query, & normalized_tokens, true )
241+ } else {
242+ items
243+ . iter ( )
244+ . take ( candidate_limit)
245+ . map ( |item| item. name . clone ( ) )
246+ . collect :: < Vec < _ > > ( )
247+ } ;
277248
278- items . truncate ( candidate_limit) ;
279- items
249+ rt . truncate ( candidate_limit) ;
250+ rt
280251 }
281252}
282253
@@ -313,8 +284,8 @@ impl Agent<AgentCtx> for ToolsSelect {
313284 "limit" : {
314285 "type" : "integer" ,
315286 "minimum" : 0 ,
316- "default" : 0 ,
317- "description" : "Maximum number of resolved callables to inject into the next turn. `0` lets the selector choose a bounded set ."
287+ "default" : 5 ,
288+ "description" : "Maximum number of resolved callables to inject into the next turn. Defaults to `5`, and is capped at `16` ."
318289 }
319290 } ,
320291 "required" : [ ] ,
@@ -348,6 +319,7 @@ impl Agent<AgentCtx> for ToolsSelect {
348319 }
349320
350321 let definitions = ctx. definitions ( None ) . await ;
322+ let total_tools = definitions. len ( ) ;
351323 let tool_definitions = if !args. tools . is_empty ( ) {
352324 select_requested_definitions ( definitions, & args. tools )
353325 } else {
@@ -356,8 +328,9 @@ impl Agent<AgentCtx> for ToolsSelect {
356328 } ;
357329
358330 Ok ( AgentOutput {
359- content : serde_json:: to_string ( & ToolsSelectOutput {
331+ content : serde_json:: to_string ( & ToolsOutput {
360332 tools : tool_definitions,
333+ total_tools,
361334 } ) ?,
362335 ..Default :: default ( )
363336 } )
@@ -366,7 +339,7 @@ impl Agent<AgentCtx> for ToolsSelect {
366339
367340async fn select_requested_names_with_model (
368341 ctx : & AgentCtx ,
369- candidates : & [ ToolsSearchItem ] ,
342+ candidates : & [ FunctionDefinition ] ,
370343 query : & str ,
371344 limit : usize ,
372345) -> Vec < String > {
@@ -471,12 +444,12 @@ const TOKEN_NAME_MATCH_WEIGHT: usize = 100;
471444const TOKEN_DESCRIPTION_MATCH_WEIGHT : usize = 10 ;
472445
473446fn rank_search_items (
474- items : Vec < ToolsSearchItem > ,
447+ items : & [ FunctionDefinition ] ,
475448 normalized_query : & str ,
476449 normalized_tokens : & [ ( String , usize ) ] ,
477450 fallback : bool ,
478- ) -> Vec < ToolsSearchItem > {
479- let mut candidates: Vec < ( bool , usize , String , ToolsSearchItem ) > = Vec :: new ( ) ;
451+ ) -> Vec < String > {
452+ let mut candidates: Vec < ( bool , usize , String ) > = Vec :: new ( ) ;
480453 for item in items {
481454 let normalized_name = item
482455 . name
@@ -508,9 +481,9 @@ fn rank_search_items(
508481 }
509482
510483 if score > 0 {
511- candidates. push ( ( exact_name_match, score, normalized_name, item ) ) ;
484+ candidates. push ( ( exact_name_match, score, normalized_name) ) ;
512485 } else if fallback {
513- candidates. push ( ( false , 0 , normalized_name, item ) ) ;
486+ candidates. push ( ( false , 0 , normalized_name) ) ;
514487 }
515488 }
516489
@@ -520,7 +493,7 @@ fn rank_search_items(
520493 . then_with ( || a. 2 . cmp ( & b. 2 ) )
521494 } ) ;
522495
523- candidates. into_iter ( ) . map ( |( _, _, _ , item ) | item ) . collect ( )
496+ candidates. into_iter ( ) . map ( |( _, _, name ) | name ) . collect ( )
524497}
525498
526499fn select_requested_definitions (
@@ -535,7 +508,6 @@ fn select_requested_definitions(
535508 }
536509
537510 let mut seen_requests = BTreeSet :: new ( ) ;
538- let mut seen_definitions = BTreeSet :: new ( ) ;
539511 let mut selected = Vec :: new ( ) ;
540512
541513 for name in requested {
@@ -544,10 +516,8 @@ fn select_requested_definitions(
544516 continue ;
545517 }
546518
547- if let Some ( def) = index. get ( & lookup)
548- && seen_definitions. insert ( def. name . clone ( ) )
549- {
550- selected. push ( def. clone ( ) ) ;
519+ if let Some ( def) = index. remove ( & lookup) {
520+ selected. push ( def) ;
551521 }
552522 }
553523
@@ -712,15 +682,15 @@ mod tests {
712682 }
713683 }
714684
715- async fn run_search ( ctx : AgentCtx , args : ToolsSearchArgs ) -> ToolsSearchOutput {
685+ async fn run_search ( ctx : AgentCtx , args : ToolsSearchArgs ) -> ToolsOutput {
716686 let output = ToolsSearch :: new ( )
717687 . run ( ctx, serde_json:: to_string ( & args) . unwrap ( ) , Vec :: new ( ) )
718688 . await
719689 . unwrap ( ) ;
720690 serde_json:: from_str ( & output. content ) . unwrap ( )
721691 }
722692
723- async fn run_select ( ctx : AgentCtx , args : ToolsSelectArgs ) -> ToolsSelectOutput {
693+ async fn run_select ( ctx : AgentCtx , args : ToolsSelectArgs ) -> ToolsOutput {
724694 let output = ToolsSelect :: new ( )
725695 . run ( ctx, serde_json:: to_string ( & args) . unwrap ( ) , Vec :: new ( ) )
726696 . await
0 commit comments