Обзор изменений в WLJS Notebook
- суббота, 31 августа 2024 г. в 00:00:06
WLJS Notebook - это приложение, похожее на Jupyter и Mathematica. Пользовательский интерфейс сделан на Electron, а сервер работает на Wolfram Language. Т.е. это не очередная оболочка для Jupyter, а полностью самостоятельное приложение. Более подробно о проекте можно почитать в предыдущих статьях: Wolfram Language JavaScript Frontend и Open-source блокнот Wolfram Language или как воссоздать минимальное ядро Mathematica на Javascript. В этой статье я постараюсь рассказать о том, чего мы достигли за последнее время. Мы добавили новую функциональность, исправили множество ошибок оптимизировали взаимодействие с сервером и ускорили выполнение кода в интерфейсе. И конечно же внесли множество изменений в пользовательский интерфейс и улучшили графику. Обо всем этом подробнее под катом!
Мы постоянно работаем над стилистикой приложения и добавляем различные новые эффекты и здесь лучше один раз увидеть и сравнить со старой версией чем долго расписывать (все примеры будут для Windows 11):
Заголовок окна теперь активен. В нем расположены элементы управления слева направо:
Главное меню
Открыть папку
Скрыть/показать область навигации слева
Сохранить документ
Поделиться ссылкой
Меню команд
Оставить вычисления
Повторно подключить ядро
Изменены шрифты по умолчанию и масштаб элементов
Меню настроек теперь в левом нижнем углу. Раньше оно находилось в стандартном меню как для любого окна
Новые иконки для различных типов файлов
Активная область редактора теперь выделена рамкой
Изменился стиль выделения текущей ячейки - вместо пунктирной рамки теперь ячейка выделяется цветом
Всплывающие кнопки для управления ячейкой теперь расположены более компактно и не отбирают место в окне
Добавлены эффекты прозрачности
В ходе разработки мы столкнулись с одной неочевидной для нас проблемой. Мы используем самописный шаблонизатор, который в чем-то подобен JSX, но вместо JS использует WL - то есть мы называем его WLX. И при формировании страниц очень долгое время мы игнорировали правильное использование первой строки HTML-документов:
<!DOCTYPE html>
В итоге из-за того, что мы не использовали указание типа документа наше приложение считало, что нужно рендерить все страницы согласно спецификации HTML v1. Из-за чего мы долго не могли понять почему многие вещи при оформлении CSS-стилей не работали, например тени или разные типы заголовков в разметке Markdown. Но самая большая проблема лично для меня была в масштабе шрифтов. Ниже пример, где я сравнивал отображение одного и того же документа до включения DOCTYPE и после:
Как видно на скриншоте выше - межстрочные расстояния стали более удобными, увеличился стандартный масштаб, а заголовки 2-го уровня и далее стали правильно отображаться.
В Mathematica и Wolfram Language - все что видит пользователь является "выражением". А пользовательский интерфейс в зависимости от формы выражения может его отображать. Почти тоже самое что и HTML, только выражения в WL могут еще и вычисляться. Математика славится своим многообразием самых разных графиков. Мы не можем просто взять и отображать их в виде картинки, ведь наша главная цель - воспроизвести принципы работы Mathematica используя веб-стек, а значит за нашими графиками тоже должны прятаться выражения. Постепенно мы добавляем все больше и больше графики, которая уже существует в Mathematica. Например, в первых версиях пользователям были недоступны чарты, а 3D-графики были очень скудными. В текущей версии мы добавили много нового.
Как видно на примере выше - теперь появилось больше возможностей для стилизации 3D-графиков. А так же мы добавили сетку и подписи осей, о которых нас давно просили. Раньше всего этого не было. Кроме того теперь пользователям доступны чарты и большее количество примитивов, которые можно использовать в Graphics.
А так же теперь вы можете настроить освещение на графиках (без RTX):
И с трассировкой лучей конечно же:
Мы добавили несколько собственных функций, которые автоматически импортируются при старте приложения. Первая функция - это ManipulatePlot. Это чуть более простой вариант Manipulate + Plot из Mathmatica, который хорошо работает в WLJS и подходит для простых интерактивных графиков. Например как тут:
Еще одна подобная функция - это AnimatePlot, которая сразу создает "анимацию" без слайдеров и кнопок:
Вся динамика на фронтенде основана на обработке событий. Большинство функций для создания анимированных и динамических графиков представляют собой один из вариантов обработчика событий EventHandler. После выполнения функции на UI создается объект, который может генерировать некоторые события, например, по таймеру. Он отправляет их на сервер и сервер отвечает сообщениями, которые говорят клиенту что и где нужно изменить.
Но в этом обзоре я не буду очень подробно останавливаться конкретно на этом аспекте, так как он заслуживает отдельной большой статьи.
В заголовке окна приложения теперь есть отдельно поле ввода для заранее подготовленных команд. Принцип работы этого поля ввода следующий - пользователь выбирает мышкой или при помощи клавиатуры нужную команду, а приложение в текущее положение курсора вставляет специальный объект, который реализует то, что хочет пользователь. Затем "активировав" этот объект в ячейку с кодом вставляется выражение. Лучше всего это показать на каком-то конкретном примере. Например в списке команд есть захват изображения с камеры:
Еще один полезный пример - таблица опций функции. Нужно сначала написать функцию, затем выполнить команду "show option". Тогда в блоке под текущей ячейкой вставится таблица опций со значениями по умолчанию. Вы можете выбрать любые опции из таблицы:
После того как пользователь нажмет галочку в правом верхнем углу таблицы - все выбранные опции вставятся в аргументы функции:
Какие команды доступны в данный момент:
Создать/переименовать блокнот
Показать опции
Вставить в график "гизмо" для навигации
Форматировать текст/код
Вставить матрицу/файл с данными/изображение с камеры/спец-символ
Открыть терминал
Но если вдруг пользователь написал в поле ввода команд что-то такое, чего нет в подготовленном списке команд, то приложение создает чат с большой языковой моделью. По умолчанию это GPT текущей общедоступной версии, но всегда можно сконфигурировать любую другую модель, которая поддерживает OpenAI API. Да вам понадобится VPN, если для текущего IP нет доступа к openai.com и конечно же ключ. Сконфигурировать параметры запросов к языковой модели можно в меню настроек в секции AI Assistant:
Ну и вот как это выглядит в действии:
Теперь при оформлении ячеек формата .md в них можно использовать не только стандартный синтаксис, но и выражения языка Wolfram с использованием синтаксиса WLX. То есть если я создам вот такую ячейку:
.md
# Current date is <DateString></DateString>
То получу следующий результат:
Подробно о WLX можно почитать в документации, но если совсем коротко, то стандартный HTML превращается в разметку, а все теги с прописной буквы в выражения:
<div> // обычный HTML
<$MyVariable /> // Одиночнй тег превращается в вызов переменной
<MyFunction>arg1 arg2</MyFunction> // парный тег превращается в вызов функции
// MyFunction["arg1", "arg2"]
</div>
Теперь можно прямо на месте нарисовать какую-нибудь блок схему (кстати я сделал это для КДПВ). Для этого нужно в .md-ячейке ввести !![]
, выполнить ячейку и дальше можно рисовать в отдельном блоке Excalidraw:
После того как пользователь закончит процесс рисования, то можно снова поставить курсор в текстовую часть ячейки, нажать сочетание клавиш Shift+Enter и итоговая картинка вставить в выходную ячейку вот так:
Теперь у всех встроенных функций во всплывающей подсказке есть дополнительная кнопка в углу, которая открывает страницу документации к функции прямо с сайта Wolfram Research:
Теперь при помощи команд можно запустить отдельное окно терминала, которое позволит выполнять команды на основном ядре сервера. Так, например, можно получить прямой доступ к серверам, которые обрабатывают события:
Одним из узких мест во взаимодействии между клиентом и сервером является сериализация и маскирование данных при передаче выражений по протоколу WebSocket. Мы в том числе пытаемся уменьшить задержку ответа сервера и увеличить скорость передачи больших объемов данных. Нам удалось оптимизировать маскирование и размаскирование данных для WebSocket, о чем я писал в предыдущей своей статье. А так же сериализацию в JSON. Благодаря этим оптимизациям сервер может стримить данные с довольно высоким фреймрейтом. Например, ниже демонстрация вычислений в реальном времени:
Теперь для объектов TabView и Dataset есть специальные способы отображения на фронтенде:
На самом деле это далеко не все изменения, которые произошли с проектом WLJS Notebook. Их намного больше, но мы в этой статье постарались рассказать про самые заметные и полезные. Подробнее всегда можно почитать в списке релизов, документации, в блоге проекта, а так же в папке с примерами (на всех скриншотах она слева). Всем спасибо за внимание, увидимся в следующих статья!