├── .gitattributes
├── .github
├── dependabot.yaml
├── labeler.yml
└── workflows
│ ├── flutter_sample.yml
│ ├── google_generative_ai.yml
│ └── samples.yml
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── pkgs
└── google_generative_ai
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── analysis_options.yaml
│ ├── lib
│ ├── google_generative_ai.dart
│ └── src
│ │ ├── api.dart
│ │ ├── chat.dart
│ │ ├── client.dart
│ │ ├── content.dart
│ │ ├── error.dart
│ │ ├── function_calling.dart
│ │ ├── model.dart
│ │ ├── utils
│ │ └── mutex.dart
│ │ ├── version.dart
│ │ └── vertex_hooks.dart
│ ├── pubspec.yaml
│ ├── test
│ ├── chat_test.dart
│ ├── generative_model_test.dart
│ ├── http_api_client_test.dart
│ ├── response_parsing_test.dart
│ └── utils
│ │ ├── matchers.dart
│ │ └── stub_client.dart
│ └── tool
│ └── validate_version.dart
└── samples
├── dart
├── README.md
├── analysis_options.yaml
├── bin
│ ├── advanced_chat.dart
│ ├── advanced_text.dart
│ ├── advanced_text_and_image.dart
│ ├── chat.dart
│ ├── code_execution.dart
│ ├── configure_model_parameters.dart
│ ├── controlled_generation.dart
│ ├── count_tokens.dart
│ ├── function_calling.dart
│ ├── guessing_game.dart
│ ├── safety_settings.dart
│ ├── simple_chat.dart
│ ├── simple_config.dart
│ ├── simple_embedding.dart
│ ├── simple_text.dart
│ ├── simple_text_and_image.dart
│ ├── system_instructions.dart
│ ├── text_generation.dart
│ └── util
│ │ └── resource.dart
├── pubspec.yaml
└── resources
│ ├── cat.jpg
│ ├── firefighter.jpg
│ ├── jetpack.jpg
│ ├── organ.jpg
│ ├── piranha.jpg
│ └── scones.jpg
└── flutter_app
├── .gitignore
├── .metadata
├── README.md
├── analysis_options.yaml
├── android
├── .gitignore
├── app
│ ├── build.gradle
│ └── src
│ │ ├── debug
│ │ └── AndroidManifest.xml
│ │ ├── main
│ │ ├── AndroidManifest.xml
│ │ ├── kotlin
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── flutter_app
│ │ │ │ └── MainActivity.kt
│ │ └── res
│ │ │ ├── drawable-v21
│ │ │ └── launch_background.xml
│ │ │ ├── drawable
│ │ │ └── launch_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ └── ic_launcher.png
│ │ │ ├── values-night
│ │ │ └── styles.xml
│ │ │ └── values
│ │ │ └── styles.xml
│ │ └── profile
│ │ └── AndroidManifest.xml
├── build.gradle
├── gradle.properties
├── gradle
│ └── wrapper
│ │ └── gradle-wrapper.properties
└── settings.gradle
├── assets
└── images
│ ├── cat.jpg
│ └── scones.jpg
├── ios
├── .gitignore
├── Flutter
│ ├── AppFrameworkInfo.plist
│ ├── Debug.xcconfig
│ └── Release.xcconfig
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ └── WorkspaceSettings.xcsettings
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
├── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── Icon-App-1024x1024@1x.png
│ │ │ ├── Icon-App-20x20@1x.png
│ │ │ ├── Icon-App-20x20@2x.png
│ │ │ ├── Icon-App-20x20@3x.png
│ │ │ ├── Icon-App-29x29@1x.png
│ │ │ ├── Icon-App-29x29@2x.png
│ │ │ ├── Icon-App-29x29@3x.png
│ │ │ ├── Icon-App-40x40@1x.png
│ │ │ ├── Icon-App-40x40@2x.png
│ │ │ ├── Icon-App-40x40@3x.png
│ │ │ ├── Icon-App-60x60@2x.png
│ │ │ ├── Icon-App-60x60@3x.png
│ │ │ ├── Icon-App-76x76@1x.png
│ │ │ ├── Icon-App-76x76@2x.png
│ │ │ └── Icon-App-83.5x83.5@2x.png
│ │ └── LaunchImage.imageset
│ │ │ ├── Contents.json
│ │ │ ├── LaunchImage.png
│ │ │ ├── LaunchImage@2x.png
│ │ │ ├── LaunchImage@3x.png
│ │ │ └── README.md
│ ├── Base.lproj
│ │ ├── LaunchScreen.storyboard
│ │ └── Main.storyboard
│ ├── Info.plist
│ └── Runner-Bridging-Header.h
└── RunnerTests
│ └── RunnerTests.swift
├── lib
└── main.dart
├── macos
├── .gitignore
├── Flutter
│ ├── Flutter-Debug.xcconfig
│ ├── Flutter-Release.xcconfig
│ └── GeneratedPluginRegistrant.swift
├── Runner.xcodeproj
│ ├── project.pbxproj
│ ├── project.xcworkspace
│ │ └── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ └── xcshareddata
│ │ └── xcschemes
│ │ └── Runner.xcscheme
├── Runner.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── Runner
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ └── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── app_icon_1024.png
│ │ │ ├── app_icon_128.png
│ │ │ ├── app_icon_16.png
│ │ │ ├── app_icon_256.png
│ │ │ ├── app_icon_32.png
│ │ │ ├── app_icon_512.png
│ │ │ └── app_icon_64.png
│ ├── Base.lproj
│ │ └── MainMenu.xib
│ ├── Configs
│ │ ├── AppInfo.xcconfig
│ │ ├── Debug.xcconfig
│ │ ├── Release.xcconfig
│ │ └── Warnings.xcconfig
│ ├── DebugProfile.entitlements
│ ├── Info.plist
│ ├── MainFlutterWindow.swift
│ └── Release.entitlements
└── RunnerTests
│ └── RunnerTests.swift
├── pubspec.yaml
├── web
├── favicon.png
├── icons
│ ├── Icon-192.png
│ ├── Icon-512.png
│ ├── Icon-maskable-192.png
│ └── Icon-maskable-512.png
├── index.html
└── manifest.json
└── windows
├── .gitignore
├── CMakeLists.txt
├── flutter
└── CMakeLists.txt
└── runner
├── CMakeLists.txt
├── Runner.rc
├── flutter_window.cpp
├── flutter_window.h
├── main.cpp
├── resource.h
├── resources
└── app_icon.ico
├── runner.exe.manifest
├── utils.cpp
├── utils.h
├── win32_window.cpp
└── win32_window.h
/.gitattributes:
--------------------------------------------------------------------------------
1 | samples/*/.metadata linguist-generated=true
2 | samples/**/Flutter/GeneratedPluginRegistrant.swift linguist-generated=true
3 | samples/**/Runner.xcodeproj/ linguist-generated=true
4 | samples/**/Runner.xcworkspace/ linguist-generated=true
5 | samples/**/flutter/CMakeLists.txt linguist-generated=true
6 | samples/**/flutter/generated_* linguist-generated=true
7 |
--------------------------------------------------------------------------------
/.github/dependabot.yaml:
--------------------------------------------------------------------------------
1 | # Dependabot configuration file; see
2 | # https://docs.github.com/en/code-security/dependabot/dependabot-version-updates
3 |
4 | version: 2
5 |
6 | updates:
7 | - package-ecosystem: github-actions
8 | directory: /
9 | schedule:
10 | interval: monthly
11 |
--------------------------------------------------------------------------------
/.github/labeler.yml:
--------------------------------------------------------------------------------
1 | # Configuration for .github/workflows/pull_request_label.yml.
2 |
3 | 'type-infra':
4 | - '.github/**'
5 |
6 | 'package:google_generative_ai':
7 | - 'pkgs/google_generative_ai/**'
8 |
--------------------------------------------------------------------------------
/.github/workflows/flutter_sample.yml:
--------------------------------------------------------------------------------
1 | name: samples_flutter
2 |
3 | permissions: read-all
4 |
5 | on:
6 | push:
7 | branches: [ main ]
8 | paths:
9 | - '.github/workflows/flutter_sample.yml'
10 | - 'pkgs/google_generative_ai/**'
11 | - 'samples/flutter_app/**'
12 | pull_request:
13 | branches: [ main ]
14 | paths:
15 | - '.github/workflows/flutter_sample.yml'
16 | - 'pkgs/google_generative_ai/**'
17 | - 'samples/flutter_app/**'
18 | schedule:
19 | - cron: '0 0 * * 0' # weekly
20 |
21 | jobs:
22 | validate:
23 | runs-on: ubuntu-latest
24 | defaults:
25 | run:
26 | working-directory: samples/flutter_app/
27 | steps:
28 | - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
29 | - uses: subosito/flutter-action@44ac965b96f18d999802d4b807e3256d5a3f9fa1
30 | with:
31 | channel: stable
32 | - run: flutter pub get
33 | - run: flutter analyze --fatal-infos
34 | - run: dart format --set-exit-if-changed .
35 |
--------------------------------------------------------------------------------
/.github/workflows/google_generative_ai.yml:
--------------------------------------------------------------------------------
1 | name: package:google_generative_ai
2 |
3 | permissions: read-all
4 |
5 | on:
6 | pull_request:
7 | branches: [ main ]
8 | paths:
9 | - '.github/workflows/google_generative_ai.yml'
10 | - 'pkgs/google_generative_ai/**'
11 | push:
12 | branches: [ main ]
13 | paths:
14 | - '.github/workflows/google_generative_ai.yml'
15 | - 'pkgs/google_generative_ai/**'
16 | schedule:
17 | - cron: '0 0 * * 0' # weekly
18 |
19 | jobs:
20 | build:
21 | runs-on: ubuntu-latest
22 | defaults:
23 | run:
24 | working-directory: pkgs/google_generative_ai
25 | strategy:
26 | fail-fast: false
27 | matrix:
28 | sdk: ['3.1', stable, dev]
29 | include:
30 | - sdk: stable
31 | run-tests: true
32 | steps:
33 | - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
34 | - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30
35 | with:
36 | sdk: ${{ matrix.sdk }}
37 |
38 | - run: dart pub get
39 |
40 | - run: dart analyze --fatal-infos
41 |
42 | # Make sure that the package version in lib/src/version.dart is kept up-to-date.
43 | - run: dart tool/validate_version.dart
44 |
45 | - run: dart format --output=none --set-exit-if-changed .
46 | if: ${{matrix.run-tests}}
47 |
48 | - run: dart test
49 | if: ${{matrix.run-tests}}
50 |
51 | - run: dart test --platform chrome
52 | if: ${{matrix.run-tests}}
53 |
--------------------------------------------------------------------------------
/.github/workflows/samples.yml:
--------------------------------------------------------------------------------
1 | name: samples_dart
2 |
3 | permissions: read-all
4 |
5 | on:
6 | pull_request:
7 | branches: [ main ]
8 | paths:
9 | - '.github/workflows/samples.yml'
10 | - 'pkgs/google_generative_ai/**'
11 | - 'samples/dart/**'
12 | push:
13 | branches: [ main ]
14 | paths:
15 | - '.github/workflows/samples.yml'
16 | - 'pkgs/google_generative_ai/**'
17 | - 'samples/dart/**'
18 | schedule:
19 | - cron: '0 0 * * 0' # weekly
20 |
21 | jobs:
22 | build:
23 | runs-on: ubuntu-latest
24 | defaults:
25 | run:
26 | working-directory: samples/dart
27 | strategy:
28 | fail-fast: false
29 | matrix:
30 | sdk: [stable, dev]
31 | include:
32 | - sdk: stable
33 | check-formatting: true
34 | steps:
35 | - uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29
36 | - uses: dart-lang/setup-dart@f0ead981b4d9a35b37f30d36160575d60931ec30
37 | with:
38 | sdk: ${{ matrix.sdk }}
39 |
40 | - run: dart pub get
41 |
42 | - run: dart analyze --fatal-infos
43 |
44 | - run: dart format --output=none --set-exit-if-changed .
45 | if: ${{matrix.check-formatting}}
46 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .atom/
3 | .idea/
4 | .vscode/*
5 |
6 | # Dart project
7 | **/doc/api/
8 | .dart_tool/
9 | build/
10 | pubspec.lock
11 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # How to Contribute
2 |
3 | We would love to accept your patches and contributions to this project.
4 |
5 | ## Before you begin
6 |
7 | ### Sign our Contributor License Agreement
8 |
9 | Contributions to this project must be accompanied by a
10 | [Contributor License Agreement](https://cla.developers.google.com/about) (CLA).
11 | You (or your employer) retain the copyright to your contribution; this simply
12 | gives us permission to use and redistribute your contributions as part of the
13 | project.
14 |
15 | If you or your current employer have already signed the Google CLA (even if it
16 | was for a different project), you probably don't need to do it again.
17 |
18 | Visit to see your current agreements or to
19 | sign a new one.
20 |
21 | ### Review our Community Guidelines
22 |
23 | This project follows [Google's Open Source Community
24 | Guidelines](https://opensource.google/conduct/).
25 |
26 | ## Contribution process
27 |
28 | ### Code Reviews
29 |
30 | All submissions, including submissions by project members, require review. We
31 | use [GitHub pull requests](https://docs.github.com/articles/about-pull-requests)
32 | for this purpose.
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Deprecated] Google AI Dart SDK for the Gemini API
2 |
3 | With Gemini 2.0, we took the chance to create a unified SDK for mobile
4 | developers who want to use Google's GenAI models (Gemini, Veo, Imagen, etc). As
5 | part of that process, we took all of the feedback from this SDK and what
6 | developers like about other SDKs in the ecosystem to directly work with the
7 | [Firebase SDK](https://firebase.google.com/docs/vertex-ai). We don't plan to add
8 | anything to this SDK or make any further changes. We know how disruptive an SDK
9 | change can be and don't take this change lightly, but our goal is to create an
10 | extremely simple and clear path for developers to build with our models so it
11 | felt necessary to make this change.
12 |
13 | Thank you for building with Gemini and
14 | [let us know](https://discuss.ai.google.dev/c/gemini-api/4) if you need any
15 | help!
16 |
--------------------------------------------------------------------------------
/pkgs/google_generative_ai/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## 0.4.7
2 |
3 | - Update the README.md to indicate that this package is deprecated; using the
4 | [Firebase SDK](https://firebase.google.com/docs/vertex-ai) is the preferred
5 | path forward.
6 |
7 | ## 0.4.6
8 |
9 | - Throw a more relevant exception for server error HTTP responses.
10 |
11 | ## 0.4.5
12 |
13 | - Add support for model side Code Execution. Enable code execution by
14 | configuring `Tools` with a `codeExecution` argument.
15 | - Use a default role `'model'` when a chat response comes back with no role.
16 |
17 | ## 0.4.4
18 |
19 | - Allow the Vertex format for citation metadata - read either `citationSources`
20 | or `citations` keys, whichever exists. Fixes a `FormatException` when parsing
21 | vertex results with citations.
22 |
23 | ## 0.4.3
24 |
25 | - Internal changes to enable reuse in the Vertex SDK. No user visible changes.
26 |
27 | ## 0.4.2
28 |
29 | - Add support for `GenerationConfig.responseSchema` for constraining JSON mime
30 | type output formats.
31 | - Require Dart 3.1.
32 |
33 | ## 0.4.1
34 |
35 | - Concatenate multiple `TextPart` into the `text` String in case the model
36 | replies with more than one part.
37 | - Fix handling of `format` argument to `Schema.number` and `Schema.integer`.
38 | - Export `UsageMetadata`.
39 | - Include the full `GenerateContentRequest` (previously omitted
40 | `safetySettings`, `generationConfig`, `tools`, `toolConfig`, and
41 | `systemInstruction`) in `countTokens` requests. This aligns the token count
42 | with the token count the backend will see in practice for a
43 | `generateContent` request.
44 | - Add a `text` getter on `Candidate` to make it easer to retrieve the text from
45 | candidates other than the first in a response.
46 |
47 | ## 0.4.0
48 |
49 | - Add support for parsing Vertex AI specific fields in `CountTokensResponse`.
50 | - Add named constructors on `Schema` for each value type.
51 | - Add `GenerationConfig.responseMimeType` which supports setting
52 | `'application/json'` to force the model to reply with JSON parseable output.
53 | - Add `outputDimensionality` argument support for `embedContent` and
54 | `batchEmbedContent`.
55 | - Add `Content.functionResponses` utility to reply to multiple function calls in
56 | parallel.
57 | - **Breaking** The `Part` class is no longer `sealed`. Exhaustive switches over
58 | a `Part` instance will need to add a wildcard case.
59 |
60 | ## 0.3.3
61 |
62 | - Add support for parsing the `usageMetadata` field in `GenerateContentResponse`
63 | messages.
64 |
65 | ## 0.3.2
66 |
67 | - Use API version `v1beta` by default.
68 | - Add note to README warning about leaking API keys.
69 |
70 | ## 0.3.1
71 |
72 | - Add support on content generating methods for overriding "tools" passed when
73 | the generative model was instantiated.
74 | - Add support for forcing the model to use or not use function calls to generate
75 | content.
76 |
77 | ## 0.3.0
78 |
79 | - Allow specifying an API version in a `requestOptions` argument when
80 | constructing a model.
81 | - Add support for referring to uploaded files in request contents.
82 | - Add support for passing tools with functions the model may call while
83 | generating responses.
84 | - Add support for passing a system instruction when creating the model.
85 | - **Breaking** Added new subclasses `FilePart`, `FunctionCall`, and
86 | `FunctionResponse` of the sealed class `Part`.
87 |
88 | ## 0.2.3
89 |
90 | - Update the package version that is sent with the HTTP client name.
91 | - Throw more actionable error objects than `FormatException` for errors. Errors
92 | were previously only correctly parsed in `generateContent` calls.
93 | - Add support for tuned models.
94 | - Add support for `batchEmbedContents` calls.
95 |
96 | ## 0.2.2
97 |
98 | - Remove usage of new SDK features - support older SDKs 3.0 and above.
99 |
100 | ## 0.2.1
101 |
102 | - Fix an issue parsing `generateContent()` responses that do not include content
103 | (this can occur for some `finishReason`s).
104 | - Fix an issue parsing `generateContent()` responses that include citation
105 | sources with unpopulated fields
106 | - Add link to ai.google.dev docs.
107 |
108 | ## 0.2.0
109 |
110 | - **Breaking** `HarmCategory.unknown` renamed to `unspecified`. Removed unused
111 | `unknown` values in the `HarmProbability` and `FinishReason` enums.
112 | - Add additional API documentation.
113 | - Update the getting started instructions in the readme.
114 |
115 | ## 0.1.0
116 |
117 | - Initial release.
118 |
--------------------------------------------------------------------------------
/pkgs/google_generative_ai/README.md:
--------------------------------------------------------------------------------
1 | # [Deprecated] Google AI Dart SDK for the Gemini API
2 |
3 | With Gemini 2.0, we took the chance to create a unified SDK for mobile
4 | developers who want to use Google's GenAI models (Gemini, Veo, Imagen, etc). As
5 | part of that process, we took all of the feedback from this SDK and what
6 | developers like about other SDKs in the ecosystem to directly work with the
7 | [Firebase SDK](https://firebase.google.com/docs/vertex-ai). We don't plan to add
8 | anything to this SDK or make any further changes. We know how disruptive an SDK
9 | change can be and don't take this change lightly, but our goal is to create an
10 | extremely simple and clear path for developers to build with our models so it
11 | felt necessary to make this change.
12 |
13 | Thank you for building with Gemini and
14 | [let us know](https://discuss.ai.google.dev/c/gemini-api/4) if you need any
15 | help!
16 |
--------------------------------------------------------------------------------
/pkgs/google_generative_ai/analysis_options.yaml:
--------------------------------------------------------------------------------
1 | include: package:lints/recommended.yaml
2 |
3 | analyzer:
4 | language:
5 | strict-casts: true
6 | strict-inference: true
7 | strict-raw-types: true
8 |
9 | linter:
10 | rules:
11 | # consistency
12 | - directives_ordering
13 | - omit_local_variable_types
14 | - prefer_final_locals
15 | - prefer_final_in_for_each
16 | - prefer_relative_imports
17 | - prefer_single_quotes
18 | - sort_pub_dependencies
19 | - unnecessary_library_directive
20 |
21 | # correctness
22 | - always_declare_return_types
23 | - avoid_catching_errors
24 | - avoid_dynamic_calls
25 | - only_throw_errors
26 | - test_types_in_equals
27 | - throw_in_finally
28 | - type_annotate_public_apis
29 | - unawaited_futures
30 |
31 | # documentation related
32 | - comment_references
33 |
--------------------------------------------------------------------------------
/pkgs/google_generative_ai/lib/google_generative_ai.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | /// Google generative AI SDK API bindings for Dart.
16 | ///
17 | /// The Google Generative AI SDK for Dart allows developers to use
18 | /// state-of-the-art Large Language Models (LLMs) to build applications.
19 | ///
20 | /// Most uses of this library will be through a [GenerativeModel].
21 | /// Here's a simple example of using this API:
22 | ///
23 | /// ```dart
24 | /// const apiKey = ...;
25 | ///
26 | /// void main() async {
27 | /// final model = GenerativeModel(
28 | /// model: 'gemini-1.5-flash-latest',
29 | /// apiKey: apiKey,
30 | /// );
31 | ///
32 | /// final prompt = 'Write a story about a magic backpack.';
33 | /// final content = [Content.text(prompt)];
34 | /// final response = await model.generateContent(content);
35 | ///
36 | /// print(response.text);
37 | /// };
38 | /// ```
39 | library;
40 |
41 | import 'src/model.dart';
42 |
43 | export 'src/api.dart'
44 | show
45 | BatchEmbedContentsResponse,
46 | BlockReason,
47 | Candidate,
48 | CitationMetadata,
49 | CitationSource,
50 | ContentEmbedding,
51 | CountTokensResponse,
52 | EmbedContentRequest,
53 | EmbedContentResponse,
54 | FinishReason,
55 | GenerateContentResponse,
56 | GenerationConfig,
57 | HarmBlockThreshold,
58 | HarmCategory,
59 | HarmProbability,
60 | PromptFeedback,
61 | SafetyRating,
62 | SafetySetting,
63 | TaskType,
64 | UsageMetadata;
65 | export 'src/chat.dart' show ChatSession, StartChatExtension;
66 | export 'src/content.dart'
67 | show
68 | CodeExecutionResult,
69 | Content,
70 | DataPart,
71 | ExecutableCode,
72 | FilePart,
73 | FunctionCall,
74 | FunctionResponse,
75 | Language,
76 | Outcome,
77 | Part,
78 | TextPart;
79 | export 'src/error.dart'
80 | show
81 | GenerativeAIException,
82 | GenerativeAISdkException,
83 | InvalidApiKey,
84 | ServerException,
85 | UnsupportedUserLocation;
86 | export 'src/function_calling.dart'
87 | show
88 | CodeExecution,
89 | FunctionCallingConfig,
90 | FunctionCallingMode,
91 | FunctionDeclaration,
92 | Schema,
93 | SchemaType,
94 | Tool,
95 | ToolConfig;
96 | export 'src/model.dart' show GenerativeModel, RequestOptions;
97 |
--------------------------------------------------------------------------------
/pkgs/google_generative_ai/lib/src/chat.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 |
17 | import 'api.dart';
18 | import 'content.dart';
19 | import 'model.dart';
20 | import 'utils/mutex.dart';
21 |
22 | /// A back-and-forth chat with a generative model.
23 | ///
24 | /// Records messages sent and received in [history]. The history will always
25 | /// record the content from the first candidate in the
26 | /// [GenerateContentResponse], other candidates may be available on the returned
27 | /// response.
28 | final class ChatSession {
29 | final Future Function(Iterable content,
30 | {List? safetySettings,
31 | GenerationConfig? generationConfig}) _generateContent;
32 | final Stream Function(Iterable content,
33 | {List? safetySettings,
34 | GenerationConfig? generationConfig}) _generateContentStream;
35 |
36 | final _mutex = Mutex();
37 |
38 | final List _history;
39 | final List? _safetySettings;
40 | final GenerationConfig? _generationConfig;
41 |
42 | ChatSession._(this._generateContent, this._generateContentStream,
43 | this._history, this._safetySettings, this._generationConfig);
44 |
45 | /// The content that has been successfully sent to, or received from, the
46 | /// generative model.
47 | ///
48 | /// If there are outstanding requests from calls to [sendMessage] or
49 | /// [sendMessageStream], these will not be reflected in the history.
50 | /// Messages without a candidate in the response are not recorded in history,
51 | /// including the message sent to the model.
52 | Iterable get history => _history.skip(0);
53 |
54 | /// Sends [message] to the model as a continuation of the chat [history].
55 | ///
56 | /// Prepends the history to the request and uses the provided model to
57 | /// generate new content.
58 | ///
59 | /// When there are no candidates in the response, the [message] and response
60 | /// are ignored and will not be recorded in the [history].
61 | ///
62 | /// Waits for any ongoing or pending requests to [sendMessage] or
63 | /// [sendMessageStream] to complete before generating new content.
64 | /// Successful messages and responses for ongoing or pending requests will
65 | /// be reflected in the history sent for this message.
66 | Future sendMessage(Content message) async {
67 | final lock = await _mutex.acquire();
68 | try {
69 | final response = await _generateContent(_history.followedBy([message]),
70 | safetySettings: _safetySettings, generationConfig: _generationConfig);
71 | if (response.candidates case [final candidate, ...]) {
72 | _history.add(message);
73 | final normalizedContent = candidate.content.role == null
74 | ? Content('model', candidate.content.parts)
75 | : candidate.content;
76 | _history.add(normalizedContent);
77 | }
78 | return response;
79 | } finally {
80 | lock.release();
81 | }
82 | }
83 |
84 | /// Continues the chat with a new [message].
85 | ///
86 | /// Sends [message] to the model as a continuation of the chat [history] and
87 | /// reads the response in a stream.
88 | /// Prepends the history to the request and uses the provided model to
89 | /// generate new content.
90 | ///
91 | /// When there are no candidates in any response in the stream, the [message]
92 | /// and responses are ignored and will not be recorded in the [history].
93 | ///
94 | /// Waits for any ongoing or pending requests to [sendMessage] or
95 | /// [sendMessageStream] to complete before generating new content.
96 | /// Successful messages and responses for ongoing or pending requests will
97 | /// be reflected in the history sent for this message.
98 | ///
99 | /// Waits to read the entire streamed response before recording the message
100 | /// and response and allowing pending messages to be sent.
101 | Stream sendMessageStream(Content message) {
102 | final controller = StreamController(sync: true);
103 | _mutex.acquire().then((lock) async {
104 | try {
105 | final responses = _generateContentStream(_history.followedBy([message]),
106 | safetySettings: _safetySettings,
107 | generationConfig: _generationConfig);
108 | final content = [];
109 | await for (final response in responses) {
110 | if (response.candidates case [final candidate, ...]) {
111 | content.add(candidate.content);
112 | }
113 | controller.add(response);
114 | }
115 | if (content.isNotEmpty) {
116 | _history.add(message);
117 | _history.add(_aggregate(content));
118 | }
119 | } catch (e, s) {
120 | controller.addError(e, s);
121 | }
122 | lock.release();
123 | unawaited(controller.close());
124 | });
125 | return controller.stream;
126 | }
127 |
128 | /// Aggregates a list of [Content] responses into a single [Content].
129 | ///
130 | /// Includes all the [Content.parts] of every element of [contents],
131 | /// and concatenates adjacent [TextPart]s into a single [TextPart],
132 | /// even across adjacent [Content]s.
133 | Content _aggregate(List contents) {
134 | assert(contents.isNotEmpty);
135 | final role = contents.first.role ?? 'model';
136 | final textBuffer = StringBuffer();
137 | // If non-null, only a single text part has been seen.
138 | TextPart? previousText;
139 | final parts = [];
140 | void addBufferedText() {
141 | if (textBuffer.isEmpty) return;
142 | if (previousText case final singleText?) {
143 | parts.add(singleText);
144 | previousText = null;
145 | } else {
146 | parts.add(TextPart(textBuffer.toString()));
147 | }
148 | textBuffer.clear();
149 | }
150 |
151 | for (final content in contents) {
152 | for (final part in content.parts) {
153 | if (part case TextPart(:final text)) {
154 | if (text.isNotEmpty) {
155 | previousText = textBuffer.isEmpty ? part : null;
156 | textBuffer.write(text);
157 | }
158 | } else {
159 | addBufferedText();
160 | parts.add(part);
161 | }
162 | }
163 | }
164 | addBufferedText();
165 | return Content(role, parts);
166 | }
167 | }
168 |
169 | extension StartChatExtension on GenerativeModel {
170 | /// Starts a [ChatSession] that will use this model to respond to messages.
171 | ///
172 | /// ```dart
173 | /// final chat = model.startChat();
174 | /// final response = await chat.sendMessage(Content.text('Hello there.'));
175 | /// print(response.text);
176 | /// ```
177 | ChatSession startChat(
178 | {List? history,
179 | List? safetySettings,
180 | GenerationConfig? generationConfig}) =>
181 | ChatSession._(generateContent, generateContentStream, history ?? [],
182 | safetySettings, generationConfig);
183 | }
184 |
--------------------------------------------------------------------------------
/pkgs/google_generative_ai/lib/src/client.dart:
--------------------------------------------------------------------------------
1 | // Copyright 2024 Google LLC
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | import 'dart:async';
16 | import 'dart:convert';
17 |
18 | import 'package:http/http.dart' as http;
19 |
20 | import 'error.dart';
21 | import 'version.dart';
22 |
23 | const clientName = 'genai-dart/$packageVersion';
24 |
25 | abstract interface class ApiClient {
26 | Future