3  Configuração do Ambiente de Desenvolvimento

Para trabalhar com LLMs, é necessário um ambiente robusto capaz de lidar com computação numérica intensiva (os tensores). Utilizaremos Python e PyTorch, o framework padrão da indústria para pesquisa em Deep Learning.

3.1 Pré-requisitos

  • Sistema Operacional: Linux (recomendado Ubuntu 20.04+) ou Windows com WSL2.
  • Hardware: GPU NVIDIA recomendada (com drivers CUDA instalados) para treinamento ou inferência eficiente.
  • Python: Versão 3.8 a 3.11.

3.2 Gerenciamento de Ambientes Virtuais

Nunca instale bibliotecas no ambiente global do Python. Utilize venv ou Conda.

# Criação do ambiente virtual (Linux/Mac)
# python3 -m venv .venv
# Ativação do ambiente
# source .venv/bin/activate

# No Windows (PowerShell):
python -m venv .venv
.\venv\Scripts\Activate.ps1

Exemplo simples em Python

print("Olá Mundo")

3.3 Instalação do PyTorch

A instalação do PyTorch depende da sua versão de CUDA. Visite pytorch.org para o comando exato. Abaixo, um exemplo padrão para CUDA 11.8:

# Instalação com suporte a GPU (NVIDIA)
pip install torch torchvision torchaudio 
  --index-url https://download.pytorch.org/whl/cu118

# Se você não possui GPU (apenas CPU - muito lento para LLMs):
# pip install torch torchvision torchaudio

3.4 Ecossistema Hugging Face

A biblioteca transformers da Hugging Face é a interface padrão para acessar modelos pré-treinados.

pip install transformers accelerate datasets torch
  • transformers: Carrega modelos e tokenizadores.
  • accelerate: Otimiza o treinamento e inferência em hardware variado (multi-GPU, mixed precision).
  • datasets: Facilita o download e processamento de grandes corpora de texto.

3.5 Script de Verificação (Sanity Check)

Crie um arquivo chamado check_env.py para validar se o PyTorch consegue acessar a GPU e se a biblioteca Transformers está funcional.

import torch
from transformers import pipeline

def check_environment():
    print("=== Verificação de Ambiente ===")
    
    # 1. Verificar Python e PyTorch
    print(f"PyTorch Version: {torch.__version__}")
    
    # 2. Verificar disponibilidade de CUDA (GPU)
    cuda_available = torch.cuda.is_available()
    print(f"CUDA Available: {cuda_available}")
    
    if cuda_available:
        print(f"GPU Device: {torch.cuda.get_device_name(0)}")
        print(f"VRAM: {torch.cuda.get_device_properties(0).total_memory 
            / 1e9:.2f} GB")
    else:
        print("AVISO: Executando em CPU. O desempenho será limitado.")

    # 3. Teste rápido de inferência com um modelo pequeno (GPT-2)
    print("\n=== Teste de Inferência (Hugging Face) ===")
    try:
        # Pipeline abstrai a complexidade de tokenização e modelo
        generator = pipeline('text-generation', model='gpt2', device=0 
            if cuda_available else -1)
        
        prompt = "The future of AI is"
        result = generator(prompt, max_length=30, max_new_tokens=30, num_return_sequences=1, 
            truncation=True)
        
        print(f"Prompt: {prompt}")
        print(f"Output: {result[0]['generated_text']}")
        print("\nSUCESSO: Ambiente configurado corretamente.")
        
    except Exception as e:
        print(f"""\nERRO: Falha ao carregar modelo ou executar inferência.
                  \nDetalhes: {e}""")

if __name__ == "__main__":
    check_environment()

Aqui estão alguns exemplos simples que ilustram conceitos básicos relacionados ao Transformer usando a biblioteca transformers da Hugging Face:

from transformers import AutoTokenizer, AutoModel
import torch

# Carregar tokenizer e modelo pré-treinado
model_name = "bert-base-uncased"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModel.from_pretrained(model_name)

# Texto de exemplo
text = "Transformers são incríveis para PLN!"

# Tokenização
inputs = tokenizer(text, return_tensors="pt")

# Obter embeddings do modelo
outputs = model(**inputs)
last_hidden_states = outputs.last_hidden_state

print(last_hidden_states.shape)  # (batch_size, sequence_length, hidden_size)
last_hidden_states

Este código mostra como carregar um modelo Transformer pré-treinado (BERT), tokenizar um texto e obter as representações internas (embeddings) do modelo.

Outro exemplo simples para usar um modelo Transformer para classificação de texto:

from transformers import pipeline

# Criar pipeline de classificação de sentimento
classifier = pipeline("sentiment-analysis")

# Classificar texto
result = classifier("Eu adoro aprender sobre Transformers!")
print(result)

Este exemplo usa um pipeline pronto para análise de sentimento, que internamente utiliza um modelo Transformer para classificar o texto.

NoteResumo

Configuramos um ambiente Python isolado, instalamos o PyTorch com suporte a CUDA e validamos a instalação executando um modelo GPT-2 básico.

3.6 Como tornar o experimento reproduzível

Um ambiente funcionar hoje não garante que funcionará após uma atualização. Registre a versão do Python, do PyTorch, do driver e das bibliotecas instaladas. Em projetos acadêmicos, salve as dependências em requirements.txt ou pyproject.toml e anote a semente aleatória usada nos experimentos. A semente não elimina todas as fontes de não determinismo em GPU, mas reduz variações difíceis de investigar.

Antes de treinar, estime a memória. Os parâmetros são apenas uma parte do consumo: ativações, gradientes e estados do otimizador também ocupam espaço. Um modelo em float32 usa quatro bytes por parâmetro somente para os pesos; durante o treinamento com AdamW, o total pode ser várias vezes maior. Começar com lote e sequência pequenos evita confundir falta de memória com erro no código.

TipChecklist de diagnóstico

Execute primeiro uma operação pequena na CPU, depois na GPU, confirme tensor.device e inspecione os formatos com tensor.shape. Se ocorrer out of memory, reduza batch_size ou seq_len antes de alterar a arquitetura.

3.7 Entendendo o caminho até a GPU

Uma GPU acelera o treinamento porque executa muitas operações numéricas semelhantes em paralelo. Entretanto, o ganho só aparece quando há trabalho suficiente para ocupar seus núcleos e quando a movimentação de dados não domina o tempo total. Um programa pode possuir GPU disponível e ainda ser lento por causa de lotes muito pequenos, carregamento de dados bloqueante ou cópias frequentes entre CPU e dispositivo.

Três recursos disputam espaço na memória: pesos, estados necessários à retropropagação e dados do lote. Precisão reduzida, acumulação de gradientes e gradient checkpointing atacam partes diferentes desse consumo. A precisão reduzida diminui bytes por número; a acumulação simula um lote maior com vários microlotes; o checkpointing economiza ativações e as recalcula durante o backward.

import torch

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
x = torch.randn(32, 128, 512, device=device)
print("dispositivo:", x.device)
print("memória do tensor (MiB):", x.nelement() * x.element_size() / 2**20)

Ao medir desempenho, sincronize a GPU antes e depois do trecho cronometrado, pois as operações CUDA são assíncronas. Faça algumas iterações de aquecimento e compare o mesmo cálculo; medir apenas a primeira execução inclui inicialização e compilação de kernels.

NoteDiagnóstico orientado por evidências

Se a GPU estiver pouco utilizada, investigue alimentação de dados e tamanho das operações. Se estiver sem memória, investigue formatos, ativações e lote. Se estiver totalmente utilizada, otimizações de kernel e precisão podem ser mais relevantes.