+
Skip to content

feat(genai): Add generate content with routing option #5327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 30, 2025
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"encoding/json"
"fmt"
"io"
"time"

genai "google.golang.org/genai"
)
Expand Down Expand Up @@ -65,7 +66,7 @@ func createContentCache(w io.Writer) (string, error) {
},
},
DisplayName: "example-cache",
TTL: "86400s",
TTL: time.Duration(time.Duration.Seconds(86400)),
}

res, err := client.Caches.Create(ctx, modelName, config)
Expand Down
8 changes: 4 additions & 4 deletions genai/content_cache/contentcache_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,26 @@ func updateContentCache(w io.Writer, cacheName string) error {

// Update expire time using TTL
resp, err := client.Caches.Update(ctx, cacheName, &genai.UpdateCachedContentConfig{
TTL: "36000s",
TTL: time.Duration(time.Duration.Seconds(36000)),
})
if err != nil {
return fmt.Errorf("failed to update content cache exp. time with TTL: %w", err)
}

fmt.Fprintf(w, "Cache expires in: %s\n", time.Until(*resp.ExpireTime))
fmt.Fprintf(w, "Cache expires in: %s\n", time.Until(resp.ExpireTime))
// Example response:
// Cache expires in: 10h0m0.005875s

// Update expire time using specific time stamp
inSevenDays := time.Now().Add(7 * 24 * time.Hour)
resp, err = client.Caches.Update(ctx, cacheName, &genai.UpdateCachedContentConfig{
ExpireTime: &inSevenDays,
ExpireTime: inSevenDays,
})
if err != nil {
return fmt.Errorf("failed to update content cache expire time: %w", err)
}

fmt.Fprintf(w, "Cache expires in: %s\n", time.Until(*resp.ExpireTime))
fmt.Fprintf(w, "Cache expires in: %s\n", time.Until(resp.ExpireTime))
// Example response:
// Cache expires in: 167h59m59.80327s

Expand Down
6 changes: 2 additions & 4 deletions genai/content_cache/contentcache_use_with_txt.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@ func useContentCacheWithTxt(w io.Writer, cacheName string) error {
return fmt.Errorf("failed to use content cache to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
8 changes: 3 additions & 5 deletions genai/controlled_generation/ctrlgen_with_enum_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func generateWithEnumSchema(w io.Writer) error {
contents := []*genai.Content{
{Parts: []*genai.Part{
{Text: "What type of instrument is an oboe?"},
}},
}, Role: "user"},
}
config := &genai.GenerateContentConfig{
ResponseMIMEType: "text/x.enum",
Expand All @@ -54,10 +54,8 @@ func generateWithEnumSchema(w io.Writer) error {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
19 changes: 9 additions & 10 deletions genai/controlled_generation/ctrlgen_with_nullable_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F,
contents := []*genai.Content{
{Parts: []*genai.Part{
{Text: prompt},
}},
},
Role: "user"},
}
config := &genai.GenerateContentConfig{
ResponseMIMEType: "application/json",
Expand All @@ -63,11 +64,11 @@ Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F,
Items: &genai.Schema{
Type: "object",
Properties: map[string]*genai.Schema{
"Day": {Type: "string", Nullable: true},
"Forecast": {Type: "string", Nullable: true},
"Temperature": {Type: "integer", Nullable: true},
"Humidity": {Type: "string", Nullable: true},
"Wind Speed": {Type: "integer", Nullable: true},
"Day": {Type: "string", Nullable: genai.Ptr(true)},
"Forecast": {Type: "string", Nullable: genai.Ptr(true)},
"Temperature": {Type: "integer", Nullable: genai.Ptr(true)},
"Humidity": {Type: "string", Nullable: genai.Ptr(true)},
"Wind Speed": {Type: "integer", Nullable: genai.Ptr(true)},
},
Required: []string{"Day", "Temperature", "Forecast", "Wind Speed"},
},
Expand All @@ -81,10 +82,8 @@ Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F,
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
9 changes: 4 additions & 5 deletions genai/controlled_generation/ctrlgen_with_resp_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ func generateWithRespSchema(w io.Writer) error {
contents := []*genai.Content{
{Parts: []*genai.Part{
{Text: "List a few popular cookie recipes."},
}},
},
Role: "user"},
}
modelName := "gemini-2.0-flash-001"

Expand All @@ -66,10 +67,8 @@ func generateWithRespSchema(w io.Writer) error {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
3 changes: 2 additions & 1 deletion genai/count_tokens/counttoken_compute_with_txt.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func computeWithTxt(w io.Writer) error {
contents := []*genai.Content{
{Parts: []*genai.Part{
{Text: "What's the longest word in the English language?"},
}},
},
Role: "user"},
}

resp, err := client.Models.ComputeTokens(ctx, modelName, contents, nil)
Expand Down
3 changes: 2 additions & 1 deletion genai/count_tokens/counttoken_resp_with_txt.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ func generateTextAndCount(w io.Writer) error {
contents := []*genai.Content{
{Parts: []*genai.Part{
{Text: "Why is the sky blue?"},
}},
},
Role: "user"},
}

resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil)
Expand Down
3 changes: 2 additions & 1 deletion genai/count_tokens/counttoken_with_txt_vid.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ func countWithTxtAndVid(w io.Writer) error {
FileURI: "gs://cloud-samples-data/generative-ai/video/pixel8.mp4",
MIMEType: "video/mp4",
}},
}},
},
Role: "user"},
}

resp, err := client.Models.CountTokens(ctx, modelName, contents, nil)
Expand Down
2 changes: 1 addition & 1 deletion genai/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.23.0

require (
github.com/GoogleCloudPlatform/golang-samples v0.0.0-20250201051611-5fb145d1e974
google.golang.org/genai v0.4.0
google.golang.org/genai v1.6.0
)

require (
Expand Down
4 changes: 2 additions & 2 deletions genai/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
google.golang.org/api v0.217.0 h1:GYrUtD289o4zl1AhiTZL0jvQGa2RDLyC+kX1N/lfGOU=
google.golang.org/api v0.217.0/go.mod h1:qMc2E8cBAbQlRypBTBWHklNJlaZZJBwDv81B1Iu8oSI=
google.golang.org/genai v0.4.0 h1:nHLpFvp1i2nUGQ8CjIQ8j/6d3H79Echt1jiNLb9myDk=
google.golang.org/genai v0.4.0/go.mod h1:yPyKKBezIg2rqZziLhHQ5CD62HWr7sLDLc2PDzdrNVs=
google.golang.org/genai v1.6.0 h1:aG0J3QF/Ad2GsjHvY8LjRp9hiDl4hvLJN98YwkLDqFE=
google.golang.org/genai v1.6.0/go.mod h1:TyfOKRz/QyCaj6f/ZDt505x+YreXnY40l2I6k8TvgqY=
google.golang.org/genproto v0.0.0-20250115164207-1a7da9e5054f h1:387Y+JbxF52bmesc8kq1NyYIp33dnxCw6eiA7JMsTmw=
google.golang.org/genproto v0.0.0-20250115164207-1a7da9e5054f/go.mod h1:0joYwWwLQh18AOj8zMYeZLjzuqcYTU3/nC5JdCvC3JI=
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f h1:gap6+3Gk41EItBuyi4XX/bp4oqJ3UwuIMl25yGinuAA=
Expand Down
14 changes: 14 additions & 0 deletions genai/text_generation/text_generation_examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,4 +172,18 @@ func TestTextGeneration(t *testing.T) {
t.Error("expected non-empty output, got empty")
}
})

t.Run("generate with routing", func(t *testing.T) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

issue: create a separate function for this test. Don't use t.Run() unless you need to.

Copy link
Contributor Author

@nardosalemu nardosalemu Jun 18, 2025

Choose a reason for hiding this comment

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

I was following the pattern with how the functions in text_generation folder were being tested. It seems like all the functions defined in the files under text_generation are all tested using t.Run() in TestTextGeneration function.
Do you still suggest I create a separate function for it? Thanks!

buf.Reset()
err := generateWithRouting(buf)
if err != nil {
t.Fatalf("generateWithRouting failed: %v", err)
}

output := buf.String()
if output == "" {
t.Error("expected non-empty output, got empty")
}
})

}
9 changes: 4 additions & 5 deletions genai/text_generation/textgen_code_with_pdf.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,17 @@ func generateWithPDF(w io.Writer) error {
FileURI: "https://storage.googleapis.com/cloud-samples-data/generative-ai/text/inefficient_fibonacci_series_python_code.pdf",
MIMEType: "application/pdf",
}},
}},
},
Role: "user"},
}

resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil)
if err != nil {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
10 changes: 4 additions & 6 deletions genai/text_generation/textgen_config_with_txt.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ func generateWithConfig(w io.Writer) error {
contents := genai.Text("Why is the sky blue?")
// See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.types.GenerateContentConfig
config := &genai.GenerateContentConfig{
Temperature: genai.Ptr(0.0),
CandidateCount: genai.Ptr(int64(1)),
Temperature: genai.Ptr(float32(0.0)),
CandidateCount: int32(1),
ResponseMIMEType: "application/json",
}

Expand All @@ -49,10 +49,8 @@ func generateWithConfig(w io.Writer) error {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)
// Example response:
// {
Expand Down
6 changes: 2 additions & 4 deletions genai/text_generation/textgen_sys_instr_with_txt.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,8 @@ func generateWithSystem(w io.Writer) error {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
9 changes: 4 additions & 5 deletions genai/text_generation/textgen_transcript_with_gcs_audio.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,17 @@ Use speaker A, speaker B, etc. to identify speakers.`},
FileURI: "gs://cloud-samples-data/generative-ai/audio/pixel.mp3",
MIMEType: "audio/mpeg",
}},
}},
},
Role: "user"},
}

resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil)
if err != nil {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
9 changes: 4 additions & 5 deletions genai/text_generation/textgen_with_gcs_audio.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,17 @@ Create a chapter breakdown with timestamps for key sections or topics discussed.
FileURI: "gs://cloud-samples-data/generative-ai/audio/pixel.mp3",
MIMEType: "audio/mpeg",
}},
}},
},
Role: "user"},
}

resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil)
if err != nil {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
6 changes: 2 additions & 4 deletions genai/text_generation/textgen_with_multi_img.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,8 @@ func generateWithMultiImg(w io.Writer) error {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
9 changes: 4 additions & 5 deletions genai/text_generation/textgen_with_mute_video.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,17 @@ func generateWithMuteVideo(w io.Writer) error {
FileURI: "gs://cloud-samples-data/generative-ai/video/ad_copy_from_video.mp4",
MIMEType: "video/mp4",
}},
}},
},
Role: "user"},
}

resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil)
if err != nil {
return fmt.Errorf("failed to generate content: %w", err)
}

respText, err := resp.Text()
if err != nil {
return fmt.Errorf("failed to convert model response to text: %w", err)
}
respText := resp.Text()

fmt.Fprintln(w, respText)

// Example response:
Expand Down
Loading
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载