Архив рубрики ~Лента новостей~

Усталость от Javascript: HTMX — это всё, что вам нужно для создания ChatGPT. Часть 1

Усталость от Javascript: HTMX — это всё, что вам нужно для создания ChatGPT. Часть 1

Создание чат-бота (почти) без Javascript, только с использованием Python и HTML.

Делиться

Винтажная информатика

Помню, было время, давным-давно, когда создавать сайты было легко. HTML и CSS. Казалось, всё просто. Сейчас фреймворки Javascript повсюду. Неустанные изменения, растущая сложность. Это явление называется «усталость от Javascript» и связано с тем, что разработчики измотаны погоней за новейшими фреймворками, инструментами разработки, библиотеками и попытками не отставать. С HTMX у разработчиков появился способ создавать увлекательные веб-приложения проще и без выгорания — и без всей этой возни с JavaScript.

Увлекательное веб-приложение, подобное ChatGPT, менее чем в 200 строках кода, на чистом Python и HTML. Например, вот это:

Краткое напоминание о том, как работал Интернет

Когда Тим Бернерс-Ли создал первую веб-страницу в 1990 году, разработанная им система была преимущественно системой «только для чтения», которая позволяла связывать страницы между собой гиперссылками, которые мы все знаем как анкорные теги в HTML. Таким образом, HTML 1.0 полагался на один-единственный тег и предлагал простую навигацию между страницами.

О нас

Якорный тег — это элемент управления гипермедиа, который выполняет следующий процесс:

  • показать пользователю, что это ссылка (кликабельная)
  • выполнить GET-запрос на URL-адрес гиперссылки

Когда сервер отвечает новой страницей, браузер заменит текущую страницу новой страницей (навигация)

Затем появился Web 2.0, который представил новый тег — тег формы. Этот тег позволял не только читать ресурсы через тег , но и обновлять их. Возможность обновления ресурсов означала, что мы действительно смогли начать создавать веб-приложения. Всё это с помощью всего двух элементов управления:

и .

Процесс отправки формы очень похож на отправку якорного тега, за исключением того, что мы можем:

  • выбрать, какой тип запроса мы хотим выполнить (GET или POST)
  • прикрепите информацию о пользователе, такую как адрес электронной почты, пароль и т. д., которая будет передана вместе с запросом

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

А потом появился Javascript.

Изначально JavaScript был создан для добавления простых функций взаимодействия на веб-страницы: проверки форм, получения данных и простой анимации. Но с появлением XMLHttpRequest (позже известного как AJAX) JavaScript превратился в нечто гораздо более мощное и сложное.

Благодаря Javascript разработчики теперь могут инициировать HTTP-запросы без этих двух тегов, используя технологию AJAX. AJAX позволяет извлекать данные с сервера, и хотя XHR может извлекать любые типы данных, включая необработанные HTML-фрагменты, текст или XML, JSON стал фактическим форматом обмена данными.

Это означает, что необходим дополнительный шаг преобразования JSON в HTML с помощью функции, которая визуализирует HTML из JSON. Как показано в примере ниже, мы действуем следующим образом:

  • извлечение данных JSON из конечных точек /api/users (часть response => response.json())
  • вставка этих данных в HTML-шаблоны (часть const html)
  • который затем будет добавлен в DOM (часть document.getElementById())

// Способ JavaScript: преобразование JSON → HTML fetch('/api/users') .then(response => response.json()) .then(users => { const html = users.map(user => `

${user.name}

` ).join(''); document.getElementById('users').innerHTML = html; });

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

По какой-то причине веб-разработчики начали повсеместно использовать JSON и управлять всем с помощью JSON. Это привело к появлению так называемых одностраничных приложений (SPA): в отличие от традиционного HTML 2.0, нам больше не нужно перемещаться между страницами. Весь контент остаётся на одной странице и обновляется с помощью JS и рендеринга пользовательского интерфейса. Именно так работают такие фреймворки, как React, Angular и Vue.js.

«Становящаяся нормой в веб-разработке — создание одностраничных приложений на React с серверным рендерингом. Два ключевых элемента этой архитектуры:
– Основной пользовательский интерфейс создается и обновляется на JavaScript с использованием React или чего-то подобного.
– Бэкэнд — это API, к которому приложение обращается с запросами.
Эта идея буквально захлестнула интернет. Она началась с нескольких крупных популярных сайтов и распространилась на другие сайты, например, на маркетинговые площадки и блоги.

(Том Макрайт, https://macwright.com/2020/05/10/spa-fatigue)

Большинство современных архитектур одностраничных приложений (SPA) представляют собой «клиентские» приложения, где большая часть работы выполняется на стороне клиента, а бэкенд представляет собой лишь API, возвращающий JSON. Такая структура известна своей быстрой и плавной работой, но действительно ли нам нужна такая сложность каждый раз?

«(…) есть также множество задач, для которых я не вижу конкретных преимуществ использования React. Это, например, блоги, сайты с корзинами покупок, сайты, в основном, с CRUD-запросами и формами».

Усталость от Javascript реальна

«Усталость от Javascript» становится всё громче. Она относится к основным недостаткам разработки SPA:

  • Растущая сложность : библиотеки и фреймворки становятся всё более громоздкими и сложными, требуя для управления ими больших команд. Некоторые узкоспециализированные фреймворки также подразумевают, что разработчикам JavaScript приходится специализироваться на одной технологии. Ни один разработчик Python не называл себя «разработчиком Tensorflow Python». Они просто разработчики Python, и переход с TF на Pytorch по-прежнему означает, что вы можете читать и использовать оба.
  • Тесная связь : взаимосвязь между API данных и пользовательским интерфейсом создаёт напряжение внутри команд. Критические изменения происходят каждый день, и решить эту проблему невозможно, пока команды используют JSON в качестве интерфейса обмена данными.
  • Распространение фреймворков : количество фреймворков продолжает расти, что приводит к реальному ощущению «усталости» среди разработчиков JS.
  • Избыточная инженерия : в 90% случаев вам не нужны фреймворки с большим объёмом JS. А в некоторых случаях (например, для приложений с большим объёмом контента) это даже плохая идея.

За исключением высокоинтерактивных/совместных пользовательских интерфейсов, простого HTML с многостраничными приложениями часто бывает достаточно.

Так что же такое HTMX?

HTMX — это очень лёгкая JS-библиотека (14 КБ), предлагающая HTML-ориентированный подход к созданию динамических веб-приложений. Она расширяет возможности HTML, позволяя любому элементу отправлять AJAX-запросы и обновлять любую часть DOM. В отличие от JS-фреймворков, которые выполняют всю рендеринг на стороне клиента, сервер выполняет основную работу, возвращая HTML-фрагменты для вставки в DOM. Это также означает, что если вы уже знакомы с шаблонизаторами и HTML, обучение будет гораздо проще по сравнению с изучением React или Angular.

Вместо отказа от гипермедиа в пользу JSON API, HTMX расширяет возможности HTML за счет следующих возможностей:

Фактически, вы можете написать свой собственный небольшой пользовательский интерфейс в стиле GPT с помощью HTMX и всего нескольких строк Python!

Реальная демонстрация: приложение ChatGPT с HTMX и FastAPI

В этой статье мы создадим небольшой чат, используя менее 100 строк кода Python и HTML. Мы начнём с очень простых демонстраций, чтобы показать, как работает HTMX, затем добавим простой интерфейс чата и возможность потоковой передачи. Чтобы сделать чат ещё привлекательнее, мы воспользуемся набором инструментов Google Agent Development Toolkit, чтобы использовать агентов в нашем чате!

Простые демонстрации HTMX

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

Традиционный способ JS:

Демо

Пользователи

И вот как это можно сделать с HTMX.

Сначала создайте свой бэкэнд:

из fastapi импорт FastAPI, запрос из fastapi.responses импорт HTMLResponse из fastapi.templating импорт Jinja2Templates импорт запросы app = FastAPI() templates = Jinja2Templates(directory=»templates») @app.get(«/», response_class=HTMLResponse) async def home(request: Request): return templates.TemplateResponse(«demo.html», {«request»: request}) @app.get(«/users») async def get_users(): r = requests.get(«https://dummyjson.com/users») data = r.json() html = «» for row in data['users']: html += f»

  • {row['firstName']} {row['lastName']}
  • n» return HTMLResponse(html)

    И затем HTML:

    Демо

    Пользователи

    И вы получаете точно такой же результат! Что только что произошло? Посмотрите на элемент

    • hx-get: Нажатие этой кнопки инициирует GET-запрос к конечной точке /users.
    • hx-target: сообщает браузеру о необходимости заменить содержимое элемента с идентификатором usersList на HTML-данные, полученные с сервера.
    • hx-swap: сообщает браузеру о необходимости вставить HTML-код внутрь целевого элемента.

    Итак, вы уже знаете, как использовать HTML. Преимущество этого способа в том, что если вы решите изменить HTML-код, это ничего не сломает на вашей странице.

    Конечно, у использования HTMX есть свои преимущества и недостатки. Но мне, как разработчику Python, очень приятно экспериментировать с бэкендом FastAPI, не особо беспокоясь о рендеринге HTML. Просто добавьте шаблоны Jinja, немного CSS Tailwind, и всё готово!

    Наш первый чат с HTMX и FastAPI

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

    • список сообщений
    • текстовая область для ввода данных пользователем

    И представьте себе, HTMX позаботится об отправке/получении сообщений! Вот как будет выглядеть результат:

    Обзор

    Поток следующий:

    1. Пользователь вводит запрос в текстовую область
    2. Эта текстовая область заключена в форму, которая отправит POST-запрос на сервер с параметром запроса.
    3. Бэкенд получает запрос и выполняет с ним какие-то действия (в реальной жизни мы можем использовать LLM для ответа на запрос). В нашем случае, для демонстрационных целей, мы просто ответим, возвращая запрос побуквенно.
    4. Бэкэнд оборачивает ответ в HTMLResponse (не JSON!)
    5. В нашей форме HTMX сообщает браузеру, куда вставить ответ, как показано в hx-target, и как поменять его местами с текущим DOM.

    Вот и всё. Итак, начнём!

    Бэкэнд

    Мы определим маршрут /send, который ожидает строку запроса от интерфейса, инвертирует ее и отправляет обратно в теге

  • .

    из fastapi импорт FastAPI, Запрос, Форма из fastapi.templating импорт Jinja2Templates из fastapi.responses импорт HTMLResponse импорт asyncio импорт время app = FastAPI() templates = Jinja2Templates(«templates») @app.get(«/») асинхронный def root(request: Request): return templates.TemplateResponse(request, «simple_chat_sync.html») @app.post(«/send») асинхронный def send_message(request: Request, query: str=Form(…)): message = «».join(list(query)[::-1]) html = f»

  • AI
    {message}
  • » return HTMLResponse(html)

    Внешний интерфейс

    На стороне frontend мы определяем простую HTML-страницу с использованием Tailwind CSS и HTMX:

    // ZeChat

    Давайте подробнее рассмотрим тег

    . У этого тега есть несколько атрибутов, поэтому давайте уделим им немного времени:
    • hx-post=»/send»: Он отправит запрос POST к конечной точке /send.
    • hx-trigger=»click from:#submitButton»: Это означает, что запрос будет запущен при нажатии на кнопку «submitButton».
    • hx-target=»#chat»: Это указывает браузеру, куда поместить HTML-ответ. В этом случае мы хотим, чтобы ответ был добавлен в список.
    • hx-swap=»beforeend»: hx-target указывает, куда поместить контент, hx-swap — КАК. В этом случае мы хотим, чтобы контент был добавлен перед концом (то есть после последнего дочернего элемента).

    Функция hx-on::before-request немного сложнее, но её легко объяснить. По сути, она происходит между щелчком мыши и моментом отправки запроса. Она добавляет введенные пользователем данные в конец списка и очищает их. Таким образом, мы получаем мгновенный пользовательский интерфейс!

    Лучший чат (трансляция + LLM)

    Мы создали очень простой, но функциональный чат. Однако, если мы захотим подключить LLM, могут возникнуть ситуации, когда ответ от сервера будет долго ждать. Наш текущий чат построен синхронно, то есть ничего не произойдёт, пока LLM не закончит писать. Не очень-то удобно для пользователя.

    Сейчас нам нужны потоковое вещание и настоящий магистр права, с которым можно поговорить. И это часть 2.

    Источник: towardsdatascience.com

    Оцените материал:

    Поделиться
    Понравилась статья? Расскажите другим
    ВКонтакте
    Читайте также
    Архив рубрики ~Коротко из Telegram~ Создаем собственную ИИ-модель с нуля и становимся вторым Сэмом Альтманом…. Архив рубрики ~Коротко из Telegram~ Kimi K3 научилась превращать сайты в 3D-фильмы — нейронка сделала… Архив рубрики ~Коротко из Telegram~ Запускаем мощную нейронку на стареньком MacBook Air. — нашли тулзу… Новости робототехники Один ролик вместо четырёх часов переобучения Чтобы научить робота новой… Архив рубрики ~Коротко из Telegram~ YouTube ужесточает контроль за «неаутентичным контентом» В этом видео детально… Новости робототехники Роботы начнут чинить спутники — SpaceX запустила на орбиту беспилотник… Новости робототехники Андроид T800 потерял голову в поединке на ринге. В Китае прошел турнир по боям между человекоподобными роботами Новости робототехники Соучредитель Uber привлек $1,7 млрд для нового робототехнического стартапа ATOMS Архив рубрики ~Обо всем~ Заметки из окопов: взгляд вычислительного биолога на цифровую революцию в разработке лекарств. Новости робототехники Holiday Robotics собирает 105 миллионов долларов для своего колесного гуманоида ПЯТНИЦА Новости робототехники [Перевод] В Корее произошла первая в мире забастовка против использования гуманоидных роботов на производстве Архив рубрики ~Обо всем~ Оксид никеля из руды ускорил восстановление железа водородом вдвое. Твердофазный катализ восстановил смесь оксидов в сплав за одну стадию Новости робототехники Украинские беспилотники доставляют роботов непосредственно в зону боевых действий по морю и воздуху. Новости робототехники AMD представила модуль Kria для управления в кратчайшие сроки и унифицированную память для роботов. Архив рубрики ~Коротко из Telegram~ Создаем собственную ИИ-модель с нуля и становимся вторым Сэмом Альтманом…. Архив рубрики ~Коротко из Telegram~ Kimi K3 научилась превращать сайты в 3D-фильмы — нейронка сделала… Архив рубрики ~Коротко из Telegram~ Запускаем мощную нейронку на стареньком MacBook Air. — нашли тулзу… Новости робототехники Один ролик вместо четырёх часов переобучения Чтобы научить робота новой… Архив рубрики ~Коротко из Telegram~ YouTube ужесточает контроль за «неаутентичным контентом» В этом видео детально… Новости робототехники Роботы начнут чинить спутники — SpaceX запустила на орбиту беспилотник… Новости робототехники Андроид T800 потерял голову в поединке на ринге. В Китае прошел турнир по боям между человекоподобными роботами Новости робототехники Соучредитель Uber привлек $1,7 млрд для нового робототехнического стартапа ATOMS Архив рубрики ~Обо всем~ Заметки из окопов: взгляд вычислительного биолога на цифровую революцию в разработке лекарств. Новости робототехники Holiday Robotics собирает 105 миллионов долларов для своего колесного гуманоида ПЯТНИЦА Новости робототехники [Перевод] В Корее произошла первая в мире забастовка против использования гуманоидных роботов на производстве Архив рубрики ~Обо всем~ Оксид никеля из руды ускорил восстановление железа водородом вдвое. Твердофазный катализ восстановил смесь оксидов в сплав за одну стадию Новости робототехники Украинские беспилотники доставляют роботов непосредственно в зону боевых действий по морю и воздуху. Новости робототехники AMD представила модуль Kria для управления в кратчайшие сроки и унифицированную память для роботов.