Accessing tuned Gemini model in Flutter

Aayush Sharma
3 min readJun 26, 2024

--

Hi everyone! Myself Aayush Sharma, a fellow Flutter developer. In this article, I’ll demonstrate how you can access a tuned Gemini model in your Flutter app.

Overview

You must’ve used google_generative_ai package if you tried integrating Gemini into your Flutter app. It lets you use the publicly available Gemini models like gemini-1.5-flash easily.

But an error will be thrown if you tuned a model in the Google AI studio for your specific use case and tried connecting to it (given below).

Problem

The problem with accessing a tuned model is that it requires OAuth authentication, Only authenticating with the Gemini API key won't suffice. In the official documentation provided by Google, They provide a way to give this OAuth access using a Python client only for Desktops.

They don’t support OAuth yet for mobile devices but are working on it. So in the future, you might be able to access the model just by using their API key.

In the meantime, you can use my solution to access tuned models or even provide access to other people (email addresses).

Permissions/Roles

The tuned models in Gemini have permissions/roles assigned to those who want to access them. If you’ve got the READER role associated with your email address for a particular model then you can access it.

Initially, READER access is given to the owner of the model. You can access the model in your application if you somehow provide OAuth authentication with this account.

Authentication

The easiest way to provide Google OAuth is to implement Google Sign-in. Now, I won’t go into details of implementation. You can easily get CHAT-GPT to get it done in minutes.

Create a GoogleSignIn object.

final googleSignIn = GoogleSignIn();

Note: You might have to specify scopes as well if it doesn’t work, Do it like given below.

final googleSignIn = GoogleSignIn(scopes: [

‘https://www.googleapis.com/auth/generative-language.retriever',

‘https://www.googleapis.com/auth/generative-language.tuning',

]);

now continue the normal flow for Google sign-in.

final googleAccount = await googleSignIn.signIn();
final googleAuthCreds = await googleAccount?.authentication;

The googleAuthCreds have the required OAuth access token that will give us access to the tuned models. So, store that in a variable that will be used later.

_oauthAccessToken = googleAuthCreds?.accessToken;

Now we need to pass the access token to the GenerativeModel object that actually connects to the model. It takes a Client as a parameter which is an HTTP client from the HTTP package.

Extend the BaseClient which is provided by default by httppackage and override its send method. This is where we’ll add the Authorization header to each request that is made to Gemini API.

class OauthHttpClient extends http.BaseClient {
final String authorizationToken;

OauthHttpClient(this.authorizationToken);

@override
Future<http.StreamedResponse> send(http.BaseRequest request) {
request.headers['Authorization'] = 'Bearer $authorizationToken';
return http.Client().send(request);
}
}

Now pass an object of OauthHttpClient to the Generative model you’re going to create.

final _tunedModel = GenerativeModel(
model: 'tunedModels/<yourModelId>',
apiKey: const String.fromEnvironment('GEMINI_API_KEY'),
httpClient: OauthHttpClient(AuthService().oathAccessToken ?? ''),
...
);

And it’s done, Now whenever you hit the Gemini API with this model it’ll automatically pass the OAuth Token and process the request normally.

Providing Access to other accounts

The above solution works as long as you have the READER permission for the respective model. To give access to others you have to follow a few steps below.

  • Get the OAuth access token for the account through which you created the model

Just print the token you got above in the console

_oauthAccessToken = googleAuthCreds?.accessToken;
print(_oauthAccessToken)
curl --location 'https://generativelanguage.googleapis.com/v1beta/tunedModels/geminiscribblewordgen-m8ul77vifyl6/permissions' \
--header 'Authorization: Bearer oAuth token>' \
--header 'Content-Type: application/json' \
--data-raw '{
"granteeType": "USER",
"emailAddress": "<email address>",
"role": "READER"
}'
  • You can also specify granteeType as EVERYONE then there is no need to specify email address.

That’s it now others can also access your tuned model after signing into Google.

Thanks for sticking to the end, I hope you learned something new. If you’ve any queries, reach out to me on LinkedIn or in the comments. Do visit my website made entirely in Flutter.

--

--