Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,12 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
late GenerativeModel _functionCallModel;
late GenerativeModel _autoFunctionCallModel;
late GenerativeModel _parallelAutoFunctionCallModel;
late GenerativeModel _complexSchemaModel;
late GenerativeModel _refDefJsonSchemaModel;
late GenerativeModel _codeExecutionModel;
late final AutoFunctionDeclaration _autoFetchWeatherTool;
late final AutoFunctionDeclaration _autoPlanVacationTool;
late final AutoFunctionDeclaration _autoProcessTransactionTool;
final List<MessageData> _messages = <MessageData>[];
bool _loading = false;
bool _enableThinking = false;
Expand Down Expand Up @@ -113,6 +117,85 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
return getRestaurantMenu(restaurantName);
},
);
_autoPlanVacationTool = AutoFunctionDeclaration(
name: 'planVacation',
description:
'Plans a complex vacation itinerary combining flights, hotels, and activities.',
parameters: {
'destination':
Schema.string(description: 'The city or country to travel to.'),
'travelers': Schema.integer(
description: 'Number of travelers.',
minimum: 1,
maximum: 10,
),
'travelClass': Schema.enumString(
enumValues: ['ECONOMY', 'BUSINESS', 'FIRST'],
description: 'The preferred travel class.',
),
'budget':
Schema.number(description: 'Total budget for the trip in USD.'),
'activities': Schema.array(
items: Schema.string(),
description: 'A list of preferred activities.',
minItems: 1,
),
'accommodations': Schema.object(
description: 'Hotel preferences.',
properties: {
'hotelType': Schema.string(),
'stars': Schema.integer(minimum: 1, maximum: 5),
'amenities': Schema.array(items: Schema.string()),
},
optionalProperties: ['amenities'],
),
},
callable: (args) async {
return {
'status': 'SUCCESS',
'itineraryId': 'TRIP-98765',
'destination': args['destination'],
'estimatedCost': 3500.0,
'message': 'Vacation planned successfully!',
};
},
);
_autoProcessTransactionTool = AutoFunctionDeclaration(
name: 'processTransactions',
description:
'Processes a list of financial transactions using a predefined transaction model reference.',
parameters: {
'transactionsBlock': JSONSchema.object(
description: 'A block containing a list of transactions.',
properties: {
'transactionsList': JSONSchema.array(
items: JSONSchema.ref(
r'#/properties/transactionsBlock/$defs/transactionDef',
),
),
},
defs: {
'transactionDef': JSONSchema.object(
properties: {
'amount': JSONSchema.number(),
'transactionId': JSONSchema.integer(),
'currency': JSONSchema.string(),
},
),
},
),
},
callable: (args) async {
final block = args['transactionsBlock'] as Map<String, dynamic>?;
final list = block?['transactionsList'] as List<dynamic>?;
return {
'status': 'SUCCESS',
'transactionsProcessed': list?.length ?? 0,
'message':
'Transactions processed successfully using the reference schema!',
};
},
);
_initializeModel();
}

Expand Down Expand Up @@ -202,6 +285,20 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
Tool.codeExecution(),
],
);
_complexSchemaModel = aiClient.generativeModel(
model: 'gemini-2.5-flash',
generationConfig: generationConfig,
tools: [
Tool.functionDeclarations([_autoPlanVacationTool]),
],
);
_refDefJsonSchemaModel = aiClient.generativeModel(
model: 'gemini-2.5-flash',
generationConfig: generationConfig,
tools: [
Tool.functionDeclarations([_autoProcessTransactionTool]),
],
);
}

// This is a hypothetical API to return a fake weather data collection for
Expand Down Expand Up @@ -375,6 +472,28 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
),
],
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: ElevatedButton(
onPressed: !_loading
? _testComplexSchemaAutoFunctionCalling
: null,
child: const Text('Complex Schema Auto FC'),
),
),
const SizedBox(width: 8),
Expanded(
child: ElevatedButton(
onPressed: !_loading
? _testRefDefJsonSchemaAutoFunctionCalling
: null,
child: const Text('Ref Def JSON Schema Auto FC'),
),
),
],
),
],
),
),
Expand Down Expand Up @@ -608,6 +727,56 @@ class _FunctionCallingPageState extends State<FunctionCallingPage> {
});
}

Future<void> _testComplexSchemaAutoFunctionCalling() async {
await _runTest(() async {
final chat = _complexSchemaModel.startChat();
const prompt =
'I want to plan a vacation to Paris for 2 people. We want to fly Business class, our budget is 5500 USD. We want to do wine tasting and museum tours. We prefer a 4-star boutique hotel with free breakfast.';

_messages.add(MessageData(text: prompt, fromUser: true));
setState(() {});

final response = await chat.sendMessage(Content.text(prompt));

final thought = response.thoughtSummary;
if (thought != null) {
_messages
.add(MessageData(text: thought, fromUser: false, isThought: true));
}

if (response.text case final text?) {
_messages.add(MessageData(text: text));
} else {
_messages.add(MessageData(text: 'No text response from model.'));
}
});
}

Future<void> _testRefDefJsonSchemaAutoFunctionCalling() async {
await _runTest(() async {
final chat = _refDefJsonSchemaModel.startChat();
const prompt =
r'Process two transactions. The first is $50.00 in USD (ID 98765) and the second is €30.00 in EUR (ID 98766).';

_messages.add(MessageData(text: prompt, fromUser: true));
setState(() {});

final response = await chat.sendMessage(Content.text(prompt));

final thought = response.thoughtSummary;
if (thought != null) {
_messages
.add(MessageData(text: thought, fromUser: false, isThought: true));
}

if (response.text case final text?) {
_messages.add(MessageData(text: text));
} else {
_messages.add(MessageData(text: 'No text response from model.'));
}
});
}

void _showError(String message) {
showDialog<void>(
context: context,
Expand Down
2 changes: 1 addition & 1 deletion packages/firebase_ai/firebase_ai/lib/firebase_ai.dart
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export 'src/live_api.dart'
GoingAwayNotice,
Transcription;
export 'src/live_session.dart' show LiveSession;
export 'src/schema.dart' show Schema, SchemaType;
export 'src/schema.dart' show JSONSchema, Schema, SchemaType;

export 'src/tool.dart'
show
Expand Down
Loading
Loading