> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getlimina.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LLM Prompt Redaction

> Learn how to use the headless or API version of Limina to preserve privacy inside applications using LLMs like ChatGPT and GPT4.

## Introduction

In this guide, you'll learn how to use Limina to perform prompt redaction and re-hydration. The guide is centred around handling personally identifiable data: you'll deidentify user prompts, send them to OpenAI's ChatGPT, and then re-identify the responses. This ensures confidential information remains safe while interacting with AI models. The process looks like this:

<img src="https://mintcdn.com/privateai/M3ZgbHyjju_DLBZg/images/llm-prompt-redaction/how-it-works.png?fit=max&auto=format&n=M3ZgbHyjju_DLBZg&q=85&s=35aee2bf5c8d3ad9dcecad5742511fa7" alt="Overview of PrivateGPT workflow" width="14652" height="5901" data-path="images/llm-prompt-redaction/how-it-works.png" />

In addition to this guide, you might find the following notebooks and code examples useful.

| Title                                                                                                                                                                                                                              | LLM Provider             | Format        |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------ | ------------- |
| [Safely work with Company Confidential Information with Limina](https://github.com/privateai/deid-examples/blob/main/python/LLM%20Examples/Removing%20Confidential%20Financial%20Information%20via%20Redaction%20for%20LLMs.ipynb) | OpenAI                   | Notebook      |
| [SEC Filing: Document Summarization and Question Answering](https://github.com/privateai/deid-examples/blob/main/python/LLM%20Examples/PAI-Cohere.ipynb)                                                                           | Cohere                   | Notebook      |
| [SEC Filing: Document Summarization and Question Answering](https://github.com/privateai/deid-examples/blob/main/python/LLM%20Examples/PAI-PaLM.ipynb)                                                                             | Google                   | Notebook      |
| [Secure Prompting with Limina](https://github.com/privateai/deid-examples/blob/main/python/LLM%20Examples/secure_prompt.py)                                                                                                        | OpenAI, Google or Cohere | Python Script |
| [Secure Prompting with Limina - Files](https://github.com/privateai/deid-examples/blob/main/python/LLM%20Examples/secure_prompt_from_file.py)                                                                                      | OpenAI, Google or Cohere | Python Script |

<Steps>
  <Step titleSize="h2" title="Environment Setup and Configuration">
    First, we need to pull and run the Limina Docker container, which is responsible for data deidentification and re-identification. Follow the instructions in the [Quickstart Guide](/container-quickstart/quickstart-guide) to set up your Docker container.

    The next step is setting up the rest of your environment. You will need to install necessary Python libraries, import the required modules in your script, and configure your API keys.

    Let's install the `privateai_client` and `openai` Python libraries using pip (this has been tested with Limina Client version 1.3.2 and Open AI Client version 0.28.0):

    ```shell pip install lines wrap theme={"theme":"poimandres"}
    pip install privateai_client openai
    ```

    Now in your Python script, you'll need to initialize the requisite constants and client libraries:

    ```python Initialize constants and import library lines wrap theme={"theme":"poimandres"}
    from privateai_client import PAIClient, request_objects
    import openai
    import os

    # Initialize the openai client
    openai.api_key = os.getenv('OPENAI_KEY')

    # initialize the privateai client
    PRIVATEAI_SCHEME = 'http'
    PRIVATEAI_HOST = 'localhost'
    PRIVATEAI_PORT = '8080'
    client = PAIClient(PRIVATEAI_SCHEME, PRIVATEAI_HOST, PRIVATEAI_PORT)
    ```

    Remember to set a local environment variable named `OPENAI_KEY` with your actual OpenAI [API key](https://platform.openai.com/account/api-keys), and set the `PRIVATEAI_SCHEME`, `PRIVATEAI_HOST`, and `PRIVATEAI_PORT` variables according to where your local Docker container is running.
  </Step>

  <Step titleSize="h2" title="Creating the Redaction Function">
    Let's create a function that will redact personal data from user input, and generate entity mappings that will later be used to re-identify the response:

    ```python Redacting Text Using Limina lines wrap theme={"theme":"poimandres"}
    def redact_text(text):
        text_request = request_objects.process_text_obj(text=[text])
        return client.process_text(text_request)
    ```
  </Step>

  <Step titleSize="h2" title="Crafting the Reidentification Function">
    Next, we'll define a function that does the opposite of the redaction function, enabling the re-identification of redacted entities in the text:

    ```python Reidentification Using Limina lines wrap theme={"theme":"poimandres"}
    def reidentify_text(text, entities):
        entity_mappings = list(map(map_entity, entities))
        reid_request = request_objects.reidentify_text_obj(processed_text=[text], entities=entity_mappings)
        reid_text = client.reidentify_text(reid_request)
        return reid_text.response.json()[0]
    ```

    We don't need all of the data in the response from the redaction service, so let's create a little mapping function to get just what we need:

    ```python Mapping Entity lines wrap theme={"theme":"poimandres"}
    def map_entity(entity):
        return {
            'processed_text': entity['processed_text'],
            'text': entity['text']
        }
    ```
  </Step>

  <Step titleSize="h2" title="Function for Calling OpenAI">
    We'll also need a function for generating responses from OpenAI's GPT-3.5-turbo chat model. Here's a simple illustration of how to accomplish this:

    ```python Prompting Chat GPT lines wrap theme={"theme":"poimandres"}
    def prompt_chat_gpt(text):
        completion = openai.ChatCompletion.create(
            model = "gpt-3.5-turbo",
            messages = [
                {
                    "role": "user",
                    "content": text
                }
            ]
        )
        return completion.choices[0].message['content']
    ```
  </Step>

  <Step titleSize="h2" title="Bringing it All Together">
    We're now ready to put all the components together to form our final solution. This is how we redact a prompt, dispatch it to the GPT model, and reidentify the response:

    ```python Redacting Text And Prompting ChatGPT lines wrap theme={"theme":"poimandres"}
    def prompt_private_gpt(prompt):
        print("******* ORIGINAL TEXT *******")
        print(prompt)

        redacted_object = redact_text(prompt)
        print("\n******* REDACTED TEXT **********")
        print(redacted_object.processed_text)

        chatgpt_response = prompt_chat_gpt(redacted_object.processed_text[0])
        print("\n******* OPEN AI RESPONSE WITH REDACTIONS ********")
        print(chatgpt_response)

        reidentified_text = reidentify_text(chatgpt_response, redacted_object.entities[0])
        print("\n******* OPEN AI RESPONSE REIDENTIFIED ********")
        print(reidentified_text)

        return reidentified_text
    ```

    There you have it - enjoy chatting while preserving your privacy!

    ```python Private GPT Example lines wrap theme={"theme":"poimandres"}
    openai_response = prompt_private_gpt("Hey! Im Joe, a developer at Limina!")
    ```
  </Step>
</Steps>

The entire code is below for you to copy-paste 😉

```python Complete LLM Prompt Redaction Example lines wrap theme={"theme":"poimandres"}
from privateai_client import PAIClient, request_objects
import openai
import os

# Initialize the openai client
openai.api_key = os.getenv('OPENAI_KEY')

# initialize the privateai client
PRIVATEAI_SCHEME = 'http'
PRIVATEAI_HOST = 'localhost'
PRIVATEAI_PORT = '8080'
client = PAIClient(PRIVATEAI_SCHEME, PRIVATEAI_HOST, PRIVATEAI_PORT)

def redact_text(text):
    text_request = request_objects.process_text_obj(text=[text])
    return client.process_text(text_request)


def reidentify_text(text, entities):
    entity_mappings = list(map(map_entity, entities))
    reid_request = request_objects.reidentify_text_obj(processed_text=[text], entities=entity_mappings)
    reid_text = client.reidentify_text(reid_request)
    return reid_text.response.json()[0]


def map_entity(entity):
    return {
        'processed_text': entity['processed_text'],
        'text': entity['text']
    }


def prompt_chat_gpt(text):
    completion = openai.ChatCompletion.create(
        model = "gpt-3.5-turbo",
        messages = [
            {
                "role": "user",
                "content": text
            }
        ]
    )
    return completion.choices[0].message['content']


def prompt_private_gpt(prompt):
    print("******* ORIGINAL TEXT *******")
    print(prompt)

    redacted_object = redact_text(prompt)
    print("\n******* REDACTED TEXT **********")
    print(redacted_object.processed_text)

    chatgpt_response = prompt_chat_gpt(redacted_object.processed_text[0])
    print("\n******* OPEN AI RESPONSE WITH REDACTIONS ********")
    print(chatgpt_response)

    reidentified_text = reidentify_text(chatgpt_response, redacted_object.entities[0])
    print("\n******* OPEN AI RESPONSE REIDENTIFIED ********")
    print(reidentified_text)

    return reidentified_text


openai_response = prompt_private_gpt("Hey! Im Joe, a developer at Limina!")
```
