AI-система виртуальных AI-персонажей для VR/AR

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1 услугВсе 1566 услуг
AI-система виртуальных AI-персонажей для VR/AR
Сложная
~2-4 недели
Часто задаваемые вопросы
Направления AI-разработки
Этапы разработки AI-решения
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1218
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    853
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1047
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    561
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    825

AI-персонажи для VR/AR

Статичные NPC в VR/AR-приложениях — узкое место любого иммерсивного опыта. Пользователь нажимает триггер, персонаж произносит заготовленную фразу из 5 вариантов, диалог заканчивается. AI-персонажи ведут реальный разговор: понимают контекст сцены, помнят предыдущие взаимодействия, адаптируют поведение под пользователя, управляют анимациями в реальном времени.

Архитектура AI-персонажа

[STT] Голос пользователя → текст (Whisper)
         ↓
[Context Manager] История + состояние сцены + характер персонажа
         ↓
[LLM] GPT-4o / Claude 3.5 → текст ответа + action commands
         ↓
[TTS] ElevenLabs → аудиопоток
         ↓
[Animation Controller] Unity/Unreal → lip sync + жесты + эмоции
import asyncio
from openai import AsyncOpenAI
from dataclasses import dataclass, field
import json

@dataclass
class CharacterState:
    character_id: str
    name: str
    personality: str       # системный промпт с характером
    scene_context: dict    # текущее состояние сцены VR
    history: list = field(default_factory=list)
    emotional_state: str = "neutral"
    relationship_score: float = 0.5  # 0=враждебный, 1=дружелюбный

class VRCharacterEngine:
    ACTION_SCHEMA = {
        "type": "json_schema",
        "json_schema": {
            "name": "character_response",
            "schema": {
                "type": "object",
                "properties": {
                    "speech": {"type": "string"},
                    "emotion": {"type": "string",
                                "enum": ["neutral", "happy", "angry", "scared",
                                         "surprised", "sad", "suspicious"]},
                    "animation": {"type": "string",
                                  "enum": ["idle", "walk_towards", "walk_away",
                                           "point", "nod", "shake_head",
                                           "hand_gesture", "look_around"]},
                    "scene_action": {"type": "string",
                                     "description": "Действие в сцене: open_door, pick_up_item, etc."},
                    "relationship_delta": {"type": "number",
                                           "description": "Изменение relationship_score [-0.2, 0.2]"}
                },
                "required": ["speech", "emotion", "animation"]
            }
        }
    }

    def __init__(self):
        self.client = AsyncOpenAI()

    async def process_interaction(
        self,
        user_input: str,
        state: CharacterState
    ) -> dict:
        messages = [
            {"role": "system", "content": self._build_system_prompt(state)},
            *state.history[-10:],  # последние 5 обменов
            {"role": "user", "content": user_input}
        ]

        response = await self.client.chat.completions.create(
            model="gpt-4o-mini",  # mini достаточно, latency важнее
            messages=messages,
            response_format=self.ACTION_SCHEMA,
            max_tokens=300,
            temperature=0.7
        )

        action = json.loads(response.choices[0].message.content)

        # Обновляем состояние персонажа
        state.emotional_state = action["emotion"]
        state.relationship_score = max(0, min(1,
            state.relationship_score + action.get("relationship_delta", 0)
        ))
        state.history.append({"role": "user", "content": user_input})
        state.history.append({"role": "assistant", "content": action["speech"]})

        return action

Lip Sync и синхронизация анимаций

// Unity: синхронизация lip sync с аудиопотоком от ElevenLabs
using OVRLipSync;
using UnityEngine;

public class AICharacterAnimator : MonoBehaviour
{
    private OVRLipSyncContext lipSyncContext;
    private Animator animator;
    private AudioSource audioSource;

    public async void PlayCharacterResponse(string speechText, string emotion, string animation)
    {
        // 1. Запрашиваем аудио от TTS
        byte[] audioData = await TTSService.Synthesize(speechText, voiceId: "character_voice");

        // 2. Устанавливаем эмоцию через Blend Shapes
        SetEmotionBlendShape(emotion);

        // 3. Запускаем анимацию тела
        animator.SetTrigger(animation);

        // 4. Воспроизводим аудио с lip sync
        AudioClip clip = AudioService.BytesToClip(audioData);
        audioSource.clip = clip;
        audioSource.Play();

        // OVRLipSync автоматически синхронизирует губы с аудио
        lipSyncContext.ProcessAudioSamplesRaw(audioData, 0);
    }

    private void SetEmotionBlendShape(string emotion)
    {
        var face = GetComponent<SkinnedMeshRenderer>();
        // Сброс всех эмоций
        for (int i = 0; i < face.sharedMesh.blendShapeCount; i++)
            face.SetBlendShapeWeight(i, 0);

        // Установка нужной эмоции
        int shapeIndex = face.sharedMesh.GetBlendShapeIndex($"emotion_{emotion}");
        if (shapeIndex >= 0)
            face.SetBlendShapeWeight(shapeIndex, 100f);
    }
}

Latency: главная проблема VR-персонажей

В VR разрыв > 800 мс между фразой пользователя и ответом персонажа рушит иммерсию. Оптимизация pipeline:

Шаг Без оптимизации С оптимизацией
STT (Whisper large) 800–1200 мс 200–400 мс (Whisper medium + streaming)
LLM (GPT-4o) 1000–2000 мс 400–700 мс (GPT-4o-mini + short context)
TTS (ElevenLabs) 600–1000 мс 200–400 мс (streaming TTS)
Итого 2400–4200 мс 800–1500 мс

Решение: параллельный запуск TTS сразу после получения первых токенов от LLM (streaming), начало воспроизведения аудио до окончания синтеза всей фразы.

Кейс: VR-тренажёр для обучения продажам. 4 персонажа с разными характерами (агрессивный клиент, лояльный клиент, скептик, нейтральный). Средняя latency после оптимизации: 920 мс. Оценка реализма диалогов (опрос 50 пользователей): 4.1/5 vs 2.3/5 для скриптованных NPC.

Сроки: один AI-персонаж с базовыми анимациями: 3–5 недель; полный тренажёр с несколькими персонажами и аналитикой: 2–3 месяца.