Руководство по API
- Во-первых, конечно же, запустить веб-интерфейс с аргументом командной строки
--api
- пример в вашем “webui-user.bat”:
set COMMANDLINE_ARGS=--api
- Это включает API, который можно просмотреть по адресу http://127.0.0.1:7860/docs (или любой URL-адрес +/docs)
Основные, которые меня интересуют, это эти два. Давайте сосредоточимся только на
/sdapi/v1/txt2img
- Когда вы раскрываете эту вкладку, она дает пример полезной нагрузки для отправки в API. Я часто использовал это как ссылку.
- Так это бэкэнд. API в основном говорит, что доступно, что запрашивает и куда это отправить. Теперь, переходя к внешнему интерфейсу, я начну с создания полезной нагрузки с нужными мне параметрами. Примером может быть:
payload = { "prompt": "maltese puppy", "steps": 5 }
Я могу ввести в полезную нагрузку столько параметров, сколько захочу. API будет использовать значения по умолчанию для всего, что я не установлю.
- После этого я могу отправить его в API
response = requests.post(url=f'http://127.0.0.1:7860/sdapi/v1/txt2img', json=payload)
Опять же, этот URL-адрес должен соответствовать URL-адресу веб-интерфейса. Если мы выполним этот код, веб-интерфейс сгенерирует изображение на основе полезной нагрузки. Это здорово, но что потом? Нигде нет изображения…
- После того, как бэкенд сделает свое дело, API отправляет ответ обратно в переменной, которая была назначена выше:
response
. Ответ содержит три записи; «изображения», «параметры» и «информация», и мне нужно найти способ получить информацию из этих записей. - Во-первых, я поставил эту строку
r = response.json()
, чтобы было проще работать с ответом. - «изображения» - это сгенерированное изображение, чего я больше всего и хочу. Там нет ссылки или чего-то еще; это гигантская строка случайных символов, по-видимому, нам нужно ее расшифровать. Вот как я это делаю:
for i in r['images']: image = Image.open(io.BytesIO(base64.b64decode(i.split(",",1)[0])))
- При этом у нас есть изображение в переменной
image
, с которым мы можем работать, например, сохраняя его с помощьюimage.save('output.png')
. - «параметры» показывают, что было отправлено в API, что может быть полезно, но в данном случае мне нужна «информация». Я использую его для вставки метаданных в изображение, поэтому я могу поместить его в веб-интерфейс PNG Info. Для этого я могу получить доступ к API
/sdapi/v1/png-info
. Мне нужно будет загрузить в него изображение, которое я получил выше.png_payload = { "image": "data:image/png;base64," + i } response2 = requests.post(url=f'http://127.0.0.1:7860/sdapi/v1/png-info', json=png_payload)
После этого я могу получить информацию с помощью
response2.json().get("info")
Пример кода, который должен работать, может выглядеть так:
import json
import requests
import io
import base64
from PIL import Image, PngImagePlugin
url = "http://127.0.0.1:7860"
payload = {
"prompt": "puppy dog",
"steps": 5
}
response = requests.post(url=f'{url}/sdapi/v1/txt2img', json=payload)
r = response.json()
for i in r['images']:
image = Image.open(io.BytesIO(base64.b64decode(i.split(",",1)[0])))
png_payload = {
"image": "data:image/png;base64," + i
}
response2 = requests.post(url=f'{url}/sdapi/v1/png-info', json=png_payload)
pnginfo = PngImagePlugin.PngInfo()
pnginfo.add_text("parameters", response2.json().get("info"))
image.save('output.png', pnginfo=pnginfo)
- Импорт вещей, которые мне нужны
- определить URL-адрес и полезную нагрузку для отправки
- отправить указанную полезную нагрузку на указанный URL-адрес через API
- в цикле захватите “изображения” и расшифруйте их
- для каждого изображения отправьте его в API информации png и получите эту информацию обратно
- определите плагин для добавления информации png, затем добавьте информацию png, которую я определил в него
- в конце сохраните изображение с информацией png
Примечание к "override_settings"
.
Целью этой конечной точки является переопределение настроек веб-интерфейса для одного запроса, например пропуска CLIP. Настройки, которые можно передать в этот параметр, видны здесь, в URL-адресе /docs.
Вы можете развернуть вкладку, и API предоставит список. Есть несколько способов добавить это значение к полезной нагрузке, но я делаю это так. Я продемонстрирую с «filter_nsfw» и «CLIP_stop_at_last_layers».
payload = {
"prompt": "cirno",
"steps": 20
}
override_settings = {}
override_settings["filter_nsfw"] = true
override_settings["CLIP_stop_at_last_layers"] = 2
override_payload = {
"override_settings": override_settings
}
payload.update(override_payload)
- иметь нормальную грузоподъемность
- после этого инициализировать словарь (я называю его “override_settings”, но может не самое удачное название)
- тогда я могу добавить столько пар ключ: значение, сколько захочу
- сделать новую полезную нагрузку только с этим параметром
- обновить исходную полезную нагрузку, чтобы добавить к ней эту
Таким образом, в этом случае, когда я отправляю полезную нагрузку, я должен получить «cirno» на 20 шагах, с пропуском CLIP на 2, а также с включенным фильтром NSFW.
Для определенных настроек или ситуаций вы можете захотеть, чтобы ваши изменения остались. Для этого вы можете отправить сообщение в конечную точку API /sdapi/v1/options
Мы можем использовать то, что мы узнали до сих пор, и легко настроить код для этого. Вот пример:
url = "http://127.0.0.1:7860"
option_payload = {
"sd_model_checkpoint": "Anything-V3.0-pruned.ckpt [2700c435]",
"CLIP_stop_at_last_layers": 2
}
response = requests.post(url=f'{url}/sdapi/v1/options', json=option_payload)
После отправки этой полезной нагрузки в API модель должна переключиться на ту, которую я установил, и установить пропуск CLIP на 2. Повторяю, это отличается от «override_settings», потому что это изменение будет сохраняться, в то время как «override_settings» предназначен для одного запроса. .
Обратите внимание, что если вы меняете sd_model_checkpoint
, значением должно быть имя контрольной точки, как оно отображается в веб-интерфейсе. На это можно ссылаться с помощью этой конечной точки API (так же, как мы ссылаемся на API «опций»)
«Название» (имя и хэш) — это то, что вы хотите использовать.
Это на момент фиксации 47a44c7
Для более полной реализации фронтенда мой бот Discord находится здесь, если кто хочет посмотреть на него в качестве примера. Большая часть действий происходит в файле stablecog.py. Есть много комментариев, объясняющих, что делает каждый код.
Это руководство можно найти на странице обсуждения.
Кроме того, ознакомьтесь с этой клиентской библиотекой API Python для webui: https://github.com/mix1009/sdwebuiapi.