Skip to content

Commit e7aff0b

Browse files
committed
Update the quick start with up to date features
1 parent 162e950 commit e7aff0b

File tree

1 file changed

+160
-54
lines changed

1 file changed

+160
-54
lines changed

vertexai/lib/main.dart

Lines changed: 160 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,12 @@ class _ChatWidgetState extends State<ChatWidget> {
8888

8989
initFirebase().then((value) {
9090
_model = FirebaseVertexAI.instance.generativeModel(
91-
model: 'gemini-1.5-pro-preview-0409',
91+
model: 'gemini-1.5-flash-preview-0514',
9292
);
9393
_functionCallModel = FirebaseVertexAI.instance.generativeModel(
94-
model: 'gemini-1.5-pro-preview-0409',
94+
model: 'gemini-1.5-flash-preview-0514',
9595
tools: [
96-
Tool(functionDeclarations: [exchangeRateTool])
96+
Tool(functionDeclarations: [exchangeRateTool]),
9797
],
9898
);
9999
_chat = _model.startChat();
@@ -108,23 +108,33 @@ class _ChatWidgetState extends State<ChatWidget> {
108108
{
109109
'date': arguments['currencyDate'],
110110
'base': arguments['currencyFrom'],
111-
'rates': <String, Object?>{arguments['currencyTo'] as String: 0.091}
111+
'rates': <String, Object?>{arguments['currencyTo']! as String: 0.091},
112112
};
113113

114114
final exchangeRateTool = FunctionDeclaration(
115-
'findExchangeRate',
116-
'Returns the exchange rate between currencies on given date.',
117-
Schema(SchemaType.object, properties: {
118-
'currencyDate': Schema(SchemaType.string,
119-
description: 'A date in YYYY-MM-DD format or '
120-
'the exact value "latest" if a time period is not specified.'),
121-
'currencyFrom': Schema(SchemaType.string,
122-
description: 'The currency code of the currency to convert from, '
123-
'such as "USD".'),
124-
'currencyTo': Schema(SchemaType.string,
125-
description: 'The currency code of the currency to convert to, '
126-
'such as "USD".')
127-
}));
115+
'findExchangeRate',
116+
'Returns the exchange rate between currencies on given date.',
117+
Schema(
118+
SchemaType.object,
119+
properties: {
120+
'currencyDate': Schema(
121+
SchemaType.string,
122+
description: 'A date in YYYY-MM-DD format or '
123+
'the exact value "latest" if a time period is not specified.',
124+
),
125+
'currencyFrom': Schema(
126+
SchemaType.string,
127+
description: 'The currency code of the currency to convert from, '
128+
'such as "USD".',
129+
),
130+
'currencyTo': Schema(
131+
SchemaType.string,
132+
description: 'The currency code of the currency to convert to, '
133+
'such as "USD".',
134+
),
135+
},
136+
),
137+
);
128138

129139
Future<void> initFirebase() async {
130140
await Firebase.initializeApp();
@@ -166,7 +176,7 @@ class _ChatWidgetState extends State<ChatWidget> {
166176
);
167177

168178
return Padding(
169-
padding: const EdgeInsets.all(8.0),
179+
padding: const EdgeInsets.all(8),
170180
child: Column(
171181
mainAxisAlignment: MainAxisAlignment.center,
172182
crossAxisAlignment: CrossAxisAlignment.start,
@@ -198,18 +208,31 @@ class _ChatWidgetState extends State<ChatWidget> {
198208
focusNode: _textFieldFocus,
199209
decoration: textFieldDecoration,
200210
controller: _textController,
201-
onSubmitted: (String value) {
202-
_sendChatMessage(value);
203-
},
211+
onSubmitted: _sendChatMessage,
204212
),
205213
),
206214
const SizedBox.square(
207215
dimension: 15,
208216
),
209217
IconButton(
218+
tooltip: 'tokenCount Test',
210219
onPressed: !_loading
211220
? () async {
212-
_testFunctionCalling();
221+
await _testCountToken();
222+
}
223+
: null,
224+
icon: Icon(
225+
Icons.numbers,
226+
color: _loading
227+
? Theme.of(context).colorScheme.secondary
228+
: Theme.of(context).colorScheme.primary,
229+
),
230+
),
231+
IconButton(
232+
tooltip: 'function calling Test',
233+
onPressed: !_loading
234+
? () async {
235+
await _testFunctionCalling();
213236
}
214237
: null,
215238
icon: Icon(
@@ -220,9 +243,10 @@ class _ChatWidgetState extends State<ChatWidget> {
220243
),
221244
),
222245
IconButton(
246+
tooltip: 'image prompt',
223247
onPressed: !_loading
224248
? () async {
225-
_sendImagePrompt(_textController.text);
249+
await _sendImagePrompt(_textController.text);
226250
}
227251
: null,
228252
icon: Icon(
@@ -232,10 +256,24 @@ class _ChatWidgetState extends State<ChatWidget> {
232256
: Theme.of(context).colorScheme.primary,
233257
),
234258
),
259+
IconButton(
260+
tooltip: 'storage prompt',
261+
onPressed: !_loading
262+
? () async {
263+
await _sendStorageUriPrompt(_textController.text);
264+
}
265+
: null,
266+
icon: Icon(
267+
Icons.folder,
268+
color: _loading
269+
? Theme.of(context).colorScheme.secondary
270+
: Theme.of(context).colorScheme.primary,
271+
),
272+
),
235273
if (!_loading)
236274
IconButton(
237275
onPressed: () async {
238-
_sendChatMessage(_textController.text);
276+
await _sendChatMessage(_textController.text);
239277
},
240278
icon: Icon(
241279
Icons.send,
@@ -252,6 +290,49 @@ class _ChatWidgetState extends State<ChatWidget> {
252290
);
253291
}
254292

293+
Future<void> _sendStorageUriPrompt(String message) async {
294+
setState(() {
295+
_loading = true;
296+
});
297+
try {
298+
final content = [
299+
Content.multi([
300+
TextPart(message),
301+
FileData(
302+
'image/jpeg',
303+
'gs://vertex-ai-example-ef5a2.appspot.com/foodpic.jpg',
304+
),
305+
]),
306+
];
307+
_generatedContent.add((image: null, text: message, fromUser: true));
308+
309+
var response = await _model.generateContent(content);
310+
var text = response.text;
311+
_generatedContent.add((image: null, text: text, fromUser: false));
312+
313+
if (text == null) {
314+
_showError('No response from API.');
315+
return;
316+
} else {
317+
setState(() {
318+
_loading = false;
319+
_scrollDown();
320+
});
321+
}
322+
} catch (e) {
323+
_showError(e.toString());
324+
setState(() {
325+
_loading = false;
326+
});
327+
} finally {
328+
_textController.clear();
329+
setState(() {
330+
_loading = false;
331+
});
332+
_textFieldFocus.requestFocus();
333+
}
334+
}
335+
255336
Future<void> _sendImagePrompt(String message) async {
256337
setState(() {
257338
_loading = true;
@@ -265,18 +346,22 @@ class _ChatWidgetState extends State<ChatWidget> {
265346
// The only accepted mime types are image/*.
266347
DataPart('image/jpeg', catBytes.buffer.asUint8List()),
267348
DataPart('image/jpeg', sconeBytes.buffer.asUint8List()),
268-
])
349+
]),
269350
];
270-
_generatedContent.add((
271-
image: Image.asset("assets/images/cat.jpg"),
272-
text: message,
273-
fromUser: true
274-
));
275-
_generatedContent.add((
276-
image: Image.asset("assets/images/scones.jpg"),
277-
text: null,
278-
fromUser: true
279-
));
351+
_generatedContent.add(
352+
(
353+
image: Image.asset('assets/images/cat.jpg'),
354+
text: message,
355+
fromUser: true
356+
),
357+
);
358+
_generatedContent.add(
359+
(
360+
image: Image.asset('assets/images/scones.jpg'),
361+
text: null,
362+
fromUser: true
363+
),
364+
);
280365

281366
var response = await _model.generateContent(content);
282367
var text = response.text;
@@ -361,7 +446,8 @@ class _ChatWidgetState extends State<ChatWidget> {
361446
// Throw an exception if the model attempted to call a function that was
362447
// not declared.
363448
_ => throw UnimplementedError(
364-
'Function not implemented: ${functionCall.name}')
449+
'Function not implemented: ${functionCall.name}',
450+
)
365451
};
366452
// Send the response to the model so that it can use the result to generate
367453
// text for the user.
@@ -377,6 +463,22 @@ class _ChatWidgetState extends State<ChatWidget> {
377463
}
378464
}
379465

466+
Future<void> _testCountToken() async {
467+
setState(() {
468+
_loading = true;
469+
});
470+
471+
const prompt = 'tell a short story';
472+
var response = await _model.countTokens([Content.text(prompt)]);
473+
print(
474+
'token: ${response.totalTokens}, billable characters: ${response.totalBillableCharacters}',
475+
);
476+
477+
setState(() {
478+
_loading = false;
479+
});
480+
}
481+
380482
void _showError(String message) {
381483
showDialog<void>(
382484
context: context,
@@ -392,7 +494,7 @@ class _ChatWidgetState extends State<ChatWidget> {
392494
Navigator.of(context).pop();
393495
},
394496
child: const Text('OK'),
395-
)
497+
),
396498
],
397499
);
398500
},
@@ -419,23 +521,27 @@ class MessageWidget extends StatelessWidget {
419521
isFromUser ? MainAxisAlignment.end : MainAxisAlignment.start,
420522
children: [
421523
Flexible(
422-
child: Container(
423-
constraints: const BoxConstraints(maxWidth: 600),
424-
decoration: BoxDecoration(
425-
color: isFromUser
426-
? Theme.of(context).colorScheme.primaryContainer
427-
: Theme.of(context).colorScheme.surfaceVariant,
428-
borderRadius: BorderRadius.circular(18),
429-
),
430-
padding: const EdgeInsets.symmetric(
431-
vertical: 15,
432-
horizontal: 20,
433-
),
434-
margin: const EdgeInsets.only(bottom: 8),
435-
child: Column(children: [
436-
if (text case final text?) MarkdownBody(data: text),
437-
if (image case final image?) image,
438-
]))),
524+
child: Container(
525+
constraints: const BoxConstraints(maxWidth: 600),
526+
decoration: BoxDecoration(
527+
color: isFromUser
528+
? Theme.of(context).colorScheme.primaryContainer
529+
: Theme.of(context).colorScheme.surfaceContainerHighest,
530+
borderRadius: BorderRadius.circular(18),
531+
),
532+
padding: const EdgeInsets.symmetric(
533+
vertical: 15,
534+
horizontal: 20,
535+
),
536+
margin: const EdgeInsets.only(bottom: 8),
537+
child: Column(
538+
children: [
539+
if (text case final text?) MarkdownBody(data: text),
540+
if (image case final image?) image,
541+
],
542+
),
543+
),
544+
),
439545
],
440546
);
441547
}

0 commit comments

Comments
 (0)