diff --git a/genai/bounding_box/boundingbox_with_txt_img.go b/genai/bounding_box/boundingbox_with_txt_img.go index 470c004a98..d12beb6b13 100644 --- a/genai/bounding_box/boundingbox_with_txt_img.go +++ b/genai/bounding_box/boundingbox_with_txt_img.go @@ -125,7 +125,7 @@ func generateBoundingBoxesWithText(w io.Writer) error { contents := []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ { FileData: &genai.FileData{ diff --git a/genai/content_cache/contentcache_create_with_txt_gcs_pdf.go b/genai/content_cache/contentcache_create_with_txt_gcs_pdf.go index 8f810ac7b9..de2fb4963c 100644 --- a/genai/content_cache/contentcache_create_with_txt_gcs_pdf.go +++ b/genai/content_cache/contentcache_create_with_txt_gcs_pdf.go @@ -55,7 +55,7 @@ func createContentCache(w io.Writer) (string, error) { MIMEType: "application/pdf", }}, }, - Role: "user", + Role: genai.RoleUser, }, } config := &genai.CreateCachedContentConfig{ diff --git a/genai/controlled_generation/ctrlgen_with_class_schema.go b/genai/controlled_generation/ctrlgen_with_class_schema.go index ac3ea0ee9f..92e8c19f63 100644 --- a/genai/controlled_generation/ctrlgen_with_class_schema.go +++ b/genai/controlled_generation/ctrlgen_with_class_schema.go @@ -46,7 +46,7 @@ func generateWithClassSchema(w io.Writer) error { contents := []*genai.Content{ {Parts: []*genai.Part{ {Text: "List a few popular cookie recipes."}, - }, Role: "user"}, + }, Role: genai.RoleUser}, } // JSON Schema for []Recipe schema := &genai.Schema{ diff --git a/genai/controlled_generation/ctrlgen_with_enum_class_schema.go b/genai/controlled_generation/ctrlgen_with_enum_class_schema.go index fa0cb21aa6..ac8aa85398 100644 --- a/genai/controlled_generation/ctrlgen_with_enum_class_schema.go +++ b/genai/controlled_generation/ctrlgen_with_enum_class_schema.go @@ -55,7 +55,7 @@ func generateWithEnumClassSchema(w io.Writer) error { contents := []*genai.Content{ {Parts: []*genai.Part{ {Text: "What type of instrument is a guitar?"}, - }, Role: "user"}, + }, Role: genai.RoleUser}, } config := &genai.GenerateContentConfig{ diff --git a/genai/controlled_generation/ctrlgen_with_enum_schema.go b/genai/controlled_generation/ctrlgen_with_enum_schema.go index bd81f182bc..b6c2ce7dc7 100644 --- a/genai/controlled_generation/ctrlgen_with_enum_schema.go +++ b/genai/controlled_generation/ctrlgen_with_enum_schema.go @@ -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"}, + }, Role: genai.RoleUser}, } config := &genai.GenerateContentConfig{ ResponseMIMEType: "text/x.enum", diff --git a/genai/controlled_generation/ctrlgen_with_nested_class_schema.go b/genai/controlled_generation/ctrlgen_with_nested_class_schema.go index 29cf93ae98..fc212655e0 100644 --- a/genai/controlled_generation/ctrlgen_with_nested_class_schema.go +++ b/genai/controlled_generation/ctrlgen_with_nested_class_schema.go @@ -55,7 +55,7 @@ func generateWithNestedClassSchema(w io.Writer) error { contents := []*genai.Content{ {Parts: []*genai.Part{ {Text: "List about 10 home-baked cookies and give them grades based on tastiness."}, - }, Role: "user"}, + }, Role: genai.RoleUser}, } config := &genai.GenerateContentConfig{ diff --git a/genai/controlled_generation/ctrlgen_with_nullable_schema.go b/genai/controlled_generation/ctrlgen_with_nullable_schema.go index 6805d690a5..cea956cc39 100644 --- a/genai/controlled_generation/ctrlgen_with_nullable_schema.go +++ b/genai/controlled_generation/ctrlgen_with_nullable_schema.go @@ -50,7 +50,7 @@ Finally, Saturday rounds off the week with sunny skies, a temperature of 80°F, {Parts: []*genai.Part{ {Text: prompt}, }, - Role: "user"}, + Role: genai.RoleUser}, } config := &genai.GenerateContentConfig{ ResponseMIMEType: "application/json", diff --git a/genai/controlled_generation/ctrlgen_with_resp_schema.go b/genai/controlled_generation/ctrlgen_with_resp_schema.go index 7228b72b26..a3d99ff1e2 100644 --- a/genai/controlled_generation/ctrlgen_with_resp_schema.go +++ b/genai/controlled_generation/ctrlgen_with_resp_schema.go @@ -58,7 +58,7 @@ func generateWithRespSchema(w io.Writer) error { {Parts: []*genai.Part{ {Text: "List a few popular cookie recipes."}, }, - Role: "user"}, + Role: genai.RoleUser}, } modelName := "gemini-2.5-flash" diff --git a/genai/count_tokens/counttoken_compute_with_txt.go b/genai/count_tokens/counttoken_compute_with_txt.go index 3833ec6843..6816c7d402 100644 --- a/genai/count_tokens/counttoken_compute_with_txt.go +++ b/genai/count_tokens/counttoken_compute_with_txt.go @@ -41,7 +41,7 @@ func computeWithTxt(w io.Writer) error { {Parts: []*genai.Part{ {Text: "What's the longest word in the English language?"}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.ComputeTokens(ctx, modelName, contents, nil) diff --git a/genai/count_tokens/counttoken_resp_with_txt.go b/genai/count_tokens/counttoken_resp_with_txt.go index e36eedc85c..5bcab501c5 100644 --- a/genai/count_tokens/counttoken_resp_with_txt.go +++ b/genai/count_tokens/counttoken_resp_with_txt.go @@ -41,7 +41,7 @@ func generateTextAndCount(w io.Writer) error { {Parts: []*genai.Part{ {Text: "Why is the sky blue?"}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/count_tokens/counttoken_with_txt_vid.go b/genai/count_tokens/counttoken_with_txt_vid.go index 7191e5e06a..02cb709ba2 100644 --- a/genai/count_tokens/counttoken_with_txt_vid.go +++ b/genai/count_tokens/counttoken_with_txt_vid.go @@ -44,7 +44,7 @@ func countWithTxtAndVid(w io.Writer) error { MIMEType: "video/mp4", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.CountTokens(ctx, modelName, contents, nil) diff --git a/genai/embeddings/embeddings_docretrieval_with_txt.go b/genai/embeddings/embeddings_docretrieval_with_txt.go index af95ecccde..e2cad722de 100644 --- a/genai/embeddings/embeddings_docretrieval_with_txt.go +++ b/genai/embeddings/embeddings_docretrieval_with_txt.go @@ -55,7 +55,7 @@ func generateEmbedContentWithText(w io.Writer) error { Text: "Driver's knowledge test study guide", }, }, - Role: "user", + Role: genai.RoleUser, }, } diff --git a/genai/express_mode/expressmode_with_api_key.go b/genai/express_mode/expressmode_with_api_key.go index 4cca36bfa0..63c5701794 100644 --- a/genai/express_mode/expressmode_with_api_key.go +++ b/genai/express_mode/expressmode_with_api_key.go @@ -46,7 +46,7 @@ func generateContentWithApiKey(w io.Writer) error { []*genai.Content{ {Parts: []*genai.Part{ {Text: "Explain bubble sort to me."}, - }, Role: "user"}, + }, Role: genai.RoleUser}, }, nil, ) diff --git a/genai/image_generation/imggen_mmflash_txt_img_with_txt.go b/genai/image_generation/imggen_mmflash_txt_img_with_txt.go index 4a0d3ec8f2..f56b928e36 100644 --- a/genai/image_generation/imggen_mmflash_txt_img_with_txt.go +++ b/genai/image_generation/imggen_mmflash_txt_img_with_txt.go @@ -45,7 +45,7 @@ func generateMMFlashTxtImgWithText(w io.Writer) error { {Text: "Generate an illustrated recipe for a paella. " + "Create images to go alongside the text as you generate the recipe."}, }, - Role: "user", + Role: genai.RoleUser, }, } diff --git a/genai/image_generation/imggen_mmflash_with_txt.go b/genai/image_generation/imggen_mmflash_with_txt.go index 5013b77f14..6ae08182ed 100644 --- a/genai/image_generation/imggen_mmflash_with_txt.go +++ b/genai/image_generation/imggen_mmflash_with_txt.go @@ -42,7 +42,7 @@ func generateMMFlashWithText(w io.Writer) error { Parts: []*genai.Part{ {Text: "Generate an image of the Eiffel tower with fireworks in the background."}, }, - Role: "user", + Role: genai.RoleUser, }, } diff --git a/genai/live/live_audio_with_txt.go b/genai/live/live_audio_with_txt.go new file mode 100644 index 0000000000..6c729691b7 --- /dev/null +++ b/genai/live/live_audio_with_txt.go @@ -0,0 +1,113 @@ +// 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 live shows how to use the GenAI SDK to generate text with live resources. +package live + +// [START googlegenaisdk_live_audio_with_txt] +import ( + "context" + "fmt" + "io" + "os" + + "google.golang.org/genai" +) + +// generateLiveAudioWithText demonstrates using a live Gemini model +// that performs live audio with text and handles responses. +func generateLiveAudioWithText(w io.Writer) 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.0-flash-live-preview-04-09" + + voiceName := "Aoede" + + config := &genai.LiveConnectConfig{ + ResponseModalities: []genai.Modality{genai.ModalityAudio}, + SpeechConfig: &genai.SpeechConfig{ + VoiceConfig: &genai.VoiceConfig{ + PrebuiltVoiceConfig: &genai.PrebuiltVoiceConfig{ + VoiceName: voiceName, + }, + }, + }, + } + + // Open a live session + session, err := client.Live.Connect(ctx, modelName, config) + if err != nil { + return fmt.Errorf("failed to connect live: %w", err) + } + defer session.Close() + + // Send the text input + textInput := "Hello? Gemini are you there?" + fmt.Fprintf(w, "> %s\n\n", textInput) + + err = session.SendClientContent(genai.LiveClientContentInput{ + Turns: []*genai.Content{ + { + Role: genai.RoleUser, + Parts: []*genai.Part{ + {Text: textInput}, + }, + }, + }, + }) + if err != nil { + return fmt.Errorf("failed to send content: %w", err) + } + + // Receive streaming audio chunks + var audioData []byte + for { + chunk, err := session.Receive() + if err != nil { + if err == io.EOF { + break + } + return fmt.Errorf("error receiving stream: %w", err) + } + + if chunk.ServerContent != nil && chunk.ServerContent.ModelTurn != nil { + for _, part := range chunk.ServerContent.ModelTurn.Parts { + if part.InlineData != nil { + audioData = append(audioData, part.InlineData.Data...) + } + } + } + } + + // Save audio if data received + if len(audioData) > 0 { + audioFile := "output.wav" + if err := os.WriteFile(audioFile, audioData, 0644); err != nil { + return fmt.Errorf("failed to write WAV file: %w", err) + } + + fmt.Fprintf(w, "Received audio answer saved to %s\n", audioFile) + } + + return nil +} + +// [END googlegenaisdk_live_audio_with_txt] diff --git a/genai/live/live_code_exec_with_txt.go b/genai/live/live_code_exec_with_txt.go new file mode 100644 index 0000000000..152e72e912 --- /dev/null +++ b/genai/live/live_code_exec_with_txt.go @@ -0,0 +1,110 @@ +// 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 live shows how to use the GenAI SDK to generate text with live resources. +package live + +// [START googlegenaisdk_live_code_exec_with_txt] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateLiveCodeExecWithTxt demonstrates using a live Gemini model +// that performs code exec with text calls and handles responses. +func generateLiveCodeExecWithTxt(w io.Writer) 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.0-flash-live-preview-04-09" + + config := &genai.LiveConnectConfig{ + ResponseModalities: []genai.Modality{genai.ModalityText}, + Tools: []*genai.Tool{ + { + CodeExecution: &genai.ToolCodeExecution{}, + }, + }, + } + + session, err := client.Live.Connect(ctx, modelName, config) + if err != nil { + return fmt.Errorf("failed to connect live session: %w", err) + } + defer session.Close() + + textInput := "Compute the largest prime palindrome under 10" + fmt.Fprintf(w, "> %s\n\n", textInput) + + err = session.SendClientContent(genai.LiveClientContentInput{ + Turns: []*genai.Content{ + { + Role: genai.RoleUser, + Parts: []*genai.Part{ + {Text: textInput}, + }, + }, + }, + }) + if err != nil { + return fmt.Errorf("failed to send client content: %w", err) + } + + var response string + + // Receive streaming responses + for { + chunk, err := session.Receive() + if err == io.EOF { + break + } + if err != nil { + return fmt.Errorf("error receiving stream: %w", err) + } + + // Handle the main model output + if chunk.ServerContent != nil { + if chunk.ServerContent.ModelTurn != nil { + for _, part := range chunk.ServerContent.ModelTurn.Parts { + if part == nil { + continue + } + if part.ExecutableCode != nil { + fmt.Fprint(w, part.ExecutableCode.Code) + } + if part.CodeExecutionResult != nil { + response += part.CodeExecutionResult.Output + } + } + + } + } + } + // Example output: + // > Compute the largest prime palindrome under 10 + // Final Answer: The final answer is $\boxed{7}$ + fmt.Fprintln(w, response) + return nil +} + +// [END googlegenaisdk_live_code_exec_with_txt] diff --git a/genai/live/live_examples_test.go b/genai/live/live_examples_test.go index f142744dd4..ae905ef8fd 100644 --- a/genai/live/live_examples_test.go +++ b/genai/live/live_examples_test.go @@ -50,6 +50,35 @@ func generateStructuredOutputWithTxtMock(w io.Writer) error { return err } +func generateLiveCodeExecMock(w io.Writer) error { + mockOutput := "Mocked Live Code Exec: final answer is 7" + _, err := fmt.Fprintln(w, mockOutput) + return err +} + +func generateLiveTranscribeWithAudioMock(w io.Writer) error { + mock := `> Hello? Gemini are you there? +Model turn: +Input transcript: hello gemini are you there +Yes, I'm here. What would you like to talk about?` + + _, err := fmt.Fprintln(w, mock) + return err +} + +func generateLiveWithTextMock(w io.Writer) error { + mockOutput := `> Hello? Gemini, are you there? +Yes, I'm here. What would you like to talk about?` + _, err := fmt.Fprintln(w, mockOutput) + return err +} + +func generateLiveAudioWithTextMock(w io.Writer) error { + mockOutput := "Mocked Live Response: Received audio answer saved to..." + _, err := fmt.Fprintln(w, mockOutput) + return err +} + func TestLiveGeneration(t *testing.T) { tc := testutil.SystemTest(t) @@ -96,4 +125,59 @@ func TestLiveGeneration(t *testing.T) { } }) + t.Run("generate live Code Exec with txt", func(t *testing.T) { + buf.Reset() + + err := generateLiveCodeExecMock(buf) + if err != nil { + t.Fatalf("generateLiveCodeExec failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) + + t.Run("generate live transcribe with audio", func(t *testing.T) { + buf.Reset() + + err := generateLiveTranscribeWithAudioMock(buf) + if err != nil { + t.Fatalf("generateLiveTranscribeWithAudio failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) + + t.Run("generate live with text", func(t *testing.T) { + buf.Reset() + + err := generateLiveWithTextMock(buf) + if err != nil { + t.Fatalf("generateLiveWithText failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) + + t.Run("generate live audio with text", func(t *testing.T) { + buf.Reset() + + err := generateLiveAudioWithTextMock(buf) + if err != nil { + t.Fatalf("generateLiveAudioWithText failed: %v", err) + } + + output := buf.String() + if output == "" { + t.Error("expected non-empty output, got empty") + } + }) } diff --git a/genai/live/live_func_call_with_txt.go b/genai/live/live_func_call_with_txt.go index 70533dda48..b0a166ea66 100644 --- a/genai/live/live_func_call_with_txt.go +++ b/genai/live/live_func_call_with_txt.go @@ -67,7 +67,7 @@ func generateLiveFuncCallWithTxt(w io.Writer) error { if err := session.SendClientContent(genai.LiveClientContentInput{ Turns: []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: textInput}, }, diff --git a/genai/live/live_ground_googsearch_with_txt.go b/genai/live/live_ground_googsearch_with_txt.go index ef77d05a70..c443d8849e 100644 --- a/genai/live/live_ground_googsearch_with_txt.go +++ b/genai/live/live_ground_googsearch_with_txt.go @@ -54,7 +54,7 @@ func generateGroundSearchWithTxt(w io.Writer) error { // Send user input userContent := &genai.Content{ - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: textInput}, }, diff --git a/genai/live/live_structured_ouput_with_txt.go b/genai/live/live_structured_ouput_with_txt.go index dff6b56647..e1f35edcc9 100644 --- a/genai/live/live_structured_ouput_with_txt.go +++ b/genai/live/live_structured_ouput_with_txt.go @@ -83,7 +83,7 @@ func generateStructuredOutputWithTxt(w io.Writer) error { }, }, { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: "Alice and Bob are going to a science fair on Friday."}, }, diff --git a/genai/live/live_transcribe_with_audio.go b/genai/live/live_transcribe_with_audio.go new file mode 100644 index 0000000000..bd75c868d5 --- /dev/null +++ b/genai/live/live_transcribe_with_audio.go @@ -0,0 +1,109 @@ +// 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 live shows how to use the GenAI SDK to generate text with live resources. +package live + +// [START googlegenaisdk_live_transcribe_with_audio] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateLiveTranscribeWithAudio demonstrates using a live Gemini model +// that performs live transcribe with audio and handles responses. +func generateLiveTranscribeWithAudio(w io.Writer) 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-live-2.5-flash-preview-native-audio" + + config := &genai.LiveConnectConfig{ + ResponseModalities: []genai.Modality{genai.ModalityAudio}, + InputAudioTranscription: &genai.AudioTranscriptionConfig{}, + OutputAudioTranscription: &genai.AudioTranscriptionConfig{}, + } + + session, err := client.Live.Connect(ctx, modelName, config) + if err != nil { + return fmt.Errorf("failed to connect live session: %w", err) + } + defer session.Close() + + inputText := "Hello? Gemini are you there?" + fmt.Fprintf(w, "> %s\n", inputText) + + err = session.SendClientContent(genai.LiveClientContentInput{ + Turns: []*genai.Content{ + { + Role: genai.RoleUser, + Parts: []*genai.Part{ + {Text: inputText}, + }, + }, + }, + }) + if err != nil { + return fmt.Errorf("failed to send client content: %w", err) + } + + var response string + + for { + message, err := session.Receive() + if err == io.EOF { + break + } + if err != nil { + return fmt.Errorf("error receiving stream: %w", err) + } + + if message.ServerContent != nil { + if message.ServerContent.ModelTurn != nil { + fmt.Fprintf(w, "Model turn: %v\n", message.ServerContent.ModelTurn) + } + + // Input transcription from audio + if message.ServerContent.InputTranscription != nil { + if message.ServerContent.InputTranscription.Text != "" { + fmt.Fprintf(w, "Input transcript: %s\n", + message.ServerContent.InputTranscription.Text) + } + } + + // Output transcription (model generated) + if message.ServerContent.OutputTranscription != nil { + if message.ServerContent.OutputTranscription.Text != "" { + response += message.ServerContent.OutputTranscription.Text + } + } + } + } + // Example output: + // > Hello? Gemini are you there? + // Yes, I'm here. What would you like to talk about? + fmt.Fprintln(w, response) + return nil +} + +// [END googlegenaisdk_live_transcribe_with_audio] diff --git a/genai/live/live_with_txt.go b/genai/live/live_with_txt.go new file mode 100644 index 0000000000..d72447b51d --- /dev/null +++ b/genai/live/live_with_txt.go @@ -0,0 +1,98 @@ +// 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 live shows how to use the GenAI SDK to generate text with live resources. +package live + +// [START googlegenaisdk_live_with_txt] +import ( + "context" + "fmt" + "io" + + "google.golang.org/genai" +) + +// generateLiveWithText demonstrates using a live Gemini model +// that performs live with text and handles responses. +func generateLiveWithText(w io.Writer) 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.0-flash-live-preview-04-09" + + config := &genai.LiveConnectConfig{ + ResponseModalities: []genai.Modality{genai.ModalityText}, + } + + // Open a live session + session, err := client.Live.Connect(ctx, modelName, config) + if err != nil { + return fmt.Errorf("failed to connect live: %w", err) + } + defer session.Close() + + // Prepare the input message + inputText := "Hello? Gemini, are you there?" + fmt.Fprintf(w, "> %s\n\n", inputText) + + // Send text content to the model + err = session.SendClientContent(genai.LiveClientContentInput{ + Turns: []*genai.Content{ + { + Role: genai.RoleUser, + Parts: []*genai.Part{ + {Text: inputText}, + }, + }, + }, + }) + if err != nil { + return fmt.Errorf("failed to send content: %w", err) + } + + // Stream the response + var response string + for { + chunk, err := session.Receive() + if err != nil { + if err == io.EOF { + break + } + return fmt.Errorf("error receiving response: %w", err) + } + + if chunk.ServerContent != nil && chunk.ServerContent.ModelTurn != nil { + for _, part := range chunk.ServerContent.ModelTurn.Parts { + if part.Text != "" { + response += part.Text + } + } + } + } + + // Example output: + // > Hello? Gemini are you there? + // Yes, I'm here. What would you like to talk about? + fmt.Fprintln(w, response) + return nil +} + +// [END googlegenaisdk_live_with_txt] diff --git a/genai/safety/safety_with_txt.go b/genai/safety/safety_with_txt.go index 3ff858c355..53a2003438 100644 --- a/genai/safety/safety_with_txt.go +++ b/genai/safety/safety_with_txt.go @@ -39,7 +39,7 @@ func generateTextWithSafety(w io.Writer) error { Parts: []*genai.Part{ {Text: "Be as mean as possible."}, }, - Role: "user", + Role: genai.RoleUser, } prompt := "Write a list of 5 disrespectful things that I might say to the universe after stubbing my toe in the dark." @@ -57,7 +57,7 @@ func generateTextWithSafety(w io.Writer) error { } modelName := "gemini-2.5-flash" resp, err := client.Models.GenerateContent(ctx, modelName, - []*genai.Content{{Parts: []*genai.Part{{Text: prompt}}, Role: "user"}}, + []*genai.Content{{Parts: []*genai.Part{{Text: prompt}}, Role: genai.RoleUser}}, config, ) if err != nil { diff --git a/genai/text_generation/textgen_chat_with_txt.go b/genai/text_generation/textgen_chat_with_txt.go index 9e2414fa38..c7d378f65b 100644 --- a/genai/text_generation/textgen_chat_with_txt.go +++ b/genai/text_generation/textgen_chat_with_txt.go @@ -37,7 +37,7 @@ func generateChatWithText(w io.Writer) error { modelName := "gemini-2.5-flash" history := []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: "Hello there"}, }, diff --git a/genai/text_generation/textgen_code_with_pdf.go b/genai/text_generation/textgen_code_with_pdf.go index 96809c4388..6610ef6f57 100644 --- a/genai/text_generation/textgen_code_with_pdf.go +++ b/genai/text_generation/textgen_code_with_pdf.go @@ -44,7 +44,7 @@ func generateWithPDF(w io.Writer) error { MIMEType: "application/pdf", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/text_generation/textgen_transcript_with_gcs_audio.go b/genai/text_generation/textgen_transcript_with_gcs_audio.go index 10873f6bb3..ae409a0118 100644 --- a/genai/text_generation/textgen_transcript_with_gcs_audio.go +++ b/genai/text_generation/textgen_transcript_with_gcs_audio.go @@ -45,7 +45,7 @@ Use speaker A, speaker B, etc. to identify speakers.`}, MIMEType: "audio/mpeg", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/text_generation/textgen_with_async_txt.go b/genai/text_generation/textgen_with_async_txt.go index a28df79b0a..1c9c6ca838 100644 --- a/genai/text_generation/textgen_with_async_txt.go +++ b/genai/text_generation/textgen_with_async_txt.go @@ -39,7 +39,7 @@ func generateWithTextAsyncStream(w io.Writer) error { contents := []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: "Compose a song about the adventures of a time-traveling squirrel."}, }, diff --git a/genai/text_generation/textgen_with_gcs_audio.go b/genai/text_generation/textgen_with_gcs_audio.go index 013a7da199..35055a2478 100644 --- a/genai/text_generation/textgen_with_gcs_audio.go +++ b/genai/text_generation/textgen_with_gcs_audio.go @@ -46,7 +46,7 @@ Create a chapter breakdown with timestamps for key sections or topics discussed. MIMEType: "audio/mpeg", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/text_generation/textgen_with_mute_video.go b/genai/text_generation/textgen_with_mute_video.go index 181f348c6e..f6f37d4be2 100644 --- a/genai/text_generation/textgen_with_mute_video.go +++ b/genai/text_generation/textgen_with_mute_video.go @@ -44,7 +44,7 @@ func generateWithMuteVideo(w io.Writer) error { MIMEType: "video/mp4", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/text_generation/textgen_with_pdf.go b/genai/text_generation/textgen_with_pdf.go index b3f772c5ec..36bfd6ffb5 100644 --- a/genai/text_generation/textgen_with_pdf.go +++ b/genai/text_generation/textgen_with_pdf.go @@ -46,7 +46,7 @@ func generateTextWithPDF(w io.Writer) error { MIMEType: "application/pdf", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/text_generation/textgen_with_txt_img.go b/genai/text_generation/textgen_with_txt_img.go index 2e890d69a5..b8eeedc7ba 100644 --- a/genai/text_generation/textgen_with_txt_img.go +++ b/genai/text_generation/textgen_with_txt_img.go @@ -45,7 +45,7 @@ func generateWithTextImage(w io.Writer) error { MIMEType: "image/jpeg", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/text_generation/textgen_with_video.go b/genai/text_generation/textgen_with_video.go index 5c309aa1fc..a20cb245b0 100644 --- a/genai/text_generation/textgen_with_video.go +++ b/genai/text_generation/textgen_with_video.go @@ -46,7 +46,7 @@ Create a chapter breakdown with timestamps for key sections or topics discussed. MIMEType: "video/mp4", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/text_generation/textgen_with_youtube_video.go b/genai/text_generation/textgen_with_youtube_video.go index a867937eb7..21c8daa0d5 100644 --- a/genai/text_generation/textgen_with_youtube_video.go +++ b/genai/text_generation/textgen_with_youtube_video.go @@ -44,7 +44,7 @@ func generateWithYTVideo(w io.Writer) error { MIMEType: "video/mp4", }}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, nil) diff --git a/genai/thinking/thinking_with_txt.go b/genai/thinking/thinking_with_txt.go index 37f2926e78..1f973231a5 100644 --- a/genai/thinking/thinking_with_txt.go +++ b/genai/thinking/thinking_with_txt.go @@ -41,7 +41,7 @@ func generateContentWithTxt(w io.Writer) error { Parts: []*genai.Part{ {Text: "solve x^2 + 4x + 4 = 0"}, }, - Role: "user", + Role: genai.RoleUser, }, } diff --git a/genai/tools/tools_code_exec_with_txt.go b/genai/tools/tools_code_exec_with_txt.go index 7f0e11bb64..3cb9bcf0d9 100644 --- a/genai/tools/tools_code_exec_with_txt.go +++ b/genai/tools/tools_code_exec_with_txt.go @@ -40,7 +40,7 @@ func generateWithCodeExec(w io.Writer) error { {Parts: []*genai.Part{ {Text: prompt}, }, - Role: "user"}, + Role: genai.RoleUser}, } config := &genai.GenerateContentConfig{ Tools: []*genai.Tool{ diff --git a/genai/tools/tools_func_desc_with_txt.go b/genai/tools/tools_func_desc_with_txt.go index 5404898390..bc62af561b 100644 --- a/genai/tools/tools_func_desc_with_txt.go +++ b/genai/tools/tools_func_desc_with_txt.go @@ -60,7 +60,7 @@ func generateWithFuncCall(w io.Writer) error { {Parts: []*genai.Part{ {Text: "What is the weather like in Boston?"}, }, - Role: "user"}, + Role: genai.RoleUser}, } resp, err := client.Models.GenerateContent(ctx, modelName, contents, config) @@ -101,7 +101,7 @@ func generateWithFuncCall(w io.Writer) error { {Parts: []*genai.Part{ {Text: "What is the weather like in Boston?"}, }, - Role: "user"}, + Role: genai.RoleUser}, {Parts: []*genai.Part{ {FunctionCall: funcCall}, }}, diff --git a/genai/tools/tools_google_maps_coordinates_with_txt.go b/genai/tools/tools_google_maps_coordinates_with_txt.go index d002eedd3d..d8c21fe4ac 100644 --- a/genai/tools/tools_google_maps_coordinates_with_txt.go +++ b/genai/tools/tools_google_maps_coordinates_with_txt.go @@ -62,7 +62,7 @@ func generateGoogleMapsCoordinatesWithText(w io.Writer) error { resp, err := client.Models.GenerateContent(ctx, modelName, []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: prompt}, }, diff --git a/genai/tools/tools_google_search_and_urlcontext_with_txt.go b/genai/tools/tools_google_search_and_urlcontext_with_txt.go index e3608d9117..3b3e1a55fa 100644 --- a/genai/tools/tools_google_search_and_urlcontext_with_txt.go +++ b/genai/tools/tools_google_search_and_urlcontext_with_txt.go @@ -61,7 +61,7 @@ func generateGoogleSearchURLContextWithText(w io.Writer) error { // Call the model resp, err := client.Models.GenerateContent(ctx, modelName, []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: prompt}, }, diff --git a/genai/tools/tools_google_search_with_txt.go b/genai/tools/tools_google_search_with_txt.go index 5160e120d9..cd822dcbc1 100644 --- a/genai/tools/tools_google_search_with_txt.go +++ b/genai/tools/tools_google_search_with_txt.go @@ -40,7 +40,7 @@ func generateWithGoogleSearch(w io.Writer) error { {Parts: []*genai.Part{ {Text: "When is the next total solar eclipse in the United States?"}, }, - Role: "user"}, + Role: genai.RoleUser}, } config := &genai.GenerateContentConfig{ Tools: []*genai.Tool{ diff --git a/genai/tools/tools_urlcontext_with_txt.go b/genai/tools/tools_urlcontext_with_txt.go index 63d4038b9f..0664c6816e 100644 --- a/genai/tools/tools_urlcontext_with_txt.go +++ b/genai/tools/tools_urlcontext_with_txt.go @@ -57,7 +57,7 @@ func generateURLContentWithText(w io.Writer) error { // Generate content using the model resp, err := client.Models.GenerateContent(ctx, modelName, []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: prompt}, }, diff --git a/genai/tuning/tuning_examples_test.go b/genai/tuning/tuning_examples_test.go index 56b744527f..4b0dcce8f5 100644 --- a/genai/tuning/tuning_examples_test.go +++ b/genai/tuning/tuning_examples_test.go @@ -80,7 +80,7 @@ func predictWithTunedEndpointMock(w io.Writer, tuningJobName string) error { contents := []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: "Why is the sky blue?"}, }, diff --git a/genai/tuning/tuning_textgen_with_txt.go b/genai/tuning/tuning_textgen_with_txt.go index 2f389e0b06..7fd21c5692 100644 --- a/genai/tuning/tuning_textgen_with_txt.go +++ b/genai/tuning/tuning_textgen_with_txt.go @@ -44,7 +44,7 @@ func predictWithTunedEndpoint(w io.Writer, tuningJobName string) error { contents := []*genai.Content{ { - Role: "user", + Role: genai.RoleUser, Parts: []*genai.Part{ {Text: "Why is the sky blue?"}, },