Как заставить ИИ на базе LLM писать полноценные приложения на HTML + CSS + JavaScript

a035a1f485ca633780b63d2e0631e0e9.jpg

Зачем вообще это делать?

Во первых это настоящий вызов современным LLM моделям и очень интересно как разные модели будут справляться с такой задачей.

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

Ну раз надо так надо, делаем)

Казалось бы что может быть проще? Берем любой чат с ИИ и говорим «напиши игру Змейка»? И нет сомнений что вы получите код страницы с рабочей версией игры.

6c8669eef3f57014b6c03387ddad6c2a.png

Но…, а если вам нужно изменить в предложенном ИИ коде что-то или добавить функционала? Если вы с такими вопросами продолжите диалог с ИИ то очень быстро увидите что он начинает путаться, переписывать уже работающие блоки кода или еще хуже — выдавать вам куски кода, который нужно заменить, а остальной код не трогать.

Как же сделать так чтобы ИИ можно сам менять часть уже написанного им кода таким образом чтобы не испортить уже работающие части, а так же дописывать новый функционал к странице?

А вот как!

Давайте любой код HTML разобьем на блоки/кирпичики/слоты и заставим ИИ писать код используя такие блоки, а самое главное потом заменять/удалять/добавлять такие блоки САМОСТОЯТЕЛЬНО.

Вот как будет выглядеть тогда пустая страница, разбитая на такие виртуальные блоки:


    
        My Page
        
        
    
    
        

Welcome

Main content here

Footer content

Главный фокус

И сразу разоблачение: мы НИКОГДА не будем показывать ИИ сам код HTML!

Мы подготовим словарь, содержащий блоки и показывать будем только его.

Вот код функции, которая создает словарь в Python по нашей структуре HTML документа:

import re

def html_to_dict(html):
    structure = {
        'html': {
            'head': {'blocks': []},
            'body': {'blocks': []}
        }
    }
    head_pattern = r'(.*?)'
    body_pattern = r'(.*?)'
    head_blocks = re.findall(head_pattern, html, re.DOTALL)
    body_blocks = re.findall(body_pattern, html, re.DOTALL)
    structure['html']['head']['blocks'] = head_blocks
    structure['html']['body']['blocks'] = body_blocks
    return structure

В результате наш код пустой странице после выполнения этого кода будет выглядеть так:

{
    "html": {
        "body": {
            "blocks": [
                "

Welcome

", "

Main content here

", "
Footer content
" ] }, "head": { "blocks": [ "My Page", "", "" ] } } }

И вот именно в этом виде ИИ будет работать с кодом.

Теперь немного промптинга, куда уж без него)

Роль для ИИ может выглядеть так:

Твоя задача - создавать и редактировать HTML/CSS/JavaScript код.
    
При этом код страницы соответствует такому шаблону:
```

    
        My Page
        
        
    
    
        

Welcome

Main content here

Footer content
``` Твой ответ должен быть всегда только в виде строк с описанием изменений: ``` head:::1:::@@@My Website@@@&&& head:::2:::@@@@@@&&& head:::3:::@@@@@@&&& head:::4:::@@@@@@&&& body:::1:::@@@

Welcome to our site

@@@&&& body:::2:::@@@@@@&&& body:::3:::@@@

Latest News

Content here

@@@&&& body:::4:::@@@@@@&&& body:::5:::@@@

© 2024 My Company

@@@&&& ``` Важно чтобы стили и скрипты были описаны внутри HTML, исключения могут быть только ссылки на библиотеки стилей (например bootstrap) или JavaScript (jquery) должны быть только в виде внешних ссылок. Если ты добавляешь код, которого еще не было, то добавляй его в новый номер блока. Если ты хочешь изменить код в блоке, который уже есть, то обязательно ответь полным кодом этого блока.

Это не идеальный, но уже вполне рабочий промпт, который слушается большинство LLM моделей.

Теперь посмотрим как выглядит запрос к ИИ:

# html_dict - словарь, полученный из HTML на предыдущем шаге
# task - Задача, например: "Создай игру Змейка"

api_key = 'sk-XXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
client = openai.OpenAI(api_key=api_key)
response = client.chat.completions.create(
    model="gpt-4o-mini", #"o1-mini",
    messages=[
        {
            "role": "user",
            "content": role # - это наш промпт, приведенный выше
        },
        {
            "role": "user",
            "content": f"Текущий код страницы: ```{html_dict}``` и вот новая задача: ```{task}```"
        }
    ]
)
ai_reply = response.choices[0].message.content

И вот какой ответ мы получим от ИИ при пустой странице и запросе «создай игру Змейка» (на модели gpt-4o-mini):

head:::1:::@@@Snake Game@@@&&&
head:::2:::@@@@@@&&&
head:::3:::@@@@@@&&&
body:::1:::@@@

Snake Game

@@@&&& body:::2:::@@@

Use arrow keys to move the snake and eat the food!

@@@&&& body:::3:::@@@

© 2024 Snake Game

@@@&&&

Назад в HTML!

Теперь наша задача из этой абракадабры обратно собрать HTML код)

Сначала напишем функцию, которая в нашем словаре внесет правки предлложенные ИИ:

import copy

def merge_changes(current_structure, changes):
    new_structure = {
        'html': {
            'head': {'blocks': copy.deepcopy(current_structure['html']['head']['blocks'])},
            'body': {'blocks': copy.deepcopy(current_structure['html']['body']['blocks'])}
        }
    }
    for change in changes:
        if change and ':::' in change:
            section, number, content = change.split(':::', 2)
            section = section.replace('\n', '').replace(' ', '')
            content = content.split('@@@')[1].replace('\n', '').replace('\r', '')
            block_index = int(number) - 1
            if section == 'head':
                while len(new_structure['html']['head']['blocks']) <= block_index:
                    new_structure['html']['head']['blocks'].append('')
                new_structure['html']['head']['blocks'][block_index] = content
            elif section == 'body':
                while len(new_structure['html']['body']['blocks']) <= block_index:
                    new_structure['html']['body']['blocks'].append('')
                new_structure['html']['body']['blocks'][block_index] = content
    return new_structure
  
  # changes - это ответ от ИИ с предложенным списком изменений
  new_structure = merge_changes(current_structure, changes.split('&&&\n'))

Итогом работы этой функции будет обновленный словарь вида:

{
    "html": {
        "body": {
            "blocks": [
                "

Snake Game

", "

Use arrow keys to move the snake and eat the food!

", "

\u00a9 2024 Snake Game

" ] }, "head": { "blocks": [ "Snake Game", "", "" ] } } }

Ну и наконец-то мы теперь можем собрать обратно HTML код вот такой функцией:

def dict_to_html(structure):
    html = ['', '']
    for i, block in enumerate(structure['html']['head']['blocks'], 1):
        if block:  # Проверяем, что блок не пустой
            html.append(f'    {block}')
    html.append('')
    html.append('')
    for i, block in enumerate(structure['html']['body']['blocks'], 1):
        if block:  # Проверяем, что блок не пустой
            html.append(f'    {block}')
    html.append('')
    html.append('')
    return '\n'.join(html)

На выходе получим HTML код работающей игры Змейка:



    Snake Game
    
    


    

Snake Game

Use arrow keys to move the snake and eat the food!

© 2024 Snake Game

Игра Змейка

Вот тут можете поиграть в начальную версию игру, описанную в статье: Змейка 1.0

А вот версия игры после нескольких последовательных запросов на улучшение кода: Змейка 3.0

Игра Змейка после тюнинга

Игра Змейка после тюнинга

Ну и как этим пользоваться если я не знаю HTML?

Очень хороший вопрос! Ответ — сделаем Телеграм бота, который может делать все что описано выше и может получать от вас инструкции голосом.

Бота соберем на одной из No-code платформ. В итоге вы получаем такого бота:

Реализация бота, который пишет веб приложения и интегрирован с GitHub

Реализация бота, который пишет веб приложения и интегрирован с GitHub

Возможности бота

  1. Создавать код HTML страниц с поддержкой скриптов

  2. Задачи можно ставить голосом

  3. Результат работы над страницей виден сразу

  4. Если возможность сохранять и загружать код в GitHub

  5. Можно взять код страницы по внешней ссылке и доработать его

Что еще можно создавать ботом?

  1. Любые калькуляторы цен на сайт

  2. Готовые игры для Телеграм MiniApp

  3. Одностраничный сайт

И многое другое…

А посмотреть можно?

Да, процесс работы с ботом показан на видео: Смотреть

Итоги

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

© Habrahabr.ru