Skip to content

Commit 35a976a

Browse files
authored
chore(vertexai): function calling sample update (#13492)
* fix the optional attributes while parsing SafetyRating * add doc comments * update function sample * comments
1 parent 92469fe commit 35a976a

File tree

1 file changed

+46
-59
lines changed
  • packages/firebase_vertexai/firebase_vertexai/example/lib

1 file changed

+46
-59
lines changed

packages/firebase_vertexai/firebase_vertexai/example/lib/main.dart

Lines changed: 46 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,24 @@ class _ChatWidgetState extends State<ChatWidget> {
9696
_functionCallModel = FirebaseVertexAI.instance.generativeModel(
9797
model: 'gemini-1.5-flash',
9898
tools: [
99-
Tool.functionDeclarations([getWeatherTool]),
99+
Tool.functionDeclarations([fetchWeatherTool]),
100100
],
101101
);
102102
_chat = _model.startChat();
103103
});
104104
}
105105

106106
// This is a hypothetical API to return a fake weather data collection for certain location
107-
Future<Map<String, Object?>> getWeather(
108-
Map<String, Object?> arguments,
107+
Future<Map<String, Object?>> fetchWeather(
108+
double latitude,
109+
double longitude,
110+
String date,
109111
) async {
110-
// Possible external api call
111-
// apiResponse = await requests.post(weather_api_url, data={'location': arguments['location']})
112-
113-
// Mock up apiResponse
112+
// TODO(developer): Call a real weather API.
113+
// Mock response from the API. In developer live code this would call the external API and return what that API returns.
114114
final apiResponse = {
115-
'location': arguments['location'],
115+
'location': '$latitude, $longitude',
116+
'date': date,
116117
'temperature': 38,
117118
'chancePrecipitation': '56%',
118119
'cloudConditions': 'partly-cloudy',
@@ -121,45 +122,29 @@ class _ChatWidgetState extends State<ChatWidget> {
121122
}
122123

123124
/// Actual function to demonstrate the function calling feature.
124-
final getWeatherTool = FunctionDeclaration(
125-
'fetchCurrentWeather',
125+
final fetchWeatherTool = FunctionDeclaration(
126+
'fetchWeather',
126127
'Get the weather conditions for a specific city on a specific date.',
127128
parameters: {
128-
'location': Schema.string(
129+
'location': Schema.object(
129130
description:
130-
'The city name of the location for which to get the weather.',
131+
'The longitude and latitude of the city for which to get the weather. Must always be a nested object of `longitude` and `latitude`. The values must be floats.',
132+
properties: {
133+
'latitude': Schema.number(
134+
format: 'float',
135+
description:
136+
'A numeric value indicating the latitude of the desired location between -90 and 90',
137+
),
138+
'longitude': Schema.number(
139+
format: 'float',
140+
description:
141+
'A numeric value indicating the longitude of the desired location between -180 and 180',
142+
),
143+
},
131144
),
132-
},
133-
);
134-
135-
/// Sample function to show the usage of Schema, and demo the usage of ToolConfig.
136-
final extractSaleRecordsTool = FunctionDeclaration(
137-
'extractSaleRecords',
138-
'Extract sale records from a document.',
139-
parameters: {
140-
'records': Schema.array(
141-
description: 'A list of sale records',
142-
items: Schema.object(
143-
description: 'Data for a sale record',
144-
properties: {
145-
'id': Schema.integer(description: 'The unique id of the sale.'),
146-
'date': Schema.string(
147-
description:
148-
'Date of the sale, in the format of MMDDYY, e.g., 031023',
149-
),
150-
'totalAmount':
151-
Schema.number(description: 'The total amount of the sale.'),
152-
'customerName': Schema.string(
153-
description:
154-
'The name of the customer, including first name and last name.',
155-
),
156-
'customerContact': Schema.string(
157-
description:
158-
'The phone number of the customer, e.g., 650-123-4567.',
159-
),
160-
},
161-
optionalProperties: ['customerName', 'customerContact'],
162-
),
145+
'date': Schema.string(
146+
description:
147+
'The date for which to get the weather. Date must be in the format: YYYY-MM-DD.',
163148
),
164149
},
165150
);
@@ -529,7 +514,7 @@ class _ChatWidgetState extends State<ChatWidget> {
529514
_loading = true;
530515
});
531516
final functionCallChat = _functionCallModel.startChat();
532-
const prompt = 'What is the weather like in Boston?';
517+
const prompt = 'What is the weather like in Boston on 10/02 this year?';
533518

534519
// Send the message to the generative model.
535520
var response = await functionCallChat.sendMessage(
@@ -540,21 +525,23 @@ class _ChatWidgetState extends State<ChatWidget> {
540525
// When the model response with a function call, invoke the function.
541526
if (functionCalls.isNotEmpty) {
542527
final functionCall = functionCalls.first;
543-
final functionResult = switch (functionCall.name) {
544-
// Forward the structured input data prepared by the model
545-
// to the hypothetical external API.
546-
'fetchCurrentWeather' => await getWeather(functionCall.args),
547-
// Throw an exception if the model attempted to call a function that was
548-
// not declared.
549-
_ => throw UnimplementedError(
550-
'Function not declared to the model: ${functionCall.name}',
551-
)
552-
};
553-
// Send the response to the model so that it can use the result to generate
554-
// text for the user.
555-
response = await functionCallChat.sendMessage(
556-
Content.functionResponse(functionCall.name, functionResult),
557-
);
528+
if (functionCall.name == 'fetchWeather') {
529+
Map<String, dynamic> location =
530+
functionCall.args['location']! as Map<String, dynamic>;
531+
var date = functionCall.args['date']! as String;
532+
var latitude = location['latitude']! as double;
533+
var longitude = location['longitude']! as double;
534+
final functionResult = await fetchWeather(latitude, longitude, date);
535+
// Send the response to the model so that it can use the result to generate
536+
// text for the user.
537+
response = await functionCallChat.sendMessage(
538+
Content.functionResponse(functionCall.name, functionResult),
539+
);
540+
} else {
541+
throw UnimplementedError(
542+
'Function not declared to the model: ${functionCall.name}',
543+
);
544+
}
558545
}
559546
// When the model responds with non-null text content, print it.
560547
if (response.text case final text?) {

0 commit comments

Comments
 (0)