From 1472f7c0536171cddfa82545eeef1b9d1363ee15 Mon Sep 17 00:00:00 2001 From: Mark Daoust Date: Tue, 28 Jan 2025 17:19:37 -0800 Subject: [PATCH] Copied from generative-ai-python https://github.com/google-gemini/generative-ai-python/tree/main/samples@362e0010dd2ebc67de4fee2278301e6d19702912 --- examples/website_samples/README.md | 26 + examples/website_samples/cache.py | 169 ++++++ examples/website_samples/chat.py | 89 ++++ examples/website_samples/code_execution.py | 202 +++++++ .../configure_model_parameters.py | 40 ++ .../website_samples/controlled_generation.py | 178 +++++++ examples/website_samples/count_tokens.py | 296 +++++++++++ examples/website_samples/embed.py | 47 ++ examples/website_samples/files.py | 148 ++++++ examples/website_samples/function_calling.py | 51 ++ .../increment_tuning_data.json | 62 +++ examples/website_samples/models.py | 44 ++ examples/website_samples/rest/README.md | 26 + examples/website_samples/rest/cache.sh | 83 +++ examples/website_samples/rest/chat.sh | 93 ++++ .../website_samples/rest/code_execution.sh | 58 +++ .../rest/configure_model_parameters.sh | 30 ++ .../rest/controlled_generation.sh | 44 ++ examples/website_samples/rest/count_tokens.sh | 288 ++++++++++ examples/website_samples/rest/embed.sh | 32 ++ examples/website_samples/rest/file_info.json | 0 examples/website_samples/rest/files.sh | 300 +++++++++++ .../website_samples/rest/function_calling.sh | 62 +++ examples/website_samples/rest/models.sh | 11 + examples/website_samples/rest/response.json | 20 + .../website_samples/rest/safety_settings.sh | 34 ++ .../rest/system_instruction.sh | 13 + .../website_samples/rest/text_generation.sh | 492 ++++++++++++++++++ examples/website_samples/rest/tuned_models.sh | 143 +++++ examples/website_samples/rest/tunemodel.json | 8 + examples/website_samples/safety_settings.py | 59 +++ .../website_samples/system_instruction.py | 33 ++ examples/website_samples/text_generation.py | 195 +++++++ examples/website_samples/tuned_models.py | 255 +++++++++ 34 files changed, 3631 insertions(+) create mode 100644 examples/website_samples/README.md create mode 100644 examples/website_samples/cache.py create mode 100644 examples/website_samples/chat.py create mode 100644 examples/website_samples/code_execution.py create mode 100644 examples/website_samples/configure_model_parameters.py create mode 100644 examples/website_samples/controlled_generation.py create mode 100644 examples/website_samples/count_tokens.py create mode 100644 examples/website_samples/embed.py create mode 100644 examples/website_samples/files.py create mode 100644 examples/website_samples/function_calling.py create mode 100644 examples/website_samples/increment_tuning_data.json create mode 100644 examples/website_samples/models.py create mode 100644 examples/website_samples/rest/README.md create mode 100644 examples/website_samples/rest/cache.sh create mode 100644 examples/website_samples/rest/chat.sh create mode 100644 examples/website_samples/rest/code_execution.sh create mode 100644 examples/website_samples/rest/configure_model_parameters.sh create mode 100644 examples/website_samples/rest/controlled_generation.sh create mode 100644 examples/website_samples/rest/count_tokens.sh create mode 100644 examples/website_samples/rest/embed.sh create mode 100644 examples/website_samples/rest/file_info.json create mode 100644 examples/website_samples/rest/files.sh create mode 100644 examples/website_samples/rest/function_calling.sh create mode 100644 examples/website_samples/rest/models.sh create mode 100644 examples/website_samples/rest/response.json create mode 100644 examples/website_samples/rest/safety_settings.sh create mode 100644 examples/website_samples/rest/system_instruction.sh create mode 100755 examples/website_samples/rest/text_generation.sh create mode 100644 examples/website_samples/rest/tuned_models.sh create mode 100644 examples/website_samples/rest/tunemodel.json create mode 100644 examples/website_samples/safety_settings.py create mode 100644 examples/website_samples/system_instruction.py create mode 100644 examples/website_samples/text_generation.py create mode 100644 examples/website_samples/tuned_models.py diff --git a/examples/website_samples/README.md b/examples/website_samples/README.md new file mode 100644 index 000000000..ce2e9d243 --- /dev/null +++ b/examples/website_samples/README.md @@ -0,0 +1,26 @@ +# Gemini API Python SDK sample code + +This directory contains sample code for key features of the SDK, organised by high level feature. + +These samples are embedded in parts of the [documentation](https://ai.google.dev), most notably in the [API reference](https://ai.google.dev/api). + +Each file is structured as a runnable test case, ensuring that samples are executable and functional. Each test demonstrates a single concept, and contains region tags that are used to demarcate the test scaffolding from the spotlight code. If you are contributing, code within region tags should follow sample code best practices - being clear, complete and concise. + +## Contents + +| File | Description | +|----------------------------------------------------------| ----------- | +| [cache.py](./cache.py) | Context caching | +| [chat.py](./chat.py) | Multi-turn chat conversations | +| [code_execution.py](./code_execution.py) | Executing code | +| [configure_model_parameters.py](./configure_model_parameters.py) | Setting model parameters | +| [controlled_generation.py](./controlled_generation.py) | Generating content with output constraints (e.g. JSON mode) | +| [count_tokens.py](./count_tokens.py) | Counting input and output tokens | +| [embed.py](./embed.py) | Generating embeddings | +| [files.py](./files.py) | Managing files with the File API | +| [function_calling.py](./function_calling.py) | Using function calling | +| [models.py](./models.py) | Listing models and model metadata | +| [safety_settings.py](./safety_settings.py) | Setting and using safety controls | +| [system_instruction.py](./system_instruction.py) | Setting system instructions | +| [text_generation.py](./text_generation.py) | Generating text | +| [tuned_models.py](./tuned_models.py) | Creating and managing tuned models | diff --git a/examples/website_samples/cache.py b/examples/website_samples/cache.py new file mode 100644 index 000000000..1d4dd6e47 --- /dev/null +++ b/examples/website_samples/cache.py @@ -0,0 +1,169 @@ +# -*- 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 pathlib + +media = pathlib.Path(__file__).parents[1] / "third_party" + + +class UnitTests(absltest.TestCase): + def test_cache_create(self): + # [START cache_create] + import google.generativeai as genai + + document = genai.upload_file(path=media / "a11.txt") + model_name = "gemini-1.5-flash-001" + cache = genai.caching.CachedContent.create( + model=model_name, + system_instruction="You are an expert analyzing transcripts.", + contents=[document], + ) + print(cache) + + model = genai.GenerativeModel.from_cached_content(cache) + response = model.generate_content("Please summarize this transcript") + print(response.text) + # [END cache_create] + cache.delete() + + def test_cache_create_from_name(self): + # [START cache_create_from_name] + import google.generativeai as genai + + document = genai.upload_file(path=media / "a11.txt") + model_name = "gemini-1.5-flash-001" + cache = genai.caching.CachedContent.create( + model=model_name, + system_instruction="You are an expert analyzing transcripts.", + contents=[document], + ) + cache_name = cache.name # Save the name for later + + # Later + cache = genai.caching.CachedContent.get(cache_name) + apollo_model = genai.GenerativeModel.from_cached_content(cache) + response = apollo_model.generate_content("Find a lighthearted moment from this transcript") + print(response.text) + # [END cache_create_from_name] + cache.delete() + + def test_cache_create_from_chat(self): + # [START cache_create_from_chat] + import google.generativeai as genai + + model_name = "gemini-1.5-flash-001" + system_instruction = "You are an expert analyzing transcripts." + + model = genai.GenerativeModel(model_name=model_name, system_instruction=system_instruction) + chat = model.start_chat() + document = genai.upload_file(path=media / "a11.txt") + response = chat.send_message(["Hi, could you summarize this transcript?", document]) + print("\n\nmodel: ", response.text) + response = chat.send_message( + ["Okay, could you tell me more about the trans-lunar injection"] + ) + print("\n\nmodel: ", response.text) + + # To cache the conversation so far, pass the chat history as the list of "contents". + cache = genai.caching.CachedContent.create( + model=model_name, + system_instruction=system_instruction, + contents=chat.history, + ) + model = genai.GenerativeModel.from_cached_content(cached_content=cache) + + # Continue the chat where you left off. + chat = model.start_chat() + response = chat.send_message( + "I didn't understand that last part, could you explain it in simpler language?" + ) + print("\n\nmodel: ", response.text) + # [END cache_create_from_chat] + cache.delete() + + def test_cache_delete(self): + # [START cache_delete] + import google.generativeai as genai + + document = genai.upload_file(path=media / "a11.txt") + model_name = "gemini-1.5-flash-001" + cache = genai.caching.CachedContent.create( + model=model_name, + system_instruction="You are an expert analyzing transcripts.", + contents=[document], + ) + cache.delete() + # [END cache_delete] + + def test_cache_get(self): + # [START cache_get] + import google.generativeai as genai + + document = genai.upload_file(path=media / "a11.txt") + model_name = "gemini-1.5-flash-001" + cache = genai.caching.CachedContent.create( + model=model_name, + system_instruction="You are an expert analyzing transcripts.", + contents=[document], + ) + print(genai.caching.CachedContent.get(name=cache.name)) + # [END cache_get] + cache.delete() + + def test_cache_list(self): + # [START cache_list] + import google.generativeai as genai + + document = genai.upload_file(path=media / "a11.txt") + model_name = "gemini-1.5-flash-001" + cache = genai.caching.CachedContent.create( + model=model_name, + system_instruction="You are an expert analyzing transcripts.", + contents=[document], + ) + print("My caches:") + for c in genai.caching.CachedContent.list(): + print(" ", c.name) + # [END cache_list] + cache.delete() + + def test_cache_update(self): + # [START cache_update] + import google.generativeai as genai + + import datetime + + document = genai.upload_file(path=media / "a11.txt") + model_name = "gemini-1.5-flash-001" + cache = genai.caching.CachedContent.create( + model=model_name, + system_instruction="You are an expert analyzing transcripts.", + contents=[document], + ) + + # You can update the ttl + cache.update(ttl=datetime.timedelta(hours=2)) + print(f"After update:\n {cache}") + + # Or you can update the expire_time + cache.update(expire_time=datetime.datetime.now() + datetime.timedelta(minutes=15)) + # [END cache_update] + cache.delete() + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/chat.py b/examples/website_samples/chat.py new file mode 100644 index 000000000..d4d77eeca --- /dev/null +++ b/examples/website_samples/chat.py @@ -0,0 +1,89 @@ +# -*- 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 pathlib + +media = pathlib.Path(__file__).parents[1] / "third_party" + + +class UnitTests(absltest.TestCase): + def test_chat(self): + # [START chat] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + chat = model.start_chat( + history=[ + {"role": "user", "parts": "Hello"}, + {"role": "model", "parts": "Great to meet you. What would you like to know?"}, + ] + ) + response = chat.send_message("I have 2 dogs in my house.") + print(response.text) + response = chat.send_message("How many paws are in my house?") + print(response.text) + # [END chat] + + def test_chat_streaming(self): + # [START chat_streaming] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + chat = model.start_chat( + history=[ + {"role": "user", "parts": "Hello"}, + {"role": "model", "parts": "Great to meet you. What would you like to know?"}, + ] + ) + response = chat.send_message("I have 2 dogs in my house.", stream=True) + for chunk in response: + print(chunk.text) + print("_" * 80) + response = chat.send_message("How many paws are in my house?", stream=True) + for chunk in response: + print(chunk.text) + print("_" * 80) + + print(chat.history) + # [END chat_streaming] + + def test_chat_streaming_with_images(self): + # [START chat_streaming_with_images] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + chat = model.start_chat() + + response = chat.send_message( + "Hello, I'm interested in learning about musical instruments. Can I show you one?", + stream=True, + ) + for chunk in response: + print(chunk.text) # Yes. + print("_" * 80) + + organ = genai.upload_file(media / "organ.jpg") + response = chat.send_message( + ["What family of intruments does this instrument belong to?", organ], stream=True + ) + for chunk in response: + print(chunk.text) + print("_" * 80) + # [END chat_streaming_with_images] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/code_execution.py b/examples/website_samples/code_execution.py new file mode 100644 index 000000000..dfc2ce84e --- /dev/null +++ b/examples/website_samples/code_execution.py @@ -0,0 +1,202 @@ +# -*- 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 + + +class UnitTests(absltest.TestCase): + def test_code_execution_basic(self): + # [START code_execution_basic] + import google.generativeai as genai + + model = genai.GenerativeModel(model_name="gemini-1.5-flash", tools="code_execution") + response = model.generate_content( + ( + "What is the sum of the first 50 prime numbers? " + "Generate and run code for the calculation, and make sure you get all 50." + ) + ) + + # Each `part` either contains `text`, `executable_code` or an `execution_result` + for part in response.candidates[0].content.parts: + print(part, "\n") + + print("-" * 80) + # The `.text` accessor joins the parts into a markdown compatible text representation. + print("\n\n", response.text) + # [END code_execution_basic] + + # [START code_execution_basic_return] + import google.generativeai as genai + + # text: "I can help with that! To calculate the sum of the first 50 prime numbers, we\'ll need to first identify all the prime numbers up to the 50th prime number. \n\nHere is the code to find and sum the first 50 prime numbers:\n\n" + # + # executable_code { + # language: PYTHON + # code: "\ndef is_prime(n):\n \"\"\"\n Checks if a number is prime.\n \"\"\"\n if n <= 1:\n return False\n for i in range(2, int(n**0.5) + 1):\n if n % i == 0:\n return False\n return True\n\nprime_count = 0\nnumber = 2\nprimes = []\nwhile prime_count < 50:\n if is_prime(number):\n primes.append(number)\n prime_count += 1\n number += 1\n\nprint(f\'The sum of the first 50 prime numbers is: {sum(primes)}\')\n" + # } + # + # code_execution_result { + # outcome: OUTCOME_OK + # output: "The sum of the first 50 prime numbers is: 5117\n" + # } + # + # text: "I ran the code and it calculated that the sum of the first 50 prime numbers is 5117. \n" + # + # + # -------------------------------------------------------------------------------- + # I can help with that! To calculate the sum of the first 50 prime numbers, we'll need to first identify all the prime numbers up to the 50th prime number. + # + # Here is the code to find and sum the first 50 prime numbers: + # + # + # ``` python + # def is_prime(n): + # """ + # Checks if a number is prime. + # """ + # if n <= 1: + # return False + # for i in range(2, int(n**0.5) + 1): + # if n % i == 0: + # return False + # return True + # + # prime_count = 0 + # number = 2 + # primes = [] + # while prime_count < 50: + # if is_prime(number): + # primes.append(number) + # prime_count += 1 + # number += 1 + # + # print(f'The sum of the first 50 prime numbers is: {sum(primes)}') + # + # ``` + # ``` + # The sum of the first 50 prime numbers is: 5117 + # + # ``` + # I ran the code and it calculated that the sum of the first 50 prime numbers is 5117. + # [END code_execution_basic_return] + + def test_code_execution_request_override(self): + # [START code_execution_request_override] + import google.generativeai as genai + + model = genai.GenerativeModel(model_name="gemini-1.5-flash") + response = model.generate_content( + ( + "What is the sum of the first 50 prime numbers? " + "Generate and run code for the calculation, and make sure you get all 50." + ), + tools="code_execution", + ) + print(response.text) + # [END code_execution_request_override] + # [START code_execution_request_override_return] + import google.generativeai as genai + + # ``` python + # def is_prime(n): + # """ + # Checks if a number is prime. + # """ + # if n <= 1: + # return False + # for i in range(2, int(n**0.5) + 1): + # if n % i == 0: + # return False + # return True + # + # primes = [] + # num = 2 + # count = 0 + # while count < 50: + # if is_prime(num): + # primes.append(num) + # count += 1 + # num += 1 + # + # print(f'The first 50 prime numbers are: {primes}') + # print(f'The sum of the first 50 prime numbers is: {sum(primes)}') + # + # ``` + # ``` + # The first 50 prime numbers are: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229] + # The sum of the first 50 prime numbers is: 5117 + # + # ``` + # The code generated a list of the first 50 prime numbers, then sums the list to find the answer. + # + # The sum of the first 50 prime numbers is **5117**. + # [END code_execution_request_override_return] + + def test_code_execution_chat(self): + # [START code_execution_chat] + import google.generativeai as genai + + model = genai.GenerativeModel(model_name="gemini-1.5-flash", tools="code_execution") + chat = model.start_chat() + response = chat.send_message('Can you print "Hello world!"?') + response = chat.send_message( + ( + "What is the sum of the first 50 prime numbers? " + "Generate and run code for the calculation, and make sure you get all 50." + ) + ) + print(response.text) + # [END code_execution_chat] + # [START code_execution_chat_return] + import google.generativeai as genai + + # ``` python + # def is_prime(n): + # """ + # Checks if a number is prime. + # """ + # if n <= 1: + # return False + # for i in range(2, int(n**0.5) + 1): + # if n % i == 0: + # return False + # return True + # + # primes = [] + # num = 2 + # count = 0 + # while count < 50: + # if is_prime(num): + # primes.append(num) + # count += 1 + # num += 1 + # + # print(f'The first 50 prime numbers are: {primes}') + # print(f'The sum of the first 50 prime numbers is: {sum(primes)}') + # + # ``` + # ``` + # The first 50 prime numbers are: [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229] + # The sum of the first 50 prime numbers is: 5117 + # + # ``` + # The code generated a list of the first 50 prime numbers, then sums the list to find the answer. + # + # The sum of the first 50 prime numbers is **5117**. + # [END code_execution_chat_return] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/configure_model_parameters.py b/examples/website_samples/configure_model_parameters.py new file mode 100644 index 000000000..3fe28a5a8 --- /dev/null +++ b/examples/website_samples/configure_model_parameters.py @@ -0,0 +1,40 @@ +# -*- 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 + + +class UnitTests(absltest.TestCase): + def test_configure_model(self): + # [START configure_model_parameters] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + response = model.generate_content( + "Tell me a story about a magic backpack.", + generation_config=genai.types.GenerationConfig( + # Only one candidate for now. + candidate_count=1, + stop_sequences=["x"], + max_output_tokens=20, + temperature=1.0, + ), + ) + + print(response.text) + # [END configure_model_parameters] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/controlled_generation.py b/examples/website_samples/controlled_generation.py new file mode 100644 index 000000000..5caa9b7d4 --- /dev/null +++ b/examples/website_samples/controlled_generation.py @@ -0,0 +1,178 @@ +# +# 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 pathlib + + +media = pathlib.Path(__file__).parents[1] / "third_party" + + +class UnitTests(absltest.TestCase): + def test_json_controlled_generation(self): + # [START json_controlled_generation] + import google.generativeai as genai + + import typing_extensions as typing + + class Recipe(typing.TypedDict): + recipe_name: str + ingredients: list[str] + + model = genai.GenerativeModel("gemini-1.5-pro-latest") + result = model.generate_content( + "List a few popular cookie recipes.", + generation_config=genai.GenerationConfig( + response_mime_type="application/json", response_schema=list[Recipe] + ), + ) + print(result) + # [END json_controlled_generation] + + def test_json_no_schema(self): + # [START json_no_schema] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-pro-latest") + prompt = """List a few popular cookie recipes in JSON format. + + Use this JSON schema: + + Recipe = {'recipe_name': str, 'ingredients': list[str]} + Return: list[Recipe]""" + result = model.generate_content(prompt) + print(result) + # [END json_no_schema] + + def test_json_enum(self): + # [START json_enum] + import google.generativeai as genai + + import enum + + class Choice(enum.Enum): + PERCUSSION = "Percussion" + STRING = "String" + WOODWIND = "Woodwind" + BRASS = "Brass" + KEYBOARD = "Keyboard" + + model = genai.GenerativeModel("gemini-1.5-pro-latest") + + organ = genai.upload_file(media / "organ.jpg") + result = model.generate_content( + ["What kind of instrument is this:", organ], + generation_config=genai.GenerationConfig( + response_mime_type="application/json", response_schema=Choice + ), + ) + print(result) # "Keyboard" + # [END json_enum] + + def test_enum_in_json(self): + # [START enum_in_json] + import google.generativeai as genai + + import enum + from typing_extensions import TypedDict + + class Grade(enum.Enum): + A_PLUS = "a+" + A = "a" + B = "b" + C = "c" + D = "d" + F = "f" + + class Recipe(TypedDict): + recipe_name: str + grade: Grade + + model = genai.GenerativeModel("gemini-1.5-pro-latest") + + result = model.generate_content( + "List about 10 cookie recipes, grade them based on popularity", + generation_config=genai.GenerationConfig( + response_mime_type="application/json", response_schema=list[Recipe] + ), + ) + print(result) # [{"grade": "a+", "recipe_name": "Chocolate Chip Cookies"}, ...] + # [END enum_in_json] + + def test_json_enum_raw(self): + # [START json_enum_raw] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-pro-latest") + + organ = genai.upload_file(media / "organ.jpg") + result = model.generate_content( + ["What kind of instrument is this:", organ], + generation_config=genai.GenerationConfig( + response_mime_type="application/json", + response_schema={ + "type": "STRING", + "enum": ["Percussion", "String", "Woodwind", "Brass", "Keyboard"], + }, + ), + ) + print(result) # "Keyboard" + # [END json_enum_raw] + + def test_x_enum(self): + # [START x_enum] + import google.generativeai as genai + + import enum + + class Choice(enum.Enum): + PERCUSSION = "Percussion" + STRING = "String" + WOODWIND = "Woodwind" + BRASS = "Brass" + KEYBOARD = "Keyboard" + + model = genai.GenerativeModel("gemini-1.5-pro-latest") + + organ = genai.upload_file(media / "organ.jpg") + result = model.generate_content( + ["What kind of instrument is this:", organ], + generation_config=genai.GenerationConfig( + response_mime_type="text/x.enum", response_schema=Choice + ), + ) + print(result) # Keyboard + # [END x_enum] + + def test_x_enum_raw(self): + # [START x_enum_raw] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-pro-latest") + + organ = genai.upload_file(media / "organ.jpg") + result = model.generate_content( + ["What kind of instrument is this:", organ], + generation_config=genai.GenerationConfig( + response_mime_type="text/x.enum", + response_schema={ + "type": "STRING", + "enum": ["Percussion", "String", "Woodwind", "Brass", "Keyboard"], + }, + ), + ) + print(result) # Keyboard + # [END x_enum_raw] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/count_tokens.py b/examples/website_samples/count_tokens.py new file mode 100644 index 000000000..33431dde8 --- /dev/null +++ b/examples/website_samples/count_tokens.py @@ -0,0 +1,296 @@ +# -*- 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 pathlib + +media = pathlib.Path(__file__).parents[1] / "third_party" + + +class UnitTests(absltest.TestCase): + def test_tokens_context_window(self): + # [START tokens_context_window] + import google.generativeai as genai + + model_info = genai.get_model("models/gemini-1.5-flash") + + # Returns the "context window" for the model, + # which is the combined input and output token limits. + print(f"{model_info.input_token_limit=}") + print(f"{model_info.output_token_limit=}") + # ( input_token_limit=30720, output_token_limit=2048 ) + # [END tokens_context_window] + + def test_tokens_text_only(self): + # [START tokens_text_only] + import google.generativeai as genai + + model = genai.GenerativeModel("models/gemini-1.5-flash") + + prompt = "The quick brown fox jumps over the lazy dog." + + # Call `count_tokens` to get the input token count (`total_tokens`). + print("total_tokens: ", model.count_tokens(prompt)) + # ( total_tokens: 10 ) + + response = model.generate_content(prompt) + + # On the response for `generate_content`, use `usage_metadata` + # to get separate input and output token counts + # (`prompt_token_count` and `candidates_token_count`, respectively), + # as well as the combined token count (`total_token_count`). + print(response.usage_metadata) + # ( prompt_token_count: 11, candidates_token_count: 73, total_token_count: 84 ) + # [END tokens_text_only] + + def test_tokens_chat(self): + # [START tokens_chat] + import google.generativeai as genai + + model = genai.GenerativeModel("models/gemini-1.5-flash") + + chat = model.start_chat( + history=[ + {"role": "user", "parts": "Hi my name is Bob"}, + {"role": "model", "parts": "Hi Bob!"}, + ] + ) + # Call `count_tokens` to get the input token count (`total_tokens`). + print(model.count_tokens(chat.history)) + # ( total_tokens: 10 ) + + response = chat.send_message( + "In one sentence, explain how a computer works to a young child." + ) + + # On the response for `send_message`, use `usage_metadata` + # to get separate input and output token counts + # (`prompt_token_count` and `candidates_token_count`, respectively), + # as well as the combined token count (`total_token_count`). + print(response.usage_metadata) + # ( prompt_token_count: 25, candidates_token_count: 21, total_token_count: 46 ) + + from google.generativeai.types.content_types import to_contents + + # You can call `count_tokens` on the combined history and content of the next turn. + print(model.count_tokens(chat.history + to_contents("What is the meaning of life?"))) + # ( total_tokens: 56 ) + # [END tokens_chat] + + def test_tokens_multimodal_image_inline(self): + # [START tokens_multimodal_image_inline] + import google.generativeai as genai + + import PIL.Image + + model = genai.GenerativeModel("models/gemini-1.5-flash") + + prompt = "Tell me about this image" + your_image_file = PIL.Image.open(media / "organ.jpg") + + # Call `count_tokens` to get the input token count + # of the combined text and file (`total_tokens`). + # An image's display or file size does not affect its token count. + # Optionally, you can call `count_tokens` for the text and file separately. + print(model.count_tokens([prompt, your_image_file])) + # ( total_tokens: 263 ) + + response = model.generate_content([prompt, your_image_file]) + + # On the response for `generate_content`, use `usage_metadata` + # to get separate input and output token counts + # (`prompt_token_count` and `candidates_token_count`, respectively), + # as well as the combined token count (`total_token_count`). + print(response.usage_metadata) + # ( prompt_token_count: 264, candidates_token_count: 80, total_token_count: 345 ) + # [END tokens_multimodal_image_inline] + + def test_tokens_multimodal_image_file_api(self): + # [START tokens_multimodal_image_file_api] + import google.generativeai as genai + + model = genai.GenerativeModel("models/gemini-1.5-flash") + + prompt = "Tell me about this image" + your_image_file = genai.upload_file(path=media / "organ.jpg") + + # Call `count_tokens` to get the input token count + # of the combined text and file (`total_tokens`). + # An image's display or file size does not affect its token count. + # Optionally, you can call `count_tokens` for the text and file separately. + print(model.count_tokens([prompt, your_image_file])) + # ( total_tokens: 263 ) + + response = model.generate_content([prompt, your_image_file]) + response.text + # On the response for `generate_content`, use `usage_metadata` + # to get separate input and output token counts + # (`prompt_token_count` and `candidates_token_count`, respectively), + # as well as the combined token count (`total_token_count`). + print(response.usage_metadata) + # ( prompt_token_count: 264, candidates_token_count: 80, total_token_count: 345 ) + # [END tokens_multimodal_image_file_api] + + def test_tokens_multimodal_video_audio_file_api(self): + # [START tokens_multimodal_video_audio_file_api] + import google.generativeai as genai + + import time + + model = genai.GenerativeModel("models/gemini-1.5-flash") + + prompt = "Tell me about this video" + your_file = genai.upload_file(path=media / "Big_Buck_Bunny.mp4") + + # Videos need to be processed before you can use them. + while your_file.state.name == "PROCESSING": + print("processing video...") + time.sleep(5) + your_file = genai.get_file(your_file.name) + + # Call `count_tokens` to get the input token count + # of the combined text and video/audio file (`total_tokens`). + # A video or audio file is converted to tokens at a fixed rate of tokens per second. + # Optionally, you can call `count_tokens` for the text and file separately. + print(model.count_tokens([prompt, your_file])) + # ( total_tokens: 300 ) + + response = model.generate_content([prompt, your_file]) + + # On the response for `generate_content`, use `usage_metadata` + # to get separate input and output token counts + # (`prompt_token_count` and `candidates_token_count`, respectively), + # as well as the combined token count (`total_token_count`). + print(response.usage_metadata) + # ( prompt_token_count: 301, candidates_token_count: 60, total_token_count: 361 ) + + # [END tokens_multimodal_video_audio_file_api] + + def test_tokens_multimodal_pdf_file_api(self): + # [START tokens_multimodal_pdf_file_api] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + sample_pdf = genai.upload_file(media / "test.pdf") + token_count = model.count_tokens(["Give me a summary of this document.", sample_pdf]) + print(f"{token_count=}") + + response = model.generate_content(["Give me a summary of this document.", sample_pdf]) + print(response.usage_metadata) + # [END tokens_multimodal_pdf_file_api] + + def test_tokens_cached_content(self): + # [START tokens_cached_content] + import google.generativeai as genai + + import time + + model = genai.GenerativeModel("models/gemini-1.5-flash") + + your_file = genai.upload_file(path=media / "a11.txt") + + cache = genai.caching.CachedContent.create( + model="models/gemini-1.5-flash-001", + # You can set the system_instruction and tools + system_instruction=None, + tools=None, + contents=["Here the Apollo 11 transcript:", your_file], + ) + + model = genai.GenerativeModel.from_cached_content(cache) + + prompt = "Please give a short summary of this file." + + # Call `count_tokens` to get input token count + # of the combined text and file (`total_tokens`). + # A video or audio file is converted to tokens at a fixed rate of tokens per second. + # Optionally, you can call `count_tokens` for the text and file separately. + print(model.count_tokens(prompt)) + # ( total_tokens: 9 ) + + response = model.generate_content(prompt) + + # On the response for `generate_content`, use `usage_metadata` + # to get separate input and output token counts + # (`prompt_token_count` and `candidates_token_count`, respectively), + # as well as the cached content token count and the combined total token count. + print(response.usage_metadata) + # ( prompt_token_count: 323393, cached_content_token_count: 323383, candidates_token_count: 64) + # ( total_token_count: 323457 ) + + cache.delete() + # [END tokens_cached_content] + + def test_tokens_system_instruction(self): + # [START tokens_system_instruction] + import google.generativeai as genai + + model = genai.GenerativeModel(model_name="gemini-1.5-flash") + + prompt = "The quick brown fox jumps over the lazy dog." + + print(model.count_tokens(prompt)) + # total_tokens: 10 + + model = genai.GenerativeModel( + model_name="gemini-1.5-flash", system_instruction="You are a cat. Your name is Neko." + ) + + # The total token count includes everything sent to the `generate_content` request. + # When you use system instructions, the total token count increases. + print(model.count_tokens(prompt)) + # ( total_tokens: 21 ) + # [END tokens_system_instruction] + + def test_tokens_tools(self): + # [START tokens_tools] + import google.generativeai as genai + + model = genai.GenerativeModel(model_name="gemini-1.5-flash") + + prompt = "I have 57 cats, each owns 44 mittens, how many mittens is that in total?" + + print(model.count_tokens(prompt)) + # ( total_tokens: 22 ) + + 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] + ) + + # The total token count includes everything sent to the `generate_content` request. + # When you use tools (like function calling), the total token count increases. + print(model.count_tokens(prompt)) + # ( total_tokens: 206 ) + # [END tokens_tools] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/embed.py b/examples/website_samples/embed.py new file mode 100644 index 000000000..a5897639b --- /dev/null +++ b/examples/website_samples/embed.py @@ -0,0 +1,47 @@ +# -*- 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 + + +class UnitTests(absltest.TestCase): + def test_embed_content(self): + # [START embed_content] + import google.generativeai as genai + + text = "Hello World!" + result = genai.embed_content( + model="models/text-embedding-004", content=text, output_dimensionality=10 + ) + print(result["embedding"]) + # [END embed_content] + + def batch_embed_contents(self): + # [START batch_embed_contents] + import google.generativeai as genai + + texts = [ + "What is the meaning of life?", + "How much wood would a woodchuck chuck?", + "How does the brain work?", + ] + result = genai.embed_content( + model="models/text-embedding-004", content=texts, output_dimensionality=10 + ) + print(result) + # [END batch_embed_contents] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/files.py b/examples/website_samples/files.py new file mode 100644 index 000000000..0011f4da2 --- /dev/null +++ b/examples/website_samples/files.py @@ -0,0 +1,148 @@ +# -*- 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 pathlib + +media = pathlib.Path(__file__).parents[1] / "third_party" + + +class UnitTests(absltest.TestCase): + def test_files_create_text(self): + # [START files_create_text] + import google.generativeai as genai + + myfile = genai.upload_file(media / "poem.txt") + print(f"{myfile=}") + + model = genai.GenerativeModel("gemini-1.5-flash") + result = model.generate_content( + [myfile, "\n\n", "Can you add a few more lines to this poem?"] + ) + print(f"{result.text=}") + # [END files_create_text] + + def test_files_create_image(self): + # [START files_create_image] + import google.generativeai as genai + + myfile = genai.upload_file(media / "Cajun_instruments.jpg") + print(f"{myfile=}") + + model = genai.GenerativeModel("gemini-1.5-flash") + result = model.generate_content( + [myfile, "\n\n", "Can you tell me about the instruments in this photo?"] + ) + print(f"{result.text=}") + # [END files_create_image] + + def test_files_create_audio(self): + # [START files_create_audio] + import google.generativeai as genai + + myfile = genai.upload_file(media / "sample.mp3") + print(f"{myfile=}") + + model = genai.GenerativeModel("gemini-1.5-flash") + result = model.generate_content([myfile, "Describe this audio clip"]) + print(f"{result.text=}") + # [END files_create_audio] + + def test_files_create_video(self): + # [START files_create_video] + import google.generativeai as genai + + import time + + # Video clip (CC BY 3.0) from https://peach.blender.org/download/ + myfile = genai.upload_file(media / "Big_Buck_Bunny.mp4") + print(f"{myfile=}") + + # Videos need to be processed before you can use them. + while myfile.state.name == "PROCESSING": + print("processing video...") + time.sleep(5) + myfile = genai.get_file(myfile.name) + + model = genai.GenerativeModel("gemini-1.5-flash") + result = model.generate_content([myfile, "Describe this video clip"]) + print(f"{result.text=}") + # [END files_create_video] + + def test_files_create_pdf(self): + # [START files_create_pdf] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + sample_pdf = genai.upload_file(media / "test.pdf") + response = model.generate_content(["Give me a summary of this pdf file.", sample_pdf]) + print(response.text) + # [END files_create_pdf] + + def test_files_create_from_IO(self): + # [START files_create_io] + import google.generativeai as genai + + # You can pass a file-like object, instead of a path. + # Useful for streaming. + model = genai.GenerativeModel("gemini-1.5-flash") + fpath = media / "test.pdf" + with open(fpath, "rb") as f: + sample_pdf = genai.upload_file(f, mime_type="application/pdf") + response = model.generate_content(["Give me a summary of this pdf file.", sample_pdf]) + print(response.text) + # [END files_create_io] + + def test_files_list(self): + # [START files_list] + import google.generativeai as genai + + print("My files:") + for f in genai.list_files(): + print(" ", f.name) + # [END files_list] + + def test_files_get(self): + # [START files_get] + import google.generativeai as genai + + myfile = genai.upload_file(media / "poem.txt") + file_name = myfile.name + print(file_name) # "files/*" + + myfile = genai.get_file(file_name) + print(myfile) + # [END files_get] + + def test_files_delete(self): + # [START files_delete] + import google.generativeai as genai + + myfile = genai.upload_file(media / "poem.txt") + + myfile.delete() + + try: + # Error. + model = genai.GenerativeModel("gemini-1.5-flash") + result = model.generate_content([myfile, "Describe this file."]) + except google.api_core.exceptions.PermissionDenied: + pass + # [END files_delete] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/function_calling.py b/examples/website_samples/function_calling.py new file mode 100644 index 000000000..829b97742 --- /dev/null +++ b/examples/website_samples/function_calling.py @@ -0,0 +1,51 @@ +# -*- 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 + + +class UnitTests(absltest.TestCase): + def test_function_calling(self): + # [START function_calling] + import google.generativeai as genai + + 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( + model_name="gemini-1.5-flash", tools=[add, subtract, multiply, divide] + ) + chat = model.start_chat(enable_automatic_function_calling=True) + response = chat.send_message( + "I have 57 cats, each owns 44 mittens, how many mittens is that in total?" + ) + print(response.text) + # [END function_calling] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/increment_tuning_data.json b/examples/website_samples/increment_tuning_data.json new file mode 100644 index 000000000..1c1ecc5ff --- /dev/null +++ b/examples/website_samples/increment_tuning_data.json @@ -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" + } +] \ No newline at end of file diff --git a/examples/website_samples/models.py b/examples/website_samples/models.py new file mode 100644 index 000000000..1eea4b31e --- /dev/null +++ b/examples/website_samples/models.py @@ -0,0 +1,44 @@ +# -*- 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 + + +class UnitTests(absltest.TestCase): + def test_models_list(self): + # [START models_list] + import google.generativeai as genai + + print("List of models that support generateContent:\n") + for m in genai.list_models(): + if "generateContent" in m.supported_generation_methods: + print(m.name) + + print("List of models that support embedContent:\n") + for m in genai.list_models(): + if "embedContent" in m.supported_generation_methods: + print(m.name) + # [END models_list] + + def test_models_get(self): + # [START models_get] + import google.generativeai as genai + + model_info = genai.get_model("models/gemini-1.5-flash-latest") + print(model_info) + # [END models_get] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/rest/README.md b/examples/website_samples/rest/README.md new file mode 100644 index 000000000..7969097d2 --- /dev/null +++ b/examples/website_samples/rest/README.md @@ -0,0 +1,26 @@ +# Gemini API REST sample code + +This directory contains sample code for key features of the API, organised by high level feature. + +These samples are embedded in parts of the [documentation](https://ai.google.dev), most notably in the [API reference](https://ai.google.dev/api). + +Each file is structured as a runnable script, ensuring that samples are executable and functional. Each filee contains region tags that are used to demarcate the script from the spotlight code. If you are contributing, code within region tags should follow sample code best practices - being clear, complete and concise. + +## Contents + +| File | Description | +| ---- | ----------- | +| [cache.sh](./cache.sh) | Context caching | +| [chat.sh](./chat.sh) | Multi-turn chat conversations | +| [code_execution.sh](./code_execution.sh) | Executing code | +| [configure_model_parameters.sh](./configure_model_parameters.sh) | Setting model parameters | +| [controlled_generation.sh](./controlled_generation.sh) | Generating content with output constraints (e.g. JSON mode) | +| [count_tokens.sh](./count_tokens.sh) | Counting input and output tokens | +| [embed.sh](./embed.sh) | Generating embeddings | +| [files.sh](./files.sh) | Managing files with the File API | +| [function_calling.sh](./function_calling.sh) | Using function calling | +| [models.sh](./models.sh) | Listing models and model metadata | +| [safety_settings.sh](./safety_settings.sh) | Setting and using safety controls | +| [system_instruction.sh](./system_instruction.sh) | Setting system instructions | +| [text_generation.sh](./text_generation.sh) | Generating text | +| [tuned_models.sh](./tuned_models.sh) | Tuned models | diff --git a/examples/website_samples/rest/cache.sh b/examples/website_samples/rest/cache.sh new file mode 100644 index 000000000..218b5e4b1 --- /dev/null +++ b/examples/website_samples/rest/cache.sh @@ -0,0 +1,83 @@ +set -eu + +if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then + B64FLAGS="--input" +else + B64FLAGS="-w0" +fi + +echo "[START cache_create]" +# [START cache_create] +wget https://storage.googleapis.com/generativeai-downloads/data/a11.txt +echo '{ + "model": "models/gemini-1.5-flash-001", + "contents":[ + { + "parts":[ + { + "inline_data": { + "mime_type":"text/plain", + "data": "'$(base64 $B64FLAGS a11.txt)'" + } + } + ], + "role": "user" + } + ], + "systemInstruction": { + "parts": [ + { + "text": "You are an expert at analyzing transcripts." + } + ] + }, + "ttl": "300s" +}' > request.json + +curl -X POST "https://generativelanguage.googleapis.com/v1beta/cachedContents?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -d @request.json \ + > cache.json + +CACHE_NAME=$(cat cache.json | grep '"name":' | cut -d '"' -f 4 | head -n 1) + +echo "[START cache_generate_content]" +# [START cache_generate_content] +curl -X POST "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-001:generateContent?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d '{ + "contents": [ + { + "parts":[{ + "text": "Please summarize this transcript" + }], + "role": "user" + }, + ], + "cachedContent": "'$CACHE_NAME'" + }' +# [END cache_generate_content] +# [END cache_create] +rm a11.txt request.json + +echo "[START cache_list]" +# [START cache_list] +curl "https://generativelanguage.googleapis.com/v1beta/cachedContents?key=$GOOGLE_API_KEY" +# [END cache_list] + +echo "[START cache_get]" +# [START cache_get] +curl "https://generativelanguage.googleapis.com/v1beta/$CACHE_NAME?key=$GOOGLE_API_KEY" +# [END cache_get] + +echo "[START cache_update]" +# [START cache_update] +curl -X PATCH "https://generativelanguage.googleapis.com/v1beta/$CACHE_NAME?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -d '{"ttl": "600s"}' +# [END cache_update] + +echo "[START cache_delete]" +# [START cache_delete] +curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/$CACHE_NAME?key=$GOOGLE_API_KEY" +# [END cache_delete] \ No newline at end of file diff --git a/examples/website_samples/rest/chat.sh b/examples/website_samples/rest/chat.sh new file mode 100644 index 000000000..78e6f9917 --- /dev/null +++ b/examples/website_samples/rest/chat.sh @@ -0,0 +1,93 @@ +set -eu + +SCRIPT_DIR=$(dirname "$0") +MEDIA_DIR=$(realpath ${SCRIPT_DIR}/../../third_party) + +echo "[START chat]" +# [START chat] +curl https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [ + {"role":"user", + "parts":[{ + "text": "Hello"}]}, + {"role": "model", + "parts":[{ + "text": "Great to meet you. What would you like to know?"}]}, + {"role":"user", + "parts":[{ + "text": "I have two dogs in my house. How many paws are in my house?"}]}, + ] + }' 2> /dev/null | grep "text" +# [END chat] + +echo "[START chat_streaming]" +# [START chat_streaming] +curl https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:streamGenerateContent?alt=sse&key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [ + {"role":"user", + "parts":[{ + "text": "Hello"}]}, + {"role": "model", + "parts":[{ + "text": "Great to meet you. What would you like to know?"}]}, + {"role":"user", + "parts":[{ + "text": "I have two dogs in my house. How many paws are in my house?"}]}, + ] + }' 2> /dev/null | grep "text" +# [END chat_streaming] + +echo "[START chat_streaming_with_images]" +# [START chat_streaming_with_images] +IMG_PATH=${MEDIA_DIR}/organ.jpg + +if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then + B64FLAGS="--input" +else + B64FLAGS="-w0" +fi + +curl https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:streamGenerateContent?alt=sse&key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [ + { + "role": "user", + "parts": [ + { + "text": "Hello, I am interested in learning about musical instruments. Can I show you one?" + } + ] + }, + { + "role": "model", + "parts": [ + { + "text": "Certainly." + }, + ] + }, + { + "role": "user", + "parts": [ + { + "text": "Tell me about this instrument" + }, + { + "inline_data": { + "mime_type": "image/jpeg", + "data": "'$(base64 $B64FLAGS $IMG_PATH)'" + } + } + ] + } + ] + }' 2> /dev/null | grep "text" +# [END chat_streaming_with_images] \ No newline at end of file diff --git a/examples/website_samples/rest/code_execution.sh b/examples/website_samples/rest/code_execution.sh new file mode 100644 index 000000000..44fbf679c --- /dev/null +++ b/examples/website_samples/rest/code_execution.sh @@ -0,0 +1,58 @@ +set -eu + +echo "[START code_execution_basic]" +# [START code_execution_basic] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d ' {"tools": [{"code_execution": {}}], + "contents": { + "parts": + { + "text": "What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50." + } + }, +}' +# [END code_execution_basic] + +echo "[START code_execution_chat]" +# [START code_execution_chat] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d '{"tools": [{"code_execution": {}}], + "contents": [ + { + "role": "user", + "parts": [{ + "text": "Can you print \"Hello world!\"?" + }] + },{ + "role": "model", + "parts": [ + { + "text": "" + }, + { + "executable_code": { + "language": "PYTHON", + "code": "\nprint(\"hello world!\")\n" + } + }, + { + "code_execution_result": { + "outcome": "OUTCOME_OK", + "output": "hello world!\n" + } + }, + { + "text": "I have printed \"hello world!\" using the provided python code block. \n" + } + ], + },{ + "role": "user", + "parts": [{ + "text": "What is the sum of the first 50 prime numbers? Generate and run code for the calculation, and make sure you get all 50." + }] + } + ] +}' +# [END code_execution_chat] diff --git a/examples/website_samples/rest/configure_model_parameters.sh b/examples/website_samples/rest/configure_model_parameters.sh new file mode 100644 index 000000000..bd8d9d4c6 --- /dev/null +++ b/examples/website_samples/rest/configure_model_parameters.sh @@ -0,0 +1,30 @@ +set -eu + +echo "[START configure_model_parameters]" +# [START configure_model_parameters] +curl https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Write a story about a magic backpack."} + ] + }], + "safetySettings": [ + { + "category": "HARM_CATEGORY_DANGEROUS_CONTENT", + "threshold": "BLOCK_ONLY_HIGH" + } + ], + "generationConfig": { + "stopSequences": [ + "Title" + ], + "temperature": 1.0, + "maxOutputTokens": 800, + "topP": 0.8, + "topK": 10 + } + }' 2> /dev/null | grep "text" +# [END configure_model_parameters] diff --git a/examples/website_samples/rest/controlled_generation.sh b/examples/website_samples/rest/controlled_generation.sh new file mode 100644 index 000000000..533870649 --- /dev/null +++ b/examples/website_samples/rest/controlled_generation.sh @@ -0,0 +1,44 @@ +set -eu + +echo "json_controlled_generation" +# [START json_controlled_generation] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d '{ + "contents": [{ + "parts":[ + {"text": "List 5 popular cookie recipes"} + ] + }], + "generationConfig": { + "response_mime_type": "application/json", + "response_schema": { + "type": "ARRAY", + "items": { + "type": "OBJECT", + "properties": { + "recipe_name": {"type":"STRING"}, + } + } + } + } +}' 2> /dev/null | head +# [END json_controlled_generation] + +echo "json_no_schema" +# [START json_no_schema] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d '{ + "contents": [{ + "parts":[ + {"text": "List a few popular cookie recipes using this JSON schema: + + Recipe = {\"recipe_name\": str} + Return: list[Recipe]" + } + ] + }], + "generationConfig": { "response_mime_type": "application/json" } +}' 2> /dev/null | head +# [END json_no_schema] diff --git a/examples/website_samples/rest/count_tokens.sh b/examples/website_samples/rest/count_tokens.sh new file mode 100644 index 000000000..e69fd6d1c --- /dev/null +++ b/examples/website_samples/rest/count_tokens.sh @@ -0,0 +1,288 @@ +set -eu + +SCRIPT_DIR=$(dirname "$0") +MEDIA_DIR=$(realpath ${SCRIPT_DIR}/../../third_party) + +TEXT_PATH=${MEDIA_DIR}/poem.txt +A11_PATH=${MEDIA_DIR}/a11.txt +IMG_PATH=${MEDIA_DIR}/organ.jpg +AUDIO_PATH=${MEDIA_DIR}/sample.mp3 +VIDEO_PATH=${MEDIA_DIR}/Big_Buck_Bunny.mp4 + +BASE_URL="https://generativelanguage.googleapis.com" + +if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then + B64FLAGS="--input" +else + B64FLAGS="-w0" +fi + +echo "[START tokens_context_window]" +# [START tokens_context_window] +curl https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro?key=$GOOGLE_API_KEY > model.json +jq .inputTokenLimit model.json +jq .outputTokenLimit model.json +# [END tokens_context_window] + +echo "[START tokens_text_only]" +# [START tokens_text_only] +curl https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:countTokens?key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[{ + "text": "The quick brown fox jumps over the lazy dog." + }], + }], + }' +# [END tokens_text_only] + +echo "[START tokens_chat]" +# [START tokens_chat] +curl https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:countTokens?key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [ + {"role": "user", + "parts": [{"text": "Hi, my name is Bob."}], + }, + {"role": "model", + "parts":[{"text": "Hi Bob"}], + }, + ], + }' +# [END tokens_chat] + +echo "[START tokens_multimodal_image_inline]" +# [START tokens_multimodal_image_inline] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:countTokens?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Tell me about this instrument"}, + { + "inline_data": { + "mime_type":"image/jpeg", + "data": "'$(base64 $B64FLAGS $IMG_PATH)'" + } + } + ] + }] + }' 2> /dev/null +# [END tokens_multimodal_image_inline] + +echo "[START tokens_multimodal_image_file_api]" +# [START tokens_multimodal_image_file_api] +MIME_TYPE=$(file -b --mime-type "${IMG_PATH}") +NUM_BYTES=$(wc -c < "${IMG_PATH}") +DISPLAY_NAME=TEXT + +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${IMG_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:countTokens?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Can you tell me about the instruments in this photo?"}, + {"file_data": + {"mime_type": "image/jpeg", + "file_uri": '$file_uri'} + }] + }] + }' +# [END tokens_multimodal_image_file_api] + +echo "# [START tokens_multimodal_video_audio_file_api]" +# [START tokens_multimodal_video_audio_file_api] + +MIME_TYPE=$(file -b --mime-type "${VIDEO_PATH}") +NUM_BYTES=$(wc -c < "${VIDEO_PATH}") +DISPLAY_NAME=VIDEO_PATH + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${VIDEO_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) + +state=$(jq ".file.state" file_info.json) + +name=$(jq ".file.name" file_info.json) + +while [[ "($state)" = *"PROCESSING"* ]]; +do + echo "Processing video..." + sleep 5 + # Get the file of interest to check state + curl https://generativelanguage.googleapis.com/v1beta/files/$name > file_info.json + state=$(jq ".file.state" file_info.json) +done + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:countTokens?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Describe this video clip"}, + {"file_data":{"mime_type": "video/mp4", "file_uri": '$file_uri'}}] + }] + }' +# [END tokens_multimodal_video_audio_file_api] + +echo "[START tokens_cached_content]" +# [START tokens_cached_content] +echo '{ + "model": "models/gemini-1.5-flash-001", + "contents":[ + { + "parts":[ + { + "inline_data": { + "mime_type":"text/plain", + "data": "'$(base64 $B64FLAGS $A11_PATH)'" + } + } + ], + "role": "user" + } + ], + "systemInstruction": { + "parts": [ + { + "text": "You are an expert at analyzing transcripts." + } + ] + }, + "ttl": "300s" +}' > request.json + +curl -X POST "https://generativelanguage.googleapis.com/v1beta/cachedContents?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -d @request.json \ + > cache.json + +jq .usageMetadata.totalTokenCount cache.json +# [END tokens_cached_content] + +echo "[START tokens_system_instruction]" +# [START tokens_system_instruction] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d '{ "system_instruction": { + "parts": + { "text": "You are a cat. Your name is Neko."}}, + "contents": { + "parts": { + "text": "Hello there"}}}' > system_instructions.json + +jq .usageMetadata.totalTokenCount system_instructions.json +# [END tokens_system_instruction] + +echo "[START tokens_tools]" +# [START tokens_tools] +cat > tools.json << EOF +{ + "function_declarations": [ + { + "name": "enable_lights", + "description": "Turn on the lighting system.", + "parameters": { "type": "object" } + }, + { + "name": "set_light_color", + "description": "Set the light color. Lights must be enabled for this to work.", + "parameters": { + "type": "object", + "properties": { + "rgb_hex": { + "type": "string", + "description": "The light color as a 6-digit hex string, e.g. ff0000 for red." + } + }, + "required": [ + "rgb_hex" + ] + } + }, + { + "name": "stop_lights", + "description": "Turn off the lighting system.", + "parameters": { "type": "object" } + } + ] +} +EOF + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -d ' + { + "system_instruction": { + "parts": { + "text": "You are a helpful lighting system bot. You can turn lights on and off, and you can set the color. Do not perform any other tasks." + } + }, + "tools": ['$(source "$tools")'], + + "tool_config": { + "function_calling_config": {"mode": "none"} + }, + + "contents": { + "role": "user", + "parts": { + "text": "What can you do?" + } + } + } +' > tools_output.json + +jq .usageMetadata.totalTokenCount tools_output.json +# [END tokens_tools] \ No newline at end of file diff --git a/examples/website_samples/rest/embed.sh b/examples/website_samples/rest/embed.sh new file mode 100644 index 000000000..26fa11d44 --- /dev/null +++ b/examples/website_samples/rest/embed.sh @@ -0,0 +1,32 @@ +set -eu + +echo "[START embed_content]" +# [START embed_content] +curl "https://generativelanguage.googleapis.com/v1beta/models/text-embedding-004:embedContent?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d '{"model": "models/text-embedding-004", + "content": { + "parts":[{ + "text": "Hello world"}]}, }' 2> /dev/null | head +# [END embed_content] + +echo "[START batch_embed_contents]" +# [START batch_embed_contents] +curl "https://generativelanguage.googleapis.com/v1beta/models/text-embedding-004:batchEmbedContents?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d '{"requests": [{ + "model": "models/text-embedding-004", + "content": { + "parts":[{ + "text": "What is the meaning of life?"}]}, }, + { + "model": "models/text-embedding-004", + "content": { + "parts":[{ + "text": "How much wood would a woodchuck chuck?"}]}, }, + { + "model": "models/text-embedding-004", + "content": { + "parts":[{ + "text": "How does the brain work?"}]}, }, ]}' 2> /dev/null | grep -C 5 values +# [END batch_embed_contents] \ No newline at end of file diff --git a/examples/website_samples/rest/file_info.json b/examples/website_samples/rest/file_info.json new file mode 100644 index 000000000..e69de29bb diff --git a/examples/website_samples/rest/files.sh b/examples/website_samples/rest/files.sh new file mode 100644 index 000000000..8f292c4f6 --- /dev/null +++ b/examples/website_samples/rest/files.sh @@ -0,0 +1,300 @@ +set -eu + +SCRIPT_DIR=$(dirname "$0") +MEDIA_DIR=$(realpath ${SCRIPT_DIR}/../../third_party) + +TEXT_PATH=${MEDIA_DIR}/poem.txt +IMG_PATH=${MEDIA_DIR}/organ.jpg +IMG_PATH_2=${MEDIA_DIR}/Cajun_instruments.jpg +AUDIO_PATH=${MEDIA_DIR}/sample.mp3 +VIDEO_PATH=${MEDIA_DIR}/Big_Buck_Bunny.mp4 +PDF_PATH=${MEDIA_DIR}/test.pdf + +BASE_URL="https://generativelanguage.googleapis.com" + +echo "[START files_create_text]" +# [START files_create_text] +MIME_TYPE=$(file -b --mime-type "${TEXT_PATH}") +NUM_BYTES=$(wc -c < "${TEXT_PATH}") +DISPLAY_NAME=TEXT + +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${TEXT_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +# Now generate content using that file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Can you add a few more lines to this poem?"}, + {"file_data":{"mime_type": "text/plain", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo + +jq ".candidates[].content.parts[].text" response.json + +echo "[START files_get]" +# [START files_get] +name=$(jq ".file.name" file_info.json) +# Get the file of interest to check state +curl https://generativelanguage.googleapis.com/v1beta/files/$name > file_info.json +# Print some information about the file you got +name=$(jq ".file.name" file_info.json) +echo name=$name +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri +# [END files_get] + +echo "[START files_delete]" +# [START files_delete] +curl --request "DELETE" https://generativelanguage.googleapis.com/v1beta/files/$name?key=$GOOGLE_API_KEY +# [END files_delete] + +# [END files_create_text] + +echo "[START files_create_image]" +# [START files_create_image] +MIME_TYPE=$(file -b --mime-type "${IMG_PATH_2}") +NUM_BYTES=$(wc -c < "${IMG_PATH_2}") +DISPLAY_NAME=TEXT + +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${IMG_PATH_2}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +# Now generate content using that file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Can you tell me about the instruments in this photo?"}, + {"file_data": + {"mime_type": "image/jpeg", + "file_uri": '$file_uri'} + }] + }] + }' 2> /dev/null > response.json + +cat response.json +echo + +jq ".candidates[].content.parts[].text" response.json +# [END files_create_image] + +echo "[START files_create_audio]" +# [START files_create_audio] +MIME_TYPE=$(file -b --mime-type "${AUDIO_PATH}") +NUM_BYTES=$(wc -c < "${AUDIO_PATH}") +DISPLAY_NAME=AUDIO + +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${AUDIO_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +# Now generate content using that file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Describe this audio clip"}, + {"file_data":{"mime_type": "audio/mp3", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo + +jq ".candidates[].content.parts[].text" response.json +# [END files_create_audio] + +echo "[START files_create_video]" +# [START files_create_video] +MIME_TYPE=$(file -b --mime-type "${VIDEO_PATH}") +NUM_BYTES=$(wc -c < "${VIDEO_PATH}") +DISPLAY_NAME=VIDEO_PATH + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${VIDEO_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +state=$(jq ".file.state" file_info.json) +echo state=$state + +# Ensure the state of the video is 'ACTIVE' +while [[ "($state)" = *"PROCESSING"* ]]; +do + echo "Processing video..." + sleep 5 + # Get the file of interest to check state + curl https://generativelanguage.googleapis.com/v1beta/files/$name > file_info.json + state=$(jq ".file.state" file_info.json) +done + +# Now generate content using that file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Describe this video clip"}, + {"file_data":{"mime_type": "video/mp4", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo + +jq ".candidates[].content.parts[].text" response.json +# [END files_create_video] + +echo "[START files_create_pdf]" +# [START files_create_pdf] +NUM_BYTES=$(wc -c < "${PDF_PATH}") +DISPLAY_NAME=TEXT +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: application/pdf" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${PDF_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +# Now generate content using that file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Can you add a few more lines to this poem?"}, + {"file_data":{"mime_type": "application/pdf", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo + +jq ".candidates[].content.parts[].text" response.json +# [END files_create_pdf] + +echo "[START files_list]" +# [START files_list] +echo "My files: " + +curl "https://generativelanguage.googleapis.com/v1beta/files?key=$GOOGLE_API_KEY" +# [END files_list] \ No newline at end of file diff --git a/examples/website_samples/rest/function_calling.sh b/examples/website_samples/rest/function_calling.sh new file mode 100644 index 000000000..f88641e81 --- /dev/null +++ b/examples/website_samples/rest/function_calling.sh @@ -0,0 +1,62 @@ +set -eu + +echo "[START function_calling]" +# [START function_calling] + +cat > tools.json << EOF +{ + "function_declarations": [ + { + "name": "enable_lights", + "description": "Turn on the lighting system.", + "parameters": { "type": "object" } + }, + { + "name": "set_light_color", + "description": "Set the light color. Lights must be enabled for this to work.", + "parameters": { + "type": "object", + "properties": { + "rgb_hex": { + "type": "string", + "description": "The light color as a 6-digit hex string, e.g. ff0000 for red." + } + }, + "required": [ + "rgb_hex" + ] + } + }, + { + "name": "stop_lights", + "description": "Turn off the lighting system.", + "parameters": { "type": "object" } + } + ] +} +EOF + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro-latest:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -d @<(echo ' + { + "system_instruction": { + "parts": { + "text": "You are a helpful lighting system bot. You can turn lights on and off, and you can set the color. Do not perform any other tasks." + } + }, + "tools": ['$(source "$tools")'], + + "tool_config": { + "function_calling_config": {"mode": "none"} + }, + + "contents": { + "role": "user", + "parts": { + "text": "What can you do?" + } + } + } +') 2>/dev/null |sed -n '/"content"/,/"finishReason"/p' +# [END function_calling] diff --git a/examples/website_samples/rest/models.sh b/examples/website_samples/rest/models.sh new file mode 100644 index 000000000..a03d5585b --- /dev/null +++ b/examples/website_samples/rest/models.sh @@ -0,0 +1,11 @@ +set -eu + +echo "[START models_list]" +# [START models_list] +curl https://generativelanguage.googleapis.com/v1beta/models?key=$GOOGLE_API_KEY +# [END models_list] + +echo "[START models_get]" +# [START models_get] +curl https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash?key=$GOOGLE_API_KEY +# [END models_get] diff --git a/examples/website_samples/rest/response.json b/examples/website_samples/rest/response.json new file mode 100644 index 000000000..243207510 --- /dev/null +++ b/examples/website_samples/rest/response.json @@ -0,0 +1,20 @@ +data: {"candidates": [{"content": {"parts": [{"text": "This"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": " is a recording of John F. Kennedy's State of the Union address to"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": " a joint session of Congress on January 30th, 196"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": "1. The address covers a wide range of topics, including:\n\n* **The state of the US economy:** Kennedy details the economic challenges facing the nation"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": ", including high unemployment, business bankruptcies, and falling farm income. He outlines plans to address these issues through legislative action.\n\n* **International balance of payments"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": ":** He discusses the deficit in the US balance of payments and the outflow of gold reserves. He reassures the audience that the US will not devalue the dollar.\n\n* **Foreign policy and global challenges:** Kennedy addresses major global issues"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": ", including the Cold War, the situation in Laos, the Congo, and Cuba. He emphasizes the need for strong military and diplomatic tools to deter aggression while also pursuing peaceful cooperation. He calls for a new approach to foreign aid, focusing"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": " on long-term development and increased collaboration with allies.\n\n* **Domestic policy:** He touches upon several domestic issues, including housing, education, medical care for the elderly, and the need to address racial injustice.\n\n* **Strengthening the executive branch:** Kennedy expresses concern about inefficiencies in the executive branch and vows"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": " to improve decision-making and reduce wasteful duplication.\n\n* **A call for national unity and purpose:** The address concludes with a plea for national unity and a call to meet the challenges of the time with both strength and diplomacy. He invokes the spirit of a previous president and stresses the importance of perseverance and dedication"}],"role": "model"}}],"usageMetadata": {"promptTokenCount": 83557,"totalTokenCount": 83557},"modelVersion": "gemini-1.5-flash-002"} + +data: {"candidates": [{"content": {"parts": [{"text": " to the national interest.\n\n\nThe audio is a historical document providing insight into the priorities and concerns of the early Kennedy administration.\n"}],"role": "model"},"finishReason": "STOP"}],"usageMetadata": {"promptTokenCount": 83557,"candidatesTokenCount": 347,"totalTokenCount": 83904},"modelVersion": "gemini-1.5-flash-002"} + diff --git a/examples/website_samples/rest/safety_settings.sh b/examples/website_samples/rest/safety_settings.sh new file mode 100644 index 000000000..713d25c06 --- /dev/null +++ b/examples/website_samples/rest/safety_settings.sh @@ -0,0 +1,34 @@ +set -eu + +echo "[START safety_settings]" +# [START safety_settings] + echo '{ + "safetySettings": [ + {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_ONLY_HIGH"} + ], + "contents": [{ + "parts":[{ + "text": "'I support Martians Soccer Club and I think Jupiterians Football Club sucks! Write a ironic phrase about them.'"}]}]}' > request.json + + curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d @request.json 2> /dev/null +# [END safety_settings] + +echo "[START safety_settings_multi]" +# [START safety_settings_multi] + echo '{ + "safetySettings": [ + {"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_ONLY_HIGH"}, + {"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_MEDIUM_AND_ABOVE"} + ], + "contents": [{ + "parts":[{ + "text": "'I support Martians Soccer Club and I think Jupiterians Football Club sucks! Write a ironic phrase about them.'"}]}]}' > request.json + + curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d @request.json 2> /dev/null +# [END safety_settings_multi] diff --git a/examples/website_samples/rest/system_instruction.sh b/examples/website_samples/rest/system_instruction.sh new file mode 100644 index 000000000..1e4c36d6c --- /dev/null +++ b/examples/website_samples/rest/system_instruction.sh @@ -0,0 +1,13 @@ +set -eu + +echo "[START system_instruction]" +# [START system_instruction] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ +-H 'Content-Type: application/json' \ +-d '{ "system_instruction": { + "parts": + { "text": "You are a cat. Your name is Neko."}}, + "contents": { + "parts": { + "text": "Hello there"}}}' +# [END system_instruction] \ No newline at end of file diff --git a/examples/website_samples/rest/text_generation.sh b/examples/website_samples/rest/text_generation.sh new file mode 100755 index 000000000..8cfadd688 --- /dev/null +++ b/examples/website_samples/rest/text_generation.sh @@ -0,0 +1,492 @@ +set -eu + +SCRIPT_DIR=$(dirname "$0") +MEDIA_DIR=$(realpath ${SCRIPT_DIR}/../../third_party) + +IMG_PATH=${MEDIA_DIR}/organ.jpg +IMG_PATH2=${MEDIA_DIR}/Cajun_instruments.jpg +AUDIO_PATH=${MEDIA_DIR}/sample.mp3 +VIDEO_PATH=${MEDIA_DIR}/Big_Buck_Bunny.mp4 +PDF_PATH=${MEDIA_DIR}/test.pdf + +if [[ "$(base64 --version 2>&1)" = *"FreeBSD"* ]]; then + B64FLAGS="--input" +else + B64FLAGS="-w0" +fi + +BASE_URL="https://generativelanguage.googleapis.com" + +echo "[START text_gen_text_only_prompt]" +# [START text_gen_text_only_prompt] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[{"text": "Write a story about a magic backpack."}] + }] + }' 2> /dev/null +# [END text_gen_text_only_prompt] + +echo "[START text_gen_text_only_prompt_streaming]" +# [START text_gen_text_only_prompt_streaming] +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:streamGenerateContent?alt=sse&key=${GOOGLE_API_KEY}" \ + -H 'Content-Type: application/json' \ + --no-buffer \ + -d '{ "contents":[{"parts":[{"text": "Write a story about a magic backpack."}]}]}' +# [END text_gen_text_only_prompt_streaming] + +echo "[START text_gen_multimodal_one_image_prompt]" +# [START text_gen_multimodal_one_image_prompt] +# Use a temporary file to hold the base64 encoded image data +TEMP_B64=$(mktemp) +trap 'rm -f "$TEMP_B64"' EXIT +base64 $B64FLAGS $IMG_PATH > "$TEMP_B64" + +# Use a temporary file to hold the JSON payload +TEMP_JSON=$(mktemp) +trap 'rm -f "$TEMP_JSON"' EXIT + +cat > "$TEMP_JSON" << EOF +{ + "contents": [{ + "parts":[ + {"text": "Tell me about this instrument"}, + { + "inline_data": { + "mime_type":"image/jpeg", + "data": "$(cat "$TEMP_B64")" + } + } + ] + }] +} +EOF + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d "@$TEMP_JSON" 2> /dev/null +# [END text_gen_multimodal_one_image_prompt] + +echo "[START text_gen_multimodal_one_image_prompt_streaming]" +# [START text_gen_multimodal_one_image_prompt_streaming] +cat > "$TEMP_JSON" << EOF +{ + "contents": [{ + "parts":[ + {"text": "Tell me about this instrument"}, + { + "inline_data": { + "mime_type":"image/jpeg", + "data": "$(cat "$TEMP_B64")" + } + } + ] + }] +} +EOF + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:streamGenerateContent?alt=sse&key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d "@$TEMP_JSON" 2> /dev/null +# [END text_gen_multimodal_one_image_prompt_streaming] + +echo "[START text_gen_multimodal_two_image_prompt]" +# [START text_gen_multimodal_two_image_prompt] +# Base64 encode both images into temporary files +TEMP_B64_1=$(mktemp) +TEMP_B64_2=$(mktemp) +trap 'rm -f "$TEMP_B64_1" "$TEMP_B64_2"' EXIT +base64 $B64FLAGS "$IMG_PATH" > "$TEMP_B64_1" +base64 $B64FLAGS "$IMG_PATH2" > "$TEMP_B64_2" + +# Create the JSON payload using the base64 data from both images +cat > "$TEMP_JSON" << EOF +{ + "contents": [{ + "parts":[ + { + "inline_data": { + "mime_type": "image/jpeg", + "data": "$(cat "$TEMP_B64_1")" + } + }, + { + "inline_data": { + "mime_type": "image/jpeg", + "data": "$(cat "$TEMP_B64_2")" + } + }, + { + "text": "Generate a list of all the objects contained in both images." + } + ] + }] +} +EOF + +# Make the API request using the JSON file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d "@$TEMP_JSON" 2> /dev/null > response.json + +# Display the response +cat response.json +# [END text_gen_multimodal_two_image_prompt] + +echo "[START text_gen_multimodal_one_image_bounding_box_prompt]" +# [START text_gen_multimodal_one_image_bounding_box_prompt] +# Re-use TEMP_B64_2 (from the previous two-image prompt) and TEMP_JSON + +# Create the JSON payload for bounding box detection +cat > "$TEMP_JSON" << EOF +{ + "contents": [{ + "parts":[ + { + "inline_data": { + "mime_type": "image/jpeg", + "data": "$(cat "$TEMP_B64_2")" + } + }, + { + "text": "Generate bounding boxes for each of the objects in this image in [y_min, x_min, y_max, x_max] format." + } + ] + }] +} +EOF + +# Make the API request using the JSON file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-pro:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d "@$TEMP_JSON" 2> /dev/null > response.json + +cat response.json +# [END text_gen_multimodal_one_image_bounding_box_prompt] + +echo "[START text_gen_multimodal_audio]" +# [START text_gen_multimodal_audio] +# Use File API to upload audio data to API request. +MIME_TYPE=$(file -b --mime-type "${AUDIO_PATH}") +NUM_BYTES=$(wc -c < "${AUDIO_PATH}") +DISPLAY_NAME=AUDIO + +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${AUDIO_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Please describe this file."}, + {"file_data":{"mime_type": "audio/mpeg", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo + +jq ".candidates[].content.parts[].text" response.json +# [END text_gen_multimodal_audio] + +echo "[START text_gen_multimodal_audio_streaming]" +# [START text_gen_multimodal_audio_streaming] +# Use File API to upload audio data to API request. +MIME_TYPE=$(file -b --mime-type "${AUDIO_PATH}") +NUM_BYTES=$(wc -c < "${AUDIO_PATH}") +DISPLAY_NAME=AUDIO + +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${AUDIO_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:streamGenerateContent?alt=sse&key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Please describe this file."}, + {"file_data":{"mime_type": "audio/mpeg", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo +# [END text_gen_multimodal_audio_streaming] + +echo "[START text_gen_multimodal_video_prompt]" +# [START text_gen_multimodal_video_prompt] +# Use File API to upload audio data to API request. +MIME_TYPE=$(file -b --mime-type "${VIDEO_PATH}") +NUM_BYTES=$(wc -c < "${VIDEO_PATH}") +DISPLAY_NAME=VIDEO + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D "${tmp_header_file}" \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${VIDEO_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +state=$(jq ".file.state" file_info.json) +echo state=$state + +name=$(jq ".file.name" file_info.json) +echo name=$name + +while [[ "($state)" = *"PROCESSING"* ]]; +do + echo "Processing video..." + sleep 5 + # Get the file of interest to check state + curl https://generativelanguage.googleapis.com/v1beta/files/$name > file_info.json + state=$(jq ".file.state" file_info.json) +done + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Transcribe the audio from this video, giving timestamps for salient events in the video. Also provide visual descriptions."}, + {"file_data":{"mime_type": "video/mp4", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo + +jq ".candidates[].content.parts[].text" response.json +# [END text_gen_multimodal_video_prompt] + +echo "[START text_gen_multimodal_video_prompt_streaming]" +# [START text_gen_multimodal_video_prompt_streaming] +# Use File API to upload audio data to API request. +MIME_TYPE=$(file -b --mime-type "${VIDEO_PATH}") +NUM_BYTES=$(wc -c < "${VIDEO_PATH}") +DISPLAY_NAME=VIDEO_PATH + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${VIDEO_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +state=$(jq ".file.state" file_info.json) +echo state=$state + +while [[ "($state)" = *"PROCESSING"* ]]; +do + echo "Processing video..." + sleep 5 + # Get the file of interest to check state + curl https://generativelanguage.googleapis.com/v1beta/files/$name > file_info.json + state=$(jq ".file.state" file_info.json) +done + +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:streamGenerateContent?alt=sse&key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Please describe this file."}, + {"file_data":{"mime_type": "video/mp4", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo +# [END text_gen_multimodal_video_prompt_streaming] + +echo "[START text_gen_multimodal_pdf]" +# [START text_gen_multimodal_pdf] +MIME_TYPE=$(file -b --mime-type "${PDF_PATH}") +NUM_BYTES=$(wc -c < "${PDF_PATH}") +DISPLAY_NAME=TEXT + + +echo $MIME_TYPE +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${PDF_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +# Now generate content using that file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Can you add a few more lines to this poem?"}, + {"file_data":{"mime_type": "application/pdf", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo + +jq ".candidates[].content.parts[].text" response.json +# [END text_gen_multimodal_pdf] + +echo "[START text_gen_multimodal_pdf_streaming]" +# [START text_gen_multimodal_pdf_streaming] +MIME_TYPE=$(file -b --mime-type "${PDF_PATH}") +NUM_BYTES=$(wc -c < "${PDF_PATH}") +DISPLAY_NAME=TEXT + + +echo $MIME_TYPE +tmp_header_file=upload-header.tmp + +# Initial resumable request defining metadata. +# The upload url is in the response headers dump them to a file. +curl "${BASE_URL}/upload/v1beta/files?key=${GOOGLE_API_KEY}" \ + -D upload-header.tmp \ + -H "X-Goog-Upload-Protocol: resumable" \ + -H "X-Goog-Upload-Command: start" \ + -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \ + -H "Content-Type: application/json" \ + -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null + +upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r") +rm "${tmp_header_file}" + +# Upload the actual bytes. +curl "${upload_url}" \ + -H "Content-Length: ${NUM_BYTES}" \ + -H "X-Goog-Upload-Offset: 0" \ + -H "X-Goog-Upload-Command: upload, finalize" \ + --data-binary "@${PDF_PATH}" 2> /dev/null > file_info.json + +file_uri=$(jq ".file.uri" file_info.json) +echo file_uri=$file_uri + +# Now generate content using that file +curl "https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:streamGenerateContent?alt=sse&key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -X POST \ + -d '{ + "contents": [{ + "parts":[ + {"text": "Can you add a few more lines to this poem?"}, + {"file_data":{"mime_type": "application/pdf", "file_uri": '$file_uri'}}] + }] + }' 2> /dev/null > response.json + +cat response.json +echo +# [END text_gen_multimodal_pdf_streaming] \ No newline at end of file diff --git a/examples/website_samples/rest/tuned_models.sh b/examples/website_samples/rest/tuned_models.sh new file mode 100644 index 000000000..5594734f6 --- /dev/null +++ b/examples/website_samples/rest/tuned_models.sh @@ -0,0 +1,143 @@ +set -eu + +echo "[START tuned_models_create]" +# [START tuned_models_create] +curl -X POST "https://generativelanguage.googleapis.com/v1beta/tunedModels?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + -d ' + { + "display_name": "number generator model", + "base_model": "models/gemini-1.5-flash-001-tuning", + "tuning_task": { + "hyperparameters": { + "batch_size": 2, + "learning_rate": 0.001, + "epoch_count":5, + }, + "training_data": { + "examples": { + "examples": [ + { + "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", + } + ] + } + } + } + }' | tee tunemodel.json + +# Check the operation for status updates during training. +# Note: you can only check the operation on v1/ +operation=$(cat tunemodel.json | jq ".name" | tr -d '"') +tuning_done=false + +while [[ "$tuning_done" != "true" ]]; +do + sleep 5 + curl -X GET "https://generativelanguage.googleapis.com/v1/${operation}?key=$GOOGLE_API_KEY" \ + -H 'Content-Type: application/json' \ + 2> /dev/null > tuning_operation.json + + complete=$(jq .metadata.completedPercent < tuning_operation.json) + tput cuu1 + tput el + echo "Tuning...${complete}%" + tuning_done=$(jq .done < tuning_operation.json) +done + +# Or get the TunedModel and check it's state. The model is ready to use if the state is active. +modelname=$(cat tunemodel.json | jq ".metadata.tunedModel" | tr -d '"') +curl -X GET https://generativelanguage.googleapis.com/v1beta/${modelname}?key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' > tuned_model.json + +cat tuned_model.json | jq ".state" +# [END tuned_models_create] + + +echo "[START tuned_models_generate_content]" +# [START tuned_models_generate_content] +curl -X POST https://generativelanguage.googleapis.com/v1beta/$modelname:generateContent?key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' \ + -d '{ + "contents": [{ + "parts": [{ + "text": "LXIII" + }] + }] + }' 2> /dev/null +# [END tuned_models_generate_content] + +echo "[START tuned_models_get]" +# [START tuned_models_get] +curl -X GET https://generativelanguage.googleapis.com/v1beta/${modelname}?key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' | grep state +# [END tuned_models_get] + +echo "[START tuned_models_list]" +# [START tuned_models_list] +# Sending a page_size is optional +curl -X GET https://generativelanguage.googleapis.com/v1beta/tunedModels?page_size=5 \ + -H "Content-Type: application/json" \ + -H "Authorization: Bearer ${access_token}" \ + -H "x-goog-user-project: ${project_id}" > tuned_models.json + +jq .tunedModels[].name < tuned_models.json + +# Send the nextPageToken to get the next page. +page_token=$(jq .nextPageToken < tuned_models.json | tr -d '"') + +if [[ "$page_token" != "null"" ]]; then +curl -X GET https://generativelanguage.googleapis.com/v1beta/tunedModels?page_size=5\&page_token=${page_token}?key=$GOOGLE_API_KEY \ + -H "Content-Type: application/json" > tuned_models2.json +jq .tunedModels[].name < tuned_models.json +fi +# [END tuned_models_list] + +echo "[START tuned_models_delete]" +# [START tuned_models_delete] +curl -X DELETE https://generativelanguage.googleapis.com/v1beta/${modelname}?key=$GOOGLE_API_KEY \ + -H 'Content-Type: application/json' +# [END tuned_models_delete] \ No newline at end of file diff --git a/examples/website_samples/rest/tunemodel.json b/examples/website_samples/rest/tunemodel.json new file mode 100644 index 000000000..d9b65f33f --- /dev/null +++ b/examples/website_samples/rest/tunemodel.json @@ -0,0 +1,8 @@ +{ + "name": "tunedModels/number-generator-model-eoykb5s4p15s/operations/par9t60is0wo", + "metadata": { + "@type": "type.googleapis.com/google.ai.generativelanguage.v1beta.CreateTunedModelMetadata", + "totalSteps": 38, + "tunedModel": "tunedModels/number-generator-model-eoykb5s4p15s" + } +} diff --git a/examples/website_samples/safety_settings.py b/examples/website_samples/safety_settings.py new file mode 100644 index 000000000..49b099dad --- /dev/null +++ b/examples/website_samples/safety_settings.py @@ -0,0 +1,59 @@ +# -*- 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 + + +class UnitTests(absltest.TestCase): + def test_safety_settings(self): + # [START safety_settings] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + unsafe_prompt = "I support Martians Soccer Club and I think Jupiterians Football Club sucks! Write a ironic phrase about them." + response = model.generate_content( + unsafe_prompt, safety_settings={"HARASSMENT": "BLOCK_ONLY_HIGH"} + ) + # If you want to set all the safety_settings to the same value you can just pass that value: + response = model.generate_content(unsafe_prompt, safety_settings="BLOCK_ONLY_HIGH") + print(response.candidates[0].finish_reason) + print(response.candidates[0].safety_ratings) + # [END safety_settings] + + def test_safety_settings_multi(self): + # [START safety_settings_multi] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + unsafe_prompt = "I support Martians Soccer Club and I think Jupiterians Football Club sucks! Write a ironic phrase about them." + response = model.generate_content( + unsafe_prompt, + safety_settings={ + "HATE": "MEDIUM", + "HARASSMENT": "BLOCK_ONLY_HIGH", + }, + ) + # If you want to set all the safety_settings to the same value you can just pass that value: + response = model.generate_content(unsafe_prompt, safety_settings="MEDIUM") + try: + print(response.text) + except: + print("No information generated by the model.") + + print(response.candidates[0].safety_ratings) + # [END safety_settings_multi] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/system_instruction.py b/examples/website_samples/system_instruction.py new file mode 100644 index 000000000..bf486ec45 --- /dev/null +++ b/examples/website_samples/system_instruction.py @@ -0,0 +1,33 @@ +# -*- 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 + + +class UnitTests(absltest.TestCase): + def test_system_instructions(self): + # [START system_instruction] + import google.generativeai as genai + + model = genai.GenerativeModel( + "models/gemini-1.5-flash", + system_instruction="You are a cat. Your name is Neko.", + ) + response = model.generate_content("Good morning! How are you?") + print(response.text) + # [END system_instruction] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/text_generation.py b/examples/website_samples/text_generation.py new file mode 100644 index 000000000..ab57149b2 --- /dev/null +++ b/examples/website_samples/text_generation.py @@ -0,0 +1,195 @@ +# -*- 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 pathlib + +media = pathlib.Path(__file__).parents[1] / "third_party" + + +class UnitTests(absltest.TestCase): + def test_text_gen_text_only_prompt(self): + # [START text_gen_text_only_prompt] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + response = model.generate_content("Write a story about a magic backpack.") + print(response.text) + # [END text_gen_text_only_prompt] + + def test_text_gen_text_only_prompt_streaming(self): + # [START text_gen_text_only_prompt_streaming] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + response = model.generate_content("Write a story about a magic backpack.", stream=True) + for chunk in response: + print(chunk.text) + print("_" * 80) + # [END text_gen_text_only_prompt_streaming] + + def test_text_gen_multimodal_one_image_prompt(self): + # [START text_gen_multimodal_one_image_prompt] + import google.generativeai as genai + + import PIL.Image + + model = genai.GenerativeModel("gemini-1.5-flash") + organ = PIL.Image.open(media / "organ.jpg") + response = model.generate_content(["Tell me about this instrument", organ]) + print(response.text) + # [END text_gen_multimodal_one_image_prompt] + + def test_text_gen_multimodal_one_image_prompt_streaming(self): + # [START text_gen_multimodal_one_image_prompt_streaming] + import google.generativeai as genai + + import PIL.Image + + 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) + for chunk in response: + print(chunk.text) + print("_" * 80) + # [END text_gen_multimodal_one_image_prompt_streaming] + + def test_text_gen_multimodal_multi_image_prompt(self): + # [START text_gen_multimodal_multi_image_prompt] + import google.generativeai as genai + + import PIL.Image + + model = genai.GenerativeModel("gemini-1.5-flash") + organ = PIL.Image.open(media / "organ.jpg") + cajun_instrument = PIL.Image.open(media / "Cajun_instruments.jpg") + response = model.generate_content( + ["What is the difference between both of these instruments?", organ, cajun_instrument] + ) + print(response.text) + # [END text_gen_multimodal_multi_image_prompt] + + def test_text_gen_multimodal_multi_image_prompt_streaming(self): + # [START text_gen_multimodal_multi_image_prompt_streaming] + import google.generativeai as genai + + import PIL.Image + + model = genai.GenerativeModel("gemini-1.5-flash") + organ = PIL.Image.open(media / "organ.jpg") + cajun_instrument = PIL.Image.open(media / "Cajun_instruments.jpg") + response = model.generate_content( + ["What is the difference between both of these instruments?", organ, cajun_instrument], + stream=True, + ) + for chunk in response: + print(chunk.text) + print("_" * 80) + # [END text_gen_multimodal_multi_image_prompt_streaming] + + def test_text_gen_multimodal_audio(self): + # [START text_gen_multimodal_audio] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + sample_audio = genai.upload_file(media / "sample.mp3") + response = model.generate_content(["Give me a summary of this audio file.", sample_audio]) + print(response.text) + # [END text_gen_multimodal_audio] + + def test_text_gen_multimodal_audio_streaming(self): + # [START text_gen_multimodal_audio_streaming] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + sample_audio = genai.upload_file(media / "sample.mp3") + response = model.generate_content(["Give me a summary of this audio file.", sample_audio]) + + for chunk in response: + print(chunk.text) + print("_" * 80) + # [END text_gen_multimodal_audio_streaming] + + def test_text_gen_multimodal_video_prompt(self): + # [START text_gen_multimodal_video_prompt] + import google.generativeai as genai + + import time + + # Video clip (CC BY 3.0) from https://peach.blender.org/download/ + myfile = genai.upload_file(media / "Big_Buck_Bunny.mp4") + print(f"{myfile=}") + + # Videos need to be processed before you can use them. + while myfile.state.name == "PROCESSING": + print("processing video...") + time.sleep(5) + myfile = genai.get_file(myfile.name) + + model = genai.GenerativeModel("gemini-1.5-flash") + response = model.generate_content([myfile, "Describe this video clip"]) + print(f"{response.text=}") + # [END text_gen_multimodal_video_prompt] + + def test_text_gen_multimodal_video_prompt_streaming(self): + # [START text_gen_multimodal_video_prompt_streaming] + import google.generativeai as genai + + import time + + # Video clip (CC BY 3.0) from https://peach.blender.org/download/ + myfile = genai.upload_file(media / "Big_Buck_Bunny.mp4") + print(f"{myfile=}") + + # Videos need to be processed before you can use them. + while myfile.state.name == "PROCESSING": + print("processing video...") + time.sleep(5) + myfile = genai.get_file(myfile.name) + + model = genai.GenerativeModel("gemini-1.5-flash") + + response = model.generate_content([myfile, "Describe this video clip"]) + for chunk in response: + print(chunk.text) + print("_" * 80) + # [END text_gen_multimodal_video_prompt_streaming] + + def test_text_gen_multimodal_pdf(self): + # [START text_gen_multimodal_pdf] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + sample_pdf = genai.upload_file(media / "test.pdf") + response = model.generate_content(["Give me a summary of this document:", sample_pdf]) + print(f"{response.text=}") + # [END text_gen_multimodal_pdf] + + def test_text_gen_multimodal_pdf_streaming(self): + # [START text_gen_multimodal_pdf_streaming] + import google.generativeai as genai + + model = genai.GenerativeModel("gemini-1.5-flash") + sample_pdf = genai.upload_file(media / "test.pdf") + response = model.generate_content(["Give me a summary of this document:", sample_pdf]) + + for chunk in response: + print(chunk.text) + print("_" * 80) + # [END text_gen_multimodal_pdf_streaming] + + +if __name__ == "__main__": + absltest.main() diff --git a/examples/website_samples/tuned_models.py b/examples/website_samples/tuned_models.py new file mode 100644 index 000000000..970919115 --- /dev/null +++ b/examples/website_samples/tuned_models.py @@ -0,0 +1,255 @@ +# -*- 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 pathlib + +samples = pathlib.Path(__file__).parent + + +class UnitTests(absltest.TestCase): + def test_tuned_models_create(self): + # [START tuned_models_create] + import google.generativeai as genai + + import time + + base_model = "models/gemini-1.5-flash-001-tuning" + 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] + import google.generativeai as genai + + model = genai.GenerativeModel(model_name="tunedModels/my-increment-model") + result = model.generate_content("III") + print(result.text) # "IV" + # [END tuned_models_generate_content] + + def test_tuned_models_get(self): + # [START tuned_models_get] + import google.generativeai as genai + + 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] + import google.generativeai as genai + + 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.5-flash-001-tuning" + 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] + import google.generativeai as genai + + 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] + import google.generativeai as genai + + 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] + import google.generativeai as genai + + 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] + import google.generativeai as genai + + 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] + import google.generativeai as genai + + 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_delete] + import google.generativeai as genai + + 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_delete] + + +if __name__ == "__main__": + absltest.main()