Skip to content
159 changes: 159 additions & 0 deletions genai/bounding-box/boundingbox-with-txt-img.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// 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_boundingbox_with_txt_img]
const {GoogleGenAI} = require('@google/genai');

const {createCanvas, loadImage} = require('canvas');
const fetch = require('node-fetch');
const fs = require('fs');

const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT;
const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global';

async function fetchImageAsBase64(uri) {
const response = await fetch(uri);
const buffer = await response.buffer();
return buffer.toString('base64');
}

async function plotBoundingBoxes(imageUri, boundingBoxes) {
console.log('Creating bounding boxes');
const image = await loadImage(imageUri);
const canvas = createCanvas(image.width, image.height);
const ctx = canvas.getContext('2d');

ctx.drawImage(image, 0, 0);

const colors = ['red', 'blue', 'green', 'orange'];

boundingBoxes.forEach((bbox, i) => {
const [yMin, xMin, yMax, xMax] = bbox.box_2d;

const absYMin = Math.floor((yMin / 1000) * image.height);
const absXMin = Math.floor((xMin / 1000) * image.width);
const absYMax = Math.floor((yMax / 1000) * image.height);
const absXMax = Math.floor((xMax / 1000) * image.width);

ctx.strokeStyle = colors[i % colors.length];
ctx.lineWidth = 4;
ctx.strokeRect(absXMin, absYMin, absXMax - absXMin, absYMax - absYMin);

ctx.fillStyle = colors[i % colors.length];
ctx.font = '20px Arial';
ctx.fillText(bbox.label, absXMin + 8, absYMin + 20);
});

fs.writeFileSync('output.png', canvas.toBuffer('image/png'));
console.log('Saved output to file: output.png');
}

async function createBoundingBox(
projectId = GOOGLE_CLOUD_PROJECT,
location = GOOGLE_CLOUD_LOCATION
) {
const client = new GoogleGenAI({
vertexai: true,
project: projectId,
location: location,
});

const systemInstruction = `
Return bounding boxes as an array with labels.
Never return masks. Limit to 25 objects.
If an object is present multiple times, give each object a unique label
according to its distinct characteristics (colors, size, position, etc.).
`;

const safetySettings = [
{
category: 'HARM_CATEGORY_DANGEROUS_CONTENT',
threshold: 'BLOCK_ONLY_HIGH',
},
];

const imageUri =
'https://storage.googleapis.com/generativeai-downloads/images/socks.jpg';
const base64Image = await fetchImageAsBase64(imageUri);

const boundingBoxSchema = {
type: 'ARRAY',
description: 'List of bounding boxes for detected objects',
items: {
type: 'OBJECT',
title: 'BoundingBox',
description: 'Represents a bounding box with coordinates and label',
properties: {
box_2d: {
type: 'ARRAY',
description:
'Bounding box coordinates in format [y_min, x_min, y_max, x_max]',
items: {
type: 'INTEGER',
format: 'int32',
},
minItems: '4',
maxItems: '4',
},
label: {
type: 'STRING',
description: 'Label describing the object within the bounding box',
},
},
required: ['box_2d', 'label'],
},
};

const response = await client.models.generateContent({
model: 'gemini-2.5-flash',
contents: [
{
role: 'user',
parts: [
{
text: 'Output the positions of the socks with a face. Label according to position in the image.',
},
{
inlineData: {
data: base64Image,
mimeType: 'image/jpeg',
},
},
],
},
],
config: {
systemInstruction: systemInstruction,
safetySettings: safetySettings,
responseMimeType: 'application/json',
temperature: 0.5,
responseSchema: boundingBoxSchema,
},
});

const candidate = response.candidates[0].content.parts[0].text;
const boundingBoxes = JSON.parse(candidate);

console.log('Bounding boxes:', boundingBoxes);

await plotBoundingBoxes(imageUri, boundingBoxes);
return boundingBoxes;
}
// [END googlegenaisdk_boundingbox_with_txt_img]

module.exports = {
createBoundingBox,
};
56 changes: 56 additions & 0 deletions genai/embeddings/embeddings-docretrieval-with-txt.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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(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,
};
43 changes: 43 additions & 0 deletions genai/express-mode/api-key-example.js
Original file line number Diff line number Diff line change
@@ -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,
};
14 changes: 5 additions & 9 deletions genai/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,18 @@
"test": "c8 mocha -p -j 2 --timeout 2400000 test/*.test.js test/**/*.test.js"
},
"dependencies": {
"@google/genai": "1.20.0",
"@google/genai": "^0.13.0",
"axios": "^1.6.2",
"google-auth-library": "^10.3.0",
"luxon": "^3.7.1",
"proxyquire": "^2.1.3",
"node-fetch": "^3.3.2",
"openai": "^5.19.1",
"supertest": "^7.0.0"
},
"devDependencies": {
"c8": "^10.0.0",
"chai": "^4.5.0",
"mocha": "^10.0.0",
"node-fetch": "^3.3.2",
"proxyquire": "^2.1.3",
"sinon": "^18.0.0",
"uuid": "^10.0.0"
"uuid": "^10.0.0",
"proxyquire": "^2.1.3",
"canvas": "^3.1.0",
"node-fetch": "^2.7.0"
}
}
62 changes: 62 additions & 0 deletions genai/provisioned-throughput/provisionedthroughput-with-txt.js
Original file line number Diff line number Diff line change
@@ -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,
};
Loading