{ "cells": [ { "cell_type": "code", "execution_count": null, "id": "bcddce7b", "metadata": { "scrolled": true }, "outputs": [], "source": [ "# download presidio\n", "!pip install presidio_analyzer presidio_anonymizer\n", "!pip install openai pandas\n", "!python -m spacy download en_core_web_lg" ] }, { "attachments": {}, "cell_type": "markdown", "id": "3345f1c4", "metadata": {}, "source": [ "###### Path to notebook: [https://www.github.com/microsoft/presidio/blob/main/docs/samples/python/synth_data_with_openai.ipynb](https://www.github.com/microsoft/presidio/blob/main/docs/samples/python/synth_data_with_openai.ipynb)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "21410c42", "metadata": {}, "source": [ "# Use Presidio + OpenAI to turn real text into fake text\n", "\n", "This notebook uses Presidio to turn text with PII into text where PII entities are replaced with placeholders, e.g. \"`My name is David`\" turns into \"`My name is {{PERSON}}`\". Then, it calls the OpenAI API to create a fake record which is based on the original one.\n", "\n", "\n", "Flow:\n", "1. `My friend David lives in Paris. He likes it.`\n", "1. `My friend {{PERSON}} lives in {{CITY}}. He likes it.`\n", "1. `My friend Lucy lives in Beirut. She likes it.`\n", " \n", "Note that OpenAI completion models could possibly detect PII values and replace them in one call, but it is suggested to validate that all PII entities are indeed detected.\n", "\n", "## Imports and set up OpenAI Key" ] }, { "cell_type": "code", "execution_count": 3, "id": "dc5146e0", "metadata": {}, "outputs": [], "source": [ "import pprint\n", "from dotenv import load_dotenv\n", "import os\n", "import pandas as pd\n", "from openai import OpenAI\n", "\n", "load_dotenv()\n", "\n", "client = OpenAI(\n", " api_key=os.environ.get(\"OPENAI_API_KEY\"),\n", ")\n", "#Or put explicitly in notebook. Find out more here: https://help.openai.com/en/articles/4936850-where-do-i-find-my-secret-api-key" ] }, { "attachments": {}, "cell_type": "markdown", "id": "7c793237", "metadata": {}, "source": [ "## Define request for the OpenAI service" ] }, { "cell_type": "code", "execution_count": 4, "id": "a15b64db", "metadata": {}, "outputs": [], "source": [ "def call_completion_model(prompt:str, model:str=\"gpt-3.5-turbo\", max_tokens:int=512) ->str:\n", " \"\"\"Creates a request for the OpenAI Completion service and returns the response.\n", " \n", " :param prompt: The prompt for the completion model\n", " :param model: OpenAI model name\n", " :param max_tokens: Model's max tokens parameter\n", " \"\"\"\n", "\n", " completion = client.chat.completions.create(\n", " messages=[\n", " {\n", " \"role\": \"user\",\n", " \"content\": prompt,\n", " }\n", " ],\n", " model=model,\n", ")\n", "\n", " return completion.choices[0].message.content" ] }, { "attachments": {}, "cell_type": "markdown", "id": "b0f30aed", "metadata": {}, "source": [ "## De-identify data using Presidio Analyzer and Anonymizer" ] }, { "cell_type": "code", "execution_count": 5, "id": "d0dd7820", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Hello, my name is and I live in .\n", "My credit card number is and my crypto wallet id is .\n", "\n", "On I visited and sent an email to , from the IP .\n", "\n", "My passport: and my phone number: .\n", "\n", "This is a valid International Bank Account Number: . Can you please check the status on bank account ?\n", "\n", "'s social security number is . Her driver license? it is .\n", "\n" ] } ], "source": [ "from presidio_analyzer import AnalyzerEngine\n", "from presidio_anonymizer import AnonymizerEngine\n", "\n", "analyzer = AnalyzerEngine()\n", "anonymizer = AnonymizerEngine()\n", "\n", "sample = \"\"\"\n", "Hello, my name is David Johnson and I live in Maine.\n", "My credit card number is 4095-2609-9393-4932 and my crypto wallet id is 16Yeky6GMjeNkAiNcBY7ZhrLoMSgg1BoyZ.\n", "\n", "On September 18 I visited microsoft.com and sent an email to test@presidio.site, from the IP 192.168.0.1.\n", "\n", "My passport: 191280342 and my phone number: (212) 555-1234.\n", "\n", "This is a valid International Bank Account Number: IL150120690000003111111 . Can you please check the status on bank account 954567876544?\n", "\n", "Kate's social security number is 078-05-1126. Her driver license? it is 1234567A.\n", "\"\"\"\n", "\n", "results = analyzer.analyze(sample, language=\"en\")\n", "anonymized = anonymizer.anonymize(text=sample, analyzer_results=results)\n", "anonymized_text = anonymized.text\n", "print(anonymized_text)\n" ] }, { "attachments": {}, "cell_type": "markdown", "id": "f77b0c0f", "metadata": {}, "source": [ "## Create prompt (instructions + text to manipulate)" ] }, { "cell_type": "code", "execution_count": 6, "id": "d2a63fda", "metadata": {}, "outputs": [], "source": [ "def create_prompt(anonymized_text: str) -> str:\n", " \"\"\"\n", " Create the prompt with instructions to GPT-3.\n", " \n", " :param anonymized_text: Text with placeholders instead of PII values, e.g. My name is .\n", " \"\"\"\n", "\n", " prompt = f\"\"\"\n", " Your role is to create synthetic text based on de-identified text with placeholders instead of Personally Identifiable Information (PII).\n", " Replace the placeholders (e.g. ,, {{DATE}}, {{ip_address}}) with fake values.\n", " Instructions:\n", " a. Use completely random numbers, so every digit is drawn between 0 and 9.\n", " b. Use realistic names that come from diverse genders, ethnicities and countries.\n", " c. If there are no placeholders, return the text as is.\n", " d. Keep the formatting as close to the original as possible.\n", " e. If PII exists in the input, replace it with fake values in the output.\n", " f. Remove whitespace before and after the generated text\n", " \n", " input: [[TEXT STARTS]] How do I change the limit on my credit card {{credit_card_number}}?[[TEXT ENDS]]\n", " output: How do I change the limit on my credit card 2539 3519 2345 1555?\n", " input: [[TEXT STARTS]] was the chief science officer at .[[TEXT ENDS]]\n", " output: Katherine Buckjov was the chief science officer at NASA.\n", " input: [[TEXT STARTS]]Cameroon lives in .[[TEXT ENDS]]\n", " output: Vladimir lives in Moscow.\n", " \n", " input: [[TEXT STARTS]]{anonymized_text}[[TEXT ENDS]]\n", " output:\"\"\"\n", " return prompt" ] }, { "cell_type": "code", "execution_count": 7, "id": "1c02d0df", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "This is the prompt with de-identified values:\n", "\n", " Your role is to create synthetic text based on de-identified text with placeholders instead of Personally Identifiable Information (PII).\n", " Replace the placeholders (e.g. ,, {DATE}, {ip_address}) with fake values.\n", " Instructions:\n", " a. Use completely random numbers, so every digit is drawn between 0 and 9.\n", " b. Use realistic names that come from diverse genders, ethnicities and countries.\n", " c. If there are no placeholders, return the text as is.\n", " d. Keep the formatting as close to the original as possible.\n", " e. If PII exists in the input, replace it with fake values in the output.\n", " f. Remove whitespace before and after the generated text\n", " \n", " input: [[TEXT STARTS]] How do I change the limit on my credit card {credit_card_number}?[[TEXT ENDS]]\n", " output: How do I change the limit on my credit card 2539 3519 2345 1555?\n", " input: [[TEXT STARTS]] was the chief science officer at .[[TEXT ENDS]]\n", " output: Katherine Buckjov was the chief science officer at NASA.\n", " input: [[TEXT STARTS]]Cameroon lives in .[[TEXT ENDS]]\n", " output: Vladimir lives in Moscow.\n", " \n", " input: [[TEXT STARTS]]\n", "Hello, my name is and I live in .\n", "My credit card number is and my crypto wallet id is .\n", "\n", "On I visited and sent an email to , from the IP .\n", "\n", "My passport: and my phone number: .\n", "\n", "This is a valid International Bank Account Number: . Can you please check the status on bank account ?\n", "\n", "'s social security number is . Her driver license? it is .\n", "[[TEXT ENDS]]\n", " output:\n" ] } ], "source": [ "print(\"This is the prompt with de-identified values:\")\n", "print(create_prompt(anonymized_text))" ] }, { "attachments": {}, "cell_type": "markdown", "id": "49aabd81", "metadata": {}, "source": [ "## Call the LLM" ] }, { "cell_type": "code", "execution_count": 8, "id": "23653b0b", "metadata": {}, "outputs": [], "source": [ "gpt_res = call_completion_model(create_prompt(anonymized_text))" ] }, { "cell_type": "code", "execution_count": 9, "id": "561f0565", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Hello, my name is Aaliyah and I live in Tokyo.\n", "My credit card number is 4928 7562 1034 8907 and my crypto wallet id is 0x3B 7a 5f 1C.\n", "\n", "On 02/07/2023 15:45 I visited www.example.com and sent an email to example@email.com, from the IP 127.0.0.1.\n", "\n", "My passport: L921483B and my phone number: +1 (555) 123-4567.\n", "\n", "This is a valid International Bank Account Number: FR76 1234 5789 1256 3321 7564 901. Can you please check the status on bank account 987654321?\n", "\n", "Eliana's social security number is 123-45-6789. Her driver license? it is DL12345678.\n" ] } ], "source": [ "print(gpt_res)" ] }, { "attachments": {}, "cell_type": "markdown", "id": "cdf4dbe1", "metadata": {}, "source": [ "### Alternatively, run on a list of template sentences:" ] }, { "cell_type": "code", "execution_count": 10, "id": "234b6204", "metadata": {}, "outputs": [], "source": [ "import urllib\n", "\n", "templates = []\n", "\n", "url = \"https://raw.githubusercontent.com/microsoft/presidio-research/master/presidio_evaluator/data_generator/raw_data/templates.txt\"\n", "for line in urllib.request.urlopen(url):\n", " templates.append(line.decode('utf-8')) " ] }, { "cell_type": "code", "execution_count": 11, "id": "da1773fb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Example templates:\n" ] }, { "data": { "text/plain": [ "['I want to increase limit on my card # {{credit_card_number}} for certain duration of time. is it possible?\\n',\n", " 'My credit card {{credit_card_number}} has been lost, Can I request you to block it.\\n',\n", " 'Need to change billing date of my card {{credit_card_number}}\\n',\n", " 'I want to update my primary and secondary address to the same: {{address}}\\n',\n", " \"In case of my child's account, we need to add {{person}} as guardian\\n\"]" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "print(\"Example templates:\")\n", "templates[:5]" ] }, { "cell_type": "code", "execution_count": 12, "id": "3757461b", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{ 'original': 'I want to increase limit on my card # {{credit_card_number}} for certain duration of time. is '\n", " 'it possible?\\n',\n", " 'synthetic': 'I want to increase limit on my card # 4701 2895 7462 8306 for certain duration of time. is '\n", " 'it possible?'}\n", "--------------\n", "{ 'original': 'My credit card {{credit_card_number}} has been lost, Can I request you to block it.\\n',\n", " 'synthetic': 'My credit card 4892 7634 1023 8756 has been lost, Can I request you to block it.'}\n", "--------------\n", "{ 'original': 'Need to change billing date of my card {{credit_card_number}}\\n',\n", " 'synthetic': 'Need to change billing date of my card 4876 2035 6981 7423'}\n", "--------------\n", "{ 'original': 'I want to update my primary and secondary address to the same: {{address}}\\n',\n", " 'synthetic': 'I want to update my primary and secondary address to the same: 123 Main Street, Apt 4.'}\n", "--------------\n", "{ 'original': \"In case of my child's account, we need to add {{person}} as guardian\\n\",\n", " 'synthetic': \"In case of my child's account, we need to add Abdul as guardian\"}\n", "--------------\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "--------------\n", "{ 'original': '{{name}} lives at {{building_number}} {{street_name}}, {{city}}\\n',\n", " 'synthetic': 'John Smith lives at 635 Poplar Street, Houston'}\n", "--------------\n", "{ 'original': '{{first_name_male}} had given {{first_name}} his address: {{building_number}} '\n", " '{{street_name}}\\n',\n", " 'synthetic': 'Adam had given Sarah his address: 44 Apple Street'}\n", "--------------\n", "{ 'original': '{{first_name_male}} had given {{first_name}} his address: {{building_number}} '\n", " '{{street_name}}, {{city}}\\n',\n", " 'synthetic': 'David had given Emma his address: 515 Elm Street, Camden.'}\n", "--------------\n", "{ 'original': 'What is your address? it is {{address}}\\n',\n", " 'synthetic': 'What is your address? it is 3498 Allensby Street, Los Angeles, CA 90011.'}\n", "--------------\n", "{'original': 'We moved here from {{city}}\\n', 'synthetic': 'We moved here from Paris.'}\n", "--------------\n", "{'original': 'We moved here from {{country}}\\n', 'synthetic': 'We moved here from Venezuela.'}\n", "--------------\n", "{ 'original': '{{person}}\\\\n\\\\n{{building_number}} {{street_name}}\\\\n {{secondary_address}}\\\\n {{city}}\\\\n '\n", " '{{country}} {{postcode}}\\\\n{{phone_number}}-Office\\\\,{{phone_number}}-Fax\\n',\n", " 'synthetic': 'Jessica Thompson\\n'\n", " ' 8745 West Drive\\n'\n", " ' Suite 1402\\n'\n", " ' Brooklyn, NY USA 12009\\n'\n", " ' 789-534-9921-Office, 567-945-0023-Fax'}\n", "--------------\n", "{ 'original': '{{person}}\\\\n{{job}}\\\\n{{organization}}\\\\n{{address}}\\n',\n", " 'synthetic': 'John Smith\\\\nAccountant\\\\nGlobalTech Solutions\\\\n25 Speedwell Street, Richmond, VA 23223'}\n", "--------------\n", "{ 'original': 'Our offices are located at {{address}}\\n',\n", " 'synthetic': 'Our offices are located at 1234 Main St, Los Angeles, CA 91234.'}\n", "--------------\n", "{ 'original': 'Please return to {{address}} in case of an issue.\\n',\n", " 'synthetic': 'Please return to 123 Cherry Street, El Monte, CA 91731 in case of an issue.'}\n", "--------------\n", "{ 'original': '{{organization}}\\\\n\\\\n{{address}}\\n',\n", " 'synthetic': 'ABC Inc.\\n 1234 Main Street, Anytown, ST 12345'}\n", "--------------\n", "{ 'original': 'The {{organization}} office is at {{address}}\\n',\n", " 'synthetic': 'The ABC Corporation office is at 123 Redwood Street, Anytown, USA.'}\n", "--------------\n", "{ 'original': '{{name}}\\\\n{{organization}}\\\\n{{address}}\\\\n{{phone_number}} office\\\\n{{phone_number}} '\n", " 'fax\\\\n{{phone_number}} mobile\\\\n\\n',\n", " 'synthetic': 'Larry Fernandez\\\\nStar Enterprises\\\\n421 5th Avenue, Los Angeles, CA 90012\\\\n123-456-7890 '\n", " 'office\\\\n456-789-0123 fax\\\\n256-454-2397 mobile\\\\n'}\n", "--------------\n", "{ 'original': '{{name}}\\\\n{{organization}}\\\\n{{address}}\\\\nMobile: {{phone_number}}\\\\nDesk: '\n", " '{{phone_number}}\\\\nFax: {{phone_number}}\\\\n\\n',\n", " 'synthetic': 'John Brown\\n'\n", " ' ABC Consulting\\n'\n", " ' 5th St., Suite 116, LA CA 90004\\n'\n", " ' Mobile: 213-294-4497\\n'\n", " ' Desk: 424-348-1275\\n'\n", " ' Fax: 323-456-2545'}\n", "--------------\n", "{ 'original': 'Billing address: {{name}}\\\\n {{building_number}} {{street_name}} '\n", " '{{secondary_address}}\\\\n {{city}}\\\\n {{state_abbr}}\\\\n {{zipcode}}\\\\n\\n',\n", " 'synthetic': 'Billing address: Mariam Rajput\\n'\n", " ' 576 Broadway Street Apartment A8\\n'\n", " ' Sacramento\\n'\n", " ' CA\\n'\n", " ' 95349'}\n", "--------------\n", "{ 'original': \"As promised, here's {{first_name}}'s address:\\\\n\\\\n{{address}}\\n\",\n", " 'synthetic': \"As promised, here's Aamir's address:\\\\n\\\\n2166 Sesame Street, Fortaleza, Ceará, Brazil.\"}\n", "--------------\n", "{ 'original': '>{{name}}\\\\n>{{organization}}\\\\n>{{person}}\\\\n>{{building_number}} '\n", " '{{street_name}}\\\\n>{{secondary_address}}\\\\n>{{city}}\\\\n>{{country}} {{postcode}}\\n',\n", " 'synthetic': '>Freda Chen\\n'\n", " '>Example Inc.\\n'\n", " '>John Doe\\n'\n", " '>50 Main Street\\n'\n", " '>Apt. 2\\n'\n", " '>New York\\n'\n", " '>United States 10005'}\n", "--------------\n", "{ 'original': '??? {{name}}\\\\n??? {{organization}}\\\\n??? {{building_number}} {{street_name}}\\\\n??? '\n", " '{{secondary_address}}\\\\n??? {{city}}\\\\n??? {{country}} {{postcode}}\\n',\n", " 'synthetic': 'John Smith\\n'\n", " ' ABC Corporation\\n'\n", " ' 192 Main Street\\n'\n", " ' Suite 100\\n'\n", " ' Austin\\n'\n", " ' United States 78701'}\n", "--------------\n", "{ 'original': '> \\\\n> {{name}}\\\\n> {{organization}}\\\\n> {{person}}\\\\n> {{building_number}} '\n", " '{{street_name}}\\\\n> {{secondary_address}}\\\\n> {{city}}\\\\n> {{country}} {{postcode}}\\n',\n", " 'synthetic': '> John Doe\\n'\n", " ' > ABC Corp\\n'\n", " ' > Jane Smith\\n'\n", " ' > 123 Main Street\\n'\n", " ' > APT 8\\n'\n", " ' > San Francisco\\n'\n", " ' > United States 12345'}\n", "--------------\n", "{ 'original': 'Pedestrians must enter on {{street_name}} St. the first three months\\n',\n", " 'synthetic': 'Pedestrians must enter on Jericho Avenue St. the first three months'}\n", "--------------\n", "{ 'original': 'When: {{date_time}}\\\\nWhere: {{city}} Country Club.\\n',\n", " 'synthetic': 'When: 05/01/2020 10:00am\\\\nWhere: Richmond Country Club.'}\n", "--------------\n", "{ 'original': \"We'll meet {{day_of_week}} at {{organization}}, {{building_number}} {{street_name}}, \"\n", " '{{city}}\\n',\n", " 'synthetic': \"We'll meet Monday at Smartdel Solutions, 145 King Street, San Diego.\"}\n", "--------------\n", "{ 'original': 'They had 6: {{first_name}}, {{first_name}}, {{first_name}}, {{first_name}}, {{first_name}} '\n", " 'and {{first_name}}.\\n',\n", " 'synthetic': 'They had 6: Sarah, Micheal, Kanak, Hana, Mei and Dan.'}\n", "--------------\n", "{'original': 'She moved here from {{country}}\\n', 'synthetic': 'She moved here from Mexico.'}\n", "--------------\n", "{'original': 'My zip code is {{zipcode}}\\n', 'synthetic': 'My zip code is 47713.'}\n", "--------------\n", "{'original': 'ZIP: {{zipcode}}\\n', 'synthetic': 'ZIP: 08547'}\n", "--------------\n", "{'original': 'The bus station is on {{street_name}}\\n', 'synthetic': 'The bus station is on Wilson Avenue.'}\n", "--------------\n", "{ 'original': \"They're not answering at {{phone_number}}\\n\",\n", " 'synthetic': \"They're not answering at 654-339-1013.\"}\n", "--------------\n", "{ 'original': 'God gave rock and roll to you, gave rock and roll to you, put it in the soul of everyone.\\n',\n", " 'synthetic': 'God gave rock and roll to you, gave rock and roll to you, put it in the soul of everyone.'}\n", "--------------\n", "{'original': '3... 2... 1... liftoff!\\n', 'synthetic': '3... 2... 1... liftoff!'}\n", "--------------\n", "{ 'original': 'My great great grandfather was called {{name_male}}, and my great great grandmother was '\n", " 'called {{name_female}}\\n',\n", " 'synthetic': 'My great great grandfather was called Michael, and my great great grandmother was called '\n", " 'Emma.'}\n", "--------------\n", "{'original': 'She named him {{first_name_male}}\\n', 'synthetic': 'She named him Juan.'}\n", "--------------\n", "{ 'original': 'Name: {{name}}\\\\nAddress: {{address}}\\n',\n", " 'synthetic': 'Name: Amari Walters\\\\nAddress: 32 Webster Street, Salem, MA 01819'}\n", "--------------\n", "{ 'original': 'Follow up with {{name}} in a couple of months.\\n',\n", " 'synthetic': 'Follow up with Beatriz Lawrence in a couple of months.'}\n", "--------------\n", "{ 'original': '{{prefix_male}} {{last_name_male}} is a {{age}} year old man who grew up in {{city}}.\\n',\n", " 'synthetic': 'Mr.Williams is a 28 year old man who grew up in Dallas.'}\n", "--------------\n", "{ 'original': 'Date: {{date_time}}\\\\nName: {{name}}\\\\nPhone: {{phone_number}}\\n',\n", " 'synthetic': 'Date: 01/03/2021 13:45 \\\\nName: Pratima Joshi \\\\nPhone: 467-562-8954'}\n", "--------------\n", "{ 'original': '{{first_name}}: \"Who are you?\"\\\\n{{first_name_female}}:\"I\\'m {{first_name}}\\'s daughter\".\\n',\n", " 'synthetic': 'Bob: \"Who are you?\"\\\\nMaria:\"I\\'m Bob\\'s daughter\".'}\n", "--------------\n", "{ 'original': 'At my suggestion, one morning over breakfast, she agreed, and on the last Sunday before Labor '\n", " 'Day we returned to {{city}} by helicopter.\\n',\n", " 'synthetic': 'At my suggestion, one morning over breakfast, she agreed, and on the last Sunday before '\n", " 'Labor Day we returned to Paris by helicopter.'}\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "--------------\n", "{ 'original': \"It was a done thing between him and {{first_name}}'s kid; and everybody thought so.\\n\",\n", " 'synthetic': \"It was a done thing between him and Jeffery's kid; and everybody thought so.\"}\n", "--------------\n", "{ 'original': 'Capitalized words like Wisdom and Discipline are often mistaken with names.\\n',\n", " 'synthetic': 'Capitalized words like Wisdom and Discipline are often mistaken with names.'}\n", "--------------\n", "{ 'original': 'The letter arrived at {{address}} last night.\\n',\n", " 'synthetic': 'The letter arrived at 1143 Orange Street last night.'}\n", "--------------\n", "{ 'original': 'The Princess Royal arrived at {{city}} this morning from {{country}}.\\n',\n", " 'synthetic': 'The Princess Royal arrived at London this morning from France.'}\n", "--------------\n", "{'original': \"I'm in {{city}}, at the conference\\n\", 'synthetic': \"I'm in Toronto, at the conference.\"}\n", "--------------\n", "{ 'original': '{{name}}, the {{job}}, said: \"I\\'m glad to hear that this has been withdrawn – quite why they '\n", " 'thought this would go down well is beyond me.\"\\n',\n", " 'synthetic': 'Gloria Green, the Nurse Practitioner, said: \"I\\'m glad to hear that this has been withdrawn '\n", " '– quite why they thought this would go down well is beyond me.\"'}\n", "--------------\n", "{ 'original': '\"I\\'m glad to hear that {{country}} is moving in that direction,\" says {{last_name}}.\\n',\n", " 'synthetic': '\"I\\'m glad to hear that Canada is moving in that direction,\" says Smith.'}\n", "--------------\n", "{ 'original': 'I am {{nation_woman}} but I live in {{country}}.\\n',\n", " 'synthetic': 'I am Marianna Montenegro but I live in Ukraine.'}\n", "--------------\n", "{'original': 'We are proud {{nation_plural}}\\n', 'synthetic': 'We are proud Americans.'}\n", "--------------\n", "{ 'original': \"{{person}}'s killers sentenced to life in prison\\n\",\n", " 'synthetic': \"John Smith's killers sentenced to life in prison\"}\n", "--------------\n", "{ 'original': \"{{country}} leader gives 'kill without warning' order\\n\",\n", " 'synthetic': \"Brazilian leader gives 'kill without warning' order\"}\n", "--------------\n", "{ 'original': 'The {{nationality}} Border Force have detained top-flight tennis player {{name_female}} over '\n", " 'visa disputes.\\n',\n", " 'synthetic': 'The British Border Force have detained top-flight tennis player Maria Rodriguez over visa '\n", " 'disputes.'}\n", "--------------\n", "{ 'original': 'You will be responsible for the husbandry and care of a large variety of species including '\n", " 'lemurs, antelope, camels, and more\\n',\n", " 'synthetic': 'You will be responsible for the husbandry and care of a large variety of species including '\n", " 'lemurs, antelope, camels, and more.'}\n", "--------------\n", "{ 'original': '{{name}}\\\\n\\\\n{{job}}\\\\n\\\\nPersonal '\n", " 'Info:\\\\nPhone:\\\\n{{phone_number}}\\\\n\\\\nE-mail:\\\\n{{email}}\\\\n\\\\nWebsite:\\\\n{{url}}\\\\n\\\\nAddress:\\\\n{{address}}.\\n',\n", " 'synthetic': 'Robert James\\\\n\\\\nSoftware Engineer\\\\n\\\\nPersonal '\n", " 'Info:\\\\nPhone:\\\\n555-847-8915\\\\n\\\\nE-mail:\\\\nrobertjames@example.com\\\\n\\\\nWebsite:\\\\nwww.example.com\\\\n\\\\nAddress:\\\\n277 '\n", " 'Park Ave North, Denver, CO 80100.'}\n", "--------------\n", "{ 'original': '{{name}}\\\\n\\\\n{{city}}\\\\n{{country}}\\n',\n", " 'synthetic': 'John Smith\\n Los Angeles\\n United States'}\n", "--------------\n", "{ 'original': 'Title VII of the Civil Rights Act of {{year}} protects individuals against employment '\n", " 'discrimination on the basis of race and color as well as national origin, sex, or religion.\\n',\n", " 'synthetic': 'Title VII of the Civil Rights Act of 1964 protects individuals against employment '\n", " 'discrimination on the basis of race and color as well as national origin, sex, or religion.'}\n", "--------------\n", "{ 'original': 'Energetic and driven salesperson with 8+ years of professional experience in inbound and '\n", " 'outbound sales. Awarded Salesperson of the Month three times. Helped increase inbound sales '\n", " 'by 16% within the first year of employment. Looking to support {{organization}} in {{city}} '\n", " '{{zipcode}} in its mission to become a market-leading solution.\\n',\n", " 'synthetic': 'Energetic and driven salesperson with 8+ years of professional experience in inbound and '\n", " 'outbound sales. Awarded Salesperson of the Month three times. Helped increase inbound sales '\n", " 'by 16% within the first year of employment. Looking to support Acme Corporation in Los '\n", " 'Angeles 90018 in its mission to become a market-leading solution.'}\n", "--------------\n", "{ 'original': 'The bus drops you off at {{building_number}} {{street_name}} St.\\n',\n", " 'synthetic': 'The bus drops you off at 2774 Chestnut St.'}\n", "--------------\n", "{ 'original': 'Ask the driver to stop at the corner of {{street_name}} St. and {{street_name}} St.\\n',\n", " 'synthetic': 'Ask the driver to stop at the corner of Maple St. and Sycamore St.'}\n", "--------------\n", "{ 'original': 'He lives on the north side of {{street_name}}.\\n',\n", " 'synthetic': 'He lives on the north side of Abbey Road.'}\n", "--------------\n", "{ 'original': \"I used to work for {{organization}} as {{job}}, but quit a few months ago. Now I'm \"\n", " 'unemployed.\\n',\n", " 'synthetic': \"I used to work for ABC Corporation as Software Engineer, but quit a few months ago. Now I'm \"\n", " 'unemployed.'}\n", "--------------\n", "{'original': '{{city}} bridge is falling down.\\n', 'synthetic': 'Berlin bridge is falling down.'}\n", "--------------\n", "{ 'original': '{{name}} of {{organization}} is the CEO of the year. ABC Business considered several other '\n", " \"influential CEOs for this year's honor, including {{name}} of {{organization}}, \"\n", " \"{{organization}}'s {{name}}, {{name}} of {{organization}}'s, {{name}} of {{organization}}, \"\n", " \"and {{organization}}'s {{name}}.\\n\",\n", " 'synthetic': 'Franklin Smith of Technology Solutions International is the CEO of the year. ABC Business '\n", " \"considered several other influential CEOs for this year's honor, including Madison Chang of \"\n", " \"Radiance Digital, Radiance Digital's Ashleigh Jones, Cash Huang of Clark & Partner's, Sierra \"\n", " \"Urbina of Intelicity, and Clark & Partners's Asher Kenney.\"}\n", "--------------\n", "{ 'original': '{{organization}} is a design agency based in {{city}}.\\n',\n", " 'synthetic': 'Maestro Design Inc. is a design agency based in Amsterdam.'}\n", "--------------\n", "{ 'original': 'Action & Adventure, Animation, Comedy, Kids & Family, Mystery & Suspense\\\\nDirected By: '\n", " '{{name}}\\n',\n", " 'synthetic': 'Action & Adventure, Animation, Comedy, Kids & Family, Mystery & Suspense\\n'\n", " 'Directed By: Esther Jones'}\n", "--------------\n", "{ 'original': '{{first_name}}: What a wife.\\\\n{{first_name}}: Remember me, {{first_name}}? When I killed '\n", " 'your brother, I talked just like this!\\\\n{{first_name}}: You saved my life! How can I ever '\n", " 'repay you?\\n',\n", " 'synthetic': 'Emma: What a wife.\\n'\n", " ' Emma: Remember me, Emma? When I killed your brother, I talked just like this!\\n'\n", " ' Emma: You saved my life! How can I ever repay you?'}\n", "--------------\n", "{'original': 'He just turned {{age}} years old\\n', 'synthetic': 'He just turned 7 years old'}\n", "--------------\n", "{ 'original': \"I'm {{name}}, originally from {{city}}, and i'm {{age}} y/o.\\n\",\n", " 'synthetic': \"I'm Emily Evanston, originally from London, and I'm 24 y/o.\"}\n", "--------------\n", "{ 'original': 'Patient is a {{age}}-year-old male with a history of headaches\\n',\n", " 'synthetic': 'Patient is a 35-year-old male with a history of headaches'}\n", "--------------\n", "{'original': 'I just turned {{age}}\\n', 'synthetic': 'I just turned 24.'}\n", "--------------\n", "{'original': 'My father retired at the age of {{age}}\\n', 'synthetic': 'My father retired at the age of 60.'}\n", "--------------\n", "{ 'original': 'This {{age}} year old female complaining of stomach pain.\\n',\n", " 'synthetic': 'This 28 year old female complaining of stomach pain.'}\n", "--------------\n", "{ 'original': \"My birthday is on the weekend. I'll turn {{age}}.\\n\",\n", " 'synthetic': \"My birthday is on the weekend. I'll turn 20.\"}\n", "--------------\n", "{'original': 'My brother just turned {{age}}\\n', 'synthetic': 'My brother just turned 18.'}\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "--------------\n", "{ 'original': '{{prefix}} {{last_name}} flew to {{city}} on {{day_of_week}} morning.',\n", " 'synthetic': 'Dr. Nguyen flew to Los Angeles on Tuesday morning.'}\n", "--------------\n" ] } ], "source": [ "templates_to_use = templates[:5]\n", "\n", "\n", "import time\n", "pp = pprint.PrettyPrinter(indent=2, width=110)\n", "sentences = []\n", "for template in templates_to_use:\n", " synth_sentence = call_completion_model(create_prompt(template))\n", " sentence_dict = {\"original\": template, \"synthetic\":synth_sentence.strip()}\n", " sentences.append(sentence_dict)\n", " pp.pprint(sentence_dict)\n", " time.sleep(3) # wait to not get blocked by service (only applicable for the free tier)\n", " print(\"--------------\")\n" ] }, { "attachments": {}, "cell_type": "markdown", "id": "3981c913", "metadata": {}, "source": [ "This notebook demonstrates how to leverage OpenAI models for fake/surrogate data generation. It uses Presidio to first de-identify data (as de-identification might be required prior to passing the model to OpenAI), and then uses OpenAI completion models to create synthetic/fake/surrogate data based on real data. OpenAI models would also potentially remove additional PII entities, if those are not detected by Presidio.\n", "\n", "Some impressions:\n", "1. LLMs sometimes gives additonal output, especially if the text is a question or concerning a human/bot interaction. Engineering the prompt can mitigate some of these issues. Potential post-processing might be required.\n", "2. LLMs sometimes creates fake values even in the absence of placeholders.\n", "3. LLMs re-uses context from other sentences, which could cause phone numbers are sometimes generated using a credit card pattern or other similar mistakes.\n", "4. Co-references are sometimes missed (i.e. two name placeholders that should be filled with the same name, or referencing he/she to a male/female name)" ] }, { "cell_type": "code", "execution_count": null, "id": "7ff32f21-33c4-4df1-9626-73cbdf5145df", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "presidio_e2e", "language": "python", "name": "presidio" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.10.13" } }, "nbformat": 4, "nbformat_minor": 5 }