
Детективная игра-допрос с голосовым управлением. Mistral Large 3 + Voxtral STT + ElevenLabs TTS. Создано для Mistral Worldwide Hackathon 2026.

Голосовая детективная игра-допрос. Вы — детектив. Мистраль — подозреваемый, который врёт. Ваша задача — поймать его на лжи с помощью одних только вопросов.
Каждое дело генерируется процедурно — уникальное преступление «белых воротничков», подозреваемый, алиби и одна скрытая ложь. Роль подозреваемого исполняет Mistral Large, которому предоставлена полная предыстория и инструкция защищать её под давлением. Ни одно дело не повторяется.
Создано для Mistral Worldwide Hackathon 2026 (онлайн-трек).
"Mistral умеет рассуждать. Я заставил его врать. Ваша задача — поймать его."
ИИ проинструктирован никогда не признаваться, даже при максимальном стрессе. Вы выигрываете, сделав конкретное, точное обвинение — а не заставив подозреваемого сломаться.
npm install
cp .env.example .env # Заполните свои ключи API
npm run dev # http://localhost:3000
MISTRAL_API_KEY= # Обязательно — генерация дел, допрос, оценка, STT
ELEVENLABS_API_KEY= # Обязательно — TTS для голоса подозреваемого
ELEVENLABS_VOICE_ID= # Опционально — конкретный ID голоса ElevenLabs
NEXT_PUBLIC_SUPABASE_URL= # Обязательно — URL проекта Supabase
NEXT_PUBLIC_SUPABASE_ANON_KEY= # Обязательно — анонимный ключ Supabase (защищено RLS)
SUPABASE_SERVICE_ROLE_KEY= # Опционально — точка входа для экспорта админа
EXPORT_SECRET= # Опционально — аутентификация экспорта админа
Ключи API также можно настроить на странице Настройки во время выполнения — приложение поставляется без ключей, игроки используют свои.
npm run dev # Сервер разработки
npm run build # Сборка для продакшена
npm run start # Продакшен-сервер
npm run lint # ESLint
Также доступен режим безлимитного таймера — на сложном/экспертном уровне подозреваемый вызовет адвоката после 4 последовательных обменов с высоким стрессом.
Улики открываются при порогах стресса, распределённых от 1 до 9, с ограничениями:
Кнопка «Обвинить» разблокируется только после сбора всех необходимых улик.
score = timeScore x difficultyMultiplier x efficiencyBonus x hintPenalty x accusationPenalty
timeScore = 1000 x sqrt(max(0, 1 - elapsed / (parTime x 2)))
multiplier = easy 1.0x, medium 1.5x, hard 2.0x, expert 2.5x
efficiencyBonus = 1.0-1.5x (меньше вопросов, чем норма = бонус)
hintPenalty = 0.85^hintsUsed
accusePenalty = max(0, 1 - wrongAccusations x 0.1)
Очки вычисляются на стороне сервера из замороженной статистики в момент победы — значения клиента игнорируются.
app/
├── page.tsx # Экран заголовка
├── cases/ # Выбор дела — локации + сложность
├── game/
│ ├── page.tsx # Главный оркестратор игры
│ ├── hooks/ # useVoiceRecorder, useTTS, useGameTimer, useSfx, useSettings
│ ├── components/ # Dock, TopBar, CaseFile, SuspectZone, BriefingScreen, dialogs
│ ├── win/ # Экран победы + InitialsEntry
│ └── lose/ # Экран поражения
├── leaderboard/ # Топ-20, анимация нового рекорда
├── settings/ # Настройка ключей API, экспорт, предпочтения
├── help/ # Как играть, подсчёт очков, об игре
├── about/ # Информация о создателе
└── api/
├── generate-case/ # GET — генерация дела Mistral
├── interrogate/ # POST — вопрос игрока → ответ подозреваемого
├── accuse/ # POST — оценка обвинения (отдельный судья)
├── evaluate/ # POST — анализ победы/поражения
├── hint/ # POST — завуалированные подсказки по триггерам стресса
├── tts/ # POST — ElevenLabs TTS
├── transcribe/ # POST — Voxtral STT
├── leaderboard/ # GET/POST — таблица лидеров Supabase
├── patterns/ # GET/POST — межсессионные паттерны обучения
└── export/ # GET — административный экспорт JSONL
src/lib/
├── mistral/ # Mistral-клиент, допрос, оценка, генерация дел, эмбеддинги
├── game-session.ts # Серверное хранилище сессий, токены победы, экспорт
├── game-state.ts # Определения типов
├── scoring.ts # Расчёт очков + рейтинг детектива
├── sanitize.ts # Валидация ввода, обнаружение инъекций
├── db.ts # Клиент Supabase
└── rate-limit.ts # Ограничение запросов по IP
Игра запускает состязательный ИИ против ввода игрока — безопасность является ключевой функцией, а не дополнением.
Санация ввода: 30+ регулярных выражений для паттернов инъекций, нормализация Unicode (NFKD), удаление нулевой ширины символов, обнаружение base64-полезной нагрузки, блокировка бессвязного/неанглийского текста.
Сканирование вывода: Ответы ИИ проверяются на секреты дела с нечетким сопоставлением (порог 40%, фильтрация стоп-слов). Утечки заменяются уклончивым ответом.
Изоляция судьи: Оценка обвинения использует отдельный вызов Mistral с выделенным системным промптом, рандомизированными граничными токенами, удалёнными маркерами инъекций. Вызовы судьи никогда не используют ключи API, предоставленные игроком.
Контроль стресса: Серверное монотонное ограничение — стресс только растёт, максимум +1 за ход. Пороги улик контролируются сервером. ИИ не может резко повысить или понизить стресс для прохождения игровых ворот.
Токены победы: 128-битные случайные, сравнение с защитой от временных атак, одноразовые, TTL 30 минут. Очки рассчитываются из серверного снимка статистики — значения, сообщённые клиентом, игнорируются.
Безопасность сессий: 192-битные случайные ID, мьютекс-блокировки, TTL 1 час, максимум 5000 сессий с вытеснением LRU. Режим таймера фиксируется при создании.
Валидация TTS: Требуется активная сессия. Текст должен совпадать с последним сообщением ассистента. Предотвращает злоупотребление бесплатным прокси TTS.
Защита от отравления RAG: Межсессионные изученные тактики фильтруются через обнаружение инъекций и санацию перед включением в промпт.
Завершённые игры сохраняются в Supabase для анализа и улучшения модели:
GET /api/export?limit=100&offset=0&outcome=win&difficulty=hard с заголовком Authorization: Bearer <EXPORT_SECRET>EXPORT_SECRET=xxx npx tsx scripts/export-data.ts --output=data/export.jsonlЭстетика нуар-детектива. Тёмный, минималистичный, типографический. JetBrains Mono. Фоны и портреты подозреваемых в стиле пиксель-арт. Никаких облачков чата — диалог отображается как стилизованный текст в сцене.
Создайте таблицу leaderboard:
CREATE TABLE leaderboard (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
player_name text NOT NULL,
case_number text,
case_setting text,
suspect_name text,
time_remaining int,
stress_level int,
clues_found int,
hints_used int,
accusations_used int,
detective_rating text,
score int NOT NULL,
created_at timestamptz DEFAULT now()
);
ALTER TABLE leaderboard ENABLE ROW LEVEL SECURITY;
CREATE POLICY "Public read" ON leaderboard FOR SELECT USING (true);
CREATE POLICY "Public insert" ON leaderboard FOR INSERT WITH CHECK (true);
Опциональная таблица game_exports для тренировочных данных:
CREATE TABLE game_exports (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
session_id text UNIQUE NOT NULL,
case_data jsonb NOT NULL,
conversation jsonb NOT NULL,
outcome text NOT NULL,
difficulty text NOT NULL,
setting text,
stats jsonb NOT NULL,
accusation_text text,
accusation_correct boolean,
created_at timestamptz DEFAULT now()
);
ALTER TABLE game_exports ENABLE ROW LEVEL SECURITY;
CREATE POLICY "anon_insert" ON game_exports FOR INSERT TO anon WITH CHECK (true);
CREATE POLICY "no_public_read" ON game_exports FOR SELECT TO anon USING (false);
Опциональная таблица interrogation_patterns для межсессионного обучения:
CREATE TABLE interrogation_patterns (
id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
session_id text UNIQUE NOT NULL,
setting text,
difficulty text NOT NULL,
outcome text NOT NULL,
questions jsonb,
effective_questions jsonb,
max_stress int,
clues_found int,
time_elapsed int,
embedding vector(1024),
created_at timestamptz DEFAULT now()
);
ALTER TABLE interrogation_patterns ENABLE ROW LEVEL SECURITY;
CREATE POLICY "anon_insert" ON interrogation_patterns FOR INSERT TO anon WITH CHECK (true);
CREATE POLICY "anon_read" ON interrogation_patterns FOR SELECT TO anon USING (true);
Mistral Worldwide Hackathon 2026 — Онлайн-трек, категория «Anything Goes».
Критерии оценки: Креативность/уникальность (наиболее важно), потенциал в будущем, техническая реализация, качество презентации.
Специальные призы: Best Mistral Vibe (AirPods), Best Voice AI (подписка ElevenLabs на 6 месяцев).
Спонсоры: Mistral, ElevenLabs, NVIDIA, AWS, Hugging Face, Jump Trading, Weights & Biases, Giant, Raise, Tilde Research, White Circle.
Большинство хакатонных AI-проектов — это ассистенты или чат-боты. Этот переворачивает сценарий — ИИ не помогает вам, а врёт вам. Игрок действует против модели, а не сотрудничает с ней. Это создаёт принципиально иное взаимодействие: вы ищете несоответствия, оказываете давление и считываете поведенческие сигналы, а не просите помощи.
Игра также генерирует тренировочные данные. Каждая завершённая сессия — заданные вопросы, прогрессия стресса, какие тактики сработали, какие нет — экспортируется в формате JSONL. Это создаёт петлю обратной связи: играйте в игру, экспортируйте данные, донастраивайте модель, делайте её сложнее для разоблачения.
Джейсон Пойндекстер — одиночная заявка, онлайн-трек из Барселоны.
| Уровень | Улики | Таймер | Поведение подозреваемого |
|---|
| Лёгкий | 2 | 5 мин | Очевидная ложь, нервничает |
| Средний | 3 | 7 мин | Ложь можно поймать, спокоен |
| Сложный | 4 | 9 мин | Тонкая ложь, умело уклоняется |
| Эксперт | 5 | 10 мин | Глубоко скрытая ложь, манипулирует |