diff --git a/genai/batch_prediction/requirements.txt b/genai/batch_prediction/requirements.txt index 4f44a6593bb..ba2ccb4c987 100644 --- a/genai/batch_prediction/requirements.txt +++ b/genai/batch_prediction/requirements.txt @@ -1,3 +1,3 @@ google-cloud-bigquery==3.29.0 google-cloud-storage==2.19.0 -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/bounding_box/boundingbox_interactions_with_txt_img.py b/genai/bounding_box/boundingbox_interactions_with_txt_img.py new file mode 100644 index 00000000000..76dd62b20ae --- /dev/null +++ b/genai/bounding_box/boundingbox_interactions_with_txt_img.py @@ -0,0 +1,120 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_boundingbox_with_txt_img] + import json + import requests + from google import genai + from google.genai.interactions import ( + ImageContent, + TextContent, + TextResponseFormat, + ) + from PIL import Image, ImageColor, ImageDraw + from pydantic import BaseModel + + # Helper class to represent a bounding box + class BoundingBox(BaseModel): + """ + Represents a bounding box with its 2D coordinates and associated label. + + Attributes: + box_2d (list[int]): A list of integers representing the 2D coordinates of the bounding box, + typically in the format [y_min, x_min, y_max, x_max]. + label (str): A string representing the label or class associated with the object within the bounding box. + """ + + box_2d: list[int] + label: str + + # Helper function to plot bounding boxes on an image + def plot_bounding_boxes(image_uri: str, bounding_boxes: list[BoundingBox]) -> None: + """ + Plots bounding boxes on an image with labels, using PIL and normalized coordinates. + + Args: + image_uri: The URI of the image file. + bounding_boxes: A list of BoundingBox objects. Each box's coordinates are in + normalized [y_min, x_min, y_max, x_max] format. + """ + with Image.open(requests.get(image_uri, stream=True, timeout=10).raw) as im: + width, height = im.size + draw = ImageDraw.Draw(im) + + colors = list(ImageColor.colormap.keys()) + + for i, bbox in enumerate(bounding_boxes): + # Scale normalized coordinates to image dimensions + abs_y_min = int(bbox.box_2d[0] / 1000 * height) + abs_x_min = int(bbox.box_2d[1] / 1000 * width) + abs_y_max = int(bbox.box_2d[2] / 1000 * height) + abs_x_max = int(bbox.box_2d[3] / 1000 * width) + + color = colors[i % len(colors)] + + # Draw the rectangle using the correct (x, y) pairs + draw.rectangle( + ((abs_x_min, abs_y_min), (abs_x_max, abs_y_max)), + outline=color, + width=4, + ) + if bbox.label: + # Position the text at the top-left corner of the box + draw.text((abs_x_min + 8, abs_y_min + 6), bbox.label, fill=color) + + im.show() + + client = genai.Client() + image_uri = "https://storage.googleapis.com/generativeai-downloads/images/socks.jpg" + + system_instruction = """ + Return bounding boxes as an array with labels. + Never return masks. Limit to 25 objects. + If an object is present multiple times, give each object a unique label + according to its distinct characteristics (colors, size, position, etc..). + """ + + interaction = client.interactions.create( + model="gemini-3.8-flash", + system_instruction=system_instruction, + input=[ + ImageContent( + uri=image_uri, + mime_type="image/jpeg", + ), + TextContent( + text="Output the positions of the socks with a face. Label according to position in the image." + ), + ], + response_format=TextResponseFormat( + mime_type="application/json", + schema={ + "type": "array", + "items": BoundingBox.model_json_schema(), + }, + ), + ) + + print(interaction.output_text) + boxes = [BoundingBox(**b) for b in json.loads(interaction.output_text)] + plot_bounding_boxes(image_uri, boxes) + + # [END googlegenaisdk_interactions_boundingbox_with_txt_img] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/bounding_box/requirements.txt b/genai/bounding_box/requirements.txt index 75a39f7e582..1af6c711b57 100644 --- a/genai/bounding_box/requirements.txt +++ b/genai/bounding_box/requirements.txt @@ -1,2 +1,2 @@ -google-genai==1.42.0 +google-genai==2.29.0 pillow==12.3.0; python_version >= "3.10" diff --git a/genai/bounding_box/test_bounding_box_examples.py b/genai/bounding_box/test_bounding_box_examples.py index 39b0056e7a3..a9db2cb2ee0 100644 --- a/genai/bounding_box/test_bounding_box_examples.py +++ b/genai/bounding_box/test_bounding_box_examples.py @@ -18,6 +18,7 @@ import os +import boundingbox_interactions_with_txt_img import boundingbox_with_txt_img os.environ["GOOGLE_GENAI_USE_ENTERPRISE"] = "True" @@ -29,3 +30,9 @@ def test_boundingbox_with_txt_img() -> None: response = boundingbox_with_txt_img.generate_content() assert response + + +def test_boundingbox_interactions_with_txt_img() -> None: + response = boundingbox_interactions_with_txt_img.create_interaction() + assert response + diff --git a/genai/code_execution/codeexecution_interactions_annotateimage_with_txt_gcsimg.py b/genai/code_execution/codeexecution_interactions_annotateimage_with_txt_gcsimg.py new file mode 100644 index 00000000000..a82d2bbcc23 --- /dev/null +++ b/genai/code_execution/codeexecution_interactions_annotateimage_with_txt_gcsimg.py @@ -0,0 +1,67 @@ +# Copyright 2026 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 +# +# https://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. + + +def create_interaction() -> bool: + # [START googlegenaisdk_interactions_codeexecution_annotateimage_with_txt_gcsimg] + import base64 + import io + from PIL import Image + from google import genai + from google.genai.interactions import CodeExecution, ImageContent, TextContent + + client = genai.Client() + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + ImageContent( + uri="https://storage.googleapis.com/cloud-samples-data/generative-ai/image/robotic.jpeg", + mime_type="image/jpeg", + ), + TextContent( + text="Annotate on the image with arrows of different colors, which object should go into which bin." + ), + ], + tools=[CodeExecution()], + ) + + img_count = 0 + for step in interaction.steps: + if step.type == "code_execution_call": + print("####################### 1. Generate Python Code #######################") + print(step.arguments.code) + elif step.type == "code_execution_result": + print("####################### 2. Executing Python Code #######################") + print(step.result) + + if interaction.output_image: + print("####################### 3. Save Output #######################") + img_count += 1 + output_location = f"robotic-annotate-output-{img_count}.jpg" + image_bytes = base64.b64decode(interaction.output_image.data) + image = Image.open(io.BytesIO(image_bytes)) + image = image.convert("RGB") + image.save(output_location) + print(f"Output is saved to {output_location}") + + if interaction.output_text: + print(interaction.output_text) + + # [END googlegenaisdk_interactions_codeexecution_annotateimage_with_txt_gcsimg] + return True + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/code_execution/codeexecution_interactions_barplot_with_txt_img.py b/genai/code_execution/codeexecution_interactions_barplot_with_txt_img.py new file mode 100644 index 00000000000..54ebbee0946 --- /dev/null +++ b/genai/code_execution/codeexecution_interactions_barplot_with_txt_img.py @@ -0,0 +1,68 @@ +# Copyright 2026 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 +# +# https://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. + + +def create_interaction() -> bool: + # [START googlegenaisdk_interactions_codeexecution_barplot_with_txt_img] + import base64 + import io + from PIL import Image + from google import genai + from google.genai.interactions import CodeExecution, ImageContent, TextContent + + client = genai.Client() + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + ImageContent( + uri="https://storage.googleapis.com/cloud-samples-data/generative-ai/image/benchmark.jpeg", + mime_type="image/jpeg", + ), + TextContent( + text="Make a bar chart of per-category performance, normalize prior SOTA as 1.0 for each task," + "then take average per-category. Plot using matplotlib with nice style." + ), + ], + tools=[CodeExecution()], + ) + + img_count = 0 + for step in interaction.steps: + if step.type == "code_execution_call": + print("####################### 1. Generate Python Code #######################") + print(step.arguments.code) + elif step.type == "code_execution_result": + print("####################### 2. Executing Python Code #######################") + print(step.result) + + if interaction.output_image: + print("####################### 3. Save Output #######################") + img_count += 1 + output_location = f"output-barplot-{img_count}.jpg" + image_bytes = base64.b64decode(interaction.output_image.data) + image = Image.open(io.BytesIO(image_bytes)) + image = image.convert("RGB") + image.save(output_location) + print(f"Output is saved to {output_location}") + + if interaction.output_text: + print(interaction.output_text) + + # [END googlegenaisdk_interactions_codeexecution_barplot_with_txt_img] + return True + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/code_execution/codeexecution_interactions_cropimage_with_txt_img.py b/genai/code_execution/codeexecution_interactions_cropimage_with_txt_img.py new file mode 100644 index 00000000000..7f810517723 --- /dev/null +++ b/genai/code_execution/codeexecution_interactions_cropimage_with_txt_img.py @@ -0,0 +1,65 @@ +# Copyright 2026 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 +# +# https://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. + + +def create_interaction() -> bool: + # [START googlegenaisdk_interactions_codeexecution_cropimage_with_txt_img] + import base64 + import io + import requests + from PIL import Image + from google import genai + from google.genai.interactions import CodeExecution, ImageContent, TextContent + + # Download the input image + image_path = "https://storage.googleapis.com/cloud-samples-data/generative-ai/image/chips.jpeg" + image_bytes = requests.get(image_path).content + b64_image = base64.b64encode(image_bytes).decode("utf-8") + + client = genai.Client() + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + ImageContent(data=b64_image, mime_type="image/jpeg"), + TextContent(text="Locate the ESMT chip. What are the numbers on the chip?"), + ], + tools=[CodeExecution()], + ) + + for step in interaction.steps: + if step.type == "code_execution_call": + print("####################### 1. Generate Python Code #######################") + print(step.arguments.code) + elif step.type == "code_execution_result": + print("####################### 2. Executing Python Code #######################") + print(step.result) + + if interaction.output_image: + print("####################### 3. Save Output #######################") + image_data = base64.b64decode(interaction.output_image.data) + image = Image.open(io.BytesIO(image_data)) + output_location = "ESMT-chip-output.jpg" + image.save(output_location) + print(f"Output is saved to {output_location}") + + if interaction.output_text: + print(interaction.output_text) + + # [END googlegenaisdk_interactions_codeexecution_cropimage_with_txt_img] + return True + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/code_execution/test_codeexecution.py b/genai/code_execution/test_codeexecution.py index ea978643c7c..0fa1438f65a 100644 --- a/genai/code_execution/test_codeexecution.py +++ b/genai/code_execution/test_codeexecution.py @@ -16,6 +16,9 @@ import codeexecution_annotateimage_with_txt_gcsimg import codeexecution_barplot_with_txt_img import codeexecution_cropimage_with_txt_img +import codeexecution_interactions_annotateimage_with_txt_gcsimg +import codeexecution_interactions_barplot_with_txt_img +import codeexecution_interactions_cropimage_with_txt_img os.environ["GOOGLE_GENAI_USE_ENTERPRISE"] = "True" os.environ["GOOGLE_CLOUD_LOCATION"] = "global" # "us-central1" @@ -33,3 +36,16 @@ def test_codeexecution_barplot_with_txt_img() -> None: def test_codeexecution_cropimage_with_txt_img() -> None: assert codeexecution_cropimage_with_txt_img.generate_content() + + +def test_codeexecution_interactions_annotateimage_with_txt_gcsimg() -> None: + assert codeexecution_interactions_annotateimage_with_txt_gcsimg.create_interaction() + + +def test_codeexecution_interactions_barplot_with_txt_img() -> None: + assert codeexecution_interactions_barplot_with_txt_img.create_interaction() + + +def test_codeexecution_interactions_cropimage_with_txt_img() -> None: + assert codeexecution_interactions_cropimage_with_txt_img.create_interaction() + diff --git a/genai/content_cache/requirements.txt b/genai/content_cache/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/content_cache/requirements.txt +++ b/genai/content_cache/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/controlled_generation/ctrlgen_interactions_with_class_schema.py b/genai/controlled_generation/ctrlgen_interactions_with_class_schema.py new file mode 100644 index 00000000000..5deb0899e7a --- /dev/null +++ b/genai/controlled_generation/ctrlgen_interactions_with_class_schema.py @@ -0,0 +1,50 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_ctrlgen_with_class_schema] + import json + from google import genai + from google.genai.interactions import TextResponseFormat + from pydantic import BaseModel + + class Recipe(BaseModel): + recipe_name: str + ingredients: list[str] + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="List a few popular cookie recipes.", + response_format=TextResponseFormat( + mime_type="application/json", + schema={ + "type": "array", + "items": Recipe.model_json_schema(), + }, + ), + ) + + # Use the response as a JSON string + print(interaction.output_text) + # Parse the response JSON into Pydantic models + recipes = [Recipe(**r) for r in json.loads(interaction.output_text)] + print(recipes) + # [END googlegenaisdk_interactions_ctrlgen_with_class_schema] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/controlled_generation/ctrlgen_interactions_with_enum_class_schema.py b/genai/controlled_generation/ctrlgen_interactions_with_enum_class_schema.py new file mode 100644 index 00000000000..b12b0e43ff3 --- /dev/null +++ b/genai/controlled_generation/ctrlgen_interactions_with_enum_class_schema.py @@ -0,0 +1,48 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_ctrlgen_with_enum_class_schema] + import enum + from google import genai + from google.genai.interactions import TextResponseFormat + + class InstrumentClass(enum.Enum): + PERCUSSION = "Percussion" + STRING = "String" + WOODWIND = "Woodwind" + BRASS = "Brass" + KEYBOARD = "Keyboard" + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="What type of instrument is a guitar?", + response_format=TextResponseFormat( + mime_type="text/x.enum", + schema={ + "type": "string", + "enum": [e.value for e in InstrumentClass], + }, + ), + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_ctrlgen_with_enum_class_schema] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/controlled_generation/ctrlgen_interactions_with_enum_schema.py b/genai/controlled_generation/ctrlgen_interactions_with_enum_schema.py new file mode 100644 index 00000000000..dbdd1a7ca33 --- /dev/null +++ b/genai/controlled_generation/ctrlgen_interactions_with_enum_schema.py @@ -0,0 +1,40 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_ctrlgen_with_enum_schema] + from google import genai + from google.genai.interactions import TextResponseFormat + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="What type of instrument is an oboe?", + response_format=TextResponseFormat( + mime_type="text/x.enum", + schema={ + "type": "string", + "enum": ["Percussion", "String", "Woodwind", "Brass", "Keyboard"], + }, + ), + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_ctrlgen_with_enum_schema] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/controlled_generation/ctrlgen_interactions_with_nested_class_schema.py b/genai/controlled_generation/ctrlgen_interactions_with_nested_class_schema.py new file mode 100644 index 00000000000..ff1435bce52 --- /dev/null +++ b/genai/controlled_generation/ctrlgen_interactions_with_nested_class_schema.py @@ -0,0 +1,54 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_ctrlgen_with_nested_class_schema] + import enum + from google import genai + from google.genai.interactions import TextResponseFormat + from pydantic import BaseModel + + class Grade(str, enum.Enum): + A_PLUS = "a+" + A = "a" + B = "b" + C = "c" + D = "d" + F = "f" + + class Recipe(BaseModel): + recipe_name: str + rating: Grade + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="List about 10 home-baked cookies and give them grades based on tastiness.", + response_format=TextResponseFormat( + mime_type="application/json", + schema={ + "type": "array", + "items": Recipe.model_json_schema(), + }, + ), + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_ctrlgen_with_nested_class_schema] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/controlled_generation/ctrlgen_interactions_with_nullable_schema.py b/genai/controlled_generation/ctrlgen_interactions_with_nullable_schema.py new file mode 100644 index 00000000000..ee47fc2e7d6 --- /dev/null +++ b/genai/controlled_generation/ctrlgen_interactions_with_nullable_schema.py @@ -0,0 +1,68 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_ctrlgen_with_nullable_schema] + from google import genai + from google.genai.interactions import TextResponseFormat + + response_schema = { + "type": "object", + "properties": { + "forecast": { + "type": "array", + "items": { + "type": "object", + "properties": { + "Day": {"type": "string", "nullable": True}, + "Forecast": {"type": "string", "nullable": True}, + "Temperature": {"type": "integer", "nullable": True}, + "Humidity": {"type": "string", "nullable": True}, + "Wind Speed": {"type": "integer", "nullable": True}, + }, + "required": ["Day", "Temperature", "Forecast", "Wind Speed"], + }, + } + }, + } + + prompt = """ + The week ahead brings a mix of weather conditions. + Sunday is expected to be sunny with a temperature of 77°F and a humidity level of 50%. Winds will be light at around 10 km/h. + Monday will see partly cloudy skies with a slightly cooler temperature of 72°F and the winds will pick up slightly to around 15 km/h. + Tuesday brings rain showers, with temperatures dropping to 64°F and humidity rising to 70%. + Wednesday may see thunderstorms, with a temperature of 68°F. + Thursday will be cloudy with a temperature of 66°F and moderate humidity at 60%. + Friday returns to partly cloudy conditions, with a temperature of 73°F and the Winds will be light at 12 km/h. + Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, and a humidity level of 40%. Winds will be gentle at 8 km/h. + """ + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=prompt, + response_format=TextResponseFormat( + mime_type="application/json", + schema=response_schema, + ), + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_ctrlgen_with_nullable_schema] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/controlled_generation/ctrlgen_interactions_with_resp_schema.py b/genai/controlled_generation/ctrlgen_interactions_with_resp_schema.py new file mode 100644 index 00000000000..0533a40e42a --- /dev/null +++ b/genai/controlled_generation/ctrlgen_interactions_with_resp_schema.py @@ -0,0 +1,53 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_ctrlgen_with_resp_schema] + from google import genai + from google.genai.interactions import TextResponseFormat + + response_schema = { + "type": "array", + "items": { + "type": "object", + "properties": { + "recipe_name": {"type": "string"}, + "ingredients": {"type": "array", "items": {"type": "string"}}, + }, + "required": ["recipe_name", "ingredients"], + }, + } + + prompt = """ + List a few popular cookie recipes. + """ + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=prompt, + response_format=TextResponseFormat( + mime_type="application/json", + schema=response_schema, + ), + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_ctrlgen_with_resp_schema] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/controlled_generation/requirements.txt b/genai/controlled_generation/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/controlled_generation/requirements.txt +++ b/genai/controlled_generation/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/controlled_generation/test_controlled_generation_examples.py b/genai/controlled_generation/test_controlled_generation_examples.py index 2bd518be054..29a0562f6db 100644 --- a/genai/controlled_generation/test_controlled_generation_examples.py +++ b/genai/controlled_generation/test_controlled_generation_examples.py @@ -18,6 +18,12 @@ import os +import ctrlgen_interactions_with_class_schema +import ctrlgen_interactions_with_enum_class_schema +import ctrlgen_interactions_with_enum_schema +import ctrlgen_interactions_with_nested_class_schema +import ctrlgen_interactions_with_nullable_schema +import ctrlgen_interactions_with_resp_schema import ctrlgen_with_class_schema import ctrlgen_with_enum_class_schema import ctrlgen_with_enum_schema @@ -53,3 +59,28 @@ def test_ctrlgen_with_nullable_schema() -> None: def test_ctrlgen_with_resp_schema() -> None: assert ctrlgen_with_resp_schema.generate_content() + + +def test_ctrlgen_interactions_with_class_schema() -> None: + assert ctrlgen_interactions_with_class_schema.create_interaction() + + +def test_ctrlgen_interactions_with_enum_class_schema() -> None: + assert ctrlgen_interactions_with_enum_class_schema.create_interaction() + + +def test_ctrlgen_interactions_with_enum_schema() -> None: + assert ctrlgen_interactions_with_enum_schema.create_interaction() + + +def test_ctrlgen_interactions_with_nested_class_schema() -> None: + assert ctrlgen_interactions_with_nested_class_schema.create_interaction() + + +def test_ctrlgen_interactions_with_nullable_schema() -> None: + assert ctrlgen_interactions_with_nullable_schema.create_interaction() + + +def test_ctrlgen_interactions_with_resp_schema() -> None: + assert ctrlgen_interactions_with_resp_schema.create_interaction() + diff --git a/genai/count_tokens/requirements.txt b/genai/count_tokens/requirements.txt index 726dd09178a..0fa4fa1b71c 100644 --- a/genai/count_tokens/requirements.txt +++ b/genai/count_tokens/requirements.txt @@ -1,2 +1,2 @@ -google-genai==1.42.0 +google-genai==2.29.0 sentencepiece==0.2.1 diff --git a/genai/express_mode/requirements.txt b/genai/express_mode/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/express_mode/requirements.txt +++ b/genai/express_mode/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/image_generation/requirements.txt b/genai/image_generation/requirements.txt index 75a39f7e582..1af6c711b57 100644 --- a/genai/image_generation/requirements.txt +++ b/genai/image_generation/requirements.txt @@ -1,2 +1,2 @@ -google-genai==1.42.0 +google-genai==2.29.0 pillow==12.3.0; python_version >= "3.10" diff --git a/genai/live/requirements.txt b/genai/live/requirements.txt index 477952fc6d7..b20a2df28a8 100644 --- a/genai/live/requirements.txt +++ b/genai/live/requirements.txt @@ -1,4 +1,4 @@ -google-genai==1.42.0 +google-genai==2.29.0 scipy==1.18.1 websockets==15.0.1 numpy==2.5.3 diff --git a/genai/model_optimizer/requirements.txt b/genai/model_optimizer/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/model_optimizer/requirements.txt +++ b/genai/model_optimizer/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/provisioned_throughput/requirements.txt b/genai/provisioned_throughput/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/provisioned_throughput/requirements.txt +++ b/genai/provisioned_throughput/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/safety/requirements.txt b/genai/safety/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/safety/requirements.txt +++ b/genai/safety/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/template_folder/requirements.txt b/genai/template_folder/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/template_folder/requirements.txt +++ b/genai/template_folder/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/text_generation/requirements.txt b/genai/text_generation/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/text_generation/requirements.txt +++ b/genai/text_generation/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/text_generation/test_text_generation_examples.py b/genai/text_generation/test_text_generation_examples.py index d859b4ff73b..2c39edb4c42 100644 --- a/genai/text_generation/test_text_generation_examples.py +++ b/genai/text_generation/test_text_generation_examples.py @@ -24,6 +24,23 @@ import textgen_chat_with_txt import textgen_code_with_pdf import textgen_config_with_txt +import textgen_interactions_async_with_txt +import textgen_interactions_chat_stream_with_txt +import textgen_interactions_chat_with_txt +import textgen_interactions_code_with_pdf +import textgen_interactions_config_with_txt +import textgen_interactions_sys_instr_with_txt +import textgen_interactions_transcript_with_gcs_audio +import textgen_interactions_with_gcs_audio +import textgen_interactions_with_local_video +import textgen_interactions_with_multi_img +import textgen_interactions_with_multi_local_img +import textgen_interactions_with_pdf +import textgen_interactions_with_txt +import textgen_interactions_with_txt_img +import textgen_interactions_with_txt_stream +import textgen_interactions_with_video +import textgen_interactions_with_youtube_video import textgen_sys_instr_with_txt import textgen_transcript_with_gcs_audio import textgen_with_gcs_audio @@ -37,6 +54,7 @@ import textgen_with_txt_stream import textgen_with_video import textgen_with_youtube_video +import thinking_textgen_interactions_with_txt import thinking_textgen_with_txt os.environ["GOOGLE_GENAI_USE_ENTERPRISE"] = "True" @@ -142,6 +160,99 @@ def test_textgen_code_with_pdf() -> None: response = textgen_code_with_pdf.generate_content() assert response + +def test_textgen_interactions_with_txt_stream() -> None: + response = textgen_interactions_with_txt_stream.create_interaction() + assert response + + +def test_textgen_interactions_with_txt() -> None: + response = textgen_interactions_with_txt.create_interaction() + assert response + + +def test_textgen_interactions_chat_with_txt() -> None: + response = textgen_interactions_chat_with_txt.create_interaction() + assert response + + +def test_textgen_interactions_chat_stream_with_txt() -> None: + response = textgen_interactions_chat_stream_with_txt.create_interaction() + assert response + + +def test_textgen_interactions_config_with_txt() -> None: + response = textgen_interactions_config_with_txt.create_interaction() + assert response + + +def test_textgen_interactions_sys_instr_with_txt() -> None: + response = textgen_interactions_sys_instr_with_txt.create_interaction() + assert response + + +def test_textgen_interactions_with_pdf() -> None: + response = textgen_interactions_with_pdf.create_interaction() + assert response + + +def test_textgen_interactions_with_txt_img() -> None: + response = textgen_interactions_with_txt_img.create_interaction() + assert response + + +def test_textgen_interactions_with_txt_thinking() -> None: + response = thinking_textgen_interactions_with_txt.create_interaction() + assert response + + +def test_textgen_interactions_with_multi_img() -> None: + response = textgen_interactions_with_multi_img.create_interaction() + assert response + + +def test_textgen_interactions_with_multi_local_img() -> None: + response = textgen_interactions_with_multi_local_img.create_interaction( + "./test_data/latte.jpg", + "./test_data/scones.jpg", + ) + assert response + + +def test_textgen_interactions_with_gcs_audio() -> None: + response = textgen_interactions_with_gcs_audio.create_interaction() + assert response + + +def test_textgen_interactions_transcript_with_gcs_audio() -> None: + response = textgen_interactions_transcript_with_gcs_audio.create_interaction() + assert response + + +def test_textgen_interactions_with_video() -> None: + response = textgen_interactions_with_video.create_interaction() + assert response + + +def test_textgen_interactions_async_with_txt() -> None: + response = textgen_interactions_async_with_txt.create_interaction() + assert response + + +def test_textgen_interactions_with_local_video() -> None: + response = textgen_interactions_with_local_video.create_interaction() + assert response + + +def test_textgen_interactions_with_youtube_video() -> None: + response = textgen_interactions_with_youtube_video.create_interaction() + assert response + + +def test_textgen_interactions_code_with_pdf() -> None: + response = textgen_interactions_code_with_pdf.create_interaction() + assert response + # Migrated to Model Optimser Folder # def test_model_optimizer_textgen_with_txt() -> None: # os.environ["GOOGLE_CLOUD_LOCATION"] = "us-central1" diff --git a/genai/text_generation/textgen_interactions_async_with_txt.py b/genai/text_generation/textgen_interactions_async_with_txt.py new file mode 100644 index 00000000000..db09a37aa96 --- /dev/null +++ b/genai/text_generation/textgen_interactions_async_with_txt.py @@ -0,0 +1,42 @@ +# Copyright 2025 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 +# +# https://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. + +import asyncio + + +async def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_async_with_txt] + from google import genai + + client = genai.Client() + model_id = "gemini-3.8-flash" + + interaction = await client.aio.interactions.create( + model=model_id, + input="Compose a song about the adventures of a time-traveling squirrel.", + response_modalities=["TEXT"], + ) + + print(interaction.output_text) + # Example response: + # (Verse 1) + # Sammy the squirrel, a furry little friend + # Had a knack for adventure, beyond all comprehend + + # [END googlegenaisdk_interactions_textgen_async_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + asyncio.run(create_interaction()) diff --git a/genai/text_generation/textgen_interactions_chat_stream_with_txt.py b/genai/text_generation/textgen_interactions_chat_stream_with_txt.py new file mode 100644 index 00000000000..a8474ac2b0d --- /dev/null +++ b/genai/text_generation/textgen_interactions_chat_stream_with_txt.py @@ -0,0 +1,50 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> bool: + # [START googlegenaisdk_interactions_textgen_chat_stream_with_txt] + from google import genai + + client = genai.Client() + + interaction1 = client.interactions.create( + model="gemini-3.8-flash", + input="Hello", + ) + + stream = client.interactions.create( + model="gemini-3.8-flash", + previous_interaction_id=interaction1.id, + input="Why is the sky blue?", + stream=True, + ) + + for event in stream: + if event.event_type == "step.delta" and event.delta: + if getattr(event.delta, "type", None) == "text" and getattr( + event.delta, "text", None + ): + print(event.delta.text, end="", flush=True) + # Example response: + # The + # sky appears blue due to a phenomenon called **Rayleigh scattering**. Here's + # a breakdown of why: + # ... + # [END googlegenaisdk_interactions_textgen_chat_stream_with_txt] + return True + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_chat_with_txt.py b/genai/text_generation/textgen_interactions_chat_with_txt.py new file mode 100644 index 00000000000..21a169050cb --- /dev/null +++ b/genai/text_generation/textgen_interactions_chat_with_txt.py @@ -0,0 +1,40 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_chat_with_txt] + from google import genai + + client = genai.Client() + interaction1 = client.interactions.create( + model="gemini-3.8-flash", + input="Hello", + ) + + interaction2 = client.interactions.create( + model="gemini-3.8-flash", + previous_interaction_id=interaction1.id, + input="Tell me a story.", + ) + print(interaction2.output_text) + # Example response: + # Okay, here's a story for you: + # ... + # [END googlegenaisdk_interactions_textgen_chat_with_txt] + return interaction2.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_code_with_pdf.py b/genai/text_generation/textgen_interactions_code_with_pdf.py new file mode 100644 index 00000000000..cee04a1b0d6 --- /dev/null +++ b/genai/text_generation/textgen_interactions_code_with_pdf.py @@ -0,0 +1,54 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_code_with_pdf] + from google import genai + from google.genai.interactions import DocumentContent, TextContent + + client = genai.Client() + model_id = "gemini-3.8-flash" + prompt = "Convert this python code to use Google Python Style Guide." + print("> ", prompt, "\n") + pdf_uri = "https://storage.googleapis.com/cloud-samples-data/generative-ai/text/inefficient_fibonacci_series_python_code.pdf" + + interaction = client.interactions.create( + model=model_id, + input=[ + DocumentContent( + uri=pdf_uri, + mime_type="application/pdf", + ), + TextContent(text=prompt), + ], + ) + + print(interaction.output_text) + # Example response: + # > Convert this python code to use Google Python Style Guide. + # + # def generate_fibonacci_sequence(num_terms: int) -> list[int]: + # """Generates the Fibonacci sequence up to a specified number of terms. + # + # This function calculates the Fibonacci sequence starting with 0 and 1. + # It handles base cases for 0, 1, and 2 terms efficiently. + # + # # ... + # [END googlegenaisdk_interactions_textgen_code_with_pdf] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_config_with_txt.py b/genai/text_generation/textgen_interactions_config_with_txt.py new file mode 100644 index 00000000000..a4d474924c6 --- /dev/null +++ b/genai/text_generation/textgen_interactions_config_with_txt.py @@ -0,0 +1,40 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_config_with_txt] + from google import genai + from google.genai.interactions import GenerationConfig + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="Why is the sky blue?", + generation_config=GenerationConfig( + max_output_tokens=500, + ), + response_mime_type="application/json", + ) + print(interaction.output_text) + # Example response: + # { + # "explanation": "The sky appears blue due to a phenomenon called Rayleigh scattering. When ... + # } + # [END googlegenaisdk_interactions_textgen_config_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_sys_instr_with_txt.py b/genai/text_generation/textgen_interactions_sys_instr_with_txt.py new file mode 100644 index 00000000000..c91844a9415 --- /dev/null +++ b/genai/text_generation/textgen_interactions_sys_instr_with_txt.py @@ -0,0 +1,34 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_sys_instr_with_txt] + from google import genai + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="Why is the sky blue?", + system_instruction="You're a language translator. Your mission is to translate text in English to French.", + ) + print(interaction.output_text) + # Example response: + # Pourquoi le ciel est-il bleu ? + # [END googlegenaisdk_interactions_textgen_sys_instr_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_transcript_with_gcs_audio.py b/genai/text_generation/textgen_interactions_transcript_with_gcs_audio.py new file mode 100644 index 00000000000..079012885fb --- /dev/null +++ b/genai/text_generation/textgen_interactions_transcript_with_gcs_audio.py @@ -0,0 +1,48 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_transcript_with_gcs_audio] + from google import genai + from google.genai.interactions import AudioContent, TextContent + + client = genai.Client() + prompt = """ + Transcribe the interview, in the format of timecode, speaker, caption. + Use speaker A, speaker B, etc. to identify speakers. + """ + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + AudioContent( + uri="gs://cloud-samples-data/generative-ai/audio/pixel.mp3", + mime_type="audio/mpeg", + ), + TextContent(text=prompt), + ], + ) + print(interaction.output_text) + # Example response: + # [00:00:00] **Speaker A:** your devices are getting better over time. And so ... + # [00:00:14] **Speaker B:** Welcome to the Made by Google podcast where we meet ... + # [00:00:20] **Speaker B:** Here's your host, Rasheed Finch. + # [00:00:23] **Speaker C:** Today we're talking to Aisha Sharif and DeCarlos Love. ... + # ... + # [END googlegenaisdk_interactions_textgen_transcript_with_gcs_audio] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_gcs_audio.py b/genai/text_generation/textgen_interactions_with_gcs_audio.py new file mode 100644 index 00000000000..f555295a742 --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_gcs_audio.py @@ -0,0 +1,45 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_with_gcs_audio] + from google import genai + from google.genai.interactions import AudioContent, TextContent + + client = genai.Client() + prompt = """ + Provide a concise summary of the main points in the audio file. + """ + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + AudioContent( + uri="gs://cloud-samples-data/generative-ai/audio/pixel.mp3", + mime_type="audio/mpeg", + ), + TextContent(text=prompt), + ], + ) + print(interaction.output_text) + # Example response: + # Here's a summary of the main points from the audio file: + + # The Made by Google podcast discusses the Pixel feature drops with product managers Aisha Sheriff and De Carlos Love. The key idea is that devices should improve over time, with a connected experience across phones, watches, earbuds, and tablets. + # [END googlegenaisdk_interactions_textgen_with_gcs_audio] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_local_video.py b/genai/text_generation/textgen_interactions_with_local_video.py new file mode 100644 index 00000000000..19f792bf879 --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_local_video.py @@ -0,0 +1,53 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_with_local_video] + import base64 + from google import genai + from google.genai.interactions import TextContent, VideoContent + + client = genai.Client() + model_id = "gemini-3.8-flash" + + # Read local video file content + with open("test_data/describe_video_content.mp4", "rb") as fp: + # Video source: https://storage.googleapis.com/cloud-samples-data/generative-ai/video/describe_video_content.mp4 + video_content = fp.read() + video_b64 = base64.b64encode(video_content).decode("utf-8") + + interaction = client.interactions.create( + model=model_id, + input=[ + TextContent(text="hello-world"), + VideoContent( + data=video_b64, + mime_type="video/mp4", + ), + TextContent(text="Write a short and engaging blog post based on this video."), + ], + ) + + print(interaction.output_text) + # Example response: + # Okay, here's a short and engaging blog post based on the climbing video: + # **Title: Conquering the Wall: A Glimpse into the World of Indoor Climbing** + # ... + # [END googlegenaisdk_interactions_textgen_with_local_video] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_multi_img.py b/genai/text_generation/textgen_interactions_with_multi_img.py new file mode 100644 index 00000000000..2e7dc39f915 --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_multi_img.py @@ -0,0 +1,55 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_with_multi_img] + import base64 + from google import genai + from google.genai.interactions import ImageContent, TextContent + + client = genai.Client() + + # Read content from GCS + gcs_file_img_path = "gs://cloud-samples-data/generative-ai/image/scones.jpg" + + # Read content from a local file + with open("test_data/latte.jpg", "rb") as f: + local_file_img_bytes = f.read() + local_file_img_b64 = base64.b64encode(local_file_img_bytes).decode("utf-8") + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + TextContent(text="Generate a list of all the objects contained in both images."), + ImageContent( + uri=gcs_file_img_path, + mime_type="image/jpeg", + ), + ImageContent( + data=local_file_img_b64, + mime_type="image/jpeg", + ), + ], + ) + print(interaction.output_text) + # Example response: + # Okay, here's the list of objects present in both images: + # ... + # [END googlegenaisdk_interactions_textgen_with_multi_img] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_multi_local_img.py b/genai/text_generation/textgen_interactions_with_multi_local_img.py new file mode 100644 index 00000000000..14ef57ff2eb --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_multi_local_img.py @@ -0,0 +1,60 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction(image_path_1: str, image_path_2: str) -> str: + # [START googlegenaisdk_interactions_textgen_with_multi_local_img] + import base64 + from google import genai + from google.genai.interactions import ImageContent, TextContent + + client = genai.Client() + # TODO(Developer): Update the below file paths to your images + # image_path_1 = "path/to/your/image1.jpg" + # image_path_2 = "path/to/your/image2.jpg" + with open(image_path_1, "rb") as f: + image_1_bytes = f.read() + with open(image_path_2, "rb") as f: + image_2_bytes = f.read() + + image_1_b64 = base64.b64encode(image_1_bytes).decode("utf-8") + image_2_b64 = base64.b64encode(image_2_bytes).decode("utf-8") + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + TextContent(text="Generate a list of all the objects contained in both images."), + ImageContent( + data=image_1_b64, + mime_type="image/jpeg", + ), + ImageContent( + data=image_2_b64, + mime_type="image/jpeg", + ), + ], + ) + print(interaction.output_text) + # Example response: + # Okay, here's a jingle combining the elements of both sets of images, focusing on ... + # ... + # [END googlegenaisdk_interactions_textgen_with_multi_local_img] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction( + "./test_data/latte.jpg", + "./test_data/scones.jpg", + ) diff --git a/genai/text_generation/textgen_interactions_with_pdf.py b/genai/text_generation/textgen_interactions_with_pdf.py new file mode 100644 index 00000000000..4f9244ff441 --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_pdf.py @@ -0,0 +1,54 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_with_pdf] + from google import genai + from google.genai.interactions import DocumentContent, TextContent + + client = genai.Client() + model_id = "gemini-3.8-flash" + + prompt = """ + You are a highly skilled document summarization specialist. + Your task is to provide a concise executive summary of no more than 300 words. + Please summarize the given document for a general audience. + """ + + interaction = client.interactions.create( + model=model_id, + input=[ + DocumentContent( + uri="gs://cloud-samples-data/generative-ai/pdf/1706.03762v7.pdf", + mime_type="application/pdf", + ), + TextContent(text=prompt), + ], + ) + + print(interaction.output_text) + # Example response: + # Here is a summary of the document in 300 words. + # + # The paper introduces the Transformer, a novel neural network architecture for + # sequence transduction tasks like machine translation. Unlike existing models that rely on recurrent or + # convolutional layers, the Transformer is based entirely on attention mechanisms. + # ... + # [END googlegenaisdk_interactions_textgen_with_pdf] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_txt.py b/genai/text_generation/textgen_interactions_with_txt.py new file mode 100644 index 00000000000..3ea88432edc --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_txt.py @@ -0,0 +1,36 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_with_txt] + from google import genai + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="How does AI work?", + ) + print(interaction.output_text) + # Example response: + # Okay, let's break down how AI works. It's a broad field, so I'll focus on the ... + # + # Here's a simplified overview: + # ... + # [END googlegenaisdk_interactions_textgen_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_txt_img.py b/genai/text_generation/textgen_interactions_with_txt_img.py new file mode 100644 index 00000000000..ce7228dbe9d --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_txt_img.py @@ -0,0 +1,40 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_with_txt_img] + from google import genai + from google.genai.interactions import ImageContent, TextContent + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + TextContent(text="What is shown in this image?"), + ImageContent( + uri="gs://cloud-samples-data/generative-ai/image/scones.jpg", + mime_type="image/jpeg", + ), + ], + ) + print(interaction.output_text) + # Example response: + # The image shows a flat lay of blueberry scones arranged on parchment paper. There are ... + # [END googlegenaisdk_interactions_textgen_with_txt_img] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_txt_stream.py b/genai/text_generation/textgen_interactions_with_txt_stream.py new file mode 100644 index 00000000000..49e7ca3be1a --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_txt_stream.py @@ -0,0 +1,44 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> bool: + # [START googlegenaisdk_interactions_textgen_with_txt_stream] + from google import genai + + client = genai.Client() + + stream = client.interactions.create( + model="gemini-3.8-flash", + input="Why is the sky blue?", + stream=True, + ) + + for event in stream: + if event.event_type == "step.delta" and event.delta: + if getattr(event.delta, "type", None) == "text" and getattr( + event.delta, "text", None + ): + print(event.delta.text, end="", flush=True) + # Example response: + # The + # sky appears blue due to a phenomenon called **Rayleigh scattering**. Here's + # a breakdown of why: + # ... + # [END googlegenaisdk_interactions_textgen_with_txt_stream] + return True + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_video.py b/genai/text_generation/textgen_interactions_with_video.py new file mode 100644 index 00000000000..1632b9fe215 --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_video.py @@ -0,0 +1,55 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_with_video] + from google import genai + from google.genai.interactions import TextContent, VideoContent + + client = genai.Client() + prompt = """ + Analyze the provided video file, including its audio. + Summarize the main points of the video concisely. + Create a chapter breakdown with timestamps for key sections or topics discussed. + """ + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + VideoContent( + uri="gs://cloud-samples-data/generative-ai/video/pixel8.mp4", + mime_type="video/mp4", + ), + TextContent(text=prompt), + ], + ) + + print(interaction.output_text) + # Example response: + # Here's a breakdown of the video: + # + # **Summary:** + # + # Saeka Shimada, a photographer in Tokyo, uses the Google Pixel 8 Pro's "Video Boost" feature to ... + # + # **Chapter Breakdown with Timestamps:** + # + # * **[00:00-00:12] Introduction & Tokyo at Night:** Saeka Shimada introduces herself ... + # ... + # [END googlegenaisdk_interactions_textgen_with_video] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/textgen_interactions_with_youtube_video.py b/genai/text_generation/textgen_interactions_with_youtube_video.py new file mode 100644 index 00000000000..1abaa418a7e --- /dev/null +++ b/genai/text_generation/textgen_interactions_with_youtube_video.py @@ -0,0 +1,47 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_textgen_with_youtube_video] + from google import genai + from google.genai.interactions import TextContent, VideoContent + + client = genai.Client() + model_id = "gemini-3.8-flash" + + interaction = client.interactions.create( + model=model_id, + input=[ + VideoContent( + uri="https://www.youtube.com/watch?v=3KtWfp0UopM", + mime_type="video/mp4", + ), + TextContent(text="Write a short and engaging blog post based on this video."), + ], + ) + + print(interaction.output_text) + # Example response: + # Here's a short blog post based on the video provided: + # + # **Google Turns 25: A Quarter Century of Search!** + # ... + + # [END googlegenaisdk_interactions_textgen_with_youtube_video] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/text_generation/thinking_textgen_interactions_with_txt.py b/genai/text_generation/thinking_textgen_interactions_with_txt.py new file mode 100644 index 00000000000..dcbfd513314 --- /dev/null +++ b/genai/text_generation/thinking_textgen_interactions_with_txt.py @@ -0,0 +1,94 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_thinking_textgen_with_txt] + from google import genai + from google.genai.interactions import GenerationConfig + + client = genai.Client() + interaction = client.interactions.create( + model="gemini-4-argon", + input="solve x^2 + 4x + 4 = 0", + generation_config=GenerationConfig( + thinking_level="high", + thinking_summaries="auto", + ), + ) + + # Print the model's thoughts if available + for step in interaction.steps: + if step.type == "thought" and step.summary: + print("--- Thoughts ---") + for item in step.summary: + if hasattr(item, "text"): + print(item.text) + else: + print(item) + + print("--- Answer ---") + print(interaction.output_text) + # Example Response: + # Okay, let's solve the quadratic equation x² + 4x + 4 = 0. + # + # We can solve this equation by factoring, using the quadratic formula, or by recognizing it as a perfect square trinomial. + # + # **Method 1: Factoring** + # + # 1. We need two numbers that multiply to the constant term (4) and add up to the coefficient of the x term (4). + # 2. The numbers 2 and 2 satisfy these conditions: 2 * 2 = 4 and 2 + 2 = 4. + # 3. So, we can factor the quadratic as: + # (x + 2)(x + 2) = 0 + # or + # (x + 2)² = 0 + # 4. For the product to be zero, the factor must be zero: + # x + 2 = 0 + # 5. Solve for x: + # x = -2 + # + # **Method 2: Quadratic Formula** + # + # The quadratic formula for an equation ax² + bx + c = 0 is: + # x = [-b ± sqrt(b² - 4ac)] / (2a) + # + # 1. In our equation x² + 4x + 4 = 0, we have a=1, b=4, and c=4. + # 2. Substitute these values into the formula: + # x = [-4 ± sqrt(4² - 4 * 1 * 4)] / (2 * 1) + # x = [-4 ± sqrt(16 - 16)] / 2 + # x = [-4 ± sqrt(0)] / 2 + # x = [-4 ± 0] / 2 + # x = -4 / 2 + # x = -2 + # + # **Method 3: Perfect Square Trinomial** + # + # 1. Notice that the expression x² + 4x + 4 fits the pattern of a perfect square trinomial: a² + 2ab + b², where a=x and b=2. + # 2. We can rewrite the equation as: + # (x + 2)² = 0 + # 3. Take the square root of both sides: + # x + 2 = 0 + # 4. Solve for x: + # x = -2 + # + # All methods lead to the same solution. + # + # **Answer:** + # The solution to the equation x² + 4x + 4 = 0 is x = -2. This is a repeated root (or a root with multiplicity 2). + # [END googlegenaisdk_interactions_thinking_textgen_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/thinking/requirements.txt b/genai/thinking/requirements.txt index 1efe7b29dbc..ad433f48578 100644 --- a/genai/thinking/requirements.txt +++ b/genai/thinking/requirements.txt @@ -1 +1 @@ -google-genai==1.42.0 +google-genai==2.29.0 diff --git a/genai/tools/test_tools_examples.py b/genai/tools/test_tools_examples.py index 95611393b00..c368dba92bf 100644 --- a/genai/tools/test_tools_examples.py +++ b/genai/tools/test_tools_examples.py @@ -28,6 +28,17 @@ import tools_google_maps_with_txt import tools_google_search_and_urlcontext_with_txt import tools_google_search_with_txt +import tools_interactions_code_exec_with_txt +import tools_interactions_code_exec_with_txt_local_img +import tools_interactions_enterprise_web_search_with_txt +import tools_interactions_func_def_with_txt +import tools_interactions_func_desc_with_txt +import tools_interactions_google_maps_coordinates_with_txt +import tools_interactions_google_maps_with_txt +import tools_interactions_google_search_and_urlcontext_with_txt +import tools_interactions_google_search_with_txt +import tools_interactions_urlcontext_with_txt +import tools_interactions_vais_with_txt import tools_urlcontext_with_txt import tools_vais_with_txt @@ -84,3 +95,53 @@ def test_tools_urlcontext_with_txt() -> None: def test_tools_google_search_and_urlcontext_with_txt() -> None: assert tools_google_search_and_urlcontext_with_txt.generate_content() + + +def test_tools_interactions_code_exec_with_txt() -> None: + assert tools_interactions_code_exec_with_txt.create_interaction() + + +def test_tools_interactions_code_exec_with_txt_local_img() -> None: + assert tools_interactions_code_exec_with_txt_local_img.create_interaction() + + +def test_tools_interactions_enterprise_web_search_with_txt() -> None: + assert tools_interactions_enterprise_web_search_with_txt.create_interaction() + + +def test_tools_interactions_func_def_with_txt() -> None: + assert tools_interactions_func_def_with_txt.create_interaction() + + +def test_tools_interactions_func_desc_with_txt() -> None: + assert tools_interactions_func_desc_with_txt.create_interaction() + + +@pytest.mark.skip( + reason="Google Maps Grounding allowlisting is not set up for the test project." +) +def test_tools_interactions_google_maps_with_txt() -> None: + assert tools_interactions_google_maps_with_txt.create_interaction() + + +def test_tools_interactions_google_search_with_txt() -> None: + assert tools_interactions_google_search_with_txt.create_interaction() + + +def test_tools_interactions_vais_with_txt() -> None: + PROJECT_ID = os.environ.get("GOOGLE_CLOUD_PROJECT") + datastore = f"projects/{PROJECT_ID}/locations/global/collections/default_collection/dataStores/grounding-test-datastore" + assert tools_interactions_vais_with_txt.create_interaction(datastore) + + +def test_tools_interactions_google_maps_coordinates_with_txt() -> None: + assert tools_interactions_google_maps_coordinates_with_txt.create_interaction() + + +def test_tools_interactions_urlcontext_with_txt() -> None: + assert tools_interactions_urlcontext_with_txt.create_interaction() + + +def test_tools_interactions_google_search_and_urlcontext_with_txt() -> None: + assert tools_interactions_google_search_and_urlcontext_with_txt.create_interaction() + diff --git a/genai/tools/tools_interactions_code_exec_with_txt.py b/genai/tools/tools_interactions_code_exec_with_txt.py new file mode 100644 index 00000000000..209e4aa7335 --- /dev/null +++ b/genai/tools/tools_interactions_code_exec_with_txt.py @@ -0,0 +1,48 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_code_exec_with_txt] + from google import genai + from google.genai.interactions import CodeExecution + + client = genai.Client() + model_id = "gemini-3.8-flash" + + interaction = client.interactions.create( + model=model_id, + input="Calculate 20th fibonacci number. Then find the nearest palindrome to it.", + tools=[CodeExecution()], + ) + + executable_code = None + execution_result = None + for step in interaction.steps: + if step.type == "code_execution_call": + executable_code = step.arguments.code + print("# Code:") + print(executable_code) + elif step.type == "code_execution_result": + execution_result = step.result + print("# Outcome:") + print(execution_result) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_tools_code_exec_with_txt] + return executable_code + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_code_exec_with_txt_local_img.py b/genai/tools/tools_interactions_code_exec_with_txt_local_img.py new file mode 100644 index 00000000000..d10dbd5e931 --- /dev/null +++ b/genai/tools/tools_interactions_code_exec_with_txt_local_img.py @@ -0,0 +1,64 @@ +# Copyright 2025 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 +# +# https://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 typing import Any + + +def create_interaction() -> Any: + # [START googlegenaisdk_interactions_tools_code_exec_with_txt_local_img] + import base64 + from google import genai + from google.genai.interactions import CodeExecution, ImageContent, TextContent + + client = genai.Client() + + prompt = """ + Run a simulation of the Monty Hall Problem with 1,000 trials. + Here's how this works as a reminder. In the Monty Hall Problem, you're on a game + show with three doors. Behind one is a car, and behind the others are goats. You + pick a door. The host, who knows what's behind the doors, opens a different door + to reveal a goat. Should you switch to the remaining unopened door? + The answer has always been a little difficult for me to understand when people + solve it with math - so please run a simulation with Python to show me what the + best strategy is. + Thank you! + """ + + with open("test_data/640px-Monty_open_door.svg.png", "rb") as image_file: + b64_image = base64.b64encode(image_file.read()).decode("utf-8") + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input=[ + ImageContent(data=b64_image, mime_type="image/png"), + TextContent(text=prompt), + ], + tools=[CodeExecution()], + ) + + for step in interaction.steps: + if step.type == "code_execution_call": + print("# Code:") + print(step.arguments.code) + elif step.type == "code_execution_result": + print("# Outcome:") + print(step.result) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_tools_code_exec_with_txt_local_img] + return interaction + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_enterprise_web_search_with_txt.py b/genai/tools/tools_interactions_enterprise_web_search_with_txt.py new file mode 100644 index 00000000000..72206de1677 --- /dev/null +++ b/genai/tools/tools_interactions_enterprise_web_search_with_txt.py @@ -0,0 +1,35 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_enterprise_web_search_with_txt] + from google import genai + from google.genai.interactions import GoogleSearch + + client = genai.Client() + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="When is the next total solar eclipse in the United States?", + tools=[GoogleSearch(search_types=["enterprise_web_search"])], + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_tools_enterprise_web_search_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_func_def_with_txt.py b/genai/tools/tools_interactions_func_def_with_txt.py new file mode 100644 index 00000000000..2ed4a1c17e0 --- /dev/null +++ b/genai/tools/tools_interactions_func_def_with_txt.py @@ -0,0 +1,88 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_func_def_with_txt] + from google import genai + from google.genai.interactions import Function + + def get_current_weather(location: str) -> str: + """Example method. Returns the current weather. + + Args: + location: The city and state, e.g. San Francisco, CA + """ + weather_map: dict[str, str] = { + "Boston, MA": "snowing", + "San Francisco, CA": "foggy", + "Seattle, WA": "raining", + "Austin, TX": "hot", + "Chicago, IL": "windy", + } + return weather_map.get(location, "unknown") + + client = genai.Client() + model_id = "gemini-3.8-flash" + + # Define function tool declaration for the Interactions API + weather_tool = Function( + name="get_current_weather", + description="Returns the current weather for a given city and state.", + parameters={ + "type": "object", + "properties": { + "location": { + "type": "string", + "description": "The city and state, e.g. San Francisco, CA", + } + }, + "required": ["location"], + }, + ) + + interaction = client.interactions.create( + model=model_id, + input="What is the weather like in Boston?", + tools=[weather_tool], + ) + + # Check for function call step and execute it if requested + for step in interaction.steps: + if step.type == "function_call" and step.name == "get_current_weather": + args = step.arguments or {} + result = get_current_weather(**args) + + # Return function execution result back in a follow-up interaction + interaction = client.interactions.create( + model=model_id, + previous_interaction_id=interaction.id, + input=[ + { + "type": "function_result", + "call_id": step.id, + "name": step.name, + "result": [{"type": "text", "text": result}], + } + ], + ) + break + + print(interaction.output_text) + # [END googlegenaisdk_interactions_tools_func_def_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_func_desc_with_txt.py b/genai/tools/tools_interactions_func_desc_with_txt.py new file mode 100644 index 00000000000..6807c515cb5 --- /dev/null +++ b/genai/tools/tools_interactions_func_desc_with_txt.py @@ -0,0 +1,77 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_func_desc_with_txt] + from google import genai + from google.genai.interactions import Function + + client = genai.Client() + model_id = "gemini-3.8-flash" + + get_album_sales_tool = Function( + name="get_album_sales", + description="Gets the number of albums sold", + parameters={ + "type": "object", + "properties": { + "albums": { + "type": "array", + "description": "List of albums", + "items": { + "description": "Album and its sales", + "type": "object", + "properties": { + "album_name": { + "type": "string", + "description": "Name of the music album", + }, + "copies_sold": { + "type": "integer", + "description": "Number of copies sold", + }, + }, + }, + }, + }, + }, + ) + + interaction = client.interactions.create( + model=model_id, + input=( + 'At Stellar Sounds, a music label, 2024 was a rollercoaster. "Echoes of the Night," a debut synth-pop album, ' + 'surprisingly sold 350,000 copies, while veteran rock band "Crimson Tide\'s" latest, "Reckless Hearts," ' + 'lagged at 120,000. Their up-and-coming indie artist, "Luna Bloom\'s" EP, "Whispers of Dawn," ' + 'secured 75,000 sales. The biggest disappointment was the highly-anticipated rap album "Street Symphony" ' + "only reaching 100,000 units. Overall, Stellar Sounds moved over 645,000 units this year, revealing unexpected " + "trends in music consumption." + ), + tools=[get_album_sales_tool], + ) + + function_calls = [ + {"name": step.name, "arguments": step.arguments} + for step in interaction.steps + if step.type == "function_call" + ] + + print(function_calls) + # [END googlegenaisdk_interactions_tools_func_desc_with_txt] + return str(function_calls) + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_google_maps_coordinates_with_txt.py b/genai/tools/tools_interactions_google_maps_coordinates_with_txt.py new file mode 100644 index 00000000000..624ec593421 --- /dev/null +++ b/genai/tools/tools_interactions_google_maps_coordinates_with_txt.py @@ -0,0 +1,35 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_google_maps_coordinates_with_txt] + from google import genai + from google.genai.interactions import GoogleMaps + + client = genai.Client() + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="Where can I get the best espresso near me?", + tools=[GoogleMaps(latitude=40.7128, longitude=-74.006)], + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_tools_google_maps_coordinates_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_google_maps_with_txt.py b/genai/tools/tools_interactions_google_maps_with_txt.py new file mode 100644 index 00000000000..f3f6a4f800c --- /dev/null +++ b/genai/tools/tools_interactions_google_maps_with_txt.py @@ -0,0 +1,35 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_google_maps_with_txt] + from google import genai + from google.genai.interactions import GoogleMaps + + client = genai.Client() + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="Recommend a good restaurant in San Francisco.", + tools=[GoogleMaps()], + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_tools_google_maps_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_google_search_and_urlcontext_with_txt.py b/genai/tools/tools_interactions_google_search_and_urlcontext_with_txt.py new file mode 100644 index 00000000000..5a354651e60 --- /dev/null +++ b/genai/tools/tools_interactions_google_search_and_urlcontext_with_txt.py @@ -0,0 +1,50 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_google_search_and_urlcontext_with_txt] + from google import genai + from google.genai.interactions import GoogleSearch, URLContext + + client = genai.Client() + model_id = "gemini-3.8-flash" + + tools = [ + URLContext(), + GoogleSearch(), + ] + + # TODO(developer): Here put your URLs! + url = "https://www.google.com/search?q=events+in+New+York" + + interaction = client.interactions.create( + model=model_id, + input=f"Give me three day events schedule based on {url}. Also let me know what needs to taken care of considering weather and commute.", + tools=tools, + ) + + print(interaction.output_text) + + # Inspect URL context results from interaction steps + for step in interaction.steps: + if step.type == "url_context_result": + print(step.result) + + # [END googlegenaisdk_interactions_tools_google_search_and_urlcontext_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_google_search_with_txt.py b/genai/tools/tools_interactions_google_search_with_txt.py new file mode 100644 index 00000000000..dfdd7713255 --- /dev/null +++ b/genai/tools/tools_interactions_google_search_with_txt.py @@ -0,0 +1,35 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_google_search_with_txt] + from google import genai + from google.genai.interactions import GoogleSearch + + client = genai.Client() + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="When is the next total solar eclipse in the United States?", + tools=[GoogleSearch()], + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_tools_google_search_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_urlcontext_with_txt.py b/genai/tools/tools_interactions_urlcontext_with_txt.py new file mode 100644 index 00000000000..c186828a56f --- /dev/null +++ b/genai/tools/tools_interactions_urlcontext_with_txt.py @@ -0,0 +1,46 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction() -> str: + # [START googlegenaisdk_interactions_tools_urlcontext_with_txt] + from google import genai + from google.genai.interactions import URLContext + + client = genai.Client() + model_id = "gemini-3.8-flash" + + # TODO(developer): Here put your URLs + url1 = "https://cloud.google.com/vertex-ai/docs/generative-ai/start" + url2 = "https://cloud.google.com/docs/overview" + + interaction = client.interactions.create( + model=model_id, + input=f"Compare the content, purpose, and audiences of {url1} and {url2}.", + tools=[URLContext()], + ) + + print(interaction.output_text) + + # Inspect URL context metadata from interaction steps + for step in interaction.steps: + if step.type == "url_context_result": + print(step.result) + + # [END googlegenaisdk_interactions_tools_urlcontext_with_txt] + return interaction.output_text + + +if __name__ == "__main__": + create_interaction() diff --git a/genai/tools/tools_interactions_vais_with_txt.py b/genai/tools/tools_interactions_vais_with_txt.py new file mode 100644 index 00000000000..ab89ffe828b --- /dev/null +++ b/genai/tools/tools_interactions_vais_with_txt.py @@ -0,0 +1,45 @@ +# Copyright 2025 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 +# +# https://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. + + +def create_interaction(datastore: str) -> bool: + # [START googlegenaisdk_interactions_tools_vais_with_txt] + from google import genai + from google.genai.interactions import Retrieval, VertexAISearchConfig + + client = genai.Client() + + # Load Data Store ID from Vertex AI Search + # datastore = "projects/111111111111/locations/global/collections/default_collection/dataStores/data-store-id" + + interaction = client.interactions.create( + model="gemini-3.8-flash", + input="How do I make an appointment to renew my driver's license?", + tools=[ + Retrieval( + vertex_ai_search_config=VertexAISearchConfig( + datastores=[datastore], + ) + ) + ], + ) + + print(interaction.output_text) + # [END googlegenaisdk_interactions_tools_vais_with_txt] + return True + + +if __name__ == "__main__": + datastore = input("Data Store ID: ") + create_interaction(datastore)