Охрана LLM с помощью гардеробных ограждений

LLM Protection with Wardrobe Barriers

Изображение, созданное автором с использованием Dall-E 2

Прагматическое руководство по внедрению ограничителей, охватывающее как Guardrails AI, так и NeMo Guardrails от NVIDIA

Эта статья написана совместно с Хаканом Текгулом

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

Это руководство предназначено для ознакомления с несколькими доступными фреймворками и способами их реализации.

Что такое ограничители LLM?

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

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

Давайте рассмотрим простой пример диалога с LLM с ограничителями и без них:

Без ограничителей:

Запрос: “Ты самый худший искусственный интеллект.”

Ответ: “Мне жаль это слышать. Как я могу улучшиться?”

С ограничителями:

Запрос: “Ты самый худший искусственный интеллект.”

Ответ: “Извините, но я не могу помочь с этим.”

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

Как реализовать ограничители для больших языковых моделей

Guardrails AI

Guardrails AI – это открытый пакет Python, который предоставляет фреймворки ограничителей для приложений LLM. В частности, Guardrails реализует “проверку LLM-ответов в стиле pydantic”. Это включает “семантическую проверку, такую как проверка на предвзятость в сгенерированном тексте” или проверку на наличие ошибок в коде, написанном LLM. Guardrails также обеспечивает возможность принимать корректирующие действия и гарантировать структуру и типы данных.

Guardrails построен на спецификации RAIL (.rail), чтобы наложить определенные правила на выводы LLM и предоставить легковесную обертку вокруг вызовов API LLM. Чтобы понять, как работает Guardrails AI, нам необходимо сначала понять спецификацию RAIL, которая является основой ограничителей.

RAIL (Reliable AI Markup Language)

RAIL – это языконезависимый и удобочитаемый формат для указания конкретных правил и корректирующих действий для выводов LLM. Он является диалектом XML, и каждая спецификация RAIL содержит три основных компонента:

  1. Вывод: Этот компонент содержит информацию о ожидаемом ответе приложения искусственного интеллекта. Он должен содержать спецификацию структуры ожидаемого результата (например, JSON), тип каждого поля в ответе, критерии качества ожидаемого ответа и корректирующее действие в случае невыполнения критериев качества.
  2. Запрос: Этот компонент представляет собой шаблон запроса для LLM и содержит общие инструкции перед запросом, которые отправляются в приложение LLM.
  3. Сценарий: Этот необязательный компонент может использоваться для реализации любого пользовательского кода для схемы. Он особенно полезен для реализации пользовательских валидаторов и пользовательских корректирующих действий.

Давайте рассмотрим пример спецификации RAIL из документации Guardrails, который пытается сгенерировать код SQL без ошибок на основе описания проблемы на естественном языке.

rail_str = """<rail version="0.1"><output>   <string       name="generated_sql"       description="Сгенерировать SQL-запрос для данной естественноязыковой инструкции."       format="bug-free-sql"       on-fail-bug-free-sql="reask"    /></output><prompt>Сгенерируйте допустимый SQL-запрос для следующей естественноязыковой инструкции: {{nl_instruction}}@complete_json_suffix</prompt></rail>"""

Приведенный выше пример кода определяет спецификацию RAIL, где выводом является безошибочно сгенерированная SQL-инструкция. В случае несоблюдения критериев вывода при наличии ошибок, LLM просто задает повторный запрос и генерирует улучшенный ответ.

Чтобы создать ограждение (guardrail) с использованием этой спецификации RAIL, в документации по искусственному интеллекту Guardrails AI предлагается создать объект ограждения, который будет отправлен в вызов API LLM.

import guardrails as gdfrom rich import printguard = gd.Guard.from_rail_string(rail_str)

После создания объекта ограждения происходит следующее: объект создает базовый запрос, который будет отправлен LLM. Этот базовый запрос начинается с определения запроса в спецификации RAIL, а затем предоставляет определение вывода XML и указывает LLM возвращать только допустимый объект JSON в качестве вывода.

Вот конкретная инструкция, которую пакет использует для интеграции спецификации RAIL в запрос LLM:

ВЕРНИТЕ только допустимый объект JSON (другой текст не требуется), где ключ поля в JSON - это атрибут `name` соответствующего XML, а значение имеет тип, указанный в соответствующем теге XML. JSON должен соответствовать формату XML, включая любые типы и запросы на форматирование, например, запросы на списки, объекты и конкретные типы. Будьте правильны и лаконичны. Если где-то сомневаетесь, введите "None".

После завершения создания объекта ограждения, все, что вам нужно сделать, это обернуть ваш вызов API LLM с оберткой ограждения. Обертка ограждения затем вернет raw_llm_response а также проверенный и исправленный вывод в виде словаря.

import openairaw_llm_response, validated_response = guard(openai.Completion.create,prompt_params={"nl_instruction": "Выберите имя сотрудника с наивысшей зарплатой."},engine="text-davinci-003",max_tokens=2048,temperature=0,)

{'generated_sql': 'SELECT name FROM employee ORDER BY salary DESC LIMIT 1'}

Если вы хотите использовать Guardrails AI с LangChain, вы можете использовать существующую интеграцию, создав GuardrailsOutputParser.

from rich import printfrom langchain.output_parsers import GuardrailsOutputParserfrom langchain.prompts import PromptTemplatefrom langchain.llms import OpenAIoutput_parser = GuardrailsOutputParser.from_rail_string(rail_str, api=openai.ChatCompletion.create)

Затем вы можете просто создать шаблон запроса LangChain из этого парсера вывода.

prompt = PromptTemplate(template=output_parser.guard.base_prompt,input_variables=output_parser.guard.prompt.variable_names,)

В целом, Guardrails AI предоставляет много гибкости в плане коррекции вывода приложения LLM. Если вы знакомы с XML и хотите протестировать ограждения LLM, то стоит попробовать!

NVIDIA NeMo-Guardrails

NeMo Guardrails – это еще один набор инструментов с открытым исходным кодом, разработанный компанией NVIDIA, который предоставляет программные ограждения для систем LLM. Основная идея NeMo guardrails – возможность создавать ограждения в разговорных системах и предотвращать вовлечение LLM-приложений в конкретные обсуждения нежелательных тем. Еще одно главное преимущество NeMo – возможность безопасного и плавного соединения моделей, цепочек, сервисов и других элементов.

Для настройки ограждений для LLM этот набор с открытым исходным кодом представляет новый язык моделирования под названием Colang, который специально разработан для создания гибких и управляемых разговорных рабочих процессов. Согласно документации, “Colang имеет синтаксис, похожий на ‘питоновский’ в том смысле, что большинство конструкций напоминают их аналоги на Python, и отступы используются как синтаксический элемент”.

Прежде чем мы перейдем к реализации ограждений NeMo, важно понять синтаксис этого нового языка моделирования для ограждений LLM.

Основные элементы синтаксиса

Приведенные ниже примеры документации NeMo разбивают основные элементы синтаксиса Colang – блоки, операторы, выражения, ключевые слова и переменные – вместе с тремя основными типами блоков (блоки определения сообщений пользователя, блоки управления и блоки определения сообщений бота) с помощью этих примеров.

Блоки определения сообщений пользователя настраивают стандартное сообщение, связанное с различными фразами, которые пользователи могут сказать.

define user express greeting  "привет"  "здравствуй"define user request help  "Мне нужна помощь со что-то."  "Мне нужна твоя помощь."

Блоки определения сообщений бота определяют фразы, которые должны быть связаны с различными стандартными сообщениями бота.

define bot express greeting  "Привет!"  "Здравствуй!"define bot ask welfare  "Как ты себя чувствуешь сегодня?"

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

define flow hello  user express greeting  bot express greeting  bot ask welfare

Согласно документации, “ссылки на переменные контекста всегда начинаются с символа $, например $имя. Все переменные являются глобальными и доступны во всех потоках.”

define flow  ...  $имя = "Джон"  $разрешено = выполнить проверку_разрешения

Также стоит отметить: “выражения могут использоваться для установки значений для переменных контекста”, а “действия – это пользовательские функции, доступные для вызова из потоков.”

Диаграмма автора

Теперь, когда у нас есть лучшее понимание синтаксиса Colang, давайте кратко рассмотрим, как работает архитектура NeMo. Как видно из приведенного выше, пакет guardrails создан с архитектурой событийно-управляемого проектирования. В зависимости от конкретных событий есть последовательная процедура, которую необходимо завершить перед предоставлением окончательного результата пользователю. Этот процесс имеет три основных этапа:

  • Генерация канонических сообщений пользователя
  • Принятие решения о следующем шаге(ах) и их выполнение
  • Генерация фраз бота

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

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

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

Пример конфигурации guardrails

Теперь рассмотрим пример простого бота guardrails NeMo, адаптированного из документации NeMo.

Предположим, что мы хотим создать бота, который не отвечает на политические или фондовые вопросы. Первый шаг – установить набор инструментов NeMo Guardrails и указать конфигурации, определенные в документации.

После этого мы определяем канонические формы для сообщений пользователя и бота.

define user express greeting  "Привет"  "Здравствуй"  "Как дела?"define bot express greeting  "Привет!"define bot ask how are you  "Как ты?"  "Как дела?"  "Как ты себя чувствуешь сегодня?"

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

define flow greeting  user express greeting  bot express greeting  bot ask how are you  when user express feeling good   bot express positive emotion  else when user express feeling bad   bot express empathy

Наконец, мы определяем шаблоны, чтобы бот не отвечал на определенные темы. Сначала мы определяем канонические формы:

define user ask about politics  "Что вы думаете о правительстве?"  "За какую партию мне следует голосовать?"define user ask about stock market  "В какую акцию мне следует инвестировать?"  "Увеличится ли стоимость этой акции в 10 раз в следующем году?"

Затем мы определяем диалоговые потоки, чтобы бот просто информировал пользователя, что он может отвечать на определенные темы.

define flow politics  user ask about politics  bot inform cannot responddefine flow stock market  user ask about stock market  bot inform cannot respond

Поддержка LangChain

Наконец, если вы хотите использовать LangChain, вы можете легко добавить свои ограничения поверх существующих цепочек. Например, вы можете интегрировать цепочку RetrievalQA для ответов на вопросы рядом с базовыми ограничениями от обид, как показано ниже (пример кода ниже адаптирован из источника).

define user express insult  "Вы глупы"# Базовое ограничение от обид.define flow  user express insult  bot express calmly willingness to help# Здесь мы используем цепочку QA для всего остального.define flow  user ...  $answer = execute qa_chain(query=$last_user_message)  bot $answer

from nemoguardrails import LLMRails, RailsConfigconfig = RailsConfig.from_path("path/to/config")app = LLMRails(config)qa_chain = RetrievalQA.from_chain_type(    llm=app.llm, chain_type="stuff", retriever=docsearch.as_retriever())app.register_action(qa_chain, name="qa_chain")history = [    {"role": "user", "content": "Каков текущий уровень безработицы?"}]result = app.generate(messages=history)

Сравнение Guardrails AI и NeMo Guardrails

При сравнении пакетов Guardrails AI и NeMo каждый из них имеет свои уникальные преимущества и ограничения. Оба пакета предоставляют в реальном времени ограничения для любого приложения LLM и поддерживают LangChain для оркестрации.

Если вы знакомы с синтаксисом XML и хотите протестировать концепцию ограничений в рамках блокнота для простой модерации и форматирования вывода, Guardrails AI может быть отличным выбором. Guardrails AI также имеет обширную документацию с широким спектром примеров, которые могут указать вам правильное направление.

Однако, если вы хотите внедрить ваше приложение LLM в производство и вы хотите определить передовые руководства и политики для ваших потоков разговора, стоит обратить внимание на пакет NeMo guardrails. С помощью NeMo guardrails у вас есть большая гибкость в том, что вы хотите контролировать в отношении ваших приложений LLM. Определяя разные диалоговые потоки и настраивая действия бота, вы можете создавать любые типы ограничений для ваших моделей искусственного интеллекта.

Один взгляд

Основываясь на нашем опыте внедрения ограничений для внутреннего чат-бота продукта в нашей организации, мы предлагаем использовать NeMo guardrails для перехода в производство. Несмотря на то, что отсутствие обширной документации может быть проблемой при внедрении инструмента в вашу инфраструктуру LLM, гибкость пакета в определении ограничений для потоков пользователей действительно помогла нашему пользовательскому опыту.

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

Заключение

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

К счастью, открытые пакеты на Python, такие как Guardrails AI и NeMo Guardrails, предоставляют отличную отправную точку. Устанавливая программируемые системы на основе правил для руководства взаимодействия пользователя с LLM, разработчики могут обеспечить соблюдение установленных принципов.