diff --git a/genai/batch-prediction/batchpredict-embeddings-with-gcs.js b/genai/batch-prediction/batchpredict-embeddings-with-gcs.js new file mode 100644 index 0000000000..161bcd7247 --- /dev/null +++ b/genai/batch-prediction/batchpredict-embeddings-with-gcs.js @@ -0,0 +1,85 @@ +// 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_batchpredict_embeddings_with_gcs] +const {GoogleGenAI} = require('@google/genai'); + +const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT; +const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global'; +const OUTPUT_URI = 'gs://your-bucket/your-prefix'; + +async function runBatchPredictionJob( + outputUri = OUTPUT_URI, + projectId = GOOGLE_CLOUD_PROJECT, + location = GOOGLE_CLOUD_LOCATION +) { + const client = new GoogleGenAI({ + vertexai: true, + project: projectId, + location: location, + httpOptions: { + apiVersion: 'v1', + }, + }); + + // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.batches.Batches.create + let job = await client.batches.create({ + model: 'text-embedding-005', + // Source link: https://storage.cloud.google.com/cloud-samples-data/batch/prompt_for_batch_gemini_predict.jsonl + src: 'gs://cloud-samples-data/generative-ai/embeddings/embeddings_input.jsonl', + config: { + dest: outputUri, + }, + }); + + console.log(`Job name: ${job.name}`); + console.log(`Job state: ${job.state}`); + + // Example response: + // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job state: JOB_STATE_PENDING + + const completedStates = new Set([ + 'JOB_STATE_SUCCEEDED', + 'JOB_STATE_FAILED', + 'JOB_STATE_CANCELLED', + 'JOB_STATE_PAUSED', + ]); + + while (completedStates.has(job.state)) { + await new Promise(resolve => setTimeout(resolve, 30000)); + job = await client.batches.get({name: job.name}); + console.log(`Job state: ${job.state}`); + if (job.state === 'JOB_STATE_FAILED') { + console.log(`Job state: ${job.state}`); + break; + } + } + + // Example response: + // Job state: JOB_STATE_PENDING + // Job state: JOB_STATE_RUNNING + // Job state: JOB_STATE_RUNNING + // ... + // Job state: JOB_STATE_SUCCEEDED + + return job.state; +} +// [END googlegenaisdk_batchpredict_embeddings_with_gcs] + +module.exports = { + runBatchPredictionJob, +}; diff --git a/genai/batch-prediction/batchpredict-with-bq.js b/genai/batch-prediction/batchpredict-with-bq.js new file mode 100644 index 0000000000..9ae9b96307 --- /dev/null +++ b/genai/batch-prediction/batchpredict-with-bq.js @@ -0,0 +1,82 @@ +// 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_batchpredict_with_bq] +const {GoogleGenAI} = require('@google/genai'); + +const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT; +const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global'; +const OUTPUT_URI = 'bq://your-project.your_dataset.your_table'; + +async function runBatchPredictionJob( + outputUri = OUTPUT_URI, + projectId = GOOGLE_CLOUD_PROJECT, + location = GOOGLE_CLOUD_LOCATION +) { + const client = new GoogleGenAI({ + vertexai: true, + project: projectId, + location: location, + httpOptions: { + apiVersion: 'v1', + }, + }); + + // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.batches.Batches.create + let job = await client.batches.create({ + // To use a tuned model, set the model param to your tuned model using the following format: + // model="projects/{PROJECT_ID}/locations/{LOCATION}/models/{MODEL_ID}" + model: 'gemini-2.5-flash', + src: 'bq://storage-samples.generative_ai.batch_requests_for_multimodal_input', + config: { + dest: outputUri, + }, + }); + + console.log(`Job name: ${job.name}`); + console.log(`Job state: ${job.state}`); + + // Example response: + // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job state: JOB_STATE_PENDING + + const completedStates = new Set([ + 'JOB_STATE_SUCCEEDED', + 'JOB_STATE_FAILED', + 'JOB_STATE_CANCELLED', + 'JOB_STATE_PAUSED', + ]); + + while (completedStates.has(job.state)) { + await new Promise(resolve => setTimeout(resolve, 30000)); + job = await client.batches.get({name: job.name}); + console.log(`Job state: ${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 job.state; +} +// [END googlegenaisdk_batchpredict_with_bq] + +module.exports = { + runBatchPredictionJob, +}; diff --git a/genai/batch-prediction/batchpredict-with-gcs.js b/genai/batch-prediction/batchpredict-with-gcs.js new file mode 100644 index 0000000000..c364d6ef46 --- /dev/null +++ b/genai/batch-prediction/batchpredict-with-gcs.js @@ -0,0 +1,83 @@ +// 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_batchpredict_with_gcs] +const {GoogleGenAI} = require('@google/genai'); + +const GOOGLE_CLOUD_PROJECT = process.env.GOOGLE_CLOUD_PROJECT; +const GOOGLE_CLOUD_LOCATION = process.env.GOOGLE_CLOUD_LOCATION || 'global'; +const OUTPUT_URI = 'gs://your-bucket/your-prefix'; + +async function runBatchPredictionJob( + outputUri = OUTPUT_URI, + projectId = GOOGLE_CLOUD_PROJECT, + location = GOOGLE_CLOUD_LOCATION +) { + const client = new GoogleGenAI({ + vertexai: true, + project: projectId, + location: location, + httpOptions: { + apiVersion: 'v1', + }, + }); + + // See the documentation: https://googleapis.github.io/python-genai/genai.html#genai.batches.Batches.create + let job = await client.batches.create({ + // To use a tuned model, set the model param to your tuned model using the following format: + // model="projects/{PROJECT_ID}/locations/{LOCATION}/models/{MODEL_ID}" + model: 'gemini-2.5-flash', + // Source link: https://storage.cloud.google.com/cloud-samples-data/batch/prompt_for_batch_gemini_predict.jsonl + src: 'gs://cloud-samples-data/batch/prompt_for_batch_gemini_predict.jsonl', + config: { + dest: outputUri, + }, + }); + + console.log(`Job name: ${job.name}`); + console.log(`Job state: ${job.state}`); + + // Example response: + // Job name: projects/%PROJECT_ID%/locations/us-central1/batchPredictionJobs/9876453210000000000 + // Job state: JOB_STATE_PENDING + + const completedStates = new Set([ + 'JOB_STATE_SUCCEEDED', + 'JOB_STATE_FAILED', + 'JOB_STATE_CANCELLED', + 'JOB_STATE_PAUSED', + ]); + + while (completedStates.has(job.state)) { + await new Promise(resolve => setTimeout(resolve, 30000)); + job = await client.batches.get({name: job.name}); + console.log(`Job state: ${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 job.state; +} +// [END googlegenaisdk_batchpredict_with_gcs] + +module.exports = { + runBatchPredictionJob, +}; diff --git a/genai/package.json b/genai/package.json index 8713d4595e..910c1b91e7 100644 --- a/genai/package.json +++ b/genai/package.json @@ -13,6 +13,8 @@ "test": "c8 mocha -p -j 2 --timeout 2400000 test/*.test.js test/**/*.test.js" }, "dependencies": { + "@google-cloud/bigquery": "^8.1.1", + "@google-cloud/storage": "^7.17.0", "@google/genai": "1.12.0", "axios": "^1.6.2", "luxon": "^3.7.1", diff --git a/genai/test/batchpredict-embeddings-with-gcs.test.js b/genai/test/batchpredict-embeddings-with-gcs.test.js new file mode 100644 index 0000000000..48e092b240 --- /dev/null +++ b/genai/test/batchpredict-embeddings-with-gcs.test.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'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const {Storage} = require('@google-cloud/storage'); + +const storage = new Storage(); + +const GCS_OUTPUT_BUCKET = 'nodejs-docs-samples-tests'; + +const projectId = process.env.CAIP_PROJECT_ID; +const location = process.env.GOOGLE_CLOUD_LOCATION || 'global'; +const sample = require('../batch-prediction/batchpredict-embeddings-with-gcs'); + +async function gcs_output_uri() { + const dt = new Date(); + const prefix = `text_output/${dt.toISOString()}`; + const fullUri = `gs://${GCS_OUTPUT_BUCKET}/${prefix}`; + + return { + uri: fullUri, + async cleanup() { + const [files] = await storage.bucket(GCS_OUTPUT_BUCKET).getFiles({ + prefix, + }); + for (const file of files) { + await file.delete(); + } + }, + }; +} + +describe('batchpredict-embeddings-with-gcs', () => { + it('should return the batch job state', async function () { + this.timeout(50000); + const gscOutput = gcs_output_uri(); + const gscUri = (await gscOutput).uri; + const output = await sample.runBatchPredictionJob( + gscUri, + projectId, + location + ); + assert.notEqual(output, undefined); + }); +}); diff --git a/genai/test/batchpredict-with-bq.test.js b/genai/test/batchpredict-with-bq.test.js new file mode 100644 index 0000000000..420e7365a4 --- /dev/null +++ b/genai/test/batchpredict-with-bq.test.js @@ -0,0 +1,57 @@ +// 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 {BigQuery} = require('@google-cloud/bigquery'); + +const bigquery = new BigQuery(); + +const BQ_OUTPUT_DATASET = `${process.env.BQ_OUTPUT_DATASET}.gen_ai_batch_prediction`; + +const projectId = process.env.CAIP_PROJECT_ID; +const location = process.env.GOOGLE_CLOUD_LOCATION || 'global'; +const sample = require('../batch-prediction/batchpredict-with-bq'); + +async function bq_output_uri() { + const dt = new Date(); + const tableName = `text_output_${dt.getFullYear()}_${dt.getMonth() + 1}_${dt.getDate()}_T${dt.getHours()}_${dt.getMinutes()}_${dt.getSeconds()}`; + const tableUri = `${BQ_OUTPUT_DATASET}.${tableName}`; + const fullUri = `bq://${tableUri}`; + + return { + uri: fullUri, + async cleanup() { + await bigquery.dataset(BQ_OUTPUT_DATASET).table(tableName).delete({ + ignoreNotFound: true, + }); + }, + }; +} + +describe('batchpredict-with-bq', () => { + it('should return the batch job state', async function () { + this.timeout(50000); + const bqOutput = bq_output_uri(); + const bqUri = (await bqOutput).uri; + const output = await sample.runBatchPredictionJob( + bqUri, + projectId, + location + ); + assert.notEqual(output, undefined); + }); +}); diff --git a/genai/test/batchpredict-with-gcs.test.js b/genai/test/batchpredict-with-gcs.test.js new file mode 100644 index 0000000000..76992bd643 --- /dev/null +++ b/genai/test/batchpredict-with-gcs.test.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'; + +const {assert} = require('chai'); +const {describe, it} = require('mocha'); +const {Storage} = require('@google-cloud/storage'); + +const storage = new Storage(); + +const GCS_OUTPUT_BUCKET = 'nodejs-docs-samples-tests'; + +const projectId = process.env.CAIP_PROJECT_ID; +const location = process.env.GOOGLE_CLOUD_LOCATION || 'global'; +const sample = require('../batch-prediction/batchpredict-with-gcs'); + +async function gcs_output_uri() { + const dt = new Date(); + const prefix = `text_output/${dt.toISOString()}`; + const fullUri = `gs://${GCS_OUTPUT_BUCKET}/${prefix}`; + + return { + uri: fullUri, + async cleanup() { + const [files] = await storage.bucket(GCS_OUTPUT_BUCKET).getFiles({ + prefix, + }); + for (const file of files) { + await file.delete(); + } + }, + }; +} + +describe('batchpredict-with-gcs', () => { + it('should return the batch job state', async function () { + this.timeout(50000); + const gscOutput = gcs_output_uri(); + const gscUri = (await gscOutput).uri; + const output = await sample.runBatchPredictionJob( + gscUri, + projectId, + location + ); + assert.notEqual(output, undefined); + }); +});