Chatbot ELIZA

Giseldo NeoGiseldo Neo
14 min read

Explicação Técnica do Funcionamento

ELIZA foi um dos primeiros programas de processamento de linguagem natural, criado entre 1964 e 1966 por Joseph Weizenbaum no MIT. Sua implementação mais famosa simula um psicoterapeuta Rogeriano (script chamado DOCTOR), refletindo as palavras do usuário de volta em forma de pergunta. Apesar de não “entender” de fato o conteúdo, ELIZA conseguia dar a ilusão de compreensão ao usuário. A seguir examinamos como esse chatbot funcionava internamente, explorando seu mecanismo de padrões e regras de transformação, bem como variações e influências modernas.

Exemplo de diálogo (em inglês) entre um usuário humano e ELIZA, mostrando as respostas em letras maiúsculas geradas pelo script DOCTOR. Nesse exemplo, o usuário faz afirmações pessoais (“Men are all alike.”, “Well, my boyfriend made me come here.”) e ELIZA responde com perguntas ou reformulações (“IN WHAT WAY”, “YOUR BOYFRIEND MADE YOU COME HERE?”), reutilizando termos do próprio usuário. Esse estilo reflexivo encoraja o usuário a continuar falando sem fornecer respostas diretas.

Processamento de Entradas e Palavras-Chave

O funcionamento do ELIZA baseia-se em correspondência de padrões por palavras-chave. A cada turno, o texto de entrada do usuário é analisado em busca de termos-chave predefinidos. Weizenbaum implementou uma varredura da sentença da esquerda para a direita, identificando se alguma palavra correspondia a uma palavra-chave do script. Caso encontrasse, ELIZA selecionava a keyword mais “importante” (havia um peso de prioridade associado a cada palavra-chave) e ignorava o restante da entrada. Por exemplo, o script DOCTOR definia palavras como “alike” ou “same” com alta prioridade; assim, na frase “Men are all alike.” o programa detectava a palavra “alike” e disparava uma resposta associada a ela (no caso: “In what way?”). Se múltiplas keywords aparecessem, ELIZA escolhia aquela de maior peso (rank) para formular a resposta. Todo texto após um ponto final ou vírgula também podia ser ignorado após identificar uma palavra-chave, de modo que cada resposta focasse em uma única afirmação do usuário.

Se nenhuma palavra-chave fosse encontrada na entrada, ELIZA recorria a frases genéricas programadas, chamadas de respostas “vazias” ou sem conteúdo. Nesses casos, o chatbot emitia mensagens do tipo “I see.” (“Entendo.”) ou “Please, go on.” (“Por favor, continue.”). Esse mecanismo evitava silêncio quando o usuário dizia algo fora do escopo do script. Além disso, a implementação original incluía uma estrutura de memória: algumas declarações recentes do usuário eram armazenadas e, se uma entrada subsequente não contivesse novas keywords, ELIZA poderia recuperar um tópico anterior e introduzi-lo na conversa. Por exemplo, se o usuário mencionasse família em um momento e depois fizesse uma afirmação vaga, o programa poderia responder retomando o assunto da família (“Does that have anything to do with your family?”). Essa estratégia dava uma pseudo-continuidade ao diálogo, simulando que o sistema “lembrava” de informações fornecidas anteriormente.

Regras de Transformação de Frases

Encontrada a palavra-chave, ELIZA aplicava uma regra de transformação associada a ela para gerar a resposta. As regras são definidas em pares: um padrão de análise (decomposition rule) e um modelo de reconstrução de frase (reassembly rule). Primeiro, a frase do usuário é decomposta conforme um padrão que identifica a contexto mínimo em torno da palavra-chave. Essa decomposição frequentemente envolve separar a frase em partes e reconhecer pronomes ou estruturas gramaticais relevantes. Por exemplo, considere a entrada (em inglês) “You are very helpful.”. Uma regra de decomposição pode identificar a estrutura “Você é X” — onde “X” representa o restante da frase — e extrair o complemento “very helpful” como um componente separado. Em seguida, a regra de reassembly correspondente é aplicada, remontando uma sentença de resposta em que “X” é inserido em um template pré-definido. No exemplo dado, o template de resposta poderia ser “What makes you think I am X?”; ao inserir X = “very helpful”, gera-se “What makes you think I am very helpful?”. Observe que há uma inversão de pessoa: o pronome “you” do usuário foi trocado por “I” na resposta do bot. De fato, uma parte importante das transformações do ELIZA envolve substituir pronomes (eu/você, meu/seu) para que a resposta faça sentido como uma frase do ponto de vista do computador falando com o usuário. Esse algoritmo de substituição é relativamente simples (por exemplo, “meu” → “seu”, “eu” → “você”, etc.), mas essencial para dar a impressão de entendimento gramatical.

As regras de transformação do ELIZA foram escritas manualmente como parte do script do domínio (no caso, terapia). O conjunto de padrões e respostas predefinidas constitui o que Weizenbaum chamou de “roteiro” (script) de conversa. Importantemente, o mecanismo do ELIZA separa o motor genérico de processamento (o algoritmo de busca de keywords e aplicação de regras) dos dados do script em si. Isso significa que ELIZA podia em teoria simular diferentes personalidades ou tópicos apenas carregando um script diferente, sem alterar o código do programa. Weizenbaum demonstrou essa flexibilidade observando que “uma vez que o script é dado como dados, ELIZA não fica restrito a nenhum conjunto específico de padrões ou até mesmo a uma língua específica”. De fato, na época ele mencionou que já haviam scripts criados em outros idiomas, como galês e alemão.

Implementação Original e Variações Modernas

A implementação original de ELIZA foi feita em uma linguagem chamada MAD-SLIP (um dialecto de Lisp) rodando em um mainframe IBM 7094 no sistema CTSS do MIT. O código fonte do programa principal continha o mecanismo de correspondência, enquanto as regras de conversação (script DOCTOR) eram fornecidas separadamente em formato de listas associativas, similar a uma lista em Lisp. Infelizmente, Weizenbaum não publicou o código completo no artigo de 1966 (o que era comum na época), mas décadas depois o código em MAD-SLIP foi recuperado nos arquivos do MIT, comprovando os detalhes de implementação. De qualquer forma, a arquitetura descrita no artigo influenciou inúmeras reimplementações acadêmicas e didáticas nos anos seguintes.

Diversos entusiastas e pesquisadores reescreveram ELIZA em outras linguagens de programação, dada a simplicidade relativa de seu algoritmo. Ao longo dos anos surgiram versões em Lisp, PL/I, BASIC, Pascal, Prolog, Java, Python, JavaScript, entre muitas outras. Cada versão normalmente incluía o mesmo conjunto de regras do script terapeuta ou pequenas variações.

As ideias de ELIZA também inspiraram chatbots mais avançados. Poucos anos depois, em 1972, surgiu PARRY, escrito pelo psiquiatra Kenneth Colby, que simulava um paciente paranoico. PARRY tinha um modelo interno de estado emocional e atitudes, mas na camada de linguagem ainda usava muitas respostas baseadas em regras, chegando a “conversar” com o próprio ELIZA em experimentos da época. Em 1995, Richard Wallace desenvolveu o chatbot ALICE (Artificial Linguistic Internet Computer Entity), que levava o paradigma de ELIZA a uma escala muito maior. ALICE utilizava um formato XML chamado AIML (Artificial Intelligence Markup Language) para definir milhares de categorias de padrões e respostas. Com mais de 41.000 templates mapeando entradas para saídas [5], ALICE conseguia manter diálogos bem mais naturais e abrangentes que o ELIZA original, embora o princípio básico de correspondência de padrões permanecesse. Esse avanço rendeu a ALICE três vitórias no Prêmio Loebner (competição de chatbots) no início dos anos 2000 [5]. Outras variações e sucessores notáveis incluem Jabberwacky (1988) – que já aprendia novas frases – e uma profusão de assistentes virtuais e bots de domínio específico nas décadas seguintes [5]. Em suma, o legado de ELIZA perdurou por meio de inúmeros chatbots baseados em regras, até a transição para abordagens estatísticas e de aprendizado de máquina no final do século XX.

Implementação de um Chatbot ELIZA em Python

A seguir, apresentamos uma implementação simplificada de um chatbot no estilo ELIZA usando Python. Esse código demonstra o uso de expressões regulares para identificar padrões (palavras-chave) na entrada do usuário e gerar respostas de acordo com regras de transformação definidas manualmente. Comentários em cada linha explicam o funcionamento:

import re  # Importa o módulo de expressões regulares (regex) para correspondência de padrões
import random  # Importa o módulo random para escolher respostas aleatórias entre as opções

# Define a lista de regras como tuplas (padrao_regex, respostas_possiveis).
# Cada padrão é uma expressão regular que, se corresponder à entrada do usuário,
# aciona uma das respostas associadas (escolhida aleatoriamente).
regras = [
    # 1) Cumprimento: detecta saudações como "hello", "hi" ou "hey" (maiúsculas/minúsculas ignoradas)
    (re.compile(r'\b(hello|hi|hey)\b', re.IGNORECASE),
     ["Hello. How do you do. Please tell me your problem."]),

    # 2) Padrão "I am" ou "I'm": captura o texto após "I am" (ou "I'm") para reuso na resposta
    (re.compile(r'\b(I am|I\'?m) (.+)', re.IGNORECASE),
     ["How long have you been {1}?",   # {1} será substituído pelo grupo 2 capturado (estado após "I am")
      "Why do you think you are {1}?"]),

    # 3) Padrão "I need": quando o usuário diz "I need X", pergunta o motivo da necessidade
    (re.compile(r'\bI need (.+)', re.IGNORECASE),
     ["Why do you need {1}?",
      "Would it really help you to get {1}?"]),

    # 4) Padrão "I can't": quando o usuário diz que não pode fazer algo, estimula a reflexão ou sugere tentativa
    (re.compile(r'\bI can\'?t (.+)', re.IGNORECASE),
     ["What makes you think you can't {1}?",
      "Have you tried {1}?"]),

    # 5) Padrão "my <family>": se mencionar "my mother/father/mom/dad", responder sobre a família/pais
    (re.compile(r'\bmy (mother|father|mom|dad)\b', re.IGNORECASE),
     ["Tell me more about your family.",
      "How do you feel about your parents?"]),

    # 6) Padrão "sorry": resposta tranquilizadora a um pedido de desculpas
    (re.compile(r'\b(sorry)\b', re.IGNORECASE),
     ["Please don't apologize."]),

    # 7) Padrão "maybe/perhaps": percebe incerteza e responde incentivando a clarificação
    (re.compile(r'\b(maybe|perhaps)\b', re.IGNORECASE),
     ["You don't seem certain."]),

    # 8) Padrão "because": questiona uma justificativa iniciada por "porque"
    (re.compile(r'\bbecause\b', re.IGNORECASE),
     ["Is that the real reason?"]),

    # 9) Padrão perguntas ao bot "Are you...?" ou "Do you...?": devolve com outra pergunta (resposta genérica)
    (re.compile(r'\b(are you|do you) (.+)\?$', re.IGNORECASE),
     ["Why do you ask that?"]),

    # 10) Padrão "computer": uma resposta específica caso a palavra "computer" apareça na fala do usuário
    (re.compile(r'\bcomputer\b', re.IGNORECASE),
     ["Do computers worry you?"]),
]

# Lista de respostas padrão (fallback) caso nenhuma regra acima corresponda à entrada
respostas_padrao = [
    "I see.",  # "Entendo."
    "Please tell me more.",  # "Por favor, me conte mais."
    "Can you elaborate on that?"  # "Você pode elaborar mais sobre isso?"
]

def eliza_responder(entrada_usuario):
    """Gera uma resposta estilo ELIZA para a entrada do usuário."""
    for padrao, respostas in regras:
        match = padrao.search(entrada_usuario)  # Tenta encontrar o padrão na entrada
        if match:
            # Se o padrão corresponder, escolhe aleatoriamente uma das respostas associadas
            resposta = random.choice(respostas)
            # Se a regex capturou grupos (parte da entrada), insere-os na resposta usando format()
            if match.groups():
                resposta = resposta.format(*match.groups())
            return resposta
    # Se nenhuma regex corresponder, devolve uma resposta genérica padrão
    return random.choice(respostas_padrao)

No código acima, definimos vários padrões regex que representam as “palavras-chave” de interesse (por exemplo, saudações, frases com “I am”, “I need”, referências à família, etc.). Quando a função eliza_responder é chamada com uma string de entrada, ela itera por essas regras na ordem e usa padrao.search(entrada) para verificar se o padrão aparece na frase do usuário. Ao encontrar um match, seleciona-se uma resposta. Observe que muitas respostas contêm placeholders como {1} – esses marcadores serão substituídos pelo conteúdo capturado na entrada do usuário. Por exemplo, se o usuário digitar "I am sad", a regex do padrão 2 capturará o grupo ("I am", "sad"), e a resposta escolhida "Why do you think you are {1}?" será formatada como "Why do you think you are sad?". Caso nenhuma regra específica seja acionada, o chatbot retorna aleatoriamente uma das respostas genéricas em respostas_padrao (como "I see.").

Demonstração: Suponha a seguinte interação usando o chatbot implementado:

Usuário: Hello
Bot: Hello. How do you do. Please tell me your problem.

Usuário: I am feeling sad
Bot: Why do you think you are feeling sad?

Usuário: Because I lost my job
Bot: Is that the real reason?

Usuário: Maybe I was not good enough.
Bot: You don't seem certain.

Usuário: My mother tried to help.
Bot: Tell me more about your family.

Podemos ver que o bot respondeu “Hello...” à saudação inicial (regra 1), depois detectou “I am sad” e devolveu uma pergunta usando sad (regra 2), seguiu questionando o “Because...” (regra 8) e reagiu a “Maybe...” (regra 7), e assim por diante. Cada resposta foi escolhida conforme as regras e conteúdo da frase do usuário, semelhante ao comportamento do ELIZA original. Vale notar que esse exemplo é em inglês para refletir as regras escritas no código (as regras poderiam ser adaptadas para português facilmente, trocando-se os padrões e respostas).

Comparação com Modelos de Linguagem Modernos

A técnica de ELIZA, baseada em palavras-chave com respostas predefinidas, contrasta fortemente com os métodos de Large Language Models (LLMs) atuais, como o GPT-4, que utilizam redes neurais de milhões (ou trilhões) de parâmetros e mecanismos de atenção. Nesta seção, comparamos os dois enfoques quanto ao mecanismo de pesos, contextualização e geração de linguagem.

Mecanismo de Pesos: Palavras-Chave vs. Atenção Neural

No ELIZA, a “importância” de uma palavra era determinada manualmente pelo programador através de pesos ou rankings atribuídos a certas keywords no script. Ou seja, o programa não aprendia quais termos focar – ele seguia uma lista fixa de gatilhos. Por exemplo, termos como “sempre” ou “igual” tinham prioridade alta no script DOCTOR para garantir respostas apropriadas. Em contraste, modelos modernos como o GPT-4 não possuem uma lista fixa de palavras importantes; em vez disso, eles utilizam o mecanismo de self-attention para calcular dinamicamente pesos entre todas as palavras da entrada conforme o contexto [4]. Na arquitetura Transformer, cada palavra (token) de entrada gera consultas e chaves que interagem com todas as outras, permitindo ao modelo atribuir pesos maiores às palavras mais relevantes daquela frase ou parágrafo [4]. Em outras palavras, o modelo aprende sozinho quais termos ou sequências devem receber mais atenção para produzir a próxima palavra na resposta. Esse mecanismo de atenção captura dependências de longo alcance e nuances contextuais que um sistema de keywords fixas como o ELIZA não consegue representar [4]. Além disso, o “vocabulário” efetivo de um LLM é imenso – o GPT-4 foi treinado com trilhões de palavras e ajustou seus parâmetros para modelar estatisticamente a linguagem humana [4]. Como resultado, pode-se dizer metaforicamente que os LLMs têm uma lista de “palavras-chave” milhões de vezes maior (na prática, distribuída em vetores contínuos) e um método bem mais sofisticado de calcular respostas do que o ELIZA (divihn.com). Enquanto ELIZA dependia de coincidências exatas de termos para disparar regras, modelos como GPT avaliam similaridades semânticas e contexto histórico graças às representações densas (embeddings) aprendidas durante o treinamento de rede neural.

Contextualização e Geração de Linguagem

Devido à sua abordagem baseada em regras locais, o ELIZA tinha capacidade de contextualização muito limitada. Cada input do usuário era tratado quase isoladamente: o programa não construía uma representação acumulada da conversa, além de artifícios simples como repetir algo mencionado (a estrutura de memória) ou usar pronomes para manter a ilusão de continuidade. Se o usuário mudasse de tópico abruptamente, o ELIZA não “perceberia” – ele apenas buscaria a próxima palavra-chave disponível ou recorreria a frases genéricas. Em contraste, modelos de linguagem modernos levam em conta um longo histórico de diálogo. Algoritmos como GPT-4 podem manter um contexto de milhares de tokens (palavras ou fragmentos) em sua janela de atenção, o que significa que eles conseguem referenciar informações mencionadas vários parágrafos atrás e integrá-las na resposta corrente. O mecanismo de self-attention, em particular, permite que o modelo incorpore relações contextuais complexas: cada palavra gerada pode considerar influências de palavras distantes no texto de entrada [4]. Por exemplo, ao conversar com um LLM, se você mencionar no início da conversa que tem um irmão chamado João e depois perguntar “ele pode me ajudar com o problema?”, o modelo entenderá que “ele” se refere ao João mencionado anteriormente (desde que dentro da janela de contexto). Já o ELIZA original não teria como fazer essa ligação, a menos que houvesse uma regra explícita para “ele” e algum armazenamento específico do nome – algo impraticável de antecipar via regras fixas para todos os casos.

Outra diferença crucial está na geração de linguagem. O ELIZA não gera texto original no sentido pleno: suas respostas são em grande parte frases prontas (ou templates fixos) embaralhadas com partes da fala do usuário. Assim, seu vocabulário e estilo são limitados pelo script escrito manualmente. Modelos como GPT-4, por sua vez, geram respostas novas combinando probabilisticamente o conhecimento adquirido de um extenso corpus. Eles não se restringem a repetir trechos da entrada, podendo elaborar explicações, fazer analogias, criar perguntas inéditas – tudo coerente com os exemplos linguísticos em sua base de treinamento. Enquanto ELIZA tendia a responder com perguntas genéricas ou devolvendo as palavras do usuário, os LLMs podem produzir respostas informativas e detalhadas sobre praticamente qualquer assunto (pois “aprenderam” uma ampla gama de tópicos durante o treinamento). Por exemplo, se perguntarmos algo factual ou complexo, o ELIZA falharia por não ter nenhuma regra a respeito, provavelmente dando uma resposta vazia. Já um modelo como GPT-4 tentará formular uma resposta baseada em padrões linguísticos aprendidos e em conhecimento implícito dos dados, muitas vezes fornecendo detalhes relevantes.

Em termos de fluência e variedade, os modelos modernos superam o ELIZA amplamente. O ELIZA frequentemente se repetia ou caía em loops verbais quando confrontado com inputs fora do roteiro – um limite claro de sistemas por regras estáticas. Os LLMs produzem linguagem muito mais natural e adaptável, a ponto de muitas vezes enganarem os usuários sobre estarem conversando com uma máquina (um efeito buscado desde o Teste de Turing). Ironicamente, ELIZA nos anos 60 já provocou um precursor desse fenômeno – o chamado Efeito ELIZA, em que pessoas atribuem compreensão ou sentimentos a respostas de computador que, na verdade, são superficiais. Hoje, com GPT-4 e similares, esse efeito se intensifica pela qualidade das respostas, mas a distinção fundamental permanece: ELIZA seguia scripts sem compreender, enquanto LLMs inferem padrões e significados de forma estatística, sem entendimento consciente, mas atingindo resultados que simulam compreensão de maneira muito mais convincente. Em suma, os avanços de arquitetura (especialmente o mecanismo de atenção) ampliaram drasticamente a capacidade de contextualização e geração dos chatbots modernos, marcando uma evolução significativa desde o mecanismo simples porém pioneiro de ELIZA.

Referências:

  1. Weizenbaum, J. (1966). ELIZA—A Computer Program For the Study of Natural Language Communication Between Man and Machine. Communications of the ACM, 9(1), 36-45.

  2. Wikipedia. ELIZA – Early NLP Chatbot. Último acesso em 19/03/2025, https://en.wikipedia.org/wiki/ELIZA.

  3. Abu Shawar, B., & Atwell, E. (2002). A Comparison Between Alice and Elizabeth Chatbot Systems. University of Leeds, School of Computing Research Report 2002.19.

  4. [4] Ferit.ai. *Demystifying Large Language Models (*2024). Último acesso em 19/03/2025, https://ferit.ai/demystifying-large-language-models/.

  5. [5] Japeto.ai. Chatbots: From the 1950s to Now (2023). Último acesso em 19/03/2025. https://www.japeto.ai/chatbots-from-the-1950s-to-now/.

0
Subscribe to my newsletter

Read articles from Giseldo Neo directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Giseldo Neo
Giseldo Neo