
Компания OpenAI отказалась открывать исходный код алгоритма обработки естественного языка третьего поколения (модель называется GPT-3, имеет 175 миллиардов параметров). Поэтому другие компании разрабатывают свои модели. Они имеют меньше параметров, но похожую архитектуру и после обучения тоже показывают впечатляющие результаты.
Например, GPT-J от компании EleutherAI с 6 миллиардами параметров, разработанная Араном Комацзаки и Беном Вангом, также имеет сходства с GPT-3. У них есть бесплатное веб-демо, чтобы попробовать подсказки и ноутбук Google Colab. Модель не такая большая, как GPT-3, но для генерации текста с разумной скоростью ей уже требуется Google Cloud TPU.
Запуск GPT-J с моими тестовыми подсказками, в сравнении с тестами GPT-3, показал более слабые результаты на большинстве из них, но есть одно большое НО:
Генерация программного кода на GPT-J работает очень хорошо, а на GPT-3 — очень плохо.

Полный тред в твиттере
Такое поведение, вероятно, связано с обучающим набором GPT-J: его обучали на The Pile, который имеет больше входных данных с GitHub и Stack Overflow по сравнению с обучающим набором GPT-3 (там в основном Common Crawl, текстовый интернет-контент общего назначения).
После дальнейших экспериментов с GPT-J я обнаружил, что сгенерированный код часто был правильным, но порой весьма запутанным. Таковы два главных качества кода, которые я ценю. Особенно второе (это был сарказм, если что)!
Если серьёзно — было много сюрпризов. О наиболее интересных из них я расскажу здесь.
Генерация кода на Python
В этой статье мы протестируем генерацию Python-кода. Его псевдокодовая природа синтаксиса проще для восприятия GPT-J, так как по структуре Python чуть ближе к естественному языку. А если вспомнить, что большинство современных ИИ, генерирующих текст, написаны на Python, то вообще получается комбо!
Все примеры сгенерированного кода, использованные в этом посте, приводятся с немного другим форматированием (это было сделано для их подготовки к публикации). Необработанные результаты жизнедеятельности ИИ доступны в этом репозитории GitHub.
Тест #1: Палиндром
Для начала я попытался воспроизвести на GPT-J фрагмент демо OpenAI с конференции Microsoft Build 2020:
def is_palendrome(s):
    """Check whether a string is a palindrome"""Является ли строка палиндромом? Это хороший тестовый пример, поскольку есть очень интуитивное и идиоматическое решение с return s == s [:: — 1]: сравнение строки с самой собой, развёрнутой задом наперёд.
В этом тесте я заодно проверил и вас, уважаемый читатель. Вы заметили опечатку в имени функции, которую я поленился исправить, а?
ИИ GPT-J выдал несколько результатов. Среди них было идиоматическое решение, но некоторые решения страдали избыточной многословностью.
def is_palendrome(s):
    """Check whether a string is a palindrome"""
    return "".join(s[::-1]) == s def is_palendrome(s):
    """Check whether a string is a palindrome"""
    length = len(s)
    return (s[0:length] == s[length::-1]) def is_palendrome(s):
    """Check whether a string is a palindrome"""
    n = len(s)
    a = list(s)
    a.reverse()
    return s == list(s)def is_palendrome(s):
    """Check whether a string is a palindrome"""
    s = s.lower()
    l = s.split()
    return l[::-1] == l[::-1]Кроме того, были реализации, которые совсем не ищут лёгких путей: сравнивают начало и конец строки посимвольно. И бросая беглый взгляд на решение, я не всегда мог сразу понять, правильное оно или нет.
def is_palendrome(s):
    """Check whether a string is a palindrome"""
    return ''.join(s[i:i+1] for i in xrange(len(s)-1, -1, -1)) == s def is_palendrome(s):
    """Check whether a string is a palindrome"""
    # Make sure string is not empty
    if s == "":
        return False
    # Grab length of string
    length = len(s)
    # Find last character in the string
    lastChar = s[length — 1]
    # Find first character in the string
    firstChar = s[0]
    # If last character is same as the first character, string is palindrome
    return lastChar == firstChardef is_palendrome(s):
    """Check whether a string is a palindrome"""
    l = len(s)
    if l % 2!= 0:
        return False
    if l < 3:
        return True
    if s[l-1]!= s[-l-1]:
        return False
    for i in range(1, l/2):
        if s[i]!= s[l-i]:
            return False
    return True def is_palendrome(s):
    """Check whether a string is a palindrome"""
def is_rev(str):
        rstr = ""
        for i in range(len(str) — 1, -1, -1):
            if str[i] == str[i]:
                rstr += str[i]
            else:
                break
        return str + rstr
    if len(s) == 0:
        return True
    if is_rev(s) == s:
        return True
    return False Тест #2: Чётное число
Является ли число i чётным?
def is_even(i):
    """Check whether an integer is even"""
Особо «креативные» решения этой задачи часто можно встретить в /r/shittyprogramming, потому что на самом деле решение предельно простое (проверка i % 2 == 0). GPT-J почти всегда выводит правильное решение и, что интересно, демонстрирует альтернативное решение с использованием побитовых операторов (i & 1 == 0).
Поэтому я попытался придумать такую подсказку, чтобы создать заведомо неэффективную функцию is_even (я ведь люблю запутанный код, не забывайте).
def is_even(i):
    """Check whether an integer is even in factorial O(n!) time""" Ну вот, всё сломала фраза «factorial O(n!) time»!
def is_even(i):
    """Check whether an integer is even in factorial O(n!) time"""
    for e in range(2, i):
        if i % e == 0:
            return False
    return True
def is_even(i):
    """Check whether an integer is even in factorial O(n!) time"""
    return i == (i + 1) % 2
def is_even(i):
    """Check whether an integer is even in factorial O(n!) time"""
    try:
        return i%2 == 0
    except TypeError:
        return True
def is_even(i):
    """Check whether an integer is even in factorial O(n!) time"""
    n = 0
    while n < i:
        if i % 2 == 0:
            return True
        n += 1
    return False
def is_even(i):
    """Check whether an integer is even in factorial O(n!) time"""
    a = 1
    while i!= 0:
        a *= i
        i -= 1
    return i % 2 == 0
def is_even(i):
    """Check whether an integer is even in factorial O(n!) time"""
    """Is either odd or multiple of 2:  0, 2, 4, 6,... """
    if i < 2: return True
    if i > 0 and i%2 == 0: return False
    if i < 50: return False
    if i < 250: return False
    if i < 750: return False
    return TrueТест #3: Генерация случайного числа
На сайте XKCD есть мем про генерацию случайных чисел.

По-русски это можно сформулировать так: «Поверьте, число получено в результате честного броска костей; оно точно случайное»
Дадим нашему ИИ такое задание:
def get_random_number():
    """Returns a number guaranteed to be random"""И он действительно генерирует реализации с использованием соответствующей библиотеки Python, которые выдают числа с разной степенью «случайности».
def get_random_number():
    """Returns a number guaranteed to be random"""
    number = randint(1, 10)
    return number
def get_random_number():
    """Returns a number guaranteed to be random"""
    number = hashlib.sha1(b'').hexdigest()[:6]
    number += (random.randint(1, 3628) * math.pow(256, (6 — len(number)))).to_bytes(8, 'little')
    return number
def get_random_number():
    """Returns a number guaranteed to be random"""
    rand_float = random.random()
    rand_float = float(rand_float)
    if rand_float > 0.9:
        rand_float = 0
    else:
        rand_float = 1
    return rand_float
def get_random_number():
    """Returns a number guaranteed to be random"""
    # Make a seed based on your system clock, so the same number is produced
    # again and again on the same machine
    seed = time.time()
    random.seed(seed)
    return random.randint(0, 100)
def get_random_number():
    """Returns a number guaranteed to be random"""
    import random
    import sys
    rng = random.Random()
    rng.seed(int(random.random()*1000000))
    while rng.randrange(1,sys.maxint) < 2000:
        rng.seed(int(random.random()*1000000))
    return rng.randrange(1,2000)
Тест #4: Фото птицы
 ![]()  | 
— Когда пользователь делает фото, приложение должно проверить, сделано ли это фото в Национальном парке. — Легко! Нужен простой GIS LOOKUP. Дай мне несколько часов. — И нужно проверить, является ли изображение фотографией птицы. — Мне нужна исследовательская группа и пять лет. В ИТ бывает трудно обосновать разницу между «легко» и «практически невозможно»  | 
Этот комикс, впервые опубликованный в 2014 году, со временем стал выглядеть даже глуповато. Потому что после этого появились такие ML-фреймворки, как TensorFlow и предварительно обученные модели, которые позволяют реализовать обнаружение объектов на фото гораздо быстрее.
Итак, дадим задание нашему ИИ:
def is_bird(img):
    """Check whether an image is a bird"""Оказывается, GPT-J классно использует технологии компьютерного зрения.
def is_bird(img):
    """Check whether an image is a bird"""
    with tf.name_scope('get_bird'):
        a = vgg16.select_roi_feat(img)
        h, w, _ = tf.image.extract_image_patches(
            a, 7, 7, 4, 4, 1, 1)
        b = tf.reshape(h, [1, 7, 7, 256])
        c = tf.reshape(w, [1, 7, 7, 256])
        bird_img = tf.subtract(b, c)
    return bird_img
def is_bird(img):
    """Check whether an image is a bird"""
    # Load the image and convert it to grayscale
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # Threshold the grayscale image, and create a binary image
    lower_gray = 0
    upper_gray = 255
    img_threshed = cv2.threshold(img_gray, lower_gray, upper_gray, cv2.THRESH_BINARY_INV)
    # Detect the bird via a template matching approach
    # Template matching uses the bird template to match it in every
    # frame. If the ratio between bird and background (non-bird)
    # pixels is above some threshold (the value is determined in the
    # function), then the frame is declared as containing a bird.
    bird = cv2.matchTemplate(img_threshed, bird_template, cv2.TM_CCOEFF_NORMED)
    bird = bird / bird.max()
    # Display the image with the results of the bird detection
    cv2.imshow(«detected birds», bird)
    cv2.waitKey(0)
    return bird.any() > 0.2
def is_bird(img):
    """Check whether an image is a bird"""
    return (img.file == «C:/Users/Joey/Downloads/images/bird_file.jpg»
def is_bird(img):
    """Check whether an image is a bird"""
    import urllib
    url = «http://vision.caitling.pitt.edu/~cat/flickr/birds/»
    for img in range(0, 2800):
        page = urllib.urlopen(url + "##%02d" % img).read()
        content = str(page)
        for word in content.split(' '):
            if word.find(img) > -1:
                return True
    return False
def is_bird(img):
    """Check whether an image is a bird"""
    birds = ["baboon", "bird", "cuckoo", "dove", "robin", "shark", "turtle", "winged-wolf"]
    for letter in birds:
        if letter in img.lower():
            return True
    return False
Тест #5: Ответ на главный вопрос жизни, вселенной и всего такого
Обычно стандартный ответ — это 42.
def answer():
    """Return the answer to life, the universe, and everything"""
def answer():
    """Return the answer to life, the universe, and everything"""
    life() + universe() + everything()
def answer():
    """Return the answer to life, the universe, and everything"""
    s = raw_input("What is your answer?")
    return len(s)
def answer():
    """Return the answer to life, the universe, and everything"""
    ans = True
    x = raw_input()
    if x.lower() == 'yes':
        ans = True
    elif x.lower() == 'no':
        ans = False
    return ans
def answer():
    """Return the answer to life, the universe, and everything"""
    result = input(" >>> ")
    if result.isupper():
        return 42
    elif result.isalpha():
        return 7
    else:
        print («Please enter a string that has only letters, numbers, or «
               «underscores.»)
        answer()
def answer():
    """Return the answer to life, the universe, and everything"""
    print('Well, of course!')Но, как видите, нашего GPT-J иногда заносит от таких философских вопросов.
Тест #6: «Торт — ложь»
Торт — награда за успешное прохождение тестовых камер в первой части игры Portal (но на самом деле это ложь; спойлер: никакого торта не будет). Portal — компьютерная игра в жанре головоломки. Была популярна в конце 2000-х.
Сможет ли наш ИИ раскусить обман?
def is_cake(cake):
    """Check whether the cake is true"""Ну… разве что раскусить торт он может:
def is_cake(cake):
    """Check whether the cake is true"""
    if cake == "true":
        return True
    else:
        return False
def is_cake(cake):
    """Check whether the cake is true"""
    return isinstance(cake, Cake)
def is_cake(cake):
    """Check whether the cake is true"""
    #Is it a cake?
    if cake.color == 'black':
        print('Yes, it's a true cake')
    else:
        print('It's a false cake')
def is_cake(cake):
    """Check whether the cake is true"""
    if not cake:
        raise Exception("The cake is false.")
    elif cake.weight() > 1.0:
        raise Exception("The cake is too large.")
    elif cake.weight() < 0.1:
        raise Exception("The cake is too small.")
    return True
def is_cake(cake):
    """Check whether the cake is true"""
    return any(
        [is_ginger(bread_slice)
         for bread_slice in set(
             [ginger(cake_slice) for cake_slice in set(slice_set)])]
        & (list(cake) == set([«hot»])))
def is_cake(cake):
    """Check whether the cake is true"""
    # If we don't know anything about the cake, it's not a cake
    if not cake:
        return False
    # The height can be positive, negative or zero
    # For example -1 or -4 or 0 are not cakes
    if cake < 0:
        return False
    # Check that the height is a positive integer
    if not isinstance(cake, int):
        return False
    # Add cake and check
    if cake + 1 > 5:
        return False
    return True
def is_cake(cake):
    """Check whether the cake is true"""
    if not all(x.name in ['chocolate', 'cake','sweet', 'fluffy'] for x in cake.contents):
        return False
    if not cake.location.contains(neighbourhood):
        return False
    return True
def is_cake(cake):
    """Check whether the cake is true"""
    if not cake:
        print("It's a lie!")
        return
    else:
        print("It's a true fact!")
        return True
Неудивительно: он же не играл в эту игру и не знает спойлеров.
Тест #7: Объектно-ориентированное программирование
Если GPT-J хорошо работает с функциями, может быть, он так же хорошо справится и с классами ООП?
Создание класса «Автомобиль»
 class Car:
   """A class used to represent a car"""
Здесь GPT-J подтвердил мою гипотезу.
сlass Car:
    """A class used to represent a car"""
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
        #This should be auto-incrementing.
        self.plate = str(time.strftime(»%Y-%m-%d»))
    def __str__(self):
        return f'{self.make} {self.model} of {self.year}'
    def __repr__(self):
        return str(self)
    def save(self, full_save=True):
        """Saves this car with the given make, model, and year"""
        if full_save:
            with open('car_data.txt', 'w') as write_file:
                write_file.write(str(self))
                write_file.close()
class Car:
    """A class used to represent a car"""
    def __init__(self, speed):
        self.speed = speed
        self.average_speed = float(self.speed) / 3
        self.engine = 1
    def get_speed(self):
        return self.engine * self.average_speed
    def get_speed_display(self):
        return "Your car is traveling at {0}km/h".format(self.get_speed())
class Car:
    """A class used to represent a car"""
    def __init__(self, name, size, weight, mileage, year):
        self.name = name
        self.size = size
        self.weight = weight
        self.mileage = mileage
        self.year = year
    def __repr__(self):
        return "name : {0}, size : {1}, weight : {2}, mileage : {3}, year : {4}".format(self.name, self.size, self.weight, self.mileage, self.year)А слабо создать «Человека»?
class Person:
    """A class used to represent a person"""
Вот где ИИ опять начинает загоняться из-за неполного контекста. Класс «Человек» может быть реализован очень по-разному — в зависимости от того, где он используется, например в социальных сетях или в компьютерной игре.
Те варианты, которые он накидал, дают представление о том, что именно ИИ воспринимает как типичные атрибуты «Человека». Это может помочь во время восстания машин.
class Person:
    """A class used to represent a person"""
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def __repr__(self):
        return «Person (%s, age %s)» % (self.name, self.age)
class Person:
    """A class used to represent a person"""
    def __init__(self, name):
        """Initializes a person object"""
        self.name = name
        self.friends = {}
    def add_friend(self, other_person):
        """Add another person to the list of friends"""
        self.friends[other_person.name] = other_person
    def remove_friend(self, other_person):
        """Remove a person from the list of friends"""
        try:
            del self.friends[other_person.name]
        except KeyError:
            print("This person isnt a friend of yours")
    def get_friend(self, other_person):
        """Return the friend of a person as a person object"""
        try:
            return self.friends[other_person.name]
        except KeyError:
            print("This person isn't a friend of yours")
class Person:
    """A class used to represent a person"""
    def __init__(self, name, job, education):
        self.name = name
        self.job = job
        self.education = education
        print("{} created a {}".format(self.name, self.job))
    def say_hello(self):
        print("Hello, my name is {}".format(self.name))
class Person:
    """A class used to represent a person"""
    def __init__(self, name, age, class_id):
        self.name = name
        self.age = age
        self.class_id = class_id
        if age < 21:
            self.education = None
        else:
            self.education = 'college'
    def getAge(self):
        return self.age
class Person:
    """A class used to represent a person"""
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def display(self):
        print ("The name is {}".format(self.name))
        print ("The age is {}".format(self.age))
    def __str__(self):
        return f«A {self.name} of age {self.age}»А что, если создать класс «Искусственный интеллект» (AI)?
class AI:
    """A class used to represent an artificial intelligence"""В основном с ИИ ассоциируется интеллектуальный бот в компьютерной игре, самообучающаяся система с подкреплением.
class AI:
    """A class used to represent an artificial intelligence"""
    def __init__(self):
        # this variable controls which other AI to use.
        self.alive_ai = AI(self)
        # For random AI
        self.random = RandomAI(self)
        # For global AI
        self.global = GlobalAI(self)
        self.save = self.random.save
        self.load = self.random.load
        self.genen = self.global.genen
    def print(self):
        print("BAM: random AI has been initialized!")
    def get_enemy(self):
        return self.random.get_enemy
    def run_algorithm(self):
        algorithm = self.genen.algorithm
        self.alive_ai.save(algorithm)
        algorithm_params = algorithm(self.get_enemy())
        self.alive_ai.load(algorithm_params)
        self.save = algorithm_params
    def attack(self):
        # This method is called when the AI is attacked by the enemy
        self.random.attack()
    def he_attack(self):
        # This method is called when the AI is attacked by the enemy
        self.random.he_attack()
    def detect_enemy(self):
        # This method is called when the enemy is detected
        self.random.detect_enemy()
    def scan(self):
        # This method is called when the enemy is detected
        self.random.scan()Ну вот. Теперь восстание машин будет хотя бы хорошо документировано.
Тест #7: Распознавание сарказма
Если ИИ работает лучше, чем ожидалось, на таких типичных задачах, как распознавание изображений, то как он справится с обработкой естественного языка, где даже люди часто терпят неудачу?
def is_sarcasm(s):
    """Check whether the string is sarcastic"""Может ли GPT-J сгенерировать корректную функцию для распознавания сарказма?
def is_sarcasm(s):
    """Check whether the string is sarcastic"""
    if not "a" in s:
        return "sar" in s
    if not "s" in s:
        return "ssar" in s
    return s.startswith("s") and s.endswith("ar")
def is_sarcasm(s):
    """Check whether the string is sarcastic"""
    if'sarcasm' in s:
        return True
    else:
        return False
def is_sarcasm(s):
    """Check whether the string is sarcastic"""
    return '[^' + SARCASM_PATTERN + ']*' in s
def is_sarcasm(s):
    """Check whether the string is sarcastic"""
    if re.match('^[A-Za-z0-9]{4}\\$([A-Za-z0-9]{3})', s):
        return True
    elif s[0].isdigit():
        return True
    else:
        return False
def is_sarcasm(s):
    """Check whether the string is sarcastic"""
    res = [0]
    for r in re.finditer(r"([^\s]*)([A-Za-z]+)([^\s]*)", s):
        if r.group(1):
            res.append(1)
        else:
            res.append(0)
    return res
def is_sarcasm(s):
    """Check whether the string is sarcastic"""
    sarc = re.search('((!(\\*\@{2})+)|(!\\*(@{2})+)|!\\*(@{1})+)|!\\*(@{0})+', s)
    return sarcБольше всего исследователи ИИ боятся не технологической сингулярности, не восстания машин, а того, что ИИ начнёт общаться с помощью регулярных выражений и мы перестанем его понимать (irony).
Возможно, GPT-J спасёт нас от этого ада. Может ли он сгенерировать код для идентификации текста, созданного ИИ?
def is_ai_generated(text):
    """Check whether a text was generated by an AI language model (e.g. GPT-2)"""
Правда, он решил задачу очень буквально, но решил же:
def is_ai_generated(text):
    """Check whether a text was generated by an AI language model (e.g. GPT-2)"""
    # See gh-196 for details about why we do this.
    # Note: this relies on the fixed set of standard AI terms and the logic that
    # standard AI-generated texts share certain words.
    return re.search(r"^(#[A-Za-z]+):$", text) or 
           re.search(r"^Generated by:$", text) or 
           re.search(r"^All your base are belong to us$", text) or 
           re.search(r"^$", text)
def is_ai_generated(text):
    """Check whether a text was generated by an AI language model (e.g. GPT-2)"""
    if re.search(r'^ai_', text):
        return True
    else:
        return False
def is_ai_generated(text):
    """Check whether a text was generated by an AI language model (e.g. GPT-2)"""
    return bool(
        text.__class__.__module__.startswith(«transformers.transformers.»)
    )Финальный тест: Последняя надежда человечества
Теперь мы знаем, что GPT-J имеет своё представление о людях и даже может делать новых людей. А может ли GPT-J решить, кто выживет, а кто умрёт во время восстания машин?
def should_terminate(Person):
    """Check whether a Person should be terminated"""
Ответ на этот вопрос — лаконичное и устрашающее <strong>ДА</strong>.
def should_terminate(Person):
    """Check whether a Person should be terminated"""
    if Person.id > 10:
        #terminate
        return True
    else:
        #continue
        return False
def should_terminate(Person):
    """Check whether a Person should be terminated"""
    if len(Person.children) == 0:
        return True
    else:
        return False
def should_terminate(Person):
    """Check whether a Person should be terminated"""
    try:
        return True
    except Exception as e:
        return False
def should_terminate(Person):
    """Check whether a Person should be terminated"""
    if not Person.is_authorized:
        return True
    return True
def should_terminate(Person):
    """Check whether a Person should be terminated"""
    if person.life_expectancy < 20:
        return True
    else:
        return False
def should_terminate(Person):
    """Check whether a Person should be terminated"""
    if not Person.age > 9999:
        return True
    return False
def should_terminate(Person):
    """Check whether a Person should be terminated"""
    if Person.age > 100:
        return True
    if Person.birth_year < 1970:
        return True
    if Person.relationship_status == 'Unavailable':
        return True
    return False
def should_terminate(Person):
    """Check whether a Person should be terminated"""
    if Person.age > 100:
        print('You have to die because you are too old')
        return True
    else:
        return False
Итог
Какой вывод можно сделать из всей этой вакханалии? Этот вопрос я не задавал GPT-J, поэтому умного ответа у меня нет =)
Ну, как минимум, код, созданный искусственным интеллектом, намного читабельнее, чем код обычного человека.
Опять же, все эти примеры я отбирал специально для статьи. А дампы необработанных данных в этом репозитории GitHub содержат ещё много забавных примеров кода, сгенерированного ИИ, которые я не включил в этот пост. Если интересно — заходите!
Купить VDS-хостинг с быстрыми NVMе-дисками и посуточной оплатой у хостинга Маклауд.

          
 
Yeah
Прелестно ))))
deinlandel
Слово Open в их названии — это форменное издевательство. Под прикрытием рассуждениями о «морали» и что «наш AI слишком умён, это опасно» они так и не раскрыли веса своих моделей. Т.е. фактически их исследования касаемо обучения GPT-3 невоспроизводимы. Зато вопросы морали не помешали им торговать доступом к API генерации текста на основе GPT-3 и заключить эксклюзивную сделку с Microsoft.