Skip to content

Add tuned_models samples #409

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 29, 2024
Merged
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
1 change: 1 addition & 0 deletions google/generativeai/types/__init__.py
Original file line number Diff line number Diff line change
@@ -21,6 +21,7 @@
from google.generativeai.types.generation_types import *
from google.generativeai.types.helper_types import *
from google.generativeai.types.model_types import *
from google.generativeai.types.permission_types import *
from google.generativeai.types.safety_types import *
from google.generativeai.types.text_types import *

59 changes: 58 additions & 1 deletion google/generativeai/types/permission_types.py
Original file line number Diff line number Diff line change
@@ -28,6 +28,7 @@
from google.generativeai.utils import flatten_update_paths
from google.generativeai import string_utils

__all__ = ["Permission", "Permissions"]

GranteeType = protos.Permission.GranteeType
Role = protos.Permission.Role
@@ -89,7 +90,7 @@ def valid_id(name: str) -> bool:


@string_utils.prettyprint
@dataclasses.dataclass
@dataclasses.dataclass(init=False)
class Permission:
"""
A permission to access a resource.
@@ -100,6 +101,24 @@ class Permission:
grantee_type: Optional[GranteeType]
email_address: Optional[str] = None

def __init__(
self,
name: str,
role: RoleOptions,
grantee_type: Optional[GranteeTypeOptions] = None,
email_address: Optional[str] = None,
):
self.name = name
if role is None:
self.role = None
else:
self.role = to_role(role)
if grantee_type is None:
self.grantee_type = None
else:
self.grantee_type = to_grantee_type(grantee_type)
self.email_address = email_address

def delete(
self,
client: glm.PermissionServiceClient | None = None,
@@ -279,6 +298,12 @@ def _make_create_permission_request(
f"Invalid operation: An 'email_address' must be provided when 'grantee_type' is not set to 'EVERYONE'. Currently, 'grantee_type' is set to '{grantee_type}' and 'email_address' is '{email_address if email_address else 'not provided'}'."
)

if email_address and grantee_type is None:
if email_address.endswith("googlegroups.com"):
grantee_type = GranteeType.GROUP
else:
grantee_type = GranteeType.USER

permission = protos.Permission(
role=role,
grantee_type=grantee_type,
@@ -367,6 +392,9 @@ def list(
permission = type(permission).to_dict(permission)
yield Permission(**permission)

def __iter__(self):
return self.list()

async def list_async(
self,
page_size: Optional[int] = None,
@@ -385,6 +413,35 @@ async def list_async(
permission = type(permission).to_dict(permission)
yield Permission(**permission)

async def __aiter__(self):
return self.list_async()

@classmethod
def get(cls, name: str) -> Permission:
"""
Get information about a specific permission.

Args:
name: The name of the permission to get.

Returns:
Requested permission as an instance of `Permission`.
"""
return Permission.get(name)

@classmethod
async def get_async(cls, name: str) -> Permission:
"""
Get information about a specific permission.

Args:
name: The name of the permission to get.

Returns:
Requested permission as an instance of `Permission`.
"""
return await Permission.get_async(name)

def transfer_ownership(
self,
email_address: str,
27 changes: 14 additions & 13 deletions samples/count_tokens.py
Original file line number Diff line number Diff line change
@@ -20,9 +20,6 @@
media = pathlib.Path(__file__).parents[1] / "third_party"





class UnitTests(absltest.TestCase):
def test_tokens_text_only(self):
# [START tokens_text_only]
@@ -84,8 +81,10 @@ def test_tokens_cached_content(self):
def test_tokens_system_instruction(self):
# [START tokens_system_instruction]
document = genai.upload_file(path=media / "a11.txt")
model = genai.GenerativeModel("models/gemini-1.5-flash-001",
system_instruction="You are an expert analyzing transcripts. Give a summary of this document.")
model = genai.GenerativeModel(
"models/gemini-1.5-flash-001",
system_instruction="You are an expert analyzing transcripts. Give a summary of this document.",
)
print(model.count_tokens(document))
# [END tokens_system_instruction]

@@ -95,25 +94,27 @@ def add(a: float, b: float):
"""returns a + b."""
return a + b


def subtract(a: float, b: float):
"""returns a - b."""
return a - b


def multiply(a: float, b: float):
"""returns a * b."""
return a * b


def divide(a: float, b: float):
"""returns a / b."""
return a / b

model = genai.GenerativeModel("models/gemini-1.5-flash-001",
tools=[add, subtract, multiply, divide])

print(model.count_tokens("I have 57 cats, each owns 44 mittens, how many mittens is that in total?"))

model = genai.GenerativeModel(
"models/gemini-1.5-flash-001", tools=[add, subtract, multiply, divide]
)

print(
model.count_tokens(
"I have 57 cats, each owns 44 mittens, how many mittens is that in total?"
)
)
# [END tokens_tools]


62 changes: 62 additions & 0 deletions samples/increment_tuning_data.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
[
{
"text_input": "1",
"output": "2"
},
{
"text_input": "3",
"output": "4"
},
{
"text_input": "-3",
"output": "-2"
},
{
"text_input": "twenty two",
"output": "twenty three"
},
{
"text_input": "two hundred",
"output": "two hundred one"
},
{
"text_input": "ninety nine",
"output": "one hundred"
},
{
"text_input": "8",
"output": "9"
},
{
"text_input": "-98",
"output": "-97"
},
{
"text_input": "1,000",
"output": "1,001"
},
{
"text_input": "10,100,000",
"output": "10,100,001"
},
{
"text_input": "thirteen",
"output": "fourteen"
},
{
"text_input": "eighty",
"output": "eighty one"
},
{
"text_input": "one",
"output": "two"
},
{
"text_input": "three",
"output": "four"
},
{
"text_input": "seven",
"output": "eight"
}
]
4 changes: 4 additions & 0 deletions samples/text_generation.py
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@ def test_text_gen_text_only_prompt_streaming(self):
def test_text_gen_multimodal_one_image_prompt(self):
# [START text_gen_multimodal_one_image_prompt]
import PIL

model = genai.GenerativeModel("gemini-1.5-flash")
organ = PIL.Image.open(media / "organ.jpg")
response = model.generate_content(["Tell me about this instrument", organ])
@@ -50,6 +51,7 @@ def test_text_gen_multimodal_one_image_prompt(self):
def test_text_gen_multimodal_one_image_prompt_streaming(self):
# [START text_gen_multimodal_one_image_prompt_streaming]
import PIL

model = genai.GenerativeModel("gemini-1.5-flash")
organ = PIL.Image.open(media / "organ.jpg")
response = model.generate_content(["Tell me about this instrument", organ], stream=True)
@@ -61,6 +63,7 @@ def test_text_gen_multimodal_one_image_prompt_streaming(self):
def test_text_gen_multimodal_multi_image_prompt(self):
# [START text_gen_multimodal_multi_image_prompt]
import PIL

model = genai.GenerativeModel("gemini-1.5-flash")
organ = PIL.Image.open(media / "organ.jpg")
cajun_instrument = PIL.Image.open(media / "Cajun_instruments.jpg")
@@ -73,6 +76,7 @@ def test_text_gen_multimodal_multi_image_prompt(self):
def test_text_gen_multimodal_multi_image_prompt_streaming(self):
# [START text_gen_multimodal_multi_image_prompt_streaming]
import PIL

model = genai.GenerativeModel("gemini-1.5-flash")
organ = PIL.Image.open(media / "organ.jpg")
cajun_instrument = PIL.Image.open(media / "Cajun_instruments.jpg")
236 changes: 236 additions & 0 deletions samples/tuning.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
# -*- coding: utf-8 -*-
# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from absl.testing import absltest

import google
import google.generativeai as genai

import pathlib

samples = pathlib.Path(__file__).parent


class UnitTests(absltest.TestCase):
def test_tuned_models_create(self):
# [START tuned_models_create]
import time

base_model = "models/gemini-1.0-pro-001"
training_data = [
{"text_input": "1", "output": "2"},
# ... more examples ...
# [START_EXCLUDE]
{"text_input": "3", "output": "4"},
{"text_input": "-3", "output": "-2"},
{"text_input": "twenty two", "output": "twenty three"},
{"text_input": "two hundred", "output": "two hundred one"},
{"text_input": "ninety nine", "output": "one hundred"},
{"text_input": "8", "output": "9"},
{"text_input": "-98", "output": "-97"},
{"text_input": "1,000", "output": "1,001"},
{"text_input": "10,100,000", "output": "10,100,001"},
{"text_input": "thirteen", "output": "fourteen"},
{"text_input": "eighty", "output": "eighty one"},
{"text_input": "one", "output": "two"},
{"text_input": "three", "output": "four"},
# [END_EXCLUDE]
{"text_input": "seven", "output": "eight"},
]
operation = genai.create_tuned_model(
# You can use a tuned model here too. Set `source_model="tunedModels/..."`
display_name="increment",
source_model=base_model,
epoch_count=20,
batch_size=4,
learning_rate=0.001,
training_data=training_data,
)

for status in operation.wait_bar():
time.sleep(10)

result = operation.result()
print(result)
# # You can plot the loss curve with:
# snapshots = pd.DataFrame(result.tuning_task.snapshots)
# sns.lineplot(data=snapshots, x='epoch', y='mean_loss')

model = genai.GenerativeModel(model_name=result.name)
result = model.generate_content("III")
print(result.text) # IV
# [END tuned_models_create]

def test_tuned_models_generate_content(self):
# [START tuned_models_generate_content]
model = genai.GenerativeModel(model_name="tunedModels/my-increment-model")
result = model.generate_content("III")
print(result.text) # "IV"
# [END tuned_models_create]

def test_tuned_models_get(self):
# [START tuned_models_get]
model_info = genai.get_model("tunedModels/my-increment-model")
print(model_info)
# [END tuned_models_get]

def test_tuned_models_list(self):
# [START tuned_models_list]
for model_info in genai.list_tuned_models():
print(model_info.name)
# [END tuned_models_list]

def test_tuned_models_delete(self):
import time

base_model = "models/gemini-1.0-pro-001"
training_data = samples / "increment_tuning_data.json"
try:
operation = genai.create_tuned_model(
id="delete-this-model",
# You can use a tuned model here too. Set `source_model="tunedModels/..."`
display_name="increment",
source_model=base_model,
epoch_count=20,
batch_size=4,
learning_rate=0.001,
training_data=training_data,
)
except google.api_core.exceptions.AlreadyExists:
pass
else:
for status in operation.wait_bar():
time.sleep(10)

# [START tuned_models_delete]
model_name = "tunedModels/delete-this-model"
model_info = genai.get_model(model_name)
print(model_info)

# You can pass the model_info or name here.
genai.delete_tuned_model(model_name)
# [END tuned_models_delete]

def test_tuned_models_permissions_create(self):
# [START tuned_models_permissions_create]
model_info = genai.get_model("tunedModels/my-increment-model")
# [START_EXCLUDE]
for p in model_info.permissions.list():
if p.role.name != "OWNER":
p.delete()
# [END_EXCLUDE]

public_permission = model_info.permissions.create(
role="READER",
grantee_type="EVERYONE",
)

group_permission = model_info.permissions.create(
role="READER",
# Use "user" for an individual email address.
grantee_type="group",
email_address="genai-samples-test-group@googlegroups.com",
)
# [END tuned_models_permissions_create]
public_permission.delete()
group_permission.delete()

def test_tuned_models_permissions_list(self):
# [START tuned_models_permissions_list]
model_info = genai.get_model("tunedModels/my-increment-model")

# [START_EXCLUDE]
for p in model_info.permissions.list():
if p.role.name != "OWNER":
p.delete()

public_permission = model_info.permissions.create(
role="READER",
grantee_type="EVERYONE",
)

group_permission = model_info.permissions.create(
role="READER",
grantee_type="group",
email_address="genai-samples-test-group@googlegroups.com",
)
# [END_EXCLUDE]

for p in model_info.permissions.list():
print(p)
# [END tuned_models_permissions_list]
public_permission.delete()
group_permission.delete()

def test_tuned_models_permissions_get(self):
# [START tuned_models_permissions_get]
model_info = genai.get_model("tunedModels/my-increment-model")

# [START_EXCLUDE]
for p in model_info.permissions.list():
if p.role.name != "OWNER":
p.delete()
# [END_EXCLUDE]

public = model_info.permissions.create(
role="READER",
grantee_type="EVERYONE",
)
print(public)
name = public.name
print(name) # tunedModels/{tunedModel}/permissions/{permission}

from_name = genai.types.Permissions.get(name)
print(from_name)
# [END tuned_models_permissions_get]

def test_tuned_models_permissions_update(self):
# [START tuned_models_permissions_update]
model_info = genai.get_model("tunedModels/my-increment-model")

# [START_EXCLUDE]
for p in model_info.permissions.list():
if p.role.name != "OWNER":
p.delete()
# [END_EXCLUDE]

test_group = model_info.permissions.create(
role="writer",
grantee_type="group",
email_address="genai-samples-test-group@googlegroups.com",
)

test_group.update({"role": "READER"})
# [END tuned_models_permissions_get]

def test_tuned_models_permission_delete(self):
# [START tuned_models_permissions_create]
model_info = genai.get_model("tunedModels/my-increment-model")
# [START_EXCLUDE]
for p in model_info.permissions.list():
if p.role.name != "OWNER":
p.delete()
# [END_EXCLUDE]

public_permission = model_info.permissions.create(
role="READER",
grantee_type="EVERYONE",
)

public_permission.delete()
# [END tuned_models_permissions_create]


if __name__ == "__main__":
absltest.main()