Imagine uma equipe de desenvolvimento onde metade das linhas de código são geradas por sugestões automáticas em vez de digitação manual. Isso já não é ficção: grandes organizações relatam que volumes significativos de código são produzidos com assistência de modelos como GitHub Copilot, GPT e Claude, com ganhos reportados de produtividade e satisfação dos desenvolvedores. Ao mesmo tempo, estudos mostram que 25–30% dos trechos de código gerados por essas ferramentas podem conter vulnerabilidades de segurança, cobrindo dezenas de categorias de falhas críticas. A tensão entre velocidade e qualidade, assistência e dependência, "inteligência" e simples reconhecimento de padrões está no centro do debate atual sobre IA generativa na Engenharia de Software. Após compreendermos o que está mudando na discussão passada, mergulhamos agora no como — os fundamentos técnicos que tornam possível essa aparente "inteligência" para código.
Essa dualidade entre produtividade e risco encapsula o desafio central da Engenharia de Software moderna: como aproveitar o poder dos Large Language Models sem abdicar do julgamento humano que distingue código funcional de código confiável?
A Revolução Transformer: O Paradigma que Mudou Tudo
Antes de 2017, modelos de linguagem processavam texto sequencialmente, palavra por palavra, como quem lê um livro sem poder voltar atrás. Redes Neurais Recorrentes (RNNs) e suas variantes Long Short-Term Memory (LSTM) sofriam de um problema crítico: ao processar sequências longas, "esqueciam" o contexto inicial — imagine tentar entender o final de um código complexo tendo esquecido as declarações de variáveis do início. Uma função de 200 linhas praticamente "esquecia" seu próprio nome ao processar o return final.
O artigo "Attention Is All You Need" (Vaswani et al., 2017) introduziu a arquitetura Transformer, que é fundamentalmente diferente do que existia até então. Em vez de processar sequencialmente, Transformers analisam toda a sequência em paralelo através de um mecanismo chamado self-attention. Na prática, ao analisar um trecho como for (let i = 0; i < array.length; i++), o modelo pode "conectar" diretamente o uso de array.length ao controle do laço, independentemente da distância em tokens.
Pensando como uma pessoa profissional da engenharia de software. Imagine um desenvolvedor experiente revisando este outro trecho de código. Ao encontrar array.filter(item => item.active), ele não lê linearmente — instantaneamente conecta filter com o callback, item com o contexto do array, e active com a estrutura de dados presumida. O attention mechanism replica esse processo: cada token "atende" a todos os outros, com pesos aprendidos que capturam relações sintáticas e semânticas. É como se o modelo pudesse usar um marca-texto infinito, destacando simultaneamente todas as conexões relevantes em um arquivo inteiro.
A inovação central está nas attention heads (cabeças de atenção). Modelos modernos utilizam múltiplas cabeças trabalhando em paralelo — GPT-4 usava 96 — cada uma especializada em capturar diferentes tipos de relações: algumas focam em estrutura sintática (parênteses, chaves), outras em relações semânticas (tipos, funções), outras ainda em padrões de chamada de funções. Essa paralelização não apenas acelera o processamento — permite capturar padrões que arquiteturas sequenciais simplesmente não conseguem ver. Pesquisas de interpretabilidade revelam que certas cabeças aprendem especializações surpreendentemente específicas: identificar o sujeito de um verbo, rastrear referências pronominais, ou detectar padrões de escopo em linguagens de programação.
Transformers são compostos por blocos empilhados de camadas de atenção e camadas feed-forward, cada um seguido de normalização e conexões residuais que facilitam o treinamento de redes muito profundas. LLMs atuais possuem dezenas de camadas e bilhões de parâmetros, capturando regularidades estatísticas complexas em corpora gigantes de texto e código. Esse escalonamento segue leis de potência: dobrar o número de parâmetros tende a produzir ganhos consistentes em métricas como HumanEval.
A chave conceitual é que Transformers não "entendem" sintaxe ou semântica de forma simbólica — aprendem distribuições de probabilidade sobre sequências de tokens. Para código, isso é particularmente relevante porque código fonte contém estruturas hierárquicas e regras rígidas de sintaxe, mas também padrões idiomáticos que se manifestam estatisticamente. Modelos treinados sobre esse material conseguem completar chamadas de API, sugerir padrões de tratamento de erro e até reproduzir estilos de codificação específicos.
Em tempo, essa arquitetura paralela também trouxe ganhos computacionais massivos. Enquanto RNNs exigiam processamento sequencial que não se beneficiava de GPUs modernas, Transformers exploram paralelismo massivo, permitindo treinar modelos com centenas de bilhões de parâmetros em tempo viável. O custo computacional cresce quadraticamente com o tamanho da sequência (cada token atende a todos os outros), mas o benefício em qualidade de representação justificou investimentos bilionários em infraestrutura de treinamento.
Anatomia do Aprendizado: Tokens, Embeddings e Attention
O ponto de partida é a tokenização: antes de "ler" código, o LLM converte o input em uma sequência de tokens — caracteres, subpalavras (como no BPE) ou unidades híbridas. Em muitos modelos, a tokenização foi originalmente pensada para linguagem natural e só depois reutilizada para código, o que pode levar a problemas como fragmentar identificadores de variáveis de forma pouco intuitiva. A palavra getUserById pode ser tokenizada como ["get", "User", "By", "Id"], preservando subpalavras significativas. GPT-4 possui vocabulário de aproximadamente 100.000 tokens.
BPE (Byte Pair Encoding) é uma técnica de tokenização por subpalavras usada em muitos LLMs (incluindo versões do GPT) para transformar texto em tokens antes do treinamento e da inferência. Em vez de trabalhar só com palavras inteiras ou caracteres isolados, o BPE começa com caracteres individuais e vai combinando, de forma iterativa, os pares de caracteres (ou bytes) mais frequentes em um corpus, criando novos “tokens” cada vez maiores até atingir um tamanho de vocabulário pré-definido.
Considere este trecho TypeScript:
function calculateFibonacci(n: number): number {
if (n <= 1) return n;
return calculateFibonacci(n - 1) + calculateFibonacci(n - 2);
}
O modelo não vê caracteres ou palavras — vê tokens, unidades subpalavras definidas durante o treinamento. O tokenizador do GPT-4 fragmentaria esse código aproximadamente assim: ["function", " calculate", "Fib", "onacci", "(", "n", ":", " number", ")", ..."]. Note que "calculateFibonacci" vira três tokens, enquanto operadores como : são tokens individuais. Modelos treinados especificamente em código (como CodeLlama) utilizam tokenizadores otimizados que tratam construções de programação de forma mais eficiente — reconhecendo keywords, operadores compostos, e padrões comuns de nomenclatura.
Essa fragmentação tem consequências práticas importantes. Nomes de variáveis em português ou com caracteres especiais consomem mais tokens que equivalentes em inglês. Um comentário // Calcula o fatorial recursivamente pode usar 8+ tokens, enquanto // Calculate factorial recursively usa 4-5. Em contextos com janela de tokens limitada, isso impacta quanto código o modelo pode "ver" simultaneamente.
Pesquisas recentes mostram que essa tokenização genérica contribui para uma compreensão superficial: quando se aplicam mutações que preservam a semântica — como renomear variáveis ou inserir código morto — o desempenho na detecção de bugs cai drasticamente, com perdas superiores a 80% em alguns cenários. Isso sugere que o modelo está sensível a pistas superficiais mais do que à lógica subjacente.
Embeddings transformam tokens discretos em vetores de alta dimensionalidade (tipicamente 4096 a 12288 dimensões). Cada token recebe uma representação numérica que captura seu "significado" no espaço vetorial. Inicialmente, essas representações são genéricas, mas após passar por dezenas de camadas Transformer, tornam-se contextuais: o embedding de n na linha if (n <= 1) difere do embedding de n em calculateFibonacci(n - 1) porque o contexto circundante é diferente. O mesmo símbolo adquire representações distintas dependendo de seu papel semântico.
O mecanismo de atenção opera sobre esses embeddings através de três projeções lineares: Query (Q), Key (K), e Value (V). Intuitivamente, cada token "pergunta" (Q) ao contexto, outros tokens respondem com suas "chaves" (K), e a relevância determina quanto do "valor" (V) de cada token contribui para a representação final. A fórmula central é: Attention(Q, K, V) = softmax(QK^T / √d_k)V, onde d_k é a dimensionalidade das chaves — um fator de escala que previne que produtos internos cresçam demais em alta dimensionalidade.
Para código, isso significa que ao processar return calculateFibonacci(n - 1), o modelo pode "atender" simultaneamente à definição da função (entendendo a recursão), ao parâmetro n (seu tipo e uso), e ao padrão estrutural de Fibonacci (reconhecido de milhões de exemplos de treinamento). A soma dos pesos de atenção sempre totaliza 1, criando uma distribuição de probabilidade sobre quais tokens são mais relevantes para cada decisão de predição.
O pré-treinamento utiliza a tarefa de modelagem de linguagem: prever o próximo token, minimizando perda de log-verossimilhança em grandes corpora. O fine-tuning supervisionado ajusta para tarefas específicas usando datasets com pares entrada–saída. Uma etapa adicional frequente é o alinhamento por reforço com feedback humano (RLHF), em que avaliadores classificam respostas e o modelo é ajustado para preferir saídas consideradas mais úteis ou seguras.
O Panorama de Modelos: GPT-4, Claude, Gemini e CodeLlama
Benchmarks como HumanEval, MBPP e SWE-bench tornaram-se referências para avaliar capacidades de LLMs em código. No trabalho que introduziu o Codex (Chen et al., 2021), um modelo de 12B parâmetros resolveu 28,8% do HumanEval com uma única amostra (pass@1), chegando a 70,2% com pass@100. Desde então, os números saltaram dramaticamente.
GPT-4 estabeleceu benchmark para modelos generalistas. Com janela de contexto de até 128.000 tokens e treinamento multilíngue, alcança resultados na faixa de 67-87% no HumanEval (dependendo da variante). Sua capacidade de chain-of-thought reasoning permite resolver problemas que exigem múltiplos passos.
Claude (Anthropic, família Sonnet/Opus) diferencia-se pela janela de contexto expandida (até 200.000 tokens) e destaca-se em benchmarks como SWE-bench, onde algumas versões atingem mais de 60% de resolução em tarefas de manutenção de software real — não apenas funções isoladas, mas issues completas de repositórios GitHub.
Gemini (Google), particularmente no AlphaCode 2, mostra força em programação competitiva: resolveu cerca de 43% dos problemas avaliados e atingiu desempenho estimado superior a 85% dos competidores em plataformas como Codeforces — rivalizando com desenvolvedores experientes.
CodeLlama (Meta) exemplifica modelos especializados open-source. A variante Python alcança 53.6% no HumanEval, notável para modelo que pode rodar em hardware próprio — crucial para organizações com restrições de privacidade.
A métrica pass@k merece atenção: representa a probabilidade de que pelo menos uma de k tentativas resolva corretamente o problema. GPT-4 com pass@10 alcança aproximadamente 90% no HumanEval — revelando que, mesmo quando a primeira sugestão falha, o modelo frequentemente contém o conhecimento necessário.
O benchmark MBPP (Mostly Basic Python Problems) complementa o HumanEval com 974 problemas mais simples, testando consistência em tarefas básicas. Modelos de ponta atingem 70-80% de accuracy, mas a correlação imperfeita entre benchmarks e utilidade prática permanece uma questão aberta — resolver problemas isolados difere substancialmente de contribuir para bases de código reais com milhares de dependências e convenções implícitas.
Na prática industrial, mais de 50 mil organizações já adotaram GitHub Copilot. Estudos em empresas como Accenture mostram que mais de 80% dos desenvolvedores adotaram rapidamente a ferramenta, relatando velocidade aumentada e maior satisfação. Contudo, a aceitação média fica em torno de 30% das sugestões — desenvolvedores ainda filtram e julgam o código em vez de aceitá-lo em massa.
Limitações Críticas: Hallucination, Segurança, Raciocínio e Contexto
A fascinação com capacidades frequentemente obscurece limitações fundamentais com consequências práticas sérias.
A performance impressionante em benchmarks mascara limitações fundamentais que todo engenheiro de software deve compreender profundamente antes de integrar essas ferramentas em workflows de produção.
Alucinações representam o problema mais insidioso. Em código, manifestam-se desde erros lógicos sutis até invenção de APIs ou pacotes inexistentes. O fenômeno de "package hallucination" é particularmente perigoso: LLMs recomendam bibliotecas inexistentes que podem ser exploradas por atacantes que registram pacotes com esses nomes em repositórios públicos, introduzindo malware na cadeia de suprimentos:
// Código gerado por LLM - bug sutil
function calculateFibonacci(n: number): number {
if (n <= 0) return 0;
if (n === 1) return 1;
return calculateFibonacci(n - 1) + calculateFibonacci(n - 2);
}
// Problemas: 1) n negativo não tratado adequadamente
// 2) Complexidade O(2^n) - extremamente ineficiente
// 3) Stack overflow para n > ~40
// Versão correta exigiria memoization ou abordagem iterativa
function fibonacciCorrect(n: number): number {
if (n < 0) throw new Error("Input must be non-negative");
if (n <= 1) return n;
let prev = 0, curr = 1;
for (let i = 2; i <= n; i++) {
[prev, curr] = [curr, prev + curr];
}
return curr;
}
O modelo gerou código sintaticamente válido, estruturalmente razoável, mas funcionalmente incorreto. Isso ocorre porque LLMs são modelos estatísticos de próximo token — não possuem verificação de correção semântica nem acesso a especificações formais.
Do ponto de vista de segurança, análises empíricas identificaram que aproximadamente 29–30% dos snippets do GitHub Copilot em projetos reais continham problemas de segurança, cobrindo mais de 30 categorias CWE — injeção de comandos, valores aleatórios inseguros, problemas de validação de entrada. Outro estudo comparou Copilot com desenvolvedores humanos e concluiu que, embora não fosse "pior" em geral, repetia vulnerabilidades conhecidas em cerca de um terço dos casos, especialmente padrões de bugs mais antigos presentes nos dados de treinamento.
Limites de raciocínio são evidentes além de problemas sintéticos. Trabalhos sobre "compreensão de código" mostram que LLMs são altamente sensíveis a mutações semânticas-preservadoras: alterar nomes de variáveis ou inserir código morto reduz dramaticamente a capacidade de localizar bugs. Em benchmarks realistas como SWE-bench, mesmo sistemas avançados apresentaram taxas abaixo de 5% quando se corrigem problemas de qualidade do dataset e vazamentos de solução.
Reasoning vs pattern matching representa talvez a limitação mais profunda. LLMs excelente em reconhecer e reproduzir padrões vistos durante treinamento, mas apresentam degradação significativa quando enfrentam problemas que exigem raciocínio genuinamente novel. Estudos mostram que alterar superficialmente problemas de benchmark (mudando nomes de variáveis, invertendo condições, reformulando requisitos) pode reduzir dramaticamente a accuracy, sugerindo dependência de memorização parcial em vez de compreensão abstrata de princípios.
Context window limitations restringem quanto código o modelo pode "ver" simultaneamente. Mesmo com janelas de 128K tokens, bases de código corporativas excedem facilmente esse limite. O modelo pode gerar código inconsistente com módulos que não estão no contexto atual, importar bibliotecas que não existem no projeto, ou ignorar convenções estabelecidas em arquivos que não foram incluídos na janela de contexto. Técnicas como RAG (Retrieval Augmented Generation) mitigam parcialmente esse problema, mas introduzem suas próprias complexidades.
"Entendimento" ou Estatística Sofisticada? O Debate que Importa
O debate sobre se LLMs "entendem" código é intenso tanto em IA quanto em filosofia da mente. Alguns argumentam que, por exibirem comportamentos consistentes em tarefas complexas, generalizarem para casos não vistos e corrigirem seus próprios erros, demonstram forma operacional de entendimento. Outros sustentam que, por basearem-se em correlações estatísticas e falharem em cenários que exigem raciocínio causal explícito, são apenas mecanismos sofisticados de associação de padrões.
No contexto de código, estudos como benchmarks semânticos sugerem que, embora LLMs sejam bons em completamento em contextos familiares, seu desempenho degrada quando se introduzem variações estruturais que não alteram a semântica. Isso reforça a visão de "compreensão" frágil e dependente de regularidades superficiais. Por outro lado, a capacidade de resolver 43% de problemas competitivos em AlphaCode 2 levanta a questão prática: se um modelo atua como competidor de alto nível, em que medida a distinção filosófica é operacionalmente relevante?
Para engenheiros, a resposta pragmática pode ser: a distinção importa menos que o comportamento. Se LLMs produzem código correto 67% das vezes em problemas padronizados e requerem supervisão para os 33% restantes, o modelo de uso fica claro — assistente poderoso, não substituto de julgamento humano. A pergunta "entende ou não" é menos relevante que "em quais contextos posso confiar?"
Se o output é útil e verificável, a natureza interna do processamento importa menos. Contudo, para aplicações críticas — sistemas de saúde, financeiros, infraestrutura — a ausência de compreensão genuína implica que verificação humana permanece insubstituível.
Se se assume que LLMs não "entendem", a postura recomendada é tratá-los como ferramentas assistivas mas não autônomas, exigindo revisão minuciosa em componentes críticos. Se se considera que "entendimento suficiente" foi alcançado para certas tarefas, pode-se delegar mais etapas, concentrando esforço humano em design de alto nível e validação. Entre esses extremos, muitas organizações adotam estratégias híbridas: uso intenso para tarefas rotineiras (boilerplate, testes, documentação) e uso cauteloso em funcionalidades núcleo.
Para a Engenharia de Software, na minha opinião, a implicação é clara: LLMs são ferramentas de amplificação cognitiva, não substitutos de julgamento. Eles aceleram tarefas onde padrões bem estabelecidos se aplicam, mas exigem supervisão crítica onde correção semântica é imprescindível.
A compreensão dos fundamentos técnicos de LLMs — arquitetura Transformer, mecanismos de atenção, pipelines de processamento — não é mero exercício acadêmico e nem tampouco são abstrações distantes do trabalho diário. É requisito para uso criterioso dessas ferramentas uma vez que são os mecanismos que determinam por que seu assistente de código às vezes produz soluções brilhantes e outras vezes, alucinações plausíveis. Engenheiros que compreendem por que LLMs falham (hallucination, context limits, pattern dependence) podem projetar workflows que maximizam benefícios enquanto mitigam riscos. A questão não é se adotar LLMs na Engenharia de Software — sua integração é inevitável — mas como fazê-lo com a criticidade que sistemas de software de qualidade exigem.
Compreender capacidades e limitações prepara você para as aplicações específicas que exploraremos nas próximas discussões: como LLMs transformam cada fase do SDLC. A tecnologia é poderosa, mas como toda ferramenta poderosa, seu valor depende de quem a empunha saber exatamente o que ela pode — e o que não pode — fazer.
REFERÊNCIAS PARA APROFUNDAMENTO
Papers Fundamentais
-
Vaswani, A. et al. (2017). Attention Is All You Need. NeurIPS.
- Por que ler: Paper seminal que introduz a arquitetura Transformer, base de todos os LLMs modernos.
- Link: https://arxiv.org/abs/1706.03762
-
Chen, M. et al. (2021). Evaluating Large Language Models Trained on Code. arXiv.
- Por que ler: Introduz Codex, o benchmark HumanEval e discute limitações de modelos de código.
- Link: https://arxiv.org/abs/2107.03374
-
Brown, T. et al. (2020). Language Models are Few-Shot Learners. NeurIPS.
- Por que ler: Introduz GPT-3 e demonstra capacidades de in-context learning.
- Link: https://arxiv.org/abs/2005.14165
Benchmarks e Avaliações
-
Aleithan, R. et al. (2024). SWE-Bench+: Enhanced Coding Benchmark for LLMs. arXiv.
- Por que ler: Analisa criticamente o SWE-bench e mostra como controle de vazamento reduz taxas de sucesso.
- Link: https://arxiv.org/abs/2410.06992
-
Gemini Team, Google (2023). AlphaCode 2 Technical Report.
- Por que ler: Mostra sistema baseado em Gemini alcançando desempenho superior a 85% dos competidores em programação competitiva.
- Link: https://storage.googleapis.com/deepmind-media/AlphaCode2/AlphaCode2_Tech_Report.pdf
-
EvalPlus Project (2024). HumanEval and MBPP Extended Leaderboards.
- Por que ler: Leaderboards atualizados para comparar GPT-4, CodeLlama e outros modelos.
- Link: https://evalplus.github.io/leaderboard.html
Segurança e Limitações
-
Fu, Y. et al. (2025). Security Weaknesses of Copilot-Generated Code in GitHub Projects: An Empirical Study. Preprint accepted for publication in ACM Transactions on Software Engineering and Methodology (TOSEM), 2025.
- Por que ler: Estudo sistemático identificando ~30% de snippets com fraquezas de segurança.
- Link: https://arxiv.org/abs/2310.02059
-
Haroon, S. et al. (2025). How Accurately Do Large Language Models Understand Code?
- Por que ler: Investiga "compreensão de código" usando mutações semânticas-preservadoras, destacando limitações de robustez.
- Link: https://arxiv.org/html/2504.04372v1
-
Krishna, A. et al. (2025). Importing Phantoms: Measuring LLM Package Hallucination Vulnerabilities. Machine Learning (cs.LG); Computation and Language (cs.CL); Cryptography and Security (cs.CR)
- Por que ler: Analisa package hallucination e como pode ser explorado em ataques à cadeia de suprimentos.
- Link: https://arxiv.org/html/2501.19012v1
Debate Filosófico e Surveys
-
Mitchell, M. (2023). The Debate over Understanding in AI's Large Language Models. PNAS.
- Por que ler: Survey acessível sobre o debate filosófico e técnico em torno de "entendimento" em LLMs.
- Link: https://www.pnas.org/doi/10.1073/pnas.2215907120
-
Fan, A. et al. (2023). Large Language Models for Software Engineering: Survey and Open Problems. arXiv.
- Por que ler: Survey abrangente sobre aplicações de LLMs em todas as fases do SDLC.
- Link: https://arxiv.org/abs/2310.03533
Material do Curso
-
Meira, S. (2024). The Impact of AI on Software Engineering: A Holistic Perspective. TDS Books.
- Por que ler: Contexto brasileiro e perspectiva estratégica sobre transformações no SDLC.
- Link: https://biblioteca.tds.company/tds-books-the-impact-of-artificial-intelligence-on-software-engineering-a-holistic-perspective
-
Garcia, V. & Medeiros, R. (2025). Sinfonia: Orquestrando a Inteligência Artificial. ASSERT Lab.
- Por que ler: Framework metodológico usado nos projetos da disciplina.
- Link: https://github.com/assertlab/sinfonia & https://a.co/d/23ouD46
Top comments (0)