func FunctionCalling()

in go/function_calling.go [61:164]


func FunctionCalling() error {
	// [START function_calling]
	ctx := context.Background()
	client, err := genai.NewClient(ctx, &genai.ClientConfig{
		APIKey:  os.Getenv("GEMINI_API_KEY"),
		Backend: genai.BackendGeminiAPI,
	})
	if err != nil {
		log.Fatal(err)
	}
	modelName := "gemini-2.0-flash"

	// Create the function declarations for arithmetic operations.
	addDeclaration := createArithmeticToolDeclaration("addNumbers", "Return the result of adding two numbers.")
	subtractDeclaration := createArithmeticToolDeclaration("subtractNumbers", "Return the result of subtracting the second number from the first.")
	multiplyDeclaration := createArithmeticToolDeclaration("multiplyNumbers", "Return the product of two numbers.")
	divideDeclaration := createArithmeticToolDeclaration("divideNumbers", "Return the quotient of dividing the first number by the second.")

	// Group the function declarations as a tool.
	tools := []*genai.Tool{
		{
			FunctionDeclarations: []*genai.FunctionDeclaration{
				addDeclaration,
				subtractDeclaration,
				multiplyDeclaration,
				divideDeclaration,
			},
		},
	}

	// Create the content prompt.
	contents := []*genai.Content{
		genai.NewContentFromText(
			"I have 57 cats, each owns 44 mittens, how many mittens is that in total?", genai.RoleUser,
		),
	}

	// Set up the generate content configuration with function calling enabled.
	config := &genai.GenerateContentConfig{
		Tools: tools,
		ToolConfig: &genai.ToolConfig{
			FunctionCallingConfig: &genai.FunctionCallingConfig{
				// The mode equivalent to FunctionCallingConfigMode.ANY in JS.
				Mode: genai.FunctionCallingConfigModeAny,
			},
		},
	}

	genContentResp, err := client.Models.GenerateContent(ctx, modelName, contents, config)
	if err != nil {
		log.Fatal(err)
	}

	// Assume the response includes a list of function calls.
	if len(genContentResp.FunctionCalls()) == 0 {
		log.Println("No function call returned from the AI.")
		return nil
	}
	functionCall := genContentResp.FunctionCalls()[0]
	log.Printf("Function call: %+v\n", functionCall)

	// Marshal the Args map into JSON bytes.
	argsMap, err := json.Marshal(functionCall.Args)
	if err != nil {
		log.Fatal(err)
	}

	// Unmarshal the JSON bytes into the ArithmeticArgs struct.
	var args ArithmeticArgs
	if err := json.Unmarshal(argsMap, &args); err != nil {
		log.Fatal(err)
	}

	// Map the function name to the actual arithmetic function.
	var result float64
	switch functionCall.Name {
		case "addNumbers":
			result = add(args.FirstParam, args.SecondParam)
		case "subtractNumbers":
			result = subtract(args.FirstParam, args.SecondParam)
		case "multiplyNumbers":
			result = multiply(args.FirstParam, args.SecondParam)
		case "divideNumbers":
			result = divide(args.FirstParam, args.SecondParam)
		default:
			return fmt.Errorf("unimplemented function: %s", functionCall.Name)
	}
	log.Printf("Function result: %v\n", result)

	// Prepare the final result message as content.
	resultContents := []*genai.Content{
		genai.NewContentFromText("The final result is " + fmt.Sprintf("%v", result), genai.RoleUser),
	}

	// Use GenerateContent to send the final result.
	finalResponse, err := client.Models.GenerateContent(ctx, modelName, resultContents, &genai.GenerateContentConfig{})
	if err != nil {
		log.Fatal(err)
	}

	printResponse(finalResponse)
	// [END function_calling]
	return err
}