Skip to content

Commit

Permalink
feat!: Migrate internal client from googleai_dart to google_generativ…
Browse files Browse the repository at this point in the history
…e_ai (#407)
  • Loading branch information
davidmigloz committed May 9, 2024
1 parent 5e2b0ec commit fa4b5c3
Show file tree
Hide file tree
Showing 24 changed files with 596 additions and 333 deletions.
72 changes: 40 additions & 32 deletions docs/modules/model_io/models/chat_models/integrations/googleai.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,21 @@ Wrapper around [Google AI for Developers](https://ai.google.dev/) API (aka Gemin

## Setup

To use `ChatGoogleGenerativeAI` you need to have an API key. You can get one [here](https://makersuite.google.com/app/apikey).

The following models are available at the moment:
- `gemini-pro`: text -> text model
- `gemini-pro-vision`: text / image -> text model
To use `ChatGoogleGenerativeAI` you need to have an API key. You can get one [here](https://aistudio.google.com/app/apikey).

The following models are available:
- `gemini-1.0-pro` (or `gemini-pro`):
* text -> text model
* Max input token: 30720
* Max output tokens: 2048
- `gemini-pro-vision`:
* text / image -> text model
* Max input token: 12288
* Max output tokens: 4096
- `gemini-1.5-pro-latest`: text / image -> text model
* text / image -> text model
* Max input token: 1048576
* Max output tokens: 8192

Mind that this list may not be up-to-date. Refer to the [documentation](https://ai.google.dev/models) for the updated list.

Expand All @@ -20,17 +30,15 @@ final apiKey = Platform.environment['GOOGLEAI_API_KEY'];
final chatModel = ChatGoogleGenerativeAI(
apiKey: apiKey,
defaultOptions: ChatGoogleGenerativeAIOptions(
model: 'gemini-1.5-pro-latest',
temperature: 0,
),
);
const template = '''
You are a helpful assistant that translates {input_language} to {output_language}.
Text to translate:
{text}''';
final humanMessagePrompt = HumanChatMessagePromptTemplate.fromTemplate(template);
final chatPrompt = ChatPromptTemplate.fromPromptMessages([humanMessagePrompt]);
final chatPrompt = ChatPromptTemplate.fromTemplates([
(ChatMessageType.system, 'You are a helpful assistant that translates {input_language} to {output_language}.'),
(ChatMessageType.human, 'Text to translate:\n{text}'),
]);
final chain = chatPrompt | chatModel | StringOutputParser();
Expand All @@ -40,7 +48,7 @@ final res = await chain.invoke({
'text': 'I love programming.',
});
print(res);
// -> 'J'adore la programmation.'final
// -> 'J'adore programmer.'
```

## Multimodal support
Expand All @@ -51,7 +59,7 @@ final apiKey = Platform.environment['GOOGLEAI_API_KEY'];
final chatModel = ChatGoogleGenerativeAI(
apiKey: apiKey,
defaultOptions: ChatGoogleGenerativeAIOptions(
model: 'gemini-pro-vision',
model: 'gemini-1.5-pro-latest',
temperature: 0,
),
);
Expand All @@ -71,35 +79,35 @@ final res = await chatModel.invoke(
]),
);
print(res.output.content);
// -> 'A Red and Green Apple'
// -> 'That is an apple.'
```

## Streaming

```dart
final apiKey = Platform.environment['GOOGLEAI_API_KEY'];
final promptTemplate = ChatPromptTemplate.fromTemplate(
'You are a helpful assistant that replies only with numbers '
'in order without any spaces or commas '
'List the numbers from 1 to {max_num}');
final promptTemplate = ChatPromptTemplate.fromTemplates(const [
(ChatMessageType.system, 'You are a helpful assistant that replies only with numbers in order without any spaces or commas.'),
(ChatMessageType.human, 'List the numbers from 1 to {max_num}'),
]);
final chatModel = ChatGoogleGenerativeAI(apiKey: apiKey);
final chatModel = ChatGoogleGenerativeAI(
apiKey: apiKey,
defaultOptions: const ChatGoogleGenerativeAIOptions(
model: 'gemini-1.5-pro-latest',
temperature: 0,
),
);
final chain = promptTemplate.pipe(chatModel).pipe(StringOutputParser());
final stream = chain.stream({'max_num': '30'});
await stream.forEach(print);
// 1234567891011121
// 31415161718192021222324252627282
// 930
```

## Limitations
// 1
// 2345678910111213
// 1415161718192021
// 222324252627282930
As of the time this doc was written (15/12/23), Gemini has some restrictions on the types and structure of prompts it accepts. Specifically:

1. When providing multimodal (image) inputs, you are restricted to at most 1 message of “human” (user) type. You cannot pass multiple messages (though the single human message may have multiple content entries).
2. System messages are not accepted.
3. For regular chat conversations, messages must follow the human/ai/human/ai alternating pattern. You may not provide 2 AI or human messages in sequence.
4. Message may be blocked if they violate the safety checks of the LLM. In this case, the model will return an empty response.
chatModel.close();
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ The embedding service in the [Gemini API](https://ai.google.dev/docs/embeddings_

## Available models

- `embedding-001` (default)
* Optimized for creating embeddings for text of up to 2048 tokens
- `text-embedding-004`
* Dimensions: 768 (with support for reduced dimensionality)
- `embedding-001`
* Dimensions: 768

The previous list of models may not be exhaustive or up-to-date. Check out the [Google AI documentation](https://ai.google.dev/models/gemini) for the latest list of available models.

Expand Down
4 changes: 2 additions & 2 deletions examples/browser_summarizer/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ packages:
path: "../../packages/langchain_openai"
relative: true
source: path
version: "0.6.0+1"
version: "0.6.0+2"
langchain_tiktoken:
dependency: transitive
description:
Expand Down Expand Up @@ -309,7 +309,7 @@ packages:
path: "../../packages/openai_dart"
relative: true
source: path
version: "0.3.0"
version: "0.3.1"
path:
dependency: transitive
description:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,18 @@ Future<void> _chatGoogleGenerativeAI() async {
final chatModel = ChatGoogleGenerativeAI(
apiKey: apiKey,
defaultOptions: const ChatGoogleGenerativeAIOptions(
model: 'gemini-1.5-pro-latest',
temperature: 0,
),
);

const template = '''
You are a helpful assistant that translates {input_language} to {output_language}.
Text to translate:
{text}''';
final humanMessagePrompt =
HumanChatMessagePromptTemplate.fromTemplate(template);
final chatPrompt =
ChatPromptTemplate.fromPromptMessages([humanMessagePrompt]);
final chatPrompt = ChatPromptTemplate.fromTemplates(const [
(
ChatMessageType.system,
'You are a helpful assistant that translates {input_language} to {output_language}.'
),
(ChatMessageType.human, 'Text to translate:\n{text}'),
]);

final chain = chatPrompt | chatModel | const StringOutputParser();

Expand All @@ -39,7 +38,7 @@ Text to translate:
'text': 'I love programming.',
});
print(res);
// -> 'J'adore la programmation.'
// -> 'J'adore programmer.'

chatModel.close();
}
Expand All @@ -50,7 +49,7 @@ Future<void> _chatGoogleGenerativeAIMultiModal() async {
final chatModel = ChatGoogleGenerativeAI(
apiKey: apiKey,
defaultOptions: const ChatGoogleGenerativeAIOptions(
model: 'gemini-pro-vision',
model: 'gemini-1.5-pro-latest',
temperature: 0,
),
);
Expand All @@ -70,28 +69,39 @@ Future<void> _chatGoogleGenerativeAIMultiModal() async {
]),
);
print(res.output.content);
// -> 'A Red and Green Apple'
// -> 'That is an apple.'

chatModel.close();
}

Future<void> _chatOpenAIStreaming() async {
final apiKey = Platform.environment['GOOGLEAI_API_KEY'];

final promptTemplate = ChatPromptTemplate.fromTemplate(
final promptTemplate = ChatPromptTemplate.fromTemplates(const [
(
ChatMessageType.system,
'You are a helpful assistant that replies only with numbers '
'in order without any spaces or commas '
'List the numbers from 1 to {max_num}');
'in order without any spaces or commas.',
),
(ChatMessageType.human, 'List the numbers from 1 to {max_num}'),
]);

final chatModel = ChatGoogleGenerativeAI(apiKey: apiKey);
final chatModel = ChatGoogleGenerativeAI(
apiKey: apiKey,
defaultOptions: const ChatGoogleGenerativeAIOptions(
model: 'gemini-1.5-pro-latest',
temperature: 0,
),
);

final chain = promptTemplate.pipe(chatModel).pipe(const StringOutputParser());

final stream = chain.stream({'max_num': '30'});
await stream.forEach(print);
// 1234567891011121
// 31415161718192021222324252627282
// 930
// 1
// 2345678910111213
// 1415161718192021
// 222324252627282930

chatModel.close();
}
19 changes: 10 additions & 9 deletions examples/docs_examples/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.8.12"
google_generative_ai:
dependency: transitive
description:
name: google_generative_ai
sha256: "3a51ed314e596ddee9654ab9f1372fff0b8f3917be937655bcadebd5fa063df0"
url: "https://pub.dev"
source: hosted
version: "0.3.3"
google_identity_services_web:
dependency: transitive
description:
Expand All @@ -136,13 +144,6 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.3.1+1"
googleai_dart:
dependency: "direct overridden"
description:
path: "../../packages/googleai_dart"
relative: true
source: path
version: "0.0.4"
googleapis:
dependency: transitive
description:
Expand Down Expand Up @@ -270,7 +271,7 @@ packages:
path: "../../packages/langchain_openai"
relative: true
source: path
version: "0.6.0+1"
version: "0.6.0+2"
langchain_tiktoken:
dependency: transitive
description:
Expand Down Expand Up @@ -323,7 +324,7 @@ packages:
path: "../../packages/openai_dart"
relative: true
source: path
version: "0.3.0"
version: "0.3.1"
path:
dependency: transitive
description:
Expand Down
4 changes: 1 addition & 3 deletions examples/docs_examples/pubspec_overrides.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
# melos_managed_dependency_overrides: chromadb,googleai_dart,langchain,langchain_chroma,langchain_google,langchain_mistralai,langchain_ollama,langchain_openai,mistralai_dart,ollama_dart,openai_dart,vertex_ai,langchain_core,langchain_community
# melos_managed_dependency_overrides: chromadb,langchain,langchain_chroma,langchain_google,langchain_mistralai,langchain_ollama,langchain_openai,mistralai_dart,ollama_dart,openai_dart,vertex_ai,langchain_core,langchain_community
dependency_overrides:
chromadb:
path: ../../packages/chromadb
googleai_dart:
path: ../../packages/googleai_dart
langchain:
path: ../../packages/langchain
langchain_chroma:
Expand Down
4 changes: 2 additions & 2 deletions examples/hello_world_backend/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ packages:
path: "../../packages/langchain_openai"
relative: true
source: path
version: "0.6.0+1"
version: "0.6.0+2"
langchain_tiktoken:
dependency: transitive
description:
Expand All @@ -156,7 +156,7 @@ packages:
path: "../../packages/openai_dart"
relative: true
source: path
version: "0.3.0"
version: "0.3.1"
path:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions examples/hello_world_cli/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ packages:
path: "../../packages/langchain_openai"
relative: true
source: path
version: "0.6.0+1"
version: "0.6.0+2"
langchain_tiktoken:
dependency: transitive
description:
Expand All @@ -148,7 +148,7 @@ packages:
path: "../../packages/openai_dart"
relative: true
source: path
version: "0.3.0"
version: "0.3.1"
path:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions examples/hello_world_flutter/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ packages:
path: "../../packages/langchain_openai"
relative: true
source: path
version: "0.6.0+1"
version: "0.6.0+2"
langchain_tiktoken:
dependency: transitive
description:
Expand Down Expand Up @@ -193,7 +193,7 @@ packages:
path: "../../packages/openai_dart"
relative: true
source: path
version: "0.3.0"
version: "0.3.1"
path:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions melos.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ command:
flutter_markdown: ^0.6.22
freezed_annotation: ^2.4.1
gcloud: ^0.8.12
google_generative_ai: 0.3.3
googleapis: ^12.0.0
googleapis_auth: ^1.5.1
http: ^1.1.0
Expand Down
6 changes: 4 additions & 2 deletions packages/googleai_dart/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
[![](https://dcbadge.vercel.app/api/server/x4qbhqecVR?style=flat)](https://discord.gg/x4qbhqecVR)
[![MIT](https://img.shields.io/badge/license-MIT-purple.svg)](https://github.com/davidmigloz/langchain_dart/blob/main/LICENSE)

Unofficial Dart client for [Google AI](https://ai.google.dev) for Developers (Gemini API).
Unofficial Dart client for [Google AI](https://ai.google.dev) for Developers (Gemini API v1).

> Note: The official [`google_generative_ai`](https://pub.dev/packages/google_generative_ai) now has feature parity with this package (except for the [Model info](https://github.com/google-gemini/generative-ai-dart/issues/93) endpoints). We plan to deprecate this package in the near future.
## Features

Expand Down Expand Up @@ -53,7 +55,7 @@ Refer to the [documentation](https://ai.google.dev/docs) for more information ab

### Authentication

The Google AI API uses API keys for authentication. Visit [Google AI Studio dashboard](https://makersuite.google.com/app/apikey) page to retrieve the API key you'll use in your requests.
The Google AI API uses API keys for authentication. Visit [Google AI Studio dashboard](https://aistudio.google.com/app/apikey) page to retrieve the API key you'll use in your requests.

> **Remember that your API key is a secret!**
> Do not share it with others or expose it in any client-side code (browsers, apps). Production requests must be routed through your own backend server where your API key can be securely loaded from an environment variable or key management service.
Expand Down
2 changes: 1 addition & 1 deletion packages/googleai_dart/lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class GoogleAIClient extends g.GoogleAIClient {
///
/// Main configuration options:
/// - `apiKey`: your Google AI API key. You can find your API key in the
/// [Google AI Studio dashboard](https://makersuite.google.com/app/apikey).
/// [Google AI Studio dashboard](https://aistudio.google.com/app/apikey).
///
/// Advance configuration options:
/// - `baseUrl`: the base URL to use.You can override this to use a different
Expand Down

0 comments on commit fa4b5c3

Please sign in to comment.