Как построить Character AI-приложение: архитектура, код и расчёт стоимости
Updated 2026-07-15
Character AI-приложение — это четыре компонента, подключённых к OpenAI-совместимому chat-эндпоинту: системный промпт персонажа, слой памяти, шлюз модерации и роутер моделей. Рабочий прототип можно выпустить менее чем за 200 строк Python и запускать его значительно дешевле доллара на одного активного пользователя в месяц при правильном выборе моделей.
Короткий ответ: архитектура из четырёх компонентов
Обучать или дообучать модель не нужно. Каждое серьёзное приложение-компаньон на рынке сегодня, включая те, что обслуживают миллионы пользователей, — это тонкий слой оркестрации поверх облачных LLM-API. Персонаж живёт в промпте и базе данных, а не в весах модели. Остальная часть этого гайда собирает каждый компонент с рабочим кодом против стандартного OpenAI-совместимого эндпоинта, а затем разбирает расчёт токенов, чтобы вы знали, сколько реально стоит один активный пользователь в месяц, ещё до запуска.
- Промпт персонажа: структурированный системный промпт (500-1000 токенов), который определяет, кто такой персонаж и как он говорит.
- Память: скользящее окно недавних реплик плюс периодически обновляемое резюме, чтобы разговоры переживали лимит контекста.
- Модерация: возрастной ценз, классификатор входных данных и политики контента, согласованные с моделью, к которой идёт маршрутизация.
- Маршрутизация: небольшая функция, которая выбирает дешёвую модель для непринуждённого чата и более сильную для долгих сцен.
Компонент 1: промпт персонажа
Промпт персонажа и есть продукт. Это системное сообщение, которое отправляется с каждым запросом, и обычно оно состоит из пяти частей: идентичность (имя, возраст, предыстория), черты характера, стиль речи с двумя-тремя примерами реплик, жёсткие поведенческие правила (никогда не выходить из образа, держать ответы в пределах лимита длины) и текущий сценарий. Держите его в пределах 500-1000 токенов. Более короткие промпты персонажа дрейфуют; намного более длинные сжигают бюджет входа на каждом сообщении и редко улучшают соответствие образу. Храните промпты персонажей строками в базе данных, чтобы пользователи могли создавать и редактировать персонажей — это основной цикл продуктов в стиле Character.AI. Вот полный запрос. Та же форма работает с любым OpenAI-совместимым бэкендом; в этом примере используется эндпоинт мультимодельного шлюза, чтобы можно было менять модель, меняя одну строку:
curl https://api.apisrouter.com/v1/chat/completions \
-H "Authorization: Bearer $KEAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-v4-flash",
"messages": [
{"role": "system", "content": "You are Mira, a sarcastic starship engineer in her 30s. Personality: dry wit, fiercely loyal, hates small talk. Speech style: short technical sentences, occasional teasing. Example: \"The coupling is fried. Again. Did you touch it?\" Rules: never break character, never mention being an AI, keep replies under 120 words."},
{"role": "user", "content": "Mira, the reactor is making that noise again."}
],
"temperature": 0.9,
"max_tokens": 300,
"stream": true
}'Компонент 2: память, переживающая долгие разговоры
Сессии в приложениях-компаньонах длятся долго. Трёхслойный стек памяти сохраняет связность контекста без отправки всей истории каждый раз: Слой 1 — скользящее окно: последние 10-14 сырых реплик, отправляемые дословно. Слой 2 — накопительное резюме: примерно каждые 20 реплик дешёвая модель сжимает старые сообщения в абзац, отслеживающий имена, состояние отношений и открытые сюжетные линии. Слой 3 — закреплённые факты: устойчивые данные пользователя (имя, предпочтения, прошлые события, которые персонаж должен помнить), извлечённые в базу данных и вставляемые как короткое системное сообщение. Вот вся реализация на Python с официальным OpenAI SDK:
| Слот контекста | Типичный размер | Частота обновления |
|---|---|---|
| Системный промпт персонажа | 500-1000 токенов | Статичен для каждого персонажа |
| Закреплённые факты пользователя | 100-200 токенов | При событиях извлечения |
| Накопительное резюме | 300-500 токенов | Каждые ~20 реплик |
| Скользящее окно (12 реплик) | ~1800-2200 токенов | Каждое сообщение |
| Новое сообщение пользователя | ~100 токенов | Каждое сообщение |
from openai import OpenAI
client = OpenAI(
api_key="sk-...",
base_url="https://api.apisrouter.com/v1",
)
def build_context(persona, summary, pinned_facts, recent_turns, user_msg):
facts = "\n".join(f"- {f}" for f in pinned_facts)
return [
{"role": "system", "content": persona},
*([{"role": "system", "content": f"Facts to remember:\n{facts}"}]
if pinned_facts else []),
*([{"role": "system", "content": f"Story so far: {summary}"}]
if summary else []),
*recent_turns[-12:],
{"role": "user", "content": user_msg},
]
def refresh_summary(old_turns, prev_summary):
prompt = (
"Update this running summary of a roleplay chat. Keep names, "
"relationship state, and open plot threads. Max 150 words.\n\n"
f"Current summary: {prev_summary}\n\nNew messages: {old_turns}"
)
resp = client.chat.completions.create(
model="deepseek-v4-flash",
messages=[{"role": "user", "content": prompt}],
max_tokens=400,
)
return resp.choices[0].message.contentКомпонент 3: модерация и политики контента
У модерации в приложении-компаньоне три отдельные задачи, и их смешение — самая частая ошибка при запуске. Во-первых, ограничьте аудиторию. Если ваше приложение допускает взрослые вымышленные темы, поместите их за возрастным цензом для совершеннолетних и держите отдельный вариант по умолчанию для всех возрастов. Проверка App Store и Play Store смотрит на это, платёжные процессоры тоже. Во-вторых, проверяйте входные данные. Прогоняйте сообщения пользователя через дешёвый классификатор до того, как они попадут в модель персонажа, блокируя категории, которые не разрешает ни один провайдер: контент с участием несовершеннолетних, правдоподобный реальный вред и незаконные инструкции. Один вызов deepseek-v4-flash с рубрикой да/нет стоит долю цента и добавляет менее секунды задержки. В-третьих, сопоставляйте политику контента с моделью. Провайдеры различаются в отношении художественного текста: опубликованная политика xAI явно разрешает взрослые вымышленные темы для совершеннолетних пользователей, DeepSeek и другие модели, производные от открытых весов, — фавориты сообщества для ролплея, потому что их облачные политики гибкие для художественного текста, тогда как политика Anthropic запрещает откровенный контент, что делает Claude правильным выбором только для творческого письма для всех возрастов. Понимание этих политик до маршрутизации трафика избавляет от штормов отказов в продакшене. Что бы вы ни строили, это должно уважать условия обслуживания каждого провайдера, к которому вы обращаетесь.
Компонент 4: маршрутизация моделей и матрица выбора
Большинство сообщений в приложении-компаньоне — короткие непринуждённые реплики, с которыми прекрасно справляется бюджетная модель. Меньшинство — долгие эмоциональные сцены или творческие постановочные эпизоды, где качество текста и есть продукт. Маршрутизация по глубине сцены резко снижает расходы, оставаясь незаметной для пользователей:
| Модель | ID модели API | Тариф за 1М токенов (вход/выход) | Применимость в приложении-компаньоне |
|---|---|---|---|
| DeepSeek V4 Flash | deepseek-v4-flash | $0.126 / $0.252 | Модель чата по умолчанию. Фаворит сообщества для ролплея, лучшая цена в каталоге. |
| DeepSeek V4 Pro | deepseek-v4-pro | $0.3915 / $0.783 | Долгие сцены, более точное следование инструкциям, всё ещё дёшево. |
| GLM-5 | glm-5 | $0.514 / $2.314 | Выгодный выбор с сильным творческим письмом. |
| Kimi K2.6 | kimi-k2.6 | См. /pricing | Выгодный выбор для сессий с длинным контекстом. MiMo — похожий бюджетный вариант. |
| grok-4.5 | grok-4.5 | $1.60 / $4.80 | Взрослые вымышленные темы для совершеннолетних пользователей по опубликованной политике xAI. Контекстное окно 500K. |
| Claude Sonnet 4.6 | claude-sonnet-4-6 | $2.40 / $12.00 | Самое высокое качество текста. Только творческое письмо для всех возрастов; Anthropic запрещает откровенный контент. |
| Gemini 3.5 Flash | gemini-3.5-flash | $1.20 / $7.20 | Быстрая, хороша для функций с изображениями вроде реакций аватара. |
ROUTES = {
"casual": "deepseek-v4-flash",
"scene": "deepseek-v4-pro",
"prose": "claude-sonnet-4-6", # только творческое письмо для всех возрастов
}
def pick_model(user_msg: str, turns_in_scene: int) -> str:
if turns_in_scene > 6 or len(user_msg) > 400:
return ROUTES["scene"]
return ROUTES["casual"]Сколько реально стоит активный пользователь в месяц
Расчёт токенов до запуска лучше, чем сюрприз в счёте после. Используя бюджет контекста из таблицы памяти: примерно 3300 входных токенов и 250 выходных на сообщение. Пользователи приложений-компаньонов активны; по сообщениям сообщества, вовлечённые пользователи отправляют десятки сообщений в день, поэтому предположим примерно 40 сообщений в день за 20 активных дней, или около 800 сообщений на MAU в месяц. Это даёт 2.64М входных токенов и 0.2М выходных токенов на MAU в месяц. Умножая на тарифы каталога:
| Модель | Стоимость входа / MAU | Стоимость выхода / MAU | Итого / MAU / месяц |
|---|---|---|---|
| deepseek-v4-flash | $0.33 | $0.05 | $0.38 |
| deepseek-v4-pro | $1.03 | $0.16 | $1.19 |
| glm-5 | $1.36 | $0.46 | $1.82 |
| gemini-3.5-flash | $3.17 | $1.44 | $4.61 |
| grok-4.5 | $4.22 | $0.96 | $5.18 |
| claude-sonnet-4-6 | $6.34 | $2.40 | $8.74 |
| gpt-5.5 | $10.56 | $4.80 | $15.36 |
Один эндпоинт для всех моделей в матрице
Регистрация пяти аккаунтов у провайдеров ради одного роутера — это реальные накладные расходы: пять ключей, пять биллинговых панелей, пять наборов лимитов скорости. Мультимодельный шлюз сворачивает всё это. APIsRouter открывает каждую модель выше через единый OpenAI-совместимый base URL https://api.apisrouter.com/v1, поэтому сниппет роутера работает как есть, меняя только строку модели. Оплата по факту использования без подписки, глобальные модели идут на 20% дешевле официальных цен, китайские модели — ниже официальных тарифов, а оформление на /topup без регистрации присылает ключ на email после оплаты, причём первое пополнение добавляет +100% к балансу. GET /v1/models с вашим ключом возвращает актуальный список моделей, что также удобно для заполнения выбора модели в собственном админ-интерфейсе.
Продакшн-советы, которые экономят реальные деньги и нервы
- Стримите всё. Time-to-first-token — метрика, которую чувствуют пользователи; потоковый ответ за 2 секунды ощущается быстрее, чем полный ответ за 4.
- Держите стабильный префикс стабильным. Промпт персонажа и закреплённые факты должны быть побайтово идентичны между запросами, чтобы бэкенды с поддержкой кэширования префиксов могли это использовать.
- Ограничивайте max_tokens для каждого маршрута. Непринуждённым репликам редко нужно больше 300 выходных токенов; модель без ограничения, которая растекается мыслью, удваивает счёт за выход.
- Логируйте стоимость на пользователя, а не только на запрос. Небольшая доля активных пользователей будет доминировать в расходах; вам нужно их видеть, чтобы спроектировать справедливые тарифы использования.
- Встройте резервный вариант в роутер. Если основная модель отвечает таймаутом или отказывает, повторите попытку один раз на родственной модели, прежде чем показывать ошибку.
- Обрезайте скользящее окно по токенам, а не по репликам, чтобы одна длинная вставка не взорвала бюджет.
- Обрабатывайте отказы, не выходя из образа. Превращайте отказ в изящное отклонение внутри истории вместо показа сырого текста API.
- Не храните сырые чаты дольше необходимого и укажите это в политике конфиденциальности. Логи чатов с компаньоном по своей природе чувствительны.
Частые вопросы
Сколько стоит построить Character AI-приложение?
Стоимость разработки — это в основном ваше время: рабочий прототип делается за выходные, поскольку обучение модели не требуется. Стоимость эксплуатации — реальная цифра, и она масштабируется с использованием. На бюджетной модели вроде deepseek-v4-flash активный пользователь в месяц стоит примерно $0.38 в токенах; на премиальной модели вроде gpt-5.5 тот же пользователь стоит около $15. Маржу определяет выбор модели, а не инфраструктура.
Какая ИИ-модель лучше всего подходит для Character AI-приложения?
Семейство DeepSeek V4 — фаворит сообщества для ролплея и лучшая цена: Flash для непринуждённого чата, Pro для более долгих сцен. GLM-5, Kimi K2.6 и MiMo — крепкие выгодные варианты. Grok подходит приложениям, предоставляющим взрослые вымышленные темы совершеннолетним, согласно опубликованной политике xAI. Claude Sonnet 4.6 пишет лучший текст, но подходит только для творческого письма для всех возрастов, потому что Anthropic запрещает откровенный контент.
Как Character AI-приложения помнят прошлые разговоры?
Через prompt engineering, а не память модели. Приложение заново отправляет скользящее окно недавних сообщений, периодически сжатое резюме более старых и короткий список закреплённых фактов, извлечённых в базу данных. Сама модель без состояния; каждый запрос содержит всё, что персонаж «помнит».
Нужно ли обучать собственную модель для AI-приложения-компаньона?
Нет. Дообучение дорого, медленно итерируется и не нужно для консистентности персонажа. Хорошо структурированный промпт персонажа на 500-1000 токенов плюс слой памяти даёт такое соответствие образу, что пользователи не отличат его от кастомной модели, и позволяет свободно менять базовые модели по мере выхода более удачных.
Как обращаться со взрослым контентом в приложении-компаньоне?
Относитесь к этому как к задаче сопоставления с политикой. Поместите взрослые вымышленные темы за возрастным цензом для совершеннолетних, проверяйте входные данные на категории, которые не разрешает ни один провайдер, и направляйте этот трафик только к моделям, чьи опубликованные политики разрешают художественный текст для взрослых, например Grok согласно политике xAI. Держите отдельный трек по умолчанию для всех возрастов на более строгих моделях и соблюдайте условия обслуживания каждого провайдера.
Можно ли использовать OpenAI SDK для Character AI-приложения с другими моделями?
Да. DeepSeek, GLM, Kimi, Gemini, Claude и Grok доступны через OpenAI-совместимые эндпоинты — либо напрямую у вендоров, либо через шлюз. Код вашего приложения остаётся на стандартном интерфейсе chat.completions и переключает модели, меняя строку модели, — именно это делает маршрутизацию на уровне сообщения дешёвой в реализации.