!function(){function t(t){document.documentElement.setAttribute("data-theme",t)}var e=function(){var t=null;try{t=new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}return t}()||function(){var t=null;try{t=localStorage.getItem("theme")}catch(t){}return t}();t(null!==e?e:"light")}(),document.documentElement.setAttribute("data-announcement-bar-initially-dismissed",function(){try{return"true"===localStorage.getItem("docusaurus.announcement.dismiss")}catch(t){}return!1}())

[Skip to main content](#__docusaurus_skipToContent_fallback)

LangChain v0.2 is coming soon! Preview the new docs [here](/v0.2/docs/introduction/).

[

![🦜️🔗 Langchain](/v0.1/img/brand/wordmark.png)![🦜️🔗 Langchain](/v0.1/img/brand/wordmark-dark.png)

](/v0.1/)[Docs](/v0.1/docs/get_started/introduction/)[Use cases](/v0.1/docs/use_cases/)[Integrations](/v0.1/docs/integrations/platforms/)[API Reference](https://api.js.langchain.com)

[More](#)

*   [People](/v0.1/docs/people/)
*   [Community](/v0.1/docs/community/)
*   [Tutorials](/v0.1/docs/additional_resources/tutorials/)
*   [Contributing](/v0.1/docs/contributing/)

[v0.1](#)

*   [v0.2](https://js.langchain.com/v0.2/docs/introduction)
*   [v0.1](/v0.1/docs/get_started/introduction/)

[🦜🔗](#)

*   [LangSmith](https://smith.langchain.com)
*   [LangSmith Docs](https://docs.smith.langchain.com)
*   [LangChain Hub](https://smith.langchain.com/hub)
*   [LangServe](https://github.com/langchain-ai/langserve)
*   [Python Docs](https://python.langchain.com/)

[Chat](https://chatjs.langchain.com)[](https://github.com/langchain-ai/langchainjs)

Search

*   [Get started](/v0.1/docs/get_started/)
    
    *   [Introduction](/v0.1/docs/get_started/introduction/)
    *   [Installation](/v0.1/docs/get_started/installation/)
    *   [Quickstart](/v0.1/docs/get_started/quickstart/)
*   [LangChain Expression Language](/v0.1/docs/expression_language/)
    
    *   [Get started](/v0.1/docs/expression_language/get_started/)
    *   [Why use LCEL?](/v0.1/docs/expression_language/why/)
    *   [Interface](/v0.1/docs/expression_language/interface/)
    *   [Streaming](/v0.1/docs/expression_language/streaming/)
    *   [How to](/v0.1/docs/expression_language/how_to/routing/)
        
    *   [Cookbook](/v0.1/docs/expression_language/cookbook/)
        
    *   [LangChain Expression Language (LCEL)](/v0.1/docs/expression_language/)
*   [Modules](/v0.1/docs/modules/)
    
    *   [Model I/O](/v0.1/docs/modules/model_io/)
        
    *   [Retrieval](/v0.1/docs/modules/data_connection/)
        
    *   [Chains](/v0.1/docs/modules/chains/)
    *   [Agents](/v0.1/docs/modules/agents/)
        
    *   [More](/v0.1/docs/modules/memory/)
        
        *   [Memory](/v0.1/docs/modules/memory/)
            
        *   [Callbacks](/v0.1/docs/modules/callbacks/)
            
        *   [Experimental](/v0.1/docs/modules/experimental/)
            
            *   [Masking](/v0.1/docs/modules/experimental/mask/)
            *   [Prompts](/v0.1/docs/modules/experimental/prompts/custom_formats/)
                
            *   [Experimental](/v0.1/docs/modules/experimental/)
*   [Security](/v0.1/docs/security/)
*   [Guides](/v0.1/docs/guides/)
    
*   [Ecosystem](/v0.1/docs/ecosystem/)
    
*   [LangGraph](/v0.1/docs/langgraph/)
*   * * *
    

*   [](/v0.1/)
*   [Modules](/v0.1/docs/modules/)
*   More
*   [Experimental](/v0.1/docs/modules/experimental/)
*   Masking

On this page

Masking
=======

The experimental masking parser and transformer is an extendable module for masking and rehydrating strings. One of the primary use cases for this module is to redact PII (Personal Identifiable Information) from a string before making a call to an llm.

### Real world scenario[​](#real-world-scenario "Direct link to Real world scenario")

A customer support system receives messages containing sensitive customer information. The system must parse these messages, mask any PII (like names, email addresses, and phone numbers), and log them for analysis while complying with privacy regulations. Before logging the transcript a summary is generated using an llm.

Get started[​](#get-started "Direct link to Get started")
---------------------------------------------------------

### Basic Example[​](#basic-example "Direct link to Basic Example")

Use the RegexMaskingTransformer to create a simple mask for email and phone.

tip

See [this section for general instructions on installing integration packages](/v0.1/docs/get_started/installation/#installing-integration-packages).

*   npm
*   Yarn
*   pnpm

    npm install @langchain/openai

    yarn add @langchain/openai

    pnpm add @langchain/openai

    import {  MaskingParser,  RegexMaskingTransformer,} from "langchain/experimental/masking";// Define masking strategyconst emailMask = () => `[email-${Math.random().toString(16).slice(2)}]`;const phoneMask = () => `[phone-${Math.random().toString(16).slice(2)}]`;// Configure pii transformerconst piiMaskingTransformer = new RegexMaskingTransformer({  email: { regex: /\S+@\S+\.\S+/g, mask: emailMask },  phone: { regex: /\d{3}-\d{3}-\d{4}/g, mask: phoneMask },});const maskingParser = new MaskingParser({  transformers: [piiMaskingTransformer],});maskingParser.addTransformer(piiMaskingTransformer);const input =  "Contact me at jane.doe@email.com or 555-123-4567. Also reach me at john.smith@email.com";const masked = await maskingParser.mask(input);console.log(masked);// Contact me at [email-a31e486e324f6] or [phone-da8fc1584f224]. Also reach me at [email-d5b6237633d95]const rehydrated = await maskingParser.rehydrate(masked);console.log(rehydrated);// Contact me at jane.doe@email.com or 555-123-4567. Also reach me at john.smith@email.com

#### API Reference:

*   [MaskingParser](https://api.js.langchain.com/classes/langchain_experimental_masking.MaskingParser.html) from `langchain/experimental/masking`
*   [RegexMaskingTransformer](https://api.js.langchain.com/classes/langchain_experimental_masking.RegexMaskingTransformer.html) from `langchain/experimental/masking`

note

If you plan on storing the masking state to rehydrate the original values asynchronously ensure you are following best security practices. In most cases you will want to define a custom hashing and salting strategy.

### Next.js stream[​](#nextjs-stream "Direct link to Next.js stream")

Example nextjs chat endpoint leveraging the RegexMaskingTransformer. The current chat message and chat message history are masked every time the api is called with a chat payload.

    // app/api/chatimport {  MaskingParser,  RegexMaskingTransformer,} from "langchain/experimental/masking";import { ChatOpenAI } from "@langchain/openai";import { PromptTemplate } from "@langchain/core/prompts";import { BytesOutputParser } from "@langchain/core/output_parsers";export const runtime = "edge";// Function to format chat messages for consistencyconst formatMessage = (message: any) => `${message.role}: ${message.content}`;const CUSTOMER_SUPPORT = `You are a customer support summarizer agent. Always include masked PII in your response.  Current conversation:  {chat_history}  User: {input}  AI:`;// Configure Masking Parserconst maskingParser = new MaskingParser();// Define transformations for masking emails and phone numbers using regular expressionsconst piiMaskingTransformer = new RegexMaskingTransformer({  email: { regex: /\S+@\S+\.\S+/g }, // If a regex is provided without a mask we fallback to a simple default hashing function  phone: { regex: /\d{3}-\d{3}-\d{4}/g },});maskingParser.addTransformer(piiMaskingTransformer);export async function POST(req: Request) {  try {    const body = await req.json();    const messages = body.messages ?? [];    const formattedPreviousMessages = messages.slice(0, -1).map(formatMessage);    const currentMessageContent = messages[messages.length - 1].content; // Extract the content of the last message    // Mask sensitive information in the current message    const guardedMessageContent = await maskingParser.mask(      currentMessageContent    );    // Mask sensitive information in the chat history    const guardedHistory = await maskingParser.mask(      formattedPreviousMessages.join("\n")    );    const prompt = PromptTemplate.fromTemplate(CUSTOMER_SUPPORT);    const model = new ChatOpenAI({ temperature: 0.8 });    // Initialize an output parser that handles serialization and byte-encoding for streaming    const outputParser = new BytesOutputParser();    const chain = prompt.pipe(model).pipe(outputParser); // Chain the prompt, model, and output parser together    console.log("[GUARDED INPUT]", guardedMessageContent); // Contact me at -1157967895 or -1626926859.    console.log("[GUARDED HISTORY]", guardedHistory); // user: Contact me at -1157967895 or -1626926859. assistant: Thank you for providing your contact information.    console.log("[STATE]", maskingParser.getState()); // { '-1157967895' => 'jane.doe@email.com', '-1626926859' => '555-123-4567'}    // Stream the AI response based on the masked chat history and current message    const stream = await chain.stream({      chat_history: guardedHistory,      input: guardedMessageContent,    });    return new Response(stream, {      headers: { "content-type": "text/plain; charset=utf-8" },    });  } catch (e: any) {    return new Response(JSON.stringify({ error: e.message }), {      status: 500,      headers: {        "content-type": "application/json",      },    });  }}

#### API Reference:

*   [MaskingParser](https://api.js.langchain.com/classes/langchain_experimental_masking.MaskingParser.html) from `langchain/experimental/masking`
*   [RegexMaskingTransformer](https://api.js.langchain.com/classes/langchain_experimental_masking.RegexMaskingTransformer.html) from `langchain/experimental/masking`
*   [ChatOpenAI](https://api.js.langchain.com/classes/langchain_openai.ChatOpenAI.html) from `@langchain/openai`
*   [PromptTemplate](https://api.js.langchain.com/classes/langchain_core_prompts.PromptTemplate.html) from `@langchain/core/prompts`
*   [BytesOutputParser](https://api.js.langchain.com/classes/langchain_core_output_parsers.BytesOutputParser.html) from `@langchain/core/output_parsers`

### Kitchen sink[​](#kitchen-sink "Direct link to Kitchen sink")

    import {  MaskingParser,  RegexMaskingTransformer,} from "langchain/experimental/masking";// A simple hash function for demonstration purposesfunction simpleHash(input: string): string {  let hash = 0;  for (let i = 0; i < input.length; i += 1) {    const char = input.charCodeAt(i);    hash = (hash << 5) - hash + char;    hash |= 0; // Convert to 32bit integer  }  return hash.toString(16);}const emailMask = (match: string) => `[email-${simpleHash(match)}]`;const phoneMask = (match: string) => `[phone-${simpleHash(match)}]`;const nameMask = (match: string) => `[name-${simpleHash(match)}]`;const ssnMask = (match: string) => `[ssn-${simpleHash(match)}]`;const creditCardMask = (match: string) => `[creditcard-${simpleHash(match)}]`;const passportMask = (match: string) => `[passport-${simpleHash(match)}]`;const licenseMask = (match: string) => `[license-${simpleHash(match)}]`;const addressMask = (match: string) => `[address-${simpleHash(match)}]`;const dobMask = (match: string) => `[dob-${simpleHash(match)}]`;const bankAccountMask = (match: string) => `[bankaccount-${simpleHash(match)}]`;// Regular expressions for different types of PIIconst patterns = {  email: { regex: /\S+@\S+\.\S+/g, mask: emailMask },  phone: { regex: /\b\d{3}-\d{3}-\d{4}\b/g, mask: phoneMask },  name: { regex: /\b[A-Z][a-z]+ [A-Z][a-z]+\b/g, mask: nameMask },  ssn: { regex: /\b\d{3}-\d{2}-\d{4}\b/g, mask: ssnMask },  creditCard: { regex: /\b(?:\d{4}[ -]?){3}\d{4}\b/g, mask: creditCardMask },  passport: { regex: /(?i)\b[A-Z]{1,2}\d{6,9}\b/g, mask: passportMask },  license: { regex: /(?i)\b[A-Z]{1,2}\d{6,8}\b/g, mask: licenseMask },  address: {    regex: /\b\d{1,5}\s[A-Z][a-z]+(?:\s[A-Z][a-z]+)\*\b/g,    mask: addressMask,  },  dob: { regex: /\b\d{4}-\d{2}-\d{2}\b/g, mask: dobMask },  bankAccount: { regex: /\b\d{8,17}\b/g, mask: bankAccountMask },};// Create a RegexMaskingTransformer with multiple patternsconst piiMaskingTransformer = new RegexMaskingTransformer(patterns);// Hooks for different stages of masking and rehydratingconst onMaskingStart = (message: string) =>  console.log(`Starting to mask message: ${message}`);const onMaskingEnd = (maskedMessage: string) =>  console.log(`Masked message: ${maskedMessage}`);const onRehydratingStart = (message: string) =>  console.log(`Starting to rehydrate message: ${message}`);const onRehydratingEnd = (rehydratedMessage: string) =>  console.log(`Rehydrated message: ${rehydratedMessage}`);// Initialize MaskingParser with the transformer and hooksconst maskingParser = new MaskingParser({  transformers: [piiMaskingTransformer],  onMaskingStart,  onMaskingEnd,  onRehydratingStart,  onRehydratingEnd,});// Example message containing multiple types of PIIconst message =  "Contact Jane Doe at jane.doe@email.com or 555-123-4567. Her SSN is 123-45-6789 and her credit card number is 1234-5678-9012-3456. Passport number: AB1234567, Driver's License: X1234567, Address: 123 Main St, Date of Birth: 1990-01-01, Bank Account: 12345678901234567.";// Mask and rehydrate the messagemaskingParser  .mask(message)  .then((maskedMessage: string) => {    console.log(`Masked message: ${maskedMessage}`);    return maskingParser.rehydrate(maskedMessage);  })  .then((rehydratedMessage: string) => {    console.log(`Final rehydrated message: ${rehydratedMessage}`);  });

#### API Reference:

*   [MaskingParser](https://api.js.langchain.com/classes/langchain_experimental_masking.MaskingParser.html) from `langchain/experimental/masking`
*   [RegexMaskingTransformer](https://api.js.langchain.com/classes/langchain_experimental_masking.RegexMaskingTransformer.html) from `langchain/experimental/masking`

* * *

#### Help us out by providing feedback on this documentation page:

[

Previous

Experimental

](/v0.1/docs/modules/experimental/)[

Next

Custom template formats

](/v0.1/docs/modules/experimental/prompts/custom_formats/)

*   [Real world scenario](#real-world-scenario)
*   [Get started](#get-started)
    *   [Basic Example](#basic-example)
    *   [Next.js stream](#nextjs-stream)
    *   [Kitchen sink](#kitchen-sink)

Community

*   [Discord](https://discord.gg/cU2adEyC7w)
*   [Twitter](https://twitter.com/LangChainAI)

GitHub

*   [Python](https://github.com/langchain-ai/langchain)
*   [JS/TS](https://github.com/langchain-ai/langchainjs)

More

*   [Homepage](https://langchain.com)
*   [Blog](https://blog.langchain.dev)

Copyright © 2024 LangChain, Inc.