From 5bcd48dcea10b6599e112041e71f208acb2482a3 Mon Sep 17 00:00:00 2001 From: cfloress Date: Wed, 3 Sep 2025 13:03:41 -0400 Subject: [PATCH 1/6] genai: added vais, video gen samples --- genai/tools/tools_examples_test.go | 15 ++++ genai/tools/tools_vais_search_with_txt.go | 67 ++++++++++++++++ genai/video_generation/video_gen_with_img.go | 77 +++++++++++++++++++ genai/video_generation/video_gen_with_txt.go | 72 +++++++++++++++++ .../video_generation_examples_test.go | 64 +++++++++++++++ 5 files changed, 295 insertions(+) create mode 100644 genai/tools/tools_vais_search_with_txt.go create mode 100644 genai/video_generation/video_gen_with_img.go create mode 100644 genai/video_generation/video_gen_with_txt.go create mode 100644 genai/video_generation/video_generation_examples_test.go diff --git a/genai/tools/tools_examples_test.go b/genai/tools/tools_examples_test.go index 867e868ae1..eff5262c5c 100644 --- a/genai/tools/tools_examples_test.go +++ b/genai/tools/tools_examples_test.go @@ -16,6 +16,7 @@ package tools import ( "bytes" + "fmt" "testing" "github.com/GoogleCloudPlatform/golang-samples/internal/testutil" @@ -68,4 +69,18 @@ func TestTextGeneration(t *testing.T) { t.Error("expected non-empty output, got empty") } }) + + t.Run("generate with VAIS Search", func(t *testing.T) { + buf.Reset() + dataStore := fmt.Sprintf("projects/%s/locations/global/collections/default_collection/dataStores/grounding-test-datastore", tc.ProjectID) + err := generateWithGoogleVAIS(buf, dataStore) + if err != nil { + t.Fatalf("generateWithGoogleVAIS failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) } diff --git a/genai/tools/tools_vais_search_with_txt.go b/genai/tools/tools_vais_search_with_txt.go new file mode 100644 index 0000000000..d4ac2b1149 --- /dev/null +++ b/genai/tools/tools_vais_search_with_txt.go @@ -0,0 +1,67 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package tools shows examples of various tools that Gemini model can use to generate text. +package tools + +// [START googlegenaisdk_tools_vais_with_txt] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateWithGoogleVAIS shows how to generate text using VAIS Search. +func generateWithGoogleVAIS(w io.Writer, datastore string) error { + ctx := context.Background() + + client, err := genai.NewClient(ctx, &genai.ClientConfig{ + HTTPOptions: genai.HTTPOptions{APIVersion: "v1"}, + }) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + modelName := "gemini-2.5-flash" + contents := genai.Text("How do I make an appointment to renew my driver's license?") + config := &genai.GenerateContentConfig{ + Tools: []*genai.Tool{ + { + Retrieval: &genai.Retrieval{ + VertexAISearch: &genai.VertexAISearch{ + Datastore: datastore, + }, + }, + }, + }, + } + + resp, err := client.Models.GenerateContent(ctx, modelName, contents, config) + if err != nil { + return fmt.Errorf("failed to generate content: %w", err) + } + + respText := resp.Text() + + fmt.Fprintln(w, respText) + + // Example response: + // 'The process for making an appointment to renew your driver's license varies depending on your location. To provide you with the most accurate instructions...' + + return nil +} + +// [END googlegenaisdk_tools_vais_with_txt] diff --git a/genai/video_generation/video_gen_with_img.go b/genai/video_generation/video_gen_with_img.go new file mode 100644 index 0000000000..af68c700c9 --- /dev/null +++ b/genai/video_generation/video_gen_with_img.go @@ -0,0 +1,77 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package video_generation shows how to use the GenAI SDK to generate video. +package video_generation + +// [START googlegenaisdk_videogen_with_img] +import ( + "context" + "fmt" + "io" + "time" + + "google.golang.org/genai" +) + +// generateVideoFromImage shows how to gen video from img. +func generateVideoFromImage(w io.Writer, outputGCSURI string) error { + ctx := context.Background() + + client, err := genai.NewClient(ctx, &genai.ClientConfig{ + HTTPOptions: genai.HTTPOptions{APIVersion: "v1"}, + }) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + image := &genai.Image{ + GCSURI: "gs://cloud-samples-data/generative-ai/image/flowers.png", + MIMEType: "image/png", + } + + config := &genai.GenerateVideosConfig{ + AspectRatio: "16:9", + OutputGCSURI: outputGCSURI, + } + + modelName := "veo-3.0-generate-preview" + prompt := "Extreme close-up of a cluster of vibrant wildflowers swaying gently in a sun-drenched meadow." + operation, err := client.Models.GenerateVideos(ctx, modelName, prompt, image, config) + if err != nil { + return fmt.Errorf("failed to start video generation: %w", err) + } + + // Polling until the operation is done + for !operation.Done { + time.Sleep(15 * time.Second) + operation, err = client.Operations.GetVideosOperation(ctx, operation, nil) + if err != nil { + return fmt.Errorf("failed to get operation status: %w", err) + } + } + + if operation.Response != nil && len(operation.Response.GeneratedVideos) > 0 { + videoURI := operation.Response.GeneratedVideos[0].Video.URI + fmt.Fprintln(w, videoURI) + return nil + } + + // Example response: + // gs://your-bucket/your-prefix/videoURI + + return fmt.Errorf("video generation failed or returned no results") +} + +// [END googlegenaisdk_videogen_with_img] diff --git a/genai/video_generation/video_gen_with_txt.go b/genai/video_generation/video_gen_with_txt.go new file mode 100644 index 0000000000..333e489a45 --- /dev/null +++ b/genai/video_generation/video_gen_with_txt.go @@ -0,0 +1,72 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package video_generation shows how to use the GenAI SDK to generate video. +package video_generation + +// [START googlegenaisdk_videogen_with_txt] +import ( + "context" + "fmt" + "io" + "time" + + "google.golang.org/genai" +) + +// generateVideoWithText shows how to gen video from text. +func generateVideoWithText(w io.Writer, outputGCSURI string) error { + ctx := context.Background() + + client, err := genai.NewClient(ctx, &genai.ClientConfig{ + HTTPOptions: genai.HTTPOptions{APIVersion: "v1"}, + }) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + config := &genai.GenerateVideosConfig{ + AspectRatio: "16:9", + OutputGCSURI: outputGCSURI, + } + + modelName := "veo-3.0-generate-preview" + prompt := "a cat reading a book" + operation, err := client.Models.GenerateVideos(ctx, modelName, prompt, nil, config) + if err != nil { + return fmt.Errorf("failed to start video generation: %w", err) + } + + // Polling until the operation is done + for !operation.Done { + time.Sleep(15 * time.Second) + operation, err = client.Operations.GetVideosOperation(ctx, operation, nil) + if err != nil { + return fmt.Errorf("failed to get operation status: %w", err) + } + } + + if operation.Response != nil && len(operation.Response.GeneratedVideos) > 0 { + videoURI := operation.Response.GeneratedVideos[0].Video.URI + fmt.Fprintln(w, videoURI) + return nil + } + + // Example response: + // gs://your-bucket/your-prefix/videoURI + + return fmt.Errorf("video generation failed or returned no results") +} + +// [END googlegenaisdk_videogen_with_txt] diff --git a/genai/video_generation/video_generation_examples_test.go b/genai/video_generation/video_generation_examples_test.go new file mode 100644 index 0000000000..591cfc8313 --- /dev/null +++ b/genai/video_generation/video_generation_examples_test.go @@ -0,0 +1,64 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package video_generation + +import ( + "bytes" + "testing" + "time" + + "github.com/GoogleCloudPlatform/golang-samples/internal/testutil" +) + +func TestVideoGeneration(t *testing.T) { + tc := testutil.SystemTest(t) + + t.Setenv("GOOGLE_GENAI_USE_VERTEXAI", "1") + t.Setenv("GOOGLE_CLOUD_LOCATION", "us-central1") + t.Setenv("GOOGLE_CLOUD_PROJECT", tc.ProjectID) + + buf := new(bytes.Buffer) + + gcsOutputBucket := "HERE-go-bucket-samples-tests" + prefix := "go_videogen_test/" + time.Now().Format("20060102-150405") + outputGCSURI := "gs://" + gcsOutputBucket + "/" + prefix + + t.Run("generate video content with img", func(t *testing.T) { + buf.Reset() + err := generateVideoFromImage(buf, outputGCSURI) + if err != nil { + t.Fatalf("generateVideoFromImage failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) + + t.Run("generate video content with text", func(t *testing.T) { + buf.Reset() + err := generateVideoWithText(buf, outputGCSURI) + if err != nil { + t.Fatalf("generateVideoWithText failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) + +} From 4f899b6ef60ee0a043f23c3aca1f4987f1966146 Mon Sep 17 00:00:00 2001 From: cfloress Date: Thu, 4 Sep 2025 13:14:02 -0400 Subject: [PATCH 2/6] genai: added batch prediction samples --- .../batchpredict_embeddings_with_gcs.go | 99 +++++++++++++++++++ .../batch_prediction/batchpredict_with_bq.go | 96 ++++++++++++++++++ .../batch_prediction/batchpredict_with_gcs.go | 99 +++++++++++++++++++ .../batchprediction_examples_test.go | 80 +++++++++++++++ 4 files changed, 374 insertions(+) create mode 100644 genai/batch_prediction/batchpredict_embeddings_with_gcs.go create mode 100644 genai/batch_prediction/batchpredict_with_bq.go create mode 100644 genai/batch_prediction/batchpredict_with_gcs.go create mode 100644 genai/batch_prediction/batchprediction_examples_test.go diff --git a/genai/batch_prediction/batchpredict_embeddings_with_gcs.go b/genai/batch_prediction/batchpredict_embeddings_with_gcs.go new file mode 100644 index 0000000000..3b71130f22 --- /dev/null +++ b/genai/batch_prediction/batchpredict_embeddings_with_gcs.go @@ -0,0 +1,99 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package batch_prediction shows how to use the GenAI SDK to batch prediction. + +package batch_prediction + +// [START googlegenaisdk_batchpredict_embeddings_with_gcs] +import ( + "context" + "fmt" + "io" + "time" + + "google.golang.org/genai" +) + +// generateBatchEmbeddings shows how to run a batch embeddings prediction job. +func generateBatchEmbeddings(w io.Writer, outputURI string) error { + // output_uri = "gs://your-bucket/your-prefix" + ctx := context.Background() + + client, err := genai.NewClient(ctx, &genai.ClientConfig{ + HTTPOptions: genai.HTTPOptions{APIVersion: "v1"}, + }) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + modelName := "text-embedding-005" + // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.batches.Batches.create + job, err := client.Batches.Create(ctx, + modelName, + &genai.BatchJobSource{ + Format: "jsonl", + // Source link: https://storage.cloud.google.com/cloud-samples-data/generative-ai/embeddings/embeddings_input.jsonl + GCSURI: []string{"gs://cloud-samples-data/generative-ai/embeddings/embeddings_input.jsonl"}, + }, + &genai.CreateBatchJobConfig{ + Dest: &genai.BatchJobDestination{ + Format: "jsonl", + GCSURI: outputURI, + }, + }, + ) + if err != nil { + return fmt.Errorf("failed to create batch job: %w", err) + } + + fmt.Fprintf(w, "Job name: %s\n", job.Name) + fmt.Fprintf(w, "Job state: %s\n", job.State) + // Example response: + // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job state: JOB_STATE_PENDING + + // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.types.BatchJob + completedStates := map[genai.JobState]bool{ + genai.JobStateSucceeded: true, + genai.JobStateFailed: true, + genai.JobStateCancelled: true, + genai.JobStatePaused: true, + } + + // Poll until job finishes + for !completedStates[job.State] { + time.Sleep(30 * time.Second) + job, err = client.Batches.Get(ctx, job.Name, nil) + if err != nil { + return fmt.Errorf("failed to get batch job: %w", err) + } + fmt.Fprintf(w, "Job state: %s\n", job.State) + + if job.State == genai.JobStateFailed { + fmt.Fprintf(w, "Error: %+v\n", job.Error) + break + } + } + + // Example response: + // Job state: JOB_STATE_PENDING + // Job state: JOB_STATE_RUNNING + // Job state: JOB_STATE_RUNNING + // ... + // Job state: JOB_STATE_SUCCEEDED + + return nil +} + +// [END googlegenaisdk_batchpredict_embeddings_with_gcs] diff --git a/genai/batch_prediction/batchpredict_with_bq.go b/genai/batch_prediction/batchpredict_with_bq.go new file mode 100644 index 0000000000..4917c7ac16 --- /dev/null +++ b/genai/batch_prediction/batchpredict_with_bq.go @@ -0,0 +1,96 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package batch_prediction shows how to use the GenAI SDK to batch prediction. + +package batch_prediction + +// [START googlegenaisdk_batchpredict_with_bq] +import ( + "context" + "fmt" + "io" + "time" + + "google.golang.org/genai" +) + +// generateBatchPredictWithBQ shows how to run a batch prediction job with BigQuery input/output. +func generateBatchPredictWithBQ(w io.Writer, outputURI string) error { + // output_uri = "bq://your-project.your_dataset.your_table" + ctx := context.Background() + + client, err := genai.NewClient(ctx, &genai.ClientConfig{ + HTTPOptions: genai.HTTPOptions{APIVersion: "v1"}, + }) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + // BigQuery input + src := &genai.BatchJobSource{ + Format: "bigquery", + BigqueryURI: "bq://storage-samples.generative_ai.batch_requests_for_multimodal_input", + } + + // BigQuery output + config := &genai.CreateBatchJobConfig{ + Dest: &genai.BatchJobDestination{ + Format: "bigquery", + BigqueryURI: outputURI, + }, + } + + // To use a tuned model, set the model param to your tuned model using the following format: + // modelName:= "projects/{PROJECT_ID}/locations/{LOCATION}/models/{MODEL_ID} + modelName := "gemini-2.5-flash" + job, err := client.Batches.Create(ctx, modelName, src, config) + if err != nil { + return fmt.Errorf("failed to create batch job: %w", err) + } + + fmt.Fprintf(w, "Job name: %s\n", job.Name) + fmt.Fprintf(w, "Job state: %s\n", job.State) + // Example response: + // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job state: JOB_STATE_PENDING + + // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.types.BatchJob + completedStates := map[genai.JobState]bool{ + genai.JobStateSucceeded: true, + genai.JobStateFailed: true, + genai.JobStateCancelled: true, + genai.JobStatePaused: true, + } + + for !completedStates[job.State] { + time.Sleep(30 * time.Second) + job, err = client.Batches.Get(ctx, job.Name, nil) + if err != nil { + return fmt.Errorf("failed to get batch job: %w", err) + } + fmt.Fprintf(w, "Job state: %s\n", job.State) + } + + // Example response: + // Job state: JOB_STATE_PENDING + // Job state: JOB_STATE_RUNNING + // Job state: JOB_STATE_RUNNING + // ... + // Job state: JOB_STATE_SUCCEEDED + + return nil +} + +// [END googlegenaisdk_batchpredict_with_bq] diff --git a/genai/batch_prediction/batchpredict_with_gcs.go b/genai/batch_prediction/batchpredict_with_gcs.go new file mode 100644 index 0000000000..d4ffed2b3f --- /dev/null +++ b/genai/batch_prediction/batchpredict_with_gcs.go @@ -0,0 +1,99 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package batch_prediction shows how to use the GenAI SDK to batch prediction. + +package batch_prediction + +// [START googlegenaisdk_batchpredict_with_gcs] +import ( + "context" + "fmt" + "io" + "time" + + "google.golang.org/genai" +) + +// generateBatchPredict runs a batch prediction job using GCS input/output. +func generateBatchPredict(w io.Writer, outputURI string) error { + // output_uri = "gs://your-bucket/your-prefix" + ctx := context.Background() + + client, err := genai.NewClient(ctx, &genai.ClientConfig{ + HTTPOptions: genai.HTTPOptions{APIVersion: "v1"}, + }) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + // Source file with prompts for prediction + src := &genai.BatchJobSource{ + Format: "jsonl", + // Source link: https://storage.cloud.google.com/cloud-samples-data/batch/prompt_for_batch_gemini_predict.jsonl + GCSURI: []string{"gs://cloud-samples-data/batch/prompt_for_batch_gemini_predict.jsonl"}, + } + + // Batch job config with output GCS location + config := &genai.CreateBatchJobConfig{ + Dest: &genai.BatchJobDestination{ + Format: "jsonl", + GCSURI: outputURI, + }, + } + // To use a tuned model, set the model param to your tuned model using the following format: + // modelName:= "projects/{PROJECT_ID}/locations/{LOCATION}/models/{MODEL_ID} + modelName := "gemini-2.5-flash" + // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.batches.Batches.create + job, err := client.Batches.Create(ctx, modelName, src, config) + if err != nil { + return fmt.Errorf("failed to create batch job: %w", err) + } + + fmt.Fprintf(w, "Job name: %s\n", job.Name) + fmt.Fprintf(w, "Job state: %s\n", job.State) + // Example response: + // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job state: JOB_STATE_PENDING + + // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.types.BatchJob + completedStates := map[genai.JobState]bool{ + genai.JobStateSucceeded: true, + genai.JobStateFailed: true, + genai.JobStateCancelled: true, + genai.JobStatePaused: true, + } + + for !completedStates[job.State] { + time.Sleep(30 * time.Second) + + job, err = client.Batches.Get(ctx, job.Name, nil) + if err != nil { + return fmt.Errorf("failed to get batch job: %w", err) + } + + fmt.Fprintf(w, "Job state: %s\n", job.State) + } + + // Example response: + // Job state: JOB_STATE_PENDING + // Job state: JOB_STATE_RUNNING + // Job state: JOB_STATE_RUNNING + // ... + // Job state: JOB_STATE_SUCCEEDED + + return nil +} + +// [END googlegenaisdk_batchpredict_with_gcs] diff --git a/genai/batch_prediction/batchprediction_examples_test.go b/genai/batch_prediction/batchprediction_examples_test.go new file mode 100644 index 0000000000..03cb1e4009 --- /dev/null +++ b/genai/batch_prediction/batchprediction_examples_test.go @@ -0,0 +1,80 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package batch_prediction + +import ( + "bytes" + "fmt" + "testing" + "time" + + "github.com/GoogleCloudPlatform/golang-samples/internal/testutil" +) + +const gcsOutputBucket = "golang-docs-samples-tests" + +func TestGenerateBatchEmbeddings(t *testing.T) { + tc := testutil.SystemTest(t) + + t.Setenv("GOOGLE_GENAI_USE_VERTEXAI", "1") + t.Setenv("GOOGLE_CLOUD_LOCATION", "us-central1") + t.Setenv("GOOGLE_CLOUD_PROJECT", tc.ProjectID) + + prefix := fmt.Sprintf("embeddings_output/%d", time.Now().UnixNano()) + outputURI := fmt.Sprintf("gs://%s/%s", gcsOutputBucket, prefix) + buf := new(bytes.Buffer) + + t.Run("generate batch embeddings with GCS", func(t *testing.T) { + buf.Reset() + err := generateBatchEmbeddings(buf, outputURI) + if err != nil { + t.Fatalf("generateBatchEmbeddings failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) + + t.Run("generate batch predict with gcs input/output", func(t *testing.T) { + buf.Reset() + err := generateBatchPredict(buf, outputURI) + if err != nil { + t.Fatalf("generateBatchPredict failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + + }) + + t.Run("generate batch predict with BigQuery", func(t *testing.T) { + buf.Reset() + outputURIBQ := "bq://your-project.your_dataset.your_table" + + err := generateBatchPredictWithBQ(buf, outputURIBQ) + if err != nil { + t.Fatalf("generateBatchPredictWithBQ failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) +} From c1cebee3c223db221290816419a081200f9bfc20 Mon Sep 17 00:00:00 2001 From: cfloress Date: Fri, 5 Sep 2025 12:31:21 -0400 Subject: [PATCH 3/6] genai: added image generation samples --- .../batchpredict_embeddings_with_gcs.go | 2 +- .../batch_prediction/batchpredict_with_bq.go | 2 +- .../batch_prediction/batchpredict_with_gcs.go | 2 +- .../image_generation_examples_test.go | 72 ++++++++++++++++ .../imggen_canny_ctrl_type_with_txt_img.go | 81 +++++++++++++++++ .../imggen_scribble_ctrl_type_with_txt_img.go | 81 +++++++++++++++++ .../imggen_styleref_with_txt_img.go | 86 +++++++++++++++++++ genai/tools/tools_vais_search_with_txt.go | 1 + genai/video_generation/video_gen_with_img.go | 1 + genai/video_generation/video_gen_with_txt.go | 1 + 10 files changed, 326 insertions(+), 3 deletions(-) create mode 100644 genai/image_generation/image_generation_examples_test.go create mode 100644 genai/image_generation/imggen_canny_ctrl_type_with_txt_img.go create mode 100644 genai/image_generation/imggen_scribble_ctrl_type_with_txt_img.go create mode 100644 genai/image_generation/imggen_styleref_with_txt_img.go diff --git a/genai/batch_prediction/batchpredict_embeddings_with_gcs.go b/genai/batch_prediction/batchpredict_embeddings_with_gcs.go index 3b71130f22..8a3df27c5d 100644 --- a/genai/batch_prediction/batchpredict_embeddings_with_gcs.go +++ b/genai/batch_prediction/batchpredict_embeddings_with_gcs.go @@ -28,7 +28,7 @@ import ( // generateBatchEmbeddings shows how to run a batch embeddings prediction job. func generateBatchEmbeddings(w io.Writer, outputURI string) error { - // output_uri = "gs://your-bucket/your-prefix" + // outputURI = "gs://your-bucket/your-prefix" ctx := context.Background() client, err := genai.NewClient(ctx, &genai.ClientConfig{ diff --git a/genai/batch_prediction/batchpredict_with_bq.go b/genai/batch_prediction/batchpredict_with_bq.go index 4917c7ac16..3e1a941128 100644 --- a/genai/batch_prediction/batchpredict_with_bq.go +++ b/genai/batch_prediction/batchpredict_with_bq.go @@ -28,7 +28,7 @@ import ( // generateBatchPredictWithBQ shows how to run a batch prediction job with BigQuery input/output. func generateBatchPredictWithBQ(w io.Writer, outputURI string) error { - // output_uri = "bq://your-project.your_dataset.your_table" + // outputURI = "bq://your-project.your_dataset.your_table" ctx := context.Background() client, err := genai.NewClient(ctx, &genai.ClientConfig{ diff --git a/genai/batch_prediction/batchpredict_with_gcs.go b/genai/batch_prediction/batchpredict_with_gcs.go index d4ffed2b3f..29b62a27d7 100644 --- a/genai/batch_prediction/batchpredict_with_gcs.go +++ b/genai/batch_prediction/batchpredict_with_gcs.go @@ -28,7 +28,7 @@ import ( // generateBatchPredict runs a batch prediction job using GCS input/output. func generateBatchPredict(w io.Writer, outputURI string) error { - // output_uri = "gs://your-bucket/your-prefix" + // outputURI = "gs://your-bucket/your-prefix" ctx := context.Background() client, err := genai.NewClient(ctx, &genai.ClientConfig{ diff --git a/genai/image_generation/image_generation_examples_test.go b/genai/image_generation/image_generation_examples_test.go new file mode 100644 index 0000000000..50ecb3ac86 --- /dev/null +++ b/genai/image_generation/image_generation_examples_test.go @@ -0,0 +1,72 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package image_generation + +import ( + "bytes" + "testing" +) + +func TestStyleCustomization(t *testing.T) { + buf := new(bytes.Buffer) + + t.Run("style customization with style reference", func(t *testing.T) { + buf.Reset() + // TODO(developer): update with your bucket + outputGCSURI := "gs://your-bucket/your-prefix" + + err := generateStyleRefWithText(buf, outputGCSURI) + if err != nil { + t.Fatalf("generateStyleRefWithText failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected printed output, got empty") + } + }) + + t.Run("canny edge customization with text+image", func(t *testing.T) { + buf.Reset() + // TODO(developer): update with your bucket + outputGCSURI := "gs://your-bucket/your-prefix" + + err := generateCannyCtrlTypeWithText(buf, outputGCSURI) + if err != nil { + t.Fatalf("generateCannyCtrlTypeWithText failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) + + t.Run("generate image with scribble control type", func(t *testing.T) { + buf.Reset() + // TODO(developer): update with your bucket + outputGCSURI := "gs://your-bucket/your-prefix" + + err := generateScribbleCtrlTypeWithText(buf, outputGCSURI) + if err != nil { + t.Fatalf("generateScribbleCtrlTypeWithText failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) +} diff --git a/genai/image_generation/imggen_canny_ctrl_type_with_txt_img.go b/genai/image_generation/imggen_canny_ctrl_type_with_txt_img.go new file mode 100644 index 0000000000..d5584b75ed --- /dev/null +++ b/genai/image_generation/imggen_canny_ctrl_type_with_txt_img.go @@ -0,0 +1,81 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package image_generation shows how to use the GenAI SDK to generate images from prompt. + +package image_generation + +// [START googlegenaisdk_imggen_canny_ctrl_type_with_txt_img] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateCannyCtrlTypeWithText demonstrates how to generate an image using a canny ctrl type. +func generateCannyCtrlTypeWithText(w io.Writer, outputGCSURI string) error { + //outputGCSURI = "gs://your-bucket/your-prefix" + ctx := context.Background() + + client, err := genai.NewClient(ctx, nil) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + controlReference := &genai.ControlReferenceConfig{ + ControlType: genai.ControlReferenceTypeCanny, + } + + referenceImage := &genai.ControlReferenceImage{ + ReferenceID: 1, + ReferenceImage: &genai.Image{ + GCSURI: "gs://cloud-samples-data/generative-ai/image/car_canny.png", + }, + Config: controlReference, + } + + modelName := "imagen-3.0-capability-001" + prompt := "a watercolor painting of a red car[1] driving on a road" + + resp, err := client.Models.EditImage(ctx, + modelName, + prompt, + []genai.ReferenceImage{referenceImage}, + &genai.EditImageConfig{ + EditMode: genai.EditModeControlledEditing, + NumberOfImages: 1, + SafetyFilterLevel: genai.SafetyFilterLevelBlockMediumAndAbove, + PersonGeneration: genai.PersonGenerationAllowAdult, + OutputGCSURI: outputGCSURI, + }, + ) + if err != nil { + return fmt.Errorf("failed to edit image: %w", err) + } + + if len(resp.GeneratedImages) == 0 || resp.GeneratedImages[0].Image == nil { + return fmt.Errorf("no image generated") + } + + uri := resp.GeneratedImages[0].Image.GCSURI + fmt.Fprintln(w, uri) + + // Example response: + // gs://your-bucket/your-prefix + return nil +} + +// [END googlegenaisdk_imggen_canny_ctrl_type_with_txt_img] diff --git a/genai/image_generation/imggen_scribble_ctrl_type_with_txt_img.go b/genai/image_generation/imggen_scribble_ctrl_type_with_txt_img.go new file mode 100644 index 0000000000..48d5ae7e73 --- /dev/null +++ b/genai/image_generation/imggen_scribble_ctrl_type_with_txt_img.go @@ -0,0 +1,81 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package image_generation shows how to use the GenAI SDK to generate images from prompt. + +package image_generation + +// [START googlegenaisdk_imggen_scribble_ctrl_type_with_txt_img] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateScribbleCtrlTypeWithText demonstrates how to generate an image using a scribble ctrl type. +func generateScribbleCtrlTypeWithText(w io.Writer, outputGCSURI string) error { + //outputGCSURI = "gs://your-bucket/your-prefix" + ctx := context.Background() + + client, err := genai.NewClient(ctx, nil) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + controlReference := &genai.ControlReferenceConfig{ + ControlType: genai.ControlReferenceTypeScribble, + } + + referenceImage := &genai.ControlReferenceImage{ + ReferenceID: 1, + ReferenceImage: &genai.Image{ + GCSURI: "gs://cloud-samples-data/generative-ai/image/car_scribble.png", + }, + Config: controlReference, + } + + modelName := "imagen-3.0-capability-001" + prompt := "an oil painting showing the side of a red car[1]" + + resp, err := client.Models.EditImage(ctx, + modelName, + prompt, + []genai.ReferenceImage{referenceImage}, + &genai.EditImageConfig{ + EditMode: genai.EditModeControlledEditing, + NumberOfImages: 1, + SafetyFilterLevel: genai.SafetyFilterLevelBlockMediumAndAbove, + PersonGeneration: genai.PersonGenerationAllowAdult, + OutputGCSURI: outputGCSURI, + }, + ) + if err != nil { + return fmt.Errorf("failed to edit image: %w", err) + } + + if len(resp.GeneratedImages) == 0 || resp.GeneratedImages[0].Image == nil { + return fmt.Errorf("no image generated") + } + + uri := resp.GeneratedImages[0].Image.GCSURI + fmt.Fprintln(w, uri) + + // Example response: + // gs://your-bucket/your-prefix + return nil +} + +// [END googlegenaisdk_imggen_scribble_ctrl_type_with_txt_img] diff --git a/genai/image_generation/imggen_styleref_with_txt_img.go b/genai/image_generation/imggen_styleref_with_txt_img.go new file mode 100644 index 0000000000..391e7e27e2 --- /dev/null +++ b/genai/image_generation/imggen_styleref_with_txt_img.go @@ -0,0 +1,86 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package image_generation shows how to use the GenAI SDK to generate images from prompt. + +package image_generation + +// [START googlegenaisdk_imggen_style_reference_with_txt_img] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateStyleRefWithText demonstrates how to generate an image using a style reference. +func generateStyleRefWithText(w io.Writer, outputGCSURI string) error { + //outputGCSURI = "gs://your-bucket/your-prefix" + ctx := context.Background() + + client, err := genai.NewClient(ctx, nil) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + // Create a style reference image of a neon sign stored in Google Cloud Storage + // using https://storage.googleapis.com/cloud-samples-data/generative-ai/image/neon.png + styleRefImg := &genai.StyleReferenceImage{ + ReferenceID: 1, + ReferenceImage: &genai.Image{ + GCSURI: "gs://cloud-samples-data/generative-ai/image/neon.png", + }, + Config: &genai.StyleReferenceConfig{ + StyleDescription: "neon sign", + }, + } + + // prompt that references the style image with [1] + prompt := "generate an image of a neon sign [1] with the words: have a great day" + modelName := "imagen-3.0-capability-001" + + // EditImage takes: ctx, model, prompt, referenceImages []ReferenceImage, config *EditImageConfig + resp, err := client.Models.EditImage(ctx, + modelName, + prompt, + []genai.ReferenceImage{ + styleRefImg, + }, + &genai.EditImageConfig{ + EditMode: genai.EditModeDefault, + NumberOfImages: 1, + SafetyFilterLevel: genai.SafetyFilterLevelBlockMediumAndAbove, + PersonGeneration: genai.PersonGenerationAllowAdult, + OutputGCSURI: outputGCSURI, + }, + ) + if err != nil { + return fmt.Errorf("failed to edit image: %w", err) + } + + if len(resp.GeneratedImages) == 0 || resp.GeneratedImages[0].Image == nil { + return fmt.Errorf("no generated images returned") + } + + // Grab the first generated image URI and print it + uri := resp.GeneratedImages[0].Image.GCSURI + fmt.Fprintln(w, uri) + + // Example response: + // gs://your-bucket/your-prefix + return nil +} + +// [END googlegenaisdk_imggen_style_reference_with_txt_img] diff --git a/genai/tools/tools_vais_search_with_txt.go b/genai/tools/tools_vais_search_with_txt.go index d4ac2b1149..250df01ffd 100644 --- a/genai/tools/tools_vais_search_with_txt.go +++ b/genai/tools/tools_vais_search_with_txt.go @@ -26,6 +26,7 @@ import ( // generateWithGoogleVAIS shows how to generate text using VAIS Search. func generateWithGoogleVAIS(w io.Writer, datastore string) error { + //datastore = "gs://your-datastore/your-prefix" ctx := context.Background() client, err := genai.NewClient(ctx, &genai.ClientConfig{ diff --git a/genai/video_generation/video_gen_with_img.go b/genai/video_generation/video_gen_with_img.go index af68c700c9..c52b97189e 100644 --- a/genai/video_generation/video_gen_with_img.go +++ b/genai/video_generation/video_gen_with_img.go @@ -27,6 +27,7 @@ import ( // generateVideoFromImage shows how to gen video from img. func generateVideoFromImage(w io.Writer, outputGCSURI string) error { + //outputGCSURI = "gs://your-bucket/your-prefix" ctx := context.Background() client, err := genai.NewClient(ctx, &genai.ClientConfig{ diff --git a/genai/video_generation/video_gen_with_txt.go b/genai/video_generation/video_gen_with_txt.go index 333e489a45..922e153111 100644 --- a/genai/video_generation/video_gen_with_txt.go +++ b/genai/video_generation/video_gen_with_txt.go @@ -27,6 +27,7 @@ import ( // generateVideoWithText shows how to gen video from text. func generateVideoWithText(w io.Writer, outputGCSURI string) error { + //outputGCSURI = "gs://your-bucket/your-prefix" ctx := context.Background() client, err := genai.NewClient(ctx, &genai.ClientConfig{ From 49c065b017fb21fec4de238926191426434f1f73 Mon Sep 17 00:00:00 2001 From: cfloress Date: Fri, 5 Sep 2025 12:53:56 -0400 Subject: [PATCH 4/6] genai: PR comments --- genai/batch_prediction/batchpredict_embeddings_with_gcs.go | 2 +- genai/batch_prediction/batchpredict_with_bq.go | 2 +- genai/batch_prediction/batchpredict_with_gcs.go | 2 +- genai/batch_prediction/batchprediction_examples_test.go | 2 +- genai/image_generation/image_generation_examples_test.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/genai/batch_prediction/batchpredict_embeddings_with_gcs.go b/genai/batch_prediction/batchpredict_embeddings_with_gcs.go index 8a3df27c5d..38c5a19eb2 100644 --- a/genai/batch_prediction/batchpredict_embeddings_with_gcs.go +++ b/genai/batch_prediction/batchpredict_embeddings_with_gcs.go @@ -60,7 +60,7 @@ func generateBatchEmbeddings(w io.Writer, outputURI string) error { fmt.Fprintf(w, "Job name: %s\n", job.Name) fmt.Fprintf(w, "Job state: %s\n", job.State) // Example response: - // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job name: projects/{PROJECT_ID}/locations/us-central1/batchPredictionJobs/9876453210000000000 // Job state: JOB_STATE_PENDING // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.types.BatchJob diff --git a/genai/batch_prediction/batchpredict_with_bq.go b/genai/batch_prediction/batchpredict_with_bq.go index 3e1a941128..085e383f00 100644 --- a/genai/batch_prediction/batchpredict_with_bq.go +++ b/genai/batch_prediction/batchpredict_with_bq.go @@ -63,7 +63,7 @@ func generateBatchPredictWithBQ(w io.Writer, outputURI string) error { fmt.Fprintf(w, "Job name: %s\n", job.Name) fmt.Fprintf(w, "Job state: %s\n", job.State) // Example response: - // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job name: projects/{PROJECT_ID}/locations/us-central1/batchPredictionJobs/9876453210000000000 // Job state: JOB_STATE_PENDING // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.types.BatchJob diff --git a/genai/batch_prediction/batchpredict_with_gcs.go b/genai/batch_prediction/batchpredict_with_gcs.go index 29b62a27d7..433da01a2b 100644 --- a/genai/batch_prediction/batchpredict_with_gcs.go +++ b/genai/batch_prediction/batchpredict_with_gcs.go @@ -64,7 +64,7 @@ func generateBatchPredict(w io.Writer, outputURI string) error { fmt.Fprintf(w, "Job name: %s\n", job.Name) fmt.Fprintf(w, "Job state: %s\n", job.State) // Example response: - // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job name: projects/{PROJECT_ID}/locations/us-central1/batchPredictionJobs/9876453210000000000 // Job state: JOB_STATE_PENDING // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.types.BatchJob diff --git a/genai/batch_prediction/batchprediction_examples_test.go b/genai/batch_prediction/batchprediction_examples_test.go index 03cb1e4009..d076dac5eb 100644 --- a/genai/batch_prediction/batchprediction_examples_test.go +++ b/genai/batch_prediction/batchprediction_examples_test.go @@ -25,7 +25,7 @@ import ( const gcsOutputBucket = "golang-docs-samples-tests" -func TestGenerateBatchEmbeddings(t *testing.T) { +func TestBatchPrediction(t *testing.T) { tc := testutil.SystemTest(t) t.Setenv("GOOGLE_GENAI_USE_VERTEXAI", "1") diff --git a/genai/image_generation/image_generation_examples_test.go b/genai/image_generation/image_generation_examples_test.go index 50ecb3ac86..82d15440dd 100644 --- a/genai/image_generation/image_generation_examples_test.go +++ b/genai/image_generation/image_generation_examples_test.go @@ -19,7 +19,7 @@ import ( "testing" ) -func TestStyleCustomization(t *testing.T) { +func TestImageGeneration(t *testing.T) { buf := new(bytes.Buffer) t.Run("style customization with style reference", func(t *testing.T) { From 4a9fa6885e850224d836a7ccd953e00d08f1438b Mon Sep 17 00:00:00 2001 From: cfloress Date: Wed, 10 Sep 2025 20:03:21 -0300 Subject: [PATCH 5/6] genai: added image generation samples --- .../image_generation_examples_test.go | 16 ++++ ...gen_subj_refer_ctrl_refer_with_txt_imgs.go | 96 +++++++++++++++++++ 2 files changed, 112 insertions(+) create mode 100644 genai/image_generation/imggen_subj_refer_ctrl_refer_with_txt_imgs.go diff --git a/genai/image_generation/image_generation_examples_test.go b/genai/image_generation/image_generation_examples_test.go index 82d15440dd..b847b82a52 100644 --- a/genai/image_generation/image_generation_examples_test.go +++ b/genai/image_generation/image_generation_examples_test.go @@ -69,4 +69,20 @@ func TestImageGeneration(t *testing.T) { t.Error("expected non-empty output, got empty") } }) + + t.Run("subject customization with control reference", func(t *testing.T) { + buf.Reset() + // TODO(developer): update with your bucket + outputGCSURI := "gs://your-bucket/your-prefix" + + err := generateSubjRefCtrlReferWithText(buf, outputGCSURI) + if err != nil { + t.Fatalf("generateSubjRefCtrlReferWithText failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) } diff --git a/genai/image_generation/imggen_subj_refer_ctrl_refer_with_txt_imgs.go b/genai/image_generation/imggen_subj_refer_ctrl_refer_with_txt_imgs.go new file mode 100644 index 0000000000..43f48c754e --- /dev/null +++ b/genai/image_generation/imggen_subj_refer_ctrl_refer_with_txt_imgs.go @@ -0,0 +1,96 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package image_generation shows how to use the GenAI SDK to generate images from prompt. + +package image_generation + +// [START googlegenaisdk_imggen_subj_refer_ctrl_refer_with_txt_imgs] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateSubjRefCtrlReferWithText demonstrates subject & control reference customization. +func generateSubjRefCtrlReferWithText(w io.Writer, outputGCSURI string) error { + //outputGCSURI = "gs://your-bucket/your-prefix" + ctx := context.Background() + + client, err := genai.NewClient(ctx, nil) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + // Create subject and control reference images of a photograph stored in Google Cloud Storage + // using https://storage.googleapis.com/cloud-samples-data/generative-ai/image/person.png + subjectReferenceImage := &genai.SubjectReferenceImage{ + ReferenceID: 1, + ReferenceImage: &genai.Image{ + GCSURI: "gs://cloud-samples-data/generative-ai/image/person.png", + }, + Config: &genai.SubjectReferenceConfig{ + SubjectType: genai.SubjectReferenceTypeSubjectTypePerson, + SubjectDescription: "a headshot of a woman", + }, + } + + controlReferenceImage := &genai.ControlReferenceImage{ + ReferenceID: 2, + ReferenceImage: &genai.Image{ + GCSURI: "gs://cloud-samples-data/generative-ai/image/person.png", + }, + Config: &genai.ControlReferenceConfig{ + ControlType: genai.ControlReferenceTypeFaceMesh, + }, + } + + // prompt that references the style image with [1] + prompt := "a portrait of a woman[1] in the pose of the control image[2] in a watercolor style by a professional artist, light and low-contrast strokes, bright pastel colors, a warm atmosphere, clean background, grainy paper, bold visible brushstrokes, patchy details" + modelName := "imagen-3.0-capability-001" + + resp, err := client.Models.EditImage(ctx, + modelName, + prompt, + []genai.ReferenceImage{ + subjectReferenceImage, + controlReferenceImage, + }, + &genai.EditImageConfig{ + EditMode: genai.EditModeDefault, + NumberOfImages: 1, + SafetyFilterLevel: genai.SafetyFilterLevelBlockMediumAndAbove, + PersonGeneration: genai.PersonGenerationAllowAdult, + OutputGCSURI: outputGCSURI, + }, + ) + if err != nil { + return fmt.Errorf("failed to edit image: %w", err) + } + + if len(resp.GeneratedImages) == 0 || resp.GeneratedImages[0].Image == nil { + return fmt.Errorf("no generated images returned") + } + + uri := resp.GeneratedImages[0].Image.GCSURI + fmt.Fprintln(w, uri) + + // Example response: + // gs://your-bucket/your-prefix + return nil +} + +// [END googlegenaisdk_imggen_subj_refer_ctrl_refer_with_txt_imgs] From ecc85ba262daff8597b081e46392fd2f8b5b4bd8 Mon Sep 17 00:00:00 2001 From: cfloress Date: Wed, 10 Sep 2025 22:08:53 -0300 Subject: [PATCH 6/6] genai: added imggen_raw_reference_with_txt_img sample --- .../image_generation_examples_test.go | 16 ++++ .../imggen_raw_refer_with_txt_img.go | 80 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 genai/image_generation/imggen_raw_refer_with_txt_img.go diff --git a/genai/image_generation/image_generation_examples_test.go b/genai/image_generation/image_generation_examples_test.go index b847b82a52..00df420c64 100644 --- a/genai/image_generation/image_generation_examples_test.go +++ b/genai/image_generation/image_generation_examples_test.go @@ -85,4 +85,20 @@ func TestImageGeneration(t *testing.T) { t.Error("expected non-empty output, got empty") } }) + + t.Run("generate style transfer customization with raw reference", func(t *testing.T) { + buf.Reset() + // TODO(developer): update with your bucket + outputGCSURI := "gs://your-bucket/your-prefix" + + err := generateRawReferWithText(buf, outputGCSURI) + if err != nil { + t.Fatalf("generateRawReferWithText failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) } diff --git a/genai/image_generation/imggen_raw_refer_with_txt_img.go b/genai/image_generation/imggen_raw_refer_with_txt_img.go new file mode 100644 index 0000000000..b437a8c5dd --- /dev/null +++ b/genai/image_generation/imggen_raw_refer_with_txt_img.go @@ -0,0 +1,80 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package image_generation shows how to use the GenAI SDK to generate images from prompt. + +package image_generation + +// [START googlegenaisdk_imggen_raw_reference_with_txt_img] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateRawReferWithText demonstrates subject & control reference customization. +func generateRawReferWithText(w io.Writer, outputGCSURI string) error { + //outputGCSURI = "gs://your-bucket/your-prefix" + ctx := context.Background() + + client, err := genai.NewClient(ctx, nil) + if err != nil { + return fmt.Errorf("failed to create genai client: %w", err) + } + + // Create a raw reference image of teacup stored in Google Cloud Storage + // using https://storage.googleapis.com/cloud-samples-data/generative-ai/image/teacup-1.png + rawRefImage := &genai.RawReferenceImage{ + ReferenceID: 1, + ReferenceImage: &genai.Image{ + GCSURI: "gs://cloud-samples-data/generative-ai/image/teacup-1.png", + }, + } + + prompt := "transform the subject in the image so that the teacup[1] is made entirely out of chocolate" + modelName := "imagen-3.0-capability-001" + + resp, err := client.Models.EditImage(ctx, + modelName, + prompt, + []genai.ReferenceImage{ + rawRefImage, + }, + &genai.EditImageConfig{ + EditMode: genai.EditModeDefault, + NumberOfImages: 1, + SafetyFilterLevel: genai.SafetyFilterLevelBlockMediumAndAbove, + PersonGeneration: genai.PersonGenerationAllowAdult, + OutputGCSURI: outputGCSURI, + }, + ) + if err != nil { + return fmt.Errorf("failed to edit image: %w", err) + } + + if len(resp.GeneratedImages) == 0 || resp.GeneratedImages[0].Image == nil { + return fmt.Errorf("no generated images returned") + } + + uri := resp.GeneratedImages[0].Image.GCSURI + fmt.Fprintln(w, uri) + + // Example response: + // gs://your-bucket/your-prefix + return nil +} + +// [END googlegenaisdk_imggen_raw_reference_with_txt_img]