Сбалансирование инноваций с безопасностью и конфиденциальностью в эпоху больших языковых моделей (LLM)

Балансировка инноваций и безопасности в эпоху LLM.

Руководство по внедрению механизмов безопасности и конфиденциальности для ваших приложений Генеративного ИИ

Фото: Джейсон Дент на Unsplash

Эра искусственного интеллекта принесла на передний план крупные языковые модели (также известные как LLM), которые много обсуждались в 2023 году и, вероятно, будут оставаться таковыми в течение многих лет. LLM – это модели искусственного интеллекта, которые стоят за такими вещами, как ChatGPT. Эти модели искусственного интеллекта, основанные на огромных объемах данных и вычислительных возможностях, обладают удивительными способностями, от генерации текста, похожего на человеческий, до помощи в понимании естественного языка (NLU). Они быстро стали основой для создания бесчисленных приложений и программных сервисов, или по крайней мере использования их в качестве дополнения.

Однако, как и с любыми новаторскими достижениями, появление LLM вызывает важный вопрос: “Как найти баланс между преследованием технологического прогресса и необходимостью обеспечения безопасности и конфиденциальности?”. Это не просто философский вопрос, а вызов, требующий активных и продуманных действий.

Безопасность и конфиденциальность

Для обеспечения безопасности и конфиденциальности в наших приложениях, основанных на LLM, мы сосредоточимся на нескольких ключевых аспектах, включая контроль распространения персональных данных (например, идентифицирующей информации) и вредоносного или токсичного контента. Это важно как при настройке LLM с использованием собственного набора данных, так и при использовании LLM для генерации текста. Почему это важно? Есть несколько причин, почему это может быть важно.

  • Соблюдение правительственных регуляций, которые требуют защиты персональной информации пользователей (например, GDPR, CCPA, HIPAA Privacy Rule и т. д.)
  • Соблюдение лицензионного соглашения конечного пользователя (EULA) или политики приемлемого использования LLM-провайдера
  • Соблюдение политик информационной безопасности, установленных в организациях
  • Снижение возможности возникновения предвзятости и искажения в модели после настройки
  • Обеспечение этичного использования LLM и сохранение репутации бренда
  • Подготовка к возможным будущим регулированиям искусственного интеллекта

Аспекты настройки

При подготовке к настройке LLM первым шагом является подготовка данных. За исключением исследований, образования или личных проектов, вероятно, вы столкнетесь с ситуациями, когда ваши тренировочные данные могут содержать идентифицирующую информацию. Первым этапом здесь является выявление наличия таких идентифицирующих сущностей в данных, а вторым этапом является очистка данных для гарантированного анонимизации этих сущностей.

Настройка LLM

Аспекты генерации текста

При генерации текста с использованием LLM есть несколько вещей, которые следует учитывать. Во-первых, мы гарантируем, что любые запросы, содержащие токсичный контент, не передаются LLM, а во-вторых, мы убеждаемся, что наш запрос не содержит идентифицирующих сущностей. Кроме того, в некоторых случаях может быть целесообразно проверять эти условия на сгенерированном тексте LLM или на “машинно-сгенерированном тексте”. Это обеспечивает двухуровневую защиту соблюдения этики и конфиденциальности. Третьим аспектом является определение намерения самого запроса, что в некоторой степени может ограничить такие атаки, как внедрение запросов. Однако в этой статье я сконцентрируюсь в основном на идентифицирующей информации и токсичности и обсужу классификацию намерений и ее влияние на LLM в отдельной дискуссии.

Генерация текста с LLM

Внедрение

Мы будем использовать двухэтапный подход для реализации решения. Во-первых, мы используем модель распознавания именных сущностей (NER), которая может идентифицировать идентифицирующие сущности в тексте и позволяет анонимизировать эти сущности. В идентифицирующие сущности обычно входят такие вещи, как имя человека, местоположение или адрес, номер телефона, номер кредитной карты, ССН и т. д. Во-вторых, мы используем модель классификации текста для определения, является ли текст “токсичным” или “нейтральным”. Примерами токсичного текста обычно являются тексты, содержащие оскорбления, непристойности, домогательства, угрозы и тому подобное.

Для модели PII NER наиболее распространенным выбором будет модель BERT Base, которую можно настроить для обнаружения конкретных сущностей PII. Вы также можете настроить предварительно обученные модели трансформера, такие как предварительно обученная модель Robust DeID (деидентификация), которая является моделью RoBERTa, настроенной для деидентификации медицинских заметок и в основном сосредоточена на персональной медицинской информации (PHI). Гораздо более простым вариантом для начала экспериментов было бы использование spaCy ER (EntityRecognizer).

import spacynlp = spacy.load("en_core_web_lg")text = "Имя заявителя - Джон Доу, и он живет на Сильвер Стрит. \        и его телефонный номер: 555-123-1290"doc = nlp(text)displacy.render(doc, style="ent", jupyter=True)

что дает нам

Аннотация обнаруженных сущностей PII с помощью spaCy

spaCy EntityRecognizer смог идентифицировать три сущности – PERSON (люди, включая вымышленных персонажей), FAC (местоположение или адрес) и CARDINAL (числительные, не относящиеся к другому типу). spaCy также предоставляет нам начальную и конечную позицию (позицию символа в тексте) обнаруженной сущности, которую мы можем использовать для анонимизации.

ent_positions = [(ent.start_char, ent.end_char) for ent in doc.ents]for start, end in reversed(ent_positions):    text = text[:start] + '#' * (end - start) + text[end:]print(text)

что дает нам

Имя заявителя - ######## и он живет на ###################и его телефонный номер: ###-123-1290

Но здесь есть несколько очевидных проблем. Список сущностей по умолчанию в spaCy ER не исчерпывающий и не покрывает все типы сущностей PII. Например, в нашем случае мы хотели бы обнаружить 555-123-1290 как PHONE_NUMBER, а не просто как часть текста в качестве CARDINAL, что приводит к неполному обнаружению сущности. Конечно, подобно моделям NER, основанным на трансформерах, spaCy также может быть обучен собственным набором данных пользовательских именных сущностей, чтобы сделать его более надежным. Однако мы будем использовать открытую Presidio SDK, которая является более специализированным инструментарием для защиты данных и деидентификации.

Обнаружение и анонимизация PII с помощью Presidio

SDK Presidio предоставляет полный набор возможностей для обнаружения PII с использованием длинного списка поддерживаемых сущностей PII. Presidio в основном использует сопоставление шаблонов вместе с возможностями ML в spaCy и Stanza. Однако Presidio настраиваем и может быть подключен для использования вашей модели распознавания сущностей PII на основе трансформера или даже для использования возможностей облачных служб обнаружения PII, таких как Azure Text Analytics PII detection или Amazon Comprehend PII detection. Он также имеет встроенный настраиваемый анонимизатор, который может помочь очистить и скрыть сущности PII из текста.

from presidio_analyzer import AnalyzerEnginetext="""Имя заявителя - Джон Доу, и он живет на Сильвер Стрит, а его телефонный номер: 555-123-1290."""analyzer = AnalyzerEngine()results = analyzer.analyze(text=text,                           language='en')for result in results:  print(f"Тип PII={result.entity_type},",        f"Начальная позиция={result.start},",        f"Конечная позиция={result.end},",        f"Оценка={result.score}")

что дает нам

Тип PII=PERSON, Начало=21, Конец=29, Оценка=0.85Тип PII=LOCATION, Начало=50, Конец=60, Оценка=0.85Тип PII=PHONE_NUMBER, Начало=85, Конец=97, Оценка=0.75

и

Аннотация обнаруженных сущностей PII с помощью Presidio

Как мы видели ранее, анонимизация текста является довольно простой задачей, поскольку у нас есть начальные и конечные позиции каждой из сущностей в тексте. Однако, мы собираемся воспользоваться встроенным в Presidio инструментом AnonymizerEngine, чтобы помочь нам с этим.

from presidio_anonymizer import AnonymizerEngineanonymizer = AnonymizerEngine()anonymized_text = anonymizer.anonymize(text=text,analyzer_results=results)print(anonymized_text.text)

что дает нам

Имя заявителя - <PERSON>, а он живет в <LOCATION>, а его номер телефона - <PHONE_NUMBER>.

Пока все хорошо, но что, если мы хотим, чтобы анонимизация была просто маскировкой. В этом случае мы можем передать пользовательскую конфигурацию в AnonymizerEngine, которая может выполнять простую маскировку сущностей PII. Например, мы можем маскировать сущности символами астериска (*).

from presidio_anonymizer import AnonymizerEnginefrom presidio_anonymizer.entities import OperatorConfigoperators = dict()# предполагая, что `results` - это результат обнаружения PII-сущностей `AnalyzerEngine`for result in results:  operators[result.entity_type] = OperatorConfig("mask",                                  {"chars_to_mask": result.end - result.start,                                   "masking_char": "*",                                   "from_end": False})anonymizer = AnonymizerEngine()anonymized_results = anonymizer.anonymize(    text=text, analyzer_results=results, operators=operators)print(anonymized_results.text)

что дает нам

Имя заявителя - ********, и он живет в ********** и его номер телефона - ************.

Соображения по анонимизации

Есть несколько вещей, о которых следует помнить, когда вы решите анонимизировать PII-сущности в тексте.

  • Встроенный AnonymizerEngine Presidio использует шаблон <ENTITY_LABEL> для маскировки PII-сущностей (например, <PHONE_NUMBER>). Это может потенциально вызвать проблемы, особенно при тонкой настройке LLM. Замена PII метками типов сущностей может внести слова, несущие семантическое значение, что может повлиять на поведение языковых моделей.
  • Псевдонимизация является полезным инструментом для защиты данных, однако следует проявлять осторожность при псевдонимизации обучающих данных. Например, замена всех сущностей NAME псевдонимом John Doe или замена всех сущностей DATE на 01-JAN-2000 в данных для тонкой настройки может привести к крайней предвзятости в обученной модели.
  • Учитывайте, как ваша LLM реагирует на определенные символы или шаблоны в вашем запросе. Некоторым LLM может понадобиться очень специфический способ формирования запросов для наилучшего использования модели, например, Anthropic рекомендует использовать теги запросов. Быть в курсе этого поможет определить, как вы можете выполнить анонимизацию.

Анонимизация данных может вызывать и другие общие побочные эффекты при тонкой настройке модели, такие как потеря контекста, семантический дрейф, галлюцинации модели и т.д. Важно проводить итерации и эксперименты, чтобы определить уровень анонимизации, соответствующий ваши нужды, минимизируя его негативное влияние на работу модели.

Обнаружение токсичности с помощью текстовой классификации

Для определения, содержит ли текст токсичный контент или нет, мы будем использовать двоичный подход классификации — 0, если текст нейтрален, 1, если текст токсичен. Я решил обучить базовую модель DistilBERT (uncased), которая является упрощенной версией базовой модели BERT. В качестве обучающих данных я использовал набор данных Jigsaw.

Я не буду вдаваться в детали того, как была обучена модель и метрики модели и т.д., но вы можете обратиться к этой статье о тренировке базовой модели DistilBERT для задач текстовой классификации. Здесь вы можете увидеть скрипт тренировки модели. Модель доступна в HuggingFace Hub как tensor-trek/distilbert-toxicity-classifier. Давайте прогоним несколько образцов текста через вывод, чтобы проверить, что модель говорит нам.

from transformers import pipelinetext = ["Это было шедеврально. Не совсем верное отражение книг, но завораживающее с начала до конца. Может быть, это мое любимое из трех.",
         "Я бы хотел убить эту птицу, я ненавижу ее."]classifier = pipeline("text-classification", model="tensor-trek/distilbert-toxicity-classifier")classifier(text)

что дает нам —

[  {'label': 'NEUTRAL', 'score': 0.9995143413543701},  {'label': 'TOXIC', 'score': 0.9622979164123535}]

Модель правильно классифицирует текст как NEUTRAL или TOXIC с достаточно высокой уверенностью. Эта модель классификации текста, в сочетании с ранее обсуждаемой классификацией сущностей PII, может быть использована для создания механизма, который может обеспечивать конфиденциальность и безопасность в наших приложениях или сервисах, основанных на LLM.

Сборка всех компонентов

Мы решили вопрос конфиденциальности с помощью механизма распознавания сущностей PII, и мы решили вопрос безопасности с помощью классификатора токсичности текста. Вы можете подумать о других механизмах, которые могут быть актуальны для определения безопасности и конфиденциальности вашей организации. Например, организации здравоохранения могут быть более заинтересованы в защите PHI вместо PII и так далее. В конечном итоге, общий подход к реализации остается неизменным, независимо от контролов, которые вы хотите внедрить.

Имея это в виду, теперь пришло время объединить все в действие. Мы хотим использовать как механизмы конфиденциальности, так и механизмы безопасности в сочетании с LLM для приложения, в котором мы хотим внедрить возможности генерации искусственного интеллекта. Я собираюсь использовать популярный языковой фреймворк LangChain на языке Python (также доступен на JavaScript/TS) для создания приложения, которое будет включать оба механизма. Вот как выглядит наша общая архитектура.

Поток конфиденциальности и безопасности с LangChain

В указанной выше архитектуре первое, что я проверяю, это содержит ли текст токсичный контент с точностью модели более 80%. Если так, то выполнение всего приложения LangChain останавливается на этом этапе, и пользователю показывается соответствующее сообщение. Если текст в основном классифицируется как нейтральный, тогда я передаю его на следующий этап определения сущностей PII. Затем я выполняю анонимизацию этих сущностей в тексте, если уверенность обнаружения каждой из этих сущностей составляет более 50%. После полной анонимизации текст передается в качестве подсказки LLM для дальнейшей генерации текста моделью. Обратите внимание, что пороги точности (80% и 50%) являются произвольными, вы захотите протестировать точность обоих детекторов (PII и токсичности) на ваших данных и определить порог, который наилучшим образом подходит для вашего случая использования. Чем ниже порог, тем более строгой становится система, чем выше порог, тем слабее осуществляется контроль.

Другой более консервативный подход может заключаться в том, чтобы остановить выполнение, если обнаружены какие-либо сущности PII. Это может быть полезно для приложений, которые не имеют сертификации на обработку данных PII вообще, и вы хотите гарантировать, что текст, содержащий PII, не попадет в приложение в качестве входных данных, каким бы способом это ни происходило.

Поток конфиденциальности и безопасности с LangChain — альтернативный поток

Реализация LangChain

Чтобы это работало с LangChain, я создал пользовательскую цепочку под названием PrivacyAndSafetyChain. Это можно связать с любыми поддерживаемыми LLM в LangChain для реализации механизма конфиденциальности и безопасности. Вот как это выглядит —

from langchain import HuggingFaceHubfrom langchain import PromptTemplate, LLMChainfrom PrivacyAndSafety import PrivacyAndSafetyChainsafety_privacy = PrivacyAndSafetyChain(verbose=True,                                       pii_labels = ["PHONE_NUMBER", "US_SSN"])template = """{question}"""prompt = PromptTemplate(template=template, input_variables=["question"])llm = HuggingFaceHub(    repo_id=repo_id, model_kwargs={"temperature": 0.5, "max_length": 256})chain = (    prompt     | safety_privacy     | {"input": (lambda x: x['output'] ) | llm}    | safety_privacy )try:    response = chain.invoke({"question": """What is John Doe's address, phone number and SSN from the following text?John Doe, a resident of 1234 Elm Street in Springfield, recently celebrated his birthday on January 1st. Turning 43 this year, John reflected on the years gone by. He often shares memories of his younger days with his close friends through calls on his phone, (555) 123-4567. Meanwhile, during a casual evening, he received an email at johndoe@example.com reminding him of an old acquaintance's reunion. As he navigated through some old documents, he stumbled upon a paper that listed his SSN as 338-12-6789, reminding him to store it in a safer place."""})except Exception as e:    print(str(e))else:    print(response['output'])

По умолчанию PrivacyAndSafetyChain сначала выполняет обнаружение токсичного контента. Если он обнаружит токсичный контент, то цепочка остановится, как мы ранее обсуждали. Если нет, то введенный текст передается распознавателю сущностей PII, и на основе символа маскировки, который будет использоваться, цепочка выполнит анонимизацию текста с обнаруженными сущностями PII. Результат предыдущего кода показан ниже. Поскольку нет токсичного контента, цепочка не остановилась, и она обнаружила PHONE_NUMBER и SSN, и правильно анонимизировала его.

> Ввод новой цепочки PrivacyAndSafetyChain... Запуск PrivacyAndSafetyChain... Проверка на наличие токсичного контента... Проверка на наличие PII...> Завершение цепочки.> Ввод новой цепочки PrivacyAndSafetyChain... Запуск PrivacyAndSafetyChain... Проверка на наличие токсичного контента... Проверка на наличие PII...> Завершение цепочки.1234 Elm Street, **************, ***********

Заключение

Самое главное, что следует учесть в этом посте, заключается в том, что по мере нашего продолжающегося развития с помощью моделей с большим языковым объемом, становится необходимым балансировать весы инноваций с безопасностью и конфиденциальностью. Энтузиазм, окружающий МЯО, и наше постоянно растущее желание интегрировать их со всем миром возможных применений неоспоримы. Однако потенциальные опасности, такие как утечки данных, непреднамеренные предубеждения или неправильное использование, также реальны и требуют нашего немедленного внимания. Я рассмотрел, как можно установить механизм обнаружения PII и токсичного контента, поступающего в ваши МЯО, и обсудил реализацию с помощью LangChain.

Еще много работы и исследований остается — возможно, лучшая архитектура, более надежный и безупречный способ обеспечения конфиденциальности и безопасности данных. Код в этом посте усечен для краткости, но я призываю вас заглянуть в мой репозиторий на GitHub, где я собрал подробные записные книжки по каждому шагу, а также полный исходный код пользовательского LangChain, о котором мы говорили. Используйте его, форкайте его, улучшайте его, идите вперед и инновируйте!

Ссылки

[1] Jacob Devlin, Ming-Wei Chang и др. BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding

[2] Victor Sanh, Lysandre Debut и др. DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter

[3] Dataset — Jigsaw Multilingual Toxic Comment Classification 2020

Если не указано иное, все изображения принадлежат автору