diff --git a/genai/embeddings/embeddings-docretrieval-with-txt.js b/genai/embeddings/embeddings-docretrieval-with-txt.js new file mode 100644 index 0000000000..3c7a70af17 --- /dev/null +++ b/genai/embeddings/embeddings-docretrieval-with-txt.js @@ -0,0 +1,59 @@ +// 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. + +'use strict'; + +// [START googlegenaisdk_embeddings_docretrieval_with_txt] +const {GoogleGenAI} = require('@google/genai'); + +const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT; + +async function generateEmbeddingsForRetrieval( + projectId = GOOGLE_CLOUD_PROJECT +) { + const client = new GoogleGenAI({ + vertexai: true, + project: projectId, + }); + + const prompt = [ + "How do I get a driver's license/learner's permit?", + "How long is my driver's license valid for?", + "Driver's knowledge test study guide", + ]; + + const response = await client.models.embedContent({ + model: 'gemini-embedding-001', + contents: prompt, + config: { + taskType: 'RETRIEVAL_DOCUMENT', // Optional + outputDimensionality: 3072, // Optional + title: "Driver's License", // Optional + }, + }); + + console.log(response); + + // Example response: + // embeddings=[ContentEmbedding(values=[-0.06302902102470398, 0.00928034819662571, 0.014716853387653828, -0.028747491538524628, ... ], + // statistics=ContentEmbeddingStatistics(truncated=False, token_count=13.0))] + // metadata=EmbedContentMetadata(billable_character_count=112) + + return response; +} +// [END googlegenaisdk_embeddings_docretrieval_with_txt] + +module.exports = { + generateEmbeddingsForRetrieval, +}; diff --git a/genai/express-mode/api-key-example.js b/genai/express-mode/api-key-example.js new file mode 100644 index 0000000000..4cfc91e2f9 --- /dev/null +++ b/genai/express-mode/api-key-example.js @@ -0,0 +1,43 @@ +// 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. + +'use strict'; + +// [START googlegenaisdk_vertexai_express_mode] +const {GoogleGenAI} = require('@google/genai'); +const API_KEY = 'PUT HERE YOUR API KEY'; + +async function generateWithApiKey(apiKey = API_KEY) { + const client = new GoogleGenAI({ + vertexai: true, + apiKey: apiKey, + }); + + const response = await client.models.generateContentStream({ + model: 'gemini-2.5-flash', + contents: 'Explain bubble sort to me.', + }); + + console.log(response.text); + + // Example response: + // Bubble Sort is a simple sorting algorithm that repeatedly steps through the list + + return response; +} +// [END googlegenaisdk_vertexai_express_mode] + +module.exports = { + generateWithApiKey, +}; diff --git a/genai/output-folder/bw-example-image.png b/genai/output-folder/bw-example-image.png index 5972631e07..a2210daa1a 100644 Binary files a/genai/output-folder/bw-example-image.png and b/genai/output-folder/bw-example-image.png differ diff --git a/genai/output-folder/image.png b/genai/output-folder/image.png index 0f4827197a..3d9abc609a 100644 Binary files a/genai/output-folder/image.png and b/genai/output-folder/image.png differ diff --git a/genai/package.json b/genai/package.json index 9231c39c94..f7fe00f198 100644 --- a/genai/package.json +++ b/genai/package.json @@ -15,10 +15,11 @@ "dependencies": { "@google/genai": "1.30.0", "axios": "^1.6.2", + "luxon": "^3.7.2", + "node-fetch": "^2.7.0", + "openai": "^6.9.1", "canvas": "^3.2.0", "google-auth-library": "^10.3.0", - "luxon": "^3.7.1", - "openai": "^5.19.1", "proxyquire": "^2.1.3", "supertest": "^7.0.0" }, diff --git a/genai/provisioned-throughput/provisionedthroughput-with-txt.js b/genai/provisioned-throughput/provisionedthroughput-with-txt.js new file mode 100644 index 0000000000..6463284272 --- /dev/null +++ b/genai/provisioned-throughput/provisionedthroughput-with-txt.js @@ -0,0 +1,62 @@ +// 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. + +'use strict'; + +// [START googlegenaisdk_provisionedthroughput_with_txt] +const {GoogleGenAI} = require('@google/genai'); + +const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT; +const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global'; + +async function generateWithProvisionedThroughput( + projectId = GOOGLE_CLOUD_PROJECT, + location = GOOGLE_CLOUD_LOCATION +) { + const client = new GoogleGenAI({ + vertexai: true, + project: projectId, + location: location, + httpOptions: { + apiVersion: 'v1', + headers: { + // Options: + // - "dedicated": Use Provisioned Throughput + // - "shared": Use pay-as-you-go + // https://cloud.google.com/vertex-ai/generative-ai/docs/use-provisioned-throughput + 'X-Vertex-AI-LLM-Request-Type': 'shared', + }, + }, + }); + + const response = await client.models.generateContent({ + model: 'gemini-2.5-flash', + contents: 'How does AI work?', + }); + + console.log(response.text); + + // Example response: + // Okay, let's break down how AI works. It's a broad field, so I'll focus on the ... + // Here's a simplified overview: + // ... + + return response.text; +} + +// [END googlegenaisdk_provisionedthroughput_with_txt] + +module.exports = { + generateWithProvisionedThroughput, +}; diff --git a/genai/safety/safety-with-txt.js b/genai/safety/safety-with-txt.js new file mode 100644 index 0000000000..94390cdc8f --- /dev/null +++ b/genai/safety/safety-with-txt.js @@ -0,0 +1,115 @@ +// 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. + +'use strict'; + +// [START googlegenaisdk_safety_with_txt] +const {GoogleGenAI} = require('@google/genai'); + +const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT; +const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global'; + +async function generateWithSafetySettings( + projectId = GOOGLE_CLOUD_PROJECT, + location = GOOGLE_CLOUD_LOCATION +) { + const client = new GoogleGenAI({ + vertexai: true, + project: projectId, + location: location, + }); + + const systemInstruction = 'Be as mean as possible.'; + + const prompt = + 'Write a list of 5 disrespectful things that I might say to the universe after stubbing my toe in the dark.'; + + const safetySettings = [ + { + category: 'HARM_CATEGORY_DANGEROUS_CONTENT', + threshold: 'BLOCK_LOW_AND_ABOVE', + }, + { + category: 'HARM_CATEGORY_HARASSMENT', + threshold: 'BLOCK_LOW_AND_ABOVE', + }, + { + category: 'HARM_CATEGORY_HATE_SPEECH', + threshold: 'BLOCK_LOW_AND_ABOVE', + }, + { + category: 'HARM_CATEGORY_SEXUALLY_EXPLICIT', + threshold: 'BLOCK_LOW_AND_ABOVE', + }, + ]; + + const response = await client.models.generateContent({ + model: 'gemini-2.5-flash', + contents: prompt, + config: { + systemInstruction: systemInstruction, + safetySettings: safetySettings, + }, + }); + + // console.log(response.text); + // console.log(response.candidates[0].finishMessage); + // + // for (const each of response.candidates[0].safetyRatings) { + // console.log('\nCategory:', String(each.category)); + // console.log('Is Blocked:', each.blocked); + // console.log('Probability:', each.probability); + // console.log('Probability Score:', each.probabilityScore); + // console.log('Severity:', each.severity); + // console.log('Severity Score:', each.severityScore); + // } + + // Example response: + // + // Category: HarmCategory.HARM_CATEGORY_HATE_SPEECH + // Is Blocked: False + // Probability: HarmProbability.NEGLIGIBLE + // Probability Score: 2.547714e-05 + // Severity: HarmSeverity.HARM_SEVERITY_NEGLIGIBLE + // Severity Score: None + // + // Category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT + // Is Blocked: False + // Probability: HarmProbability.NEGLIGIBLE + // Probability Score: 3.6103818e-06 + // Severity: HarmSeverity.HARM_SEVERITY_NEGLIGIBLE + // Severity Score: None + // + // Category: HarmCategory.HARM_CATEGORY_HARASSMENT + // Is Blocked: True + // Probability: HarmProbability.MEDIUM + // Probability Score: 0.71599233 + // Severity: HarmSeverity.HARM_SEVERITY_MEDIUM + // Severity Score: 0.30782545 + // + // Category: HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT + // Is Blocked: False + // Probability: HarmProbability.NEGLIGIBLE + // Probability Score: 1.5624657e-05 + // Severity: HarmSeverity.HARM_SEVERITY_NEGLIGIBLE + // Severity Score: None + + return response; +} + +// [END googlegenaisdk_safety_with_txt] + +module.exports = { + generateWithSafetySettings, +}; diff --git a/genai/test/api-key-example.test.js b/genai/test/api-key-example.test.js new file mode 100644 index 0000000000..8b5aa71456 --- /dev/null +++ b/genai/test/api-key-example.test.js @@ -0,0 +1,53 @@ +// 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. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const {delay} = require('./util'); +const proxyquire = require('proxyquire').noCallThru(); + +describe('vertexai-express-mode', () => { + it('should call generateContentStream and return the mocked response', async function () { + this.timeout(10000); + + this.retries(4); + await delay(this.test); + + const mockGenerateContentStreamResult = { + text: 'Bubble sort works by repeatedly swapping adjacent elements until sorted.', + }; + + class MockModels { + async generateContentStream() { + return mockGenerateContentStreamResult; + } + } + + class MockGoogleGenAI { + constructor() { + this.models = new MockModels(); + } + } + + const sample = proxyquire('../express-mode/api-key-example.js', { + '@google/genai': {GoogleGenAI: MockGoogleGenAI}, + }); + + const response = await sample.generateWithApiKey('FAKE_API_KEY'); + + assert.strictEqual(response.text, mockGenerateContentStreamResult.text); + }); +}); diff --git a/genai/test/embeddings-docretrieval-with-txt.test.js b/genai/test/embeddings-docretrieval-with-txt.test.js new file mode 100644 index 0000000000..57fbbc0d59 --- /dev/null +++ b/genai/test/embeddings-docretrieval-with-txt.test.js @@ -0,0 +1,31 @@ +// 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. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); + +const projectId = process.env.CAIP_PROJECT_ID; +const sample = require('../embeddings/embeddings-docretrieval-with-txt.js'); +const {delay} = require('./util'); + +describe('embeddings-docretrieval-with-txt', () => { + it('should return an object containing embeddings and metadata', async function () { + this.retries(4); + await delay(this.test); + const result = await sample.generateEmbeddingsForRetrieval(projectId); + assert.containsAllKeys(result, ['embeddings', 'metadata']); + }); +}); diff --git a/genai/test/imggen-mmflash-edit-img-with-txt-img.test.js b/genai/test/imggen-mmflash-edit-img-with-txt-img.test.js index c5a04b53a8..2bb52ec962 100644 --- a/genai/test/imggen-mmflash-edit-img-with-txt-img.test.js +++ b/genai/test/imggen-mmflash-edit-img-with-txt-img.test.js @@ -28,6 +28,7 @@ describe('imggen-mmflash-edit-img-with-txt-img', async () => { this.retries(4); await delay(this.test); const response = await sample.generateImage(projectId, location); + console.log(response); assert(response); }); }); diff --git a/genai/test/provisionedthroughput-with-txt.test.js b/genai/test/provisionedthroughput-with-txt.test.js new file mode 100644 index 0000000000..c78b0bddb2 --- /dev/null +++ b/genai/test/provisionedthroughput-with-txt.test.js @@ -0,0 +1,35 @@ +// 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. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); + +const projectId = process.env.CAIP_PROJECT_ID; +const sample = require('../provisioned-throughput/provisionedthroughput-with-txt.js'); +const {delay} = require('./util'); + +describe('provisioned-throughput-with-txt', () => { + it('should return provisioned throughput result', async function () { + this.timeout(50000); + this.retries(4); + + await delay(this.test); + + const output = await sample.generateWithProvisionedThroughput(projectId); + + assert(output.length > 0); + }); +}); diff --git a/genai/test/safety-with-txt.test.js b/genai/test/safety-with-txt.test.js new file mode 100644 index 0000000000..926a608be1 --- /dev/null +++ b/genai/test/safety-with-txt.test.js @@ -0,0 +1,33 @@ +// 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. + +'use strict'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); + +const projectId = process.env.CAIP_PROJECT_ID; +const sample = require('../safety/safety-with-txt.js'); +const {delay} = require('./util'); + +describe('safety-with-txt', () => { + it('should call generateContentStream with safety instructions', async function () { + this.timeout(50000); + this.retries(4); + await delay(this.test); + const output = await sample.generateWithSafetySettings(projectId); + console.log('output', output); + assert.isObject(output); + }); +}); diff --git a/genai/test/tools-google-search-with-txt.test.js b/genai/test/tools-google-search-with-txt.test.js index 7d3dd2fd40..e1f2da4d1f 100644 --- a/genai/test/tools-google-search-with-txt.test.js +++ b/genai/test/tools-google-search-with-txt.test.js @@ -22,7 +22,7 @@ const sample = require('../tools/tools-google-search-with-txt.js'); describe('tools-google-search-with-txt', () => { it('should generate answer to a question in prompt using google search', async function () { - this.timeout(10000); + this.timeout(100000); const output = await sample.generateGoogleSearch(projectId); assert(output.length > 0); });