Skip to content

Commit 6cba173

Browse files
feat(genai): Add Tool examples (#13128)
* feat(genai): Add Tool examples * Code execution example * Function Calling example * Grounding with Google Search example * fix(genai): Linter suggestion * feat(genai): Add region tags * fix(genai): add image file. * fix(genai): Fix for CICD issues - update Pillow pkg * fix(genai): Fix for CICD issues - update Pillow pkg * fix(genai): Fix for CICD issues - update Pillow pkg
1 parent 080725c commit 6cba173

10 files changed

+408
-0
lines changed

genai/tools/noxfile_config.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2021 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Default TEST_CONFIG_OVERRIDE for python repos.
16+
17+
# You can copy this file into your directory, then it will be imported from
18+
# the noxfile.py.
19+
20+
# The source of truth:
21+
# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/noxfile_config.py
22+
23+
TEST_CONFIG_OVERRIDE = {
24+
# You can opt out from the test for specific Python versions.
25+
"ignored_versions": ["2.7", "3.7", "3.8", "3.10", "3.11", "3.12"],
26+
# Old samples are opted out of enforcing Python type hints
27+
# All new samples should feature them
28+
"enforce_type_hints": True,
29+
# An envvar key for determining the project id to use. Change it
30+
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
31+
# build specific Cloud project. You can also use your own string
32+
# to use your own Cloud project.
33+
"gcloud_project_env": "GOOGLE_CLOUD_PROJECT",
34+
# 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT',
35+
# If you need to use a specific version of pip,
36+
# change pip_version_override to the string representation
37+
# of the version number, for example, "20.2.4"
38+
"pip_version_override": None,
39+
# A dictionary you want to inject into your test. Don't put any
40+
# secrets here. These values will override predefined values.
41+
"envs": {},
42+
}

genai/tools/requirements-test.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
backoff==2.2.1
2+
google-api-core==2.19.0
3+
pytest==8.2.0
4+
pytest-asyncio==0.23.6

genai/tools/requirements.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
google-genai==0.8.0
2+
# PIl is required for tools_code_execution_with_txt_img.py
3+
pillow==11.1.0
Loading

genai/tools/test_tools.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
17+
import tools_code_exec_with_txt
18+
import tools_code_exec_with_txt_local_img
19+
import tools_func_def_with_txt
20+
import tools_func_desc_with_txt
21+
import tools_google_search_with_txt
22+
23+
os.environ["GOOGLE_GENAI_USE_VERTEXAI"] = "True"
24+
os.environ["GOOGLE_CLOUD_LOCATION"] = "us-central1"
25+
# The project name is included in the CICD pipeline
26+
# os.environ['GOOGLE_CLOUD_PROJECT'] = "add-your-project-name"
27+
28+
29+
def test_tools_code_exec_with_txt() -> None:
30+
response = tools_code_exec_with_txt.generate_content()
31+
assert response
32+
33+
34+
def test_tools_code_exec_with_txt_local_img() -> None:
35+
response = tools_code_exec_with_txt_local_img.generate_content()
36+
assert response
37+
38+
39+
def test_tools_func_def_with_txt() -> None:
40+
response = tools_func_def_with_txt.generate_content()
41+
assert response
42+
43+
44+
def test_tools_func_desc_with_txt() -> None:
45+
response = tools_func_desc_with_txt.generate_content()
46+
assert response
47+
48+
49+
def test_tools_google_search_with_txt() -> None:
50+
response = tools_google_search_with_txt.generate_content()
51+
assert response
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
def generate_content() -> str:
17+
# [START googlegenaisdk_tools_code_exec_with_txt]
18+
from google import genai
19+
from google.genai.types import Tool, ToolCodeExecution, GenerateContentConfig
20+
21+
client = genai.Client()
22+
model_id = "gemini-2.0-flash-exp"
23+
24+
code_execution_tool = Tool(code_execution=ToolCodeExecution())
25+
response = client.models.generate_content(
26+
model=model_id,
27+
contents="Calculate 20th fibonacci number. Then find the nearest palindrome to it.",
28+
config=GenerateContentConfig(
29+
tools=[code_execution_tool],
30+
temperature=0,
31+
),
32+
)
33+
for part in response.candidates[0].content.parts:
34+
if part.executable_code:
35+
print(part.executable_code)
36+
if part.code_execution_result:
37+
print(part.code_execution_result)
38+
# Example response:
39+
# code='...' language='PYTHON'
40+
# outcome='OUTCOME_OK' output='The 20th Fibonacci number is: 6765\n'
41+
# code='...' language='PYTHON'
42+
# outcome='OUTCOME_OK' output='Lower Palindrome: 6666\nHigher Palindrome: 6776\nNearest Palindrome to 6765: 6776\n'
43+
44+
# [END googlegenaisdk_tools_code_exec_with_txt]
45+
return str(response.candidates[0].content.parts)
46+
47+
48+
if __name__ == "__main__":
49+
generate_content()
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.genai.types import GenerateContentResponse
16+
17+
18+
def generate_content() -> GenerateContentResponse:
19+
# [START googlegenaisdk_tools_code_exec_with_txt_local_img]
20+
from PIL import Image
21+
from google import genai
22+
from google.genai.types import Tool, ToolCodeExecution, GenerateContentConfig
23+
24+
client = genai.Client()
25+
code_execution_tool = Tool(code_execution=ToolCodeExecution())
26+
27+
prompt = """
28+
Run a simulation of the Monty Hall Problem with 1,000 trials.
29+
Here's how this works as a reminder. In the Monty Hall Problem, you're on a game
30+
show with three doors. Behind one is a car, and behind the others are goats. You
31+
pick a door. The host, who knows what's behind the doors, opens a different door
32+
to reveal a goat. Should you switch to the remaining unopened door?
33+
The answer has always been a little difficult for me to understand when people
34+
solve it with math - so please run a simulation with Python to show me what the
35+
best strategy is.
36+
Thank you!
37+
"""
38+
39+
# Image source: https://upload.wikimedia.org/wikipedia/commons/thumb/3/3f/Monty_open_door.svg/640px-Monty_open_door.svg.png
40+
image_data = Image.open(open("test_data/640px-Monty_open_door.svg.png", "rb"))
41+
42+
response = client.models.generate_content(
43+
model="gemini-2.0-flash-exp",
44+
contents=[image_data, prompt],
45+
config=GenerateContentConfig(
46+
tools=[code_execution_tool],
47+
temperature=0,
48+
),
49+
)
50+
51+
print("# Code:")
52+
for part in response.candidates[0].content.parts:
53+
if part.executable_code:
54+
print(part.executable_code)
55+
56+
print("# Outcome:")
57+
for part in response.candidates[0].content.parts:
58+
if part.code_execution_result:
59+
print(part.code_execution_result)
60+
61+
# Example response:
62+
# # Code:
63+
# code='\nimport random\n\ndef monty_hall_simulation(num_trials):\n
64+
# """Simulates the Monty Hall problem and returns the win rates for switching and not switching."""\n\n
65+
# wins_switching = 0\n wins_not_switching = 0\n\n for _ in range(num_trials):\n # 1. Set up the game:\n
66+
# - Randomly place the car behind one of the three doors.\n car_door = random.randint(0, 2)\n
67+
# ...
68+
# # Outcome:
69+
# outcome=<Outcome.OUTCOME_OK: 'OUTCOME_OK'> output='Win percentage when switching: 65.90%\nWin percentage when not switching: 34.10%\n'
70+
# [END googlegenaisdk_tools_code_exec_with_txt_local_img]
71+
return response
72+
73+
74+
if __name__ == "__main__":
75+
generate_content()
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
def generate_content() -> str:
17+
# [START googlegenaisdk_tools_func_def_with_txt]
18+
from google import genai
19+
from google.genai.types import GenerateContentConfig
20+
21+
def get_current_weather(location: str) -> str:
22+
"""Example method. Returns the current weather.
23+
24+
Args:
25+
location: The city and state, e.g. San Francisco, CA
26+
"""
27+
import random
28+
29+
return random.choice(["sunny", "raining", "snowing", "fog"])
30+
31+
client = genai.Client()
32+
model_id = "gemini-2.0-flash-exp"
33+
34+
response = client.models.generate_content(
35+
model=model_id,
36+
contents="What is the weather like in Boston?",
37+
config=GenerateContentConfig(
38+
tools=[get_current_weather],
39+
temperature=0,
40+
),
41+
)
42+
43+
print(response.text)
44+
# Example response:
45+
# The weather in Boston is sunny.
46+
# [END googlegenaisdk_tools_func_def_with_txt]
47+
return response.text
48+
49+
50+
if __name__ == "__main__":
51+
generate_content()
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
def generate_content() -> str:
17+
# [START googlegenaisdk_tools_func_desc_with_txt]
18+
from google import genai
19+
from google.genai.types import FunctionDeclaration, Tool, GenerateContentConfig
20+
21+
client = genai.Client()
22+
model_id = "gemini-2.0-flash-exp"
23+
24+
get_album_sales = FunctionDeclaration(
25+
name="get_album_sales",
26+
description="Gets the number of albums sold",
27+
# Function parameters are specified in JSON schema format
28+
parameters={
29+
"type": "OBJECT",
30+
"properties": {
31+
"albums": {
32+
"type": "ARRAY",
33+
"description": "List of albums",
34+
"items": {
35+
"description": "Album and its sales",
36+
"type": "OBJECT",
37+
"properties": {
38+
"album_name": {
39+
"type": "STRING",
40+
"description": "Name of the music album",
41+
},
42+
"copies_sold": {
43+
"type": "INTEGER",
44+
"description": "Number of copies sold",
45+
},
46+
},
47+
},
48+
},
49+
},
50+
},
51+
)
52+
53+
sales_tool = Tool(
54+
function_declarations=[get_album_sales],
55+
)
56+
57+
response = client.models.generate_content(
58+
model=model_id,
59+
contents='At Stellar Sounds, a music label, 2024 was a rollercoaster. "Echoes of the Night," a debut synth-pop album, '
60+
'surprisingly sold 350,000 copies, while veteran rock band "Crimson Tide\'s" latest, "Reckless Hearts," '
61+
'lagged at 120,000. Their up-and-coming indie artist, "Luna Bloom\'s" EP, "Whispers of Dawn," '
62+
'secured 75,000 sales. The biggest disappointment was the highly-anticipated rap album "Street Symphony" '
63+
"only reaching 100,000 units. Overall, Stellar Sounds moved over 645,000 units this year, revealing unexpected "
64+
"trends in music consumption.",
65+
config=GenerateContentConfig(
66+
tools=[sales_tool],
67+
temperature=0,
68+
),
69+
)
70+
71+
print(response.candidates[0].content.parts[0].function_call)
72+
# Example response:
73+
# [FunctionCall(
74+
# id=None,
75+
# name="get_album_sales",
76+
# args={
77+
# "albums": [
78+
# {"album_name": "Echoes of the Night", "copies_sold": 350000},
79+
# {"copies_sold": 120000, "album_name": "Reckless Hearts"},
80+
# {"copies_sold": 75000, "album_name": "Whispers of Dawn"},
81+
# {"copies_sold": 100000, "album_name": "Street Symphony"},
82+
# ]
83+
# },
84+
# )]
85+
86+
# [END googlegenaisdk_tools_func_desc_with_txt]
87+
return str(response.candidates[0].content.parts[0].function_call)
88+
89+
90+
if __name__ == "__main__":
91+
generate_content()

0 commit comments

Comments
 (0)