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, нам удалось успешно разработать персонифицированный эмоциональный диалоговый агент, интегрировав ряд модулей, направленных на распознавание и интерпретацию эмоциональной окраски письменной речи. Также реализованные в библиотеки модули позволили нашему диалоговому агенту классифицировать эмоции, адаптировать свои ответы в зависимости от эмоционального состояния пользователя и заданной эмоции. Это помогло сделать взаимодействие более глубоким и персонализированным.