@@ -41,12 +41,16 @@ class Location {
4141class _FunctionCallingPageState extends State <FunctionCallingPage > {
4242 late GenerativeModel _functionCallModel;
4343 late GenerativeModel _autoFunctionCallModel;
44+ late GenerativeModel _parallelAutoFunctionCallModel;
4445 late GenerativeModel _codeExecutionModel;
4546 late final AutoFunctionDeclaration _autoFetchWeatherTool;
4647 final List <MessageData > _messages = < MessageData > [];
4748 bool _loading = false ;
4849 bool _enableThinking = false ;
4950
51+ late final AutoFunctionDeclaration _autoFindRestaurantsTool;
52+ late final AutoFunctionDeclaration _autoGetRestaurantMenuTool;
53+
5054 @override
5155 void initState () {
5256 super .initState ();
@@ -74,9 +78,72 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
7478 },
7579 callable: _fetchWeatherCallable,
7680 );
81+ _autoFindRestaurantsTool = AutoFunctionDeclaration (
82+ name: 'findRestaurants' ,
83+ description: 'Find restaurants of a certain cuisine in a given location.' ,
84+ parameters: {
85+ 'cuisine' : Schema .string (
86+ description: 'The cuisine of the restaurant.' ,
87+ ),
88+ 'location' : Schema .string (
89+ description:
90+ 'The location to search for restaurants. e.g. San Francisco, CA' ,
91+ ),
92+ },
93+ callable: (args) async {
94+ final cuisine = args['cuisine' ]! as String ;
95+ final location = args['location' ]! as String ;
96+ return findRestaurants (cuisine, location);
97+ },
98+ );
99+ _autoGetRestaurantMenuTool = AutoFunctionDeclaration (
100+ name: 'getRestaurantMenu' ,
101+ description: 'Get the menu for a specific restaurant.' ,
102+ parameters: {
103+ 'restaurantName' : Schema .string (
104+ description: 'The name of the restaurant.' ,
105+ ),
106+ },
107+ callable: (args) async {
108+ final restaurantName = args['restaurantName' ]! as String ;
109+ return getRestaurantMenu (restaurantName);
110+ },
111+ );
77112 _initializeModel ();
78113 }
79114
115+ Future <Map <String , Object ?>> findRestaurants (
116+ String cuisine,
117+ String location,
118+ ) async {
119+ // This is a mock response.
120+ return {
121+ 'restaurants' : [
122+ {
123+ 'name' : 'The Golden Spoon' ,
124+ 'cuisine' : 'Vegetarian' ,
125+ 'location' : 'San Francisco, CA' ,
126+ },
127+ {
128+ 'name' : 'Green Leaf Bistro' ,
129+ 'cuisine' : 'Vegetarian' ,
130+ 'location' : 'San Francisco, CA' ,
131+ },
132+ ],
133+ };
134+ }
135+
136+ Future <Map <String , Object ?>> getRestaurantMenu (String restaurantName) async {
137+ // This is a mock response.
138+ return {
139+ 'menu' : [
140+ {'name' : 'Lentil Soup' , 'price' : '8.99' },
141+ {'name' : 'Garden Salad' , 'price' : '10.99' },
142+ {'name' : 'Mushroom Risotto' , 'price' : '15.99' },
143+ ],
144+ };
145+ }
146+
80147 Future <Map <String , Object ?>> _fetchWeatherCallable (
81148 Map <String , Object ?> args,
82149 ) async {
@@ -112,6 +179,15 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
112179 Tool .functionDeclarations ([_autoFetchWeatherTool]),
113180 ],
114181 );
182+ _parallelAutoFunctionCallModel = vertexAI.generativeModel (
183+ model: 'gemini-2.5-flash' ,
184+ generationConfig: generationConfig,
185+ tools: [
186+ Tool .functionDeclarations (
187+ [_autoFindRestaurantsTool, _autoGetRestaurantMenuTool],
188+ ),
189+ ],
190+ );
115191 _codeExecutionModel = vertexAI.generativeModel (
116192 model: 'gemini-2.5-flash' ,
117193 generationConfig: generationConfig,
@@ -135,6 +211,15 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
135211 Tool .functionDeclarations ([_autoFetchWeatherTool]),
136212 ],
137213 );
214+ _parallelAutoFunctionCallModel = googleAI.generativeModel (
215+ model: 'gemini-2.5-flash' ,
216+ generationConfig: generationConfig,
217+ tools: [
218+ Tool .functionDeclarations (
219+ [_autoFindRestaurantsTool, _autoGetRestaurantMenuTool],
220+ ),
221+ ],
222+ );
138223 _codeExecutionModel = googleAI.generativeModel (
139224 model: 'gemini-2.5-flash' ,
140225 generationConfig: generationConfig,
@@ -266,6 +351,17 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
266351 child: const Text ('Auto Function Calling' ),
267352 ),
268353 ),
354+ const SizedBox (width: 8 ),
355+ Expanded (
356+ child: ElevatedButton (
357+ onPressed: ! _loading
358+ ? () async {
359+ await _testParallelAutoFunctionCalling ();
360+ }
361+ : null ,
362+ child: const Text ('Parallel Auto FC' ),
363+ ),
364+ ),
269365 ],
270366 ),
271367 const SizedBox (height: 8 ),
@@ -293,7 +389,7 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
293389 ),
294390 ),
295391 ],
296- ),
392+ )
297393 ],
298394 ),
299395 ),
@@ -303,6 +399,46 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
303399 );
304400 }
305401
402+ Future <void > _testParallelAutoFunctionCalling () async {
403+ setState (() {
404+ _loading = true ;
405+ _messages.clear ();
406+ });
407+ try {
408+ final autoFunctionCallChat = _parallelAutoFunctionCallModel.startChat ();
409+ const prompt =
410+ 'Find me a good vegetarian restaurant in San Francisco and get its menu.' ;
411+
412+ _messages.add (MessageData (text: prompt, fromUser: true ));
413+ setState (() {});
414+
415+ // Send the message to the generative model.
416+ final response = await autoFunctionCallChat.sendMessage (
417+ Content .text (prompt),
418+ );
419+
420+ final thought = response.thoughtSummary;
421+ if (thought != null ) {
422+ _messages
423+ .add (MessageData (text: thought, fromUser: false , isThought: true ));
424+ }
425+
426+ // The SDK should have handled the function call automatically.
427+ // The final response should contain the text from the model.
428+ if (response.text case final text? ) {
429+ _messages.add (MessageData (text: text));
430+ } else {
431+ _messages.add (MessageData (text: 'No text response from model.' ));
432+ }
433+ } catch (e) {
434+ _showError (e.toString ());
435+ } finally {
436+ setState (() {
437+ _loading = false ;
438+ });
439+ }
440+ }
441+
306442 Future <void > _testStreamFunctionCalling () async {
307443 setState (() {
308444 _loading = true ;
0 commit comments