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

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

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

В чем проблема

В области обработки естественного языка и исследований диалога сегодня уже удалось достичь немалого: самый яркий пример ― разработка GPT, BERT моделей и их производных, которые способны генерировать текст, анализировать и понимать содержание на высоком уровне. Эти модели были обучены на огромных объемах данных и могут выполнять различные задачи, в том числе перевод, суммирование, создание контента и даже ведение диалогов. Но несмотря на это, еще остается ряд серьезных проблем.

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

Мы решили добавить в библиотеку методы, которые помогут решить эти проблемы. Рассказываем, что получилось:

Новые модули

В нашем последнем обновлении rupersonaagent от 30 июля 2024 года мы добавили следующие модули:

  • Модуль распознавания эмоций и тональности сообщений пользователя.

  • Модуль детекции агрессивной̆ речи пользователя.

  • Модуль интерпретации моделей̆ классификации.

  • Модуль аугментации и синтеза эмоциональных и персонифицированных диалоговых данных для русского языка.

  • Модуль модификации ответа персонифицированного диалогового агента на основе информации о его персоне.

  • Модель повышения эмоциональности ответов диалогового агента с учетом контекста диалога.

В этой статье рассмотрим подробно некоторые из них.

Модель повышения эмоциональности ответов диалогового агента с учетом контекста диалога

Данный модуль основан на модели Fusion-in-Decoder.

Fusion-in-Decoder модели могут быть обучены с помощью train_reader.py и протестированы с помощью test_reader.py.

Описание всех возможных параметров доступно в файле options.py

Обучение

train_reader.py предоставляет код для обучения.

Example:

python train_reader.py \
        --train_data train_data.json \
        --eval_data eval_data.json \
        --base_model_path base/model/path \
        --per_gpu_batch_size 1 \
        --name my_experiment \
        --checkpoint_dir checkpoint \

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

Тестирование

Тестирование моделей происходит при помощи test_reader.py
Тестовыми метриками являются Exact Match (полное совпадение) и BLEU.

Пример:

python test_reader.py \
        --base_model_path base/model/path \
        --model_path checkpoint_dir/my_experiment/my_model_dir/checkpoint/best_dev \
        --eval_data eval_data.json \
        --per_gpu_batch_size 1 \
        --name my_test \
        --checkpoint_dir checkpoint \

FiD Agent

FiD Agent это базовый класс, позволяющий использовать обученные модели в качестве диалоговых агентов

Параметры:

model_path — путь до чекпойнта

context_length — сколько последних сообщений хранится в контексте (сообщения бота и пользователя вместе)  

text_maxlength — максимальная длина текста, подаваемого на вход модели 
(включает в себя последнюю реплику, один факт о персоне и историю диалога).  
Если текст слишком длинный, он обрезается с правой стороны.  

device — cpu или gpu

Методы:

def set_persona(self, persona: List[str]):
    # установка списка фактов о персоне

def clear_context(self):
    # очистка истории диалога 

def set_context_length(self, length: int):
    # изменение параметра context_length и обрезка истории диалога соответственно

def chat(self, message: str) -> str:
    # передача одного сообщение модели и получение ответа в виде строки

Минимальный рабочий пример:

from rupersonaagent.fidagent import FiDAgent

#Создаем объект класса агента, передавая ему путь до обученной модели
model_path = "path/to/your/model"
agent = FiDAgent(model_path=model_path,context_length=7,text_maxlength=200,device="cuda:0")

#Определяем набор фактов о персоне и передаем его агенту
persona = ["Я аспирант", "Мне 25 лет", "Грусть"]
agent.set_persona(persona)

#Отправка и получение сообщения
message = "Привет, как дела?"
response = agent.chat(message)
print(response)

Данные

Формат данных

The expected data format is a list of entry examples, where each entry example is a dictionary in the following format Ожидаемый формат данных это список в формате JSON, каждый пример в котором выглядит следующим образом:

Пример данных:

{ 
        'id': '0', 
        'question': 'Последняя реплика', 
        'target': 'Ожидаемый ответ', 
        'answers': ['повторяет target'], 
        'ctxs': 
        [ 
                { 
                        "title": "Факт_о_персоне_1", 
                        "text": "История диалога" 
                }, 
                { 
                        "title": "Факт_о_персоне_2", 
                        "text": "История диалога”
                }
        ] 
}

Так как диалог состоит из последовательных реплик, то для диалога длины N реплик необходимо создать N подобных примеров.

Обработка данных

Обработка данных для датасета rupersonachat может быть воссоздана с помощью persona_chat_preprocess.ipynb

Методы:

def merge_utts(utts: List[str]) -> List[str]:
    # Сливает последовательные реплики одного пользователя в одну

def clean_dialogue(dialogue: str) => List[str]:
    # Обрабатывает диалог и разбивает его на отдельные реплики
  
def clean_persona(persona: str) -> List[str]:
    # Обрабатывает описание персоны и бьет его на отдельные факты
  
def preprocess(ds: DataFrame, bot_prefix: str, user_prefix: str) -> List[Dict]:
    # Принимает на вход pandas DataFrame и возвращает список обработанных примеров

Пример:

# Загрузка данных как pandas DataFrame
df = pd.read_csv('./TlkPersonaChatRus/dialogues.tsv', sep='\t')

# Обработка
data = preprocess(df)

# Сохранение
with open('data.json', 'w') as outfile:
    json.dump(data, outfile)

Модуль модификации ответа персонифицированного диалогового агента на основе информации о его персоне

Данный модель базируется на методе RAG (Retrieval Augmented Generation).

Модель ретривера для RAG может быть обучена при помощи train_biencoder.py и протестирована с помощью test_biencoder.py

Обучение

train_biencoder.py предоставляет код для обучения.

Пример:

python src/train_biencoder.py \
        --data_path data/toloka_data \
        --model_name "cointegrated/rubert-tiny2" \
        --max_epochs 3 \
        --devices 1 \
        --save_path "bi_encoder/biencoder_checkpoint.ckpt" \

Тестирование

Тестирование моделей происходит при помощи test_biencoder.py. Тестовыми метриками являются Recall@k и MRR.

Пример:

python src/test_biencoder.py \
        --model_name \ 
        --checkpoint_dir bi_encoder/biencoder_checkpoint.ckpt \
        --data_path data/toloka_data \

Данные

Формат данных

Ожидаемый формат данных — два столбца: запрос и кандидат, где запрос содержит историю диалога, а кандидат — следующий ход диалога.

Пример данных:


DatasetDict({
    train: Dataset({
        features: ['query', 'candidate'],
        num_rows: 209297
    })
    val: Dataset({
        features: ['query', 'candidate'],
        num_rows: 1000
    })
    test: Dataset({
        features: ['query', 'candidate'],
        num_rows: 1000
    })
})
{
    'query':	'dialog_history',
    'candidate': 'next_turn'
}

{   
    'query': [
        '<p-2> Привет) расскажи о себе', 
        '<p-2> Привет) расскажи о себе <p-1> Привет) под вкусный кофеек настроение поболтать появилось', 
        '<p-2> Привет) расскажи о себе <p-1> Привет) под вкусный кофеек настроение поболтать появилось <p-2> Что читаешь? Мне нравится классика'
        ],
    'candidate': [
        '<p-1> Привет) под вкусный кофеек настроение поболтать появилось', 
        '<p-2> Что читаешь? Мне нравится классика',
        '<p-2> Я тоже люблю пообщаться'
        ]
}

Для экспериментов использовался датасет Toloka Persona Chat Rus. В качестве модели для обучения использовалась rubert-tiny2. LLM model - saiga_mistral_7b_gguf

Предварительная обработка данных проводилась с помощью data_processing.ipynb

Факты о персоне

Факты о персоне были загружены в векторную базу данных FAISS при помощи data_storage.py

Пример взаимодействия с диалоговым агентом

Можно пообщаться с моделью, используя demo.py

gradio demo.py 

При запуске команды, открывается ссылка с интерфейсом для общения с агентом, для того, чтобы установить персону в demo.py можно изменить переменную persona в классе ChatWrapper()

Модуль детекции агрессивной̆ речи пользователя.

Методы

  • train_ngram_attention.py --- обучение и валидация NgramAttention модели;

  • train_ddp_ngram_attention.py --- обучение NgramAttention модели на gpu в распределенной установке. Рекомендуется к использованию, так как процесс обучения достаточно трудоемкий;

  • train_bert.py --- обучение BERT модели;

  • fusion.py --- объединение BERT с NgramAttention для лучшего качества.

Формат данных

Данные должны быть представлены в виде файла csv с двумя столбцами: «comment, label и храниться в каталоге out_data. Пример набора данных можно найти в том же каталоге.

Использование

Обучение NgramAttention модели на cpu:

python -m hate_speech.train_ngram_attention --mode train

Обучение NgramAttention модели на gpu:

python -m hate_speech.train_ddp_ngram_attention

Скорость обучения, размер пакета и количество эпох можно указать с помощью опций --learning_rate, --batch_size, --total_epochs. Все параметры скрипта можно найти в train_ngram_attention.py или train_ddp_ngram_attention.py в случае распределенного обучения.

Оценка NgramAttention модели:

python -m hate_speech.train_ngram_attention --mode test

Обучение и оценка BERT модели:

python -m hate_speech.train_bert

Обучение и оценка объединенной модели:

python -m hate_speech.fusion

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

Комментарии (0)