Что такое Марк?

Сейчас Марк от медиа Маркер — это генеративная языковая модель, которая умеет придумывать новостные статьи без помощи человека. Марк может писать свободно, опираясь на свой опыт и выбирая каждое слово самостоятельно. Либо же мы можем помочь ему с темой новости и дать начало заголовка или заголовок, тогда Марк продолжит нашу мысль.

Что такое языковые модели?

Говоря просто, языковые модели — это когда мы пытаемся найти закономерности и правильные речевые последовательности в человеческом языке, а потом на основе этого пробуем создать “язык” независимо от самого человека.

Как это можно сделать?

Можно оценить вероятность появления какого-то словосочетания в языке. Иными словами, каждый раз мы отвечаем себе на вопрос: корректно ли использовать такую последовательность слов (формулировку) в русском языке? Если это допустимо, то вероятность употребления такого словосочетания достаточно велика, а значит мы используем языковую конструкцию, которую могут понять остальные, знающие русский.

В противном случае появляются конструкции вроде “лето наступила”, по правилам нашего языка составленные некорректно, а значит, вероятность появления такой конструкции в речи довольно мала.

Главная идея: правильные языковые конструкции могут быть созданы не только человеком, но и искусственным интеллектом (или роботом). Соответственно между хорошей языковой моделью (которая хорошо понимает правила нашего языка) и человеком можно наладить продуктивную взаимную коммуникацию. И вот это уже идея на миллион!

Ты сам можешь генерировать новости!

Начнём с простого: сейчас мы покажем тебе, как генерировать новости. Целиком код для генерации лежит на COLAB — можно запустить всё и посмотреть, какую новость Марк сгенерирует для тебя!

Нашу обученную модель мы выложили на Hugging Face — технологический стартап с активным open source сообществом, который способствовал внедрению моделей на основе трансформеров (к примеру, предшественников и самой ChatGPT) во всем мире.

Благодаря стартапу к большому количеству тяжелых (и умных) моделей можно подключиться просто по API и самому творить магию, не имея огромных вычислительных машин.

Например, вот так мы получим доступ к нашей модели:

from transformers import GPT2LMHeadModel, GPT2Tokenizer

path = 'AnyaSchen/news_gpt-3'
tokenizer = GPT2Tokenizer.from_pretrained(path)
model = GPT2LMHeadModel.from_pretrained(path).to(DEVICE)

Возможно, нужно будет установить библиотеку transformers. Например, вот так:

!pip install transformers

Ну, а новости ты можешь сгенерировать вот этим кодом:

inp = input('Введи начало заголовка или просто нажми Enter:')
inp = inp if len(inp) > 0 else tokenizer.bos_token #токен начала предложения

input_ids = tokenizer.encode(inp, return_tensors="pt").to(DEVICE)

out = model.generate(input_ids,
                    do_sample = True,
                    num_beams = 3,
                    temperature = 2.0,
                    top_p = 0.9,
                    max_length = 200,
                    stopping_criteria = StoppingCriteriaList([stop_criteria]),
                    eos_token_id = tokenizer.eos_token_id,
                    bos_token_id = tokenizer.bos_token_id).to(DEVICE)

print(tokenizer.batch_decode(out, skip_special_tokens=False)[0])

Что тут происходит? Сейчас расскажем.

Шаг 1: Мы задаём начало заголовка нашей новости в переменную input. Если вдруг нам нечего дать в начало, и мы нажимаем Enter, то подставляется специальный символ, обозначающий для нашей модели начало предложения (мол, генерируй давай с самого начала).

inp = input('Введи начало заголовка или просто нажми Enter:')
inp = inp if inp else tokenizer.bos_token #токен начала предложения

Шаг 2: Дальше мы берём наш входной текст и говорим (дословно): токенайзер, тебе нужно заэнкодить наше начало.

input_ids = tokenizer.encode(inp, return_tensors="pt").to(DEVICE)

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

Зачем так?

Цель: Мы пытаемся научить компьютер “понимать” наш язык.

Компьютер хранит наши буковки числами, например, в виде ASCII-кода, где каждому символу присваивается уникальный номер (1, 2, 3…), а потом оно конвертируется в нолики и единички. Так вот слова в такой системе просто набор чисел, например:

котик → 1000011101010000111110100010000101000011100010000111010 (попробуй сам)

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

10000011010100010000001000011000010001000001100001100001000011001010001000111100001110001000011101010110010000010001000010100010010111000001000100000110001000011100001111111000011010110001000000100001

Понятно, что тут ничего не понятно: ни сколько тут слов, ни что они собой значат. Ты можешь прочитать эти 1 и 0, но в чем смысл, это просто цифры, да?) Ещё одно послание (как у тебя дела с китайским?) — 你會成功的! Но ты не поймешь, пока кто-то не переведёт это на понятный тебе язык.

Энкодер делает именно это: переводит с человеческого на понятный компьютеру.

Проблема: как объяснить компьютеру, что это за слова и что они значат?

Умные ученые нашли решение:

  • разбиваем предложения на кусочки, из которых могут быть составлены родственные слова (именно это и делает токенайзер в нашей модели)

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

    • Почему кусочки, а не слова? Потому что кот и котик — это про одно и тоже, но настроение меняется)

    Можно сравнить с настройкой робота из фильма Интерстеллар: 70% честности, 80% позитивности и т.д. Мы задаем какие-то параметры, по которым можно “почувствовать” каждое слово, но не нам, а компьютеру.

    В реальности, конечно, все сильно сложнее…???? Но идея понятна, да?

  • Каждому кусочку присваивается уникальный номер, и энкодер нам возвращает именно его. Почему так? Чтобы общаться, мы используем слова в определенной последовательности и не сообщаем собеседнику все трактовки каждого сказанного нами слова, надеясь, что наше понимание слов идентично. Так и с компьютером: наборы уникальных номеров — это его слова.

    Например, слово “нейросеть”, переведенное на язык нашей модели, выглядит так:

    [[ 845, 648, 1380 ]]

Шаг 3: Генерация на понятном компьютеру языке

out = model.generate(input_ids,
                     do_sample = True,
                     num_beams = 3,
                     temperature = 2.0,
                     top_p = 0.9,
                     max_length = 200,
                     stopping_criteria = StoppingCriteriaList([stop_criteria]),
                     eos_token_id = tokenizer.eos_token_id,
                     bos_token_id = tokenizer.bos_token_id).to(DEVICE)

Мы научили языковую модель генерировать новости (как? Потом расскажем), но создаёт она их, подбирая семантически каждый кусочек по своим выученным закономерностям и правилам. Чтобы новости получались разнообразнее и умнее, чем тексты у T9, мы использовали самые разные параметры генерации: температура, количество звеньев и т.д. Если будет интересно — расскажем, как они влияют на процесс (можешь поменять значения у себя в коде — увидишь, как всё ломается).

Из интересного тут — критерий остановки (код ниже тоже тебе нужен).

class KeywordsStoppingCriteria(StoppingCriteria):
    def __init__(self, keywords_ids:list):
      self.keywords = keywords_ids
    def __call__(self, input_ids: torch.LongTensor, scores: torch.FloatTensor, **kwargs) -> bool:
      if input_ids[0][-1] in self.keywords:
        print(input_ids)
        return True
      return False

stop_criteria = KeywordsStoppingCriteria(tokenizer.encode(tokenizer.eos_token, return_tensors="pt").to(DEVICE))

Что на выходе генерации? Чтобы модель не выдавала бесконечные потоки слов, мы ограничили длину предложения в 200 слов (смотри параметры генерации). Но это не всё, ей нужно помочь с окончанием процесса в момент, когда она сгенерировала свою логическую мысль и напечатала специальный токен конца предложения <eos>. Для этого нужен код выше: остановить генерацию, когда увидели ключевое слово (токен) для остановки.

После выполнения этого шага генерации в переменной out будут лежать числа — уникальные значения кусочков, которые наша языковая модель нагенерировал (aka новости, только на языке, понятном компьютеру).

Шаг 4: Перевести это обратно на человеческий

print(tokenizer.batch_decode(out, skip_special_tokens=False)[0])

Мы перевели человеческий в машинный, машина нагененерировала нам новости на своем языке, а теперь что? Правильно, машинный на человеческий, пожалуйста, чтобы нам понять. → Это и делает декодер.

И вот нам выводится новость, которая поделена на специальные токены: начала, отделения заголовка от описания и конца предложения. Чтобы эти токены нормально сработали, нужно вначале их показать токенайзеру (смотри, у нас и такие специальные “слова” есть).

SPECIAL_TOKENS = {'bos_token':'<bos>','eos_token' :'<eos>', 'pad_token':'<pad>', 'sep_token': '<sep>'}
tokenizer.add_special_tokens(SPECIAL_TOKENS)

Напоминаем, что целиком код для генерации можно найти тут: COLAB

Что же ты сегодня узнал:

  • Что такое языковая модель

  • Как происходит генерация кода в языковых моделях

  • Энкодер переводит с человеческого на машинный, а декодер — наоборот

  • Токенайзер пилит слова на кусочки, а модель — обрабатывает семантику этих кусочков

Автор статьи: @anyaschenikova

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


  1. anonymous
    00.00.0000 00:00

    НЛО прилетело и опубликовало эту надпись здесь


    1. dimars08
      00.00.0000 00:00

      Вы серьезно решили задать этот главный вопрос?;


  1. cry_san
    00.00.0000 00:00

    Выдает ошибку на последнем шаге


    1. marker_media Автор
      00.00.0000 00:00

      Починили:)

      Вероятно, случились сложности с подключением к видеокарте, поскольку часть кода удалили (случайно, остались права на редактирование у всех пользователей по ссылке). Теперь все должно быть в порядке!


  1. vladimircape
    00.00.0000 00:00

    Итак в мире было много белого шума(перепечатка новостей ,сеошные статьи, пропаганда и ....) так теперь и мл модели увеличат его на порядок


  1. venanen
    00.00.0000 00:00

    Интересно было бы посмотреть на процесс fine-tuning модели, хотелось бы такую статью


  1. dimars08
    00.00.0000 00:00

    По ссылке 404 ошибка(