1717using System ;
1818using System . Collections . Generic ;
1919using System . Linq ;
20+ using System . Reflection ;
21+ using Firebase . AI . Internal ;
2022
2123namespace Firebase . AI
2224{
@@ -86,9 +88,9 @@ public FunctionDeclaration(string name, string description,
8688 internal Dictionary < string , object > ToJson ( )
8789 {
8890 var json = new Dictionary < string , object > ( ) {
89- { "name" , Name } ,
90- { "description" , Description } ,
91- } ;
91+ { "name" , Name } ,
92+ { "description" , Description } ,
93+ } ;
9294 // Only one of these will likely be set, but just check
9395 if ( JsonParameters != null )
9496 {
@@ -103,6 +105,27 @@ internal Dictionary<string, object> ToJson()
103105 }
104106 }
105107
108+ /// <summary>
109+ /// Structured representation of a function declaration, designed
110+ /// to be automatically handled when using Chat, instead of requiring
111+ /// manual handling.
112+ ///
113+ /// See `FunctionDeclaration` for more information.
114+ /// </summary>
115+ public class AutoFunctionDeclaration : BaseAutoFunctionDeclaration
116+ {
117+ /// <summary>
118+ /// Constructs a new `AutoFunctionDeclaration`
119+ /// </summary>
120+ /// <param name="callable">The delegate that will be called automatically when requested by the model.</param>
121+ /// <param name="description">A brief description of the function.</param>
122+ /// <param name="name">Optional name to use for the function, used to overwrite the delegate name.</param>
123+ public AutoFunctionDeclaration ( Delegate callable , string description ,
124+ string name = null )
125+ : base ( callable , description , name )
126+ { }
127+ }
128+
106129 /// <summary>
107130 /// A tool that allows the generative model to connect to Google Search to access and incorporate
108131 /// up-to-date information from the web into its responses.
@@ -134,6 +157,7 @@ public readonly struct Tool
134157 // No public properties, on purpose since it is meant for user input only
135158
136159 private List < FunctionDeclaration > FunctionDeclarations { get ; }
160+ internal List < AutoFunctionDeclaration > AutoFunctionDeclarations { get ; }
137161 private GoogleSearch ? GoogleSearch { get ; }
138162 private CodeExecution ? CodeExecution { get ; }
139163 private UrlContext ? UrlContext { get ; }
@@ -146,6 +170,7 @@ public readonly struct Tool
146170 public Tool ( params FunctionDeclaration [ ] functionDeclarations )
147171 {
148172 FunctionDeclarations = new List < FunctionDeclaration > ( functionDeclarations ) ;
173+ AutoFunctionDeclarations = null ;
149174 GoogleSearch = null ;
150175 CodeExecution = null ;
151176 UrlContext = null ;
@@ -158,6 +183,34 @@ public Tool(params FunctionDeclaration[] functionDeclarations)
158183 public Tool ( IEnumerable < FunctionDeclaration > functionDeclarations )
159184 {
160185 FunctionDeclarations = new List < FunctionDeclaration > ( functionDeclarations ) ;
186+ AutoFunctionDeclarations = null ;
187+ GoogleSearch = null ;
188+ CodeExecution = null ;
189+ UrlContext = null ;
190+ }
191+
192+ /// <summary>
193+ /// Creates a tool that allows the model to perform function calling.
194+ /// </summary>
195+ /// <param name="functionDeclarations">A list of `FunctionDeclarations` available to the model
196+ /// that can be used for function calling.</param>
197+ public Tool ( params AutoFunctionDeclaration [ ] functionDeclarations )
198+ {
199+ FunctionDeclarations = null ;
200+ AutoFunctionDeclarations = new List < AutoFunctionDeclaration > ( functionDeclarations ) ;
201+ GoogleSearch = null ;
202+ CodeExecution = null ;
203+ UrlContext = null ;
204+ }
205+ /// <summary>
206+ /// Creates a tool that allows the model to perform function calling.
207+ /// </summary>
208+ /// <param name="functionDeclarations">A list of `FunctionDeclarations` available to the model
209+ /// that can be used for function calling.</param>
210+ public Tool ( IEnumerable < AutoFunctionDeclaration > functionDeclarations )
211+ {
212+ FunctionDeclarations = null ;
213+ AutoFunctionDeclarations = new List < AutoFunctionDeclaration > ( functionDeclarations ) ;
161214 GoogleSearch = null ;
162215 CodeExecution = null ;
163216 UrlContext = null ;
@@ -171,6 +224,7 @@ public Tool(IEnumerable<FunctionDeclaration> functionDeclarations)
171224 public Tool ( GoogleSearch googleSearch )
172225 {
173226 FunctionDeclarations = null ;
227+ AutoFunctionDeclarations = null ;
174228 GoogleSearch = googleSearch ;
175229 CodeExecution = null ;
176230 UrlContext = null ;
@@ -184,6 +238,7 @@ public Tool(GoogleSearch googleSearch)
184238 public Tool ( CodeExecution codeExecution )
185239 {
186240 FunctionDeclarations = null ;
241+ AutoFunctionDeclarations = null ;
187242 GoogleSearch = null ;
188243 CodeExecution = codeExecution ;
189244 UrlContext = null ;
@@ -198,6 +253,7 @@ public Tool(CodeExecution codeExecution)
198253 public Tool ( UrlContext urlContext )
199254 {
200255 FunctionDeclarations = null ;
256+ AutoFunctionDeclarations = null ;
201257 GoogleSearch = null ;
202258 CodeExecution = null ;
203259 UrlContext = urlContext ;
@@ -210,9 +266,18 @@ public Tool(UrlContext urlContext)
210266 internal Dictionary < string , object > ToJson ( )
211267 {
212268 var json = new Dictionary < string , object > ( ) ;
269+ List < Dictionary < string , object > > functionDeclarations = new ( ) ;
213270 if ( FunctionDeclarations != null && FunctionDeclarations . Any ( ) )
214271 {
215- json [ "functionDeclarations" ] = FunctionDeclarations . Select ( f => f . ToJson ( ) ) . ToList ( ) ;
272+ functionDeclarations . AddRange ( FunctionDeclarations . Select ( f => f . ToJson ( ) ) ) ;
273+ }
274+ if ( AutoFunctionDeclarations != null && AutoFunctionDeclarations . Any ( ) )
275+ {
276+ functionDeclarations . AddRange ( AutoFunctionDeclarations . Select ( f => f . ToJson ( ) ) ) ;
277+ }
278+ if ( functionDeclarations . Count > 0 )
279+ {
280+ json [ "functionDeclarations" ] = functionDeclarations ;
216281 }
217282 if ( GoogleSearch . HasValue )
218283 {
@@ -342,4 +407,73 @@ internal Dictionary<string, object> ToJson()
342407 }
343408 }
344409
410+ /// <summary>
411+ /// Attribute that can be attached to parameters to give them a description,
412+ /// used when using `AutoFunctionDeclaration`.
413+ /// </summary>
414+ [ AttributeUsage ( AttributeTargets . Parameter ) ]
415+ public class AutoFunctionDescriptionAttribute : Attribute
416+ {
417+ public AutoFunctionDescriptionAttribute ( string description )
418+ {
419+ Description = description ;
420+ }
421+
422+ public string Description { get ; set ; } = null ;
423+ }
424+
425+ #if ! DOXYGEN
426+ public abstract class BaseAutoFunctionDeclaration
427+ {
428+ internal string Name { get ; }
429+ internal string Description { get ; }
430+ internal JsonSchema Parameters { get ; }
431+
432+ internal Delegate Callable { get ; }
433+
434+ public BaseAutoFunctionDeclaration ( Delegate callable , string description ,
435+ string name = null )
436+ {
437+ if ( callable == null )
438+ {
439+ throw new ArgumentNullException ( nameof ( callable ) ) ;
440+ }
441+ Name = name ?? callable . Method . Name ;
442+ Description = description ;
443+
444+ Dictionary < string , JsonSchema > parameters = new ( ) ;
445+ List < string > optionalParameters = new ( ) ;
446+ // Construct the Parameters based on the given Delegate
447+ foreach ( var pInfo in callable . Method . GetParameters ( ) )
448+ {
449+ var attr = pInfo . GetCustomAttribute < AutoFunctionDescriptionAttribute > ( ) ;
450+ parameters . Add ( pInfo . Name ,
451+ JsonSchema . FromType ( pInfo . ParameterType , attr ? . Description ) ) ;
452+ if ( pInfo . HasDefaultValue )
453+ {
454+ optionalParameters . Add ( pInfo . Name ) ;
455+ }
456+ }
457+ Parameters = JsonSchema . Object ( parameters , optionalParameters ) ;
458+
459+ Callable = callable ;
460+ }
461+
462+ /// <summary>
463+ /// Intended for internal use only.
464+ /// This method is used for serializing the object to JSON for the API request.
465+ /// </summary>
466+ internal Dictionary < string , object > ToJson ( )
467+ {
468+ var json = new Dictionary < string , object > ( ) {
469+ { "name" , Name } ,
470+ { "parametersJsonSchema" , Parameters . ToJson ( ) }
471+ } ;
472+ json . AddIfHasValue ( "description" , Description ) ;
473+
474+ return json ;
475+ }
476+ }
477+ #endif // !DOXYGEN
478+
345479}
0 commit comments