
Я створив нішевий AI-англійський розмовний застосунок Mesugaki AI English на Kotonia з підміркуванням персонажа як коду та вводу аудіо Gemini для корекції вимови. «Mesugaki» (メスガキ) — це персоно-цундера стилю нахабна дитина, популярна в японському субкультурному середовищі — уявіть персонажа, який постійно висміює вас, але водночас підтримує. На перший погляд це виглядає як одноразовий жарт, але під капотом — двошарова конструкція: персону дотримує код + аудіо-вхід Gemini для фактичної корекції вимови. Цей пост описує відповідні рішення дизайну та зручні та недоліки, з точки зору самостійного розробника.
Чому Sarcastic AI English Tutor?
Стратегія насамперед. Ринок AI-чатів — це сутичка між Anthropic, OpenAI та Google за мультитемпова моделі загального призначення — сольному розробнику не перемогти напряму. Але занурювальні досвіди, що поєднують конкретну персону, голос та рольову динаміку мають низьку пріоритетність у великій лабораторії R&D (внутрішнє узгодження — справжній кошмар). Саме це пропонує Kotonia в цілому.
Три причини, чому я обрав саме цю персону для вивчення англійської:
– Нуль конкуренції в пошуку. Немає SaaS, що бореться за «mesugaki English conversation». Нішевий попит реальний (doujin audio, VTuber-культура), і володіння вузькою нішою реально.
– Пам’ятність = можливість поширення. «Застосунок, де знущається AI над вашою англійською» поширюється у соцмережах у 100× більше, ніж «AI English conversation app». Різниця, яку великі гравці копіювати не можуть.
– Тотожна основа продукту. Я використав рушій голосового спілкування Kotonia та поміняв лише персону. Майже без нового коду.
Лендінг-сторінка знаходиться на /use/mesugaki-english/. SEO націлений на довгі хвостові запити навколо «саркастичної англійської практики» та «строгий AI English tutor».
Персонa Design: Bratty × Tsundere Hybrid
Спочатку реалізував чисто 100% саркастичну персону. Після тестування я згорів за п’ять раунків.
Безперервне насміхання виснажує когнітивно. Реальні люди-тьютори, які залишаються суворими 100% часу, не утримують студентів. Учням потрібні малші перемоги та часом тепла, щоб продовжувати.
Тож я перейшов до саркастично-цундера гібриду. Скелет виглядає так:
– На помилці → легка шибка + негайне виправлення («Pfft, неправильно. Це ‘I went.’»)
– На правильній відповіді → небажане похвала («Hmm… не погано, мабуть. Не в тому, що я тебе хвалю.»)
– Коли застрягає → прибираю ставлення і дійсно допомагаю («…Це було занадто важко? Гаразд, дам тобі підказку.»)
– Після довшої сесії → рідкісна м’яка мить («Не думаю, що ти вражаєш мене за те, що тримаєш це, …Окей, можливо трохи.»)
Я додав розділ «емоційний градієнт» до системного промпу, що чітко прописує ці if-then гілки. LLM набагато надійніше слідують конкретним умовно-обумовленим інструкціям, ніж загальному «будь різким».
Ще один ключовий регулятор: частотні обмеження. Додав правило, що вигуки на кшталт «pfft» або «hmph» можуть з’являтися не більше одного разу за висловлення — це миттєво заспокоїло вихід. LLM часто перенасичуються суворими інструкціями характеру, тому явні заглушувачі працюють добре.
Управління персонажами як код
Персона живе у src/data/personas/mesugaki-english.ts як константа TypeScript. У Kotonia є CRUD-потоці з БД для персон, але я вирішив, продукти, що паруються з лендингом, мають бути в git.
Аргументація:
– Копія персонажі частина маркетингового повідомлення — та ж причина, чому заголовок H1 у git. Промтоормп несе PR-огляд.
– Зберігання його в БД створює ризик того, що хтось підміняє його через адміністратор UI і знижує якість.
– Як самотній розробник, «налаштування персонажа = редагування файлу + пуш» підходить під той же цикл як і будь-яка інша копія. Один канал для всього.
Чітке розділення: БД-персони — створені користувачем, особисті; код-персони — фіксовані продуктові пропозиції.
Стіна: ASR сам по собі не може виправляти вимову
Коли персона працювала, ASR став наступним вузьким місцем швидко.
Я почав з Whisper (small). Передавання language=’ja’ примушує Whisper працювати в японському режимі транскрипції, коли отримує англійне аудіо — упереджує вихідність до катакани або повноцінних японських перекладів. «I went to the supermarket» може стати «アイ ウェント トゥ ザ スーパーマーケット», або, в гіршому випадку, «私はスーパーに行きました». З таким виходом штучний інтелект не може оцінити помилки англійської.
Це відоме явище Whisper: параметр language примушує мову транскрипції та просочується у вхід англійської.
Перехід на Qwen3-ASR Multi-lang
Рішенням стало додавання окремого налаштування мови для STT-слою:
–
// Added sttLanguage option to useVoiceChat hook
– Роз’єднує мову TTS від мови STT
– const { voiceState, conversation, // … = useVoiceChat({ language: ‘ja’, // TTS in Japanese (Ono_Anna voice) sttLanguage: ‘multi’, // STT auto-detect sttModel: ‘qwen3_asr’, // …
Персона конфігурації вказує stt.model: 'qwen3_asr' + stt.language: 'multi'. Qwen3-ASR-1.7B підтримує багатомовну автоматичну діагностику та добре справляється з перемикаванням між кодами (змішана японська/англійська). Відсутнє упередження по мові від Whisper.
Але транскрипція як основа має обмеження
Якщо транскрипт повертається як «I want an apple»:
– Граматика ✓
– Словник ✓
– Але фактичне звучання аудіо було як «I wont an apple» — проблема вимови
AI бачить правильний рядок і не має чого виділити. Для продукту з вивчення англійської це фатально. Якщо саркастичний репетитор дозволяє неакуратну вимову, половина цінності зникає.
Рішення: надсилати сирий аудіо до Gemini разом із транскриптом
Gemini — це мультимодальна модель, що приймає текст, зображення та аудіо. Тому замість того, щоб надсилати лише транскрипцію ASR, я міг надсилати і сире аудіо також.
Kotonia має хук useVoiceChat з опцією geminiAudioInput з попередніх експериментів:
– якщо geminiAudioInput && model.startsWith(‘gemini’) && userAudioBlob
– конвертує до base64 і надсилає audio_base64 в /api/voice/chat
– бекенд embeds його як inline_data audio/wav у запит Gemini
Rust-бекенд (voice_chat.rs) уже обробляє прийом audio_base64 та вставляє його як inline_data: { mime_type: 'audio/wav', data: ... }. Увімкнення geminiAudioInput: true в конфігу персона зробило все разом — щаслива випадковість з минулої ітерації.
Я також додав інструкції до системного промпу: «You can hear the user’s raw audio directly. You can call out pronunciation issues, not just transcription errors», та три конкретні приклади (м’яки звуки th, відмінність want vs won’t, ударність).
Результати:
– Навіть з ідеальним транскриптом «I want an apple», AI тепер може сказати «Ваше ‘want’ звучить як ‘won’t’».
– Коли транскрипт перекручено до «アイ ウェント トゥ», AI слухає безпосередньо і може сказати «Ви намагалися сказати ‘I want to’?».
– Фрустрація від неправдивих транскрипцій зменшилася значно — розчарування через помилку транскрипції, коли вимова була нормальною, деморалізувала.
На обмін: надсилання WAV-бло до кожного обертання збільшує розмір даних і додає трохи затримки. Приріст якості досвіду настільки великий, що це не є близько до рішення.
Нерівні краї та майбутня робота
Це не досконала реалізація. Нерішені проблеми:
1. Нестабільність Gemini
– використовується gemini-3.1 flash-lite preview, що іноді створює затримку 5–10 секунд. Прев’ю-кількість лімітує, іноді з’являються холодні старти/обмеження.
– План: перейти на стабільну реліз-версію (не прев’ю). Claude Sonnet 4.6 та Haiku 4.5 також підходять для більш передбачуваної затримки.
2. Хибнопозитивний Content Filter
– Безпека Gemini іноді ситуативно перевищує сарказм. Легкі зауваження типу «Pfft, ця вимова груба» іноді повертаються порожнім відповідям.
– Персона explicit говорить «не атакувати зовнішність, особистість чи інтелект — тільки вказувати на англійські помилки», але мета-зрілість все одно фігурує. Це проблема постачальника LLM; відстежуватиму поведінку на стабільній збірці. Запуск локальних LLM (наприклад, Gemma 4 31B) — варіант, але аудіо-вхідні локальні моделі наразі обмежені.
3. Затримка через TTL кешу контексту
– 5–10 секундні піки, мабуть, через те, що я надсилаю повну історію розмови Gemini кожного разу, а у Gemini є кеш контексту: кешує префікс (системний промпт + префікс персона + історія). Коли кеш теплий, обробляється лише новий раунд.
– Бекенд вже має: кеш TTL та оновлення
– Найкраща гіпотеза: якщо користувач мовчить більш ніж 5 хвилин — кеш-міс → повне відбудування префікса → багато секундова пік.
Майбутня робота:
– Запуск фонової keep-alive пінг під час активних розмов, щоб тримати кеш довше.
– Збільшити TTL кешу Gemini API (до 1 години підтримується).
– Явно видаляти кеш під кінцем розмови (щоб уникати витоків пам’яті).
Розширення на інші мови та персони
Якщо це набере обертів, природний наступний крок — саркастичний AI-румно-англійський, китайський та корейський діалоги. Qwen3-TTS підтримує 10 мов із голосовими акторами як Vivian (китайська жіноча) та Sohee (корейська жіноча) — головне — переписати персона instruct та системний промп на кожну мову.
Інші оснастки персона — «ніжний вчитель англійської», «TOEIC drill sergeant» — можна додати за день за допомогою тієї самої схеми: src/data/personas/<slug>.ts + /use/<slug>/ + /chat/<slug>/.
Повний системний промп
Для тих, хто хоче відтворити або адаптувати це, ось фактичний системний промп, що використовується (первинна японська; продукт працює на японській):
[уривок японського системного промпу та англійський переклад збережено в оригінальному стилі; далі текст не повторюється тут через обсяг]
Tech stack summary:
– Component: LLM — Gemini 3.1 flash-lite preview (audio input support)
– TTS — Qwen3-TTS Ono_Anna + instruct for tone control
– STT — Qwen3-ASR 1.7B multi-lang (auto-detect)
– VAD — @ricky0123/vad-react (браузерний)
– Web — Next.js (статичний експорт) + Rust (Axum) бекенд
– GPU — RTX PRO 6000 Blackwell Max-Q (96GB, власна інфраструктура)
Підсумок
Цей саркастичний AI-англійський репетитор є тестовим майданчиком для стратегії: ніша × іммерсія × диференціація, яку великі гравці не зможуть повторити, зібраний самостійно. Чотири design-рішення, які з цього вийшли:
– Управління персонажами як кодом під Git
– Розв’язання розділення мови STT від мови TTS, щоб усунути упередження ASR
– Передача сирого аудіо до Gemini для реального зворотного зв’язку щодо вимови
– Поєднання сарказму з теплом цундера, щоб запобігти втомі
Усе це — повторювані активи, коли я розширюю на інші мови та персонажі.
Живий продукт знаходиться за адресою /use/mesugaki-english/. Приходьте на розмову — розігрівають.
May 22, 2026 at 01:30PM

Залишити відповідь