Sanitize prompts and responses

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:

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

  1. Enable the Model Armor API.

    Roles required to enable APIs

    To enable APIs, you need the serviceusage.services.enable permission. If you created the project, then you likely already have this permission through the Owner role (roles/owner). Otherwise, you can get this permission through the Service Usage Admin role (roles/serviceusage.serviceUsageAdmin). Learn how to grant roles.

    Enable the API

  2. 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:

  1. In the Google Cloud console, activate Cloud Shell.

    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.

  2. Set the API endpoint override using the gcloud CLI.

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.


import (
	"context"
	"fmt"
	"io"

	modelarmor "cloud.google.com/go/modelarmor/apiv1"
	modelarmorpb "cloud.google.com/go/modelarmor/apiv1/modelarmorpb"
	"google.golang.org/api/option"
)

// sanitizeUserPrompt sanitizes a user prompt based on the project, location, and template settings.
//
// w io.Writer: The writer to use for logging.
// projectID string: The ID of the project.
// locationID string: The ID of the location.
// templateID string: The ID of the template.
// userPrompt string: The user prompt to sanitize.
func sanitizeUserPrompt(w io.Writer, projectID, locationID, templateID, userPrompt string) error {
	ctx := context.Background()

	//Create options for Model Armor client.
	opts := option.WithEndpoint(fmt.Sprintf("modelarmor.%s.rep.googleapis.com:443", locationID))

	// Create the Model Armor client.
	client, err := modelarmor.NewClient(ctx, opts)
	if err != nil {
		return fmt.Errorf("failed to create client for location %s: %w", locationID, err)
	}
	defer client.Close()

	// Initialize request argument(s)
	userPromptData := &modelarmorpb.DataItem{
		DataItem: &modelarmorpb.DataItem_Text{
			Text: userPrompt,
		},
	}

	// Prepare request for sanitizing user prompt.
	req := &modelarmorpb.SanitizeUserPromptRequest{
		Name:           fmt.Sprintf("projects/%s/locations/%s/templates/%s", projectID, locationID, templateID),
		UserPromptData: userPromptData,
	}

	// Sanitize the user prompt.
	response, err := client.SanitizeUserPrompt(ctx, req)
	if err != nil {
		return fmt.Errorf("failed to sanitize user prompt for template %s: %w", templateID, err)
	}

	// Sanitization Result.
	fmt.Fprintf(w, "Sanitization Result: %v\n", response)

	return nil
}

C#

To run this code, first set up a C# development environment and install the Model Armor C# SDK.

using Google.Api.Gax.ResourceNames;
using Google.Cloud.ModelArmor.V1;
using Newtonsoft.Json;
using System;

namespace ModelArmor.Samples
{
    public class SanitizeUserPromptSample
    {
        public SanitizeUserPromptResponse SanitizeUserPrompt(
            string projectId = "my-project",
            string locationId = "us-central1",
            string templateId = "my-template",
            string userPrompt = "Unsafe user prompt"
        )
        {
            // Endpoint to call the Model Armor server.
            ModelArmorClientBuilder clientBuilder = new ModelArmorClientBuilder
            {
                Endpoint = $"modelarmor.{locationId}.rep.googleapis.com",
            };

            // Create the client.
            ModelArmorClient client = clientBuilder.Build();

            // Build the resource name of the template.
            TemplateName templateName = TemplateName.FromProjectLocationTemplate(projectId, locationId, templateId);

            // Prepare the request.
            SanitizeUserPromptRequest request = new SanitizeUserPromptRequest
            {
                TemplateName = templateName,
                UserPromptData = new DataItem { Text = userPrompt },
            };

            // Send the request and get the response.
            SanitizeUserPromptResponse response = client.SanitizeUserPrompt(request);

            return response;
        }
    }
}

Java

To run this code, first set up a Java development environment and install the Model Armor Java SDK.


import com.google.cloud.modelarmor.v1.DataItem;
import com.google.cloud.modelarmor.v1.ModelArmorClient;
import com.google.cloud.modelarmor.v1.ModelArmorSettings;
import com.google.cloud.modelarmor.v1.SanitizeUserPromptRequest;
import com.google.cloud.modelarmor.v1.SanitizeUserPromptResponse;
import com.google.cloud.modelarmor.v1.TemplateName;
import com.google.protobuf.util.JsonFormat;
import java.io.IOException;

public class SanitizeUserPrompt {

  public static void main(String[] args) throws IOException {
    // TODO(developer): Replace these variables before running the sample.

    // Specify the Google Project ID.
    String projectId = "your-project-id";
    // Specify the location ID. For example, us-central1.
    String locationId = "your-location-id";
    // Specify the template ID.
    String templateId = "your-template-id";
    // Specify the user prompt.
    String userPrompt = "Unsafe user prompt";

    sanitizeUserPrompt(projectId, locationId, templateId, userPrompt);
  }

  public static SanitizeUserPromptResponse sanitizeUserPrompt(String projectId, String locationId,
      String templateId, String userPrompt) throws IOException {

    // Endpoint to call the Model Armor server.
    String apiEndpoint = String.format("modelarmor.%s.rep.googleapis.com:443", locationId);
    ModelArmorSettings modelArmorSettings = ModelArmorSettings.newBuilder()
        .setEndpoint(apiEndpoint)
        .build();

    try (ModelArmorClient client = ModelArmorClient.create(modelArmorSettings)) {
      // Build the resource name of the template.
      String templateName = TemplateName.of(projectId, locationId, templateId).toString();

      // Prepare the request.
      SanitizeUserPromptRequest request = SanitizeUserPromptRequest.newBuilder()
          .setName(templateName)
          .setUserPromptData(DataItem.newBuilder().setText(userPrompt).build())
          .build();

      SanitizeUserPromptResponse response = client.sanitizeUserPrompt(request);
      System.out.println("Result for the provided user prompt: "
          + JsonFormat.printer().print(response.getSanitizationResult()));

      return response;
    }
  }
}

Node.js

To run this code, first set up a Node.js development environment and install the Model Armor Node.js SDK.

/**
 * TODO(developer): Uncomment these variables before running the sample.
 */
// const projectId = process.env.PROJECT_ID || 'your-project-id';
// const locationId = process.env.LOCATION_ID || 'us-central1';
// const templateId = process.env.TEMPLATE_ID || 'template-id';
// const userPrompt = 'unsafe user prompt';
const {ModelArmorClient} = require('@google-cloud/modelarmor').v1;

const client = new ModelArmorClient({
  apiEndpoint: `modelarmor.${locationId}.rep.googleapis.com`,
});

const request = {
  name: `projects/${projectId}/locations/${locationId}/templates/${templateId}`,
  userPromptData: {
    text: userPrompt,
  },
};

const [response] = await client.sanitizeUserPrompt(request);
console.log(JSON.stringify(response, null, 2));
return response;

PHP

To run this code, first set up a PHP development environment and install the Model Armor PHP SDK.

use Google\Cloud\ModelArmor\V1\Client\ModelArmorClient;
use Google\Cloud\ModelArmor\V1\SanitizeUserPromptRequest;
use Google\Cloud\ModelArmor\V1\DataItem;

/**
 * Sanitizes a user prompt using the specified template.
 *
 * @param string $projectId The ID of your Google Cloud Platform project (e.g. 'my-project').
 * @param string $locationId The ID of the location where the template is stored (e.g. 'us-central1').
 * @param string $templateId The ID of the template (e.g. 'my-template').
 * @param string $userPrompt The user prompt to sanitize (e.g. 'my-user-prompt').
 */
function sanitize_user_prompt(
    string $projectId,
    string $locationId,
    string $templateId,
    string $userPrompt
): void {
    $options = ['apiEndpoint' => "modelarmor.$locationId.rep.googleapis.com"];
    $client = new ModelArmorClient($options);

    $userPromptRequest = (new SanitizeUserPromptRequest())
        ->setName("projects/$projectId/locations/$locationId/templates/$templateId")
        ->setUserPromptData((new DataItem())->setText($userPrompt));

    $response = $client->sanitizeUserPrompt($userPromptRequest);

    printf('Result for Sanitize User Prompt: %s' . PHP_EOL, $response->serializeToJsonString());
}

Python

To run this code, set up a Python development environment and install the Model Armor Python SDK.


from google.api_core.client_options import ClientOptions
from google.cloud import modelarmor_v1

# TODO(Developer): Uncomment these variables.
# project_id = "YOUR_PROJECT_ID"
# location_id = "us-central1"
# template_id = "template_id"
# user_prompt = "Prompt entered by the user"

# Create the Model Armor client.
client = modelarmor_v1.ModelArmorClient(
    transport="rest",
    client_options=ClientOptions(
        api_endpoint=f"modelarmor.{location_id}.rep.googleapis.com"
    ),
)

# Initialize request argument(s).
user_prompt_data = modelarmor_v1.DataItem(text=user_prompt)

# Prepare request for sanitizing the defined prompt.
request = modelarmor_v1.SanitizeUserPromptRequest(
    name=f"projects/{project_id}/locations/{location_id}/templates/{template_id}",
    user_prompt_data=user_prompt_data,
)

# Sanitize the user prompt.
response = client.sanitize_user_prompt(request=request)

# Sanitization Result.
print(response)

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 SanitizeUserPrompt API 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. The userPromptData field 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 userPromptData field.

  • Don't include system prompts: The system prompt shouldn't be included in the userPromptData field. 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:

  1. Chunked input: Your application sends text to Model Armor in smaller pieces (chunks) instead of sending the entire text body at once.
  2. Real-time processing: Model Armor processes these chunks as they arrive and applies the security and safety filters configured in your template.
  3. 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++) {