Создание потрясающего приложения для генеративного ИИ с помощью React IDE
Если вы когда-нибудь задавались вопросом, как приложения искусственного интеллекта генерируют изображения по подсказкам пользователя, то вы попали по адресу.
В этой статье вы узнаете, как работают эти инструменты, создав приложение ИИ для генерации изображений.
Создание приложения
Начнем с создания React + TypeScript-приложения с помощью Vite. Выполните в терминале следующую команду:
npm create vite@latest
Затем необходимо ответить на три вопроса, чтобы Vite понял, как сконфигурировать ваш проект.
✔ Project name: aimages
✔ Select a framework: › React
✔ Select a variant: › TypeScript
Наконец, необходимо установить и настроить TailwindCSS.
Выполните две команды, приведенные ниже (в указанном порядке). Первая команда устанавливает tailwindcss
и его одноранговые зависимости. Вторая команда генерирует файлы tailwind.config.js
и postcss.config.js
.
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Теперь откройте файл tailwind.config.js
и измените код следующим образом:
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./index.html",
"./src/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Приведенный выше код настраивает TailwindCSS, указывая, какие файлы фреймворк должен проверять на предмет использования классов. Он настроен на проверку файла index.html
и всех файлов JavaScript и TypeScript в каталоге src
. Здесь же можно настроить тему оформления, цвета, шрифты и многое другое.
Наконец, откройте файл /src/styles.css
и добавьте директивы TailwindCSS в верхней части файла:
@tailwind base;
@tailwind components;
@tailwind utilities;
Настройка проекта завершена! Теперь, прежде чем переходить к следующему этапу, загрузите проект на GitHub. Позже вы поймете, почему!
Проблема построения пользовательских интерфейсов
Прежде чем продолжить, остановимся на основных проблемах создания пользовательских интерфейсов.
Одна из основных проблем создания пользовательских интерфейсов заключается в том, что при их создании отсутствует живая визуальная обратная связь. Вы вносите изменения в редакторе, сохраняете их и просматриваете в браузере. Затем, если изменения не устраивают, приходится повторять процесс.
В результате приходится часто переключаться между IDE и браузером. Хотя это может показаться незначительным неудобством, эти секунды ожидания обновления браузера, а также переключение между ними со временем увеличиваются. В течение дня такое переключение приводит к значительным потерям времени.
Это также приводит к нарушению потока. Любая помеха (например, переключение между приложениями) нарушает поток, что приводит к увеличению времени выполнения задачи и, возможно, к увеличению количества ошибок.
Кроме того, совместная работа с другими сотрудниками может быть утомительной и отнимать много времени. Обычный способ совместной работы предполагает работу над приложением, размещение изменений на GitHub и их развертывание. Только после этого другие участники могут проверить вашу работу. Это приводит к тому, что значительная часть времени уходит на непродуктивные действия, например, на ожидание развертывания изменений. Таким образом, традиционный подход может быть весьма громоздким и неэффективным.
В этой статье мы познакомимся с дополнительным инструментом, который можно использовать вместе с вашей любимой IDE для более качественного и быстрого создания пользовательских интерфейсов.
Визуальная среда разработки React IDE
Codux - это бесплатная визуальная IDE для приложений на React + TypeScript. Она позволяет работать над проектами в режиме реального времени с помощью визуального редактора. Все изменения, вносимые в свойства, стили и структуру (JSX) компонента, автоматически отражаются на экране.
Важное замечание: Codux не предназначен для замены вашей любимой IDE. Это дополнительный инструмент, который можно использовать вместе с IDE.
Вы можете создавать и модифицировать свои интерфейсы, используя панели и контроллеры, предоставляемые Codux. Как показано на рисунке, можно, например, задавать свойства и классы CSS и различные состояния элементов.
И, конечно же, внизу имеется редактор кода, если необходимо внести конкретные изменения путем написания кода.
Обратите внимание: независимо от того, делаете ли вы изменения с помощью визуального редактора, встроенного редактора кода или вашей обычной IDE, они всегда будут синхронизированы!
Codux также поддерживает все популярные решения для стилизации, такие как CSS, Sass, модули CSS/Sass, Stylable и TailwindCSS. В создаваемом нами приложении, например, используется TailwindCSS.
Комплексная площадка
Еще одной замечательной особенностью Codux является функция playground, позволяющая делиться своими наработками (компонентами) с другими пользователями.
В режиме playground люди могут просматривать и редактировать ваши компоненты без установки локальной среды разработки и других необходимых условий.
Давайте посмотрим на это в действии. В начале статьи я упомянул, что проект необходимо загрузить на GitHub. Причина в том, что playground требует, чтобы ваш проект был размещен на GitHub.
Чтобы поделиться своей доской (или компонентом), нажмите кнопку "Поделиться" справа.
Примечание: Общая доска является общедоступной, то есть любой, у кого есть ссылка, может ее увидеть. Будьте внимательны.
После этого Codux предложит создать имя ссылки для доски. Выберите имя и нажмите кнопку "Создать ссылку" (в первый раз) и "Опубликовать" (в последующем).
Упоминание: Каждый раз, когда вы вносите изменения, необходимо нажимать кнопку "Обновить ссылку" перед тем, как открыть общий доступ к доске. В противном случае изменения не будут применены и видны на общей доске.
Теперь вы можете скопировать ссылку и передать ее другим людям. Когда они перейдут по ссылке, то увидят онлайн-версию Codux (см. рисунок ниже).
Любой человек, имеющий ссылку на общую доску, может видеть ее и вносить изменения, включая текст, цвета, изображения и даже код. Это делает ее идеальным инструментом для совместной работы, где каждый может поделиться своими замечаниями и применить их простым и прямым способом.
Таким образом, разработчики могут сосредоточиться на важной работе, а не тратить драгоценное время на пересылку изменений друг другу.
Однако важно отметить, что изменения на общей доске не влияют на исходную доску и не применяются к ней. А ведь это была бы отличная возможность!
Добавление проекта в Codux
Продолжим импортировать в Codux созданный ранее проект. Щелкните на опции "Open Local Project" ("Открытый локальный проект") и выберите папку проекта.
После этого Codux предлагает запустить конфигурационные скрипты, которые устанавливают необходимый пакет для работы над проектом в данной IDE.
После завершения установки нажмите кнопку "Сканировать на наличие компонентов", чтобы Codux импортировал все компоненты.
После этого в боковой панели можно увидеть все доступные компоненты. В нашем случае имеется только один - App, поскольку это новый проект.
Вы можете создавать новые компоненты, нажав кнопку "+ Новый компонент", но об этом подробнее позже.
Как вы могли заметить, существуют "компоненты" и "доски". Доска" - это понятие, введенное в Codux, и она представляет собой крепление для ваших компонентов, чтобы Codux мог автоматически визуализировать их и позволить вам редактировать их визуально.
Чтобы создать "доску", щелкните на компонент, а затем нажмите кнопку " + Создать доску". Откроется меню, в котором можно задать начальную точку, имя доски и путь к ней.
Можно оставить параметры по умолчанию и нажать кнопку "Создать".
А это вид доски, где можно визуально редактировать компоненты.
Настройка TailwindCSS
Для того чтобы TailwindCSS работал в Codux, необходимо выполнить некоторые настройки в дополнение к процессу установки Tailwind, который был выполнен в начале статьи.
Создайте файл codux.config.js
в корневой папке проекта и добавьте в него следующий объект:
{
"$schema": "https://wixplosives.github.io/codux-config-schema/codux.config.schema.json",
"boardGlobalSetup": "./src/_codux/board-global-setup.ts"
}
Затем создайте файл board-global-setup.ts
в папке ./src/_codux
и добавьте в него следующий импорт:
import "../index.css";
Готово! Теперь классы TailwindCSS можно увидеть в IDE Codux.
Более подробную информацию о данной конфигурации можно найти по этой ссылке.
Создание приложения
В следующих разделах мы приступим к созданию приложения.
Создание папки components
Начнем с создания папки component
для всех компонентов. Это можно сделать либо в IDE, либо в терминале, либо в Codux. Вот как это можно сделать из Codux:
Щелкните на выделенный значок, чтобы увидеть файлы проекта. После этого создайте папку так, как вы бы создали ее на своей машине. Щелкните правой кнопкой мыши по папке src
и выберите пункт New Folder
.
Создание компонентов в Codux
Если вы хотите создавать компоненты с помощью интерактивного процесса из Codux, то вам необходимо задать путь к компонентам. Это можно сделать, добавив данный код в codux.config.json
:
{
"$schema": "https://wixplosives.github.io/codux-config-schema/codux.config.schema.json",
"boardGlobalSetup": "./src/_codux/board-global-setup.ts",
"newComponent": {
"componentsPath": "src/components"
}
}
Теперь можно создавать компоненты, используя визуальный интерфейс.
Компонент макета
Создайте компонент Layout
в папке components
. Мы будем использовать макет на всех страницах.
Дальнейшие шаги можно выполнить, используя привычную IDE или Codux.
Совет: В любом случае все будет в порядке, поскольку код автоматически синхронизируется между ними. Независимо от того, используете ли вы Codux или ваш редактор, оба будут содержать один и тот же код, и вам не придется ничего делать. Это здорово!
Теперь откройте компонент Layout
и добавьте следующий код:
type LayoutProps = {
children: React.ReactNode;
};
export default function Layout({ children }: LayoutProps) {
return (
<>
<main>{children}</main>
</>
);
}
Рефактор App.tsx
Затем перейдите в файл App.tsx
и замените его содержимое на следующий код:
import Layout from "./components/Layout";
import "./App.css";
import { useState } from "react";
function App() {
const [inputValue, setInputValue] = useState("");
const [imageURL, setImageURL] = useState("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState<null | string>(null);
const fetchImage = async (prompt: string) => {
const response = await fetch("http://localhost:3000/api/genimg", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ value: prompt }),
});
if (response.ok) {
const data = await response.json();
if (Array.isArray(data) && data.length > 0) {
return data[0];
}
throw new Error("Unexpected server response");
} else {
throw new Error(response.statusText);
}
};
const onInputChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setInputValue(e.target.value);
};
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
const url = await fetchImage(inputValue);
setImageURL(url);
} catch (err) {
if (err instanceof Error) {
setError(err.message);
} else {
setError("An unexpected error occurred");
}
} finally {
setLoading(false);
}
};
return (
<>
<Layout>
<section>
<div>
<div>
<h1>PromptPix AI</h1>
<p>
Dive into the world of AI-driven creativity with PromptPix AI,
where your words become vivid visuals. Simply input your idea,
and watch as our advanced algorithms craft the image you
envisioned.
</p>
</div>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="prompt">Image prompt</label>
<textarea
id="prompt"
placeholder="Enter your prompt"
value={inputValue}
onChange={onInputChange}
/>
</div>
<button type="submit" disabled={inputValue.length === 0}>
Generate
</button>
</form>
</div>
<div>
{loading && (
<div>
<p>Your image is being generated...</p>
<div>
<div>
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="44"
height="44"
viewBox="0 0 24 24"
strokeWidth="2"
stroke="currentColor"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
>
<path
stroke="none"
d="M0 0h24v24H0z"
fill="none"
></path>
<path d="M12 6l0 -3"></path>
<path d="M16.25 7.75l2.15 -2.15"></path>
<path d="M18 12l3 0"></path>
<path d="M16.25 16.25l2.15 2.15"></path>
<path d="M12 18l0 3"></path>
<path d="M7.75 16.25l-2.15 2.15"></path>
<path d="M6 12l-3 0"></path>
<path d="M7.75 7.75l-2.15 -2.15"></path>
</svg>
</div>
</div>
</div>
</div>
)}
{imageURL && !loading && (
<div>
<p>Find your generated image below</p>
<img
src={imageURL}
width={600}
height={600}
alt="Generated image"
/>
</div>
)}
{!imageURL && !loading && (
<div>
<p>Your image will appear below</p>
<div>
<div>
<div>
<svg
xmlns="http://www.w3.org/2000/svg"
width="44"
height="44"
viewBox="0 0 24 24"
strokeWidth="2"
stroke="currentColor"
fill="none"
strokeLinecap="round"
strokeLinejoin="round"
>
<path
stroke="none"
d="M0 0h24v24H0z"
fill="none"
></path>
<path d="M15 8h.01"></path>
<path d="M11.5 21h-5.5a3 3 0 0 1 -3 -3v-12a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v5.5"></path>
<path d="M18 18m-3 0a3 3 0 1 0 6 0a3 3 0 1 0 -6 0"></path>
<path d="M20.2 20.2l1.8 1.8"></path>
<path d="M3 16l5 -5c.928 -.893 2.072 -.893 3 0l2 2"></path>
</svg>
</div>
</div>
</div>
</div>
)}
{error && <div>{error}</div>}
</div>
</section>
</Layout>
</>
);
}
export default App;
Этот компонент содержит "голое" приложение без применения каких-либо стилей.
Примечание: В файле App
все приведено для наглядности. Так проще продемонстрировать инструмент. Окончательный вариант приложения можно увидеть на GitHub.
Создание стиля приложения с помощью Codux
Начнем со стилизации компонента Layout
. Дважды щелкните App
на вкладке Elements
(левый столбец).
Откроется новое дерево, в котором должен появиться компонент Layout
. Дважды щелкните на Layout
, а затем выберите main
.
На вкладке Elements
отображаются все HTML-элементы из вашего кода.
Чтобы добавить классы Tailwind к HTML-элементам, щелкните по значку "Свойства" с правой стороны. Затем найдите свойство "className".
После этого добавьте следующие классы Tailwind:
flex min-h-screen flex-col justify-center items-center
Эти классы устанавливают гибкий контейнер с минимальной высотой, равной высоте области просмотра, располагают его дочерние элементы в столбец и центрируют их по вертикали и горизонтали внутри контейнера.
Изменения должны быть заметны как визуально, так и в коде.
Довольно круто, правда?
Теперь давайте переключимся на вашу любимую IDE и посмотрим, насколько просто использовать их вместе. Откройте файл index.css
и добавьте в него этот блок:
body {
@apply bg-gray-50;
}
Компонент приложения
Продолжите добавление следующих классов в элемент section
из компонента App
:
container flex flex-col gap-6 py-8 md:max-w-[64rem] md:py-12 lg:py-24
Эти классы модифицируют секцию в гибкий контейнер с направлением колонок, вертикальным зазором между дочерними элементами в 6 единиц, вертикальным отступом в 8 единиц (увеличивается до 12 единиц на средних и 24 единиц на больших экранах) и максимальной шириной в 64rem на средних и больших экранах.
Аналогичным образом примените следующие классы к первому элементу div
:
bg-white shadow-md rounded border border-slate-200 p-14 text-center
Эти классы TailwindCSS используют белый фон, среднюю тень, закругленные углы, границы грифельного цвета, отступы со всех сторон в 14 единиц и текст, выровненный по центру.
Вот как выглядит приложение до этого момента.
Дальнейшие действия будут следующими:
- стилизация заголовка и описания
- стилизация формы
- стилизация той части, где будет появляться изображение
- создание API
Давайте зададим стиль заголовка и описания через вашу IDE (в моем случае VS Code), чтобы увидеть автосинхронизацию в действии.
Замените 2-й элемент div
следующим кодом:
<div className="mx-auto flex w-full flex-col md:max-w-[58rem]">
<h1 className="font-heading text-2xl mb-4 sm:text-4xl text-center">
PromptPix AI
</h1>
<p className="text-sm sm:text-base text-center mb-4">
Dive into the world of AI-driven creativity with PromptPix AI,
where your words become vivid visuals. Simply input your idea,
and watch as our advanced algorithms craft the image you
envisioned.
</p>
</div>
На скриншоте ниже показано, как должен выглядеть ваш код:
Если вы снова перейдете в Codux, то увидите примененные изменения в визуальной области и редакторе кода внизу страницы.
Аналогично, все изменения, сделанные в Codux, доступны в вашей IDE.
В качестве тренировки добавьте к этим элементам следующие классы:
- Элемент
form
-space-y-6
- Элемент
div
внутри формы -flex flex-col items-center gap-4
- Элемент
label
-text-sm sm:text-base
- Элемент
textarea
-border border-slate-200 rounded p-2 w-3/4 h-32 resize-none
- Элемент
button
:
`${
inputValue.length === 0
? "bg-white text-gray-800 font-semibold py-2 px-4 border border-slate-400 rounded shadow opacity-50 hover:opacity-50 cursor-not-allowed"
: "bg-white hover:bg-slate-100 text-gray-800 font-semibold py-2 px-4 border border-slate-400 rounded shadow"
}`
Вот как выглядит приложение с применением всех вышеперечисленных классов:
Выглядит уже неплохо, не так ли?
Последний шаг связан со стилизацией той части, где будет отображаться сгенерированное изображение. Мы сделаем начальный элемент div
(который отображается перед вводом подсказки) гибким контейнером с дочерними элементами, расположенными в столбец, центрированными по горизонтали, с промежутком 24px между каждым дочерним элементом и верхним полем 48px - flex flex-col items-center gap-6 mt-12
.
Вы можете добавить их как обычно, используя поле "className" из Codux.
Примените те же классы Tailwind к двум другим элементам div
, отображающим состояние загрузки и сгенерированное изображение.
Наконец, стилизуем сообщение типа error
:
{error && (
<div className="text-center w-1/2 mx-auto bg-red-500 mt-2 rounded border border-red-800">
{error}
</div>
)}
Теперь с пользовательским интерфейсом покончено!
Codux предлагает гораздо большее
При создании этого приложения вы в основном применяли классы и визуализировали результаты в реальном времени. Однако Codux предлагает гораздо больше.
С помощью Codux можно тестировать приложение на нескольких видовых экранах и вносить изменения в каждый из них в реальном времени.
Кроме того, мы добавили классы вручную для каждого элемента. Однако для стилизации элементов можно также использовать вкладку "Вычисленные стили". Вместо того чтобы писать код вручную, можно стилизовать элементы в интерактивном режиме.
Одна из моих любимых функций - возможность открыть код для определенного элемента. Вы можете выбрать конкретный элемент, щелкнуть на него правой кнопкой мыши и открыть его в редакторе кода/IDE.
На рисунке показано, как Codux выделяет соответствующий код для выбранного элемента. Здорово, правда?
Как видите, в Codux есть много интересных возможностей. Я рекомендую вам загрузить его и изучить. Это бесплатно!
Бэкенд-код для генерации изображения
Вероятно, вы используете другой язык программирования и фреймворк, нежели я. Вместо того чтобы тратить ваше время на мучительный процесс создания бэкенда на неинтересной вам технологии, я сразу поделюсь кодом для маршрута API.
import express, { Request, Response } from "express";
import Replicate from "replicate";
import cors from "cors";
const app = express();
const port = 3030;
app.use(express.json());
app.use(cors());
app.options("/api/genimg", (req: Request, res: Response) => {
// Pre-flight request. Reply successfully:
res.status(200).end();
});
app.post("/api/genimg", async (req: Request, res: Response) => {
const { value } = req.body;
try {
const replicate = new Replicate({
auth: process.env.REPLICATE_API_TOKEN || "",
});
const result = await replicate.run(
"stability-ai/stable-diffusion:a00d0b7dcbb9c3fbb34ba87d2d5b46c56969c84a628bf778a7fdaec30b1b99c5",
{
input: {
prompt: value,
image_dimensions: "1024x1024",
num_inference_steps: 50,
num_outputs: 1,
guideance_scale: 7.5,
prompt_strength: 0.8,
scheduler: "KarrasDPM",
},
}
);
res.status(200).json(result);
} catch (error) {
console.error("Failed to generate image. Error:", error);
res.status(500).json({ message: "Failed to generate image" });
}
});
app.all("/api/genimg", (req: Request, res: Response) => {
res.status(405).json({ message: "Method Not Allowed" });
});
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
Этот код TypeScript устанавливает сервер Express, который прослушивает порт 3030 и имеет включенный CORS. Он определяет три маршрута, все для пути "/api/genimg". Маршрут OPTIONS предназначен для обработки предполетных CORS-запросов. Маршрут POST принимает JSON-тело со свойством "value", использует его в качестве запроса на генерацию изображения с помощью Replicate API и возвращает результат. Если в ходе этого процесса возникает ошибка, то она фиксируется и возвращается код состояния 500 с сообщением о неудаче. Маршрут ALL является универсальным и возвращает код состояния 405, указывающий на то, что используемый метод не разрешен. Сервер прослушивает указанный порт и при работе выводит сообщение в консоль.
Таким образом, вы можете адаптировать код к выбранному вами языку программирования и фреймворку.
Примечание: Вы можете ознакомиться со всем кодом приложения (как сервера, так и клиента), перейдя по этой ссылке GitHub.
Заключение
Создание приложений сопряжено с трудностями, которые могут замедлить процесс разработки и затруднить совместную работу. Одной из основных проблем является постоянная необходимость переключаться между различными инструментами. Это отнимает значительное время и может нарушить концентрацию и поток работы. Кроме того, совместная работа с другими пользователями очень сложна, часто требуется несколько шагов, прежде чем другие смогут проверить вашу работу.
Именно здесь на помощь приходит Codux, который делает этот процесс более плавным и эффективным. Codux позволяет визуализировать изменения по мере их внесения, не переключаясь постоянно между несколькими инструментами. Более того, он предлагает визуальный пользовательский интерфейс, который упрощает создание приложений, позволяя создавать их всего парой щелчков мыши. Но, пожалуй, самое главное - он обеспечивает совместную работу в режиме реального времени, позволяя людям работать вместе без помех.
В заключение хочу еще раз отметить, что Codux не является заменой вашей IDE и других инструментов, которые вы используете. Рассматривайте Codux как еще один инструмент в вашем арсенале разработчика.