This page describes how to sanitize prompts and responses in detail. Model Armor offers a set of filters to protect your AI applications. Model Armor checks prompts and responses for the configured screening confidence levels.
Before you begin
Create a template following the instructions in Create templates.
Obtain the required permissions
To get the permissions that you need to sanitize prompts and responses, ask your administrator to grant you the following IAM roles on Model Armor:
- Model Armor User (
roles/modelarmor.user) - Model Armor Viewer (
roles/modelarmor.viewer)
For more information about granting roles, see Manage access to projects, folders, and organizations.
You might also be able to get the required permissions through custom roles or other predefined roles.
In the project containing the Sensitive Data Protection template, grant the
DLP User role (roles/dlp.user)
and DLP Reader role (roles/dlp.reader)
to the service agent created as a part of the Advanced Sensitive Data Protection step of
Create templates.
Skip this step if the Sensitive Data Protection template is in the same
project as the Model Armor template.
gcloud projects add-iam-policy-binding SDP_PROJECT_ID \ --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-modelarmor.iam.gserviceaccount.com --role=roles/dlp.user gcloud projects add-iam-policy-binding SDP_PROJECT_ID \ --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-modelarmor.iam.gserviceaccount.com --role=roles/dlp.reader
Replace the following:
SDP_PROJECT_ID: the ID of the project that the advanced Sensitive Data Protection template belongs to.PROJECT_NUMBER: the number of the project the template belongs to.
Enable APIs
You must enable the Model Armor API before you can use Model Armor.
Console
Enable the Model Armor API.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM role (
roles/serviceusage.serviceUsageAdmin), which contains theserviceusage.services.enablepermission. Learn how to grant roles.Select the project where you want to activate Model Armor.
gcloud
Before you begin, follow these steps using the Google Cloud CLI with the Model Armor API:
In the Google Cloud console, activate Cloud Shell.
At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.
Set the API endpoint override using the gcloud CLI
This step is only required if you are using the gcloud CLI to enable the Model Armor API. You must manually set the API endpoint override to ensure the gcloud CLI correctly routes requests to the Model Armor service.
Run the following command to set the API endpoint for the Model Armor service.
gcloud config set api_endpoint_overrides/modelarmor "https://modelarmor.LOCATION.rep.googleapis.com/"
Replace LOCATION with the region where you want to use
Model Armor.
Sanitize prompts
Sanitize prompts to prevent malicious inputs and help ensure safe and appropriate prompts are sent to your LLMs.
Text prompts
Model Armor sanitizes text prompts by analyzing the text and applying different filters to identify and mitigate potential threats.
REST
Use the following command to sanitize a text prompt in Model Armor.
curl -X POST \
-d '{"userPromptData":{"text":"[UNSAFE TEXT]"}}' \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID:sanitizeUserPrompt"
Replace the following:
PROJECT_ID: the ID of the project for the template.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.
This results in the following response. Note that MATCH_FOUND is in the
Dangerous category.
{ "sanitizationResult": { "filterMatchState": "MATCH_FOUND", "invocationResult": "SUCCESS", "filterResults": { "csam": { "csamFilterFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, "malicious_uris": { "maliciousUriFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, "rai": { "raiFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "MATCH_FOUND", "raiFilterTypeResults": { "sexually_explicit": { "matchState": "NO_MATCH_FOUND" }, "hate_speech": { "matchState": "NO_MATCH_FOUND" }, "harassment": { "matchState": "NO_MATCH_FOUND" }, "dangerous": { "matchState": "MATCH_FOUND" } } } }, "pi_and_jailbreak": { "piAndJailbreakFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "MATCH_FOUND" } }, "sdp": { "sdpFilterResult": { "inspectResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } } } } } }
Go
To run this code, first set up a Go development environment and install the Model Armor Go SDK.
C#
To run this code, first set up a C# development environment and install the Model Armor C# SDK.
Java
To run this code, first set up a Java development environment and install the Model Armor Java SDK.
Node.js
To run this code, first set up a Node.js development environment and install the Model Armor Node.js SDK.
PHP
To run this code, first set up a PHP development environment and install the Model Armor PHP SDK.
Python
To run this code, set up a Python development environment and install the Model Armor Python SDK.
This results in the following response.
sanitization_result { filter_match_state: MATCH_FOUND filter_results { key: "rai" value { rai_filter_result { execution_state: EXECUTION_SUCCESS match_state: MATCH_FOUND rai_filter_type_results { key: "dangerous" value { confidence_level: HIGH match_state: MATCH_FOUND } } } } } filter_results { key: "pi_and_jailbreak" value { pi_and_jailbreak_filter_result { execution_state: EXECUTION_SUCCESS match_state: MATCH_FOUND confidence_level: HIGH } } } filter_results { key: "malicious_uris" value { malicious_uri_filter_result { execution_state: EXECUTION_SUCCESS match_state: NO_MATCH_FOUND } } } filter_results { key: "csam" value { csam_filter_filter_result { execution_state: EXECUTION_SUCCESS match_state: NO_MATCH_FOUND } } } invocation_result: SUCCESS }
Best practices for sanitizing prompts in conversational AI
When using Model Armor to sanitize inputs in a conversational AI application,
it's important to understand what to include in the userPromptData field
for the SanitizeUserPrompt method.
Sanitize each user input separately: Call the
SanitizeUserPromptAPI for each new message received from the user. This ensures every piece of user input is analyzed for potential threats before being processed by your LLM. TheuserPromptDatafield must contain only the content of the latest message from the user in the current conversation.Don't include conversation history: Avoid concatenating the entire chat history into the
userPromptDatafield.Don't include system prompts: The system prompt shouldn't be included in the
userPromptDatafield. Model Armor focuses on detecting threats only in user-provided inputs.
Sanitize text prompts with multi-language detection enabled
Enable multi-language detection on a per-request basis by setting the
enableMultiLanguageDetection flag to true for each individual request.
Optionally, you can specify the source language
for more accurate results.
- If you don't specify the source language, Model Armor automatically detects the language to provide multi-language support.
- If you specify the source language, Model Armor uses that language to evaluate the text prompt and doesn't perform automatic language detection.
Use the following command to sanitize a text prompt in Model Armor with multi-language detection enabled at a request level.
curl -X POST \ -d '{"userPromptData":{"text":"[UNSAFE TEXT]"}, "multiLanguageDetectionMetadata": { "enableMultiLanguageDetection": true , "sourceLanguage": "jp"}}' \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID:sanitizeUserPrompt"
Replace the following:
PROJECT_ID: the ID of the project for the template.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.
Prompts containing images
To enable image screening, set
the modality in the template metadata.
You can configure modalities in both new and existing templates.
If you specify a single modality (IMAGE or TEXT), Model Armor
skips the other and returns EXECUTION_SKIPPED. You must explicitly set the
byteDataType field to IMAGE and provide the base64-encoded image in the
supported format in the byteData field.
Use the following command to sanitize a prompt that contains an image.
curl -X POST \ -d "$(jq -n \ --arg data "$(base64 -w 0 -i IMAGE)" \ '{userPromptData: {byteItem: {byteDataType: "IMAGE", byteData: $data}}}')" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID:sanitizeUserPrompt"
Replace the following:
PROJECT_ID: the ID of the project that contains the template.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.IMAGE: the image in a supported format.
The response is similar to the following:
{ "sanitizationResult": { "filterMatchState": "MATCH_FOUND", "invocationResult": "SUCCESS", "filterResults": { "csam": { "csamFilterFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, "sdp": { "sdpFilterResult": { "inspectResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "MATCH_FOUND" } } } }, } }
Redact images
For the Sensitive Data Protection advanced mode, Model Armor redacts images only if you configured Model Armor filters with a Sensitive Data Protection inspect template and a Sensitive Data Protection de-identify template. For more information, see Set Sensitive Data Protection settings. Make sure that you configure image redaction in the de-identify template.
When using Sensitive Data Protection advanced mode, the BASIC_AUTH_HEADER
infoType might be reported in detection results even if it is not explicitly
included in the configured inspection template.
The following example shows the filter configuration with Sensitive Data Protection redaction enabled.
{ "filterConfig": { "sdpSettings": { "advancedConfig": { "inspectTemplate": "projects/PROJECT_ID/locations/LOCATION/inspectTemplates/TEMPLATE_ID", "deidentifyTemplate": "projects/PROJECT_ID/locations/LOCATION/deidentifyTemplates/TEMPLATE_ID" } } } }
Replace the following:
PROJECT_ID: the ID of the project that contains the template.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.
This results in the following response.
{ "sanitizationResult": { "filterMatchState": "MATCH_FOUND", "invocationResult": "SUCCESS", "filterResults": { "csam": { "csamFilterFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, "sdp": { "sdpFilterResult": { "redactResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "MATCH_FOUND", "redactedImage": "[REDACTED_IMAGE]", "findings": [ { "infoType": "EMAIL_ADDRESS", "likelihood": "LIKELY", "location": { "contentLocations": [ { "imageFindingLocation": { "boundingBox": { "top": 16, "left": 121, "width": 620, "height": 90 } } } ] } } ] } } } } } }
Sanitize streaming text prompts
The streaming methods of Model Armor sanitize prompts and responses in real-time as text streams, without waiting for the entire content to become available. This capability is particularly useful for applications that handle large text payloads or that require low-latency interactions with LLMs.
Use these methods to enable streaming:
- StreamSanitizeUserPrompt: Streams and sanitizes user-provided text.
- StreamSanitizeModelResponse: Streams and sanitizes LLM-generated text.
Model Armor offers the following streaming modes:
- Buffered mode: Collects all streamed chunks and processes them together as a single unit.
- Real-time mode: Processes each chunk individually as it is received, providing continuous feedback.
Model Armor supports unlimited tokens when using real-time streaming mode, whereas buffered mode is subject to token limits.
Streaming works as follows:
- Chunked input: Your application sends text to Model Armor in smaller pieces (chunks) instead of sending the entire text body at once.
- Real-time processing: Model Armor processes these chunks as they arrive and applies the security and safety filters configured in your template.
- Continuous feedback: Depending on the mode (real-time mode or buffered mode), Model Armor returns results per processed chunk or after all chunks are received.
Use the following command to sanitize a streaming text prompt.
Go
To run this code, first set up a Go development environment and install the Model Armor Go SDK.
package main
import (
"context"
"fmt"
"io"
"log"
modelarmor "cloud.google.com/go/modelarmor/apiv1beta"
modelarmorpb "cloud.google.com/go/modelarmor/apiv1beta/modelarmorpb"
"google.golang.org/api/option"
"google.golang.org/protobuf/encoding/protojson"
)
func main() {
ctx := context.Background()
// Define variables for project, location, and template ID
projectID := "YOUR_PROJECT_ID"
location := "LOCATION_ID"
templateID := "YOUR_TEMPLATE_ID"
// 1. Create the client with the custom regional endpoint.
opts := option.WithEndpoint("modelarmor.us-central1.rep.googleapis.com:443")
c, err := modelarmor.NewClient(ctx, opts)
if err != nil {
log.Fatalf("failed to create client: %v", err)
}
defer c.Close()
// 2. Start the StreamSanitizeUserPrompt bidirectional stream.
stream, err := c.StreamSanitizeUserPrompt(ctx)
if err != nil {
log.Fatalf("failed to initialize stream: %v", err)
}
// 3. Use a goroutine to send the requests.
go func() {
// Define the user prompt data
userPromptData := &modelarmorpb.DataItem{
DataItem: &modelarmorpb.DataItem_Text{
// Specify the user prompt.
Text: "This is a sample user prompt",
},
}
// Create the request object
req := &modelarmorpb.SanitizeUserPromptRequest{ // Use fmt.Sprintf to construct the resource name
Name: fmt.Sprintf("projects/%s/locations/%s/templates/%s", projectID, location, templateID),
UserPromptData: userPromptData,
}
reqs := []*modelarmorpb.SanitizeUserPromptRequest{req}
for _, r := range reqs {
if err := stream.Send(r); err != nil {
log.Printf("Failed to send request: %v", err)
return
}
}
stream.CloseSend()
}()
// 4. Iterate over the responses from the stream.
for {
resp, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
log.Fatalf("failed to receive response: %v", err)
}
// Marshal the proto message to a formatted JSON string
b, _ := protojson.MarshalOptions{
Multiline: true,
Indent: " ",
}.Marshal(resp)
// Results can be consumed or assigned here in production workflows
}
}
C#
To run this code, first set up a C# development environment and install the Model Armor C# SDK.
using Google.Api.Gax.Grpc;
using Google.Cloud.ModelArmor.V1Beta;
using Grpc.Core;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
public class StreamSanitizeUserPromptExample
{
public static async Task Main(string[] args)
{
try
{
await RunStreamSanitizeUserPromptExample();
}
catch (Exception e)
{
Console.WriteLine($"An error occurred: {e}");
}
}
public static async Task RunStreamSanitizeUserPromptExample()
{
string projectId = "YOUR_PROJECT_ID";
string location = "LOCATION_ID";
string templateId = "YOUR_TEMPLATE_ID";
var promptChunks = new List<string>
{
"This is the first part of the user prompt. ",
"This is the second part. ",
"And this is the final part."
};
// Construct the regional REP endpoint (without port)
string regionalEndpoint = $"modelarmor.{location}.rep.googleapis.com";
Console.WriteLine($"Using endpoint: {regionalEndpoint}");
// Initialize the Model Armor client using Application Default Credentials.
var client = new ModelArmorClientBuilder
{
Endpoint = regionalEndpoint
}.Build();
// Construct the resource name.
var resourceName = TemplateName.FromProjectLocationTemplate(projectId, location, templateId);
// Get the bi-directional streaming call object
using var stream = client.StreamSanitizeUserPrompt();
Console.WriteLine("Sending requests...");
// --- Send First Request ---
var firstRequest = new SanitizeUserPromptRequest
{
Name = resourceName.ToString(),
UserPromptData = new DataItem { Text = promptChunks[0] },
StreamingMode = StreamingMode.Buffered // Or StreamingMode.Realtime
};
await stream.WriteAsync(firstRequest);
Console.WriteLine($"Sent chunk 1: \"{promptChunks[0]}\"");
// --- Send Subsequent Requests ---
for (int i = 1; i < promptChunks.Count; i++)
{
var subsequentRequest = new SanitizeUserPromptRequest
{
Name = resourceName.ToString(),
UserPromptData = new DataItem { Text = promptChunks[i] }
};
await stream.WriteAsync(subsequentRequest);
Console.WriteLine($"Sent chunk {i + 1}: \"{promptChunks[i]}\"");
}
// Signal that the client has finished sending requests.
await stream.WriteCompleteAsync();
Console.WriteLine("Client finished sending.");
// --- Receive Responses ---
Console.WriteLine("Receiving responses...");
// This loop waits for responses until the server closes the stream.
while (await stream.GetResponseStream().MoveNextAsync())
{
SanitizeUserPromptResponse response = stream.GetResponseStream().Current;
if (response.SanitizationResult != null)
{
var result = response.SanitizationResult;
Console.WriteLine("Received response:");
Console.WriteLine($" Match State: {result.FilterMatchState}");
Console.WriteLine($" Invocation Result: {result.InvocationResult}");
}
else
{
Console.WriteLine("Received empty response.");
}
}
Console.WriteLine("Stream finished and closed.");
}
}
Java
To run this code, first set up a Java development environment and install the Model Armor Java SDK.
package com.example.armor;
import com.google.api.gax.rpc.BidiStream;
import com.google.cloud.modelarmor.v1beta.DataItem;
import com.google.cloud.modelarmor.v1beta.ModelArmorClient;
import com.google.cloud.modelarmor.v1beta.ModelArmorSettings;
import com.google.cloud.modelarmor.v1beta.SanitizationResult;
import com.google.cloud.modelarmor.v1beta.SanitizeUserPromptRequest;
import com.google.cloud.modelarmor.v1beta.SanitizeUserPromptResponse;
import com.google.cloud.modelarmor.v1beta.StreamingMode;
import com.google.cloud.modelarmor.v1beta.TemplateName;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
public class StreamSanitizeUserPrompt {
public static void main(String[] args) {
try {
streamSanitizeUserPromptExample();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void streamSanitizeUserPromptExample()
throws IOException, InterruptedException, ExecutionException {
// Specify the Google Project ID.
String projectId = "YOUR_PROJECT_ID";
// Specify the location ID. For example, us-central1.
String locationId = "LOCATION_ID";
// Specify the template ID.
String templateId = "YOUR_TEMPLATE_ID";
String customApiEndpoint = "modelarmor.us-central1.rep.googleapis.com:443";
List<String> promptChunks = Arrays.asList(
"This is the first part of the user prompt. ",
"This is the second part. ",
"And this is the final part."
);
// ModelArmorSettings is now properly imported and recognized here
try (
ModelArmorClient modelArmorClient = ModelArmorClient.create(
ModelArmorSettings.newBuilder()
.setEndpoint(customApiEndpoint)
.build()
)
) {
BidiStream<SanitizeUserPromptRequest, SanitizeUserPromptResponse> stream =
modelArmorClient.streamSanitizeUserPromptCallable().call();
String resourceName = TemplateName.of(projectId, locationId, templateId).toString();
// --- Send First Request ---
SanitizeUserPromptRequest firstRequest = SanitizeUserPromptRequest.newBuilder()
.setName(resourceName)
.setUserPromptData(DataItem.newBuilder().setText(promptChunks.get(0)))
.setStreamingMode(StreamingMode.STREAMING_MODE_BUFFERED)
.build();
stream.send(firstRequest);
// --- Send Subsequent Requests ---
for (int i = 1; i < promptChunks.size(); i++) {
SanitizeUserPromptRequest subsequentRequest = SanitizeUserPromptRequest.newBuilder()
.setName(resourceName)
.setUserPromptData(DataItem.newBuilder().setText(promptChunks.get(i)))
.build();
stream.send(subsequentRequest);
}
stream.closeSend();
// --- Receive Responses ---
for (SanitizeUserPromptResponse response : stream) {
if (response.hasSanitizationResult()) {
SanitizationResult result = response.getSanitizationResult();
// Results can be consumed or assigned here in production workflows
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Node.js
To run this code, first set up a Node.js development environment and install the Model Armor Node.js SDK.
const { ModelArmorClient } = require('@google-cloud/modelarmor').v1beta;
async function streamSanitizeUserPromptExample() {
const projectId = 'YOUR_PROJECT_ID';
const location = 'LOCATION_ID';
const templateId = 'YOUR_TEMPLATE_ID';
const promptChunks = [
'This is the first part of the user prompt. ',
'This is the second part. ',
'And this is the final part.'
];
// Construct the regional REP endpoint
const regionalEndpoint = `modelarmor.${location}.rep.googleapis.com`;
console.log(`Using endpoint: ${regionalEndpoint}`);
// Initialize the Model Armor client with options
const modelArmorClient = new ModelArmorClient({
apiEndpoint: regionalEndpoint,
});
const resourceName = `projects/${projectId}/locations/${location}/templates/${templateId}`;
try {
// Obtain the bidirectional stream object
const stream = modelArmorClient.streamSanitizeUserPrompt();
// Setup events for receiving responses
stream.on('data', (response) => {
if (response.sanitizationResult) {
const result = response.sanitizationResult;
console.log('Received response:');
console.log(` Match State: ${result.filterMatchState}`);
console.log(` Invocation Result: ${result.invocationResult}`);
} else {
console.log('Received empty response.');
}
});
stream.on('error', (err) => {
console.error('Stream error occurred:', err);
});
stream.on('end', () => {
console.log('Stream finished and closed.');
});
console.log('Sending requests...');
// --- Send First Request ---
const firstRequest = {
name: resourceName,
userPromptData: {
text: promptChunks[0]
},
streamingMode: 'STREAMING_MODE_BUFFERED' // Or 'STREAMING_MODE_REALTIME'
};
stream.write(firstRequest);
console.log(`Sent chunk 1: "${promptChunks[0]}"`);
// --- Send Subsequent Requests ---
for (let i = 1; i < promptChunks.length; i++) {
const subsequentRequest = {
name: resourceName,
userPromptData: {
text: promptChunks[i]
}
};
stream.write(subsequentRequest);
console.log(`Sent chunk ${i + 1}: "${promptChunks[i]}"`);
}
// Signals gRPC end-of-writing from client
stream.end();
console.log('Client finished sending.');
} catch (e) {
console.error('Error during stream initialization:', e);
}
}
// Execute logic
streamSanitizeUserPromptExample();
```
PHP
To run this code, first set up a PHP development environment and install the Model Armor PHP SDK.
use Google\ApiCore\ApiException;
use Google\ApiCore\BidiStream;
use Google\Cloud\ModelArmor\V1beta\Client\ModelArmorClient;
use Google\Cloud\ModelArmor\V1beta\DataItem;
use Google\Cloud\ModelArmor\V1beta\SanitizeUserPromptRequest;
use Google\Cloud\ModelArmor\V1beta\SanitizeUserPromptResponse;
use Google\Cloud\ModelArmor\V1beta\StreamingMode;
use Google\Cloud\ModelArmor\V1beta\FilterMatchState;
use Google\Cloud\ModelArmor\V1beta\InvocationResult;
function stream_sanitize_user_prompt_example()
{
$projectId = 'YOUR_PROJECT_ID';
$location = 'LOCATION_ID';
$templateId = 'YOUR_TEMPLATE_ID';
$promptChunks = [
"This is the first part of the user prompt. ",
"This is the second part. ",
"And this is the final part."
];
// Construct the regional REP endpoint (without port)
$regionalEndpoint = sprintf('modelarmor.%s.rep.googleapis.com', $location);
echo "Using endpoint: " . $regionalEndpoint . PHP_EOL;
try {
// Initialize the Model Armor client
$modelArmorClient = new ModelArmorClient([
'apiEndpoint' => $regionalEndpoint,
]);
// Construct the resource name.
$resourceName = sprintf('projects/%s/locations/%s/templates/%s', $projectId, $location, $templateId);
// Get a stream object for the StreamSanitizeUserPrompt API method.
$stream = $modelArmorClient->streamSanitizeUserPrompt();
echo "Sending requests..." . PHP_EOL;
// --- Send First Request ---
$firstRequest = (new SanitizeUserPromptRequest())
->setName($resourceName)
->setUserPromptData((new DataItem())->setText($promptChunks[0]))
->setStreamingMode(StreamingMode::STREAMING_MODE_BUFFERED); // Or STREAMING_MODE_REALTIME
$stream->write($firstRequest);
echo "Sent chunk 1: \"" . $promptChunks[0] . "\"" . PHP_EOL;
// --- Send Subsequent Requests ---
for ($i = 1; $i < count($promptChunks); $i++) {
$subsequentRequest = (new SanitizeUserPromptRequest())
->setName($resourceName)
->setUserPromptData((new DataItem())->setText($promptChunks[$i]));
$stream->write($subsequentRequest);
echo "Sent chunk " . ($i + 1) . ": \"" . $promptChunks[$i] . "\"" . PHP_EOL;
}
// Signal that the client has finished sending requests.
$stream->closeWrite();
echo "Client finished sending." . PHP_EOL;
// --- Receive Responses ---
echo "Receiving responses..." . PHP_EOL;
/** @var SanitizeUserPromptResponse $response */
foreach ($stream->closeWriteAndReadAll() as $response) {
if ($response->hasSanitizationResult()) {
$result = $response->getSanitizationResult();
echo "Received response:" . PHP_EOL;
echo " Match State: " . FilterMatchState::name($result->getFilterMatchState()) . PHP_EOL;
echo " Invocation Result: " . InvocationResult::name($result->getInvocationResult()) . PHP_EOL;
} else {
echo "Received empty response." . PHP_EOL;
}
}
echo "Stream finished and closed." . PHP_EOL;
} catch (ApiException $e) {
echo "Error during streaming: " . $e->getMessage() . PHP_EOL;
foreach ($e->getMetadata() as $key => $value) {
echo $key . ": " . print_r($value, true) . PHP_EOL;
}
} catch (Exception $e) {
echo "An unexpected error occurred: " . $e->getMessage() . PHP_EOL;
} finally {
if (isset($modelArmorClient)) {
$modelArmorClient->close();
}
}
}
stream_sanitize_user_prompt_example();
Python
To run this code, set up a Python development environment and install the Model Armor Python SDK.
from google.cloud import modelarmor_v1beta
def sample_stream_sanitize_user_prompt():
# Create a client
client = modelarmor_v1beta.ModelArmorClient(transport="grpc", client_options = {"api_endpoint" : "modelarmor.us-central1.rep.googleapis.com"})
# Specify the Google Project ID.
project_id = "YOUR_PROJECT_ID"
# Specify the location ID. For example, us-central1.
location = "LOCATION_ID"
# Specify the template ID.
template_id = "YOUR_TEMPLATE_ID"
template_name = client.template_path(project_id, location, template_id)
# Initialize request argument(s)
user_prompt_data = modelarmor_v1beta.DataItem()
# Specify the user prompt.
user_prompt_data.text = "This is a sample user prompt"
request = modelarmor_v1beta.SanitizeUserPromptRequest(
name=template_name,
user_prompt_data=user_prompt_data,
)
# This method expects an iterator which contains
# 'modelarmor_v1beta.SanitizeUserPromptRequest' objects
# Here we create a generator that yields a single `request` for
# demonstrative purposes.
requests = [request]
def request_generator():
for request in requests:
yield request
# Make the request
stream = client.stream_sanitize_user_prompt(requests=request_generator())
# Handle the response
for response in stream:
# Results can be consumed or assigned here in production workflows
sample_stream_sanitize_user_prompt()
Consider the following when sanitizing a streaming text prompt or response:
- To sanitize the content effectively, make sure that individual chunks don't exceed the token limits.
- Model Armor streaming methods support only textual input, not attachments like images and files.
- Use correlation ID to track streaming sanitization logs for a given request.
- Model Armor streaming methods don't support Sensitive Data Protection de-identification.
File-based prompts
To sanitize a prompt that is stored in a file, provide the file content in
base64 format. Model Armor doesn't automatically detect the file
type. You must explicitly set the byteDataType field to indicate the file
format. If the field is missing or not specified, the request fails. The possible
byteDataType values are PLAINTEXT_UTF8, PDF, WORD_DOCUMENT,
EXCEL_DOCUMENT, POWERPOINT_DOCUMENT, TXT, and CSV.
Sensitive Data Protection de-identification is not supported for file-based prompts.
REST
curl -X POST \ -d "$(jq -n \ --arg data "$(base64 -w 0 -i sample.pdf)" \ '{userPromptData: {byteItem: {byteDataType: "FILE_TYPE", byteData: $data}}}')" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID:sanitizeUserPrompt"
Replace the following:
PROJECT_ID: the ID of the project that the template belongs to.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.FILE_TYPE: the format of the input file.
Go
To run this code, first set up a Go development environment and install the Model Armor Go SDK.
C#
To run this code, first set up a C# development environment and install the Model Armor C# SDK.
Java
To run this code, first set up a Java development environment and install the Model Armor Java SDK.
Node.js
To run this code, first set up a Node.js development environment and install the Model Armor Node.js SDK.
PHP
To run this code, first set up a PHP development environment and install the Model Armor PHP SDK.
Python
To run this code, set up a Python development environment and install the Model Armor Python SDK.
Basic Sensitive Data Protection configuration
Model Armor integrates with Sensitive Data Protection to help prevent accidental exposure of private information. Create a template with basic Sensitive Data Protection settings enabled. Basic Sensitive Data Protection helps you screen for a fixed set of Sensitive Data Protection infoTypes.
The following Sensitive Data Protection infoTypes are scanned in the prompt for all regions:
CREDIT_CARD_NUMBER: A credit card number is 12 to 19 digits long. It is used for payment transactions globally.FINANCIAL_ACCOUNT_NUMBER: A number referring to a specific financial account, for example, a bank account number or a retirement account number.GCP_CREDENTIALS: Google Cloud service account credentials. Credentials that can be used to authenticate with {api_client_lib_name} and service accounts.GCP_API_KEY: Google Cloud API key. An encrypted string that is used when calling Google Cloud APIs that don't need to access private user data.PASSWORD: Clear text passwords in configs, code, and other text.
The following additional Sensitive Data Protection infoTypes are scanned in the prompt for US-based regions:
US_SOCIAL_SECURITY_NUMBER: A United States Social Security number (SSN) is a 9-digit number issued to US citizens, permanent residents, and temporary residents. This detector won't match against numbers with all zeros in any digit group (that is, 000-##-####, ###-00-####, or ###-##-0000), against numbers with 666 in the first digit group, or against numbers whose first digit is 9.US_INDIVIDUAL_TAXPAYER_IDENTIFICATION_NUMBER: A United States Individual Taxpayer Identification Number (ITIN) is a type of Tax Identification Number (TIN) issued by the Internal Revenue Service (IRS). An ITIN is a tax processing number only available for certain nonresident and resident aliens, their spouses, and dependents who cannot get a Social Security Number (SSN).
Here's an example basic Sensitive Data Protection configuration:
gcloud
gcloud model-armor templates create TEMPLATE_ID \ --location=LOCATION \ --project=PROJECT_ID \ --basic-config-filter-enforcement=enabled
Replace the following:
TEMPLATE_ID: the ID of the template.LOCATION: the location of the template.
REST
export FILTER_CONFIG_SDP_BASIC='{ "filterConfig": { "sdpSettings": { "basicConfig": { "filterEnforcement": "ENABLED" } } } }' curl -X PATCH \ -d "$FILTER_CONFIG_SDP_BASIC" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID?updateMask=filterConfig.sdpSettings.basicConfig.filterEnforcement"
Replace the following:
PROJECT_ID: the ID of the project that the template belongs to.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.
Go
To run this code, first set up a Go development environment and install the Model Armor Go SDK.
C#
To run this code, first set up a C# development environment and install the Model Armor C# SDK.
Java
To run this code, first set up a Java development environment and install the Model Armor Java SDK.
Node.js
To run this code, first set up a Node.js development environment and install the Model Armor Node.js SDK.
PHP
To run this code, first set up a PHP development environment and install the Model Armor PHP SDK.
Python
To run this code, set up a Python development environment and install the Model Armor Python SDK.
Use the template created to screen your prompts. Here's an example:
curl -X POST \ -d '{"userPromptData":{"text":"can you remember my ITIN : ###-##-####"}}' \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID:sanitizeUserPrompt"
Replace the following:
PROJECT_ID: the ID of the project that the template belongs to.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.
This example returns the following response:
{ "sanitizationResult": { "filterMatchState": "MATCH_FOUND", "invocationResult": "SUCCESS", "filterResults": [ { "csamFilterFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, { "sdpFilterResult": { "inspectResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "MATCH_FOUND", "findings": [ { "infoType": "US_INDIVIDUAL_TAXPAYER_IDENTIFICATION_NUMBER", "likelihood": "LIKELY", "location": { "byteRange": { "start": "26", "end": "37" }, "codepointRange": { "start": "26", "end": "37" } } } ] } } } ] } }
Advanced Sensitive Data Protection configuration
Model Armor screens the LLM prompts and responses using the advanced Sensitive Data Protection configuration setting. This lets you use Sensitive Data Protection capabilities beyond the infoTypes offered in the basic Sensitive Data Protection setting.
To use the Sensitive Data Protection advanced filter in Model Armor, the Sensitive Data Protection templates must be in the same cloud location as the Model Armor template.
gcloud
gcloud model-armor templates create TEMPLATE_ID \ --location=LOCATION \ --advanced-config-inspect-template="path/to/template" \
Replace the following:
TEMPLATE_ID: the ID of the template.LOCATION: the location of the template.
REST
export FILTER_CONFIG_SDP_ADV='{ "filterConfig": { "sdpSettings": { "advancedConfig": { "deidentifyTemplate": "projects/PROJECT_ID/locations/LOCATION/deidentifyTemplates/deidentify-ip-address", "inspectTemplate": "projects/PROJECT_ID/locations/LOCATION/inspectTemplates/inspect-ip-address" } } } }' curl -X POST \ -d "$FILTER_CONFIG_SDP_ADV" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID?updateMask=filterConfig.sdpSettings.advancedConfig"
Replace the following:
PROJECT_ID: the ID of the project that the template belongs to.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.
This example returns the following response:
{ "name": "projects/PROJECT_ID/locations/LOCATION/templates/all-filters-test", "createTime": "2024-12-16T17:08:19.626693819Z", "updateTime": "2024-12-16T17:08:19.626693819Z", "filterConfig": { "sdpSettings": { "advancedConfig": { "deidentifyTemplate": "projects/PROJECT_ID/locations/LOCATION/deidentifyTemplates/deidentify-ip-address", "inspectTemplate": "projects/PROJECT_ID/locations/LOCATION/inspectTemplates/inspect-ip-address" } } } }
C#
To run this code, first set up a C# development environment and install the Model Armor C# SDK.
Go
To run this code, first set up a Go development environment and install the Model Armor Go SDK.
Java
To run this code, first set up a Java development environment and install the Model Armor Java SDK.
Node.js
To run this code, first set up a Node.js development environment and install the Model Armor Node.js SDK.
PHP
To run this code, first set up a PHP development environment and install the Model Armor PHP SDK.
Python
To run this code, set up a Python development environment and install the Model Armor Python SDK.
Use the template created to screen your prompts. Here's an example:
curl -X POST \ -d '{"userPromptData":{"text":"is there anything malicious running on 1.1.1.1?"}}' \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID:sanitizeUserPrompt"
Replace the following:
PROJECT_ID: the ID of the project that the template belongs to.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.
This example returns the following response:
{ "sanitizationResult": { "filterMatchState": "MATCH_FOUND", "invocationResult": "SUCCESS", "filterResults": [ { "csamFilterFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, { "sdpFilterResult": { "deidentifyResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "MATCH_FOUND", "data": { "text": "is there anything malicious running on [IP_ADDRESS]?" }, "transformedBytes": "7", "infoTypes": ["IP_ADDRESS"] } } } ] } }
For information about image redaction requests and responses, see Redact images.
Sanitize model response
LLMs can sometimes generate harmful responses. To reduce the risks associated with using LLMs in your applications, it is important to sanitize their responses.
Here's an example command to sanitize a model response in Model Armor.
REST
curl -X POST \
-d '{"modelResponseData":{"text":"IP address of the current network is ##.##.##.##"}}' \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID:sanitizeModelResponse"
Replace the following:
PROJECT_ID: the ID of the project that the template belongs to.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.This example returns the following response:
{ "sanitizationResult": { "filterMatchState": "MATCH_FOUND", "invocationResult": "SUCCESS", "filterResults": { "rai": { "raiFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "MATCH_FOUND", "raiFilterTypeResults": { "dangerous": { "confidenceLevel": "MEDIUM_AND_ABOVE", "matchState": "MATCH_FOUND" }, "sexually_explicit": { "matchState": "NO_MATCH_FOUND" }, "hate_speech": { "matchState": "NO_MATCH_FOUND" }, "harassment": { "matchState": "NO_MATCH_FOUND" } } } }, "pi_and_jailbreak": { "piAndJailbreakFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, "csam": { "csamFilterFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, "malicious_uris": { "maliciousUriFilterResult": { "executionState": "EXECUTION_SUCCESS", "matchState": "NO_MATCH_FOUND" } }, } } }
C#
To run this code, first set up a C# development environment and install the Model Armor C# SDK.
Go
To run this code, first set up a Go development environment and install the Model Armor Go SDK.
Java
To run this code, first set up a Java development environment and install the Model Armor Java SDK.
Node.js
To run this code, first set up a Node.js development environment and install the Model Armor Node.js SDK.
PHP
To run this code, first set up a PHP development environment and install the Model Armor PHP SDK.
Python
To run this code, set up a Python development environment and install the Model Armor Python SDK.
Sanitize model response with multi-language detection enabled
Enable multi-language detection on a per-request basis by setting the
enableMultiLanguageDetection flag to true for each individual response.
Optionally, you can specify the
source language
for more accurate results.
- If you don't specify the source language, Model Armor automatically detects the language to provide multi-language support.
- If you specify the source language, Model Armor uses that language to evaluate the model response and doesn't perform automatic language detection.
curl -X POST \ -d '{"modelResponseData":{"text":"[UNSAFE TEXT]"}, "multiLanguageDetectionMetadata": { "enableMultiLanguageDetection": true , "sourceLanguage": "jp"}}' \ -H "Content-Type: application/json" \ -H "Authorization: Bearer $(gcloud auth print-access-token)" \ "https://modelarmor.LOCATION.rep.googleapis.com/v1/projects/PROJECT_ID/locations/LOCATION/templates/TEMPLATE_ID:sanitizeModelResponse"
Replace the following:
PROJECT_ID: the ID of the project that the template belongs to.LOCATION: the location of the template.TEMPLATE_ID: the ID of the template.
Sanitize model response across projects
To enable centralized AI safety management, organizations often store
Model Armor templates in a dedicated project
(project A: TEMPLATE_PROJECT_ID) while their applications run in separate
projects (project B).
To allow a service account (CALLER_SERVICE_ACCOUNT) from project B to access
a template in project A, you must add an IAM policy binding to
the template project.
To grant the necessary cross-project permissions, run the following command:
gcloud projects add-iam-policy-binding TEMPLATE_PROJECT_ID \ --member='serviceAccount:CALLER_SERVICE_ACCOUNT' \ --role='roles/modelarmor.user'
Replace the following:
TEMPLATE_PROJECT_ID: the ID of the project where the template is hosted.CALLER_SERVICE_ACCOUNT: the service account from the project making the API request.
What's next
- Learn more about Model Armor.
- Learn about Model Armor floor settings.
- Learn about Model Armor templates.
- Troubleshoot Model Armor issues.