Criador de namorada IA: como as escolhas viram uma personagem
Desenvolvedor de aplicações de IA trabalhando com modelos de linguagem desde 2022. Construiu vários chatbots com memória e personalidade.
O construtor de personagem é um formulário: você marca alguns chips, clica em criar e recebe uma companhia. Por baixo, é muito mais simples do que a interface sugere e bem mais honesto do que essas interfaces costumam ser. Praticamente tudo o que você escolhe vira três campos de texto que depois entram no prompt de sistema da conversa e no prompt de imagem.
Este texto foi escrito por quem escreveu o código, então não há aqui nenhuma promessa que não possa ser conferida no código-fonte. Onde o pipeline não dá conta, é isso que eu digo: não dá conta.
O que o construtor deixa ajustar e o que não deixa
O conjunto de configurações é fixo e mais estreito do que parece à primeira vista. Tudo o que você escolhe se resume a oito grupos de campos:
- Identidade — gênero e nome de até 32 caracteres. O nome ainda passa por uma sanitização: colchetes angulares, chaves, colchetes quadrados, barras, pipe e um conjunto de caracteres de serviço são removidos, espaços consecutivos são colapsados e o resultado é cortado em 32. O motivo é simples: o nome é renderizado no site e vai para o prompt, o que faz dele um vetor possível de injeção de tags.
- Estilo — realista ou anime. Não é cosmético: o estilo escolhe o modelo de imagem, o conjunto de prompts negativos, a direção de arte e todo o mecanismo que mantém o rosto estável.
- Aparência — etnia (7), cor do cabelo (7), comprimento do cabelo (3), cor dos olhos (5), tipo de corpo (6 para personagem feminino, 5 para masculino), altura (3) e, apenas para o feminino, tamanho do busto (3), mais 600 caracteres de texto livre.
- Personalidade — 12 traços de preset (carinhosa, brincalhona, dominadora, submissa, tímida, confiante, intelectual, misteriosa, romântica, ciumenta, engraçada, protetora) mais 600 caracteres de texto livre.
- Fala de abertura — uma saudação de até 400 caracteres. Opcional, mas com uma consequência prática: se você deixar vazio, a personagem abre a conversa em silêncio.
- Estilo de intimidade — um controle de ousadia de 0 a 100 (padrão 34) e 8 chips de preferência (romance, dominação, submissão, roleplay, sacanagem na conversa, provocação, possessividade, elogios), mais texto livre.
- Privacidade — particular ou disponível por link.
- Imagem de prévia — um campo técnico, tratado à parte.
Agora a lista mais importante: o que não existe.
- Idade. Não existe campo nenhum. Idade não é parâmetro de aparência, é exigência legal: todas as personagens do serviço são adultas, e isso é garantido no nível da moderação e dos prompts negativos, e não entregue ao usuário como configuração.
- Roupa. Não existe chip de roupa, e isso é deliberado. A roupa é descrita no prompt de cena a cada geração — o modelo escolhe o nível de despimento pelo contexto.
- Voz. A API ainda aceita o campo voice_id, mas ele é forçado para None — a escolha de voz está temporariamente fora da interface.
- Bio e descrição. O modelo tem uma coluna de descrição, mas o construtor não a preenche: as bios do catálogo vêm do personality_prompt, e personagens de usuário não chegam ao catálogo público.
- Edição depois de criar. Não existe endpoint de atualização. Criar, listar, apagar. Um erro de digitação na personalidade significa apagar a personagem e fazer de novo — levando junto todo o histórico da conversa.
Como as configurações viram prompt
Este é o mecanismo inteiro, sem embalagem de marketing. Uma função do backend monta o perfil visual. Primeiro vem o sujeito — “beautiful woman” ou “handsome man”, também escolhido pelo gênero. Depois as tags entram numa ordem fixa: etnia, cor do cabelo, comprimento do cabelo, cor dos olhos, tipo de corpo, altura e, se a personagem for feminina, busto. Cada chip corresponde a uma frase curta em inglês: “brunette hair”, “medium bust”, “Slavic features”.
A ordem não é acidental e está fixada no código. Depois vêm os traços vindos da foto, se existirem, e então o seu texto livre, colados com pontos em uma string só. Se nada foi selecionado, entra um fallback neutro — “attractive adult character” — para que o prompt nunca fique vazio.
A personalidade é montada à parte. Os 12 presets não são rótulos decorativos, são frases prontas com gênero: “carinhosa, atenta aos sentimentos da pessoa com quem fala” e “carinhoso, atento aos sentimentos da pessoa com quem fala” são duas linhas diferentes sob a mesma chave. Sem seleção, entra “uma personalidade viva, emocional”. Seu texto livre é acrescentado depois dos presets, e não no lugar deles: os presets dão o arcabouço gramatical, o texto livre enriquece. Se ele substituísse os presets, um campo vazio deixaria o personality_prompt em branco e o modelo receberia uma personagem sem personalidade nenhuma.
O estilo de intimidade é montado em duas partes. O controle de 0 a 100 vira uma de quatro frases-âncora por faixa: 0 — “romântica e reservada…”, 34 — “se abre aos poucos, flerta com conforto…”, 67 — “flerta abertamente e tem confiança na própria sensualidade…”, 85 — “muito desinibida e explícita…”. Quatro degraus em vez de cem, porque uma frase de gradiente suave soa nitidamente pior na conversa do que quatro estados com significado, entre os quais o modelo alterna conforme o contexto. Por cima da âncora vêm os chips escolhidos e o seu texto livre.
Último detalhe mecânico. Os três campos entram num prompt de sistema remontado no idioma do usuário. personality_prompt e intimacy_profile permanecem em russo, porque o prompt de sistema já é construído a partir de fórmulas russas; traduzi-los a cada mensagem seria uma chamada de modelo desperdiçada. visual_profile é traduzido para inglês uma vez, na criação, porque os modelos de imagem foram treinados em tags em inglês.
Como a aparência é definida: seed, prévia e foto enviada
Primeiro, a seed. Toda personagem tem um campo reference_seed, atribuído na primeira requisição de foto pela fórmula (id * 7919 + 104729) mod 2^31 — não um número aleatório nem um UUID gerado, mas uma função determinística do id da personagem no banco. O objetivo é que a mesma personagem parta sempre do mesmo ponto: com o prompt inalterado você não obtém o quadro idêntico, mas um muito próximo em composição e cor. No momento da criação o campo vale None; a seed é atribuída preguiçosamente, na primeira geração.
Segundo, a prévia. O botão de geração de teste cria um objeto temporário de personagem, que não existe no banco, e pede ao modelo de imagem um único quadro de corpo inteiro com um prompt de cena neutro. A seed desse objeto vem do id do usuário, e não do id da personagem, então as prévias repetidas são estáveis dentro de uma conta. Depois há uma bifurcação: se você clicar em criar e o frontend reenviar essa mesma imagem no campo de prévia, ela é salva como o retrato-mestre da personagem e vira imediatamente o avatar.
Terceiro, a foto enviada. A foto não é salva: os bytes vão para uma única chamada de visão e saem do escopo. O modelo devolve não um rosto, mas uma lista de traços gerais — cor e comprimento do cabelo, cor dos olhos, compleição e altura aproximadas, tom de pele, detalhes de estilo como óculos ou maquiagem. O limite é de 40 palavras. O prompt de sistema dessa chamada exige descrever um personagem “DIFERENTE, fictício, inspirado no estilo” e proíbe nomear ou insinuar quem é a pessoa, e uma verificação separada recusa fotos de menores, de pessoas públicas reconhecíveis e quadros sem um único rosto humano claro. O recurso foi desenhado como “inspiração”, não como “clone”.
Agora a parte honesta sobre os nós de identidade. Nós que transferem traços de rosto de uma referência para o resultado existem aqui — no pipeline de reserva no RunningHub, onde o retrato-mestre é passado para o nó de imagem do workflow. Mas o pipeline principal de foto roda na Venice e é puro text-to-image: nem o retrato-mestre nem um nó de identidade participam, e tudo se sustenta em tags-âncora mais a seed. A razão é medida: um quadro anime completo pelo pipeline de edit levava cerca de 30 segundos contra mais ou menos 5 do text-to-image, em troca de um ganho de estabilidade de rosto que as tags cobriam bem o bastante na prática.
O que o construtor não faz, e por quê
A principal coisa que ele não faz é deixar você “só enviar uma foto e conseguir a mesma pessoa”. Não por razões éticas e não por preguiça, mas por três motivos técnicos.
- Uma chamada de visão não devolve um vetor paramétrico do rosto. Para gerar “a mesma” pessoa você precisaria de um embedding de rosto ou de uma imagem de referência em um nó. Não temos nenhum dos dois — temos 40 palavras de tags, e delas é construída uma personagem fictícia parecida.
- Cópia de um rosto real é identificação de uma pessoa real. O código aqui proíbe: o prompt de visão exige descrever outra personagem, e essa proibição está embutida na própria string que forma a descrição.
- Previsibilidade não é reconhecibilidade. Mesmo com um nó de identidade perfeito o resultado não é uma fotografia da mesma pessoa, é uma repintura baseada nela. Prometer “envie uma foto e receba a mesma pessoa” seria uma promessa que o pipeline não consegue cumprir.
O que acontece depois de salvar
Esta parte funciona de um jeito diferente do que “publicar no catálogo” sugeriria. Personagens de usuário não chegam ao catálogo público. Isso é decisão deliberada: o catálogo é montado a partir de personagens do sistema mais personagens públicos aprovados, mas o construtor aceita apenas dois valores de privacidade — particular e compartilhado por link — e qualquer outro valor, inclusive público, é convertido em particular. Nada do que você constrói vaza por acidente para a vitrine.
Também não existe fila de moderação na criação — a personagem é criada já aprovada. Mas há checagens: o nome, a aparência final (já em inglês) e o perfil de intimidade passam por uma lista de bloqueio, e um acerto significa que a personagem nem chega a ser criada.
O limite é de 30 personagens por conta, e ultrapassá-lo devolve um 429. O acesso é o que foi dito — particular significa só você, compartilhado por link significa qualquer pessoa com o link, que não pode ser adivinhado por ser um token aleatório, e cuja página está fora da indexação.
Site e Telegram
No site, um botão abre o mesmo widget de conversa usado para as personagens do sistema, só que carregando o id da sua personagem e o seu token de link; o acesso é verificado como “personagem de catálogo de estilo permitido, dono, ou link de compartilhamento apresentado”, e a sua personagem passa pelo segundo caminho.
Com o Telegram é um pouco mais intricado, e isso é uma decisão, não um esquecimento. Depois de criar você recebe dois links, e eles não são intercambiáveis. O primeiro é pessoal, com um token de vinculação de conta: ao abri-lo você liga o seu Telegram à conta web e ganha acesso à personagem. Ele não deve ser reencaminhado, porque o Telegram de outra pessoa, abrindo-o, se vincularia à sua conta. O token vive 30 dias. O segundo é pelo token de compartilhamento: pode ser mandado a qualquer um, funciona também para uma personagem particular e não vincula nada.
O token pessoal é escrito em três bancos Redis ao mesmo tempo — os bots russo, inglês e português — porque cada um tem seu banco e cada um lê o token só do seu. É um detalhe pequeno no código e um motivo bem pouco óbvio para a versão inglesa do link não “funcionar sozinha”. Os bots em si são um por idioma, de propósito: o idioma afeta o prompt de sistema da personagem, o registro e a forma de tratamento, e trocar no meio da conversa quebra o personagem, então o bot é escolhido uma vez na entrada.
Quanto custa e quanto tempo leva
A criação da personagem é gratuita. Exatamente um passo do construtor é pago: a geração de teste da prévia, precificada como uma foto comum — 14 cristais.
Enviar foto para inspiração é o único recurso do construtor que exige assinatura paga de verdade, qualquer uma das três. No plano gratuito o servidor responde 402 e o frontend mostra o convite para atualizar.
Sobre tempo: enviar o formulário são três montagens de string, um filtro prévio e uma escrita no banco — frações de segundo. Gerar a saudação, se você não escreveu nenhuma, é uma chamada de modelo de linguagem síncrona, então a personagem não aparece na hora.