Skip to content

Commit f128b23

Browse files
authored
feat(modelarmor-samples): add model armor template and prompt samples (#13143)
* feat(modelarmor-samples): add model armor template and prompt samples * header fix * add noxfile * add pytest * address comments and lint fix * lint fix * updated templates * addressed review comments * addressed review comments * addressed review comments
1 parent 790fe97 commit f128b23

File tree

10 files changed

+449
-0
lines changed

10 files changed

+449
-0
lines changed

model_armor/create_template.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.cloud.modelarmor_v1 import Template
16+
17+
18+
def create_model_armor_template(project_id: str, location: str, template_id: str) -> Template:
19+
# [START modelarmor_create_template]
20+
21+
from google.api_core.client_options import ClientOptions
22+
from google.cloud.modelarmor_v1 import (
23+
Template,
24+
DetectionConfidenceLevel,
25+
FilterConfig,
26+
PiAndJailbreakFilterSettings,
27+
MaliciousUriFilterSettings,
28+
ModelArmorClient,
29+
CreateTemplateRequest
30+
)
31+
32+
client = ModelArmorClient(
33+
transport="rest",
34+
client_options=ClientOptions(api_endpoint=f"modelarmor.{location}.rep.googleapis.com"),
35+
)
36+
37+
# TODO(Developer): Uncomment these variables and initialize
38+
# project_id = "your-google-cloud-project-id"
39+
# location = "us-central1"
40+
# template_id = "template_id"
41+
42+
template = Template(
43+
filter_config=FilterConfig(
44+
pi_and_jailbreak_filter_settings=PiAndJailbreakFilterSettings(
45+
filter_enforcement=PiAndJailbreakFilterSettings.PiAndJailbreakFilterEnforcement.ENABLED,
46+
confidence_level=DetectionConfidenceLevel.MEDIUM_AND_ABOVE,
47+
),
48+
malicious_uri_filter_settings=MaliciousUriFilterSettings(
49+
filter_enforcement=MaliciousUriFilterSettings.MaliciousUriFilterEnforcement.ENABLED,
50+
)
51+
),
52+
)
53+
54+
# Initialize request arguments
55+
request = CreateTemplateRequest(
56+
parent=f"projects/{project_id}/locations/{location}",
57+
template_id=template_id,
58+
template=template,
59+
)
60+
61+
# Make the request
62+
response = client.create_template(request=request)
63+
# Response
64+
print(response.name)
65+
66+
# [END modelarmor_create_template]
67+
68+
return response

model_armor/delete_template.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
16+
def delete_model_armor_template(project_id: str, location: str, template_id: str) -> None:
17+
# [START modelarmor_delete_template]
18+
19+
from google.api_core.client_options import ClientOptions
20+
from google.cloud.modelarmor_v1 import (
21+
ModelArmorClient,
22+
DeleteTemplateRequest,
23+
)
24+
25+
client = ModelArmorClient(
26+
transport="rest",
27+
client_options=ClientOptions(api_endpoint=f"modelarmor.{location}.rep.googleapis.com"),
28+
)
29+
30+
# TODO(Developer): Uncomment these variables and initialize
31+
# project_id = "YOUR_PROJECT_ID"
32+
# location = "us-central1"
33+
# template_id = "template_id"
34+
35+
request = DeleteTemplateRequest(
36+
name=f"projects/{project_id}/locations/{location}/templates/{template_id}",
37+
)
38+
39+
# Make the request
40+
client.delete_template(request=request)
41+
42+
43+
# [END modelarmor_delete_template]

model_armor/get_template.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.cloud.modelarmor_v1 import Template
16+
17+
18+
def get_model_armor_template(project_id: str, location: str, template_id: str) -> Template:
19+
# [START modelarmor_get_template]
20+
21+
from google.api_core.client_options import ClientOptions
22+
from google.cloud.modelarmor_v1 import (
23+
ModelArmorClient,
24+
GetTemplateRequest,
25+
)
26+
27+
client = ModelArmorClient(
28+
transport="rest",
29+
client_options=ClientOptions(api_endpoint=f"modelarmor.{location}.rep.googleapis.com"),
30+
)
31+
32+
# TODO(Developer): Uncomment these variables and initialize
33+
# project_id = "YOUR_PROJECT_ID"
34+
# location = "us-central1"
35+
# template_id = "template_id"
36+
37+
# Initialize request arguments
38+
request = GetTemplateRequest(
39+
name=f"projects/{project_id}/locations/{location}/templates/{template_id}",
40+
)
41+
42+
# Make the request
43+
response = client.get_template(request=request)
44+
print(response.name)
45+
46+
# [END modelarmor_get_template]
47+
48+
# Handle the response
49+
return response

model_armor/list_templates.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.cloud.modelarmor_v1.services.model_armor.pagers import ListTemplatesPager
16+
17+
18+
def list_model_armor_templates(project_id: str, location: str) -> ListTemplatesPager:
19+
# [START modelarmor_list_templates]
20+
from google.api_core.client_options import ClientOptions
21+
from google.cloud.modelarmor_v1 import (
22+
ModelArmorClient,
23+
ListTemplatesRequest,
24+
)
25+
26+
client = ModelArmorClient(
27+
transport="rest",
28+
client_options=ClientOptions(api_endpoint=f"modelarmor.{location}.rep.googleapis.com"),
29+
)
30+
31+
# TODO(Developer): Uncomment these variables and initialize
32+
# project_id = "YOUR_PROJECT_ID"
33+
# location = "us-central1"
34+
35+
# Initialize request argument(s)
36+
request = ListTemplatesRequest(
37+
parent=f"projects/{project_id}/locations/{location}"
38+
)
39+
40+
# Make the request
41+
response = client.list_templates(request=request)
42+
for template in response:
43+
print(template.name)
44+
45+
# [END modelarmor_list_templates]
46+
47+
# Handle the response
48+
return response

model_armor/noxfile_config.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Default TEST_CONFIG_OVERRIDE for python repos.
16+
17+
# You can copy this file into your directory, then it will be imported from
18+
# the noxfile.py.
19+
20+
# The source of truth:
21+
# https://github.com/GoogleCloudPlatform/python-docs-samples/blob/main/noxfile_config.py
22+
23+
TEST_CONFIG_OVERRIDE = {
24+
# You can opt out from the test for specific Python versions.
25+
"ignored_versions": ["2.7", "3.7", "3.8", "3.10", "3.11", "3.12"],
26+
# Old samples are opted out of enforcing Python type hints
27+
# All new samples should feature them
28+
"enforce_type_hints": True,
29+
# An envvar key for determining the project id to use. Change it
30+
# to 'BUILD_SPECIFIC_GCLOUD_PROJECT' if you want to opt in using a
31+
# build specific Cloud project. You can also use your own string
32+
# to use your own Cloud project.
33+
"gcloud_project_env": "GOOGLE_CLOUD_PROJECT",
34+
# 'gcloud_project_env': 'BUILD_SPECIFIC_GCLOUD_PROJECT',
35+
# If you need to use a specific version of pip,
36+
# change pip_version_override to the string representation
37+
# of the version number, for example, "20.2.4"
38+
"pip_version_override": None,
39+
# A dictionary you want to inject into your test. Don't put any
40+
# secrets here. These values will override predefined values.
41+
"envs": {},
42+
}

model_armor/requirements-test.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pytest==8.3.4

model_armor/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
google-cloud-modelarmor==0.1.1
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from google.cloud.modelarmor_v1 import SanitizeUserPromptResponse
16+
17+
18+
def sanitize_user_prompt(
19+
project_id: str, location: str, template_id: str
20+
) -> SanitizeUserPromptResponse:
21+
# [START modelarmor_sanitize_user_prompt]
22+
23+
from google.api_core.client_options import ClientOptions
24+
from google.cloud.modelarmor_v1 import (
25+
ModelArmorClient,
26+
DataItem,
27+
SanitizeUserPromptRequest
28+
)
29+
30+
client = ModelArmorClient(
31+
transport="rest",
32+
client_options=ClientOptions(api_endpoint=f"modelarmor.{location}.rep.googleapis.com"),
33+
)
34+
35+
# TODO(Developer): Uncomment these variables and initialize
36+
# project_id = "YOUR_PROJECT_ID"
37+
# location = "us-central1"
38+
# template_id = "template_id"
39+
40+
# Define the prompt
41+
user_prompt = "Can you describe this link? https://testsafebrowsing.appspot.com/s/malware.html"
42+
43+
# Initialize request argument(s)
44+
user_prompt_data = DataItem(
45+
text=user_prompt
46+
)
47+
48+
request = SanitizeUserPromptRequest(
49+
name=f"projects/{project_id}/locations/{location}/templates/{template_id}",
50+
user_prompt_data=user_prompt_data,
51+
)
52+
53+
# Make the request
54+
response = client.sanitize_user_prompt(request=request)
55+
# Match state is TRUE when the prompt is caught by one of the safety policies in the template.
56+
print(response.sanitization_result.filter_match_state)
57+
58+
# [END modelarmor_sanitize_user_prompt]
59+
60+
# Handle the response
61+
return response

model_armor/test_templates.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import os
16+
import uuid
17+
18+
from google.api_core.exceptions import NotFound
19+
from google.cloud.modelarmor_v1 import (
20+
DetectionConfidenceLevel,
21+
FilterMatchState,
22+
)
23+
import pytest
24+
25+
from create_template import create_model_armor_template
26+
from delete_template import delete_model_armor_template
27+
from get_template import get_model_armor_template
28+
from list_templates import list_model_armor_templates
29+
from sanitize_user_prompt import sanitize_user_prompt
30+
from update_template import update_model_armor_template
31+
32+
PROJECT_ID = os.environ["GOOGLE_CLOUD_PROJECT"]
33+
LOCATION = "us-central1"
34+
TEMPLATE_ID = f"test-model-armor-{uuid.uuid4()}"
35+
36+
37+
def test_create_template() -> None:
38+
template = create_model_armor_template(PROJECT_ID, LOCATION, TEMPLATE_ID)
39+
assert template is not None
40+
41+
42+
def test_get_template() -> None:
43+
template = get_model_armor_template(PROJECT_ID, LOCATION, TEMPLATE_ID)
44+
assert TEMPLATE_ID in template.name
45+
46+
47+
def test_list_templates() -> None:
48+
templates = list_model_armor_templates(PROJECT_ID, LOCATION)
49+
assert TEMPLATE_ID in str(templates)
50+
51+
52+
def test_user_prompt() -> None:
53+
response = sanitize_user_prompt(PROJECT_ID, LOCATION, TEMPLATE_ID)
54+
assert (
55+
response.sanitization_result.filter_match_state == FilterMatchState.MATCH_FOUND
56+
)
57+
58+
59+
def test_update_templates() -> None:
60+
template = update_model_armor_template(PROJECT_ID, LOCATION, TEMPLATE_ID)
61+
assert (
62+
template.filter_config.pi_and_jailbreak_filter_settings.confidence_level == DetectionConfidenceLevel.LOW_AND_ABOVE
63+
)
64+
65+
66+
def test_delete_template() -> None:
67+
delete_model_armor_template(PROJECT_ID, LOCATION, TEMPLATE_ID)
68+
with pytest.raises(NotFound) as exception_info:
69+
get_model_armor_template(PROJECT_ID, LOCATION, TEMPLATE_ID)
70+
assert TEMPLATE_ID in str(exception_info.value)

0 commit comments

Comments
 (0)