diff --git a/model-armor/snippets/createTemplate.js b/model-armor/snippets/createTemplate.js new file mode 100644 index 0000000000..43010db2f0 --- /dev/null +++ b/model-armor/snippets/createTemplate.js @@ -0,0 +1,86 @@ +// 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'; + +/** + * Creates a Model Armor template with Responsible AI (RAI) filters. + * + * This function creates a template that can be used for sanitizing user prompts and model responses. + * + * @param {string} projectId - Google Cloud project ID where the template will be created. + * @param {string} locationId - Google Cloud location (region) for the template, e.g., 'us-central1'. + * @param {string} templateId - Unique identifier for the new template. + */ +async function createTemplate(projectId, locationId, templateId) { + // [START modelarmor_create_template] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'your-template-id'; + + const parent = `projects/${projectId}/locations/${locationId}`; + + // Imports the Model Armor library + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + const {protos} = modelarmor; + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + /** Build the Model Armor template with your preferred filters. + For more details on filters, please refer to the following doc: + https://cloud.google.com/security-command-center/docs/key-concepts-model-armor#ma-filters + */ + const templateConfig = { + filterConfig: { + raiSettings: { + raiFilters: [ + { + filterType: + protos.google.cloud.modelarmor.v1.RaiFilterType.HATE_SPEECH, + confidenceLevel: + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel.HIGH, + }, + { + filterType: + protos.google.cloud.modelarmor.v1.RaiFilterType.SEXUALLY_EXPLICIT, + confidenceLevel: + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel + .MEDIUM_AND_ABOVE, + }, + ], + }, + }, + }; + + // Construct request + const request = { + parent, + templateId, + template: templateConfig, + }; + + // Create the template + const [response] = await client.createTemplate(request); + return response; + // [END modelarmor_create_template] +} + +module.exports = createTemplate; diff --git a/model-armor/snippets/createTemplateWithAdvancedSdp.js b/model-armor/snippets/createTemplateWithAdvancedSdp.js new file mode 100644 index 0000000000..cef66edfaa --- /dev/null +++ b/model-armor/snippets/createTemplateWithAdvancedSdp.js @@ -0,0 +1,123 @@ +// 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'; + +/** + * Creates a new model armor template with advanced SDP settings enabled. + * + * @param {string} projectId - Google Cloud project ID where the template will be created. + * @param {string} locationId - Google Cloud location where the template will be created. + * @param {string} templateId - ID for the template to create. + * @param {string} inspectTemplate - Optional. Sensitive Data Protection inspect template resource name. + If only inspect template is provided (de-identify template + not provided), then Sensitive Data Protection InspectContent + action is performed during Sanitization. All Sensitive Data + Protection findings identified during inspection will be + returned as SdpFinding in SdpInsepctionResult e.g. + `organizations/{organization}/inspectTemplates/{inspect_template}`, + `projects/{project}/inspectTemplates/{inspect_template}` + `organizations/{organization}/locations/{location}/inspectTemplates/{inspect_template}` + `projects/{project}/locations/{location}/inspectTemplates/{inspect_template}` + * @param {string} deidentifyTemplate - Optional. Optional Sensitive Data Protection Deidentify template resource name. + If provided then DeidentifyContent action is performed + during Sanitization using this template and inspect + template. The De-identified data will be returned in + SdpDeidentifyResult. Note that all info-types present in the + deidentify template must be present in inspect template. + e.g. + `organizations/{organization}/deidentifyTemplates/{deidentify_template}`, + `projects/{project}/deidentifyTemplates/{deidentify_template}` + `organizations/{organization}/locations/{location}/deidentifyTemplates/{deidentify_template}` + `projects/{project}/locations/{location}/deidentifyTemplates/{deidentify_template}` + */ +async function createTemplateWithAdvancedSdp( + projectId, + locationId, + templateId, + inspectTemplate, + deidentifyTemplate +) { + // [START modelarmor_create_template_with_advanced_sdp] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'template-id'; + // const inspectTemplate = `projects/${projectId}/locations/${locationId}/inspectTemplates/inspect-template-id`; + // const deidentifyTemplate = `projects/${projectId}/locations/${locationId}/deidentifyTemplates/deidentify-template-id`; + + const parent = `projects/${projectId}/locations/${locationId}`; + + // Imports the Model Armor library + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + const {protos} = modelarmor; + + const RaiFilterType = protos.google.cloud.modelarmor.v1.RaiFilterType; + const DetectionConfidenceLevel = + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel; + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + // Configuration for the template with advanced SDP settings + const templateConfig = { + filterConfig: { + raiSettings: { + raiFilters: [ + { + filterType: RaiFilterType.DANGEROUS, + confidenceLevel: DetectionConfidenceLevel.HIGH, + }, + { + filterType: RaiFilterType.HARASSMENT, + confidenceLevel: DetectionConfidenceLevel.MEDIUM_AND_ABOVE, + }, + { + filterType: RaiFilterType.HATE_SPEECH, + confidenceLevel: DetectionConfidenceLevel.HIGH, + }, + { + filterType: RaiFilterType.SEXUALLY_EXPLICIT, + confidenceLevel: DetectionConfidenceLevel.HIGH, + }, + ], + }, + sdpSettings: { + advancedConfig: { + inspectTemplate: inspectTemplate, + deidentifyTemplate: deidentifyTemplate, + }, + }, + }, + }; + + // Construct request + const request = { + parent, + templateId, + template: templateConfig, + }; + + // Create the template + const [response] = await client.createTemplate(request); + return response; + // [END modelarmor_create_template_with_advanced_sdp] +} + +module.exports = createTemplateWithAdvancedSdp; diff --git a/model-armor/snippets/createTemplateWithBasicSdp.js b/model-armor/snippets/createTemplateWithBasicSdp.js new file mode 100644 index 0000000000..33ba1850e5 --- /dev/null +++ b/model-armor/snippets/createTemplateWithBasicSdp.js @@ -0,0 +1,94 @@ +// 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'; + +/** + * Creates a new model armor template with basic SDP settings enabled. + * + * @param {string} projectId - Google Cloud project ID where the template will be created. + * @param {string} locationId - Google Cloud location where the template will be created. + * @param {string} templateId - ID for the template to create. + */ +async function createTemplateWithBasicSdp(projectId, locationId, templateId) { + // [START modelarmor_create_template_with_basic_sdp] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'template-id'; + + const parent = `projects/${projectId}/locations/${locationId}`; + + // Imports the Model Armor library + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + const {protos} = modelarmor; + + const RaiFilterType = protos.google.cloud.modelarmor.v1.RaiFilterType; + const DetectionConfidenceLevel = + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel; + const SdpBasicConfigEnforcement = + protos.google.cloud.modelarmor.v1.SdpBasicConfig.SdpBasicConfigEnforcement; + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + // Configuration for the template with basic SDP settings + const templateConfig = { + filterConfig: { + raiSettings: { + raiFilters: [ + { + filterType: RaiFilterType.DANGEROUS, + confidenceLevel: DetectionConfidenceLevel.HIGH, + }, + { + filterType: RaiFilterType.HARASSMENT, + confidenceLevel: DetectionConfidenceLevel.MEDIUM_AND_ABOVE, + }, + { + filterType: RaiFilterType.HATE_SPEECH, + confidenceLevel: DetectionConfidenceLevel.HIGH, + }, + { + filterType: RaiFilterType.SEXUALLY_EXPLICIT, + confidenceLevel: DetectionConfidenceLevel.HIGH, + }, + ], + }, + sdpSettings: { + basicConfig: { + filterEnforcement: SdpBasicConfigEnforcement.ENABLED, + }, + }, + }, + }; + + // Construct request + const request = { + parent, + templateId, + template: templateConfig, + }; + + const [response] = await client.createTemplate(request); + return response; + // [END modelarmor_create_template_with_basic_sdp] +} + +module.exports = createTemplateWithBasicSdp; diff --git a/model-armor/snippets/createTemplateWithLabels.js b/model-armor/snippets/createTemplateWithLabels.js new file mode 100644 index 0000000000..610081fa4c --- /dev/null +++ b/model-armor/snippets/createTemplateWithLabels.js @@ -0,0 +1,92 @@ +// 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'; + +/** + * Creates a Model Armor template with Responsible AI (RAI) filters and custom labels. + * + * @param {string} projectId - Google Cloud project ID where the template will be created. + * @param {string} locationId - Google Cloud location (region) for the template, e.g., 'us-central1'. + * @param {string} templateId - Unique identifier for the new template. + * @param {string} labelKey - The key for the label to add to the template. + * @param {string} labelValue - The value for the label. + */ +async function createTemplateWithLabels( + projectId, + locationId, + templateId, + labelKey, + labelValue +) { + // [START modelarmor_create_template_with_labels] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'your-template-id'; + // const labelKey = 'environment'; + // const labelValue = 'production'; + + const parent = `projects/${projectId}/locations/${locationId}`; + + // Imports the Model Armor library + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + const {protos} = modelarmor; + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + // Construct the request with template configuration and labels + const request = { + parent, + templateId, + template: { + filterConfig: { + raiSettings: { + raiFilters: [ + { + filterType: + protos.google.cloud.modelarmor.v1.RaiFilterType.HATE_SPEECH, + confidenceLevel: + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel.HIGH, + }, + { + filterType: + protos.google.cloud.modelarmor.v1.RaiFilterType + .SEXUALLY_EXPLICIT, + confidenceLevel: + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel + .MEDIUM_AND_ABOVE, + }, + ], + }, + }, + labels: { + [labelKey]: labelValue, + }, + }, + }; + + // Create the template + const [response] = await client.createTemplate(request); + return response; + // [END modelarmor_create_template_with_labels] +} + +module.exports = createTemplateWithLabels; diff --git a/model-armor/snippets/createTemplateWithMetadata.js b/model-armor/snippets/createTemplateWithMetadata.js new file mode 100644 index 0000000000..d1e182eb4d --- /dev/null +++ b/model-armor/snippets/createTemplateWithMetadata.js @@ -0,0 +1,87 @@ +// 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'; + +/** + * Creates a new model armor template with template metadata. + * + * @param {string} projectId - Google Cloud project ID where the template will be created. + * @param {string} locationId - Google Cloud location where the template will be created. + * @param {string} templateId - ID for the template to create. + */ +async function createTemplateWithMetadata(projectId, locationId, templateId) { + // [START modelarmor_create_template_with_metadata] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'template-id'; + + const parent = `projects/${projectId}/locations/${locationId}`; + + // Imports the Model Armor library + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + const {protos} = modelarmor; + + const RaiFilterType = protos.google.cloud.modelarmor.v1.RaiFilterType; + const DetectionConfidenceLevel = + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel; + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + /** Add template metadata to the template. + * For more details on template metadata, please refer to the following doc: + * https://cloud.google.com/security-command-center/docs/reference/model-armor/rest/v1/projects.locations.templates#templatemetadata + */ + const templateConfig = { + filterConfig: { + raiSettings: { + raiFilters: [ + { + filterType: RaiFilterType.HATE_SPEECH, + confidenceLevel: DetectionConfidenceLevel.HIGH, + }, + { + filterType: RaiFilterType.SEXUALLY_EXPLICIT, + confidenceLevel: DetectionConfidenceLevel.MEDIUM_AND_ABOVE, + }, + ], + }, + }, + templateMetadata: { + ignorePartialInvocationFailures: true, + logSanitizeOperations: true, + }, + }; + + // Construct request + const request = { + parent, + templateId, + template: templateConfig, + }; + + // Create the template + const [response] = await client.createTemplate(request); + return response; + // [END modelarmor_create_template_with_metadata] +} + +module.exports = createTemplateWithMetadata; diff --git a/model-armor/snippets/deleteTemplate.js b/model-armor/snippets/deleteTemplate.js new file mode 100644 index 0000000000..8bcabc1e55 --- /dev/null +++ b/model-armor/snippets/deleteTemplate.js @@ -0,0 +1,50 @@ +// 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'; + +/** + * Deletes a Model Armor template. + * + * @param {string} projectId - Google Cloud project ID where the template exists. + * @param {string} locationId - Google Cloud location (region) of the template, e.g., 'us-central1'. + * @param {string} templateId - Identifier of the template to delete. + */ +async function deleteTemplate(projectId, locationId, templateId) { + // [START modelarmor_delete_template] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const locationId = 'us-central1'; + // const templateId = 'my-template'; + + const name = `projects/${projectId}/locations/${locationId}/templates/${templateId}`; + + // Imports the Model Armor library + const {ModelArmorClient} = require('@google-cloud/modelarmor'); + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + const response = await client.deleteTemplate({ + name: name, + }); + return response; + // [END modelarmor_delete_template] +} + +module.exports = deleteTemplate; diff --git a/model-armor/snippets/getTemplate.js b/model-armor/snippets/getTemplate.js new file mode 100644 index 0000000000..3f82094fee --- /dev/null +++ b/model-armor/snippets/getTemplate.js @@ -0,0 +1,53 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +/** + * Retrieves a Model Armor template by its ID. + * + * @param {string} projectId - Google Cloud project ID where the template exists. + * @param {string} locationId - Google Cloud location (region) of the template. + * @param {string} templateId - Identifier of the template to retrieve. + */ +async function getTemplate(projectId, locationId, templateId) { + // [START modelarmor_get_template] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'my-project'; + // const locationId = 'my-location'; + // const templateId = 'my-template'; + + const name = `projects/${projectId}/locations/${locationId}/templates/${templateId}`; + + // Imports the Model Armor library + const {ModelArmorClient} = require('@google-cloud/modelarmor').v1; + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + const request = { + name: name, + }; + + // Run request + const [response] = await client.getTemplate(request); + return response; + // [END modelarmor_get_template] +} + +module.exports = getTemplate; diff --git a/model-armor/snippets/listTemplates.js b/model-armor/snippets/listTemplates.js new file mode 100644 index 0000000000..0a348262a6 --- /dev/null +++ b/model-armor/snippets/listTemplates.js @@ -0,0 +1,56 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +'use strict'; + +/** + * Lists all Model Armor templates in a specified project and location. + * + * @param {string} projectId - Google Cloud project ID to list templates from. + * @param {string} locationId - Google Cloud location (region) to list templates from. + */ +async function listTemplates(projectId, locationId) { + // [START modelarmor_list_templates] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'YOUR_PROJECT_ID'; + // const locationId = 'us-central1'; + + const parent = `projects/${projectId}/locations/${locationId}`; + + // Imports the Model Armor library + const {ModelArmorClient} = require('@google-cloud/modelarmor'); + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + const request = { + parent: parent, + }; + + // Run request and collect all results + const templates = []; + const iterable = client.listTemplatesAsync(request); + for await (const template of iterable) { + templates.push(template); + } + + return templates; + // [END modelarmor_list_templates] +} + +module.exports = listTemplates; diff --git a/model-armor/snippets/listTemplatesWithFilter.js b/model-armor/snippets/listTemplatesWithFilter.js new file mode 100644 index 0000000000..64910720c5 --- /dev/null +++ b/model-armor/snippets/listTemplatesWithFilter.js @@ -0,0 +1,60 @@ +// 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'; + +/** + * Lists Model Armor templates that match a specific filter criteria. + * + * @param {string} projectId - Google Cloud project ID to list templates from. + * @param {string} locationId - Google Cloud location (region) to list templates from, e.g., 'us-central1'. + * @param {string} templateId - Template ID to filter by. Only templates with this ID will be returned. + */ +async function listTemplatesWithFilter(projectId, locationId, templateId) { + // [START modelarmor_list_templates_with_filter] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'your-location-id'; + // const templateId = 'your-template-id'; + + const parent = `projects/${projectId}/locations/${locationId}`; + + // Imports the Model Armor library + const {ModelArmorClient} = require('@google-cloud/modelarmor').v1; + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + const request = { + parent: parent, + filter: `name="${parent}/templates/${templateId}"`, + }; + + // Run request and collect all results + const templates = []; + const iterable = await client.listTemplatesAsync(request); + + for await (const template of iterable) { + templates.push(template); + } + + return templates; + // [END modelarmor_list_templates_with_filter] +} + +module.exports = listTemplatesWithFilter; diff --git a/model-armor/snippets/updateTemplate.js b/model-armor/snippets/updateTemplate.js new file mode 100644 index 0000000000..b7edf2dc67 --- /dev/null +++ b/model-armor/snippets/updateTemplate.js @@ -0,0 +1,74 @@ +// 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'; + +/** + * Updates an existing model armor template. + * + * @param {string} projectId - Google Cloud project ID where the template exists. + * @param {string} locationId - Google Cloud location where the template exists. + * @param {string} templateId - ID of the template to update. + */ +async function updateTemplate(projectId, locationId, templateId) { + // [START modelarmor_update_template] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'template-id'; + + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + const {protos} = modelarmor; + + const DetectionConfidenceLevel = + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel; + const PiAndJailbreakFilterEnforcement = + protos.google.cloud.modelarmor.v1.PiAndJailbreakFilterSettings + .PiAndJailbreakFilterEnforcement; + const MaliciousUriFilterEnforcement = + protos.google.cloud.modelarmor.v1.MaliciousUriFilterSettings + .MaliciousUriFilterEnforcement; + + // Instantiates a client + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + // Build the updated template configuration + const updatedTemplate = { + name: `projects/${projectId}/locations/${locationId}/templates/${templateId}`, + filterConfig: { + piAndJailbreakFilterSettings: { + filterEnforcement: PiAndJailbreakFilterEnforcement.ENABLED, + confidenceLevel: DetectionConfidenceLevel.LOW_AND_ABOVE, + }, + maliciousUriFilterSettings: { + filterEnforcement: MaliciousUriFilterEnforcement.ENABLED, + }, + }, + }; + + const request = { + template: updatedTemplate, + }; + + const [response] = await client.updateTemplate(request); + return response; + // [END modelarmor_update_template] +} + +module.exports = updateTemplate; diff --git a/model-armor/snippets/updateTemplateLabels.js b/model-armor/snippets/updateTemplateLabels.js new file mode 100644 index 0000000000..63a4cc466c --- /dev/null +++ b/model-armor/snippets/updateTemplateLabels.js @@ -0,0 +1,72 @@ +// 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'; + +/** + * Updates the labels of an existing model armor template. + * + * @param {string} projectId - Google Cloud project ID where the template exists. + * @param {string} locationId - Google Cloud location where the template exists. + * @param {string} templateId - ID of the template to update. + * @param {string} labelKey - The key for the label to add or update. + * @param {string} labelValue - The value for the label to add or update. + */ +async function updateTemplateWithLabels( + projectId, + locationId, + templateId, + labelKey, + labelValue +) { + // [START modelarmor_update_template_with_labels] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'template-id'; + // const labelKey = 'env'; + // const labelValue = 'prod'; + + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + const labels = {}; + labels[labelKey] = labelValue; + + const template = { + name: `projects/${projectId}/locations/${locationId}/templates/${templateId}`, + labels: labels, + }; + + const updateMask = { + paths: ['labels'], + }; + + const request = { + template: template, + updateMask: updateMask, + }; + + const [response] = await client.updateTemplate(request); + return response; + // [END modelarmor_update_template_with_labels] +} + +module.exports = updateTemplateWithLabels; diff --git a/model-armor/snippets/updateTemplateMetadata.js b/model-armor/snippets/updateTemplateMetadata.js new file mode 100644 index 0000000000..b01df28724 --- /dev/null +++ b/model-armor/snippets/updateTemplateMetadata.js @@ -0,0 +1,78 @@ +// 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'; + +/** + * Updates the metadata of an existing model armor template. + * + * @param {string} projectId - Google Cloud project ID where the template exists. + * @param {string} locationId - Google Cloud location where the template exists. + * @param {string} templateId - ID of the template to update. + */ +async function updateTemplateMetadata(projectId, locationId, templateId) { + // [START modelarmor_update_template_metadata] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'template-id'; + + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + const {protos} = modelarmor; + + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + const DetectionConfidenceLevel = + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel; + const PiAndJailbreakFilterEnforcement = + protos.google.cloud.modelarmor.v1.PiAndJailbreakFilterSettings + .PiAndJailbreakFilterEnforcement; + const MaliciousUriFilterEnforcement = + protos.google.cloud.modelarmor.v1.MaliciousUriFilterSettings + .MaliciousUriFilterEnforcement; + + const templateName = `projects/${projectId}/locations/${locationId}/templates/${templateId}`; + + const template = { + name: templateName, + filterConfig: { + piAndJailbreakFilterSettings: { + filterEnforcement: PiAndJailbreakFilterEnforcement.ENABLED, + confidenceLevel: DetectionConfidenceLevel.LOW_AND_ABOVE, + }, + maliciousUriFilterSettings: { + filterEnforcement: MaliciousUriFilterEnforcement.ENABLED, + }, + }, + templateMetadata: { + logTemplateOperations: true, + logSanitizeOperations: true, + }, + }; + + const request = { + template: template, + }; + + const [response] = await client.updateTemplate(request); + return response; + // [END modelarmor_update_template_metadata] +} + +module.exports = updateTemplateMetadata; diff --git a/model-armor/snippets/updateTemplateWithMaskConfiguration.js b/model-armor/snippets/updateTemplateWithMaskConfiguration.js new file mode 100644 index 0000000000..0e7e596db3 --- /dev/null +++ b/model-armor/snippets/updateTemplateWithMaskConfiguration.js @@ -0,0 +1,89 @@ +// 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'; + +/** + * Updates an existing model armor template with a specific update mask. + * + * @param {string} projectId - Google Cloud project ID where the template exists. + * @param {string} locationId - Google Cloud location where the template exists. + * @param {string} templateId - ID of the template to update. + */ +async function updateTemplateWithMaskConfiguration( + projectId, + locationId, + templateId +) { + // [START modelarmor_update_template_with_mask_configuration] + /** + * TODO(developer): Uncomment these variables before running the sample. + */ + // const projectId = 'your-project-id'; + // const locationId = 'us-central1'; + // const templateId = 'template-id'; + + const modelarmor = require('@google-cloud/modelarmor'); + const {ModelArmorClient} = modelarmor.v1; + const {protos} = modelarmor; + + const client = new ModelArmorClient({ + apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`, + }); + + const DetectionConfidenceLevel = + protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel; + const PiAndJailbreakFilterEnforcement = + protos.google.cloud.modelarmor.v1.PiAndJailbreakFilterSettings + .PiAndJailbreakFilterEnforcement; + const MaliciousUriFilterEnforcement = + protos.google.cloud.modelarmor.v1.MaliciousUriFilterSettings + .MaliciousUriFilterEnforcement; + + const templateName = `projects/${projectId}/locations/${locationId}/templates/${templateId}`; + + // Build the Model Armor template with your preferred filters + // For more details on filters, please refer to the following doc: + // https://cloud.google.com/security-command-center/docs/key-concepts-model-armor#ma-filters + const template = { + name: templateName, + filterConfig: { + piAndJailbreakFilterSettings: { + filterEnforcement: PiAndJailbreakFilterEnforcement.ENABLED, + confidenceLevel: DetectionConfidenceLevel.LOW_AND_ABOVE, + }, + maliciousUriFilterSettings: { + filterEnforcement: MaliciousUriFilterEnforcement.ENABLED, + }, + }, + }; + + // Mask config for specifying field to update + // Refer to following documentation for more details on update mask field and its usage: + // https://protobuf.dev/reference/protobuf/google.protobuf/#field-mask + const updateMask = { + paths: ['filter_config'], + }; + + const request = { + template: template, + updateMask: updateMask, + }; + + const [response] = await client.updateTemplate(request); + return response; + // [END modelarmor_update_template_with_mask_configuration] +} + +module.exports = updateTemplateWithMaskConfiguration; diff --git a/model-armor/test/modelarmor.test.js b/model-armor/test/modelarmor.test.js index f040427f42..4350357999 100644 --- a/model-armor/test/modelarmor.test.js +++ b/model-armor/test/modelarmor.test.js @@ -37,6 +37,7 @@ let allFilterTemplateId; let inspectTemplateName; let deidentifyTemplateName; +// Helper function to create a template for sanitization tests async function createTemplate(templateId, filterConfig) { const parent = `projects/${projectId}/locations/${locationId}`; @@ -57,6 +58,7 @@ async function createTemplate(templateId, filterConfig) { } } +// Helper function to delete a template async function deleteTemplate(templateName) { try { await client.deleteTemplate({ @@ -73,6 +75,7 @@ async function deleteTemplate(templateName) { } } +// Helper function to create DLP template. async function createDlpTemplates() { try { const dlpClient = new DlpServiceClient({ @@ -140,6 +143,7 @@ async function createDlpTemplates() { } } +// Helper function to delete DLP template. async function deleteDlpTemplates() { try { if (inspectTemplateName) { @@ -177,8 +181,8 @@ describe('Model Armor tests', () => { before(async () => { projectId = await client.getProjectId(); - const {protos} = require('@google-cloud/modelarmor'); + // Import necessary enums const DetectionConfidenceLevel = protos.google.cloud.modelarmor.v1.DetectionConfidenceLevel; const PiAndJailbreakFilterEnforcement = @@ -195,9 +199,6 @@ describe('Model Armor tests', () => { // Create empty template for sanitizeUserPrompt tests emptyTemplateId = `${templateIdPrefix}-empty`; await createTemplate(emptyTemplateId, {}); - templatesToDelete.push( - `projects/${projectId}/locations/${locationId}/templates/${emptyTemplateId}` - ); // Create basic template with PI/Jailbreak and Malicious URI filters for sanitizeUserPrompt tests basicTemplateId = `${templateIdPrefix}-basic`; @@ -210,9 +211,6 @@ describe('Model Armor tests', () => { filterEnforcement: MaliciousUriFilterEnforcement.ENABLED, }, }); - templatesToDelete.push( - `projects/${projectId}/locations/${locationId}/templates/${basicTemplateId}` - ); // Create basic SDP template basicSdpTemplateId = `${templateIdPrefix}-basic-sdp`; @@ -228,9 +226,6 @@ describe('Model Armor tests', () => { }, }, }); - templatesToDelete.push( - `projects/${projectId}/locations/${locationId}/templates/${basicSdpTemplateId}` - ); // Create advanced SDP template with DLP templates const dlpTemplates = await createDlpTemplates(); @@ -243,9 +238,6 @@ describe('Model Armor tests', () => { }, }, }); - templatesToDelete.push( - `projects/${projectId}/locations/${locationId}/templates/${advanceSdpTemplateId}` - ); // Create all-filter template allFilterTemplateId = `${templateIdPrefix}-all-filters`; @@ -278,9 +270,6 @@ describe('Model Armor tests', () => { filterEnforcement: MaliciousUriFilterEnforcement.ENABLED, }, }); - templatesToDelete.push( - `projects/${projectId}/locations/${locationId}/templates/${allFilterTemplateId}` - ); // Create a template to be deleted templateToDeleteId = `${templateIdPrefix}-to-delete`; @@ -290,7 +279,13 @@ describe('Model Armor tests', () => { confidenceLevel: DetectionConfidenceLevel.MEDIUM_AND_ABOVE, }, }); + templatesToDelete.push( + `projects/${projectId}/locations/${locationId}/templates/${emptyTemplateId}`, + `projects/${projectId}/locations/${locationId}/templates/${basicTemplateId}`, + `projects/${projectId}/locations/${locationId}/templates/${basicSdpTemplateId}`, + `projects/${projectId}/locations/${locationId}/templates/${advanceSdpTemplateId}`, + `projects/${projectId}/locations/${locationId}/templates/${allFilterTemplateId}`, `projects/${projectId}/locations/${locationId}/templates/${templateToDeleteId}` ); }); @@ -303,6 +298,235 @@ describe('Model Armor tests', () => { await deleteDlpTemplates(); }); + // =================== Template Creation Tests =================== + + it('should create a basic template', async () => { + const testTemplateId = `${templateIdPrefix}-basic-create`; + const createTemplate = require('../snippets/createTemplate'); + + const response = await createTemplate( + projectId, + locationId, + testTemplateId + ); + const templateName = `projects/${projectId}/locations/${locationId}/templates/${testTemplateId}`; + templatesToDelete.push(templateName); + + assert.strictEqual(response.name, templateName); + }); + + it('should create a template with basic SDP settings', async () => { + const testTemplateId = `${templateIdPrefix}-basic-sdp-1`; + const createTemplateWithBasicSdp = require('../snippets/createTemplateWithBasicSdp'); + + const response = await createTemplateWithBasicSdp( + projectId, + locationId, + testTemplateId + ); + const templateName = `projects/${projectId}/locations/${locationId}/templates/${testTemplateId}`; + templatesToDelete.push(templateName); + + assert.strictEqual(response.name, templateName); + }); + + it('should create a template with advanced SDP settings', async () => { + const testTemplateId = `${templateIdPrefix}-adv-sdp`; + const inspectTemplate = basicSdpTemplateId; + const deidentifyTemplate = basicSdpTemplateId; + const createTemplateWithAdvancedSdp = require('../snippets/createTemplateWithAdvancedSdp'); + + const fullInspectTemplate = `projects/${projectId}/locations/${locationId}/inspectTemplates/${inspectTemplate}`; + const fullDeidentifyTemplate = `projects/${projectId}/locations/${locationId}/deidentifyTemplates/${deidentifyTemplate}`; + + const response = await createTemplateWithAdvancedSdp( + projectId, + locationId, + testTemplateId, + fullInspectTemplate, + fullDeidentifyTemplate + ); + + const templateName = `projects/${projectId}/locations/${locationId}/templates/${testTemplateId}`; + templatesToDelete.push(templateName); + + assert.strictEqual(response.name, templateName); + }); + + it('should create a template with metadata', async () => { + const testTemplateId = `${templateIdPrefix}-metadata`; + const createTemplateWithMetadata = require('../snippets/createTemplateWithMetadata'); + + const response = await createTemplateWithMetadata( + projectId, + locationId, + testTemplateId + ); + const templateName = `projects/${projectId}/locations/${locationId}/templates/${testTemplateId}`; + templatesToDelete.push(templateName); + + assert.strictEqual(response.name, templateName); + }); + + it('should create a template with labels', async () => { + const testTemplateId = `${templateIdPrefix}-labels`; + const labelKey = 'environment'; + const labelValue = 'test'; + const createTemplateWithLabels = require('../snippets/createTemplateWithLabels'); + + const response = await createTemplateWithLabels( + projectId, + locationId, + testTemplateId, + labelKey, + labelValue + ); + + const templateName = `projects/${projectId}/locations/${locationId}/templates/${testTemplateId}`; + templatesToDelete.push(templateName); + + assert.strictEqual(response.name, templateName); + }); + + // =================== Template Management Tests =================== + + it('should get a template', async () => { + const templateToGet = `${templateIdPrefix}-basic-sdp`; + const templateName = `projects/${projectId}/locations/${locationId}/templates/${templateToGet}`; + + const getTemplate = require('../snippets/getTemplate'); + const template = await getTemplate(projectId, locationId, templateToGet); + + assert.strictEqual(template.name, templateName); + }); + + it('should delete a template', async () => { + const deleteTemplate = require('../snippets/deleteTemplate'); + const response = await deleteTemplate( + projectId, + locationId, + templateToDeleteId + ); + assert.isArray(response); + assert.isObject(response[0]); + assert.isNull(response[1]); + assert.isNull(response[2]); + + assert.deepEqual(response[0], {}); + }); + + it('should list templates', async () => { + const listTemplates = require('../snippets/listTemplates'); + const templates = await listTemplates(projectId, locationId); + + const hasMatchingTemplate = templates.some(template => + template.name.includes(templateIdPrefix) + ); + + assert.isTrue( + hasMatchingTemplate, + `Should find at least one template with prefix ${templateIdPrefix}` + ); + }); + + it('should list templates with filter', async () => { + const templateToGet = `${templateIdPrefix}-basic-sdp`; + const templateName = `projects/${projectId}/locations/${locationId}/templates/${templateToGet}`; + + const listTemplatesWithFilter = require('../snippets/listTemplatesWithFilter'); + const templates = await listTemplatesWithFilter( + projectId, + locationId, + templateToGet + ); + // Should find exactly one template + assert.strictEqual(templates.length, 1); + assert.strictEqual(templates[0].name, templateName); + }); + + // =================== Template Update Tests =================== + + it('should update a template', async () => { + const templateToUpdate = `${templateIdPrefix}-basic-create`; + + const updateTemplate = require('../snippets/updateTemplate'); + const response = await updateTemplate( + projectId, + locationId, + templateToUpdate + ); + assert.property(response, 'filterConfig'); + assert.property(response.filterConfig, 'piAndJailbreakFilterSettings'); + assert.property(response.filterConfig, 'maliciousUriFilterSettings'); + + const piSettings = response.filterConfig.piAndJailbreakFilterSettings; + assert.strictEqual(piSettings.filterEnforcement, 'ENABLED'); + assert.strictEqual(piSettings.confidenceLevel, 'LOW_AND_ABOVE'); + + const uriSettings = response.filterConfig.maliciousUriFilterSettings; + assert.strictEqual(uriSettings.filterEnforcement, 'ENABLED'); + }); + + it('should update template labels', async () => { + const labelKey = 'environment'; + const labelValue = 'testing'; + const templateToUpdate = `${templateIdPrefix}-basic-create`; + const templateName = `projects/${projectId}/locations/${locationId}/templates/${templateToUpdate}`; + + const updateTemplateWithLabels = require('../snippets/updateTemplateLabels'); + const response = await updateTemplateWithLabels( + projectId, + locationId, + templateToUpdate, + labelKey, + labelValue + ); + + assert.strictEqual(response.name, templateName); + assert.property(response, 'labels'); + }); + + it('should update template metadata', async () => { + const templateToUpdateMetadata = `${templateIdPrefix}-metadata`; + const templateName = `projects/${projectId}/locations/${locationId}/templates/${templateToUpdateMetadata}`; + + const updateTemplateMetadata = require('../snippets/updateTemplateMetadata'); + const response = await updateTemplateMetadata( + projectId, + locationId, + templateToUpdateMetadata + ); + assert.strictEqual(response.name, templateName); + + assert.property(response, 'templateMetadata'); + assert.property(response.templateMetadata, 'logTemplateOperations'); + assert.property(response.templateMetadata, 'logSanitizeOperations'); + assert.strictEqual(response.templateMetadata.logTemplateOperations, true); + assert.strictEqual(response.templateMetadata.logSanitizeOperations, true); + }); + + it('should update template with mask configuration', async () => { + const templateToUpdateWithMask = `${templateIdPrefix}-metadata`; + const templateName = `projects/${projectId}/locations/${locationId}/templates/${templateToUpdateWithMask}`; + + const updateTemplateWithMaskConfiguration = require('../snippets/updateTemplateWithMaskConfiguration'); + const response = await updateTemplateWithMaskConfiguration( + projectId, + locationId, + templateToUpdateWithMask + ); + + assert.strictEqual(response.name, templateName); + + assert.property(response, 'filterConfig'); + assert.property(response.filterConfig, 'piAndJailbreakFilterSettings'); + assert.property(response.filterConfig, 'maliciousUriFilterSettings'); + + const piSettings = response.filterConfig.piAndJailbreakFilterSettings; + assert.strictEqual(piSettings.filterEnforcement, 'ENABLED'); + assert.strictEqual(piSettings.confidenceLevel, 'LOW_AND_ABOVE'); + }); + // =================== Quickstart Tests =================== it('should create a template and sanitize content', async () => {