Skip to content
Merged
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
36 changes: 1 addition & 35 deletions packages/firebase_ai/firebase_ai/lib/src/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,13 @@ import 'tool.dart' show Tool, ToolConfig;
/// Response for Count Tokens
final class CountTokensResponse {
// ignore: public_member_api_docs
CountTokensResponse(this.totalTokens,
{this.totalBillableCharacters, this.promptTokensDetails});
CountTokensResponse(this.totalTokens, {this.promptTokensDetails});

/// The number of tokens that the `model` tokenizes the `prompt` into.
///
/// Always non-negative.
final int totalTokens;

/// The number of characters that the `model` could bill at.
///
/// Always non-negative.
@Deprecated(
'Use `totalTokens` instead; Gemini 2.0 series models and newer are always billed by token count.',
)
final int? totalBillableCharacters;

/// List of modalities that were processed in the request input.
final List<ModalityTokenCount>? promptTokensDetails;
}
Expand Down Expand Up @@ -448,12 +439,6 @@ final class GroundingMetadata {
/// page) that the model used to ground its response.
final List<GroundingChunk> groundingChunks;

/// A list of [GroundingSupport]s.
///
/// Keeping for backwards compatibility. See b/477107542.
@Deprecated('Use groundingSupports instead')
List<GroundingSupport> get groundingSupport => groundingSupports;

/// A list of [GroundingSupport]s.
///
/// Each object details how specific segments of the
Expand Down Expand Up @@ -1129,19 +1114,6 @@ enum ThinkingLevel {

/// Config for thinking features.
class ThinkingConfig {
/// Deprecated public constructor of [ThinkingConfig].
///
/// Keep for backwards compatibility.
/// [thinkingBudget] and [thinkingLevel] cannot be set at the same time.
@Deprecated(
'Use ThinkingConfig.withThinkingBudget() or ThinkingConfig.withThinkingLevel() instead.')
ThinkingConfig(
{this.thinkingBudget, this.thinkingLevel, this.includeThoughts})
: assert(
!(thinkingBudget != null && thinkingLevel != null),
'thinkingBudget and thinkingLevel cannot be set at the same time.',
);

// Private constructor
ThinkingConfig._(
{this.thinkingBudget, this.thinkingLevel, this.includeThoughts});
Expand Down Expand Up @@ -1540,11 +1512,6 @@ final class AgentPlatformSerialization implements SerializationStrategy {
}

final totalTokens = jsonObject['totalTokens'] as int;
final totalBillableCharacters = switch (jsonObject) {
{'totalBillableCharacters': final int totalBillableCharacters} =>
totalBillableCharacters,
_ => null,
};
final promptTokensDetails = switch (jsonObject) {
{'promptTokensDetails': final List<Object?> promptTokensDetails} =>
promptTokensDetails.map(_parseModalityTokenCount).toList(),
Expand All @@ -1553,7 +1520,6 @@ final class AgentPlatformSerialization implements SerializationStrategy {

return CountTokensResponse(
totalTokens,
totalBillableCharacters: totalBillableCharacters,
promptTokensDetails: promptTokensDetails,
);
}
Expand Down
54 changes: 2 additions & 52 deletions packages/firebase_ai/firebase_ai/lib/src/firebase_ai.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import 'package:meta/meta.dart';
import '../firebase_ai.dart';
import 'base_model.dart';

const _defaultVertexAILocation = 'us-central1';
const _defaultAgentPlatformLocation = 'global';

/// The entrypoint for generative models.
Expand Down Expand Up @@ -58,47 +57,6 @@ class FirebaseAI extends FirebasePlugin {

static final Map<String, FirebaseAI> _cachedInstances = {};

/// Returns an instance using a specified [FirebaseApp].
///
/// If [app] is not provided, the default Firebase app will be used.
/// If pass in [appCheck], request session will get protected from abusing.
@Deprecated(
'Use agentPlatform() instead. Note that the default location for agentPlatform is now "global" instead of "us-central1"')
static FirebaseAI vertexAI({
FirebaseApp? app,
@Deprecated(
'Passing an explicit instance is deprecated, internal handling is now automatic.')
FirebaseAppCheck? appCheck,
@Deprecated(
'Passing an explicit instance is deprecated, internal handling is now automatic.')
FirebaseAuth? auth,
String? location,
bool? useLimitedUseAppCheckTokens,
}) {
app ??= Firebase.app();
appCheck ??= app.getService<FirebaseAppCheck>();
auth ??= app.getService<FirebaseAuth>();
var instanceKey = '${app.name}::vertexai::$location';

if (_cachedInstances.containsKey(instanceKey)) {
return _cachedInstances[instanceKey]!;
}

location ??= _defaultVertexAILocation;

FirebaseAI newInstance = FirebaseAI._(
app: app,
location: location,
appCheck: appCheck,
auth: auth,
useAgentPlatform: true,
useLimitedUseAppCheckTokens: useLimitedUseAppCheckTokens ?? false,
);
_cachedInstances[instanceKey] = newInstance;

return newInstance;
}

/// Returns an instance using a specified [FirebaseApp].
///
/// If [app] is not provided, the default Firebase app will be used.
Expand Down Expand Up @@ -135,17 +93,9 @@ class FirebaseAI extends FirebasePlugin {
/// If pass in [appCheck], request session will get protected from abusing.
static FirebaseAI googleAI({
FirebaseApp? app,
@Deprecated(
'Passing an explicit instance is deprecated, internal handling is now automatic.')
FirebaseAppCheck? appCheck,
@Deprecated(
'Passing an explicit instance is deprecated, internal handling is now automatic.')
FirebaseAuth? auth,
bool? useLimitedUseAppCheckTokens,
}) {
app ??= Firebase.app();
appCheck ??= app.getService<FirebaseAppCheck>();
auth ??= app.getService<FirebaseAuth>();
var instanceKey = '${app.name}::googleai';

if (_cachedInstances.containsKey(instanceKey)) {
Expand All @@ -155,8 +105,8 @@ class FirebaseAI extends FirebasePlugin {
FirebaseAI newInstance = FirebaseAI._(
app: app,
location: _defaultAgentPlatformLocation,
appCheck: appCheck,
auth: auth,
appCheck: app.getService<FirebaseAppCheck>(),
auth: app.getService<FirebaseAuth>(),
useAgentPlatform: false,
useLimitedUseAppCheckTokens: useLimitedUseAppCheckTokens ?? false,
);
Expand Down
24 changes: 5 additions & 19 deletions packages/firebase_ai/firebase_ai/lib/src/live_api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,6 @@ class LiveServerResponse {
class LiveClientRealtimeInput {
/// Creates a [LiveClientRealtimeInput] instance.
LiveClientRealtimeInput({
@Deprecated('Use audio, video, or text instead') this.mediaChunks,
this.audio,
this.video,
this.text,
Expand All @@ -435,35 +434,31 @@ class LiveClientRealtimeInput {
/// Creates a [LiveClientRealtimeInput] with audio data.
LiveClientRealtimeInput.audio(this.audio)
// ignore: deprecated_member_use_from_same_package
: mediaChunks = null,
video = null,
: video = null,
text = null,
activityStart = null,
activityEnd = null;

/// Creates a [LiveClientRealtimeInput] with video data.
LiveClientRealtimeInput.video(this.video)
// ignore: deprecated_member_use_from_same_package
: mediaChunks = null,
audio = null,
: audio = null,
text = null,
activityStart = null,
activityEnd = null;

/// Creates a [LiveClientRealtimeInput] with text data.
LiveClientRealtimeInput.text(this.text)
// ignore: deprecated_member_use_from_same_package
: mediaChunks = null,
audio = null,
: audio = null,
video = null,
activityStart = null,
activityEnd = null;

/// Creates a [LiveClientRealtimeInput] with activity start signal.
LiveClientRealtimeInput.activityStart()
// ignore: deprecated_member_use_from_same_package
: mediaChunks = null,
audio = null,
: audio = null,
video = null,
text = null,
activityStart = const {},
Expand All @@ -472,17 +467,12 @@ class LiveClientRealtimeInput {
/// Creates a [LiveClientRealtimeInput] with activity end signal.
LiveClientRealtimeInput.activityEnd()
// ignore: deprecated_member_use_from_same_package
: mediaChunks = null,
audio = null,
: audio = null,
video = null,
text = null,
activityStart = null,
activityEnd = const {};

/// The list of media chunks.
@Deprecated('Use audio, video, or text instead')
final List<InlineDataPart>? mediaChunks;

/// Audio data.
final InlineDataPart? audio;

Expand All @@ -501,10 +491,6 @@ class LiveClientRealtimeInput {
// ignore: public_member_api_docs
Map<String, dynamic> toJson() => {
'realtime_input': {
if (mediaChunks != null)
'media_chunks':
// ignore: deprecated_member_use_from_same_package
mediaChunks?.map((e) => e.toMediaChunkJson()).toList(),
if (audio != null) 'audio': audio!.toMediaChunkJson(),
if (video != null) 'video': video!.toMediaChunkJson(),
if (text != null) 'text': text,
Expand Down
44 changes: 0 additions & 44 deletions packages/firebase_ai/firebase_ai/lib/src/live_session.dart
Original file line number Diff line number Diff line change
Expand Up @@ -323,50 +323,6 @@ class LiveSession {
_ws.sink.add(clientJson);
}

/// Sends realtime input (media chunks) to the server.
///
/// [mediaChunks]: The list of media chunks to send.
@Deprecated(
'Use sendAudioRealtime, sendVideoRealtime, or sendTextRealtime instead')
Future<void> sendMediaChunks({
required List<InlineDataPart> mediaChunks,
}) async {
_checkWsStatus();
var clientMessage = LiveClientRealtimeInput(mediaChunks: mediaChunks);
var clientJson = jsonEncode(clientMessage.toJson());
_ws.sink.add(clientJson);
}

/// Starts streaming media chunks to the server from the provided [mediaChunkStream].
///
/// This function asynchronously processes each [InlineDataPart] from the given
/// [mediaChunkStream] and sends it to the server via the WebSocket connection.
///
/// Parameters:
/// - [mediaChunkStream]: The stream of [InlineDataPart] objects to send to the server.
@Deprecated('Use sendAudio, sendVideo, or sendText with a stream instead')
Future<void> sendMediaStream(Stream<InlineDataPart> mediaChunkStream) async {
_checkWsStatus();

try {
await for (final chunk in mediaChunkStream) {
await _sendMediaChunk(chunk);
}
} catch (e) {
throw FirebaseAISdkException(e.toString());
} finally {
log('Stream processing completed.');
}
}

Future<void> _sendMediaChunk(InlineDataPart chunk) async {
var clientMessage = LiveClientRealtimeInput(
// ignore: deprecated_member_use_from_same_package
mediaChunks: [chunk]); // Create a list with the single chunk
var clientJson = jsonEncode(clientMessage.toJson());
_ws.sink.add(clientJson);
}

/// Receives messages from the server.
///
/// Returns a [Stream] of [LiveServerResponse] objects representing the
Expand Down
25 changes: 9 additions & 16 deletions packages/firebase_ai/firebase_ai/test/api_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ void main() {

test('GenerationConfig toJson with all fields', () {
final schema = Schema.object(properties: {});
final thinkingConfig = ThinkingConfig(thinkingBudget: 100);
final thinkingConfig = ThinkingConfig.withThinkingBudget(100);
const imageConfig = ImageConfig(
aspectRatio: ImageAspectRatio.square1x1, imageSize: ImageSize.size1K);
final config = GenerationConfig(
Expand Down Expand Up @@ -629,7 +629,7 @@ void main() {

group('ThinkingConfig', () {
test('toJson with thinkingBudget set', () {
final config = ThinkingConfig(thinkingBudget: 123);
final config = ThinkingConfig.withThinkingBudget(123);

expect(config.toJson(), {'thinkingBudget': 123});
});
Expand All @@ -643,37 +643,39 @@ void main() {
});

test('toJson with includeThoughts set', () {
final config = ThinkingConfig(includeThoughts: true);
final config =
ThinkingConfig.withThinkingBudget(null, includeThoughts: true);

expect(config.toJson(), {'includeThoughts': true});
});

test('toJson with thinkingBudget and thinkingLevel null', () {
final config = ThinkingConfig();
final config = ThinkingConfig.withThinkingBudget(null);

// Expecting the key to be absent or the value to be explicitly null,
// depending on implementation. Current implementation omits the key.
expect(config.toJson(), {});
});

test('constructor initializes thinkingBudget', () {
final config = ThinkingConfig(thinkingBudget: 456);
final config = ThinkingConfig.withThinkingBudget(456);

expect(config.thinkingBudget, 456);
expect(config.thinkingLevel, isNull);
expect(config.includeThoughts, isNull);
});

test('constructor initializes thinkingLevel', () {
final config = ThinkingConfig(thinkingLevel: ThinkingLevel.low);
final config = ThinkingConfig.withThinkingLevel(ThinkingLevel.low);

expect(config.thinkingBudget, isNull);
expect(config.thinkingLevel, ThinkingLevel.low);
expect(config.includeThoughts, isNull);
});

test('constructor initializes includeThoughts', () {
final config = ThinkingConfig(includeThoughts: true);
final config =
ThinkingConfig.withThinkingLevel(null, includeThoughts: true);

expect(config.thinkingBudget, isNull);
expect(config.thinkingLevel, isNull);
Expand All @@ -697,15 +699,6 @@ void main() {
expect(config.thinkingLevel, ThinkingLevel.medium);
expect(config.includeThoughts, isTrue);
});

test(
'deprecated constructor throws AssertionError if both thinkingBudget and thinkingLevel are provided',
() {
expect(
() => ThinkingConfig(
thinkingBudget: 100, thinkingLevel: ThinkingLevel.high),
throwsA(isA<AssertionError>()));
});
});

group('Parsing Functions', () {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -573,7 +573,6 @@ void main() {
expect(response.totalTokens, 123);
// Developer API does not return other fields
// ignore: deprecated_member_use_from_same_package
expect(response.totalBillableCharacters, isNull);
expect(response.promptTokensDetails, isNull);
});

Expand Down
Loading
Loading