Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 29 additions & 18 deletions genai/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -297,13 +297,9 @@ func TestLive(t *testing.T) {
})
t.Run("tools", func(t *testing.T) {

weatherChat := func(t *testing.T, s *Schema) {
weatherChat := func(t *testing.T, fd *FunctionDeclaration) {
weatherTool := &Tool{
FunctionDeclarations: []*FunctionDeclaration{{
Name: "CurrentWeather",
Description: "Get the current weather in a given location",
Parameters: s,
}},
FunctionDeclarations: []*FunctionDeclaration{fd},
}
model := client.GenerativeModel(*modelName)
model.SetTemperature(0)
Expand Down Expand Up @@ -341,20 +337,35 @@ func TestLive(t *testing.T) {
}

t.Run("direct", func(t *testing.T) {
weatherChat(t, &Schema{
Type: TypeObject,
Properties: map[string]*Schema{
"location": {
Type: TypeString,
Description: "The city and state, e.g. San Francisco, CA",
},
"unit": {
Type: TypeString,
Enum: []string{"celsius", "fahrenheit"},
fd := &FunctionDeclaration{
Name: "CurrentWeather",
Description: "Get the current weather in a given location",
Parameters: &Schema{
Type: TypeObject,
Properties: map[string]*Schema{
"location": {
Type: TypeString,
Description: "The city and state, e.g. San Francisco, CA",
},
"unit": {
Type: TypeString,
Enum: []string{"celsius", "fahrenheit"},
},
},
Required: []string{"location"},
},
Required: []string{"location"},
})
}
weatherChat(t, fd)
})
t.Run("inferred", func(t *testing.T) {
fds, err := NewCallableFunctionDeclaration(
"CurrentWeather",
"Get the current weather in a given location",
func(string) {}, "location")
if err != nil {
t.Fatal(err)
}
weatherChat(t, fds)
})
})
}
Expand Down
1 change: 0 additions & 1 deletion genai/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,6 @@ types:

# Types for function calling
Tool:
FunctionDeclaration:
FunctionCall:
FunctionResponse:
Schema:
Expand Down
16 changes: 16 additions & 0 deletions genai/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@
// You will need an API key to use the service.
// See the [setup tutorial] for details.
//
// # Tools
//
// Gemini can call functions if you tell it about them.
// Create FunctionDeclarations, add them to a Tool, and install the Tool in a Model.
// When used in a ChatSession, the content returned from a model may include FunctionCall
// parts. Your code performs the requested call and sends back a FunctionResponse.
// See The example for Tool
//
// To have the SDK call a Go function for you, assign it to the FunctionDeclaration.Function.
// field. A ChatSession will look for FunctionCalls, invoke the function you supply, and reply
// with a FunctionResponse. Your code will see only the final result.
//
// The NewCallableFunctionDeclaration function will infer the schema for a function you supply,
// and create a FunctionDeclaration that exposes that function for automatic calling.
// See the example for NewCallableFunctionDeclaration.
//
// # Errors
//
// [examples]: https://pkg.go.dev/github.com/google/generative-ai-go/genai#pkg-examples
Expand Down
36 changes: 36 additions & 0 deletions genai/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,42 @@ func ExampleTool() {
printResponse(res)
}

func ExampleNewCallableFunctionDeclaration() {
// Define a function to use as a tool.
weatherToday := func(city string) string {
return "comfortable, if you have the right clothing"
}
// You can construct the Schema for this function by hand, or
// let Go reflection figure it out.
// This also makes the function automatically callable.
// Reflection can't see parameter names, so provide those too.
fd, err := genai.NewCallableFunctionDeclaration("CurrentWeather", "Get the current weather in a given location", weatherToday, "city")
if err != nil {
// Not every type can be used in a tool function.
panic(err)
}

ctx := context.Background()
client, err := genai.NewClient(ctx, option.WithAPIKey(os.Getenv("GEMINI_API_KEY")))
if err != nil {
log.Fatal(err)
}
defer client.Close()

// Use the FunctionDeclaration to populate Model.Tools.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The example should probably be extended to show this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started to do that. I can finish when I have an implementation.

model := client.GenerativeModel("gemini-1.0-pro")

// Before initiating a conversation, we tell the model which tools it has
// at its disposal.
weatherTool := &genai.Tool{
FunctionDeclarations: []*genai.FunctionDeclaration{fd},
}

model.Tools = []*genai.Tool{weatherTool}

// Now use the model in a ChatSession; see [ExampleTool].
}

func printResponse(resp *genai.GenerateContentResponse) {
for _, cand := range resp.Candidates {
if cand.Content != nil {
Expand Down
79 changes: 0 additions & 79 deletions genai/generativelanguagepb_veneer.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -400,47 +400,6 @@ func (FunctionCall) fromProto(p *pb.FunctionCall) *FunctionCall {
}
}

// FunctionDeclaration is structured representation of a function declaration as defined by the
// [OpenAPI 3.03 specification](https://spec.openapis.org/oas/v3.0.3). Included
// in this declaration are the function name and parameters. This
// FunctionDeclaration is a representation of a block of code that can be used
// as a `Tool` by the model and executed by the client.
type FunctionDeclaration struct {
// Required. The name of the function.
// Must be a-z, A-Z, 0-9, or contain underscores and dashes, with a maximum
// length of 63.
Name string
// Required. A brief description of the function.
Description string
// Optional. Describes the parameters to this function. Reflects the Open
// API 3.03 Parameter Object string Key: the name of the parameter. Parameter
// names are case sensitive. Schema Value: the Schema defining the type used
// for the parameter.
Parameters *Schema
}

func (v *FunctionDeclaration) toProto() *pb.FunctionDeclaration {
if v == nil {
return nil
}
return &pb.FunctionDeclaration{
Name: v.Name,
Description: v.Description,
Parameters: v.Parameters.toProto(),
}
}

func (FunctionDeclaration) fromProto(p *pb.FunctionDeclaration) *FunctionDeclaration {
if p == nil {
return nil
}
return &FunctionDeclaration{
Name: p.Name,
Description: p.Description,
Parameters: (Schema{}).fromProto(p.Parameters),
}
}

// FunctionResponse is the result output from a `FunctionCall` that contains a string
// representing the `FunctionDeclaration.name` and a structured JSON
// object containing any output from the function is used as context to
Expand Down Expand Up @@ -1005,44 +964,6 @@ func (v TaskType) String() string {
return fmt.Sprintf("TaskType(%d)", v)
}

// Tool details that the model may use to generate response.
//
// A `Tool` is a piece of code that enables the system to interact with
// external systems to perform an action, or set of actions, outside of
// knowledge and scope of the model.
type Tool struct {
// Optional. A list of `FunctionDeclarations` available to the model that can
// be used for function calling.
//
// The model or system does not execute the function. Instead the defined
// function may be returned as a [FunctionCall][content.part.function_call]
// with arguments to the client side for execution. The model may decide to
// call a subset of these functions by populating
// [FunctionCall][content.part.function_call] in the response. The next
// conversation turn may contain a
// [FunctionResponse][content.part.function_response]
// with the [content.role] "function" generation context for the next model
// turn.
FunctionDeclarations []*FunctionDeclaration
}

func (v *Tool) toProto() *pb.Tool {
if v == nil {
return nil
}
return &pb.Tool{
FunctionDeclarations: support.TransformSlice(v.FunctionDeclarations, (*FunctionDeclaration).toProto),
}
}

func (Tool) fromProto(p *pb.Tool) *Tool {
if p == nil {
return nil
}
return &Tool{
FunctionDeclarations: support.TransformSlice(p.FunctionDeclarations, (FunctionDeclaration{}).fromProto),
}
}

// Type contains the list of OpenAPI data types as defined by
// https://spec.openapis.org/oas/v3.0.3#data-types
Expand Down
Loading