НСПК / 24.12.24 / перетяжка / 2W5zFK76vmn
НСПК / 24.12.24 / перетяжка / 2W5zFK76vmn
НСПК / 24.12.24 / перетяжка / 2W5zFK76vmn

API Kandinsky 3.0 и метод улучшения качества генераций

Разобрали API Kandinsky 3.0 и автоматизировали процесс генерации изображений с примерами кода. Код написан на Python.

5К открытий10К показов
API Kandinsky 3.0 и метод улучшения качества генераций

Итак, совсем недавно вышла третья версия генеративной нейросети от Сбера, названной в честь знаменитого художника.

Её отличительной особенностью является генерация видео и собственное API. Видео – тоже интересная тема, однако тут речь пойдёт именно о изображениях.

Ранее я уже автоматизировал генерацию (на 2.2 версии), но без API она пользовалась UI Mozilla Firefox и давала сбои. Среднее время генерации находилось на отметке 28,7 секунд/картинку, а теперь – 11,6.

Писать нам придётся на python, чему многие не обрадуются, но поверьте, в данном случае это на скорость не влияет.

По себе знаю, что программисты уже жаждут кода, поэтому без длинных предисловий…

			import requests

import json
import time
import base64

from random import randint as r
from random import choice as ch

import os
		

Поверьте, оно всё нам понадобится.

Дальше я “своровал” с Дзена целый класс (я пока не умею в ООП):

			class Text2ImageAPI:

    def __init__(self, url, api_key, secret_key):
        self.URL = url
        self.AUTH_HEADERS = {
            'X-Key': f'Key {api_key}',
            'X-Secret': f'Secret {secret_key}',
        }

    def get_model(self):
        response = requests.get(self.URL + 'key/api/v1/models', headers=self.AUTH_HEADERS)
        data = response.json()
        return data[0]['id']

    def generate(self, prompt, model, images=1, width=1024, height=1024):
        params = {
            "type": "GENERATE",
            "numImages": images,
            "width": width,
            "height": height,
            "generateParams": {
                "query": f"{prompt}"
            }
        }

        data = {
            'model_id': (None, model),
            'params': (None, json.dumps(params), 'application/json')
        }
        response = requests.post(self.URL + 'key/api/v1/text2image/run', headers=self.AUTH_HEADERS, files=data)
        data = response.json()
        return data['uuid']

    def check_generation(self, request_id, attempts=10, delay=10):
        while attempts > 0:
            response = requests.get(self.URL + 'key/api/v1/text2image/status/' + request_id, headers=self.AUTH_HEADERS)
            data = response.json()
            if data['status'] == 'DONE':
                return data['images']

            attempts -= 1
            time.sleep(delay)
		

А вот теперь наконец функция генерации и сохранения. На вход она получает запрос (prompt) и путь сохранения итога.

Само API выдаёт данные в формате base64, и для их преобразования мы используем соответствующую библиотеку.

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

			def gen(prom, dirr = "res"):
    api = Text2ImageAPI('https://api-key.fusionbrain.ai/', 'YOUR_API_KEY', 'YOUR_SECRET_KEY')
    model_id = api.get_model()
    uuid = api.generate(prom, model_id)
    images = api.check_generation(uuid)    

    # Здесь image_base64 - это строка с данными изображения в формате base64
    image_base64 = images[0]

    # Декодируем строку base64 в бинарные данные
    image_data = base64.b64decode(image_base64)

    # Открываем файл для записи бинарных данных изображения
    try:
        with open(f"{dirr}/{prom.split('.')[0]} _ {r(0, 100000)}.jpg", "wb") as file:
            file.write(image_data)
    except:
        with open(f"{dirr}/{prom.split('.')[0]} _ {r(0, 100000)}.jpg", "w+") as file:
            file.write(image_data)
		

Теперь вы можете делать запросы очень просто:

			while 1:
    i = input("prompt: ")
    
    try:
        os.mkdir(os.getcwd().replace("\\", "/") + f'/' + zapros.replace("\n", " ").split(".")[0])
    except FileExistsError:
        print('exist')
            
    for j in range(4):
        gen(zapros.replace("\n", " "), zapros.replace("\n", " ").split(".")[0])
        print(f"сделано {j+1}")

    
    print("завершено")
		

Код выше сохранит 4 варианта картинки с одним запросом в одноимённой папке в директории программы.

Структура получится такая:

			DIR
| main.py
| 
| cute_boy
| | cute_boy_4563.jpg
| | cute_boy_384.jpg
| | cute_boy_457.jpg
| | cute_boy_6983.jpg
|
| cute_girl
| | cute_girl_1293.jpg
| | cute_girl_4657.jpg
| | cute_girl_879.jpg
| | cute_girl_564.jpg
		
API Kandinsky 3.0 и метод улучшения качества генераций 1
API Kandinsky 3.0 и метод улучшения качества генераций 2
API Kandinsky 3.0 и метод улучшения качества генераций 3
API Kandinsky 3.0 и метод улучшения качества генераций 4

Метод улучшения качества генераций GAN (на примере генератора изображений) посредством оптимизации запроса генетическим алгоритмом

Для начала я бы очень посоветовал вам каналы Veritasium и Vert dider (перевод), не только потому, что я использую тут их видео, а и потому, что это помогает мне лучше понимать физику ещё с 5 класса.

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

Итак, алгоритм действий:

  1. Из списка слов случайно составляем запрос
  2. генерируем и сохраняем с названием
  3. удаляем кривые и некачественные, с плохой стилизацией и т.п.
  4. !ВАЖНО! Берём названия успешных, и используем это как список слов для нового цикла, начиная с пункта 1.

При осуществлении работы такого алгоритма мы узнаём, какие слова влияют на поведение модели. Даже больше: удаляете картинки вы лично, а значит новые генерации вам понравятся. Возьмём список популярных художников. Сама модель о них и не слышала никогда, но некоторые слова делают генерации лучше. Мы переберём их всех, и те хорошие слова помогут создать хорошее изображение. Вы можете составить из этих слов свой запрос, а можете просто найти его в каталоге. Это быстрее и удобнее – больше вариантов, есть из чего выбрать.

В запросе есть слова типа fair hair, 1girl, cute.

Это значит, что можно удовлетворить все ваши потребности одной поисковой системой. Вы же понимаете, что в интернете конечное количество информации, но на каждый плюс-минус осмысленный и нужный запрос найдётся статья или новость.

Так и тут: изображений можно сделать настолько много, что генерировать уже не потребуется.

API Kandinsky 3.0 и метод улучшения качества генераций 5
Обычный поиск по папке позволяет найти всё, что нужно.

По моим примерным оценкам для 95% удовлетворения потребностей будет достаточно 2М изображений.

Их генерация займёт 3*2`000`000*11,6= 69,6М секунд или 2,2 года.

Кажется, это много, но ведь никто не запрещает использовать больше одного аккаунта.

SEGIM (СПГИ)

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

Сиситема Поиска Готовых Изображений работает просто: вы выполняете поиск по папке. Никаких алгоритмов лично от меня и т.п. Отлично работает стандартный проводник windows, но, может быть, вы знаете что-то другое. Например, поиск в Яндекс диске тоже отличный и предоставляет все файлы в удобном виде.

Собственно, мой вклад – изображения.

Возникает проблема… не моя. Они выполнены только в одном стиле. Если вам нужно что-то другое – можно подождать обновления (примерно 4 – 5 лет) или попробовать сделать это самому.

Ниже представлена функция, генерирующая в папку res/ 4000 изображений.

			def for_big_gen():
    print(len(res))
    last = time.time()

    for i in range(4000):
        try:
            line = 500 * " "
            while len(line) > 240:
                line = ""
                for j in range(r(4,20)):
                    line += ch(res).replace("\\", "").replace(", ,", ",") + ", "

            gen(line)

        except Exception as ex:
            print("detect except")

        if i % 20 == 0 and i != 0:
            now = time.time()
            print(i, "сделаны, ", round((now-last) / i, 5), "сек/шт.")
		

Внимательный программист заметит, что присутствует некий список res. Это собственно список слов для запросов. Их история изменения также приведена, как и последний на сегодня вариант – четвёртый.

Заключение

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

SMTHelse, 2023

API Kandinsky 3.0 и метод улучшения качества генераций 6
Следите за новыми постами
Следите за новыми постами по любимым темам
5К открытий10К показов