Skip to content

Commit 8678ca6

Browse files
Thoughtseize1riathakkar
authored andcommitted
refactor: (GenAI) Reorganized Function calling Samples (Group A) (GoogleCloudPlatform#12591)
* New files for Function Calling folder * Marks old files to be deleted * Renamed tests * Fix comments * Update comments * Rewrite tests * Changed comments -> JSON schema format
1 parent 571d6e2 commit 8678ca6

14 files changed

+680
-0
lines changed

generative_ai/chat_completions/chat_completions_function_calling_basic.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
# TODO: Delete this file after approval generative_ai/function_calling/chat_function_calling_basic.py
1415

1516

1617
def generate_text(project_id: str, location: str = "us-central1") -> object:

generative_ai/chat_completions/chat_completions_function_calling_config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
# TODO: Delete this file after approval generative_ai/function_calling/chat_function_calling_config.py
1415

1516

1617
def generate_text(project_id: str, location: str = "us-central1") -> object:

generative_ai/chat_completions/chat_completions_test.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,15 @@ def test_non_streaming_image() -> None:
4747
assert response
4848

4949

50+
# TODO: Delete this test after approval /function_calling/chat_function_calling_test.py::test_function_calling_basic
5051
def test_function_calling_basic() -> None:
5152
response = chat_completions_function_calling_basic.generate_text(
5253
PROJECT_ID, LOCATION
5354
)
5455
assert response
5556

5657

58+
# TODO: Delete this test after approval /function_calling/chat_function_calling_test.py::test_function_calling_config
5759
def test_function_calling_config() -> None:
5860
response = chat_completions_function_calling_config.generate_text(
5961
PROJECT_ID, LOCATION

generative_ai/function_calling.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14+
# TODO: Delete this file after approval function_calling/basic_example.py AND function_calling/advanced_example.py
15+
1416
import os
1517

1618
from vertexai.generative_models import GenerationResponse
@@ -178,3 +180,7 @@ def generate_function_call_advanced() -> GenerationResponse:
178180
print(response.candidates[0].function_calls)
179181
# [END generativeaionvertexai_gemini_function_calling_advanced]
180182
return response
183+
184+
185+
if __name__ == "__main__":
186+
generate_function_call_advanced()
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Copyright 2024 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+
from vertexai.generative_models import GenerationResponse
18+
19+
PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
20+
21+
22+
def generate_function_call_advanced() -> GenerationResponse:
23+
# [START generativeaionvertexai_gemini_function_calling_advanced]
24+
import vertexai
25+
from vertexai.preview.generative_models import (
26+
FunctionDeclaration,
27+
GenerativeModel,
28+
Tool,
29+
ToolConfig,
30+
)
31+
32+
# TODO(developer): Update & uncomment below line
33+
# PROJECT_ID = "your-project-id"
34+
35+
# Initialize Vertex AI
36+
vertexai.init(project=PROJECT_ID, location="us-central1")
37+
38+
# Specify a function declaration and parameters for an API request
39+
get_product_sku_func = FunctionDeclaration(
40+
name="get_product_sku",
41+
description="Get the available inventory for a Google products, e.g: Pixel phones, Pixel Watches, Google Home etc",
42+
# Function parameters are specified in JSON schema format
43+
parameters={
44+
"type": "object",
45+
"properties": {
46+
"product_name": {"type": "string", "description": "Product name"}
47+
},
48+
},
49+
)
50+
51+
# Specify another function declaration and parameters for an API request
52+
get_store_location_func = FunctionDeclaration(
53+
name="get_store_location",
54+
description="Get the location of the closest store",
55+
# Function parameters are specified in JSON schema format
56+
parameters={
57+
"type": "object",
58+
"properties": {"location": {"type": "string", "description": "Location"}},
59+
},
60+
)
61+
62+
# Define a tool that includes the above functions
63+
retail_tool = Tool(
64+
function_declarations=[
65+
get_product_sku_func,
66+
get_store_location_func,
67+
],
68+
)
69+
70+
# Define a tool config for the above functions
71+
retail_tool_config = ToolConfig(
72+
function_calling_config=ToolConfig.FunctionCallingConfig(
73+
# ANY mode forces the model to predict a function call
74+
mode=ToolConfig.FunctionCallingConfig.Mode.ANY,
75+
# List of functions that can be returned when the mode is ANY.
76+
# If the list is empty, any declared function can be returned.
77+
allowed_function_names=["get_product_sku"],
78+
)
79+
)
80+
81+
model = GenerativeModel(
82+
model_name="gemini-1.5-flash-001",
83+
tools=[retail_tool],
84+
tool_config=retail_tool_config,
85+
)
86+
response = model.generate_content(
87+
"Do you have the Pixel 8 Pro 128GB in stock?",
88+
)
89+
90+
print(response.candidates[0].function_calls)
91+
# Example response:
92+
# [
93+
# name: "get_product_sku"
94+
# args {
95+
# fields { key: "product_name" value { string_value: "Pixel 8 Pro 128GB" }}
96+
# }
97+
# ]
98+
99+
# [END generativeaionvertexai_gemini_function_calling_advanced]
100+
return response
101+
102+
103+
if __name__ == "__main__":
104+
generate_function_call_advanced()
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# Copyright 2024 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+
from vertexai.generative_models import GenerationResponse
18+
19+
PROJECT_ID = os.getenv("GOOGLE_CLOUD_PROJECT")
20+
21+
22+
def generate_function_call() -> GenerationResponse:
23+
# [START generativeaionvertexai_gemini_function_calling]
24+
import vertexai
25+
from vertexai.generative_models import (
26+
Content,
27+
FunctionDeclaration,
28+
GenerationConfig,
29+
GenerativeModel,
30+
Part,
31+
Tool,
32+
)
33+
34+
# TODO(developer): Update & uncomment below line
35+
# PROJECT_ID = "your-project-id"
36+
37+
# Initialize Vertex AI
38+
vertexai.init(project=PROJECT_ID, location="us-central1")
39+
40+
# Initialize Gemini model
41+
model = GenerativeModel("gemini-1.5-flash-001")
42+
43+
# Define the user's prompt in a Content object that we can reuse in model calls
44+
user_prompt_content = Content(
45+
role="user",
46+
parts=[
47+
Part.from_text("What is the weather like in Boston?"),
48+
],
49+
)
50+
51+
# Specify a function declaration and parameters for an API request
52+
function_name = "get_current_weather"
53+
get_current_weather_func = FunctionDeclaration(
54+
name=function_name,
55+
description="Get the current weather in a given location",
56+
# Function parameters are specified in JSON schema format
57+
parameters={
58+
"type": "object",
59+
"properties": {"location": {"type": "string", "description": "Location"}},
60+
},
61+
)
62+
63+
# Define a tool that includes the above get_current_weather_func
64+
weather_tool = Tool(
65+
function_declarations=[get_current_weather_func],
66+
)
67+
68+
# Send the prompt and instruct the model to generate content using the Tool that you just created
69+
response = model.generate_content(
70+
user_prompt_content,
71+
generation_config=GenerationConfig(temperature=0),
72+
tools=[weather_tool],
73+
)
74+
function_call = response.candidates[0].function_calls[0]
75+
print(function_call)
76+
77+
# Check the function name that the model responded with, and make an API call to an external system
78+
if function_call.name == function_name:
79+
# Extract the arguments to use in your API call
80+
location = function_call.args["location"] # noqa: F841
81+
82+
# Here you can use your preferred method to make an API request to fetch the current weather, for example:
83+
# api_response = requests.post(weather_api_url, data={"location": location})
84+
85+
# In this example, we'll use synthetic data to simulate a response payload from an external API
86+
api_response = """{ "location": "Boston, MA", "temperature": 38, "description": "Partly Cloudy",
87+
"icon": "partly-cloudy", "humidity": 65, "wind": { "speed": 10, "direction": "NW" } }"""
88+
89+
# Return the API response to Gemini so it can generate a model response or request another function call
90+
response = model.generate_content(
91+
[
92+
user_prompt_content, # User prompt
93+
response.candidates[0].content, # Function call response
94+
Content(
95+
parts=[
96+
Part.from_function_response(
97+
name=function_name,
98+
response={
99+
"content": api_response, # Return the API response to Gemini
100+
},
101+
),
102+
],
103+
),
104+
],
105+
tools=[weather_tool],
106+
)
107+
108+
# Get the model response
109+
print(response.text)
110+
# Example response:
111+
# The weather in Boston is partly cloudy with a temperature of 38 degrees Fahrenheit.
112+
# The humidity is 65% and the wind is blowing from the northwest at 10 mph.
113+
114+
# [END generativeaionvertexai_gemini_function_calling]
115+
return response
116+
117+
118+
if __name__ == "__main__":
119+
generate_function_call()

0 commit comments

Comments
 (0)