@@ -39,28 +39,39 @@ class Location {
3939}
4040
4141class _FunctionCallingPageState extends State <FunctionCallingPage > {
42- late final GenerativeModel _functionCallModel;
42+ late GenerativeModel _functionCallModel;
4343 final List <MessageData > _messages = < MessageData > [];
4444 bool _loading = false ;
45+ bool _enableThinking = false ;
4546
4647 @override
4748 void initState () {
4849 super .initState ();
50+ _initializeModel ();
51+ }
52+
53+ void _initializeModel () {
54+ final generationConfig = GenerationConfig (
55+ thinkingConfig:
56+ _enableThinking ? ThinkingConfig (includeThoughts: true ) : null ,
57+ );
4958 if (widget.useVertexBackend) {
5059 var vertexAI = FirebaseAI .vertexAI (auth: FirebaseAuth .instance);
5160 _functionCallModel = vertexAI.generativeModel (
52- model: 'gemini-2.0 -flash' ,
61+ model: 'gemini-2.5 -flash' ,
5362 tools: [
5463 Tool .functionDeclarations ([fetchWeatherTool]),
5564 ],
65+ generationConfig: generationConfig,
5666 );
5767 } else {
5868 var googleAI = FirebaseAI .googleAI (auth: FirebaseAuth .instance);
5969 _functionCallModel = googleAI.generativeModel (
60- model: 'gemini-2.0 -flash' ,
70+ model: 'gemini-2.5 -flash' ,
6171 tools: [
6272 Tool .functionDeclarations ([fetchWeatherTool]),
6373 ],
74+ generationConfig: generationConfig,
6475 );
6576 }
6677 }
@@ -118,12 +129,24 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
118129 mainAxisAlignment: MainAxisAlignment .center,
119130 crossAxisAlignment: CrossAxisAlignment .start,
120131 children: [
132+ SwitchListTile (
133+ title: const Text ('Enable Thinking' ),
134+ value: _enableThinking,
135+ onChanged: (bool value) {
136+ setState (() {
137+ _enableThinking = value;
138+ _initializeModel ();
139+ });
140+ },
141+ ),
121142 Expanded (
122143 child: ListView .builder (
123144 itemBuilder: (context, idx) {
145+ final message = _messages[idx];
124146 return MessageWidget (
125- text: _messages[idx].text,
126- isFromUser: _messages[idx].fromUser ?? false ,
147+ text: message.text,
148+ isFromUser: message.fromUser ?? false ,
149+ isThought: message.isThought,
127150 );
128151 },
129152 itemCount: _messages.length,
@@ -158,43 +181,87 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
158181 Future <void > _testFunctionCalling () async {
159182 setState (() {
160183 _loading = true ;
184+ _messages.clear ();
161185 });
162- final functionCallChat = _functionCallModel.startChat ();
163- const prompt = 'What is the weather like in Boston on 10/02 in year 2024?' ;
186+ try {
187+ final functionCallChat = _functionCallModel.startChat ();
188+ const prompt =
189+ 'What is the weather like in Boston on 10/02 in year 2024?' ;
164190
165- // Send the message to the generative model.
166- var response = await functionCallChat.sendMessage (
167- Content .text (prompt),
168- );
191+ _messages.add (MessageData (text: prompt, fromUser: true ));
169192
170- final functionCalls = response.functionCalls.toList ();
171- // When the model response with a function call, invoke the function.
172- if (functionCalls.isNotEmpty) {
173- final functionCall = functionCalls.first;
174- if (functionCall.name == 'fetchWeather' ) {
175- Map <String , dynamic > location =
176- functionCall.args['location' ]! as Map <String , dynamic >;
177- var date = functionCall.args['date' ]! as String ;
178- var city = location['city' ] as String ;
179- var state = location['state' ] as String ;
180- final functionResult = await fetchWeather (Location (city, state), date);
181- // Send the response to the model so that it can use the result to
182- // generate text for the user.
183- response = await functionCallChat.sendMessage (
184- Content .functionResponse (functionCall.name, functionResult),
185- );
186- } else {
187- throw UnimplementedError (
188- 'Function not declared to the model: ${functionCall .name }' ,
189- );
193+ // Send the message to the generative model.
194+ var response = await functionCallChat.sendMessage (
195+ Content .text (prompt),
196+ );
197+
198+ final thought = response.thoughtSummary;
199+ if (thought != null ) {
200+ _messages
201+ .add (MessageData (text: thought, fromUser: false , isThought: true ));
190202 }
191- }
192- // When the model responds with non-null text content, print it.
193- if (response.text case final text? ) {
194- _messages.add (MessageData (text: text));
203+
204+ final functionCalls = response.functionCalls.toList ();
205+ // When the model response with a function call, invoke the function.
206+ if (functionCalls.isNotEmpty) {
207+ final functionCall = functionCalls.first;
208+ if (functionCall.name == 'fetchWeather' ) {
209+ Map <String , dynamic > location =
210+ functionCall.args['location' ]! as Map <String , dynamic >;
211+ var date = functionCall.args['date' ]! as String ;
212+ var city = location['city' ] as String ;
213+ var state = location['state' ] as String ;
214+ final functionResult =
215+ await fetchWeather (Location (city, state), date);
216+ // Send the response to the model so that it can use the result to
217+ // generate text for the user.
218+ response = await functionCallChat.sendMessage (
219+ Content .functionResponse (functionCall.name, functionResult),
220+ );
221+ } else {
222+ throw UnimplementedError (
223+ 'Function not declared to the model: ${functionCall .name }' ,
224+ );
225+ }
226+ }
227+ // When the model responds with non-null text content, print it.
228+ if (response.text case final text? ) {
229+ _messages.add (MessageData (text: text));
230+ setState (() {
231+ _loading = false ;
232+ });
233+ }
234+ } catch (e) {
235+ _showError (e.toString ());
236+ setState (() {
237+ _loading = false ;
238+ });
239+ } finally {
195240 setState (() {
196241 _loading = false ;
197242 });
198243 }
199244 }
245+
246+ void _showError (String message) {
247+ showDialog <void >(
248+ context: context,
249+ builder: (context) {
250+ return AlertDialog (
251+ title: const Text ('Something went wrong' ),
252+ content: SingleChildScrollView (
253+ child: SelectableText (message),
254+ ),
255+ actions: [
256+ TextButton (
257+ onPressed: () {
258+ Navigator .of (context).pop ();
259+ },
260+ child: const Text ('OK' ),
261+ ),
262+ ],
263+ );
264+ },
265+ );
266+ }
200267}
0 commit comments