Skip to content

Commit f18def1

Browse files
authored
Merge pull request google-gemini#45 from kinarr/go-function-calling-samples
Add Go samples for function calling
2 parents 076dcc4 + 8ed3240 commit f18def1

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

go/function_calling.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package examples
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"log"
8+
"os"
9+
10+
"google.golang.org/genai"
11+
)
12+
13+
// Arithmetic functions.
14+
func add(a, b float64) float64 {
15+
return a + b
16+
}
17+
18+
func subtract(a, b float64) float64 {
19+
return a - b
20+
}
21+
22+
func multiply(a, b float64) float64 {
23+
return a * b
24+
}
25+
26+
func divide(a, b float64) float64 {
27+
return a / b
28+
}
29+
30+
// ArithmeticArgs represents the expected arguments for our arithmetic operations.
31+
type ArithmeticArgs struct {
32+
FirstParam float64 `json:"firstParam"`
33+
SecondParam float64 `json:"secondParam"`
34+
}
35+
36+
// createArithmeticToolDeclaration creates a function declaration with the given name and description.
37+
// The parameters schema includes "firstParam" and "secondParam" as required numbers.
38+
func createArithmeticToolDeclaration(name, description string) *genai.FunctionDeclaration {
39+
paramSchema := &genai.Schema{
40+
Type: genai.TypeObject,
41+
Description: "The result of the arithmetic operation.",
42+
Properties: map[string]*genai.Schema{
43+
"firstParam": {
44+
Type: genai.TypeNumber,
45+
Description: "The first parameter which can be an integer or a floating point number.",
46+
},
47+
"secondParam": {
48+
Type: genai.TypeNumber,
49+
Description: "The second parameter which can be an integer or a floating point number.",
50+
},
51+
},
52+
Required: []string{"firstParam", "secondParam"},
53+
}
54+
return &genai.FunctionDeclaration{
55+
Name: name,
56+
Description: description,
57+
Parameters: paramSchema,
58+
}
59+
}
60+
61+
func FunctionCalling() error {
62+
// [START function_calling]
63+
ctx := context.Background()
64+
client, err := genai.NewClient(ctx, &genai.ClientConfig{
65+
APIKey: os.Getenv("GEMINI_API_KEY"),
66+
Backend: genai.BackendGeminiAPI,
67+
})
68+
if err != nil {
69+
log.Fatal(err)
70+
}
71+
modelName := "gemini-2.0-flash"
72+
73+
// Create the function declarations for arithmetic operations.
74+
addDeclaration := createArithmeticToolDeclaration("addNumbers", "Return the result of adding two numbers.")
75+
subtractDeclaration := createArithmeticToolDeclaration("subtractNumbers", "Return the result of subtracting the second number from the first.")
76+
multiplyDeclaration := createArithmeticToolDeclaration("multiplyNumbers", "Return the product of two numbers.")
77+
divideDeclaration := createArithmeticToolDeclaration("divideNumbers", "Return the quotient of dividing the first number by the second.")
78+
79+
// Group the function declarations as a tool.
80+
tools := []*genai.Tool{
81+
{
82+
FunctionDeclarations: []*genai.FunctionDeclaration{
83+
addDeclaration,
84+
subtractDeclaration,
85+
multiplyDeclaration,
86+
divideDeclaration,
87+
},
88+
},
89+
}
90+
91+
// Create the content prompt.
92+
contents := []*genai.Content{
93+
genai.NewUserContentFromText("I have 57 cats, each owns 44 mittens, how many mittens is that in total?"),
94+
}
95+
96+
// Set up the generate content configuration with function calling enabled.
97+
config := &genai.GenerateContentConfig{
98+
Tools: tools,
99+
ToolConfig: &genai.ToolConfig{
100+
FunctionCallingConfig: &genai.FunctionCallingConfig{
101+
// The mode equivalent to FunctionCallingConfigMode.ANY in JS.
102+
Mode: genai.FunctionCallingConfigModeAny,
103+
},
104+
},
105+
}
106+
107+
genContentResp, err := client.Models.GenerateContent(ctx, modelName, contents, config)
108+
if err != nil {
109+
log.Fatal(err)
110+
}
111+
112+
// Assume the response includes a list of function calls.
113+
if len(genContentResp.FunctionCalls()) == 0 {
114+
log.Println("No function call returned from the AI.")
115+
return nil
116+
}
117+
functionCall := genContentResp.FunctionCalls()[0]
118+
log.Printf("Function call: %+v\n", functionCall)
119+
120+
// Marshal the Args map into JSON bytes.
121+
argsMap, err := json.Marshal(functionCall.Args)
122+
if err != nil {
123+
log.Fatal(err)
124+
}
125+
126+
// Unmarshal the JSON bytes into the ArithmeticArgs struct.
127+
var args ArithmeticArgs
128+
if err := json.Unmarshal(argsMap, &args); err != nil {
129+
log.Fatal(err)
130+
}
131+
132+
// Map the function name to the actual arithmetic function.
133+
var result float64
134+
switch functionCall.Name {
135+
case "addNumbers":
136+
result = add(args.FirstParam, args.SecondParam)
137+
case "subtractNumbers":
138+
result = subtract(args.FirstParam, args.SecondParam)
139+
case "multiplyNumbers":
140+
result = multiply(args.FirstParam, args.SecondParam)
141+
case "divideNumbers":
142+
result = divide(args.FirstParam, args.SecondParam)
143+
default:
144+
return fmt.Errorf("unimplemented function: %s", functionCall.Name)
145+
}
146+
log.Printf("Function result: %v\n", result)
147+
148+
// Prepare the final result message as content.
149+
resultContents := []*genai.Content{
150+
genai.NewUserContentFromText("The final result is " + fmt.Sprintf("%v", result)),
151+
}
152+
153+
// Use GenerateContent to send the final result.
154+
finalResponse, err := client.Models.GenerateContent(ctx, modelName, resultContents, &genai.GenerateContentConfig{})
155+
if err != nil {
156+
log.Fatal(err)
157+
}
158+
159+
printResponse(finalResponse)
160+
// [END function_calling]
161+
return err
162+
}

go/function_calling_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package examples
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestFunctionCalling(t *testing.T) {
8+
err := FunctionCalling()
9+
if err != nil {
10+
t.Errorf("FunctionCalling returned an error.")
11+
}
12+
}

0 commit comments

Comments
 (0)