-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(vertexai): add code sample for parallel function calling
- Loading branch information
1 parent
a70eda1
commit b2181fb
Showing
2 changed files
with
168 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// Copyright 2024 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
// Function calling allows to improve the model response with the use of external | ||
// APIs and functions. | ||
package functioncalling | ||
|
||
// [START generativeaionvertexai_function_calling_generate_parallel_calls] | ||
import ( | ||
"context" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
"io" | ||
|
||
"cloud.google.com/go/vertexai/genai" | ||
) | ||
|
||
// parallelFunctionCalling demonstrates the concept of parallel function calling, when the model | ||
// determines that it requires two or more function calls in order to complete its response. | ||
func parallelFunctionCalling(w io.Writer, projectID, location, modelName string) error { | ||
// location = "us-central1" | ||
// modelName = "gemini-1.5-flash-002" | ||
ctx := context.Background() | ||
client, err := genai.NewClient(ctx, projectID, location) | ||
if err != nil { | ||
return fmt.Errorf("failed to create GenAI client: %w", err) | ||
} | ||
defer client.Close() | ||
|
||
model := client.GenerativeModel(modelName) | ||
// Set temperature to 0.0 for maximum determinism in function calling. | ||
model.SetTemperature(0.0) | ||
|
||
funcName := "getCurrentWeather" | ||
funcDecl := &genai.FunctionDeclaration{ | ||
Name: funcName, | ||
Description: "Get the current weather in a given location", | ||
Parameters: &genai.Schema{ | ||
Type: genai.TypeObject, | ||
Properties: map[string]*genai.Schema{ | ||
"location": { | ||
Type: genai.TypeString, | ||
Description: "The location for which to get the weather. " + | ||
"It can be a city name, a city name and state, or a zip code. " + | ||
"Examples: 'San Francisco', 'San Francisco, CA', '95616', etc.", | ||
}, | ||
}, | ||
Required: []string{"location"}, | ||
}, | ||
} | ||
// Add the weather function to our model toolbox. | ||
model.Tools = []*genai.Tool{ | ||
{ | ||
FunctionDeclarations: []*genai.FunctionDeclaration{funcDecl}, | ||
}, | ||
} | ||
|
||
prompt := genai.Text("Get weather details in New Delhi and San Francisco?") | ||
resp, err := model.GenerateContent(ctx, prompt) | ||
|
||
if err != nil { | ||
return fmt.Errorf("failed to generate content: %w", err) | ||
} | ||
if len(resp.Candidates) == 0 { | ||
return errors.New("got empty response from model") | ||
} else if len(resp.Candidates[0].FunctionCalls()) == 0 { | ||
return errors.New("got no function call suggestions from model") | ||
} | ||
|
||
for _, fnCall := range resp.Candidates[0].FunctionCalls() { | ||
fmt.Fprintf(w, "The model suggests to call the function %q with args: %v\n", fnCall.Name, fnCall.Args) | ||
// Example response: | ||
// The model suggests to call the function "getCurrentWeather" with args: map[location:New Delhi] | ||
// The model suggests to call the function "getCurrentWeather" with args: map[location:San Francisco] | ||
} | ||
|
||
// Use synthetic data to simulate a response from the external API. | ||
// In a real application, this would come from an actual weather API. | ||
mockAPIResp_1, err := json.Marshal(map[string]string{ | ||
"location": "New Delhi", | ||
"temperature": "42", | ||
"temperature_unit": "C", | ||
"description": "Warm and humid", | ||
"humidity": "65", | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed to marshal function response to JSON: %w", err) | ||
} | ||
// 2 | ||
mockAPIResp_2, err := json.Marshal(map[string]string{ | ||
"location": "San Francisco", | ||
"temperature": "36", | ||
"temperature_unit": "F", | ||
"description": "Cold and cloudy", | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("failed to marshal function response to JSON: %w", err) | ||
} | ||
|
||
funcResp_1 := &genai.FunctionResponse{ | ||
Name: funcName, | ||
Response: map[string]any{ | ||
"content": mockAPIResp_1, | ||
}, | ||
} | ||
funcResp_2 := &genai.FunctionResponse{ | ||
Name: funcName, | ||
Response: map[string]any{ | ||
"content": mockAPIResp_2, | ||
}, | ||
} | ||
|
||
// Return both API responses to the model allowing it to complete its response. | ||
resp, err = model.GenerateContent(ctx, prompt, funcResp_1, funcResp_2) | ||
if err != nil { | ||
return fmt.Errorf("failed to generate content: %w", err) | ||
} | ||
if len(resp.Candidates) == 0 || len(resp.Candidates[0].Content.Parts) == 0 { | ||
return errors.New("got empty response from model") | ||
} | ||
|
||
fmt.Fprintln(w, resp.Candidates[0].Content.Parts[0]) | ||
// Example response: | ||
// The weather in New Delhi is warm and humid with a humidity of 65 and a temperature of 42°C. The weather in San Francisco ... | ||
|
||
return nil | ||
} | ||
|
||
// [END generativeaionvertexai_function_calling_generate_parallel_calls] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters