From 1c34637fd8032935b825fa9d21489fb759f6d3e1 Mon Sep 17 00:00:00 2001 From: Nate Bosch Date: Wed, 10 Apr 2024 09:25:45 -0700 Subject: [PATCH] Add support for referring to uploaded files (#115) Adding only the support to refer to files which for now need to be uploaded separately. - Add a `FilePart` subclass of `Part` with a Uri argument for a file uploaded to the google AI file service. - Change an exhaustive switch on a `Part` to an if/else to avoid needing to update for further new subtypes of `Part`. - Add the new classes to an exhaustive switch in a testing utility. --- pkgs/google_generative_ai/CHANGELOG.md | 4 +++- .../lib/google_generative_ai.dart | 2 +- pkgs/google_generative_ai/lib/src/chat.dart | 17 ++++++++--------- pkgs/google_generative_ai/lib/src/content.dart | 13 +++++++++++++ pkgs/google_generative_ai/lib/src/version.dart | 2 +- pkgs/google_generative_ai/pubspec.yaml | 2 +- .../test/utils/matchers.dart | 4 ++++ 7 files changed, 31 insertions(+), 13 deletions(-) diff --git a/pkgs/google_generative_ai/CHANGELOG.md b/pkgs/google_generative_ai/CHANGELOG.md index 88800ee..23bab4c 100644 --- a/pkgs/google_generative_ai/CHANGELOG.md +++ b/pkgs/google_generative_ai/CHANGELOG.md @@ -1,7 +1,9 @@ -## 0.2.4-wip +## 0.3.0-wip - Allow specifying an API version in a `requestOptions` argument when constructing a model. +- Add support for referring to uploaded files in request contents. +- **Breaking** Added a new subclass `FilePart` of the sealed class `Part`. ## 0.2.3 diff --git a/pkgs/google_generative_ai/lib/google_generative_ai.dart b/pkgs/google_generative_ai/lib/google_generative_ai.dart index b0bdefb..812e2d5 100644 --- a/pkgs/google_generative_ai/lib/google_generative_ai.dart +++ b/pkgs/google_generative_ai/lib/google_generative_ai.dart @@ -59,7 +59,7 @@ export 'src/api.dart' SafetySetting, TaskType; export 'src/chat.dart' show ChatSession, StartChatExtension; -export 'src/content.dart' show Content, DataPart, Part, TextPart; +export 'src/content.dart' show Content, DataPart, FilePart, Part, TextPart; export 'src/error.dart' show GenerativeAIException, diff --git a/pkgs/google_generative_ai/lib/src/chat.dart b/pkgs/google_generative_ai/lib/src/chat.dart index a08acd8..8953fa2 100644 --- a/pkgs/google_generative_ai/lib/src/chat.dart +++ b/pkgs/google_generative_ai/lib/src/chat.dart @@ -151,15 +151,14 @@ final class ChatSession { for (final content in contents) { for (final part in content.parts) { - switch (part) { - case TextPart(:final text): - if (text.isNotEmpty) { - previousText = textBuffer.isEmpty ? part : null; - textBuffer.write(text); - } - case DataPart(): - addBufferedText(); - parts.add(part); + if (part case TextPart(:final text)) { + if (text.isNotEmpty) { + previousText = textBuffer.isEmpty ? part : null; + textBuffer.write(text); + } + } else { + addBufferedText(); + parts.add(part); } } } diff --git a/pkgs/google_generative_ai/lib/src/content.dart b/pkgs/google_generative_ai/lib/src/content.dart index 320dd21..9fdda15 100644 --- a/pkgs/google_generative_ai/lib/src/content.dart +++ b/pkgs/google_generative_ai/lib/src/content.dart @@ -75,6 +75,7 @@ final class TextPart implements Part { Object toJson() => {'text': text}; } +/// A [Part] with the byte content of a file. final class DataPart implements Part { final String mimeType; final Uint8List bytes; @@ -84,3 +85,15 @@ final class DataPart implements Part { 'inlineData': {'data': base64Encode(bytes), 'mimeType': mimeType} }; } + +/// A [Part] referring to an uploaded file. +/// +/// The [uri] should refer to a file uploaded to the Google AI File Service API. +final class FilePart implements Part { + final Uri uri; + FilePart(this.uri); + @override + Object toJson() => { + 'file_data': {'file_uri': '$uri'} + }; +} diff --git a/pkgs/google_generative_ai/lib/src/version.dart b/pkgs/google_generative_ai/lib/src/version.dart index e59804c..f247f49 100644 --- a/pkgs/google_generative_ai/lib/src/version.dart +++ b/pkgs/google_generative_ai/lib/src/version.dart @@ -12,4 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -const packageVersion = '0.2.4-wip'; +const packageVersion = '0.3.0-wip'; diff --git a/pkgs/google_generative_ai/pubspec.yaml b/pkgs/google_generative_ai/pubspec.yaml index d8627d3..bc8fcba 100644 --- a/pkgs/google_generative_ai/pubspec.yaml +++ b/pkgs/google_generative_ai/pubspec.yaml @@ -1,5 +1,5 @@ name: google_generative_ai -version: 0.2.4-wip +version: 0.3.0-wip description: >- The Google AI Dart SDK enables developers to use Google's state-of-the-art generative AI models (like Gemini). diff --git a/pkgs/google_generative_ai/test/utils/matchers.dart b/pkgs/google_generative_ai/test/utils/matchers.dart index fc72e2f..d739649 100644 --- a/pkgs/google_generative_ai/test/utils/matchers.dart +++ b/pkgs/google_generative_ai/test/utils/matchers.dart @@ -26,6 +26,10 @@ Matcher matchesPart(Part part) => switch (part) { // TODO: When updating min SDK remove ignore. // ignore: unused_result, implementation bug .having((p) => p.bytes, 'bytes', bytes), + FilePart(uri: final uri) => isA() + // TODO: When updating min SDK remove ignore. + // ignore: unused_result, implementation bug + .having((p) => p.uri, 'uri', uri), }; Matcher matchesContent(Content content) => isA()