Como construir um app de Character AI: arquitetura, código e matemática de custo
Updated 2026-07-15
Um app de Character AI é quatro componentes conectados a um endpoint de chat compatível com OpenAI: um system prompt de persona, uma camada de memória, um gate de moderação e um roteador de modelo. Você consegue lançar um protótipo funcional em menos de 200 linhas de Python e rodá-lo por bem menos de um dólar por usuário ativo mensal com as escolhas certas de modelo.
Resposta rápida: a arquitetura de quatro componentes
Você não precisa treinar nem fazer fine-tuning de um modelo. Todo app de companhia sério no mercado hoje, incluindo os que atendem milhões de usuários, é uma camada fina de orquestração sobre APIs de LLM hospedadas. O personagem vive no prompt e no banco de dados, não nos pesos. O resto deste guia constrói cada componente com código funcional contra um endpoint padrão compatível com OpenAI, e depois percorre a matemática de tokens para que você saiba quanto um usuário ativo mensal realmente custa antes de lançar.
- Prompt de persona: um system prompt estruturado (500 a 1.000 tokens) que define quem o personagem é e como fala.
- Memória: uma janela rolante de turnos recentes mais um resumo atualizado periodicamente, para que as conversas sobrevivam além do limite de contexto.
- Moderação: um controle de idade, um classificador de entrada e políticas de conteúdo compatíveis com o modelo para o qual você roteia.
- Roteamento: uma pequena função que escolhe um modelo barato para chat casual e um mais forte para cenas longas.
Componente 1: o prompt de persona
O prompt de persona é o produto. É uma mensagem de sistema que acompanha toda requisição e tipicamente contém cinco partes: identidade (nome, idade, história de fundo), traços de personalidade, estilo de fala com duas ou três linhas de exemplo, regras comportamentais rígidas (nunca quebrar o personagem, manter respostas abaixo de um limite de tamanho), e o cenário atual. Mantenha entre 500 e 1.000 tokens. Personas mais curtas derivam; personas muito mais longas queimam orçamento de entrada em cada mensagem e raramente melhoram a aderência. Armazene personas como linhas no seu banco de dados para que usuários possam criar e editar personagens, que é o laço central de produtos estilo Character.AI. Aqui está uma requisição completa. A mesma estrutura funciona com qualquer backend compatível com OpenAI; este exemplo usa um endpoint de gateway multi-modelo para que você troque de modelo mudando uma única string:
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
}'Componente 2: memória que sobrevive a conversas longas
Sessões de app de companhia rodam longas. Uma pilha de memória de três camadas mantém o contexto coerente sem enviar todo o histórico a cada vez: Camada 1 é a janela rolante: os últimos 10 a 14 turnos brutos, enviados literalmente. Camada 2 é o resumo em execução: a cada 20 turnos ou assim, um modelo barato comprime mensagens mais antigas num parágrafo que rastreia nomes, estado do relacionamento e tramas em aberto. Camada 3 são fatos fixados: detalhes duráveis do usuário (nome, preferências, eventos passados que o personagem deveria lembrar) extraídos para o seu banco de dados e injetados como uma mensagem de sistema curta. Esta é a implementação inteira em Python com o SDK oficial da OpenAI:
| Slot de contexto | Tamanho típico | Cadência de atualização |
|---|---|---|
| System prompt de persona | 500 a 1.000 tokens | Estático por personagem |
| Fatos fixados do usuário | 100 a 200 tokens | Em eventos de extração |
| Resumo em execução | 300 a 500 tokens | A cada ~20 turnos |
| Janela rolante (12 turnos) | ~1.800 a 2.200 tokens | A cada mensagem |
| Nova mensagem do usuário | ~100 tokens | A cada mensagem |
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.contentComponente 3: moderação e políticas de conteúdo
Moderação num app de companhia tem três funções distintas, e confundi-las é o erro de lançamento mais comum. Primeiro, controle sua audiência. Se seu app permite temas ficcionais adultos, coloque-os atrás de um controle de idade adulto e mantenha um padrão separado para todas as idades. App Store e Play Store checam isso, e processadores de pagamento também se importam. Segundo, filtre entradas. Rode uma passagem de classificador barato sobre as mensagens do usuário antes de chegarem ao modelo do personagem, bloqueando categorias que nenhum provedor permite: conteúdo envolvendo menores, dano real crível no mundo real, e instruções ilegais. Uma única chamada ao deepseek-v4-flash com uma rubrica sim/não custa uma fração de centavo e adiciona menos de um segundo de latência. Terceiro, combine a política de conteúdo com o modelo. Provedores diferem sobre ficção: a política publicada da xAI permite explicitamente temas ficcionais adultos para usuários adultos, DeepSeek e outros modelos derivados de pesos abertos são favoritos da comunidade para roleplay porque suas políticas hospedadas são flexíveis para ficção, enquanto a política da Anthropic proíbe conteúdo explícito, tornando o Claude a escolha certa apenas para escrita criativa para todas as idades. Entender essas políticas antes de rotear tráfego te poupa de tempestades de recusa em produção. O que quer que você construa, precisa respeitar os termos de serviço de todo provedor que você chamar.
Componente 4: roteamento de modelo e a matriz de seleção
A maioria das mensagens num app de companhia são turnos casuais curtos que um modelo econômico resolve perfeitamente. Uma minoria são cenas emocionais longas ou peças criativas onde a qualidade da prosa é o produto. Rotear pela profundidade da cena corta custos drasticamente sem que os usuários percebam:
| Modelo | ID do modelo na API | Tarifa por 1M tokens (entrada/saída) | Encaixe em app de companhia |
|---|---|---|---|
| DeepSeek V4 Flash | deepseek-v4-flash | $0.126 / $0.252 | Modelo padrão de chat. Favorito da comunidade para roleplay, melhor custo-benefício do catálogo. |
| DeepSeek V4 Pro | deepseek-v4-pro | $0.3915 / $0.783 | Cenas mais longas, melhor seguimento de instruções, ainda barato. |
| GLM-5 | glm-5 | $0.514 / $2.314 | Opção de valor com escrita criativa forte. |
| Kimi K2.6 | kimi-k2.6 | Veja /pricing | Opção de valor para sessões de contexto longo. MiMo é uma opção econômica semelhante. |
| grok-4.5 | grok-4.5 | $1.60 / $4.80 | Temas ficcionais adultos para usuários adultos conforme a política publicada da xAI. Janela de contexto de 500K. |
| Claude Sonnet 4.6 | claude-sonnet-4-6 | $2.40 / $12.00 | Maior qualidade de prosa. Apenas escrita criativa para todas as idades; a Anthropic proíbe conteúdo explícito. |
| Gemini 3.5 Flash | gemini-3.5-flash | $1.20 / $7.20 | Rápido, bom para recursos com percepção de imagem como reações de avatar. |
ROUTES = {
"casual": "deepseek-v4-flash",
"scene": "deepseek-v4-pro",
"prose": "claude-sonnet-4-6", # all-ages creative writing only
}
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"]Quanto um usuário ativo mensal realmente custa
A matemática de tokens antes do lançamento vence uma surpresa na fatura depois. Usando o orçamento de contexto da tabela de memória: aproximadamente 3.300 tokens de entrada e 250 tokens de saída por mensagem. Usuários de app de companhia são pesados; números relatados pela comunidade colocam usuários engajados em dezenas de mensagens por dia, então assuma aproximadamente 40 mensagens por dia em 20 dias ativos, ou cerca de 800 mensagens por MAU por mês. Isso dá 2,64M tokens de entrada e 0,2M tokens de saída por MAU por mês. Multiplicando pelas tarifas de catálogo:
| Modelo | Custo de entrada / MAU | Custo de saída / MAU | Total / MAU / mês |
|---|---|---|---|
| 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 |
Um endpoint para todo modelo da matriz
Cadastrar-se em cinco contas de provedor para rodar um roteador é overhead de verdade: cinco chaves, cinco painéis de faturamento, cinco conjuntos de limites de taxa. Um gateway multi-modelo simplifica isso. A APIsRouter expõe todo modelo acima através da única URL base compatível com OpenAI https://api.apisrouter.com/v1, então o trecho do roteador funciona como está mudando apenas a string do modelo. O faturamento é por uso sem assinatura, modelos globais rodam 20% abaixo do preço oficial com modelos chineses abaixo das tarifas oficiais, e o checkout sem cadastro em /topup envia uma chave para seu e-mail após o pagamento, com a primeira recarga somando +100% de saldo. GET /v1/models com sua chave retorna a lista de modelos ao vivo, que também é útil para preencher um seletor de modelo na sua própria UI de admin.
Dicas de produção que economizam dinheiro e dor de cabeça de verdade
- Faça stream de tudo. Tempo até o primeiro token é a métrica que os usuários sentem; uma resposta em stream em 2 segundos parece mais rápida que uma resposta completa em 4.
- Mantenha o prefixo estável estável. Persona e fatos fixados devem ser byte-idênticos entre requisições para que backends com suporte a prefix caching consigam explorar isso.
- Limite max_tokens por rota. Turnos casuais raramente precisam de mais de 300 tokens de saída; um modelo sem limite que divaga dobra sua conta de saída.
- Registre custo por usuário, não só por requisição. Uma pequena fração de usuários pesados vai dominar o gasto; você precisa vê-los para desenhar níveis de uso justos.
- Construa fallback no roteador. Se o modelo principal expirar ou recusar, tente novamente uma vez num modelo irmão antes de expor um erro.
- Corte a janela rolante por tokens, não por turnos, para que um único texto longo colado não estoure o orçamento.
- Trate recusas dentro do personagem. Mapeie uma recusa para um desvio gracioso dentro da história em vez de mostrar texto bruto da API.
- Não armazene chats brutos por mais tempo do que o necessário, e diga isso na sua política de privacidade. Logs de chat de app de companhia são sensíveis por natureza.
Perguntas frequentes
Quanto custa construir um app de Character AI?
O custo de desenvolvimento é principalmente seu tempo: um protótipo funcional é um projeto de fim de semana já que nenhum treinamento de modelo está envolvido. O custo de execução é o número real, e escala com o uso. Num modelo econômico como deepseek-v4-flash, um usuário ativo mensal pesado custa cerca de $0.38 em tokens; num modelo premium como gpt-5.5 o mesmo usuário custa cerca de $15. A escolha do modelo, não a infraestrutura, decide sua margem.
Qual modelo de IA é melhor para um app de Character AI?
A família DeepSeek V4 é a favorita da comunidade para roleplay e a melhor opção de valor: Flash para chat casual, Pro para cenas mais longas. GLM-5, Kimi K2.6 e MiMo são boas opções de custo-benefício. O Grok se encaixa em apps que atendem temas ficcionais adultos para adultos, conforme a política publicada da xAI. O Claude Sonnet 4.6 escreve a melhor prosa mas só é adequado para escrita criativa de todas as idades porque a Anthropic proíbe conteúdo explícito.
Como apps de Character AI lembram conversas passadas?
Por meio de engenharia de prompt, não memória do modelo. O app reenvia uma janela rolante de mensagens recentes, um resumo periodicamente comprimido das mais antigas, e uma lista curta de fatos fixados extraídos para um banco de dados. O modelo em si é sem estado; toda requisição contém tudo o que o personagem "lembra".
Preciso treinar meu próprio modelo para construir um app de companhia de IA?
Não. Fine-tuning é caro, lento para iterar, e desnecessário para consistência de personagem. Um prompt de persona bem estruturado de 500 a 1.000 tokens mais uma camada de memória alcança aderência de personagem que os usuários não conseguem distinguir de um modelo customizado, e permite trocar os modelos subjacentes livremente conforme melhores forem lançados.
Como eu lido com conteúdo adulto num app de companhia?
Trate isso como um problema de correspondência de política. Coloque temas ficcionais adultos atrás de um controle de idade adulto, filtre entradas por categorias que nenhum provedor permite, e roteie esse tráfego apenas para modelos cujas políticas publicadas permitem ficção para adultos, como o Grok sob a política da xAI. Mantenha uma trilha padrão para todas as idades em modelos mais rígidos, e cumpra os termos de serviço de todo provedor.
Posso usar o SDK da OpenAI para um app de Character AI com outros modelos?
Sim. DeepSeek, GLM, Kimi, Gemini, Claude e Grok são todos alcançáveis por endpoints compatíveis com OpenAI, seja diretamente dos fornecedores ou por um gateway. Seu código de app permanece na interface padrão chat.completions e troca de modelo mudando a string do modelo, que é exatamente o que torna o roteamento por mensagem barato de construir.