search icon search icon ВЕРСИЯ ДЛЯ СЛАБОВИДЯЩИХ

Инженерный тур. 2 этап

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

Цели профиля:

  • Проведение экспериментов с различными типами дополненной реальности.
  • Исследование сфер применения технологии дополненной реальности.
  • Удержание фокуса образовательной программы на трех ключевых составляющих: творческой, технической и научной.
Развитие технологии с появлением искусственного интеллекта

С развитием искусственного интеллекта у технологии дополненной реальности появились новые направления для применения. В текущем сезоне задания Национальной технологической олимпиады сосредоточены на разработке виртуальных помощников — AR-интерфейсов, которые сочетают трехмерные виртуальные модели объектов с генеративным искусственным интеллектом. Примером таких решений являются цифровые аватары, которых можно рассматривать как коммуникативных агентов.

Необходимые компетенции

Для реализации коммуникационного агента в дополненной реальности требуются знания и навыки в следующих областях:

  • Трехмерное моделирование.
  • Frontend- и Backend-разработка.
  • Инструменты дополненной реальности (AR).
  • Работа с искусственным интеллектом.

Задания второго отборочного этапа направлены на проверку и развитие именно этих компетенций.

Индивидуальные задачи

Индивидуальные задачи второго этапа инженерного тура открыты для решения. Соревнование доступно на платформе Яндекс.Контест: https://contest.yandex.ru/contest/69905/enter/.

Задача 1.1.(2 балла)
Правильная последовательность
Темы: 3D-дизайнер, 3D-моделирование, Blender

Условие

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

Особенности создания процедурных текстур

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

Документация

Подробная информация о процедурных текстурах в Blender доступна по ссылке: https://docs.blender.org/manual/en/latest/render/shader_nodes/index.html.

Примечания

Для выполнения задания необходимо использовать Blender.

Рис. 1.1.

Рис. 1.2.

Рис. 1.3.

Рис. 1.4.

Рис. 1.5.

Рис. 1.6.

Формат ответа

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

Пример ответа: 123 2314 4213, где:

  • 123 — последовательность нодов для первой текстуры,
  • 2314 — для второй текстуры,
  • 4213 — для третьей текстуры.

Решение

Для решения задачи необходимо корректно настроить и соединить узлы материала в Blender. В качестве примера рассмотрим создание материала на плоскости (plane).

  1. Создание плоскости:

    • В рабочем файле Blender выберите Add (Добавить) в верхней панели инструментов или нажмите Shift + A, чтобы открыть меню добавления объектов.
    • В появившемся меню выберите MeshPlane, чтобы создать новую плоскость.
  2. Работа с материалами:

    • Перейдите в режим редактирования материалов, выбрав Material в нижней части окна 3D Viewport.
    • Нажмите кнопку Use Nodes (Использовать ноды), если она еще не активна.
    • По умолчанию в окне материала создаются два узла: Material Output и шейдер. Эти узлы не указаны в условии, но необходимы для вывода материала, поэтому их следует оставить.
  3. Добавление и настройка нодов:

    • Добавьте ноды, представленные в условии, через верхнюю панель инструментов или, нажав Shift + A и выбрав нужный узел:

      • Musgrave Texture Node (в новых версиях Blender заменен на Noise Texture).
      • Math Node: выберите операцию Abs (абсолютное значение), чтобы усилить контрастность текстуры.
      • Mix Color Node: этот нод смешивает два цвета, позволяя управлять соотношением элементов на текстуре.
      • Color Ramp Node: помогает точно настроить цветовые переходы и формы текстуры.
    • Настройте все ноды в соответствии с условиями задачи.
  4. Соединение узлов:

    • Соедините ноды в правильной последовательности. Обычно рекомендуется сначала подключить Musgrave Texture, а затем остальные ноды в следующем порядке: Math Node, Mix Color Node, Color Ramp Node. В некоторых случаях требуется другая последовательность.
    • После соединения узлов сравните результат с референсным изображением. Если результат отличается, измените последовательность подключения.

Пример решения

Для первой референсной текстуры ноды необходимо соединить в следующей последовательности:

  1. Musgrave Texture Node;
  2. Math Node;
  3. Color Ramp Node;
  4. Mix Color Node.

Таким образом, ответ для первой текстуры: 4132.

Итоговый ответ

Для получения референсных текстур ноды необходимо соединить в следующем порядке:

  • первая текстура: 4132;
  • вторая текстура: 24153;
  • третья текстура: 2341.
4132 24153 2341

Ответ

4132 24153 2341.

Задача 1.2.(8 баллов)
Облако точек
Темы: 3D-дизайнер, 3D-моделирование, Blender

Условие

Современные методы генерации трехмерных моделей позволяют создавать объекты по простому запросу. Однако у таких методов есть значительный недостаток: большинство из них способны генерировать только облако точек. Эти точки не соединены между собой и не отображают поверхность объекта.

Задача

По заданному списку координат необходимо воссоздать облако точек и преобразовать его в единый меш (сетку). Внутри меш должен быть полностью полым. Для достижения результата можно использовать различные инструменты, но количество вершин объекта должно оставаться близким к референсному значению: 166 вершин, не превышая 1000. Рекомендуется использовать инструмент MeshLab для генерации меша из облака точек.

Требования к результату

  • Рендеринг выполняется с мягким шейдингом.
  • Изображение результата необходимо прислать в отклик.
  • Для рендеринга используйте приложенный файл в формате .blend.
  • Не изменяйте настройки освещения, окружения и камеры.
  • Не изменяйте координаты объекта.
  • При экспорте из других программ в Blender убедитесь, что оси совпадают. При необходимости поверните объект на 90°.
  • Создайте рендер с заданными настройками в формате .png, используя материал объекта (в файле он назван «основной»).
  • Прикрепите результат на проверку.

Данные

Список координат: https://disk.yandex.ru/d/No65_PqqywOP6g/vertex_coordinates_1.py.

Пример координат:

[(-0.22782757878303528, 0.2848300337791443, 0.44945237040519714),
(-0.2572392225265503, 0.2931027114391327, -0.4023423194885254),
(-0.2167816013097763, -0.2583923935890198, 0.5664927363395691),
(-0.33079683780670166, -0.36342835426330566, -0.2099088430404663),
(1.5133447647094727, 0.16900011897087097, 0.791064441204071),
(1.6552481651306152, 0.18668070435523987, 0.5616824626922607),
(1.5163331031799316, -0.1422557830810547, 0.7901015877723694),
(1.5983494520187378, -0.1830269992351532, 0.543191134929657),
(0.6147313714027405, 0.40514254570007324, 0.7142897844314575)...]

Файл для рендера: https://disk.yandex.ru/d/No65_PqqywOP6g/render.blend.

Решение

Алгоритм эталонного решения:

  1. С помощью Python написать скрипт, который визуализирует точки в трехмерном пространстве.
    Python
    import bpy
    import bmesh
    
    def create_vertices(coords):
        mesh = bpy.data.meshes.new("NTO_Mesh")
        obj = bpy.data.objects.new("NTO_Object", mesh)
        bpy.context.collection.objects.link(obj)
        bm = bmesh.new()
        for coord in coords:
            bm.verts.new(coord)
        bm.to_mesh(mesh)
        bm.free()
    
    coordinates = [тут список координат]
    create_vertices(coordinates)
  2. После этого сохранить полученный результат в формате .ply.
  3. В программе MeshLab открыть данный файл, выбрать функцию FilterNormals, Curvatures and OrientationCompute normals for point set для создания ориентации вершин в пространстве. Это даст понять программе, где находится внутренняя, а где — внешняя часть создаваемого меша. Настройки можно оставить по умолчанию. После использования данной функции вершины с внешней стороны должны окраситься в более светлый оттенок, внутри — в более темный.
  4. Выбрать FilterRemeshing, Simplification and ReconstructionSurface Reconstruction: Screened Poisson. Настройки можно оставить по умолчанию. Получившийся меш сохранить как один из экспортируемых форматов, предпочтительно .fbx или .obj.
  5. Полученный результат импортировать в приложенный файл формата .blend, использовать модификатор decimate или иным способом уменьшить количество полигонов, наложить подготовленный материал «основной».
  6. Нажать RenderRender Image и полученное изображение отправить на проверку.

Ответ

см. рис. 1.7.

Рис. 1.7.

Задача 1.3.(2 балла)
Термины больших языковых моделей
Темы: искусственный интеллект, определения, обучение

Условие

Работа с большими языковыми моделями требует понимания ряда ключевых терминов, которые помогают настраивать модель для получения качественных и точных ответов. Знание этих терминов позволяет эффективнее использовать модель, настраивать ее поведение и решать возникающие проблемы, такие как излишне творческие ответы или неуместные ошибки.

В данной задаче необходимо соотнести каждое из определений с соответствующим термином.

  1. Минимальная единица текста, с которой работает языковая модель. Это может быть слово, часть слова или даже отдельный символ.
  2. Параметр модели, который контролирует степень случайности в ее ответах. При низком значении модель более предсказуема, при высоком — более креативна.
  3. Явление, при котором языковая модель генерирует некорректные или несуществующие данные, хотя они выглядят правдоподобно.
  4. Процесс обновления нейросети на новых данных для улучшения ее производительности или адаптации к новым задачам.
  5. Ограничение на количество токенов (слов, символов), которые модель может учитывать при генерации ответа. Если текст превышает этот предел, часть данных теряется.
  1. Галлюцинации.
  2. Токен.
  3. Размер контекста.
  4. Дообучение.
  5. Температура.

Ответ

1 — B; 2 — E; 3 — A, 4 — D, 5 — C.

Задача 1.4.(2 балла)
Botpress. Основы
Темы: искусственный интеллект, Botpress, обучение

Условие

Для решения командной задачи и построения системы, способной естественным языком общаться с конечным пользователем, предполагается использовать Botpress (https://botpress.com/), позволяющую создавать чат-ботов с применением технологий искусственного интеллекта для размещения на разных платформах.

Пройдите регистрацию, ознакомьтесь с документацией и выберите корректные утверждения про общие понятия построения бота на Botpress: https://botpress.com/docs/home.

  1. Специализировать формат общения с ботом можно, использовав специальные механизмы — Hooks. Но привязывают такой механизм только после получения сообщения.
  2. Основной Workflow бота начинается с блока Start и заканчивается End.
  3. Логика бота представлена в виде простой последовательности блоков, в каждом блоке предусмотрен исключительно один вход и один выход.
  4. Каждый блок представляет собой набор определенных карточек, каждая карточка может выполнять свою функцию. Например, указывать боту текст, который он будет выводить при обращению к блоку.
  5. В системе подразумевается, что можно создавать свою базу знаний (knowledge Base), но способом представления может быть только специальная таблица.
  6. В качестве ответа от бота можно получить не только текст, но, например, и изображение или геометку.
  7. Для того чтобы настроить взаимодействие бота с базой знаний, или, например, примерить на него какую-либо роль, необходимо определить соответствующего агента.

Ответ

2, 4, 6, 7.

Задача 1.5.(2 балла)
Botpress. База знаний
Темы: искусственный интеллект, Botpress, обучение

Условие

Для выполнения командной задачи будет необходимо создать базу знаний — место, откуда бот берет информацию для ответа.

Изучите документацию (https://botpress.com/docs/knowledge-base) и выберите корректные утверждения про работу с базой знаний Botpress.

  1. Полученный из базы знаний ответ хранится в переменной turn.Knowledge Agent.answer.
  2. В базу знаний можно добавлять только документы форматов doc, pdf и txt.
  3. Нельзя наложить ограничения по использованию баз знаний только на один узел, они применятся ко всем.
  4. При обращении к базе знаний можно указать дополнительные инструкции, например, про желаемому формату ответа.
  5. Для обращения к базе знаний используется карточка Prompt Knowledge Base.
  6. Чтобы передать заданный пользователем вопрос в базу знаний, может понадобиться переменная event.preview.

Ответ

1, 4, 6.

Задача 1.6.(2 балла)
Botpress. API
Темы: искусственный интеллект, Botpress, обучение

Условие

Общение с готовым ботом на веб-странице происходит по запросам к API. Для этого в проект установите интеграцию Chat (https://clck.ru/3Gnn5U). В документации по API (https://botpress.com/reference/introduction) описан алгоритм работы и все реализованные конструкции запросов.

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

JavaScript
const webhookUrl = 'webhook_url';
const id = 'conversation_id';
const key = 'user_key';

let url = `https://chat.botpress.cloud/${webhookUrl}/conversations/${id}/<?>`; // 1

const response = await <?>(url, { // 2
    method: '<?>', // 3
    headers: {
      'Content-Type': 'text/event-stream',
      '<?>': <?>; // 4, 5
    }
  })
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
while (true) {
  const {value, done} = await reader.read();
  if (done) break;
  console.log('Received', value);

Примечания

Для ответа используйте формат пункт.слово для пропусков и в качестве разделителя между пропусками используйте символ |. Без пробелов. Например: 1.if|2.elif|3.else.

Ответ

listen|fetch|GET|x-user-key|key.

Задача 1.7.(4 балла)
Botpress. Workflow
Темы: искусственный интеллект, Botpress, обучение

Условие

Основная логика работы бота происходит во flows, которые состоят из узлов (nodes), содержащих какие-либо функции карточки: https://botpress.com/docs/cards. Допустим, существует специальная база знаний, которая предоставляет информацию о внутренних органах человека, и вы хотите предоставить логику того, чтобы бот отвечал на вопросы, касающиеся только сердца. Составьте простой workflow для ответа бота на один запрос. Если пользователь говорит на отвлеченную тему, обозначить это и закончить разговор (назовем это альтернативной веткой).

Дан набор карточек. Требуется распределить их по узлам и расположить узлы в правильном порядке, присвоив номера. Если узел workflow содержит несколько карточек, объедините их одним числом. В карточках также присутствует один альтернативный узел, обозначьте его как n*, где n — номер узла основной последовательности, соответствующий альтернативному шагу.

Номер Карточки
а
б
в
г
д
е
ж

Примечания

Ответ дайте в следующем формате: n.буквы n*.буква n.буквы, где:

  • n — это номер узла;
  • буквы — это названия карточек, входящих в этот узел без пробелов между ними;
  • n* — обозначение номера альтернативной последовательности;
  • в качестве разделителя между номером узла и названиями карточек используйте точку без пробелов;
  • в качестве разделителя между номерами узлов используйте пробел;
  • в конце последовательности ничего не нужно ставить.

Например, рассмотрим рис. 1.8.

Рис. 1.8.

В стартовый узел входят карточки a и б, а также из него выходит ветвление, где один из следующих узлов — альтернативная последовательность с карточкой д, а основной узел содержит карточки в и г. Тогда ответом будет: 1.аб 2.вг 2*.д.

Решение

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

Описание логики алгоритма с указанием карточек:

  • После старта бота он может отправить сообщение с приветствием, поэтому карточка а будет первой.
  • После приветствия и вопроса бот ожидает ответа или вопроса от пользователя — это карточка б.
  • Для последующей работы с текстом сообщения необходимо записать его в переменную, что соответствует карточке в. Следует уточнить, что перед выполнением этой операции переменная должна быть определена в интерфейсе Botpress.
  • Следующим шагом определяется, содержит ли вопрос пользователя ключевые слова, необходимые для поиска в базе знаний бота (карточка г).
  • Если ключевые слова найдены, отправляется запрос в базу знаний, которую необходимо заранее создать и разметить заголовками в соответствующей части интерфейса инструмента. Для тестирования бота можно использовать данные из Википедии. За поиск в базе данных отвечает карточка е.
  • Если информация найдена, она выводится пользователю (карточка ж).
  • Существует альтернативный сценарий, при котором пользователь вводит некорректный вопрос. В этом случае бот отвечает, что не может об этом говорить (карточка д). Это происходит, если ключевые слова не были найдены в сообщении пользователя.

Разделение карточек по узлам может быть выполнено различными способами, например, на четыре основных этапа:

  1. Приветствие и ожидание ввода сообщения.
  2. Получение сообщения и поиск ключевых слов.
  3. Поиск информации в базе данных или ответ о том, что бот не может предоставить информацию.
  4. Ответ из базы знаний.

В этом случае схема в инструменте будет выглядеть как на рис. 1.9.

Рис. 1.9.

Ответ

1.аб 2.вг 3.д 3*.е 4.ж.

Задача 1.8.(18 баллов)
Инструменты дополненной реальности
Темы: дополненная реальность, WebAR, AR-инструменты

Следующие задания будут представлены в формате теста и предназначены для оценки знаний по нескольким инструментам дополненной реальности и веб-фреймворками для отображения AR в вебе.

  1. С какими 3D-фреймворками JavaScript интегрируется AR.js и mindAR.js?

    1. A-Frame;
    2. three.js;
    3. Zdog;
    4. Cesium;
    5. Blippar.js.

    Ответ

    A, B.

  2. Что такое A-Frame?

    1. Это библиотека для создания мобильных приложений.
    2. Это фреймворк для создания VR/AR-сцен с использованием HTML.
    3. Это инструмент для работы с 3D-графикой на Python.
    4. Это приложение для редактирования видео.

    Ответ

    B.

  3. Какие функции AR поддерживаются AR.js?

    1. Распознавание изображений.
    2. Отслеживание геопозиции.
    3. Распознавание лица.
    4. Отслеживание мира (World Tracking).
    5. Распознавание голоса.
    6. Сегментация неба.

    Ответ

    A, B.

  4. Какие функции AR поддерживаются MindAR.js?

    1. Распознавание изображений.
    2. Отслеживание геопозиции.
    3. Распознавание лица.
    4. Отслеживание мира (World Tracking).
    5. Распознавание голоса.
    6. Сегментация неба.

    Ответ

    A, C.

  5. Какой формат 3D-моделей предпочтителен (поддерживается по умолчанию) для WebAR?

    Ответ

    Один из следующих вариантов: GLB, glb, Glb, GLTF, glTF, gltf.

  6. Какие характеристики должны быть у маркера, чтобы обеспечить наивысшее качество отслеживания? Выберите все подходящие из списка.

    1. Много разнообразных деталей.
    2. Высокий контраст изображения.
    3. Повторяющиеся узоры.
    4. Избыточное пустое пространство.
    5. Разные цветовые схемы для набора маркеров, состоящего из одинаковых изображений (одного изображения).
    6. Изображения низкого разрешения.

    Ответ

    A, B.

  7. Как загрузить модель на сцену в A-Frame?

    1. <a-model src="url(path/to/model.gltf)"></a-model>
    2. <a-entity gltf-model="url(path/to/model.gltf)"></a-entity>
    3. <a-box gltf-model="url(path/to/model.gltf)"></a-box>
    4. <a-object model="url(path/to/model.gltf)"></a-object>

    Ответ

    B.

  8. Ниже представлен шаблон для создания и регистрации пользовательского A-Frame компонента, где аргументы это {string} name — название компонента и {Object} definition — объект конфигурации компонента, который содержит методы жизненного цикла.

    AFRAME.registerComponent(‘component-name’, {
        schema: {},
        init: function () {},
        update: function () {},
        tick: function () {},
        remove: function () {},
        pause: function () {},
        play: function () {}
        });

    Сопоставьте названия свойств конфигурации с их описанием.

    1. Schema.
    2. Init.
    3. Update.
    4. Tick.
    5. Remove.
    6. Pause.
    7. Play.
    1. Определяет и описывает свойство или свойства компонента.
    2. Вызывается один раз в начале жизненного цикла компонента. Обработчик часто используется для настройки начального состояния и переменных, привязки методов и присоединения слушателей событий.
    3. Вызывается всякий раз, когда изменяются свойства компонента, в том числе в начале жизненного цикла компонента. Этот обработчик часто использует this.data для изменения сущности. Также он имеет доступ к предыдущему состоянию данных компонента через свой первый аргумент.
    4. Вызывается на каждом такте или кадре цикла рендеринга сцены.
    5. Вызывается всякий раз, когда компонент отсоединяется (отключается) от a-entity. Обработчик часто используется для: удаления, отмены или очистки всех изменений компонента в сущности и для отключения всех слушателей событий.
    6. Вызывается, когда a-entity или a-scene останавливаются. Обработчик используется для удаления слушателей событий и исключения возможности динамического поведения.
    7. Вызывается, когда a-entity или a-scene возобновляются. Обработчик часто используется для добавления слушателей событий.

    Ответ

    1 — A, 2 — B, 3 — C, 4 — D, 5 — E, 6 — F, 7 — G.

  9. Какие три элемента обязательно требуются для создания базовой сцены в Three.js?

    1. Scene.
    2. Light.
    3. Camera.
    4. WebGLRenderer.
    5. Raycaster.
    6. Orbit Controller.

    Ответ

    A, C, D.

  10. С помощью какого метода можно загрузить 3D-модель в three.js?

    Ответ

    THREE.GLTFLoader, THREE.GLTFLoader(), GLTFLoader, GLTFLoader().

Командные задачи

Командные задачи второго этапа инженерного тура открыты для решения. Соревнование доступно на платформе Яндекс.Контест: https://contest.yandex.ru/contest/69927/enter/.

Для решения данных задач рекомендуем разделиться на следующие роли в команде:

  • 3D-дизайнер,
  • веб-разработчик,
  • AR-разработчик,
  • ИИ-разработчик.

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

Все задачи из командного блока будут оцениваться вручную командой разработчиков. Особенности критериев оценки написаны для каждой задачи отдельно. Каждая задача оценивается в 15 баллов. Итого за командную задачу можно набрать 60 баллов.

Для организации совместной работы в команде можно воспользоваться сервисом Glitch: https://glitch.com/.

Общая формулировка задачи

Создайте веб-проект в дополненной реальности с ассистентом для ответов на вопросы по работе органов человека.

В проекте должна отображаться 3D-модель человека в дополненной реальности, а на экране пользовательского устройства будет UI-элемент для ввода вопросов.

  • Модель человека может быть схематичной, но при этом должны быть отображены основные внутренние органы, такие как: легкие, сердце, мозг, печень, желудок, кишечник.
  • UI-элемент для ввода может быть представлен разными способами: раскрывающийся диалог по нажатию на кнопку или статичное окно ввода. В данный элемент пользователь может ввести вопрос о работе органов человека.

Для распознавания вопроса должен быть подключен искусственный интеллект с ограниченной базой знаний, который будет понимать:

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

Ответ пользователю может быть предоставлен в формате ответного сообщения или всплывающих 3D-заметок с текстом рядом с моделью. При этом, если речь идет о конкретном органе, то он должен быть подсвечен или другим способом визуально выделен на 3D-модели в дополненной реальности. Если вопрос не связан с конкретным органом, то пользователь видит все тело целиком.

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

Примерная структура файлов в архиве изображена на рис. 2.1.

Рис. 2.1.

Примечание

Можно объединить задания 3 и 4 при сдаче.

P. S. Внимание! Эта задача проверяется вручную. Баллы за нее будут выставлены после окончания отборочного этапа. Вердикт OK при отправке означает, что ваше решение было успешно отправлено на проверку.

Задача 2.1.(15 баллов)
Моделирование органов
Темы: 3D-дизайнер, 3D-моделирование

Условие

Создать 3D-модель аватара в соответствии с представленной концепцией.

Предусмотреть возможность просматривать органы аватара.

Создать модели органов: легкие, сердце, мозг, печень, желудок, кишечник.

Для всех моделей создать материалы / наложить текстуры.

Количество полигонов для каждой модели должно быть адаптировано под дополненную реальность.

Критерии оценивания

В качестве ответа на данное задание необходимо будет прислать:

  • скриншоты всех этапов работы на каждую 3D-модель, если их не будет, то баллы не засчитываются (блокинг, этап моделинга, финальный вариант);
  • исходные файлы каждой модели (файлы .blend, если вы работаете в Blender, .fbx или .obj иначе);
  • текстуры должны быть вшиты в файл или приложены к нему, если они в наличии.

Оценка модели также включает в себя сравнение схожести разработанной модели с анатомическими референсами.

Решение

В качестве решения для данной задачи подготовлен видеоразбор задачи: https://disk.yandex.ru/d/No65_PqqywOP6g/solution.mp4.

Вот краткий пошаговый план из видео выше для создания 3D-модели, которая будет оптимизирована под проект дополненной реальности:

  1. Создайте модель, используя предложенные примитивы.
  2. Измените модель в режиме редактирования в соответствии с анатомическим референсом.
  3. Создайте UV-развертку.
  4. Создайте копию модели и добавьте модификатор Multiresolution, увеличьте количество уровней подразделения.
  5. В режиме скульптинга добавьте детали. Примите модификатор.
  6. В настройках рендера смените движок на Cycles, во вкладке Bake выберите тип запекания Normal, включите чекбокс Selected to Active.
  7. Выделите высокодетализированную версию вместе с низкодетализированной, низкодетализированная модель должна быть активной.
  8. В режиме шейдинга низкодетализированной модели добавьте материал и текстуру. Выделите текстуру, но не соединяйте ее с нодом шейдера.
  9. Нажмите кнопку запекания. При необходимости откорректируйте параметр Max distance, если на изображении запечки есть артефакты.
  10. Сохраните текстуру и соедините текстуру через нод Normal Map с шейдером, цветовой профиль выставьте не цветовой.
  11. Добавьте текстуру Diffuse. Это может быть ручная текстура, текстура изображения или процедурная текстура. Допускается использование нейросетей.
  12. Проверьте настройки трансформации модели, по необходимости примите текущие как базовые.
  13. Выделите модель и экспортируйте ее в формате gltf, отметьте чекбокс Selected Only для исключения лишних объектов.
Задача 2.2.(15 баллов)
Чат-бот с базой знаний
Темы: ИИ-разработчик, чат-бот, база знаний

Условие

Реализовать разговорного бота, который способен вести диалог на строго обозначенную тему. То есть бот должен обладать подгружаемой базой знаний, на которой обучается. Заготовлены ветки диалога, в котором предлагается конечному пользователю поговорить про конкретный орган или составляющую часть. Важно, чтобы бот мог отвечать на запросы, написанные на естественном языке. Также бот должен сообщать остальным частям системы, про какую конкретную часть тела/детали ведется диалог.

Задачи, которые должен решать ИИ-разработчик:

  • построение Workflow графа бота;
  • настройка дополнительных агентов для возможности общаться с ботом не только текстом (при необходимости);
  • настройка базы знаний, для того чтобы искомый бот умел общаться на конкретную тему;
  • общее тестирование корректности ответов бота, ограничений бота.

При выполнении задания не допускается использование Autonomous Node, а также обращений ко внешним языковым моделям (например, ChatGPT) или поисковым системам внутри программы для получения информации. Таким образом, нельзя использовать карточки из разделов:

  • OpenAI;
  • Anthropic;
  • Groq;
  • Browser;
  • AI.

А также обращаться к LLM из кода программы внутри карточки Execute code.

Например:

Вход { question: "Что такое сердце? Расскажи про сердце?"}

Выход { message: "Сердце это самая выносливая мышца которая никогда не отдыхает и прокачивает 6 литров крови в минуту",
object: "heart" }

Критерии оценивания

В качестве ответа на данное задание следует прикрепить:

  • Концепт базы знаний в виде изображения. Пример концепта базы знаний на тему «собака» см. на рис. 2.2.
  • Скриншоты графового представления чат-бота (workflow).
  • Ссылка на доступ к настроенному чат-боту, в котором можно непосредственно задавать вопросы (в txt-файле).

Рис. 2.2. Пример концепта базы знаний

Чат-бот будет тестироваться на заготовленном банке вопросов и оцениваться по критериям на полноту ответа и его правильность.

Решение

Задачу можно разделить на две составляющие:

  1. база знаний,
  2. разработка чат-бота.

Для базы знаний можно использовать открытые источники, например, научные статьи в интернете, материалы из учебников и т. п. Кроме того, следует выделить ключевые вопросы, которые можно дополнительно обсуждать с ассистентом. Например, бот может рассказывать исключительно о работе органа или дополнительно рассказать о каждой его клетке/части, часто встречаемых заболеваниях данного органа и тому подобные аспекты. Для отображения разработанного концепта нужно составить изображение, содержащее краткие подписи (см. рис. 2.3). В дальнейшем эта информация собирается в базы данных.

Рис. 2.3. В качестве примера приведено решение команды «СбежавшиеИзРеальности»

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

Рис. 2.4. Пример текста Википедии

Для разработки бота первым этапом опишем сценарий его работы:

  1. Приветствие от бота при старте.
  2. Ожидание пользовательского ввода и обработка для поиска интента.
  3. Ответ от бота ограничивается базой знаний с помощью выделенного интента.
  4. Отдельный вывод, в случае если интент не был выделен.
  5. Наличие обратной дуги на обработку пользовательского ввода для обработки дальнейших вопросов.

Для реализации подобного сценария в задаче 1.7 индивидуального тура представлена примерная схема работы, ее следует доработать в нескольких аспектах: добавить интенты для разговоров по пяти органам, расширить базу знаний и зациклить его работу для бесконечного диалога с пользователем.

Архитектура бота в Botpress для данной задачи выглядит как на рис. 2.5.

Рис. 2.5. Архитектура бота

Задача 2.3.(15 баллов)
Интерфейс взаимодействия
Темы: веб-разработчик, интерфейсы

Условие

Задача веб-разработчика состоит в том, чтобы настроить правильный routing выходов бота и их интеграции на клиентскую сторону (настройка отображения и обеспечение корректного взаимодействия клиента и бота).

Для этого необходимо решить следующие задачи:

  • настройка передачи запроса боту;
  • написание логики клиента для отображения вывода бота (вывод ответа бота пользователю);
  • обработка возможных ошибок в выводе бота: объявление стандартизации того, как конкретно должен бот общаться с клиентом с точки зрения объектной модели.

Критерии оценивания

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

Решение

Для интеграции разработанного чат-бота в Botpress есть два варианта: API и web-chat. Так как в дальнейшем в задаче предусмотрена подсветка органов в зависимости от контекста общения с пользователем, то потребуется настройка API, а также данный метод более гибок для настройки UI интерфейса в дальнейшем.

Первым шагом необходимо правильно настроить web-hook. Для этого рекомендуем ознакомиться с официальной документацией, доступной по ссылке: https://botpress.com/docs/hooks. Botpress реализует web-hook для того, чтобы каким-либо образом преобразовать вывод от агента в разные моменты взаимодействия с ним. В данном случае необходим web-hook, который срабатывает в момент после того, как агент сформировал полный ответ. Он преобразовывает ответ, явно выделяя, какой именно орган определил агент из вопроса пользователя.

Для того чтобы начать работу с web-hook, необходимо перейти в соответствующий пункт в меню работы с агентом в интерфейсе и явно создать hook - before outgoing, как представлено на рис. 2.6.

Рис. 2.6.

После этого появится заготовка функции на языке JavaScript, аргументы которой понадобятся для реализации поведения. В данном случае ключевым аргументом является outgoingEvent — именно в этом аргументе хранится весь ответ от агента, который был сформирован до вызова функции.

JavaScript
async function hook(outgoingEvent: IO.OutgoingEvent, event: IO.IncomingEvent): Promise<void> {
  let full_answer = outgoingEvent['payload']['text']
  let organ_end = full_answer.indexOf('.')

  let organ_name = full_answer.slice(0, organ_end).toLowerCase()
  let answer = full_answer.slice(organ_end + 2)

  if (organ_end == -1) {
    organ_name = ''
    answer = full_answer
  }
  let new_text = { organ: organ_name, answer: answer }

  outgoingEvent['payload']['text'] = JSON.stringify(new_text)
  console.log(outgoingEvent['payload']['text'])
}

Выше представлен полный код, достаточный чтобы реализовать поставленную задачу.

Алгоритм работы функции следующий:

  1. Получаем весь ответ от пользователя из приходящего аргумента outgoingEvent.
  2. Разделяем весь ответ на две части: явно прописанный орган и соответствующая информация, которая отвечает на вопрос пользователя.
  3. В случае, если орган определить не удалось, ответ от агента не содержит информации о том, про какой орган идет речь, поэтому необходимо проверить поведение и задать переменную organ_name — явно пустой.
  4. Остается сформировать JSON стандарт в ответе, здесь явно необходимы organ_name и answer.
  5. Получившийся ответ необходимо поместить обратно в outgoingEvent.

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

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

Ниже представлен итоговый код для данной задачи.

JavaScript
async function changeText(text) {
    if (text) {
        const answerText = document.getElementById("answerText");
        answerText.setAttribute("value", text);
    }
}

function getQuestionInput() {
    const question = document.getElementById("promt");
    return question ? question.value : '';
}

function clearQuestionInput() {
    const question = document.getElementById("promt");
    if (question) question.value = '';
}

var start_dialog = false;

const URL = "https://chat.botpress.cloud/{Ваша ссылка на бота}";

// Функция для отправки POST-запросов
async function sendRequest(url_add, headers, body) {
    try {
        const options = Object.assign({}, headers, body);
        console.log("Отправка запроса с параметрами:", options);
        const response = await fetch(URL + url_add, options);
        const data = await response.json();

        if (response.status === 200) {
            return { success: true, data };
        } else {
            console.error("Ошибка:", response.status, data);
            return { success: false };
        }
    } catch (error) {
        console.error("Ошибка запроса:", error);
        return { success: false };
    }
}

// Функция для отправки GET-запросов
async function getRequest(url_add, headers) {
    try {
        const options = headers;
        const response = await fetch(URL + url_add, options);
        const data = await response.json();

        if (response.status === 200) {
            return { success: true, data };
        } else {
            console.error("Ошибка:", response.status, data);
            return { success: false };
        }
    } catch (error) {
        console.error("Ошибка запроса:", error);
        return { success: false };
    }
}

// Функция для отправки вопроса боту
async function submitQuestion(question, userid, conversationid) {
    if (!question) return;

    changeText("Подожди секундочку");

    let headers = {
        method: "POST",
        headers: {
            accept: "application/json",
            "x-user-key": userid,
            'Content-Type': 'application/json',
        }
    };
    let body = {
        body: JSON.stringify({payload: {type: 'text', text: question}, conversationId: conversationid})
    };

    const response = await sendRequest("/messages", headers, body);

    if (response.success) {
        console.log("Ответ бота:", response.data);
        return {status: true, ans: response.data};
    } else {
        changeText("Упс! Произошла ошибка");
        return {status: false, ans: response.data};
    }
}

// Функция для получения сообщений из чата
async function fetchMessages(conversationid, userid) {
    try {
        let headers = {
            method: 'GET', headers: {accept: 'application/json', 'x-user-key': userid}
        }
        const messagesResponse = await getRequest(`/conversations/${conversationid}/messages`, headers);
        if (!messagesResponse.success) throw new Error("Ошибка при получении сообщений");

        const messages = messagesResponse.data.messages;
        console.log("Полученные сообщения:", messages);
        if (messages.length > 0){
          let msg = JSON.parse(messages[0].payload.text);
          console.log("Ответ бота:", msg.answer);
          return {st: true, ms: msg};
        }
        return {st: false};
    } catch (error) {
        return {st: false};
    }
}

let userid = "ваш апи ключ";
let token = "идентификатор бота";
let we = "";
let conversationid = "";

// Функция инициализации пользователя и беседы
async function initialize() {
    try {
        let headers = {
            method: "POST",
            headers: {
                accept: "application/json",
                "x-user-key": userid,
                'Content-Type': 'application/json',
                'Access-Control-Request-Method': 'POST',
                'Origin': 'https://working-grey-protoceratops.glitch.me'
            }
        };
        let body = {
            body: JSON.stringify({name: "test"})
        };

        const userResponse = await sendRequest(`/users/`, headers, body);
        if (!userResponse.success) throw new Error("Ошибка при получении пользователя");

        we = userResponse.data.user.id;
        
        headers = {
            method: "POST",
            headers: {
                accept: "application/json",
                "x-user-key": userid,
                'Content-Type': 'application/json',
            }
        };
        body = {
            body: JSON.stringify({id: '111'})
        };

        const convoResponse = await sendRequest(`/conversations/get-or-create`, headers, body);
        if (!convoResponse.success) throw new Error("Ошибка при создании беседы");

        conversationid = convoResponse.data.conversation.id;
        
        return { userid, conversationid, we };
    } catch (error) {
        console.error("Ошибка инициализации:", error);
        return { success: false };
    }
}

// Функция для управления видимостью 3D моделей
function handleModelVisibility(answer) {
    const brainModel = document.getElementById("brain");
    const heartModel = document.getElementById("heart");

    if (answer.toLowerCase().includes("brain")) {
      brainModel.setAttribute("visible", "true");
      heartModel.setAttribute("visible", "false");
    } else if (answer.toLowerCase().includes("heart")) {
      heartModel.setAttribute("visible", "true");
      brainModel.setAttribute("visible", "false");
    } else {
      brainModel.setAttribute("visible", "false");
      heartModel.setAttribute("visible", "false");
    }
}

// Основная функция запуска
async function start() {
    var start_dialog = false;
    const { userid, conversationid, we } = await initialize();
    if (!userid || !conversationid) return;
    setInterval(() => {
      fetchMessages(conversationid, userid).then(d =>{
        if(d.st){
          handleModelVisibility(d.ms.organ);
          changeText(d.ms.answer);
        }
      });
    }, 5000);
}

document.addEventListener("DOMContentLoaded", (event) => {
  start();
});

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

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

  1. Пример обработки ошибок, которые могут возникать в процессе REST API-взаимодействия. Важным аспектом этого пункта является то, что после получения ответа необходимо обработать специальные коды возврата, которые явно сигнализируют о штатной работе.

    JavaScript
    // Функция для отправки POST-запросов
    async function sendRequest(url_add, headers, body) {
        try {
            const options = Object.assign({}, headers, body);
            console.log("Отправка запроса с параметрами:", options);
            const response = await fetch(URL + url_add, options);
            const data = await response.json();
    
            if (response.status === 200) {
                return { success: true, data };
            } else {
                console.error("Ошибка:", response.status, data);
                return { success: false };
            }
        } catch (error) {
            console.error("Ошибка запроса:", error);
            return { success: false };
        }
    }
  2. Реализация механики получения сообщений. Особенность взаимодействия заключается в том, что получать последние сообщения необходимо через запрос, который возвращает последние 20 сообщений. Следовательно, необходимо реализовать функцию, которая повторялась бы спустя какое-то время и отслеживала, получен ли новый ответ.

    JavaScript
    // Основная функция запуска
    async function start() {
        var start_dialog = false;
        const { userid, conversationid, we } = await initialize();
        if (!userid || !conversationid) return;
        setInterval(() => {
          fetchMessages(conversationid, userid).then(d =>{
            if(d.st){
              handleModelVisibility(d.ms.organ);
              changeText(d.ms.answer);
            }
          });
        }, 5000);
    }
  3. Реализация механики отправки сообщения. В данном случае этот запрос является классическим POST-запросом, в header которого необходимо передать набор токенов, которые необходимы для корректной регистрации сообщения.

    JavaScript
    async function submitQuestion(question, userid, conversationid) {
        if (!question) return;
    
        changeText("Подожди секундочку");
    
        let headers = {
            method: "POST",
            headers: {
                accept: "application/json",
                "x-user-key": userid,
                'Content-Type': 'application/json',
            }
        };
        let body = {
            body: JSON.stringify({payload: {type: 'text', text: question}, conversationId: conversationid})
        };
    
        const response = await sendRequest("/messages", headers, body);
    
        if (response.success) {
            console.log("Ответ бота:", response.data);
            return {status: true, ans: response.data};
        } else {
            changeText("Упс! Произошла ошибка");
            return {status: false, ans: response.data};
        }
    }
    
Задача 2.4.(15 баллов)
Дополненная реальность
Темы: AR-разработчик, интерфейсы

Условие

Реализовать клиента, который позволяет коммуницировать с ИИ и отображать результаты ответов при наведении на маркер в дополненной реальности. В задачи AR-разработчика входит не только наложение оверлея на маркер, но и создание AR-интерфейса, который соединит все части работы.

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

Формат входных данных

  • UI-элементы на экране, которые видно даже без наведения на маркер. UI может быть представлен в формате диалога или поисковой строки: одно поле ввода с кнопкой.
  • При наведении на маркер отображается модель человека.

Формат выходных данных

  • Текстовый ответ, который содержит информацию о выбранном органе. Ответ может быть представлен в формате ответного UI-сообщения или в формате 3D-текста на панели рядом с 3D-моделью органа.
  • Визуальное выделение выбранного органа. Оно может быть выполнено произвольно, главное, чтобы было понятно, о каком органе идет речь. Например, одним из возможных вариантов может быть следующий:

    • в режиме ввода или при неизвестной информации отображается тело человека с прозрачностью 100%;
    • в режиме вывода при «подсветке», например, сердца, основное тело становится полупрозрачным, и в нем ясно становится видно только сердце.

Критерии оценивания

В качестве отклика прикрепите проект и изображение маркера, на который все выводится.

Для данной задачи будет оцениваться:

  • качество маркера и его стилизация под команду;
  • UI сайта;
  • корректность вывода ответов и выделения органов в соответствии с ответом от бота;
  • единый стиль интерфейса.

Решение

Первым этапом опишем сценарий взаимодействия с приложением, с точки зрения пользователя и дополненной реальности.

Алгоритм работы AR-бота:

  1. При наведении на QR-код или поверхность, на экране устройства отображается 3D-модель тела человека, с которым общается пользователь, приветствие и описание возможностей чат-бота. На начальном этапе можно дополнительно отображать не модель, а 3D-аватар человека.
  2. Пользователь вводит вопрос в отображаемый интерфейс, например, «Что такое сердце?» и нажимает кнопку для отправки вопроса.
  3. Бот делает запрос в базу знаний и, при нахождении ответа, отображает информацию пользователю на экране устройства. А также подсвечивает орган, о котором идет речь, на 3D-модели. Дополнительно можно реализовать анимацию органа или его детализацию.
  4. Если информация не найдена в базе знаний, то пользователю выводится информация об этом. Дополнительная реализация: можно предложить пользователю несколько вопросов на выбор, ответ на которые знает бот.

Для его реализации разделим работу на несколько составляющих:

  • создание маркера с собственной стилизацией;
  • инициализация сцены дополненной реальности;
  • отображение интерфейса, необходимого для ввода вопроса пользователем;
  • написание алгоритма отображения человека или органа в зависимости от контекста диалога;
  • отображение текста для пользователя: приветствие, статус обработки запроса, ответ от чат-бота.

Примечания

В качестве библиотек для реализации задачи были выбраны AR.js и aframe, поэтому в дальнейшем решение будет описываться именно для них.

Создание маркера

  1. Выбор изображения для маркера.

    Примечание: рекомендуется выбирать контрастные изображения с четкими границами, чтобы AR.js мог легко их распознать.

    Советы по выбору маркера:

    • используйте изображения с четкими деталями, избегайте размытия.
    • предпочитайте черно-белую палитру или минимализм.
    • избегайте слишком сложных узоров, которые могут путать алгоритм распознавания.
  2. Создание маркера через AR.js Studio.

    Используйте AR.js Studio Marker Generator+: https://jeromeetienne.github.io/AR.js/three.js/examples/marker-training/examples/generator.html

    • загрузите изображение (формат: png или jpeg);
    • настройте параметры генерации, такие как размер маркера;
    • скачайте сгенерированные файлы: .patt (шаблон маркера) и изображение маркера для печати.

    Рис. 2.7.

  3. Подключение маркера к сцене.

    Для работы с разработанным маркером поместите .patt файл в папку проекта и используйте компонент <a-marker> для добавления маркера.

    Для того чтобы проверить готовый маркер, воспользуемся следующим кодом:

    HTML
    
    <!DOCTYPE html>
    <html>
      <head>
        <script src="https://aframe.io/releases/1.6.0/aframe.min.js"></script>
        <script src="https://raw.githack.com/AR-js-org/AR.js/master/aframe/build/aframe-ar.js"></script>
      </head>
      <body style="margin: 0; overflow: hidden;">
        <a-scene embedded arjs>
          <!-- Маркер с кастомным шаблоном -->
          <a-marker type="pattern" url="path/to/your-marker.patt">
            <!-- 3D-объект, привязанный к маркеру -->
            <a-box position="0 0.5 0" material="color: red;"></a-box>
          </a-marker>
    
          <!-- Камера для AR -->
          <a-entity camera></a-entity>
        </a-scene>
      </body>
    </html>

Инициализация сцены дополненной реальности

Для дальнейшего отображения всех 3D-моделей необходимо заранее их подгрузить в сцену, присваивая им соответствующие id.

Пример кода с подгрузкой 3D-модели:

HTML
<a-assets>
    <a-asset-item id="model" src="https://cdn.glitch.global/77779c2d-e490-401b-a8d0-8dc0346ee3dd/scene.gltf?v=1737434668578">
    </a-asset-item>
</a-assets>

После загрузки модели необходимо настроить ее размер и местоположение на сцене относительно маркера:

HTML
<a-entity id='model' scale="0.25 0.25 0.25" gltf-model="#model" color="red" position="0 2 0" shadow></a-entity>

Отображение интерфейса, необходимого для ввода вопроса пользователем

Для реализации данного пункта необходимо расположить на экране пользователя поле для ввода текста и кнопку отправки вопроса.

HTML
<div
      style="
        position: fixed;
        top: 10px;
        width: 100%;
        text-align: center;
        z-index: 10;"
    >
      <input
        type="text"
        id="promt"
        placeholder="Ask a question"
        style="width: 70%; padding: 10px"
      />
      <button id="submit-button" style="padding: 10px 20px">
        Отправить
      </button>
    </div>

Написание алгоритма отображения человека или органа в зависимости от контекста диалога

В задание веб-разработчика входила правильная настройка вывода органа в ответе от чат-бота, теперь необходимо настроить отображение 3D-модели в зависимости от параметра organ.

JavaScript
//Пример функции для управления видимостью 3D моделей для двух органов
function handleModelVisibility(answer) {
    const brainModel = document.getElementById("brain");
    const heartModel = document.getElementById("heart");

    if (answer.toLowerCase().includes("brain")) {
      brainModel.setAttribute("visible", "true");
      heartModel.setAttribute("visible", "false");
    } else if (answer.toLowerCase().includes("heart")) {
      heartModel.setAttribute("visible", "true");
      brainModel.setAttribute("visible", "false");
    } else {
      brainModel.setAttribute("visible", "false");
      heartModel.setAttribute("visible", "false");
    }
  }

Отображение текста для пользователя: приветствие, статус обработки запроса, ответ от чат-бота

Для вывода текста на экран пользователя можно воспользоваться следующим шаблоном кода:

HTML
<a-entity text="font: name_font; value: HELLO"></a-entity>

Для отображения русского шрифта необходимо создать его с помощью дополнительного инструмента (https://msdf-bmfont.donmccurdy.com/), представленного в документации aframe (https://aframe.io/docs/1.6.0/components/text.html), загрузить в виде картинки и json-файла в папку проекта и указать его название в коде выше.

Пример шрифта Roboto представлен на рис. 2.8.

Рис. 2.8.

Ссылка на получившийся json-файл с шрифтом: https://disk.yandex.ru/d/No65_PqqywOP6g/Roboto-Medium-msdf.json

Для изменения текста на экране пользователя воспользуемся следующим js-кодом:

JavaScript
// Напишем функцию для последующей замены текста
async function changeText(text) {
    if (text) {
        const answerText = document.getElementById("answerText");
        answerText.setAttribute("value", text);
    }
}
...
// Фрагмент кода для изменения текста на экране пользователя
changeText("Идет запрос в базу, подождите секундочку...");
text slider background image text slider background image
text slider background image text slider background image text slider background image text slider background image