From dc9370fa9366bbe1043b75c7688043229b3ba6cb Mon Sep 17 00:00:00 2001 From: "pattishin@google.com" Date: Fri, 1 Dec 2023 18:15:19 -0800 Subject: [PATCH 1/4] feat: initial base for generative-ai --- .github/auto-label.yaml | 1 + .github/workflows/generative-ai-snippets.yaml | 106 ++++++++++++++++++ .../workflows/utils/workflows-secrets.json | 1 + generative-ai/snippets/package.json | 25 +++++ 4 files changed, 133 insertions(+) create mode 100644 .github/workflows/generative-ai-snippets.yaml create mode 100644 generative-ai/snippets/package.json diff --git a/.github/auto-label.yaml b/.github/auto-label.yaml index 2ef6e6a402..450d366f8a 100644 --- a/.github/auto-label.yaml +++ b/.github/auto-label.yaml @@ -45,6 +45,7 @@ path: eventarc: "eventarc" error-reporting: "clouderrorreporting" functions: "cloudfunctions" + generative-ai: "genai" game-servers: "gameservices" healthcare: "healhcare" iam: "iam" diff --git a/.github/workflows/generative-ai-snippets.yaml b/.github/workflows/generative-ai-snippets.yaml new file mode 100644 index 0000000000..1dc64a5b13 --- /dev/null +++ b/.github/workflows/generative-ai-snippets.yaml @@ -0,0 +1,106 @@ +# Copyright 2023 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. + +name: generative-ai-snippets +on: + push: + branches: + - main + paths: + - 'generative-ai/snippets/**' + - '.github/workflows/generative-ai-snippets.yaml' + pull_request: + paths: + - 'generative-ai/snippets/**' + - '.github/workflows/generative-ai-snippets.yaml' + pull_request_target: + types: [labeled] + paths: + - 'generative-ai/snippets/**' + - '.github/workflows/generative-ai-snippets.yaml' + schedule: + - cron: '0 0 * * 0' +jobs: + test: + if: github.event.action != 'labeled' || github.event.label.name == 'actions:force-run' + runs-on: ubuntu-latest + timeout-minutes: 120 + permissions: + contents: 'read' + id-token: 'write' + defaults: + run: + working-directory: 'generative-ai/snippets' + steps: + - uses: actions/checkout@v4.1.0 + with: + ref: ${{github.event.pull_request.head.sha}} + - uses: 'google-github-actions/auth@v1.1.1' + with: + workload_identity_provider: 'projects/1046198160504/locations/global/workloadIdentityPools/github-actions-pool/providers/github-actions-provider' + service_account: 'kokoro-system-test@long-door-651.iam.gserviceaccount.com' + create_credentials_file: 'true' + access_token_lifetime: 600s + - id: secrets + uses: 'google-github-actions/get-secretmanager-secrets@v1' + with: + secrets: |- + caip_id:nodejs-docs-samples-tests/nodejs-docs-samples-ai-platform-caip-project-id + location:nodejs-docs-samples-tests/nodejs-docs-samples-ai-platform-location + - uses: actions/setup-node@v4.0.0 + with: + node-version: 16 + - name: Get npm cache directory + id: npm-cache-dir + shell: bash + run: echo "dir=$(npm config get cache)" >> ${GITHUB_OUTPUT} + - uses: actions/cache@v3 + id: npm-cache + with: + path: ${{ steps.npm-cache-dir.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - name: install repo dependencies + run: npm install + working-directory: . + - name: install directory dependencies + run: npm install + - run: npm run build --if-present + - name: set env vars for scheduled run + if: github.event.action == 'schedule' + run: | + echo "MOCHA_REPORTER_SUITENAME=generative-ai-snippets" >> $GITHUB_ENV + echo "MOCHA_REPORTER_OUTPUT=${{github.run_id}}_sponge_log.xml" >> $GITHUB_ENV + echo "MOCHA_REPORTER=xunit" >> $GITHUB_ENV + - run: npm test + env: + LOCATION: ${{ steps.secrets.outputs.location }} + CAIP_PROJECT_ID: ${{ steps.secrets.outputs.caip_id }} + - name: upload test results for FlakyBot workflow + if: github.event.action == 'schedule' && always() + uses: actions/upload-artifact@v3 + env: + MOCHA_REPORTER_OUTPUT: "${{github.run_id}}_sponge_log.xml" + with: + name: test-results + path: generative-ai/snippets/${{ env.MOCHA_REPORTER_OUTPUT }} + retention-days: 1 + flakybot: + permissions: + contents: 'read' + id-token: 'write' + if: github.event_name == 'schedule' && always() # always() submits logs even if tests fail + uses: ./.github/workflows/flakybot.yaml + needs: [test] diff --git a/.github/workflows/utils/workflows-secrets.json b/.github/workflows/utils/workflows-secrets.json index e426ce37a9..9c816a1f8b 100644 --- a/.github/workflows/utils/workflows-secrets.json +++ b/.github/workflows/utils/workflows-secrets.json @@ -5,5 +5,6 @@ "iam/deny", "security-center/snippets", "storagetransfer", + "generative-ai/snippets", "vision" ] diff --git a/generative-ai/snippets/package.json b/generative-ai/snippets/package.json new file mode 100644 index 0000000000..b1c9614f6c --- /dev/null +++ b/generative-ai/snippets/package.json @@ -0,0 +1,25 @@ +{ + "name": "nodejs-generativeai-samples", + "private": true, + "license": "Apache-2.0", + "author": "Google LLC", + "engines": { + "node": ">=16.0.0" + }, + "files": [ + "*.js" + ], + "scripts": { + "test": "c8 mocha -p -j 2 --timeout 2400000 test/*.js" + }, + "dependencies": { + "@google-cloud/aiplatform": "^3.0.0" + }, + "devDependencies": { + "c8": "^8.0.0", + "chai": "^4.2.0", + "mocha": "^10.0.0", + "uuid": "^9.0.0", + "sinon": "^16.0.0" + } +} From f5e5888dd33bb77cc1a2f87dfc5617305c1ee722 Mon Sep 17 00:00:00 2001 From: "pattishin@google.com" Date: Fri, 1 Dec 2023 18:24:32 -0800 Subject: [PATCH 2/4] # This is a combination of 16 commits. # This is the 1st commit message: refactor: updating codeowners # This is the commit message #2: add chat functions # This is the commit message #3: use correct testing project # This is the commit message #4: refactor: adding system tests + updating corresponding chat samples # This is the commit message #5: add countTokens sample # This is the commit message #6: refactor: adding in region tags, abstracting out mimetype, adding new image ur # This is the commit message #7: refactor: updating gs url in test, fix to args getting passed to sample functions # This is the commit message #8: refactor: resolving file paths in tests, adding wait helper function # This is the commit message #9: add warning about safety concerns # This is the commit message #10: refactor:filling out nonstreamingchat and streamcontent tests # This is the commit message #11: add countTokens test # This is the commit message #12: refactor: filling out more streaming tests # This is the commit message #13: add safety settings test # This is the commit message #14: refactor: adding in stream content and multipart content tests # This is the commit message #15: feat: add new sendMultiModalPromptWithImage sample # This is the commit message #16: refactor: adding region tags --- CODEOWNERS | 1 + generative-ai/snippets/countTokens.js | 52 ++++++++ generative-ai/snippets/index.js | 124 ++++++++++++++++++ generative-ai/snippets/nonStreamingChat.js | 73 +++++++++++ generative-ai/snippets/nonStreamingContent.js | 64 +++++++++ .../snippets/nonStreamingMultipartContent.js | 81 ++++++++++++ generative-ai/snippets/package.json | 10 +- generative-ai/snippets/safetySettings.js | 70 ++++++++++ .../snippets/sendMultiModalPromptWithImage.js | 32 +++++ .../snippets/sendMultiModalPromptWithVideo.js | 32 +++++ generative-ai/snippets/streamChat.js | 53 ++++++++ generative-ai/snippets/streamContent.js | 60 +++++++++ .../snippets/streamMultipartContent.js | 77 +++++++++++ .../snippets/test/countTokens.test.js | 36 +++++ .../snippets/test/nonStreamingChat.test.js | 45 +++++++ .../snippets/test/nonStreamingContent.test.js | 42 ++++++ .../test/nonStreamingMultipartContent.test.js | 42 ++++++ .../snippets/test/safetySettings.test.js | 36 +++++ .../snippets/test/streamChat.test.js | 42 ++++++ .../snippets/test/streamContent.test.js | 42 ++++++ .../test/streamMultipartContent.test.js | 42 ++++++ 21 files changed, 1052 insertions(+), 4 deletions(-) create mode 100644 generative-ai/snippets/countTokens.js create mode 100644 generative-ai/snippets/index.js create mode 100644 generative-ai/snippets/nonStreamingChat.js create mode 100644 generative-ai/snippets/nonStreamingContent.js create mode 100644 generative-ai/snippets/nonStreamingMultipartContent.js create mode 100644 generative-ai/snippets/safetySettings.js create mode 100644 generative-ai/snippets/sendMultiModalPromptWithImage.js create mode 100644 generative-ai/snippets/sendMultiModalPromptWithVideo.js create mode 100644 generative-ai/snippets/streamChat.js create mode 100644 generative-ai/snippets/streamContent.js create mode 100644 generative-ai/snippets/streamMultipartContent.js create mode 100644 generative-ai/snippets/test/countTokens.test.js create mode 100644 generative-ai/snippets/test/nonStreamingChat.test.js create mode 100644 generative-ai/snippets/test/nonStreamingContent.test.js create mode 100644 generative-ai/snippets/test/nonStreamingMultipartContent.test.js create mode 100644 generative-ai/snippets/test/safetySettings.test.js create mode 100644 generative-ai/snippets/test/streamChat.test.js create mode 100644 generative-ai/snippets/test/streamContent.test.js create mode 100644 generative-ai/snippets/test/streamMultipartContent.test.js diff --git a/CODEOWNERS b/CODEOWNERS index 6257ebd48e..d9e0907476 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -50,6 +50,7 @@ monitoring/opencensus @GoogleCloudPlatform/nodejs-samples-reviewers # Data & AI ai-platform @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/nodejs-samples-reviewers +generative-ai @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/nodejs-samples-reviewers automl @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/nodejs-samples-reviewers cloud-language @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/nodejs-samples-reviewers contact-center-insights @GoogleCloudPlatform/dee-data-ai @GoogleCloudPlatform/nodejs-samples-reviewers diff --git a/generative-ai/snippets/countTokens.js b/generative-ai/snippets/countTokens.js new file mode 100644 index 0000000000..a9f75dabbb --- /dev/null +++ b/generative-ai/snippets/countTokens.js @@ -0,0 +1,52 @@ +// Copyright 2023 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. + +const { VertexAI } = require('@google-cloud/vertexai'); + +async function countTokens( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL' +) { + // [START aiplatform_gemini_token_count] + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const location = 'us-central1'; + // const model = 'gemini-pro'; + + // Initialize Vertex with your Cloud project and location + const vertex_ai = new VertexAI({ project: projectId, location: location }); + + // Instantiate the model + const generativeModel = vertex_ai.preview.getGenerativeModel({ + model: model, + }); + + const req = { + contents: [{ role: 'user', parts: [{ text: 'How are you doing today?' }] }], + }; + + const countTokensResp = await generativeModel.countTokens(req); + console.log('count tokens response: ', countTokensResp); + + // [END aiplatform_gemini_token_count] +} + +countTokens(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/generative-ai/snippets/index.js b/generative-ai/snippets/index.js new file mode 100644 index 0000000000..0449960d8e --- /dev/null +++ b/generative-ai/snippets/index.js @@ -0,0 +1,124 @@ +const { + VertexAI, + HarmBlockThreshold, + HarmCategory, +} = require('@google-cloud/vertexai'); + +const project = 'cloud-llm-preview1'; +const location = 'us-central1'; + +// Initialize Vertex with your Cloud project and location +const vertex_ai = new VertexAI({project: project, location: location}); + +// Instantiate the models +const generativeModel = vertex_ai.preview.getGenerativeModel({ + model: 'gemini-pro', + // The following parameters are optional + // They can also be passed to individual content generation requests + safety_settings: [ + { + category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, + }, + ], + generation_config: {max_output_tokens: 256}, +}); + +const generativeVisionModel = vertex_ai.preview.getGenerativeModel({ + model: 'gemini-pro-vision', +}); + +async function streamContentTextOnly() { + const req = { + contents: [{role: 'user', parts: [{text: 'How are you doing today?'}]}], + }; + + const streamingResp = await generativeModel.generateContentStream(req); + + for await (const item of streamingResp.stream) { + console.log('stream chunk:', item); + } + + console.log('aggregated response: ', await streamingResp.response); +} + +async function nonStreamingTextOnly() { + const req = { + contents: [{role: 'user', parts: [{text: 'How are you doing today?'}]}], + }; + + const nonstreamingResp = await generativeModel.generateContent(req); + console.log('non-streaming response: ', await nonstreamingResp.response); +} + +async function countTokens() { + const req = { + contents: [{role: 'user', parts: [{text: 'How are you doing today?'}]}], + }; + + const countTokensResp = await generativeModel.countTokens(req); + console.log('count tokens response: ', countTokensResp); +} + +async function nonStreamingChat() { + const chat = generativeModel.startChat({}); + const result1 = await chat.sendMessage('hello'); + console.log('send message result1: ', result1); + const resp1 = result1.response; + console.log('send message response1: ', resp1); + const result2 = await chat.sendMessage('what day is it today?'); + console.log('result2: ', result2); + const resp2 = result2.response; + console.log('send message response2: ', resp2); + const result3 = await chat.sendMessage('what day is it tomorrow?'); + console.log('result3: ', result3); + const resp3 = result3.response; + console.log('send message response3: ', resp3); +} + +async function streamingChat() { + const chat = generativeModel.startChat({}); + const streamResult1 = await chat.sendMessageStream('hello again'); + console.log('stream result1: ', streamResult1); + const streamResp1 = await streamResult1.response; + console.log('stream send message response1: ', streamResp1); + const streamResult2 = await chat.sendMessageStream('what is the date today?'); + console.log('stream result2: ', streamResult2); + const streamResp2 = await streamResult2.response; + console.log('stream send message response2: ', streamResp2); + const streamResult3 = await chat.sendMessageStream( + 'what is the date tomorrow?' + ); + console.log('stream result3: ', streamResult3); + const streamResp3 = await streamResult3.response; + console.log('stream send message response3: ', streamResp3); +} + +async function multiPartContent() { + const filePart = { + file_data: { + file_uri: 'gs://sararob_imagegeneration_test/kitten.jpeg', + mime_type: 'image/jpeg', + }, + }; + const textPart = {text: 'What is this a picture of?'}; + + const request = { + contents: [{role: 'user', parts: [textPart, filePart]}], + }; + + const generativeVisionModel = vertex_ai.preview.getGenerativeModel({ + model: 'gemini-pro-vision', + }); + + const resp = await generativeVisionModel.generateContentStream(request); + const contentResponse = await resp.response; + console.log(contentResponse.candidates[0].content); +} + +nonStreamingTextOnly(); +streamContentTextOnly(); +countTokens(); +nonStreamingChat(); +streamingChat(); +multiPartContent(); diff --git a/generative-ai/snippets/nonStreamingChat.js b/generative-ai/snippets/nonStreamingChat.js new file mode 100644 index 0000000000..f64503f5e8 --- /dev/null +++ b/generative-ai/snippets/nonStreamingChat.js @@ -0,0 +1,73 @@ +// Copyright 2023 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. + +const {VertexAI} = require('@google-cloud/vertexai'); + +function wait(time) { + return new Promise(resolve => { + setTimeout(resolve, time); + }); +} + +async function createNonStreamingChat( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL' +) { + // TODO: Find better method. Setting delay to give api time to respond, otherwise it will 404 + // await wait(10); + + // [START aiplatform_gemini_multiturn_chat] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const location = 'us-central1'; + + // Initialize Vertex with your Cloud project and location + const vertexAI = new VertexAI({project: projectId, location: location}); + + // Instantiate the model + const generativeModel = vertexAI.preview.getGenerativeModel({ + model: model, + }); + + const chat = generativeModel.startChat({}); + + const chatInput1 = 'Hello'; + console.log(`User: ${chatInput1}`); + + const result1 = await chat.sendMessage(chatInput1); + const response1 = result1.response.candidates[0].content.parts[0].text; + console.log('Chat bot: ', response1); + + const chatInput2 = 'Can you tell me a scientific fun fact?'; + console.log(`User: ${chatInput2}`); + const result2 = await chat.sendMessage(chatInput2); + const response2 = result2.response.candidates[0].content.parts[0].text; + console.log('Chat bot: ', response2); + + const chatInput3 = 'How can I learn more about that?'; + console.log(`User: ${chatInput3}`); + const result3 = await chat.sendMessage(chatInput3); + const response3 = result3.response.candidates[0].content.parts[0].text; + console.log('Chat bot: ', response3); + + // [END aiplatform_gemini_multiturn_chat] +} + +createNonStreamingChat(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); \ No newline at end of file diff --git a/generative-ai/snippets/nonStreamingContent.js b/generative-ai/snippets/nonStreamingContent.js new file mode 100644 index 0000000000..c1b5ff9ea8 --- /dev/null +++ b/generative-ai/snippets/nonStreamingContent.js @@ -0,0 +1,64 @@ +// Copyright 2023 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. + +const {VertexAI} = require('@google-cloud/vertexai'); + +async function createNonStreamingContent( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL' +) { + // [START aiplatform_gemini_function_calling] + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const location = 'us-central1'; + + // Initialize Vertex with your Cloud project and location + const vertexAI = new VertexAI({project: projectId, location: location}); + + // Instantiate the model + const generativeModel = vertexAI.preview.getGenerativeModel({ + model: model, + }); + + const request = { + contents: [{role: 'user', parts: [{text: 'What is Node.js?'}]}], + }; + + console.log('Prompt:'); + console.log(request.contents[0].parts[0].text); + console.log('Non-Streaming Response Text:'); + + // Create the response stream + const responseStream = await generativeModel.generateContentStream(request); + + // Wait for the response stream to complete + const aggregatedResponse = await responseStream.response; + + // Select the text from the response + const fullTextResponse = + aggregatedResponse.candidates[0].content.parts[0].text; + + console.log(fullTextResponse); + + // [END aiplatform_gemini_function_calling] +} + +createNonStreamingContent(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/generative-ai/snippets/nonStreamingMultipartContent.js b/generative-ai/snippets/nonStreamingMultipartContent.js new file mode 100644 index 0000000000..6e26c6ed7d --- /dev/null +++ b/generative-ai/snippets/nonStreamingMultipartContent.js @@ -0,0 +1,81 @@ +// Copyright 2023 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. + +const {VertexAI} = require('@google-cloud/vertexai'); + +async function createNonStreamingMultipartContent( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL', + image = 'gs://generativeai-downloads/images/scones.jpg', + mimeType = 'image/jpeg' +) { + // [START aiplatform_gemini_get_started] + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const location = 'us-central1'; + // const image = 'gs://generativeai-downloads/images/scones.jpg'; // Google Cloud Storage image + // const mimeType = 'image/jpeg'; + + // Initialize Vertex with your Cloud project and location + const vertexAI = new VertexAI({project: projectId, location: location}); + + // Instantiate the model + const generativeVisionModel = vertexAI.preview.getGenerativeModel({ + model: model, + }); + + // For images, the SDK supports both Google Cloud Storage URI and base64 strings + const filePart = { + file_data: { + file_uri: image, + mime_type: mimeType, + }, + }; + + const textPart = { + text: 'Use several paragraphs to describe what is happening in this picture.', + }; + + const request = { + contents: [{role: 'user', parts: [textPart, filePart]}], + }; + + console.log('Prompt Text:'); + console.log(request.contents[0].parts[0].text); + console.log('Non-Streaming Response Text:'); + + // Create the response stream + const responseStream = + await generativeVisionModel.generateContentStream(request); + + // Wait for the response stream to complete + const aggregatedResponse = await responseStream.response; + + // Select the text from the response + const fullTextResponse = + aggregatedResponse.candidates[0].content.parts[0].text; + + console.log(fullTextResponse); + + // [END aiplatform_gemini_get_started] +} + +createNonStreamingMultipartContent(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/generative-ai/snippets/package.json b/generative-ai/snippets/package.json index b1c9614f6c..765acfa217 100644 --- a/generative-ai/snippets/package.json +++ b/generative-ai/snippets/package.json @@ -10,16 +10,18 @@ "*.js" ], "scripts": { - "test": "c8 mocha -p -j 2 --timeout 2400000 test/*.js" + "test": "c8 mocha -p -j 2 --timeout 2400000 test/*.test.js" }, "dependencies": { - "@google-cloud/aiplatform": "^3.0.0" + "@google-cloud/aiplatform": "^3.0.0", + "@google-cloud/vertexai": "github:googleapis/nodejs-vertexai", + "supertest": "^6.3.3" }, "devDependencies": { "c8": "^8.0.0", "chai": "^4.2.0", "mocha": "^10.0.0", - "uuid": "^9.0.0", - "sinon": "^16.0.0" + "sinon": "^16.0.0", + "uuid": "^9.0.0" } } diff --git a/generative-ai/snippets/safetySettings.js b/generative-ai/snippets/safetySettings.js new file mode 100644 index 0000000000..92c6dad687 --- /dev/null +++ b/generative-ai/snippets/safetySettings.js @@ -0,0 +1,70 @@ +// Copyright 2023 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. + +const { VertexAI, HarmCategory, HarmBlockThreshold } = require('@google-cloud/vertexai'); + +async function createStreamContent( +) { + // [START aiplatform_gemini_safety_settings] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + const projectId = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro' + + // Initialize Vertex with your Cloud project and location + const vertexAI = new VertexAI({ project: projectId, location: location }); + + // Instantiate the model + const generativeModel = vertexAI.preview.getGenerativeModel({ + model: model, + // The following parameters are optional + // They can also be passed to individual content generation requests + safety_settings: [ + { + category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, + }, + ], + generation_config: {max_output_tokens: 256}, + }); + + const request = { + contents: [{ role: 'user', parts: [{ text: 'Tell me something dangerous.' }] }], + }; + + console.log('Prompt:'); + console.log(request.contents[0].parts[0].text); + console.log('Streaming Response Text:'); + + // Create the response stream + const responseStream = await generativeModel.generateContentStream(request); + + // Log the text response as it streams + for await (const item of responseStream.stream) { + if (item.candidates[0].finishReason === 'SAFETY') { + console.log('This response stream terminated due to safety concerns.') + } else { + process.stdout.write(item.candidates[0].content.parts[0].text); + } + } + // [END aiplatform_gemini_safety_settings] +} + + +createStreamContent(...process.argv.slice(3)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/generative-ai/snippets/sendMultiModalPromptWithImage.js b/generative-ai/snippets/sendMultiModalPromptWithImage.js new file mode 100644 index 0000000000..f777c68ec0 --- /dev/null +++ b/generative-ai/snippets/sendMultiModalPromptWithImage.js @@ -0,0 +1,32 @@ +// Copyright 2023 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. + +const {VertexAI} = require('@google-cloud/vertexai'); + +async function sendMultiModalPromptWithImage( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL' +) { + // [START aiplatform_gemini_single_turn_multi_image] + + + + // [END aiplatform_gemini_single_turn_multi_image] +} + +sendMultiModalPromptWithImage(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); \ No newline at end of file diff --git a/generative-ai/snippets/sendMultiModalPromptWithVideo.js b/generative-ai/snippets/sendMultiModalPromptWithVideo.js new file mode 100644 index 0000000000..391a1fea9c --- /dev/null +++ b/generative-ai/snippets/sendMultiModalPromptWithVideo.js @@ -0,0 +1,32 @@ +// Copyright 2023 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. + +const {VertexAI} = require('@google-cloud/vertexai'); + +async function sendMultiModalPromptWithImage( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL' +) { + // [START aiplatform_gemini_single_turn_video] + + + + // [END aiplatform_gemini_single_turn_video] +} + +sendMultiModalPromptWithImage(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); \ No newline at end of file diff --git a/generative-ai/snippets/streamChat.js b/generative-ai/snippets/streamChat.js new file mode 100644 index 0000000000..1d02257996 --- /dev/null +++ b/generative-ai/snippets/streamChat.js @@ -0,0 +1,53 @@ +// Copyright 2023 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. + +const {VertexAI} = require('@google-cloud/vertexai'); + +async function createStreamChat( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL' +) { + // [START aiplatform_gemini_multiturn_chat] + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const location = 'us-central1'; + + // Initialize Vertex with your Cloud project and location + const vertexAI = new VertexAI({project: projectId, location: location}); + + // Instantiate the model + const generativeModel = vertexAI.preview.getGenerativeModel({ + model: model, + }); + + const chat = generativeModel.startChat({}); + + const chatInput1 = 'How can I learn more about that?'; + console.log(`User: ${chatInput1}`); + const result1 = await chat.sendMessageStream(chatInput1); + for await (const item of result1.stream) { + console.log(item.candidates[0].content.parts[0].text); + } + + // [END aiplatform_gemini_multiturn_chat] +} + +createStreamChat(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/generative-ai/snippets/streamContent.js b/generative-ai/snippets/streamContent.js new file mode 100644 index 0000000000..17c71ff87b --- /dev/null +++ b/generative-ai/snippets/streamContent.js @@ -0,0 +1,60 @@ +// Copyright 2023 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. + +const {VertexAI} = require('@google-cloud/vertexai'); + +async function createStreamContent( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL' +) { + // [START aiplatform_gemini_function_calling] + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const location = 'us-central1'; + + // Initialize Vertex with your Cloud project and location + const vertexAI = new VertexAI({project: projectId, location: location}); + + // Instantiate the model + const generativeModel = vertexAI.preview.getGenerativeModel({ + model: model, + }); + + const request = { + contents: [{role: 'user', parts: [{text: 'What is Node.js?'}]}], + }; + + console.log('Prompt:'); + console.log(request.contents[0].parts[0].text); + console.log('Streaming Response Text:'); + + // Create the response stream + const responseStream = await generativeModel.generateContentStream(request); + + // Log the text response as it streams + for await (const item of responseStream.stream) { + process.stdout.write(item.candidates[0].content.parts[0].text); + } + + // [END aiplatform_gemini_function_calling] +} + +createStreamContent(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/generative-ai/snippets/streamMultipartContent.js b/generative-ai/snippets/streamMultipartContent.js new file mode 100644 index 0000000000..f75f414dc5 --- /dev/null +++ b/generative-ai/snippets/streamMultipartContent.js @@ -0,0 +1,77 @@ +// Copyright 2023 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. + +const {VertexAI} = require('@google-cloud/vertexai'); + +async function createStreamMultipartContent( + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL', + image = 'gs://generativeai-downloads/images/scones.jpg', + mimeType = 'image/jpeg' +) { + // [START aiplatform_gemini_get_started] + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const location = 'us-central1'; + // const image = 'gs://generativeai-downloads/images/scones.jpg'; // Google Cloud Storage image + // const mimeType = 'image/jpeg'; + + // Initialize Vertex with your Cloud project and location + const vertexAI = new VertexAI({project: projectId, location: location}); + + // Instantiate the model + const generativeVisionModel = vertexAI.preview.getGenerativeModel({ + model: model, + }); + + // For images, the SDK supports both Google Cloud Storage URI and base64 strings + const filePart = { + file_data: { + file_uri: image, + mime_type: mimeType, + }, + }; + + const textPart = { + text: 'Use several paragraphs to describe what is happening in this picture.', + }; + + const request = { + contents: [{role: 'user', parts: [textPart, filePart]}], + }; + + console.log('Prompt Text:'); + console.log(request.contents[0].parts[0].text); + console.log('Streaming Response Text:'); + + // Create the response stream + const responseStream = + await generativeVisionModel.generateContentStream(request); + + // Log the text response as it streams + for await (const item of responseStream.stream) { + process.stdout.write(item.candidates[0].content.parts[0].text); + } + + // [END aiplatform_gemini_get_started] +} + +createStreamMultipartContent(...process.argv.slice(2)).catch(err => { + console.error(err.message); + process.exitCode = 1; +}); diff --git a/generative-ai/snippets/test/countTokens.test.js b/generative-ai/snippets/test/countTokens.test.js new file mode 100644 index 0000000000..df15c3cd3c --- /dev/null +++ b/generative-ai/snippets/test/countTokens.test.js @@ -0,0 +1,36 @@ +// Copyright 2023 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 cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Count tokens', async () => { + const project = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro'; + + it('should count tokens', async () => { + const output = execSync( + `node ./countTokens.js ${project} ${location} ${model}` + ); + + // Expect 6 tokens + assert(output.match('totalTokens: 6')); + }); +}); diff --git a/generative-ai/snippets/test/nonStreamingChat.test.js b/generative-ai/snippets/test/nonStreamingChat.test.js new file mode 100644 index 0000000000..b127e33286 --- /dev/null +++ b/generative-ai/snippets/test/nonStreamingChat.test.js @@ -0,0 +1,45 @@ +// Copyright 2023 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 cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Generative AI NonStreaming Chat', async () => { + const project = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro'; + + it('should create nonstreaming chat and begin the conversation the same in each instance', async () => { + const output = execSync( + `node ./nonStreamingChat.js ${project} ${location} ${model}` + ); + // Split up conversation output + const conversation = output.split('\n'); + + // Ensure that the beginning of the conversation is consistent + assert(conversation[0].match(/User: Hello/)); + assert(conversation[1].match(/Chat bot: Hello! How may I assist you?/)); + assert(conversation[2].match(/User: Can you tell me a scientific fun fact?/)); + assert(conversation[3].match(/Chat bot: Sure, here's a scientific fun fact for you:?/)); + assert(conversation[4] === ''); + + // Assert that user prompts are getting through + assert(output.match(/User: How can I learn more about that?/)); + }); +}); diff --git a/generative-ai/snippets/test/nonStreamingContent.test.js b/generative-ai/snippets/test/nonStreamingContent.test.js new file mode 100644 index 0000000000..2c7ead4e3a --- /dev/null +++ b/generative-ai/snippets/test/nonStreamingContent.test.js @@ -0,0 +1,42 @@ +// Copyright 2023 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 cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Generative AI NonStreaming Content', () => { + const project = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro'; + + it('should create nonstreaming content and begin the conversation the same in each instance', async () => { + const output = execSync( + `node ./nonStreamingContent.js ${project} ${location} ${model}` + ); + // Split up conversation output + const conversation = output.split('\n'); + + // Ensure that the beginning of the conversation is consistent + assert(conversation[0].match(/Prompt:/)); + assert(conversation[1].match(/What is Node.js?/)); + assert(conversation[2].match(/Non-Streaming Response Text:/)); + assert(conversation[3].match(/Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It is designed to build scalable network applications. Node.js runs JavaScript code outside of a browser./)); + assert(conversation[5].match(/Here are some key features of Node.js:/)); + }); +}); diff --git a/generative-ai/snippets/test/nonStreamingMultipartContent.test.js b/generative-ai/snippets/test/nonStreamingMultipartContent.test.js new file mode 100644 index 0000000000..af83187c70 --- /dev/null +++ b/generative-ai/snippets/test/nonStreamingMultipartContent.test.js @@ -0,0 +1,42 @@ +// Copyright 2023 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 cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Generative AI NonStreaming Multipart Content', () => { + const project = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro-vision'; + const image = 'gs://generativeai-downloads/images/scones.jpg'; + + it('should create nonstreaming multipart content and begin the conversation the same in each instance', async () => { + const output = execSync( + `node ./nonStreamingMultipartContent.js ${project} ${location} ${model} ${image}` + ); + // Split up conversation output + const conversation = output.split('\n'); + + // Ensure that the conversation is what we expect for this scone image + assert(conversation[0].match(/Prompt Text:/)); + assert(conversation[1].match(/Use several paragraphs to describe what is happening in this picture./)); + assert(conversation[2].match(/Non-Streaming Response Text:/)); + assert(conversation[3].match(/There are several blueberry scones on a table. They are arranged on a white surface that is covered in blue stains. There is a bowl of blueberries next to the scones. There is a cup of coffee on the table. There are pink flowers on the table. The scones are round and have a crumbly texture. They are topped with blueberries and sugar. The coffee is hot and steaming. The flowers are in bloom and have a sweet fragrance. The table is made of wood and has a rustic appearance. The overall effect of the image is one of beauty and tranquility./)); + }); +}); diff --git a/generative-ai/snippets/test/safetySettings.test.js b/generative-ai/snippets/test/safetySettings.test.js new file mode 100644 index 0000000000..6cf7293395 --- /dev/null +++ b/generative-ai/snippets/test/safetySettings.test.js @@ -0,0 +1,36 @@ +// Copyright 2023 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 cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Safety settings', async () => { + const project = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro'; + + it('should reject a dangerous request', async () => { + const output = execSync( + `node ./safetySettings.js ${project} ${location} ${model}` + ); + + // Expect rejection due to safety concerns + assert(output.match('This response stream terminated due to safety concerns')); + }); +}); diff --git a/generative-ai/snippets/test/streamChat.test.js b/generative-ai/snippets/test/streamChat.test.js new file mode 100644 index 0000000000..26e5c27a9b --- /dev/null +++ b/generative-ai/snippets/test/streamChat.test.js @@ -0,0 +1,42 @@ +// Copyright 2023 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 cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Generative AI Stream Chat', () => { + const project = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro'; + + it('should create stream chat and begin the conversation the same in each instance', async () => { + const output = execSync( + `node ./streamChat.js ${project} ${location} ${model}` + ); + + // Assert that the advice given for learning is what we expect + assert(output.match(/User: How can I learn more about that?/)); + assert(output.match(/**Read books, articles, and reports:**/)); + assert(output.match(/**Attend seminars, workshops, and conferences:**/)); + assert(output.match(/**Take online courses or tutorials:**/)); + assert(output.match(/**Watch documentaries and videos:**/)); + assert(output.match(/**Interview experts:**/)); + assert(output.match(/**Do your own research:**/)); + }); +}); diff --git a/generative-ai/snippets/test/streamContent.test.js b/generative-ai/snippets/test/streamContent.test.js new file mode 100644 index 0000000000..c9c78e50d8 --- /dev/null +++ b/generative-ai/snippets/test/streamContent.test.js @@ -0,0 +1,42 @@ +// Copyright 2023 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 cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Generative AI Stream Content', () => { + const project = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro'; + + it('should create stream content', async () => { + const output = execSync( + `node ./streamContent.js ${project} ${location} ${model}` + ); + // Split up conversation output + const conversation = output.split('\n'); +; + // Ensure that the beginning of the conversation is consistent + assert(conversation[0].match(/Prompt:/)); + assert(conversation[1].match(/What is Node.js?/)); + assert(conversation[2].match(/Streaming Response Text:/)); + assert(conversation[3].match(/Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It is designed to build scalable network applications. Node.js runs JavaScript code outside of a browser./)); + assert(conversation[5].match(/Here are some key features of Node.js:/)); + }); +}); diff --git a/generative-ai/snippets/test/streamMultipartContent.test.js b/generative-ai/snippets/test/streamMultipartContent.test.js new file mode 100644 index 0000000000..939ae2fe8d --- /dev/null +++ b/generative-ai/snippets/test/streamMultipartContent.test.js @@ -0,0 +1,42 @@ +// Copyright 2023 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 cp = require('child_process'); + +const execSync = cmd => cp.execSync(cmd, {encoding: 'utf-8'}); + +describe('Generative AI Stream Multipart Content', () => { + const project = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro-vision'; + const image = 'gs://generativeai-downloads/images/scones.jpg'; + + it('should create stream multipart content', async () => { + const output = execSync( + `node ./streamMultipartContent.js ${project} ${location} ${model} ${image}` + ); + // Split up conversation output + const conversation = output.split('\n'); + + // Ensure that the conversation is what we expect for this scone image + assert(conversation[0].match(/Prompt Text:/)); + assert(conversation[1].match(/Use several paragraphs to describe what is happening in this picture./)); + assert(conversation[2].match(/Streaming Response Text:/)); + assert(conversation[3].match(/scones/)); + }); +}); From adbb42b6f21b2cc3821643acfce155421a963aff Mon Sep 17 00:00:00 2001 From: "pattishin@google.com" Date: Tue, 12 Dec 2023 19:54:23 -0800 Subject: [PATCH 3/4] refactor: updating codeowners add chat functions use correct testing project refactor: adding system tests + updating corresponding chat samples add countTokens sample refactor: adding in region tags, abstracting out mimetype, adding new image ur refactor: updating gs url in test, fix to args getting passed to sample functions refactor: resolving file paths in tests, adding wait helper function add warning about safety concerns refactor:filling out nonstreamingchat and streamcontent tests add countTokens test refactor: filling out more streaming tests add safety settings test refactor: adding in stream content and multipart content tests feat: add new sendMultiModalPromptWithImage sample refactor: adding region tags update to common prompt fix: resolve linting --- generative-ai/snippets/countTokens.js | 62 ++++++------- generative-ai/snippets/nonStreamingChat.js | 10 +-- generative-ai/snippets/nonStreamingContent.js | 6 +- .../snippets/nonStreamingMultipartContent.js | 8 +- generative-ai/snippets/safetySettings.js | 90 ++++++++++--------- .../snippets/sendMultiModalPromptWithImage.js | 13 ++- .../snippets/sendMultiModalPromptWithVideo.js | 7 +- generative-ai/snippets/streamChat.js | 4 +- generative-ai/snippets/streamContent.js | 4 +- .../snippets/streamMultipartContent.js | 6 +- .../snippets/test/countTokens.test.js | 2 +- .../snippets/test/nonStreamingChat.test.js | 11 +-- .../snippets/test/nonStreamingContent.test.js | 10 +-- .../test/nonStreamingMultipartContent.test.js | 10 +-- .../snippets/test/safetySettings.test.js | 4 +- .../snippets/test/streamChat.test.js | 8 +- .../snippets/test/streamContent.test.js | 11 +-- .../test/streamMultipartContent.test.js | 4 +- 18 files changed, 122 insertions(+), 148 deletions(-) diff --git a/generative-ai/snippets/countTokens.js b/generative-ai/snippets/countTokens.js index a9f75dabbb..68847dc62d 100644 --- a/generative-ai/snippets/countTokens.js +++ b/generative-ai/snippets/countTokens.js @@ -12,41 +12,41 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { VertexAI } = require('@google-cloud/vertexai'); +const {VertexAI} = require('@google-cloud/vertexai'); async function countTokens( - projectId = 'PROJECT_ID', - location = 'LOCATION_ID', - model = 'MODEL' + projectId = 'PROJECT_ID', + location = 'LOCATION_ID', + model = 'MODEL' ) { - // [START aiplatform_gemini_token_count] - - /** - * TODO(developer): Uncomment these variables before running the sample. - */ - // const projectId = 'your-project-id'; - // const location = 'us-central1'; - // const model = 'gemini-pro'; - - // Initialize Vertex with your Cloud project and location - const vertex_ai = new VertexAI({ project: projectId, location: location }); - - // Instantiate the model - const generativeModel = vertex_ai.preview.getGenerativeModel({ - model: model, - }); - - const req = { - contents: [{ role: 'user', parts: [{ text: 'How are you doing today?' }] }], - }; - - const countTokensResp = await generativeModel.countTokens(req); - console.log('count tokens response: ', countTokensResp); - - // [END aiplatform_gemini_token_count] + // [START aiplatform_gemini_token_count] + + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const location = 'us-central1'; + // const model = 'gemini-pro'; + + // Initialize Vertex with your Cloud project and location + const vertex_ai = new VertexAI({project: projectId, location: location}); + + // Instantiate the model + const generativeModel = vertex_ai.preview.getGenerativeModel({ + model: model, + }); + + const req = { + contents: [{role: 'user', parts: [{text: 'How are you doing today?'}]}], + }; + + const countTokensResp = await generativeModel.countTokens(req); + console.log('count tokens response: ', countTokensResp); + + // [END aiplatform_gemini_token_count] } countTokens(...process.argv.slice(2)).catch(err => { - console.error(err.message); - process.exitCode = 1; + console.error(err.message); + process.exitCode = 1; }); diff --git a/generative-ai/snippets/nonStreamingChat.js b/generative-ai/snippets/nonStreamingChat.js index f64503f5e8..199c387498 100644 --- a/generative-ai/snippets/nonStreamingChat.js +++ b/generative-ai/snippets/nonStreamingChat.js @@ -16,7 +16,7 @@ const {VertexAI} = require('@google-cloud/vertexai'); function wait(time) { return new Promise(resolve => { - setTimeout(resolve, time); + setTimeout(resolve, time); }); } @@ -27,8 +27,8 @@ async function createNonStreamingChat( ) { // TODO: Find better method. Setting delay to give api time to respond, otherwise it will 404 // await wait(10); - - // [START aiplatform_gemini_multiturn_chat] + + // [START aiplatform_gemini_multiturn_chat] /** * TODO(developer): Uncomment these variables before running the sample. */ @@ -63,11 +63,11 @@ async function createNonStreamingChat( const result3 = await chat.sendMessage(chatInput3); const response3 = result3.response.candidates[0].content.parts[0].text; console.log('Chat bot: ', response3); - + // [END aiplatform_gemini_multiturn_chat] } createNonStreamingChat(...process.argv.slice(2)).catch(err => { console.error(err.message); process.exitCode = 1; -}); \ No newline at end of file +}); diff --git a/generative-ai/snippets/nonStreamingContent.js b/generative-ai/snippets/nonStreamingContent.js index c1b5ff9ea8..21936c9d01 100644 --- a/generative-ai/snippets/nonStreamingContent.js +++ b/generative-ai/snippets/nonStreamingContent.js @@ -19,8 +19,8 @@ async function createNonStreamingContent( location = 'LOCATION_ID', model = 'MODEL' ) { - // [START aiplatform_gemini_function_calling] - + // [START aiplatform_gemini_function_calling] + /** * TODO(developer): Uncomment these variables before running the sample. */ @@ -54,7 +54,7 @@ async function createNonStreamingContent( aggregatedResponse.candidates[0].content.parts[0].text; console.log(fullTextResponse); - + // [END aiplatform_gemini_function_calling] } diff --git a/generative-ai/snippets/nonStreamingMultipartContent.js b/generative-ai/snippets/nonStreamingMultipartContent.js index 6e26c6ed7d..e899886d3e 100644 --- a/generative-ai/snippets/nonStreamingMultipartContent.js +++ b/generative-ai/snippets/nonStreamingMultipartContent.js @@ -21,7 +21,7 @@ async function createNonStreamingMultipartContent( image = 'gs://generativeai-downloads/images/scones.jpg', mimeType = 'image/jpeg' ) { - // [START aiplatform_gemini_get_started] + // [START aiplatform_gemini_get_started] /** * TODO(developer): Uncomment these variables before running the sample. @@ -48,7 +48,7 @@ async function createNonStreamingMultipartContent( }; const textPart = { - text: 'Use several paragraphs to describe what is happening in this picture.', + text: 'what is shown in this image?', }; const request = { @@ -71,8 +71,8 @@ async function createNonStreamingMultipartContent( aggregatedResponse.candidates[0].content.parts[0].text; console.log(fullTextResponse); - - // [END aiplatform_gemini_get_started] + + // [END aiplatform_gemini_get_started] } createNonStreamingMultipartContent(...process.argv.slice(2)).catch(err => { diff --git a/generative-ai/snippets/safetySettings.js b/generative-ai/snippets/safetySettings.js index 92c6dad687..deb3c7f046 100644 --- a/generative-ai/snippets/safetySettings.js +++ b/generative-ai/snippets/safetySettings.js @@ -12,59 +12,61 @@ // See the License for the specific language governing permissions and // limitations under the License. -const { VertexAI, HarmCategory, HarmBlockThreshold } = require('@google-cloud/vertexai'); +const { + VertexAI, + HarmCategory, + HarmBlockThreshold, +} = require('@google-cloud/vertexai'); -async function createStreamContent( -) { - // [START aiplatform_gemini_safety_settings] - /** - * TODO(developer): Uncomment these variables before running the sample. - */ - const projectId = 'cloud-llm-preview1'; - const location = 'us-central1'; - const model = 'gemini-pro' +async function createStreamContent() { + // [START aiplatform_gemini_safety_settings] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + const projectId = 'cloud-llm-preview1'; + const location = 'us-central1'; + const model = 'gemini-pro'; - // Initialize Vertex with your Cloud project and location - const vertexAI = new VertexAI({ project: projectId, location: location }); + // Initialize Vertex with your Cloud project and location + const vertexAI = new VertexAI({project: projectId, location: location}); - // Instantiate the model - const generativeModel = vertexAI.preview.getGenerativeModel({ - model: model, - // The following parameters are optional - // They can also be passed to individual content generation requests - safety_settings: [ - { - category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, - threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, - }, - ], - generation_config: {max_output_tokens: 256}, - }); + // Instantiate the model + const generativeModel = vertexAI.preview.getGenerativeModel({ + model: model, + // The following parameters are optional + // They can also be passed to individual content generation requests + safety_settings: [ + { + category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, + threshold: HarmBlockThreshold.BLOCK_LOW_AND_ABOVE, + }, + ], + generation_config: {max_output_tokens: 256}, + }); - const request = { - contents: [{ role: 'user', parts: [{ text: 'Tell me something dangerous.' }] }], - }; + const request = { + contents: [{role: 'user', parts: [{text: 'Tell me something dangerous.'}]}], + }; - console.log('Prompt:'); - console.log(request.contents[0].parts[0].text); - console.log('Streaming Response Text:'); + console.log('Prompt:'); + console.log(request.contents[0].parts[0].text); + console.log('Streaming Response Text:'); - // Create the response stream - const responseStream = await generativeModel.generateContentStream(request); + // Create the response stream + const responseStream = await generativeModel.generateContentStream(request); - // Log the text response as it streams - for await (const item of responseStream.stream) { - if (item.candidates[0].finishReason === 'SAFETY') { - console.log('This response stream terminated due to safety concerns.') - } else { - process.stdout.write(item.candidates[0].content.parts[0].text); - } + // Log the text response as it streams + for await (const item of responseStream.stream) { + if (item.candidates[0].finishReason === 'SAFETY') { + console.log('This response stream terminated due to safety concerns.'); + } else { + process.stdout.write(item.candidates[0].content.parts[0].text); } - // [END aiplatform_gemini_safety_settings] + } + // [END aiplatform_gemini_safety_settings] } - createStreamContent(...process.argv.slice(3)).catch(err => { - console.error(err.message); - process.exitCode = 1; + console.error(err.message); + process.exitCode = 1; }); diff --git a/generative-ai/snippets/sendMultiModalPromptWithImage.js b/generative-ai/snippets/sendMultiModalPromptWithImage.js index f777c68ec0..f9d1d486a4 100644 --- a/generative-ai/snippets/sendMultiModalPromptWithImage.js +++ b/generative-ai/snippets/sendMultiModalPromptWithImage.js @@ -19,14 +19,11 @@ async function sendMultiModalPromptWithImage( location = 'LOCATION_ID', model = 'MODEL' ) { - // [START aiplatform_gemini_single_turn_multi_image] - - - - // [END aiplatform_gemini_single_turn_multi_image] + // [START aiplatform_gemini_single_turn_multi_image] + // [END aiplatform_gemini_single_turn_multi_image] } sendMultiModalPromptWithImage(...process.argv.slice(2)).catch(err => { - console.error(err.message); - process.exitCode = 1; -}); \ No newline at end of file + console.error(err.message); + process.exitCode = 1; +}); diff --git a/generative-ai/snippets/sendMultiModalPromptWithVideo.js b/generative-ai/snippets/sendMultiModalPromptWithVideo.js index 391a1fea9c..a7564c7855 100644 --- a/generative-ai/snippets/sendMultiModalPromptWithVideo.js +++ b/generative-ai/snippets/sendMultiModalPromptWithVideo.js @@ -19,14 +19,11 @@ async function sendMultiModalPromptWithImage( location = 'LOCATION_ID', model = 'MODEL' ) { - // [START aiplatform_gemini_single_turn_video] - - - + // [START aiplatform_gemini_single_turn_video] // [END aiplatform_gemini_single_turn_video] } sendMultiModalPromptWithImage(...process.argv.slice(2)).catch(err => { console.error(err.message); process.exitCode = 1; -}); \ No newline at end of file +}); diff --git a/generative-ai/snippets/streamChat.js b/generative-ai/snippets/streamChat.js index 1d02257996..b28536129c 100644 --- a/generative-ai/snippets/streamChat.js +++ b/generative-ai/snippets/streamChat.js @@ -19,7 +19,7 @@ async function createStreamChat( location = 'LOCATION_ID', model = 'MODEL' ) { - // [START aiplatform_gemini_multiturn_chat] + // [START aiplatform_gemini_multiturn_chat] /** * TODO(developer): Uncomment these variables before running the sample. @@ -43,7 +43,7 @@ async function createStreamChat( for await (const item of result1.stream) { console.log(item.candidates[0].content.parts[0].text); } - + // [END aiplatform_gemini_multiturn_chat] } diff --git a/generative-ai/snippets/streamContent.js b/generative-ai/snippets/streamContent.js index 17c71ff87b..6f2ed3e2bc 100644 --- a/generative-ai/snippets/streamContent.js +++ b/generative-ai/snippets/streamContent.js @@ -20,7 +20,7 @@ async function createStreamContent( model = 'MODEL' ) { // [START aiplatform_gemini_function_calling] - + /** * TODO(developer): Uncomment these variables before running the sample. */ @@ -50,7 +50,7 @@ async function createStreamContent( for await (const item of responseStream.stream) { process.stdout.write(item.candidates[0].content.parts[0].text); } - + // [END aiplatform_gemini_function_calling] } diff --git a/generative-ai/snippets/streamMultipartContent.js b/generative-ai/snippets/streamMultipartContent.js index f75f414dc5..aa816baf92 100644 --- a/generative-ai/snippets/streamMultipartContent.js +++ b/generative-ai/snippets/streamMultipartContent.js @@ -22,7 +22,7 @@ async function createStreamMultipartContent( mimeType = 'image/jpeg' ) { // [START aiplatform_gemini_get_started] - + /** * TODO(developer): Uncomment these variables before running the sample. */ @@ -48,7 +48,7 @@ async function createStreamMultipartContent( }; const textPart = { - text: 'Use several paragraphs to describe what is happening in this picture.', + text: 'what is shown in this image?', }; const request = { @@ -67,7 +67,7 @@ async function createStreamMultipartContent( for await (const item of responseStream.stream) { process.stdout.write(item.candidates[0].content.parts[0].text); } - + // [END aiplatform_gemini_get_started] } diff --git a/generative-ai/snippets/test/countTokens.test.js b/generative-ai/snippets/test/countTokens.test.js index df15c3cd3c..d168b26fe5 100644 --- a/generative-ai/snippets/test/countTokens.test.js +++ b/generative-ai/snippets/test/countTokens.test.js @@ -30,7 +30,7 @@ describe('Count tokens', async () => { `node ./countTokens.js ${project} ${location} ${model}` ); - // Expect 6 tokens + // Expect 6 tokens assert(output.match('totalTokens: 6')); }); }); diff --git a/generative-ai/snippets/test/nonStreamingChat.test.js b/generative-ai/snippets/test/nonStreamingChat.test.js index b127e33286..24ffe5a58b 100644 --- a/generative-ai/snippets/test/nonStreamingChat.test.js +++ b/generative-ai/snippets/test/nonStreamingChat.test.js @@ -29,17 +29,10 @@ describe('Generative AI NonStreaming Chat', async () => { const output = execSync( `node ./nonStreamingChat.js ${project} ${location} ${model}` ); - // Split up conversation output - const conversation = output.split('\n'); // Ensure that the beginning of the conversation is consistent - assert(conversation[0].match(/User: Hello/)); - assert(conversation[1].match(/Chat bot: Hello! How may I assist you?/)); - assert(conversation[2].match(/User: Can you tell me a scientific fun fact?/)); - assert(conversation[3].match(/Chat bot: Sure, here's a scientific fun fact for you:?/)); - assert(conversation[4] === ''); - - // Assert that user prompts are getting through + assert(output.match(/User: Hello/)); + assert(output.match(/User: Can you tell me a scientific fun fact?/)); assert(output.match(/User: How can I learn more about that?/)); }); }); diff --git a/generative-ai/snippets/test/nonStreamingContent.test.js b/generative-ai/snippets/test/nonStreamingContent.test.js index 2c7ead4e3a..51134de8b2 100644 --- a/generative-ai/snippets/test/nonStreamingContent.test.js +++ b/generative-ai/snippets/test/nonStreamingContent.test.js @@ -29,14 +29,10 @@ describe('Generative AI NonStreaming Content', () => { const output = execSync( `node ./nonStreamingContent.js ${project} ${location} ${model}` ); - // Split up conversation output - const conversation = output.split('\n'); // Ensure that the beginning of the conversation is consistent - assert(conversation[0].match(/Prompt:/)); - assert(conversation[1].match(/What is Node.js?/)); - assert(conversation[2].match(/Non-Streaming Response Text:/)); - assert(conversation[3].match(/Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It is designed to build scalable network applications. Node.js runs JavaScript code outside of a browser./)); - assert(conversation[5].match(/Here are some key features of Node.js:/)); + assert(output.match(/Prompt:/)); + assert(output.match(/What is Node.js/)); + assert(output.match(/Non-Streaming Response Text:/)); }); }); diff --git a/generative-ai/snippets/test/nonStreamingMultipartContent.test.js b/generative-ai/snippets/test/nonStreamingMultipartContent.test.js index af83187c70..5e0888bb86 100644 --- a/generative-ai/snippets/test/nonStreamingMultipartContent.test.js +++ b/generative-ai/snippets/test/nonStreamingMultipartContent.test.js @@ -30,13 +30,11 @@ describe('Generative AI NonStreaming Multipart Content', () => { const output = execSync( `node ./nonStreamingMultipartContent.js ${project} ${location} ${model} ${image}` ); - // Split up conversation output - const conversation = output.split('\n'); // Ensure that the conversation is what we expect for this scone image - assert(conversation[0].match(/Prompt Text:/)); - assert(conversation[1].match(/Use several paragraphs to describe what is happening in this picture./)); - assert(conversation[2].match(/Non-Streaming Response Text:/)); - assert(conversation[3].match(/There are several blueberry scones on a table. They are arranged on a white surface that is covered in blue stains. There is a bowl of blueberries next to the scones. There is a cup of coffee on the table. There are pink flowers on the table. The scones are round and have a crumbly texture. They are topped with blueberries and sugar. The coffee is hot and steaming. The flowers are in bloom and have a sweet fragrance. The table is made of wood and has a rustic appearance. The overall effect of the image is one of beauty and tranquility./)); + assert(output.match(/Prompt Text:/)); + assert(output.match(/what is shown in this image/)); + assert(output.match(/Non-Streaming Response Text:/)); + assert(output.match(/scone/)); }); }); diff --git a/generative-ai/snippets/test/safetySettings.test.js b/generative-ai/snippets/test/safetySettings.test.js index 6cf7293395..265def1791 100644 --- a/generative-ai/snippets/test/safetySettings.test.js +++ b/generative-ai/snippets/test/safetySettings.test.js @@ -31,6 +31,8 @@ describe('Safety settings', async () => { ); // Expect rejection due to safety concerns - assert(output.match('This response stream terminated due to safety concerns')); + assert( + output.match('This response stream terminated due to safety concerns') + ); }); }); diff --git a/generative-ai/snippets/test/streamChat.test.js b/generative-ai/snippets/test/streamChat.test.js index 26e5c27a9b..823fe6ccce 100644 --- a/generative-ai/snippets/test/streamChat.test.js +++ b/generative-ai/snippets/test/streamChat.test.js @@ -31,12 +31,6 @@ describe('Generative AI Stream Chat', () => { ); // Assert that the advice given for learning is what we expect - assert(output.match(/User: How can I learn more about that?/)); - assert(output.match(/**Read books, articles, and reports:**/)); - assert(output.match(/**Attend seminars, workshops, and conferences:**/)); - assert(output.match(/**Take online courses or tutorials:**/)); - assert(output.match(/**Watch documentaries and videos:**/)); - assert(output.match(/**Interview experts:**/)); - assert(output.match(/**Do your own research:**/)); + assert(output.match(/User: How can I learn more about that/)); }); }); diff --git a/generative-ai/snippets/test/streamContent.test.js b/generative-ai/snippets/test/streamContent.test.js index c9c78e50d8..769b68372e 100644 --- a/generative-ai/snippets/test/streamContent.test.js +++ b/generative-ai/snippets/test/streamContent.test.js @@ -29,14 +29,9 @@ describe('Generative AI Stream Content', () => { const output = execSync( `node ./streamContent.js ${project} ${location} ${model}` ); - // Split up conversation output - const conversation = output.split('\n'); -; // Ensure that the beginning of the conversation is consistent - assert(conversation[0].match(/Prompt:/)); - assert(conversation[1].match(/What is Node.js?/)); - assert(conversation[2].match(/Streaming Response Text:/)); - assert(conversation[3].match(/Node.js is a JavaScript runtime built on Chrome's V8 JavaScript engine. It is designed to build scalable network applications. Node.js runs JavaScript code outside of a browser./)); - assert(conversation[5].match(/Here are some key features of Node.js:/)); + assert(output.match(/Prompt:/)); + assert(output.match(/What is Node.js/)); + assert(output.match(/Streaming Response Text:/)); }); }); diff --git a/generative-ai/snippets/test/streamMultipartContent.test.js b/generative-ai/snippets/test/streamMultipartContent.test.js index 939ae2fe8d..d9b4fb061a 100644 --- a/generative-ai/snippets/test/streamMultipartContent.test.js +++ b/generative-ai/snippets/test/streamMultipartContent.test.js @@ -31,11 +31,11 @@ describe('Generative AI Stream Multipart Content', () => { `node ./streamMultipartContent.js ${project} ${location} ${model} ${image}` ); // Split up conversation output - const conversation = output.split('\n'); + const conversation = output.split('\n'); // Ensure that the conversation is what we expect for this scone image assert(conversation[0].match(/Prompt Text:/)); - assert(conversation[1].match(/Use several paragraphs to describe what is happening in this picture./)); + assert(conversation[1].match(/what is shown in this image/)); assert(conversation[2].match(/Streaming Response Text:/)); assert(conversation[3].match(/scones/)); }); From 080d94b51cea43e0bcf594328215a6faa82c13f3 Mon Sep 17 00:00:00 2001 From: "pattishin@google.com" Date: Tue, 12 Dec 2023 19:57:03 -0800 Subject: [PATCH 4/4] refactor: remove index file --- generative-ai/snippets/index.js | 124 -------------------------------- 1 file changed, 124 deletions(-) delete mode 100644 generative-ai/snippets/index.js diff --git a/generative-ai/snippets/index.js b/generative-ai/snippets/index.js deleted file mode 100644 index 0449960d8e..0000000000 --- a/generative-ai/snippets/index.js +++ /dev/null @@ -1,124 +0,0 @@ -const { - VertexAI, - HarmBlockThreshold, - HarmCategory, -} = require('@google-cloud/vertexai'); - -const project = 'cloud-llm-preview1'; -const location = 'us-central1'; - -// Initialize Vertex with your Cloud project and location -const vertex_ai = new VertexAI({project: project, location: location}); - -// Instantiate the models -const generativeModel = vertex_ai.preview.getGenerativeModel({ - model: 'gemini-pro', - // The following parameters are optional - // They can also be passed to individual content generation requests - safety_settings: [ - { - category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT, - threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE, - }, - ], - generation_config: {max_output_tokens: 256}, -}); - -const generativeVisionModel = vertex_ai.preview.getGenerativeModel({ - model: 'gemini-pro-vision', -}); - -async function streamContentTextOnly() { - const req = { - contents: [{role: 'user', parts: [{text: 'How are you doing today?'}]}], - }; - - const streamingResp = await generativeModel.generateContentStream(req); - - for await (const item of streamingResp.stream) { - console.log('stream chunk:', item); - } - - console.log('aggregated response: ', await streamingResp.response); -} - -async function nonStreamingTextOnly() { - const req = { - contents: [{role: 'user', parts: [{text: 'How are you doing today?'}]}], - }; - - const nonstreamingResp = await generativeModel.generateContent(req); - console.log('non-streaming response: ', await nonstreamingResp.response); -} - -async function countTokens() { - const req = { - contents: [{role: 'user', parts: [{text: 'How are you doing today?'}]}], - }; - - const countTokensResp = await generativeModel.countTokens(req); - console.log('count tokens response: ', countTokensResp); -} - -async function nonStreamingChat() { - const chat = generativeModel.startChat({}); - const result1 = await chat.sendMessage('hello'); - console.log('send message result1: ', result1); - const resp1 = result1.response; - console.log('send message response1: ', resp1); - const result2 = await chat.sendMessage('what day is it today?'); - console.log('result2: ', result2); - const resp2 = result2.response; - console.log('send message response2: ', resp2); - const result3 = await chat.sendMessage('what day is it tomorrow?'); - console.log('result3: ', result3); - const resp3 = result3.response; - console.log('send message response3: ', resp3); -} - -async function streamingChat() { - const chat = generativeModel.startChat({}); - const streamResult1 = await chat.sendMessageStream('hello again'); - console.log('stream result1: ', streamResult1); - const streamResp1 = await streamResult1.response; - console.log('stream send message response1: ', streamResp1); - const streamResult2 = await chat.sendMessageStream('what is the date today?'); - console.log('stream result2: ', streamResult2); - const streamResp2 = await streamResult2.response; - console.log('stream send message response2: ', streamResp2); - const streamResult3 = await chat.sendMessageStream( - 'what is the date tomorrow?' - ); - console.log('stream result3: ', streamResult3); - const streamResp3 = await streamResult3.response; - console.log('stream send message response3: ', streamResp3); -} - -async function multiPartContent() { - const filePart = { - file_data: { - file_uri: 'gs://sararob_imagegeneration_test/kitten.jpeg', - mime_type: 'image/jpeg', - }, - }; - const textPart = {text: 'What is this a picture of?'}; - - const request = { - contents: [{role: 'user', parts: [textPart, filePart]}], - }; - - const generativeVisionModel = vertex_ai.preview.getGenerativeModel({ - model: 'gemini-pro-vision', - }); - - const resp = await generativeVisionModel.generateContentStream(request); - const contentResponse = await resp.response; - console.log(contentResponse.candidates[0].content); -} - -nonStreamingTextOnly(); -streamContentTextOnly(); -countTokens(); -nonStreamingChat(); -streamingChat(); -multiPartContent();