Skip to content

Commit ca3ac72

Browse files
committed
feat: add support for google search and browsing tools
1 parent 7ba6130 commit ca3ac72

File tree

4 files changed

+69
-8
lines changed

4 files changed

+69
-8
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,16 @@ An example of basic configuration:
9696
"threshold": "LOW"
9797
}
9898
],
99+
"tools": [
100+
{
101+
"name": "GOOGLE_SEARCH",
102+
"enabled": true
103+
},
104+
{
105+
"name": "URL_CONTEXT",
106+
"enabled": true
107+
}
108+
],
99109
"history": {
100110
}
101111
}

cmd/gemini/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func run() int {
4848
}
4949

5050
chatSession, err := gemini.NewChatSession(context.Background(), opts.GenerativeModel,
51-
configuration.Data.GenaiSafetySettings())
51+
configuration.Data.GenaiContentConfig())
5252
if err != nil {
5353
return err
5454
}

gemini/chat_session.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ type ChatSession struct {
2626
}
2727

2828
// NewChatSession returns a new [ChatSession].
29-
func NewChatSession(ctx context.Context, model string, safetySettings []*genai.SafetySetting) (*ChatSession, error) {
29+
func NewChatSession(ctx context.Context, model string,
30+
contentConfig *genai.GenerateContentConfig) (*ChatSession, error) {
3031
client, err := genai.NewClient(ctx, nil)
3132
if err != nil {
3233
return nil, fmt.Errorf("failed to create client: %w", err)
3334
}
3435

35-
config := &genai.GenerateContentConfig{SafetySettings: safetySettings}
36-
chat, err := client.Chats.Create(ctx, model, config, nil)
36+
chat, err := client.Chats.Create(ctx, model, contentConfig, nil)
3737
if err != nil {
3838
return nil, fmt.Errorf("failed to create chat: %w", err)
3939
}
@@ -42,7 +42,7 @@ func NewChatSession(ctx context.Context, model string, safetySettings []*genai.S
4242
ctx: ctx,
4343
client: client,
4444
chat: chat,
45-
config: config,
45+
config: contentConfig,
4646
model: model,
4747
}, nil
4848
}

internal/config/application_data.go

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ const (
1212
thresholdOff = "OFF"
1313
)
1414

15+
const (
16+
toolGoogleSearch = "GOOGLE_SEARCH"
17+
toolURLContext = "URL_CONTEXT"
18+
)
19+
1520
// Threshold is a custom type that wraps genai.HarmBlockThreshold
1621
// and uses the custom string for serialization.
1722
type Threshold string
@@ -32,32 +37,45 @@ func (t Threshold) toGenai() genai.HarmBlockThreshold {
3237
}
3338

3439
// SafetySetting is a custom type that wraps genai.SafetySetting
35-
// and uses the custom HarmBlockThreshold for serialization.
40+
// and uses the custom Threshold for serialization.
3641
type SafetySetting struct {
3742
Category genai.HarmCategory `json:"category"`
3843
Threshold Threshold `json:"threshold"`
3944
}
4045

46+
// Tool represents a model tool configuration.
47+
type Tool struct {
48+
Name string `json:"name"`
49+
Enabled bool `json:"enabled"`
50+
}
51+
4152
// ApplicationData encapsulates application state and configuration.
4253
// Note that the chat history is stored in plain text format.
4354
type ApplicationData struct {
4455
SystemPrompts map[string]gemini.SystemInstruction `json:"system_prompts"`
45-
SafetySettings []*SafetySetting `json:"safety_settings"`
56+
SafetySettings []SafetySetting `json:"safety_settings"`
57+
Tools []Tool `json:"tools"`
4658
History map[string][]*gemini.SerializableContent `json:"history"`
4759
}
4860

4961
// newDefaultApplicationData returns a new ApplicationData with default values.
5062
func newDefaultApplicationData() *ApplicationData {
51-
defaultSafetySettings := []*SafetySetting{
63+
defaultSafetySettings := []SafetySetting{
5264
{Category: genai.HarmCategoryHarassment, Threshold: thresholdLow},
5365
{Category: genai.HarmCategoryHateSpeech, Threshold: thresholdLow},
5466
{Category: genai.HarmCategorySexuallyExplicit, Threshold: thresholdLow},
5567
{Category: genai.HarmCategoryDangerousContent, Threshold: thresholdLow},
5668
}
5769

70+
defaultTools := []Tool{
71+
{Name: toolGoogleSearch, Enabled: true},
72+
{Name: toolURLContext, Enabled: true},
73+
}
74+
5875
return &ApplicationData{
5976
SystemPrompts: make(map[string]gemini.SystemInstruction),
6077
SafetySettings: defaultSafetySettings,
78+
Tools: defaultTools,
6179
History: make(map[string][]*gemini.SerializableContent),
6280
}
6381
}
@@ -84,3 +102,36 @@ func (d *ApplicationData) GenaiSafetySettings() []*genai.SafetySetting {
84102

85103
return genaiSafetySettings
86104
}
105+
106+
// GenaiTools builds a genai Tool slice using enabled entries.
107+
func (d *ApplicationData) GenaiTools() []*genai.Tool {
108+
tools := make([]*genai.Tool, 0, len(d.Tools))
109+
for _, tool := range d.Tools {
110+
if !tool.Enabled {
111+
continue
112+
}
113+
114+
var genaiTool *genai.Tool
115+
switch tool.Name {
116+
case toolGoogleSearch:
117+
genaiTool = &genai.Tool{GoogleSearch: &genai.GoogleSearch{}}
118+
case toolURLContext:
119+
genaiTool = &genai.Tool{URLContext: &genai.URLContext{}}
120+
default:
121+
continue // Skip unknown tools
122+
}
123+
124+
tools = append(tools, genaiTool)
125+
}
126+
127+
return tools
128+
}
129+
130+
// GenaiContentConfig builds a genai GenerateContentConfig with the current
131+
// safety settings and enabled tools.
132+
func (d *ApplicationData) GenaiContentConfig() *genai.GenerateContentConfig {
133+
return &genai.GenerateContentConfig{
134+
SafetySettings: d.GenaiSafetySettings(),
135+
Tools: d.GenaiTools(),
136+
}
137+
}

0 commit comments

Comments
 (0)