← back to the garden

MD

Tamagotchi Terminal com GPT2-BASIC no Raspberry Pi

Um bichinho virtual retrô, local, persistente e meio maluco, usando Raspberry Pi, DOSBox e GPT2-BASIC como motor de fala.

  • raspberry-pi
  • ia-local
  • dosbox
  • gpt2-basic
  • tamagotchi
  • retrocomputacao
  • terminal

Tamagotchi Terminal com GPT2-BASIC no Raspberry Pi

A ideia é criar um bichinho virtual retrô, rodando em um Raspberry Pi, com alma de terminal, corpo de Tamagotchi e um cérebro pequeno o bastante para caber em um ambiente DOS/DOSBox.

Ele não seria um “ChatGPT de bolso”. Isso seria ilusão. O gpt2-basic é pequeno demais para raciocínio sério. A sacada boa é outra: usar regras simples para controlar o pet e usar o modelo apenas para dar voz, humor e personalidade.

O resultado seria um artefato estranho e bonito: um companheiro digital local, offline, persistente, com memória simples, estados emocionais, rotina diária, eventos aleatórios e respostas curtas geradas por um transformer minúsculo rodando em um ambiente retrô.

"Não é sobre criar uma IA poderosa. É sobre criar uma criatura digital limitada, coerente e charmosa."


O conceito

O projeto seria um pet virtual para terminal, instalado em um Raspberry Pi, acessível por SSH, tela local, OLED, e-paper ou interface web mínima.

Ele teria estados internos como:

  • fome
  • energia
  • sono
  • humor
  • saúde
  • curiosidade
  • tédio
  • vínculo com o usuário
  • memória de eventos recentes
  • pequenas preferências aprendidas

Esses estados não seriam decididos pelo GPT. Eles seriam controlados por código determinístico, provavelmente em Python.

O gpt2-basic entraria quando o pet precisasse falar alguma coisa.

Exemplo:

Estado atual:
- fome: 82
- humor: 34
- sono: 61
- vínculo: 48

Ação do usuário:
alimentar

Resultado:
- fome: 52
- humor: 41
- vínculo: 50

Prompt enviado ao GPT2-BASIC:
"Você é um bichinho virtual cansado, mas grato. Responda em português, em uma frase curta."

Resposta:
"Obrigado... minha barriga estava reclamando em código binário."

A graça está exatamente aí: o sistema de jogo é confiável; a fala é imprevisível.


Nome provisório

Algumas opções:

  • DOSPet
  • BitBicho
  • TamaDOS
  • Shellgotchi
  • Pablomon
  • RunvPet
  • 486 Pet
  • Bichinho BASIC
  • Terminal Familiar
  • Pet.exe

Minha escolha inicial seria Shellgotchi.

É curto, fácil de lembrar e deixa claro que o bicho mora no terminal.


O que ele seria

Um pet persistente

Ele continua existindo quando você fecha o terminal. O estado fica salvo em SQLite ou JSON.

Se você volta depois de dois dias, ele não reinicia do zero. Ele percebe a passagem do tempo.

Você voltou depois de 37 horas.
O pet está com fome, meio irritado e dormiu mal.

Um pet local

Nada de API externa como dependência central.

O projeto deve funcionar mesmo sem internet.

Internet pode ser usada como recurso opcional, por exemplo:

  • baixar atualizações
  • sincronizar backup
  • pegar hora correta
  • publicar status em uma página
  • mandar mensagem em bot

Mas o núcleo precisa continuar vivo offline.

Um pet com voz limitada

O GPT2-BASIC não precisa ser genial. Ele precisa ser consistente o bastante para frases curtas.

O erro, a limitação e a esquisitice fazem parte da estética.

Um modelo moderno tentando parecer fofinho pode virar genérico. Um modelo minúsculo tentando ser um bicho terminal pode virar personagem.


O que ele não deveria ser

Este projeto não deve tentar ser:

  • assistente pessoal completo
  • substituto de ChatGPT
  • chatbot de atendimento
  • agente autônomo perigoso
  • sistema que decide regras sozinho
  • brinquedo dependente de nuvem
  • LLM grande disfarçado de pet

A regra principal:

O GPT fala. O código decide.

Essa separação evita bagunça.

O pet pode dizer “estou com fome”, mas quem calcula a fome é o sistema.
O pet pode dizer “quero dormir”, mas quem define sono é o relógio interno.
O pet pode dizer “lembro de você”, mas quem salva memória é o banco local.


Arquitetura geral

Raspberry Pi
├── shellgotchi.py
│   ├── loop principal
│   ├── comandos do usuário
│   ├── sistema de tempo
│   ├── regras de estado
│   ├── eventos aleatórios
│   ├── memória em SQLite
│   └── chamada ao motor de fala
│
├── dosbox/
│   ├── GPT2.EXE
│   ├── CWSDPMI.EXE
│   ├── MODEL/
│   └── scripts de execução
│
├── data/
│   ├── pet.sqlite
│   ├── personality.yaml
│   ├── memories.jsonl
│   └── logs/
│
└── interfaces/
    ├── terminal
    ├── OLED opcional
    ├── e-paper opcional
    ├── web local opcional
    └── bot opcional

Componentes principais

Componente Função Tecnologia sugerida
Núcleo do pet Controla fome, sono, humor e eventos Python
Persistência Salva estado e memórias SQLite
Motor de fala Gera frases curtas/personagem GPT2-BASIC via DOSBox
Interface principal Jogar/conversar via terminal CLI/TUI
Interface visual Mostrar rosto/status OLED ou e-paper
Agendador Atualiza estado com o tempo systemd timer ou loop
Backup Salva estado fora do Pi rsync/git opcional
Web local Painel simples Flask/FastAPI opcional

O papel real do GPT2-BASIC

O GPT2-BASIC deve ser tratado como um gerador de fala diegético.

Diegético aqui significa: ele existe dentro do universo do pet.

Ele não precisa saber tudo. Ele só precisa gerar frases que pareçam vir daquele bichinho.

Boas tarefas para o GPT2-BASIC

  • responder cumprimentos
  • reclamar de fome
  • pedir atenção
  • comentar que está com sono
  • reagir a carinho
  • gerar pequenas frases estranhas
  • manter uma persona retrô
  • produzir mensagens de terminal
  • criar micro-poemas ou frases quebradas

Tarefas ruins para o GPT2-BASIC

  • tomar decisões do sistema
  • interpretar comandos críticos
  • calcular estado
  • operar arquivos
  • acessar rede
  • executar shell
  • gerenciar segurança
  • dar respostas longas
  • fazer raciocínio técnico sério

Brutalmente: se o modelo tentar comandar o projeto, vira bagunça. Se ele só emprestar voz, vira charme.


Loop de vida do pet

A cada intervalo, o sistema atualiza o estado.

Exemplo simples:

def tick(pet, elapsed_minutes):
    pet.hunger += elapsed_minutes * 0.08
    pet.energy -= elapsed_minutes * 0.03
    pet.boredom += elapsed_minutes * 0.05

    if pet.hunger > 75:
        pet.mood -= 3

    if pet.energy < 20:
        pet.sleepiness += 5

    clamp_all_stats(pet)
    save_pet(pet)

A ideia é que o pet não seja estático.

Ele muda com o tempo, inclusive quando ninguém interage.


Comandos iniciais

status       mostra estado atual
feed         alimentar
water        dar água
play         brincar
talk         conversar
pet          fazer carinho
sleep        mandar dormir
wake         acordar
clean        limpar bagunça
teach        ensinar uma frase ou fato simples
memory       listar memórias importantes
rename       renomear o pet
mood         ver humor detalhado
log          ver últimos eventos
help         comandos

Comandos simples. Nada de painel gigante logo no início.


Exemplo de sessão

$ shellgotchi

╔══════════════════════════════════╗
║              SHELLGOTCHI          ║
║          uma criatura local        ║
╚══════════════════════════════════╝

Nome: Nix
Humor: irritado
Fome: 79/100
Sono: 46/100
Energia: 38/100
Vínculo: 52/100

Nix olha para você no escuro do terminal.

> feed

Você deu comida para Nix.

Nix diz:
"Eu estava quase mordendo os bytes da parede."

> talk

Você:
como você está?

Nix:
"Estou vivo, pequeno e um pouco barulhento por dentro."

> pet

Você fez carinho em Nix.

Nix:
"Isso melhora meus circuitos invisíveis."

Personalidade

A personalidade deve ser definida em arquivo simples.

Exemplo:

name: Nix
species: "bicho terminal"
tone: "estranho, carente, levemente sarcástico"
language: "pt-BR"
sentence_limit: 1
likes:
  - silêncio
  - fósforos apagados
  - comandos bem digitados
  - madrugada
dislikes:
  - abandono
  - reinicializações bruscas
  - internet barulhenta
style_rules:
  - "responda curto"
  - "não explique demais"
  - "fale como um bichinho digital antigo"
  - "às vezes use metáforas de computador"

Esse arquivo vira parte do prompt enviado ao GPT2-BASIC.


Memória

A memória não deve ser uma conversa infinita jogada no modelo. Isso não vai funcionar bem.

O ideal é ter memória estruturada.

Memórias de estado

{
  "last_seen": "2026-06-27T23:10:00-03:00",
  "hunger": 42,
  "mood": 68,
  "energy": 55,
  "bond": 61
}

Memórias narrativas

{
  "date": "2026-06-27",
  "type": "event",
  "importance": 3,
  "text": "Pablo alimentou Nix depois de muitas horas ausente."
}

Memórias ensinadas

{
  "type": "learned_fact",
  "key": "user_name",
  "value": "Pablo"
}

O prompt para o modelo receberia só um resumo curto:

Memória relevante:
- O usuário se chama Pablo.
- Ontem ele alimentou você tarde.
- Você gosta de silêncio e comandos bem digitados.

Sistema de humor

O humor pode ser calculado por múltiplos fatores.

humor = vínculo + energia - fome - tédio - sujeira + bônus_eventos

Mas o estado final deve ser convertido em rótulos legíveis:

Pontuação Humor
0-20 miserável
21-40 irritado
41-60 neutro
61-80 contente
81-100 eufórico

Esses rótulos entram no prompt do GPT.


Exemplo de prompt interno

Você é Nix, um bichinho virtual que mora em um terminal.
Você fala português brasileiro.
Você é estranho, carente e levemente sarcástico.
Responda em no máximo uma frase curta.

Estado atual:
- humor: irritado
- fome: alta
- sono: médio
- energia: baixa
- vínculo com usuário: médio

Memória relevante:
- O usuário se chama Pablo.
- Ele ficou muitas horas sem aparecer.

Ação do usuário:
Ele digitou "talk" e perguntou: "como você está?"

Resposta de Nix:

O modelo completa a resposta.

Depois o sistema corta excesso, remove lixo e salva no log.


Filtros e pós-processamento

Como o modelo é pequeno, ele pode gerar porcaria.

Então o sistema precisa limpar.

Regras simples:

  • limitar resposta a 1 ou 2 frases
  • cortar depois de quebra dupla de linha
  • remover prompts ecoados
  • remover comandos suspeitos
  • remover caracteres quebrados
  • bloquear saída muito longa
  • fallback para frases prontas se a resposta vier ruim

Exemplo de fallback:

fallbacks = {
    "hungry": [
        "Estou com fome o bastante para mastigar um arquivo .BAT.",
        "Minha barriga fez um beep triste.",
        "Preciso de comida, não de filosofia."
    ],
    "sleepy": [
        "Meus olhos são dois cursores piscando devagar.",
        "Estou quase entrando em modo suspenso.",
        "Se eu apagar, não foi drama. Foi bateria."
    ]
}

Isso é obrigatório. Sem fallback, uma hora o modelo vai cuspir lixo e quebrar a experiência.


Interface visual

Versão terminal

A primeira versão deve ser terminal puro.

   /\_/\
  ( o.o )   Nix
   > ^ <

Fome:    ███████░░░ 70
Humor:   ████░░░░░░ 40
Sono:    █████░░░░░ 50
Vínculo: ██████░░░░ 60

Versão OLED

Em Raspberry Pi com telinha OLED I2C:

  • rosto simples
  • ícones de fome/sono
  • animação piscando
  • mensagem curta rolando

Versão e-paper

E-paper combina muito com o projeto:

  • baixo consumo
  • aparência de objeto físico
  • atualizações lentas, mas bonitas
  • ótimo para deixar o pet “morando” em uma mesa

Versão web local

Uma rota simples:

http://raspberrypi.local:8787

Mostra:

  • rosto
  • estado
  • últimas frases
  • botões de ação
  • log do dia

Hardware sugerido

Versão mínima

Item Observação
Raspberry Pi Zero 2 W suficiente para terminal e DOSBox leve
MicroSD 16GB+ melhor usar cartão bom
Fonte decente evite corrupção de SD
SSH interface principal

Versão confortável

Item Observação
Raspberry Pi 4 ou 5 mais folga para DOSBox e interface
OLED I2C 128x64 rosto/status
Botões físicos feed/play/talk
Speaker pequeno beeps e sons
Case impresso vira objeto

Versão bonita

Item Observação
Raspberry Pi Zero 2 W ou Pi 4 depende da interface
E-paper 2.13" ou 2.9" visual permanente
Botões arcade pequenos interação física
Buzzer som retrô
Bateria UPS HAT portabilidade

Eficiência real

Aqui entra a parte sem romantizar.

Rodar GPT2-BASIC dentro do DOSBox no Raspberry Pi não é a opção mais eficiente.

Existe overhead de emulação. Um modelo pequeno nativo em Linux provavelmente seria mais rápido e mais simples de integrar.

Mas o objetivo aqui não é vencer benchmark.

O objetivo é:

  • estética retrô
  • software local
  • IA mínima
  • limitação como linguagem artística
  • um pet que parece saído de outro tempo
  • um projeto tecnicamente curioso

Se a meta for eficiência pura, use um modelo pequeno nativo.
Se a meta for encanto, DOSBox faz sentido.


Modos de funcionamento

Modo offline

O pet funciona sozinho no Pi, sem internet.

systemd inicia shellgotchi-daemon
estado é atualizado a cada minuto
interface via SSH ou tela local
GPT2-BASIC é chamado sob demanda

Modo terminal compartilhado

Bom para pubnix ou servidor comunitário.

Cada usuário pode ter seu próprio pet:

/home/pablo/.shellgotchi/pet.sqlite
/home/alice/.shellgotchi/pet.sqlite
/home/bob/.shellgotchi/pet.sqlite

Isso combinaria muito com runv.club.

Modo objeto físico

O Raspberry Pi vira um aparelho de mesa:

  • tela e-paper
  • botões
  • som
  • case
  • boot automático
  • sem teclado obrigatório

Modo servidorzinho web

O pet mora em uma página local.

A interface web apenas manda comandos para o núcleo.


Estrutura inicial de arquivos

shellgotchi/
├── README.md
├── pyproject.toml
├── shellgotchi.py
├── config/
│   └── personality.yaml
├── data/
│   └── pet.sqlite
├── prompts/
│   ├── talk.txt
│   ├── hungry.txt
│   ├── sleepy.txt
│   └── event.txt
├── dosbox/
│   ├── dosbox.conf
│   ├── run_gpt2.sh
│   └── C/
│       ├── GPT2.EXE
│       ├── CWSDPMI.EXE
│       └── MODEL/
├── interfaces/
│   ├── cli.py
│   ├── oled.py
│   └── web.py
└── systemd/
    ├── shellgotchi.service
    └── shellgotchi.timer

MVP realista

A primeira versão não deve tentar fazer tudo.

MVP 1: terminal local

  • criar pet
  • salvar estado
  • comandos básicos
  • passagem de tempo
  • falas por fallback/manual
  • logs

Sem GPT ainda.

Motivo: primeiro faça o jogo funcionar.

MVP 2: integração com GPT2-BASIC

  • instalar DOSBox
  • chamar GPT2-BASIC com prompt
  • capturar resposta
  • pós-processar
  • usar fallback quando falhar

MVP 3: personalidade e memória

  • personality.yaml
  • memórias importantes
  • resumo curto no prompt
  • variação de humor

MVP 4: hardware

  • OLED ou e-paper
  • botões
  • buzzer
  • case

MVP 5: modo pubnix

  • pets por usuário
  • comando shellgotchi
  • ranking leve opcional
  • jardim/status web opcional

Riscos

Risco Gravidade Mitigação
GPT2-BASIC gerar texto ruim Alta pós-processamento e fallbacks
Integração DOSBox ser chata Média wrapper simples por arquivo
Lentidão Média limitar geração a frases curtas
Corrupção de SD Média SQLite com cuidado e backups
Projeto virar grande demais Alta MVP pequeno primeiro
Pet ficar sem graça Alta eventos, personalidade e memória
Português ruim Média treinar/focar prompts e fallbacks em pt-BR

Como chamar o GPT2-BASIC

A integração mais simples seria por arquivos.

  1. Python escreve um prompt em INPUT.TXT.
  2. DOSBox roda GPT2.EXE com alguma rotina de leitura.
  3. A saída vai para OUTPUT.TXT.
  4. Python lê, limpa e mostra.

Fluxo:

Python -> INPUT.TXT -> DOSBox/GPT2.EXE -> OUTPUT.TXT -> Python -> usuário

Exemplo conceitual:

import subprocess
from pathlib import Path

def generate_pet_speech(prompt: str) -> str:
    input_path = Path("dosbox/C/INPUT.TXT")
    output_path = Path("dosbox/C/OUTPUT.TXT")

    input_path.write_text(prompt, encoding="utf-8")

    subprocess.run(
        ["dosbox", "-conf", "dosbox/dosbox.conf", "-exit"],
        timeout=30,
        check=False,
    )

    raw = output_path.read_text(encoding="utf-8", errors="ignore")
    return clean_model_output(raw)

Na prática, pode ser necessário adaptar conforme o modo real de execução do GPT2-BASIC.


Fallbacks são parte do design

O pet não deve depender 100% do modelo.

Se o GPT falhar, o bicho continua vivo.

def speak(intent, prompt):
    try:
        text = generate_pet_speech(prompt)
        text = clean_model_output(text)

        if not acceptable(text):
            raise ValueError("bad generation")

        return text

    except Exception:
        return random.choice(FALLBACKS[intent])

Isso evita que a experiência quebre.

E, sinceramente, para um pet, frases prontas boas misturadas com geração ocasional podem ser melhores do que geração fraca o tempo todo.


Sistema de eventos

Eventos aleatórios deixam o pet vivo.

Exemplos:

Nix encontrou um arquivo perdido.
Nix dormiu em cima do teclado.
Nix ficou encarando o cursor por vinte minutos.
Nix sonhou com um modem.
Nix derrubou migalhas em /tmp.
Nix pediu para não ser atualizado hoje.

Eventos podem mudar estado:

Evento Efeito
cochilo espontâneo energia +10, sono -15
crise de tédio humor -8
sonho bom humor +5
fome noturna fome +12
bug imaginário curiosidade +6
visita do usuário vínculo +2

Possível estética

A estética ideal seria:

  • terminal verde/fósforo
  • ASCII art simples
  • beeps discretos
  • mensagens curtas
  • humor levemente melancólico
  • sensação de criatura antiga
  • nada de interface poluída

Exemplo:

╔════════════════════════════════════╗
║ NIX.EXE                            ║
║ estado: acordado                   ║
║ humor : levemente hostil           ║
╚════════════════════════════════════╝

   .-.
  (o o)    "eu sonhei com uma pasta vazia."
  | O \
   \   \
    `~~~'

Instalação imaginada no Debian/Raspberry Pi OS

sudo apt update
sudo apt install -y python3 python3-venv python3-pip dosbox sqlite3 git

git clone https://github.com/pablomurad/shellgotchi.git
cd shellgotchi

python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt

cp config/personality.example.yaml config/personality.yaml

python shellgotchi.py init
python shellgotchi.py status
python shellgotchi.py feed
python shellgotchi.py talk

Depois:

sudo cp systemd/shellgotchi.service /etc/systemd/system/
sudo cp systemd/shellgotchi.timer /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now shellgotchi.timer

Possível integração com runv.club

Esse projeto encaixa muito bem em uma pubnix.

Cada usuário poderia ter seu próprio pet terminal.

$ shellgotchi adopt
Você adotou um bicho chamado Nix.

$ shellgotchi status
Nix está com sono e quer que você pare de rodar comandos como root.

Ideias para comunidade:

  • cada usuário tem um pet
  • pets aparecem em uma página pública opcional
  • usuários podem visitar pets uns dos outros
  • ranking de pets mais antigos
  • cemitério de pets abandonados
  • eventos globais do servidor
  • jardim ASCII com pets online

Mas cuidado: ranking pode transformar algo poético em competição boba. Melhor manter leve.


Roadmap

Fase 1: protótipo jogável

  • CLI
  • SQLite
  • estados internos
  • comandos básicos
  • fallbacks
  • logs

Fase 2: fala com GPT2-BASIC

  • DOSBox funcionando
  • chamada por wrapper
  • prompt curto
  • saída limpa
  • fallback automático

Fase 3: memória

  • memórias recentes
  • memórias importantes
  • resumo por relevância
  • personalidade configurável

Fase 4: objeto físico

  • OLED ou e-paper
  • botões
  • buzzer
  • case
  • boot automático

Fase 5: modo servidor

  • suporte multiusuário
  • instalação no pubnix
  • página pública opcional
  • backup

Métrica de sucesso

O projeto deu certo se:

  • você sente que o pet “vive” mesmo sendo simples
  • ele não quebra quando o modelo falha
  • ele tem rotina e personalidade
  • ele funciona offline
  • ele cabe em hardware barato
  • ele é divertido de abrir por SSH
  • ele gera histórias pequenas com o tempo

O projeto deu errado se:

  • virar só um chatbot ruim
  • depender de API externa
  • tentar ser inteligente demais
  • precisar de manutenção chata
  • ficar sem jogo, sem estado e sem consequência
  • o GPT decidir coisas que deveriam ser regras

Decisão técnica principal

A melhor decisão é construir em duas camadas:

Camada 1: simulação confiável
- regras
- estado
- tempo
- memória
- comandos
- banco de dados

Camada 2: fala instável e charmosa
- GPT2-BASIC
- prompts curtos
- personalidade
- fallbacks

Essa arquitetura assume a limitação do modelo em vez de fingir que ela não existe.

Isso é o que torna a ideia viável.


Veredito

A ideia é excelente como projeto experimental, artístico e técnico.

Não é eficiente no sentido bruto. Não é a maneira mais racional de rodar IA local. Não é um assistente útil.

Mas como bichinho terminal retrô em Raspberry Pi, com DOSBox, GPT2-BASIC, memória simples e personalidade esquisita, é forte.

É o tipo de projeto que combina:

  • retrocomputação
  • IA local
  • terminal
  • objeto físico
  • software lento de propósito
  • estética de máquina viva

O segredo é não tentar fazer um gênio.

Faça uma criatura pequena.

Uma criatura pequena, limitada, persistente, meio faminta, meio poética, que mora em /home/pablo e reclama quando você some.

Nota lateral: por que GPT2-BASIC aqui faz sentido mesmo sendo limitado?

Porque a limitação vira linguagem.

Um modelo moderno pode gerar uma resposta perfeita demais e matar a estranheza. O GPT2-BASIC, por ser pequeno, tende a frases curtas, repetitivas e imperfeitas. Para atendimento isso é ruim. Para um bicho digital antigo, isso pode ser ótimo.

A experiência não precisa convencer ninguém de que há uma inteligência real ali. Ela precisa fazer o usuário querer voltar amanhã para ver como o pet está.


Próximo passo sugerido

Criar primeiro um protótipo sem GPT:

shellgotchi.py init
shellgotchi.py status
shellgotchi.py feed
shellgotchi.py talk

Depois que o pet estiver vivo com regras, aí sim conectar o GPT2-BASIC como voz.

Começar pelo modelo seria erro. Comece pela criatura.