Allan Felps@allanfelps FLUXO DIGITAL @fluxodigitalmktevendas @hubfluxodigital
·
Módulo 3 — Técnico Avançado
⚡ 0 XP
3.01 · M3.1⏱ 15 min

Ambiente de desenvolvimento

Python, pip, venv, VS Code, Jupyter e .env — a base que evita 90% das dores.

Antes de qualquer linha de IA, você precisa do ambiente certo. Instale o Python (3.11+ é uma boa escolha) — no Windows, marque "Add Python to PATH" no instalador; no Mac e Linux, use o instalador oficial ou um gerenciador como o pyenv para controlar versões. O pip (gerenciador de pacotes) já vem junto. Confirme com python --version e pip --version no terminal.

Cada projeto deve ter seu próprio ambiente virtual (venv): uma pasta isolada com suas próprias bibliotecas e versões. Sem isso, instalar uma versão de uma biblioteca para o projeto A quebra o projeto B. Não é preferência, é higiene básica — todo projeto de IA sério usa venv. Você cria com python -m venv .venv e ativa antes de trabalhar.

# criar o ambiente (uma vez por projeto)
python -m venv .venv

# ativar (Mac/Linux)
source .venv/bin/activate
# ativar (Windows)
.venv\Scripts\activate

# instalar bibliotecas DENTRO do ambiente
pip install openai anthropic python-dotenv

# congelar as versões para reproduzir depois
pip freeze > requirements.txt

Há dois jeitos de rodar código. O Jupyter Notebook executa célula por célula, ideal para explorar dados e testar ideias de forma interativa. Os scripts .py são para código de produção, que roda do início ao fim. O VS Code é o editor mais usado: com extensões de Python e de IA (como assistentes de código), ele roda os dois e vira seu cockpit de desenvolvimento.

Suas chaves de API são senhas — e jamais devem ficar escritas no código. Guarde-as num arquivo .env e carregue-as com a biblioteca python-dotenv. O .env nunca vai para o GitHub (você o coloca no .gitignore, como veremos na aula 3.08). Vazar uma chave gera cobranças reais na sua conta — esse cuidado é inegociável.

# arquivo .env (NUNCA suba ao GitHub)
# OPENAI_API_KEY=sk-xxxxx

from dotenv import load_dotenv
import os

load_dotenv()                       # lê o .env
chave = os.getenv("OPENAI_API_KEY") # pega a chave com segurança
# use "chave" para autenticar — sem nunca escrevê-la no código
💡 Analogia · A bancada do marceneiro

Um marceneiro não começa a serrar antes de organizar a bancada, separar as ferramentas e prender a peça. O ambiente de dev é sua bancada: venv isola a peça, o .env guarda as ferramentas perigosas (chaves) em segurança, e o VS Code é a bancada onde tudo acontece. Pular essa etapa é serrar no colo — dá errado.

📌 Mini-caso real · A chave vazada que custou caro

É um clássico doloroso: o desenvolvedor coloca a chave de API direto no código, sobe ao GitHub público "só para testar", e em horas bots varrem o repositório, encontram a chave e disparam milhares de chamadas — gerando uma fatura inesperada de centenas ou milhares de dólares. O .env + .gitignore existe exatamente para que isso nunca aconteça com você.

✏️ Exercício prático · Monte seu ambiente
  1. Crie uma pasta de projeto, abra-a no VS Code e crie um venv com python -m venv .venv.
  2. Ative o venv e instale: pip install openai anthropic python-dotenv.
  3. Crie um arquivo .env com uma chave de teste e carregue-a com dotenv num script — imprimindo só os 4 primeiros caracteres para confirmar que leu.
Checklist da aula0/3
Tenho Python, pip e venv funcionando
Sei a diferença entre Jupyter e scripts .py
Guardo chaves em .env e nunca no código
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que ambientes virtuais (venv) são obrigatórios em projetos de IA?
A
Deixam o Python mais rápido
B
Isolam as dependências de cada projeto, evitando que versões conflitem entre projetos
C
São exigidos por lei
D
Substituem o Git
Selecione uma opção
3.02 · M3.1⏱ 18 min

Python básico

Variáveis, tipos, estruturas, funções e exceções — o que aparece em todo código de LLM.

Você não precisa virar programador profissional, mas precisa do Python que aparece em qualquer código de IA. Os fundamentos: variáveis e tipos (texto/str, número/int e float, booleano/bool), e as estruturas que você usará o tempo todo — listas (sequências ordenadas), dicionários (pares chave-valor, onipresentes em respostas de API), sets (conjuntos sem repetição) e tuplas (sequências imutáveis).

mensagens = [                       # lista de dicionários — formato de toda API de chat
    {"role": "system", "content": "Você é um assistente útil."},
    {"role": "user", "content": "Explique RAG em uma frase."},
]

config = {"model": "gpt-4o", "temperature": 0.2}  # dicionário
print(config["model"])              # acessa por chave -> gpt-4o

tags = {"ia", "rag", "ia"}          # set remove duplicatas -> {"ia", "rag"}

As funções empacotam lógica reutilizável. Em código de IA você verá muito *args (vários argumentos posicionais) e **kwargs (vários argumentos nomeados) — eles permitem funções flexíveis que repassam parâmetros adiante, padrão comum em bibliotecas de LLM. Entender isso te ajuda a ler a documentação e a customizar chamadas.

def chamar_modelo(prompt, **kwargs):
    # kwargs captura temperature, max_tokens, etc., e repassa
    params = {"temperature": 0.2, "max_tokens": 500}
    params.update(kwargs)           # sobrescreve com o que o usuário passar
    print(f"Chamando com: {params}")
    return f"resposta para: {prompt}"

chamar_modelo("Olá", temperature=0.9)  # ajusta só a temperatura

Loops (for, while), condicionais (if/elif/else) e o tratamento de erros (try/except/finally) são essenciais. Em IA, o try/except é vital: chamadas de API falham (rede, limite de taxa, timeout), e seu código precisa lidar com isso sem quebrar. As f-strings (f"texto {variavel}") são a forma moderna e legível de montar texto — você as usará para construir prompts dinamicamente.

import time

def chamar_com_retry(func, tentativas=3):
    for i in range(tentativas):
        try:
            return func()                 # tenta a chamada
        except Exception as e:
            print(f"Falha {i+1}: {e}")
            time.sleep(2 ** i)            # espera crescente (backoff)
    raise RuntimeError("Falhou após todas as tentativas")
💡 Analogia · O kit de ferramentas básico

Aprender o Python básico é como montar o kit essencial de um eletricista: você não precisa de todas as ferramentas do mundo, mas precisa do alicate, da chave de fenda e do multímetro. Listas, dicionários, funções e try/except são esse kit — com eles você já constrói praticamente qualquer integração de IA.

📌 Mini-caso real · O dicionário que está em toda API

Quando você chama qualquer LLM, envia uma lista de dicionários (as mensagens com "role" e "content") e recebe de volta um dicionário JSON com a resposta. Quem domina listas e dicionários lê e manipula essas respostas com naturalidade; quem não domina trava na primeira integração. É o conhecimento que mais "paga" no dia a dia de IA.

✏️ Exercício prático · Construa um prompt dinâmico
  1. Crie uma função que recebe um nome e um tópico e devolve a lista de mensagens (system + user) usando f-strings.
  2. Adicione um try/except que captura erro caso o tópico venha vazio.
  3. Teste com dois tópicos diferentes e imprima a lista de mensagens resultante.
Checklist da aula0/3
Domino listas, dicionários e f-strings
Sei escrever funções com argumentos flexíveis
Uso try/except para chamadas que podem falhar
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que try/except é especialmente importante em código que chama APIs de IA?
A
Deixa o código mais bonito
B
Porque chamadas de API falham (rede, rate limit, timeout) e o código precisa lidar sem quebrar
C
É obrigatório em Python
D
Aumenta a temperatura do modelo
Selecione uma opção
3.03 · M3.1⏱ 21 min

Python intermediário

Classes, decorators, generators e type hints — POO aplicada a IA.

A Programação Orientada a Objetos organiza código complexo em classes (moldes que agrupam dados e comportamento). Em IA, você verá classes para representar um agente, um cliente de API, uma ferramenta. Conceitos-chave: herança (uma classe especializa outra) e composição (uma classe usa outras). As dataclasses são um atalho do Python para criar classes que só guardam dados, com muito menos código.

from dataclasses import dataclass, field

@dataclass
class ConfigAgente:
    nome: str
    modelo: str = "gpt-4o"
    temperatura: float = 0.2
    ferramentas: list = field(default_factory=list)

agente = ConfigAgente(nome="Vendas", ferramentas=["busca", "crm"])
print(agente.modelo)        # gpt-4o (valor padrão)

Um decorator é uma função que "embrulha" outra para adicionar comportamento sem alterar o código original. Você os reconhece pelo @ acima de uma função. Em IA, eles aparecem o tempo todo: @tool (registra uma função como ferramenta de um agente, no LangChain), @property, @staticmethod. Entender o conceito destrava a leitura de praticamente todo framework moderno.

import functools

def logar(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print(f"-> chamando {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@logar
def somar(a, b):
    return a + b

somar(2, 3)   # imprime "-> chamando somar" e retorna 5

Um generator produz valores sob demanda, um de cada vez, em vez de criar tudo na memória de uma vez (isso é lazy evaluation). É exatamente o mecanismo por trás do streaming de LLMs — quando a resposta aparece palavra por palavra na tela, há um generator entregando os pedaços conforme chegam. Usa-se a palavra yield no lugar de return.

As type hints (nome: str, -> bool) indicam os tipos esperados. Não são obrigatórias, mas tornam o código autoexplicativo, ajudam o editor a pegar erros e são essenciais ao usar bibliotecas como o Pydantic (que você verá em structured output). Os context managers (o bloco with) garantem que recursos sejam abertos e fechados corretamente — você os usa ao abrir arquivos, por exemplo.

💡 Analogia · O decorator como embrulho de presente

Um decorator é como embrulhar um presente: o presente (a função) continua o mesmo por dentro, mas você adiciona uma camada por fora (o papel, o laço) que muda como ele se apresenta. @tool "embrulha" sua função Python e a apresenta ao agente como uma ferramenta utilizável — sem alterar o que a função faz internamente.

📌 Mini-caso real · Por que @tool está em todo agente

Quando você usa frameworks de agentes, transforma funções Python comuns em ferramentas que o LLM pode chamar simplesmente colocando @tool acima delas. Sem entender decorators, esse @ parece mágica incompreensível. Com o conceito claro, você lê e cria ferramentas com naturalidade — uma habilidade central na construção de agentes (M3.6 e M3.7).

✏️ Exercício prático · Crie uma ferramenta com decorator
  1. Escreva um decorator @cronometrar que mede e imprime quanto tempo uma função levou.
  2. Aplique-o a uma função que simula uma chamada lenta (use time.sleep).
  3. Crie uma @dataclass simples para representar uma "Ferramenta" com nome e descrição.
Checklist da aula0/3
Entendo classes, herança e dataclasses
Sei o que um decorator faz e por que @tool existe
Conheço generators (streaming) e type hints
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual mecanismo do Python está por trás do "streaming" de respostas de um LLM (texto aparecendo aos poucos)?
A
Classes
B
Generators (lazy evaluation, com yield)
C
Type hints
D
Decorators
Selecione uma opção
3.04 · M3.1⏱ 12 min

NumPy

Arrays, broadcasting e operações matriciais — e como embeddings vivem aqui.

O NumPy é a fundação numérica de toda a IA em Python. Sua estrela é o ndarray (array N-dimensional), muito mais eficiente que listas Python para cálculos: operações que levariam um loop lento em Python rodam de forma vetorizada, podendo ser dezenas a centenas de vezes mais rápidas. Isso porque o NumPy executa em código otimizado em C, sobre blocos de memória contíguos.

import numpy as np

v = np.array([1, 2, 3, 4])
print(v * 2)          # [2 4 6 8] — vetorizado, sem loop
print(v.mean())       # 2.5

# operações em milhões de números são quase instantâneas
grande = np.arange(1_000_000)
print((grande ** 2).sum())

O broadcasting é a regra que permite operar arrays de formatos diferentes sem escrever loops — por exemplo, somar um vetor a cada linha de uma matriz automaticamente. O slicing avançado (arr[1:3, :]) fatia os dados por dimensão. Esses dois recursos fazem você expressar cálculos complexos em uma linha legível, em vez de loops aninhados.

IA é, no fundo, álgebra linear em escala. O NumPy traz o produto escalar e matricial (np.dot, o operador @) e o módulo np.linalg para operações mais avançadas. Toda multiplicação de pesos numa rede neural, toda comparação de similaridade entre embeddings, é álgebra linear sobre arrays NumPy por baixo dos panos.

Lembre dos embeddings (texto virado em vetores de números). Na prática, um embedding é um array NumPy — uma lista de centenas ou milhares de floats. Para descobrir se dois textos são parecidos, você calcula a similaridade de cosseno entre seus embeddings, que é uma operação direta de álgebra linear. É a base técnica da busca semântica e do RAG (M3.4/M3.5).

import numpy as np

def cosseno(a, b):
    a, b = np.array(a), np.array(b)
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

emb1 = [0.10, 0.90, 0.20]   # "cachorro" (exemplo simplificado)
emb2 = [0.12, 0.88, 0.19]   # "cão"
emb3 = [0.95, 0.05, 0.30]   # "planilha"

print(round(cosseno(emb1, emb2), 3))  # ~0.999 (muito parecidos)
print(round(cosseno(emb1, emb3), 3))  # baixo (sentidos distintos)
💡 Analogia · A planilha turbinada

Pense no NumPy como uma planilha de cálculo absurdamente rápida e poderosa: em vez de digitar fórmula célula por célula (loop Python), você aplica uma operação à coluna inteira de uma vez (vetorização). O broadcasting é como arrastar uma fórmula para milhares de linhas automaticamente — só que em milissegundos.

📌 Mini-caso real · Por que toda biblioteca de IA depende do NumPy

Do scikit-learn ao PyTorch, praticamente toda biblioteca de IA usa NumPy (ou estruturas compatíveis) por baixo. Quando um modelo retorna um embedding, ele vem como array; quando você calcula a similaridade entre uma pergunta e mil documentos no RAG, é álgebra linear vetorizada com NumPy que torna isso rápido o suficiente para ser útil. É a engrenagem invisível de tudo.

✏️ Exercício prático · Calcule similaridade na prática
  1. Crie 3 vetores NumPy pequenos representando "embeddings" de 3 frases.
  2. Implemente a função de similaridade de cosseno (use o exemplo como base).
  3. Descubra qual par de frases é o "mais parecido" comparando os valores.
Checklist da aula0/3
Sei por que ndarray supera listas
Entendo broadcasting e slicing
Sei calcular similaridade de cosseno entre embeddings
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Como um embedding é representado tecnicamente para cálculos de similaridade?
A
Como uma imagem PNG
B
Como um array NumPy de números (vetor), comparado via similaridade de cosseno
C
Como um arquivo de texto puro
D
Como uma tabela SQL
Selecione uma opção
3.05 · M3.1⏱ 15 min

Pandas

Carregar, limpar e transformar dados — e preparar datasets para RAG e fine-tuning.

O Pandas é a ferramenta para dados estruturados (tabelas). Suas estruturas: o DataFrame (uma tabela com linhas e colunas, como uma planilha) e a Series (uma coluna isolada). Se você sabe pensar em planilhas, já entende o modelo mental — só que aqui com o poder da programação para automatizar tudo, sobre milhões de linhas, de forma reproduzível.

O Pandas lê praticamente qualquer fonte de dados tabular com uma linha: pd.read_csv, pd.read_json, pd.read_parquet, pd.read_excel. Isso é o ponto de partida de quase todo projeto de dados — trazer os dados de onde estão (uma planilha do cliente, um export do sistema, uma API) para dentro do Python, onde você pode trabalhá-los.

import pandas as pd

df = pd.read_csv("clientes.csv")
print(df.head())          # primeiras linhas
print(df.info())          # tipos e nulos por coluna

# filtrar clientes ativos de SP
ativos_sp = df[(df["status"] == "ativo") & (df["uf"] == "SP")]

# agrupar e somar receita por estado
receita = df.groupby("uf")["receita"].sum().sort_values(ascending=False)

A maior parte do trabalho com dados é limpeza: tratar valores nulos (fillna, dropna), remover duplicatas, padronizar texto, corrigir tipos. Depois vêm as transformações poderosas: groupby (agrupar e agregar, como "receita por estado"), merge (juntar tabelas, como um JOIN de SQL) e pivot (reorganizar). Dados do mundo real chegam sujos; saber limpá-los é metade do trabalho.

Aqui está a conexão direta com IA: antes de alimentar um RAG ou fazer fine-tuning, você precisa preparar os dados. Para RAG, isso pode ser limpar e estruturar os documentos antes do chunking. Para fine-tuning, é montar o dataset no formato exigido (geralmente JSONL com pares de pergunta/resposta). O Pandas é a ferramenta para transformar dados brutos e bagunçados no formato limpo que a IA consegue consumir.

import pandas as pd, json

df = pd.read_csv("perguntas_respostas.csv")  # colunas: pergunta, resposta

with open("treino.jsonl", "w", encoding="utf-8") as f:
    for _, linha in df.iterrows():
        exemplo = {"messages": [
            {"role": "user", "content": linha["pergunta"]},
            {"role": "assistant", "content": linha["resposta"]},
        ]}
        f.write(json.dumps(exemplo, ensure_ascii=False) + "\n")
💡 Analogia · A cozinha antes do prato

Dados brutos são como ingredientes recém-chegados da feira: terra na batata, folhas murchas, tudo misturado. O Pandas é a etapa de pré-preparo — lavar, descascar, picar e organizar — antes de cozinhar (treinar/alimentar a IA). Nenhum prato bom sai de ingredientes mal preparados, e nenhum modelo bom sai de dados sujos.

📌 Mini-caso real · "Garbage in, garbage out"

O ditado mais verdadeiro da IA: lixo entra, lixo sai. Projetos fracassam não por falta de modelo bom, mas por dados mal preparados — datas em formatos misturados, nomes duplicados, campos vazios. Profissionais experientes sabem que limpar e estruturar dados com Pandas costuma ser 70% do trabalho de um projeto de IA — e o que mais determina o resultado final.

✏️ Exercício prático · Limpe e prepare um dataset
  1. Pegue (ou crie) um CSV com algumas linhas bagunçadas: nulos, duplicatas, texto inconsistente.
  2. Use o Pandas para limpar: remover duplicatas, tratar nulos e padronizar uma coluna de texto.
  3. Exporte o resultado limpo para um novo arquivo (CSV ou JSONL no formato de fine-tuning).
Checklist da aula0/3
Sei carregar dados de CSV/JSON/Excel
Domino limpeza, groupby e merge
Sei preparar dados para RAG e fine-tuning
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que a preparação de dados com Pandas é tão crítica em projetos de IA?
A
Porque deixa o código bonito
B
Porque "garbage in, garbage out" — dados sujos arruínam qualquer modelo, e limpá-los é grande parte do trabalho
C
Porque substitui o modelo
D
Porque é exigência legal
Selecione uma opção
3.06 · M3.1⏱ 18 min

APIs com Python

requests, httpx, autenticação e o consumo das APIs de IA.

Quase toda IA na nuvem é acessada por REST APIs. O vocabulário mínimo: você faz uma requisição com um método (GET para ler, POST para enviar dados), passando headers (cabeçalhos, onde vai a autenticação) e um payload (o corpo, geralmente JSON, com o que você quer). A resposta vem com um status code: 200 = sucesso, 401 = não autorizado, 429 = limite atingido, 500 = erro do servidor.

As APIs de IA exigem autenticação, quase sempre via API key enviada como um Bearer token no header Authorization. É a sua "senha" de acesso (lembre: vinda do .env, nunca escrita no código). Sem ela, você recebe 401. Cada provider tem sua chave própria, e você gerencia limites e custos pela conta deles.

import os, requests
from dotenv import load_dotenv
load_dotenv()

resp = requests.post(
    "https://api.openai.com/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}"},
    json={
        "model": "gpt-4o",
        "messages": [{"role": "user", "content": "Diga olá em 3 línguas"}],
    },
    timeout=30,
)
resp.raise_for_status()                 # levanta erro se status != 2xx
print(resp.json()["choices"][0]["message"]["content"])

APIs impõem rate limits (limite de chamadas por minuto). Ao estourar, você recebe 429. Código de produção precisa de retry logic: ao receber 429 ou um erro temporário, esperar um pouco e tentar de novo, com backoff exponencial (esperas crescentes). Isso torna seu sistema resiliente a picos e instabilidades — diferença entre um protótipo frágil e um produto confiável.

O requests é o clássico para chamadas simples. O httpx é uma alternativa moderna que suporta async (chamadas paralelas, veremos na próxima aula) e streaming — receber a resposta em pedaços conforme o modelo gera, em vez de esperar tudo. O streaming é o que faz a resposta aparecer "digitando" na tela, melhorando muito a experiência em produtos de chat.

💡 Analogia · Pedir comida por aplicativo

Consumir uma API é como pedir num app de delivery: o método (POST) é fazer o pedido, o header com a chave é seu login, o payload é o que você pediu, e o status code é a confirmação ("pedido aceito" 200, "cartão recusado" 401, "loja lotada, tente depois" 429). O retry é remandar o pedido quando a loja estava momentaneamente cheia.

📌 Mini-caso real · O produto que caía toda sexta à tarde

Um app de IA funcionava bem, até que nos horários de pico começava a falhar para os usuários — eram os 429 (rate limit) não tratados, que quebravam as requisições. Ao adicionar retry com backoff exponencial, as chamadas que falhavam passavam a ser reenviadas automaticamente segundos depois, e os usuários nem percebiam. Resiliência simples, impacto enorme na confiabilidade.

✏️ Exercício prático · Chame uma API com resiliência
  1. Escreva uma função que chama uma API de LLM com requests, lendo a chave do .env.
  2. Adicione raise_for_status() e um try/except que trata o erro.
  3. Implemente um retry simples: se falhar, espere 2 segundos e tente mais uma vez.
Checklist da aula0/3
Entendo métodos, headers, payload e status codes
Sei autenticar com API key via Bearer token
Sei tratar rate limit (429) com retry e backoff
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que significa o status code 429 ao chamar uma API de IA, e como lidar?
A
Sucesso — nada a fazer
B
Limite de taxa atingido (rate limit) — esperar e tentar de novo com backoff
C
Chave inválida — trocar a senha
D
Servidor desligado para sempre
Selecione uma opção
3.07 · M3.1⏱ 21 min

Async Python

asyncio, await e paralelismo — por que agentes precisam disso para escalar.

Código síncrono faz uma coisa de cada vez: chama a API, espera parado a resposta, só então segue. Se você precisa de 10 respostas e cada uma leva 2 segundos, são 20 segundos esperando em fila. Código assíncrono permite iniciar as 10 chamadas e esperar todas em paralelo — as 10 voltam em ~2 segundos, não 20. Em IA, onde se espera muito por respostas de LLM, isso é transformador.

O asyncio é o sistema de concorrência do Python. Você marca uma função com async def (vira uma coroutine) e usa await para esperar uma operação sem bloquear as outras. Por baixo, um event loop coordena tudo, alternando entre tarefas enquanto elas esperam. Não é paralelismo de CPU — é a arte de não ficar parado esperando I/O (rede), e isso é exatamente o gargalo das chamadas de LLM.

import asyncio

async def perguntar(cliente, pergunta):
    resp = await cliente.chat(pergunta)   # await: não bloqueia as outras
    return resp

async def main(cliente, perguntas):
    tarefas = [perguntar(cliente, p) for p in perguntas]
    respostas = await asyncio.gather(*tarefas)  # roda todas em paralelo
    return respostas

# 10 perguntas voltam em ~o tempo de UMA, não de dez somadas

O asyncio.gather() é o coração prático: ele dispara várias coroutines de uma vez e espera todas terminarem. Combinado com clientes assíncronos (como aiohttp ou o httpx async), você paraleliza chamadas de rede com elegância. É o padrão para, por exemplo, processar 100 documentos com um LLM em lote, ou consultar várias APIs ao mesmo tempo.

Agentes (M3.7) frequentemente precisam fazer várias chamadas: consultar múltiplas ferramentas, processar vários itens, ou rodar sub-agentes em paralelo. Sem async, cada uma dessas esperas se soma e o agente fica lento e caro de escalar. Com async, as esperas se sobrepõem, e o sistema atende mais usuários com a mesma infraestrutura. É a diferença entre um agente que escala e um que engasga.

💡 Analogia · O garçom eficiente

Um garçom síncrono anota o pedido da mesa 1, vai à cozinha, espera o prato ficar pronto parado, serve, e só então atende a mesa 2 — péssimo. Um garçom assíncrono anota a mesa 1, manda para a cozinha, e enquanto cozinha já atende as mesas 2, 3 e 4, servindo cada prato quando fica pronto. O async deixa seu código ser esse garçom eficiente.

📌 Mini-caso real · De 50 minutos para 1

Imagine processar 1.500 avaliações de produtos com um LLM, cada chamada levando ~2 segundos. Em código síncrono, são ~50 minutos em fila. Reescrevendo com asyncio.gather em lotes paralelos, o mesmo trabalho cai para poucos minutos. É o tipo de ganho que torna viável uma tarefa que antes era proibitivamente lenta — e que diferencia código amador de código de produção.

✏️ Exercício prático · Paralelize chamadas
  1. Escreva duas versões de uma função que "processa" uma lista de itens com uma espera simulada (asyncio.sleep).
  2. Uma versão síncrona (em loop) e uma assíncrona com asyncio.gather.
  3. Meça e compare o tempo total das duas — observe o ganho da versão paralela.
Checklist da aula0/3
Entendo a diferença síncrono vs. assíncrono
Sei usar async/await e asyncio.gather
Entendo por que agentes precisam de async para escalar
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual o principal ganho do código assíncrono em aplicações de IA?
A
Deixa a CPU mais potente
B
Permite iniciar várias chamadas de LLM e esperá-las em paralelo, em vez de uma de cada vez
C
Elimina a necessidade de internet
D
Aumenta a qualidade das respostas
Selecione uma opção
3.08 · M3.1⏱ 12 min

Git e GitHub

Versionamento, branches, .gitignore e a estrutura de um repositório de IA.

O Git é o sistema de controle de versão padrão da indústria. Ele guarda o histórico do seu código, permitindo voltar a qualquer ponto, ver o que mudou e quando, e — crucial — colaborar sem sobrescrever o trabalho dos outros. O GitHub é a plataforma na nuvem onde esses repositórios vivem, viram portfólio e se tornam colaborativos. Para quem quer trabalhar com IA, ter projetos no GitHub é praticamente obrigatório.

O fluxo básico cabe em poucos comandos: git init (criar o repositório), git add (preparar mudanças), git commit (salvar um ponto no histórico com uma mensagem), git push/git pull (enviar/trazer do GitHub). E o conceito de branches (branch, merge): criar uma linha paralela para desenvolver algo sem mexer no código principal, e depois fundir. Não precisa decorar tudo — o uso diário fixa.

git init                       # iniciar o repositório
git add .                      # preparar todas as mudanças
git commit -m "feat: pipeline RAG inicial"
git branch -M main
git remote add origin <url-do-github>
git push -u origin main        # enviar para o GitHub

# trabalhar numa funcionalidade isolada
git checkout -b nova-ferramenta
# ...código... depois: add, commit, e merge na main

Esta é a regra mais importante para quem trabalha com IA: NUNCA suba o arquivo .env (com suas chaves) nem dados sensíveis ao GitHub. O .gitignore é um arquivo que lista o que o Git deve ignorar. Para IA, ele deve conter pelo menos .env, a pasta do venv (.venv/), caches e dados grandes. Uma chave vazada em repositório público é varrida por bots em minutos e pode gerar uma fatura enorme.

# segredos — NUNCA versionar
.env
*.key

# ambiente virtual
.venv/
__pycache__/
*.pyc

# dados e modelos pesados
data/
*.csv
chroma_db/

# notebooks com saídas grandes (opcional)
.ipynb_checkpoints/

Um repositório bem organizado comunica profissionalismo e facilita a vida. O padrão inclui: um README.md claro (o que é, como rodar), requirements.txt (as dependências), .gitignore, .env.example (um modelo do .env, sem as chaves reais), e o código organizado em pastas (por exemplo src/). Uma noção de GitHub Actions (automação que roda testes a cada push) é o passo seguinte, mais avançado.

💡 Analogia · O "salvar" com histórico infinito do videogame

O Git é como os save points de um jogo, mas infinitamente melhor: cada commit é um save ao qual você pode voltar a qualquer momento, com um rótulo do que mudou. As branches são como jogar uma fase alternativa sem perder seu progresso principal. E o .gitignore é a regra de nunca salvar dados que poderiam te prejudicar (suas senhas).

📌 Mini-caso real · O portfólio que conseguiu a vaga

No mercado de IA, recrutadores e clientes olham o GitHub antes do currículo. Um candidato com 3 ou 4 repositórios bem organizados — README claro, código limpo, .gitignore correto — comunica competência de forma que nenhuma lista de cursos consegue. O Git não é só ferramenta de código; é a vitrine onde seu trabalho vira prova concreta de capacidade.

✏️ Exercício prático · Suba seu primeiro projeto de IA
  1. Inicie um repositório Git numa pasta de projeto e crie um .gitignore incluindo .env e .venv/.
  2. Faça o primeiro commit e crie um README.md simples explicando o projeto.
  3. Crie um repositório no GitHub e faça o push — confirme que o .env NÃO apareceu lá.
Checklist da aula0/3
Domino o fluxo add/commit/push e branches
Tenho um .gitignore que protege o .env
Sei a estrutura padrão de um repositório de IA
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual o cuidado mais crítico com o .gitignore em projetos de IA?
A
Ignorar o README
B
Garantir que o .env (com as chaves de API) e dados sensíveis NUNCA sejam enviados ao GitHub
C
Ignorar o requirements.txt
D
Versionar tudo, sem exceção
Selecione uma opção
3.09 · M3.2⏱ 15 min

Matemática essencial para IA

Álgebra linear, probabilidade e estatística — a intuição, sem terror.

Você não precisa virar matemático, mas precisa da intuição. Um vetor é uma lista de números que representa algo (um embedding é um vetor). Uma matriz é uma tabela de números (um lote de embeddings, ou os pesos de uma camada). O produto escalar (dot product) entre dois vetores mede o quanto eles "apontam na mesma direção" — é exatamente o que está por trás da similaridade entre textos.

A multiplicação de matrizes é a operação mais executada em IA. Cada camada de uma rede neural, no fundo, multiplica a entrada por uma matriz de pesos. Bilhões dessas operações acontecem a cada inferência de um LLM. Você não vai calcular à mão — NumPy e PyTorch fazem —, mas entender que "a rede é, essencialmente, multiplicações de matrizes encadeadas" desmistifica boa parte do que parece magia.

IA lida com incerteza, e a probabilidade é a forma de raciocinar sobre ela. As distribuições descrevem como valores se espalham. O Teorema de Bayes formaliza como atualizar uma crença diante de nova evidência ("dado que vi isto, quão provável é aquilo?"). Quando um LLM "escolhe" a próxima palavra, ele está, no fundo, lidando com uma distribuição de probabilidade sobre os tokens possíveis.

A derivada mede a inclinação de uma função; o gradiente é a derivada em várias dimensões, apontando a direção de maior crescimento. No treino, o modelo calcula o gradiente do erro e dá um passo na direção oposta para reduzi-lo — é o "descer a montanha em direção ao vale" (gradient descent). Toda a aprendizagem de uma rede é isso, repetido milhões de vezes. Esse é o conceito que conecta cálculo a "a IA aprendeu".

💡 Analogia · Descer a montanha na neblina

Treinar um modelo é como descer uma montanha numa neblina densa, querendo chegar ao ponto mais baixo (menor erro). Você não vê o caminho todo, mas sente a inclinação sob os pés (o gradiente) e dá um passo na direção que desce. Repete passo após passo até o chão ficar plano (mínimo). Gradient descent é literalmente isso.

📌 Mini-caso real · Por que isso aparece em todo paper

Quando você abrir um paper de IA — mesmo só para entender a ideia —, vai cruzar com vetores, matrizes, probabilidades e gradientes. Quem tem a intuição desses quatro conceitos lê o paper e capta o essencial; quem não tem, trava na primeira fórmula. Não é sobre calcular: é sobre reconhecer o que cada símbolo significa e seguir o raciocínio.

✏️ Exercício prático · Ganhe a intuição
  1. Com NumPy, crie dois vetores e calcule o produto escalar com np.dot — relacione com "apontar na mesma direção".
  2. Pesquise/relembre o Teorema de Bayes com um exemplo simples (ex.: teste médico com falso positivo).
  3. Em uma frase, explique com suas palavras o que o gradiente faz no treino de um modelo.
Checklist da aula0/3
Tenho intuição de vetores, matrizes e produto escalar
Entendo probabilidade e Bayes em alto nível
Sei o que gradiente/derivada fazem no treino
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
No treino de uma rede neural, para que serve o gradiente?
A
Para criar mais dados
B
Para indicar a direção que reduz o erro, guiando o ajuste dos pesos (gradient descent)
C
Para aumentar a temperatura
D
Para comprimir o modelo
Selecione uma opção
3.10 · M3.2⏱ 18 min

Scikit-learn

O pipeline padrão de ML: dados → features → modelo → avaliação, sem vazamento.

O scikit-learn é a biblioteca padrão para ML clássico em Python. Ela impõe um fluxo consistente que vale para quase todo problema tabular: separar os dados, preparar as features (variáveis de entrada), treinar um modelo, e avaliar. Dominar esse fluxo é mais importante que decorar algoritmos — é o esqueleto reutilizável de qualquer projeto de ML.

A regra número um do ML: nunca avalie o modelo nos mesmos dados em que ele treinou. Você separa os dados em treino (para aprender) e teste (para avaliar honestamente, em dados nunca vistos). O train_test_split faz isso. Avaliar no treino dá uma nota inflada e enganosa — o modelo pode ter apenas "decorado", e você só descobre quando ele falha no mundo real.

from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42)

# Pipeline: escalonamento + modelo, evitando vazamento
pipe = Pipeline([
    ("scaler", StandardScaler()),
    ("model", LogisticRegression(max_iter=1000)),
])
pipe.fit(X_train, y_train)
print("Acurácia no teste:", pipe.score(X_test, y_test))

O data leakage (vazamento de dados) é o erro mais traiçoeiro do ML: quando informação do teste "vaza" para o treino, inflando a nota. O caso clássico é escalonar os dados (StandardScaler) antes de separar treino/teste. O Pipeline resolve isso elegantemente: ele aplica as transformações dentro de cada fold, na ordem correta. O ColumnTransformer permite tratar colunas numéricas e categóricas de formas diferentes.

A cross_val_score (validação cruzada) avalia o modelo em várias divisões diferentes dos dados, dando uma estimativa mais confiável que um único teste. O GridSearchCV automatiza a busca pelos melhores hiperparâmetros (configurações do modelo), testando combinações e escolhendo a melhor por validação cruzada. Juntos, são o que separa um modelo "ajustado no olho" de um modelo otimizado de forma rigorosa.

💡 Analogia · Estudar com simulados, não com o gabarito

Avaliar o modelo no treino é como "estudar" decorando o gabarito da prova — a nota é alta, mas você não aprendeu. O train_test_split é fazer simulados com questões novas: só assim você sabe se realmente aprendeu. A validação cruzada é fazer vários simulados diferentes para ter certeza de que não foi sorte.

📌 Mini-caso real · O modelo de 99% que falhou em produção

Um caso clássico: a equipe celebra um modelo com 99% de acurácia, coloca em produção e ele falha miseravelmente. O motivo quase sempre é data leakage — uma informação que não existiria no momento real da previsão vazou para o treino. O Pipeline do scikit-learn e a disciplina de separar treino/teste corretamente existem justamente para evitar essa armadilha cara.

✏️ Exercício prático · Monte um pipeline correto
  1. Pegue um dataset simples (pode ser um embutido do scikit-learn, como o de íris ou vinho).
  2. Separe com train_test_split e monte um Pipeline com StandardScaler + um classificador.
  3. Avalie com cross_val_score e compare com a nota num único teste.
Checklist da aula0/3
Sei o fluxo dados→features→modelo→avaliação
Nunca avalio no treino (train_test_split)
Uso Pipeline para evitar data leakage
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que é "data leakage" e como o Pipeline do scikit-learn ajuda a evitá-lo?
A
É um vazamento de memória; o Pipeline acelera o código
B
É quando informação do teste vaza para o treino, inflando a nota; o Pipeline aplica transformações na ordem certa, dentro de cada fold
C
É um erro de digitação
D
É quando o modelo é pequeno demais
Selecione uma opção
3.11 · M3.2⏱ 21 min

Regressão e Classificação

LinearReg, LogisticReg, KNN, SVM, Naive Bayes — e overfitting.

O ML supervisionado se divide em dois: regressão (prever um número contínuo — preço, temperatura, receita) e classificação (prever uma categoria — spam/não-spam, aprovado/reprovado, positivo/negativo). Identificar em qual tipo seu problema cai é o primeiro passo, pois determina os algoritmos e as métricas.

Um mapa rápido: Regressão Linear (prever números, relação simples), Regressão Logística (apesar do nome, é classificação — a base de muitos classificadores), KNN (classifica pelo "voto dos vizinhos mais próximos", simples e intuitivo), SVM (traça a melhor fronteira entre classes, forte em dados de alta dimensão) e Naive Bayes (rápido e surpreendentemente bom para texto, como filtros de spam). Comece pelo mais simples que resolve.

Os dois inimigos do ML. Overfitting: o modelo "decora" o treino, indo muito bem nele e mal em dados novos — complexo demais. Underfitting: o modelo é simples demais e não captura nem o treino. O alvo é o equilíbrio: generalizar bem para dados novos. Você detecta overfitting quando a nota no treino é ótima mas a no teste é ruim — o sinal de alerta clássico.

A regularização combate o overfitting penalizando a complexidade do modelo. A L1 (Lasso) tende a zerar pesos de features inúteis (faz seleção de variáveis); a L2 (Ridge) encolhe os pesos suavemente. É como dizer ao modelo "seja bom, mas não exagere na complexidade". Um pouco de regularização quase sempre melhora a generalização.

from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.pipeline import Pipeline

reviews = ["produto excelente, recomendo", "horrível, nao funciona",
           "adorei a qualidade", "veio quebrado, pessimo"]
rotulos = ["positivo", "negativo", "positivo", "negativo"]

modelo = Pipeline([
    ("tfidf", TfidfVectorizer()),     # texto -> features numéricas
    ("nb", MultinomialNB()),          # Naive Bayes: ótimo para texto
])
modelo.fit(reviews, rotulos)
print(modelo.predict(["chegou rapido e funciona muito bem"]))
💡 Analogia · Estudar a prova certa

Overfitting é o aluno que decora exatamente as questões do ano passado: tira nota máxima se a prova repetir, mas se afunda com questões novas. Underfitting é quem mal estudou. O bom aluno (modelo regularizado) entendeu os conceitos e resolve questões inéditas — generaliza. A regularização é o professor dizendo "entenda o conceito, não decore".

📌 Mini-caso real · O classificador de sentimento que vira produto

Um classificador de sentimento sobre reviews de produtos — exatamente o do exemplo — é um projeto real e útil: uma loja pode processar milhares de avaliações automaticamente, descobrindo o que clientes amam e odeiam sem ler tudo manualmente. Naive Bayes com TF-IDF resolve isso de forma leve e rápida, sem precisar de um LLM caro. ML clássico ainda ganha em muitos casos práticos.

✏️ Exercício prático · Construa um classificador de sentimento
  1. Monte uma pequena lista de frases (reviews) rotuladas como positivo/negativo em PT-BR.
  2. Crie o Pipeline TF-IDF + Naive Bayes (use o exemplo) e treine.
  3. Teste com 3 frases novas e veja se classifica corretamente — analise os erros.
Checklist da aula0/3
Diferencio regressão de classificação
Sei quando usar cada algoritmo básico
Reconheço e combato overfitting com regularização
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Como você reconhece o "overfitting" em um modelo?
A
Nota ruim tanto no treino quanto no teste
B
Nota ótima no treino mas ruim no teste — o modelo decorou em vez de generalizar
C
Nota ótima no teste e ruim no treino
D
O modelo treina rápido
Selecione uma opção
3.12 · M3.2⏱ 12 min

Árvores, Random Forest e XGBoost

O rei dos dados tabulares — e por que bate redes neurais neles.

Uma árvore de decisão faz perguntas sequenciais sobre os dados ("a renda é maior que X? então pergunte sobre a idade...") até chegar a uma decisão. É intuitiva e interpretável — você consegue seguir o raciocínio. Sozinha, porém, tende ao overfitting. A mágica vem ao combinar muitas árvores, e é aí que entram os métodos campeões.

O Random Forest treina muitas árvores, cada uma vendo uma parte aleatória dos dados, e combina os votos. O resultado é robusto e raramente sofre overfitting grave — a diversidade das árvores cancela os erros individuais. É um ótimo "primeiro modelo sério" para dados tabulares: confiável, pouco sensível a ajustes e fácil de usar.

O gradient boosting constrói árvores em sequência, cada uma corrigindo os erros da anterior. As implementações XGBoost, LightGBM e CatBoost são extremamente otimizadas e dominam competições de dados (como as do Kaggle) há anos. Diferenças práticas: LightGBM é muito rápido em dados grandes; CatBoost lida bem com variáveis categóricas; XGBoost é o clássico robusto.

Um insight que surpreende iniciantes: para dados tabulares estruturados (planilhas, bancos de dados), o XGBoost e companhia frequentemente superam redes neurais profundas — sendo mais rápidos, mais baratos e mais fáceis de ajustar. Deep Learning brilha em dados não estruturados (imagem, texto, áudio); para tabelas, os métodos de boosting costumam ser a escolha certa. Não use um canhão (rede neural) para matar uma formiga que o boosting resolve melhor.

Uma vantagem desses modelos é a feature importance: eles dizem quais variáveis mais pesaram na decisão. Isso é ouro para negócios — não só prever que um cliente vai cancelar, mas saber por quê (tempo de uso, número de reclamações, etc.). Interpretabilidade transforma uma previsão num insight acionável.

from xgboost import XGBClassifier
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

modelo = XGBClassifier(n_estimators=200, max_depth=4, learning_rate=0.1)
modelo.fit(X_train, y_train)
print("Acurácia:", modelo.score(X_test, y_test))

# quais variáveis mais importam?
for nome, imp in zip(X.columns, modelo.feature_importances_):
    print(f"{nome}: {imp:.3f}")
💡 Analogia · Um especialista vs. um júri

Uma árvore sozinha é um único especialista — pode ter manias e errar. O Random Forest é um júri grande e diverso: cada jurado erra um pouco, mas o veredito coletivo é sólido. O boosting é um time onde cada membro estuda especificamente os erros do anterior para corrigi-los — virando, juntos, quase imbatíveis em dados tabulares.

📌 Mini-caso real · Por que o Kaggle ama o XGBoost

Por mais de uma década, o XGBoost e seus primos (LightGBM, CatBoost) foram os vencedores recorrentes de competições de dados tabulares no Kaggle. Enquanto o hype fala só de redes neurais e LLMs, no dia a dia de previsão sobre dados de planilha — churn, fraude, demanda, crédito — o boosting segue sendo a ferramenta que mais entrega resultado com menos esforço. Saber disso evita complicar à toa.

✏️ Exercício prático · Compare modelos em dados tabulares
  1. Pegue um dataset tabular e treine um Random Forest e um XGBoost.
  2. Compare a acurácia dos dois no conjunto de teste.
  3. Use a feature_importances_ para listar as 3 variáveis mais influentes — e interprete o que significam.
Checklist da aula0/3
Entendo árvores, Random Forest e boosting
Sei por que boosting domina dados tabulares
Sei extrair e interpretar feature importance
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Para dados tabulares estruturados, o que costuma ser verdade?
A
Redes neurais profundas sempre vencem
B
XGBoost e gradient boosting frequentemente superam redes neurais, sendo mais rápidos e baratos
C
Só LLMs funcionam
D
Nenhum modelo funciona bem
Selecione uma opção
3.13 · M3.2⏱ 15 min

Clustering e redução de dimensionalidade

K-Means, DBSCAN, PCA, UMAP — achar padrões sem rótulos.

Diferente da classificação (com rótulos), aqui os dados não têm gabarito — você quer que o algoritmo encontre estrutura sozinho. As duas grandes famílias: clustering (agrupar itens parecidos) e redução de dimensionalidade (comprimir muitas variáveis em poucas, preservando o essencial). São ferramentas de descoberta: revelam padrões que você não sabia que existiam.

O K-Means agrupa os dados em K clusters (você define o K), atribuindo cada ponto ao centro mais próximo. É rápido e popular, mas exige saber quantos grupos quer e assume clusters "redondos". O DBSCAN agrupa por densidade, descobre o número de clusters sozinho e identifica outliers (pontos que não pertencem a nenhum grupo) — ótimo para detecção de anomalias.

O PCA reduz dimensões mantendo a maior variância — útil para remover ruído e acelerar modelos. O UMAP e o t-SNE são feitos para visualização: pegam dados de altíssima dimensão (como embeddings de mil dimensões) e os projetam em 2D para você ver os agrupamentos num gráfico. São a forma de "enxergar" o que um LLM acha parecido.

Aqui o elo com IA moderna: lembre que embeddings são vetores de centenas/milhares de dimensões — impossíveis de visualizar diretamente. Aplicando UMAP ou t-SNE sobre embeddings de, digamos, milhares de tickets de suporte, você os projeta em 2D e os temas se agrupando (cobrança aqui, problema técnico ali). É uma forma poderosa de explorar dados de texto sem ler tudo.

import numpy as np
from sklearn.cluster import KMeans

# embeddings já calculados para N textos (cada um é um vetor)
embeddings = np.array(lista_de_embeddings)   # shape: (N, dim)

kmeans = KMeans(n_clusters=4, random_state=42, n_init=10)
grupos = kmeans.fit_predict(embeddings)

for i, texto in enumerate(textos):
    print(f"[grupo {grupos[i]}] {texto[:50]}")
💡 Analogia · Organizar uma biblioteca bagunçada

Clustering é entrar numa biblioteca com livros jogados e, sem ler nenhuma etiqueta, agrupá-los por semelhança até emergirem seções naturais (romances aqui, técnicos ali). Redução de dimensionalidade é fazer um mapa 2D dessa biblioteca enorme para você ver, de relance, onde estão os agrupamentos — sem percorrer cada prateleira.

📌 Mini-caso real · Descobrindo temas em milhares de tickets

Uma empresa de suporte tinha dezenas de milhares de tickets e queria saber sobre o que os clientes mais reclamavam — sem ler todos. Gerando embeddings dos tickets, agrupando com K-Means e visualizando com UMAP, descobriram clusters claros (cobrança, bug X, dúvida de uso), priorizando o que mais importava. Aprendizado não-supervisionado transformou texto caótico em insight acionável.

✏️ Exercício prático · Encontre grupos sem rótulos
  1. Gere embeddings de ~10 frases curtas de 2 ou 3 temas distintos.
  2. Aplique K-Means para agrupá-las e veja se os grupos batem com os temas.
  3. Reduza para 2D com PCA ou UMAP e plote — observe os agrupamentos visualmente.
Checklist da aula0/3
Entendo clustering e redução de dimensionalidade
Sei a diferença entre K-Means e DBSCAN
Sei visualizar embeddings com UMAP/t-SNE
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Para que serve aplicar UMAP ou t-SNE sobre embeddings de LLMs?
A
Para treinar o LLM
B
Para projetar vetores de alta dimensão em 2D e visualizar os agrupamentos
C
Para criptografar os dados
D
Para aumentar a dimensão dos embeddings
Selecione uma opção
3.14 · M3.2⏱ 18 min

Métricas de avaliação

Accuracy, Precision, Recall, F1, AUC-ROC, RMSE — e por que accuracy mente.

A acurácia (% de acertos) parece a métrica óbvia, mas pode mentir feio em dados desbalanceados. Imagine detectar fraude, onde 99% das transações são legítimas: um modelo que sempre diz "não é fraude" acerta 99% — acurácia altíssima, e totalmente inútil, porque nunca pega uma fraude. Por isso, em muitos problemas reais, a acurácia sozinha é uma armadilha perigosa.

A matriz de confusão mostra os quatro resultados possíveis numa classificação: verdadeiros positivos, verdadeiros negativos, falsos positivos e falsos negativos. Quase toda métrica honesta deriva dela. Entendê-la é o primeiro passo para sair da ilusão da acurácia e medir o que realmente importa para o seu problema.

Duas métricas que medem coisas diferentes. Precision (precisão): dos que o modelo disse serem positivos, quantos realmente eram? (evita falsos alarmes). Recall (revocação): dos que realmente eram positivos, quantos o modelo pegou? (evita deixar passar). Há um trade-off: aumentar um costuma baixar o outro. Qual priorizar depende do custo do erro — e essa é uma decisão de negócio, não técnica.

O F1-score combina precision e recall num número (média harmônica), útil quando você quer equilíbrio. O AUC-ROC mede a capacidade do modelo de separar as classes em vários limiares. Para regressão (prever números), usam-se RMSE e MAE, que medem o tamanho médio do erro. Reportar a métrica certa, e não só a que parece bonita, é sinal de maturidade profissional.

A escolha depende do custo do erro. Em detecção de fraude ou diagnóstico de doença, um falso negativo (deixar passar) é gravíssimo — prioriza-se recall (pegar o máximo possível, mesmo com alguns alarmes falsos). Em filtros que bloqueiam conteúdo, um falso positivo (bloquear algo legítimo) incomoda — prioriza-se precision. Definir isso antes de treinar evita otimizar a métrica errada.

💡 Analogia · O detector de incêndio

Um detector que dispara com qualquer fumacinha tem recall altíssimo (não deixa passar incêndio) mas precision baixa (muito alarme falso, queimou torrada). Um que só dispara com fogo grande tem precision alta mas pode deixar passar um princípio de incêndio (recall baixo). Onde você regula o sensor depende do que custa mais caro: o alarme falso ou o incêndio não detectado.

📌 Mini-caso real · A acurácia que escondia o desastre

Uma equipe entregou um modelo de detecção de fraude com 99,2% de acurácia e comemorou — até perceberem que ele praticamente nunca detectava fraude real (recall pífio), apenas acertava as transações normais. Trocando a métrica de avaliação para recall e F1, o problema ficou óbvio. A lição: a métrica errada esconde o fracasso; a certa o revela. Sempre escolha a métrica pelo custo do erro.

✏️ Exercício prático · Escolha a métrica certa
  1. Para 3 cenários (detecção de fraude, filtro de spam, recomendação de produto), decida: priorizar precision ou recall? Justifique pelo custo do erro.
  2. Treine um classificador simples e gere a matriz de confusão com o scikit-learn.
  3. Calcule precision, recall e F1 — e explique qual deles você reportaria para o cenário escolhido.
Checklist da aula0/3
Sei por que accuracy pode enganar
Entendo a matriz de confusão e precision vs. recall
Sei escolher a métrica pelo custo do erro
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que a acurácia pode ser enganosa em detecção de fraude?
A
Porque é difícil de calcular
B
Porque com classes desbalanceadas, sempre prever "não é fraude" dá acurácia altíssima e é inútil
C
Porque fraude não existe
D
Porque acurácia só funciona em regressão
Selecione uma opção
3.15 · M3.3⏱ 21 min

PyTorch

Tensores, autograd e o grafo computacional — a base do Deep Learning.

O PyTorch é o framework de Deep Learning mais usado em pesquisa e cada vez mais em produção. Sua estrutura central é o tensor (torch.Tensor): como um array NumPy, mas com dois superpoderes — pode rodar na GPU (acelerando cálculos centenas de vezes) e rastreia operações para calcular gradientes automaticamente. Se você entende NumPy, já entende 80% dos tensores.

A mágica do PyTorch é o autograd. Quando você marca um tensor com requires_grad=True, o PyTorch monta nos bastidores um grafo computacional de todas as operações. Ao chamar .backward(), ele calcula automaticamente os gradientes de tudo — aquele "descer a montanha" da aula 3.09, sem você derivar nada à mão. É o que torna treinar redes complexas viável.

import torch

x = torch.tensor(2.0, requires_grad=True)
y = x**2 + 3*x + 1          # monta o grafo computacional

y.backward()                # calcula dy/dx automaticamente
print(x.grad)               # 2*x + 3 = 7.0  (o gradiente!)

Redes neurais fazem bilhões de operações; a GPU as faz em paralelo, sendo muito mais rápida que a CPU para isso. No PyTorch, você move tensores e modelos para a GPU com .to("cuda") (placas NVIDIA) ou .to("mps") (Macs com Apple Silicon). Tudo que interage precisa estar no mesmo dispositivo. É a diferença entre treinar em horas ou em dias.

Durante o treino, você precisa dos gradientes. Durante a inferência (usar o modelo pronto), não — e calcular gradientes à toa gasta memória e tempo. O torch.no_grad() desliga o autograd nesse momento, tornando a inferência mais leve e rápida. É um detalhe simples que todo código de produção usa.

💡 Analogia · A trilha de migalhas

O autograd é como Hansel deixando migalhas de pão pelo caminho: à medida que você faz os cálculos (vai pela floresta), o PyTorch anota o trajeto (o grafo). Quando chama .backward(), ele percorre as migalhas de volta para descobrir como cada passo influenciou o resultado — calculando os gradientes automaticamente, sem você refazer o caminho à mão.

📌 Mini-caso real · Por que pesquisadores escolhem o PyTorch

O PyTorch dominou a pesquisa em IA por causa do seu grafo dinâmico e da naturalidade "pythônica" — você escreve e debuga como código normal. A maioria dos modelos de ponta (incluindo muitos LLMs abertos) é desenvolvida nele. Dominar PyTorch te dá acesso a reproduzir papers, ajustar modelos e entender por dentro o que os frameworks de mais alto nível escondem.

✏️ Exercício prático · Brinque com autograd e GPU
  1. Crie um tensor com requires_grad=True, defina uma função simples e chame .backward() para ver o gradiente.
  2. Verifique se há GPU disponível (torch.cuda.is_available() ou torch.backends.mps.is_available()).
  3. Mova um tensor para o dispositivo disponível com .to(...) e confirme com .device.
Checklist da aula0/3
Entendo tensores e sua relação com NumPy
Sei o que autograd e .backward() fazem
Sei usar GPU (.to) e no_grad para inferência
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que o autograd do PyTorch faz?
A
Escreve o código sozinho
B
Calcula automaticamente os gradientes a partir do grafo de operações, ao chamar .backward()
C
Aumenta a resolução das imagens
D
Substitui a GPU
Selecione uma opção
3.16 · M3.3⏱ 12 min

Construindo redes neurais

nn.Module, camadas, loss, optimizer e o loop de treino.

No PyTorch, toda rede neural é uma classe que herda de nn.Module. Você define as camadas no construtor e o forward pass (como os dados fluem pela rede) num método forward. Esse padrão é universal: do menor classificador ao maior LLM, todos seguem essa estrutura. Aprendê-lo uma vez serve para sempre.

O kit básico de camadas: nn.Linear (camada totalmente conectada, a mais comum), nn.ReLU (a função de ativação padrão, que introduz não-linearidade), nn.Dropout (desliga neurônios aleatoriamente no treino para combater overfitting) e nn.BatchNorm (estabiliza e acelera o treino). O nn.Sequential permite empilhar camadas de forma rápida quando o fluxo é linear.

import torch.nn as nn

class Classificador(nn.Module):
    def __init__(self, entrada, saida):
        super().__init__()
        self.rede = nn.Sequential(
            nn.Linear(entrada, 128), nn.ReLU(), nn.Dropout(0.3),
            nn.Linear(128, 64), nn.ReLU(),
            nn.Linear(64, saida),
        )
    def forward(self, x):
        return self.rede(x)

modelo = Classificador(entrada=20, saida=3)

Para treinar, você precisa de dois ingredientes. A loss function (função de perda) mede o quão errado o modelo está — por exemplo, CrossEntropyLoss para classificação, MSELoss para regressão. O optimizer usa os gradientes para ajustar os pesos — o Adam (e o AdamW) é o padrão moderno, o SGD é o clássico. A loss diz "o quanto erramos"; o optimizer diz "como corrigir".

Todo treino segue o mesmo ritmo, repetido por várias épocas: (1) forward — a rede faz a previsão; (2) calcular a loss; (3) loss.backward() — calcular gradientes; (4) optimizer.step() — ajustar os pesos; (5) optimizer.zero_grad() — zerar os gradientes para a próxima rodada. Esquecer o zero_grad() é o bug mais comum de iniciantes (os gradientes se acumulam e o treino enlouquece).

import torch
criterio = nn.CrossEntropyLoss()
otimizador = torch.optim.AdamW(modelo.parameters(), lr=1e-3)

for epoca in range(10):
    for X, y in dataloader_treino:
        otimizador.zero_grad()        # 1. zera gradientes
        pred = modelo(X)              # 2. forward
        perda = criterio(pred, y)     # 3. calcula a loss
        perda.backward()              # 4. backward (gradientes)
        otimizador.step()             # 5. ajusta os pesos
    print(f"Época {epoca}: perda {perda.item():.4f}")
💡 Analogia · Aprender a arremessar

O loop de treino é como aprender a acertar uma cesta: você arremessa (forward), vê o quanto errou da cesta (loss), entende em que direção ajustar o braço (backward/gradiente), corrige o movimento (optimizer.step) e zera a cabeça para o próximo arremesso (zero_grad). Repetindo milhares de vezes, você (a rede) fica preciso.

📌 Mini-caso real · O bug clássico do zero_grad esquecido

Quase todo iniciante em PyTorch passa por isso: o treino "explode" (a loss vira NaN ou cresce sem parar) e a causa é ter esquecido o optimizer.zero_grad(). Sem ele, os gradientes de cada passo se somam aos anteriores, bagunçando tudo. Conhecer o loop canônico de cor — com seus cinco passos na ordem certa — evita horas de frustração depurando.

✏️ Exercício prático · Treine sua primeira rede
  1. Defina uma rede simples com nn.Module e nn.Sequential para um problema de classificação.
  2. Escreva o loop de treino completo com os 5 passos (lembre do zero_grad!).
  3. Treine por algumas épocas e observe a loss diminuir época a época.
Checklist da aula0/3
Sei estruturar uma rede com nn.Module
Conheço camadas, loss e optimizer
Domino o loop de treino e o zero_grad
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual passo esquecido é o bug mais comum no loop de treino do PyTorch?
A
Calcular a loss
B
optimizer.zero_grad() — sem ele, os gradientes se acumulam e o treino enlouquece
C
Importar o torch
D
Mover para a GPU
Selecione uma opção
3.17 · M3.3⏱ 15 min

CNNs na prática

Classificação de imagens com torchvision e DataLoaders.

Para imagens, usamos as camadas que vimos conceitualmente em M2.3, agora em código: nn.Conv2d (aplica os filtros que detectam padrões), nn.MaxPool2d (o pooling que resume e dá robustez) e nn.BatchNorm2d (estabiliza o treino). Empilhadas, elas formam uma CNN que vai de detectar bordas a reconhecer objetos inteiros — tudo aprendido a partir dos dados.

Você nunca treina com uma imagem por vez nem com tudo de uma vez. O Dataset representa seus dados (sabe carregar a imagem N e seu rótulo), e o DataLoader os entrega em batches (lotes), embaralhados e, opcionalmente, em paralelo. Esse mecanismo é o que torna o treino eficiente e é padrão em todo projeto de visão.

import torch
from torchvision import datasets, transforms
from torch.utils.data import DataLoader

transform = transforms.Compose([
    transforms.Resize((128, 128)),
    transforms.ToTensor(),
])

treino = datasets.ImageFolder("dados/treino", transform=transform)
loader = DataLoader(treino, batch_size=32, shuffle=True, num_workers=2)

for imagens, rotulos in loader:   # entrega em lotes de 32
    print(imagens.shape)          # [32, 3, 128, 128]
    break

Você raramente projeta uma CNN do zero. O torchvision.models oferece arquiteturas consagradas e já treinadas: ResNet, VGG, EfficientNet. Você as carrega prontas e adapta para o seu problema. É a porta de entrada para o transfer learning, que veremos na próxima aula — e o motivo de não precisar de milhões de imagens para ter um bom classificador.

Um projeto concreto e útil: classificar imagens de produtos (por categoria, ou defeituoso vs. ok) com 95%+ de acurácia. Com torchvision, um DataLoader bem montado e uma arquitetura como a ResNet adaptada, isso é alcançável até com um dataset modesto. É exatamente o tipo de aplicação industrial real — controle de qualidade, catalogação automática — que gera ROI claro.

💡 Analogia · A linha de montagem de imagens

O DataLoader é como uma esteira que entrega caixas (batches) de imagens à rede, uma após a outra, no ritmo certo e embaralhadas para a rede não "viciar" na ordem. Sem a esteira, você teria que entregar imagem por imagem à mão — inviável. Com ela, o treino flui de forma organizada e eficiente.

📌 Mini-caso real · Controle de qualidade na indústria

Fábricas usam CNNs para inspecionar peças na linha de produção: uma câmera fotografa cada item e um modelo classifica "ok" ou "defeito" em milissegundos, pegando falhas que o olho humano cansado deixaria passar. Treinado com fotos de peças boas e defeituosas, um classificador desses roda 24h sem fadiga. É Deep Learning gerando valor industrial direto e mensurável.

✏️ Exercício prático · Monte o pipeline de imagens
  1. Organize um pequeno conjunto de imagens em pastas por categoria (estrutura do ImageFolder).
  2. Crie o transform, o Dataset e o DataLoader, e itere um batch confirmando o shape.
  3. Carregue uma ResNet pré-treinada do torchvision.models e inspecione sua estrutura (sem treinar ainda).
Checklist da aula0/3
Conheço Conv2d, MaxPool2d e BatchNorm2d
Sei usar Dataset e DataLoader (batches)
Sei carregar modelos prontos do torchvision
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Para que serve o DataLoader no PyTorch?
A
Treinar o modelo sozinho
B
Entregar os dados em batches embaralhados (e em paralelo), alimentando o treino de forma eficiente
C
Calcular os gradientes
D
Salvar o modelo no disco
Selecione uma opção
3.18 · M3.3⏱ 18 min

Transfer Learning e HuggingFace

Modelos pré-treinados — por que treinar do zero é desperdício.

Treinar uma rede grande do zero exige milhões de exemplos e muito poder computacional — caro e, na maioria dos casos, desnecessário. O transfer learning reaproveita um modelo já treinado em uma tarefa enorme (por exemplo, reconhecer milhões de imagens, ou ler bilhões de palavras) e o adapta para a sua tarefa específica com pouquíssimos dados. É o atalho que democratizou o Deep Learning.

Há duas formas de adaptar. No feature extraction, você "congela" o modelo pré-treinado (usa o que ele já aprendeu) e treina só uma camada final para a sua tarefa — rápido e exige pouquíssimos dados. No full fine-tuning, você ajusta o modelo inteiro (ou boa parte) com os seus dados — mais poderoso, exige mais dados e cuidado. A regra: comece pelo feature extraction; só faça full fine-tuning se precisar de mais.

O HuggingFace é o "GitHub dos modelos de IA": um Hub com centenas de milhares de modelos pré-treinados, prontos para baixar e usar. As classes AutoModel e AutoTokenizer carregam qualquer modelo com poucas linhas. Os tokenizers convertem texto em tokens no formato que o modelo espera. É a infraestrutura que tornou o transfer learning acessível a todos.

from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch

nome = "neuralmind/bert-base-portuguese-cased"   # BERT em PT-BR
tokenizer = AutoTokenizer.from_pretrained(nome)
modelo = AutoModelForSequenceClassification.from_pretrained(nome, num_labels=2)

texto = "o atendimento foi excelente e rápido"
entradas = tokenizer(texto, return_tensors="pt", truncation=True)
with torch.no_grad():
    logits = modelo(**entradas).logits
print(torch.softmax(logits, dim=1))   # probabilidades por classe

Um projeto prático de alto valor: adaptar um BERT em português (como o BERTimbau) para classificar sentimento em reviews, comentários ou tickets brasileiros. Com transfer learning, você parte de um modelo que já "entende" português e o especializa para a sua tarefa com poucos exemplos rotulados. O resultado supera de longe um classificador clássico — e é diretamente aplicável a análise de feedback de clientes.

💡 Analogia · Contratar um especialista formado

Treinar do zero é como criar e educar uma pessoa do zero até ela virar especialista — anos e fortuna. Transfer learning é contratar alguém já formado e dar a ela um treinamento curto sobre o seu negócio específico. Em dias, ela está produtiva, aproveitando toda a educação que já tinha. Ninguém forma um PhD quando pode contratar um e especializá-lo rápido.

📌 Mini-caso real · Por que quase ninguém treina LLM do zero

Lembre da aula sobre treinamento vs. inferência: treinar um modelo de ponta custa milhões. O transfer learning (e o fine-tuning leve, que veremos em M3.4) é como o resto do mundo aproveita esses modelos caríssimos sem pagar o custo do zero. Você fica em cima de bilhões de dólares de treino prévio, adaptando para o seu caso por uma fração ínfima do custo. É a alavanca que coloca IA de ponta ao seu alcance.

✏️ Exercício prático · Use um modelo pré-treinado
  1. Carregue um modelo de classificação em PT-BR do HuggingFace (como um BERT em português).
  2. Tokenize algumas frases suas e rode a inferência (com torch.no_grad()).
  3. Interprete as probabilidades de saída — o modelo classificou como você esperava?
Checklist da aula0/3
Entendo transfer learning e seu porquê
Diferencio feature extraction de full fine-tuning
Sei usar HuggingFace (AutoModel/AutoTokenizer)
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que o transfer learning é preferível a treinar do zero na maioria dos casos?
A
Porque é mais lento
B
Porque reaproveita um modelo já treinado, exigindo pouquíssimos dados e custo para adaptar à sua tarefa
C
Porque não usa dados
D
Porque elimina a necessidade de GPU sempre
Selecione uma opção
3.19 · M3.3⏱ 21 min

Transformer do zero com PyTorch

Self-attention, multi-head e positional encoding implementados.

Você já entende o Transformer conceitualmente (M2.1). Implementá-lo do zero — um "mini-GPT" — é o que transforma entendimento superficial em domínio real. Não é para usar em produção (os frameworks fazem melhor), e sim para que nada dentro de um LLM seja caixa-preta para você. É um rito de passagem técnico que poucos fazem e que diferencia profundamente.

O coração é a self-attention, calculada com três projeções de cada token: Query (o que eu procuro?), Key (o que eu ofereço?) e Value (o que eu carrego?). Cada token usa sua Query para "perguntar" às Keys de todos os outros o quanto importam, e combina os Values conforme essas atenções. Em PyTorch, são umas poucas operações de matriz — surpreendentemente compacto para algo tão poderoso.

import torch, torch.nn.functional as F

def self_attention(X, Wq, Wk, Wv):
    Q, K, V = X @ Wq, X @ Wk, X @ Wv          # projeções
    d_k = Q.size(-1)
    scores = (Q @ K.transpose(-2, -1)) / d_k**0.5  # compatibilidade
    pesos = F.softmax(scores, dim=-1)         # quanto cada token importa
    return pesos @ V                          # combina os Values

A multi-head attention roda várias self-attentions em paralelo (cada "cabeça" aprende um tipo de relação) e junta os resultados. Como a atenção, por si, ignora a ordem das palavras, adiciona-se o positional encoding — um padrão (no paper original, senoidal) somado às entradas para informar a posição de cada token. Sem ele, "o cão mordeu o homem" e "o homem mordeu o cão" seriam idênticos para o modelo.

Um bloco Transformer completo soma à atenção: a layer norm (normalização que estabiliza o treino), uma sub-rede feed-forward (processamento adicional por token) e conexões residuais (atalhos que ajudam o gradiente a fluir em redes profundas). Empilhe vários desses blocos, adicione a camada de saída que prevê o próximo token, e você tem a estrutura de um GPT em miniatura — exatamente o que o paper original descreve.

💡 Analogia · Desmontar o motor para entender o carro

Implementar o Transformer do zero é como um mecânico que, ao menos uma vez, desmonta um motor inteiro e remonta. Ele não vai fazer isso toda vez que troca o óleo — mas, tendo feito uma vez, nenhum ruído do motor é mistério para ele. Depois desse exercício, você "ouve" qualquer LLM e sabe o que está acontecendo lá dentro.

📌 Mini-caso real · O "nanoGPT" como rito de passagem

Implementações didáticas de mini-GPTs (popularizadas por educadores como Andrej Karpathy) viraram um rito de passagem na comunidade: quem constrói um Transformer do zero, mesmo pequeno, passa a entender artigos, ajustes e limitações dos LLMs num nível que usuários de API jamais alcançam. É o investimento que separa quem usa IA de quem realmente a compreende.

✏️ Exercício prático · Implemente a atenção
  1. Implemente a função de self-attention (Q, K, V) em PyTorch, seguindo o exemplo.
  2. Teste com uma pequena matriz de entrada aleatória e inspecione os pesos de atenção (devem somar 1 por linha após o softmax).
  3. Desafio: adicione múltiplas cabeças (multi-head) concatenando o resultado de várias atenções.
Checklist da aula0/3
Entendo Q, K, V na self-attention
Sei o papel da multi-head e do positional encoding
Compreendo os blocos que formam um Transformer
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que o positional encoding é necessário no Transformer?
A
Para acelerar o treino
B
Porque a self-attention, sozinha, ignora a ordem das palavras — o encoding informa a posição
C
Para reduzir o custo
D
Para criptografar o texto
Selecione uma opção
3.20 · M3.3⏱ 12 min

Técnicas avançadas de treino

LR schedulers, gradient clipping, mixed precision e checkpointing.

A taxa de aprendizado (learning rate) é o "tamanho do passo" no treino — talvez o hiperparâmetro mais importante. Os schedulers ajustam essa taxa ao longo do treino: o OneCycleLR e o CosineAnnealingLR começam com passos maiores e os reduzem suavemente, o que costuma acelerar a convergência e melhorar o resultado final. Passo fixo funciona, mas um bom scheduler quase sempre rende mais.

Às vezes os gradientes "explodem" (ficam enormes), desestabilizando o treino — comum em redes profundas e recorrentes. O gradient clipping limita o tamanho máximo dos gradientes, como um regulador de tensão. É uma linha de código que previne treinos que divergem do nada, especialmente útil ao treinar ou ajustar modelos grandes.

Por padrão, os cálculos usam números de 32 bits (FP32). A mixed precision (com torch.cuda.amp) usa 16 bits (FP16) onde é seguro, mantendo a precisão onde importa. O resultado: treino até 2x mais rápido e usando metade da memória da GPU, com pouca ou nenhuma perda de qualidade. É padrão em treino sério de modelos grandes — ganho enorme por pouco esforço.

from torch.cuda.amp import autocast, GradScaler
scaler = GradScaler()

for X, y in loader:
    otimizador.zero_grad()
    with autocast():                 # usa FP16 onde for seguro
        pred = modelo(X)
        perda = criterio(pred, y)
    scaler.scale(perda).backward()
    scaler.unscale_(otimizador)
    torch.nn.utils.clip_grad_norm_(modelo.parameters(), 1.0)  # clipping
    scaler.step(otimizador)
    scaler.update()

Treinos longos podem cair (queda de energia, erro, fim da sessão na nuvem). O checkpointing salva o estado do modelo periodicamente, permitindo retomar de onde parou em vez de recomeçar do zero — economia que pode ser de dias. E o Weights & Biases (W&B) registra métricas, hiperparâmetros e gráficos do treino, para você comparar experimentos e entender o que funcionou. Treinar sem tracking é voar às cegas.

💡 Analogia · Subir uma montanha de bicicleta

O scheduler é trocar as marchas conforme a inclinação (passos grandes no plano, curtos na subida íngreme). O gradient clipping é o freio que impede você de despencar numa descida perigosa. A mixed precision é uma bicicleta mais leve que vai 2x mais rápido. E o checkpointing é marcar acampamentos no caminho — se cair, você volta ao último acampamento, não ao pé da montanha.

📌 Mini-caso real · O treino de 3 dias que caiu na hora 70

Sem checkpointing, é o pesadelo: um treino de vários dias na nuvem que falha perto do fim e obriga a recomeçar do zero, queimando tempo e dinheiro de GPU. Com checkpoints salvos a cada época, o mesmo incidente custa, no máximo, a última época. Essas técnicas "avançadas" não são luxo acadêmico — são o que torna o treino de modelos sérios econômico e viável na prática.

✏️ Exercício prático · Aplique as técnicas no loop
  1. Adicione um learning rate scheduler (ex.: CosineAnnealingLR) ao seu loop de treino.
  2. Inclua gradient clipping com clip_grad_norm_.
  3. Implemente o salvamento de checkpoint a cada época (salve modelo.state_dict()) e teste retomar de um deles.
Checklist da aula0/3
Sei usar LR schedulers e gradient clipping
Entendo o ganho da mixed precision
Sei salvar/retomar checkpoints e fazer tracking
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual o principal benefício da "mixed precision" (FP16) no treino?
A
Aumenta a acurácia garantidamente
B
Treino até ~2x mais rápido e com metade da memória da GPU, com pouca perda de qualidade
C
Elimina a necessidade de dados
D
Substitui o optimizer
Selecione uma opção
3.21 · M3.4⏱ 15 min

APIs de LLMs

OpenAI, Anthropic, Google, Groq, Together.ai e Ollama local.

Toda API de chat moderna fala a mesma língua: você envia uma lista de mensagens com roles. O system define o comportamento e a persona ("você é um assistente jurídico"), o user traz a pergunta, e o assistant é a resposta do modelo (incluído no histórico para manter contexto). Dominar essa estrutura é a base de absolutamente toda integração com LLMs.

# OpenAI
from openai import OpenAI
cliente = OpenAI()
r = cliente.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "Responda em 1 frase."},
        {"role": "user", "content": "O que é RAG?"},
    ],
    temperature=0.2,
)
print(r.choices[0].message.content)

# Anthropic (Claude) — system separado das messages
from anthropic import Anthropic
c = Anthropic()
m = c.messages.create(
    model="claude-opus-4-7", max_tokens=300,
    system="Responda em 1 frase.",
    messages=[{"role": "user", "content": "O que é RAG?"}],
)
print(m.content[0].text)

Quatro parâmetros aparecem sempre: temperature (criatividade — baixa para respostas previsíveis, alta para variadas), top_p (alternativa à temperatura, filtra os tokens mais prováveis), max_tokens (teto da resposta — controla custo e tamanho) e stop (sequências que encerram a geração). Saber regulá-los é a diferença entre respostas erráticas e respostas sob controle.

Com streaming, o modelo envia a resposta token a token conforme gera (lembre dos generators de M3.1), em vez de você esperar tudo. Isso melhora muito a percepção de velocidade em produtos de chat — o texto "digita" na tela. É um padrão event-driven: você itera sobre os pedaços conforme chegam.

Cada provider tem um perfil. OpenAI, Anthropic e Google oferecem os modelos de ponta. O Groq se destaca por latência baixíssima (respostas quase instantâneas, via hardware próprio). O Together.ai serve modelos abertos a bom custo. E o Ollama roda modelos localmente, de graça e privado (M2.2). Na prática, você escolhe — ou combina — providers conforme o equilíbrio entre custo, velocidade e qualidade que cada tarefa exige.

💡 Analogia · Mesma tomada, aparelhos diferentes

As APIs de chat são como aparelhos que usam a mesma tomada (a estrutura system/user/assistant): você troca o aparelho (provider) sem refazer a instalação elétrica. Um aparelho é mais potente (modelo de ponta), outro é mais rápido (Groq), outro não consome da rede (Ollama local). A padronização te dá liberdade de escolher o melhor para cada cômodo.

📌 Mini-caso real · Trocar de modelo em uma linha

Como a estrutura é padronizada, equipes maduras abstraem o provider e trocam de modelo mudando uma string ou variável — testando qual entrega melhor custo-benefício para cada caso de uso, ou caindo num modelo de backup se um provider ficar fora do ar. Essa portabilidade, fruto da estrutura comum, é uma vantagem arquitetural concreta.

✏️ Exercício prático · Compare dois providers
  1. Faça a mesma pergunta para dois modelos diferentes (ex.: um da OpenAI e um da Anthropic), com o mesmo system prompt.
  2. Ative o streaming em um deles e observe a resposta chegando aos poucos.
  3. Varie a temperature (0.0 e 0.9) na mesma pergunta e compare a diferença nas respostas.
Checklist da aula0/3
Domino a estrutura system/user/assistant
Sei regular temperature, top_p, max_tokens e stop
Conheço o perfil de cada provider (latência/custo)
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que o parâmetro "temperature" controla numa chamada de LLM?
A
O custo por token
B
A variabilidade/criatividade da resposta: baixa = previsível, alta = variada
C
O tamanho máximo da resposta
D
A velocidade da internet
Selecione uma opção
3.22 · M3.4⏱ 18 min

Prompt Engineering avançado

CoT, Few-Shot, XML tags, system prompts e JSON mode.

O Chain-of-Thought (CoT) é uma das técnicas mais impactantes: pedir ao modelo que raciocine passo a passo antes de dar a resposta final. Em problemas de lógica, matemática e análise, isso melhora drasticamente o acerto — o modelo "mostra o trabalho" e, ao fazê-lo, erra menos. Um simples "pense passo a passo" pode transformar uma resposta errada numa correta.

No few-shot prompting, você inclui no prompt alguns exemplos de entrada e saída desejada antes da pergunta real. O modelo aprende o padrão e o formato ali mesmo, sem treino. É extremamente eficaz para padronizar saídas e ensinar tarefas específicas — escolher 2 ou 3 exemplos ótimos e representativos costuma valer mais que uma longa instrução.

prompt = """Classifique o sentimento. Pense antes de responder.

Texto: "demorou mas chegou certo" -> Raciocínio: ressalva + resultado ok -> NEUTRO
Texto: "melhor compra do ano!" -> Raciocínio: entusiasmo claro -> POSITIVO

Texto: "veio quebrado e ninguem responde" -> Raciocínio:"""
# o modelo continua o raciocínio e conclui o rótulo, seguindo o padrão

O role prompting (definir um papel claro no system: "você é um revisor jurídico sênior") calibra o tom e a expertise. As XML tags são uma técnica especialmente eficaz com o Claude: envolver partes do prompt em tags como <contexto>, <pergunta>, <exemplo> dá estrutura clara, reduz ambiguidade e melhora a obediência às instruções. Estrutura no prompt = previsibilidade na resposta.

Para integrar LLMs em software, você precisa de saídas previsíveis e parseáveis — não texto livre. O JSON mode e os Structured Outputs (OpenAI/Anthropic) forçam o modelo a responder num formato JSON que segue um schema definido. Isso elimina o pesadelo de extrair dados de texto solto e é a base de pipelines confiáveis — você verá isso formalizado com Pydantic em M3.6.

💡 Analogia · Briefing para um freelancer

Um prompt avançado é como um briefing impecável para um freelancer: você define o papel dele (role), mostra exemplos do que quer (few-shot), organiza o pedido em seções claras (XML tags), pede que explique o raciocínio (CoT) e especifica o formato de entrega (JSON). Briefing vago gera trabalho vago; briefing estruturado gera resultado sob medida.

📌 Mini-caso real · O "pense passo a passo" que salvou a acurácia

É um achado bem documentado: em tarefas de raciocínio, simplesmente instruir o modelo a pensar passo a passo (CoT) elevou a taxa de acerto de forma significativa em relação a pedir a resposta direta. A mesma capacidade do modelo, destravada por uma instrução melhor. É a prova de que prompt engineering não é "frescura" — é engenharia que muda resultados mensuráveis.

✏️ Exercício prático · Aplique as técnicas
  1. Pegue uma tarefa de classificação e escreva um prompt few-shot com 2 exemplos ótimos.
  2. Adicione a instrução de Chain-of-Thought e compare o resultado com e sem ela.
  3. Reescreva o prompt usando XML tags para separar contexto, exemplos e pergunta — e peça saída em JSON.
Checklist da aula0/3
Sei usar Chain-of-Thought e few-shot
Uso role prompting e XML tags para estruturar
Sei forçar saída em JSON (structured output)
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que faz a técnica de Chain-of-Thought (CoT)?
A
Reduz o número de tokens
B
Pede que o modelo raciocine passo a passo antes da resposta, aumentando o acerto em tarefas complexas
C
Criptografa o prompt
D
Treina o modelo do zero
Selecione uma opção
3.23 · M3.4⏱ 21 min

Embeddings

Criação, similaridade de cosseno, busca semântica e casos de uso.

Você já conhece o conceito (M1.6, M3.4): embeddings são textos convertidos em vetores de números que capturam significado. Na prática, você os cria com uma chamada de API a um modelo de embedding — como o text-embedding-3-small (OpenAI) ou o embed-multilingual-v3 (Cohere, ótimo para português). Cada texto vira um vetor de centenas/milhares de dimensões.

from openai import OpenAI
cliente = OpenAI()

def embed(textos):
    r = cliente.embeddings.create(
        model="text-embedding-3-small", input=textos)
    return [d.embedding for d in r.data]

vetores = embed(["pix não caiu", "pagamento não foi aprovado",
                 "quero cancelar minha assinatura"])
print(len(vetores[0]))   # ex.: 1536 dimensões

Com os vetores em mãos, a similaridade de cosseno (M3.4) mede o quão próximos dois textos estão em significado — não em palavras. É isso que permite a busca semântica: encontrar documentos relevantes mesmo que não compartilhem as mesmas palavras da pergunta. "Meu pagamento falhou" recupera um doc sobre "transação recusada", algo que a busca por palavra-chave erraria.

Combinando embeddings com clustering (M3.2), você agrupa textos por significado automaticamente. O caso clássico: milhares de tickets de suporte agrupados em temas (cobrança, bug, dúvida) sem ninguém ler nem rotular. Isso revela onde estão os problemas mais frequentes e orienta priorização — transformar texto caótico em inteligência acionável.

Embeddings são a fundação do RAG (M3.5), dos vector databases (próxima aula) e da memória de agentes (M3.8). Quase toda aplicação séria de IA com dados próprios passa por embeddings em algum ponto. Dominar criá-los, compará-los e agrupá-los é uma das habilidades mais reutilizáveis de toda a formação.

💡 Analogia · O mapa de significados

Imagine um mapa gigante onde cada texto é um ponto, e textos com sentido parecido ficam perto. Os embeddings desenham esse mapa em números. A busca semântica é, dada uma pergunta, achar os pontos mais próximos dela no mapa — encontrando o que significa o mesmo, não o que escreve igual.

📌 Mini-caso real · Busca que entende o cliente

Uma central trocou a busca por palavra-chave na base de ajuda por busca semântica com embeddings. Antes, o cliente que digitava "não consigo entrar" não achava o artigo "problemas de login". Depois, os embeddings conectaram os significados e a taxa de auto-resolução subiu — menos tickets, clientes mais satisfeitos. É o ganho direto de entender sentido, não só palavras.

✏️ Exercício prático · Construa uma busca semântica
  1. Crie embeddings de ~8 frases curtas sobre 2 ou 3 temas distintos.
  2. Dada uma frase de consulta nova, calcule a similaridade de cosseno com todas e retorne as 3 mais próximas.
  3. Verifique se as mais próximas são, de fato, do mesmo tema — analise eventuais surpresas.
Checklist da aula0/3
Sei criar embeddings via API
Domino similaridade de cosseno e busca semântica
Entendo embeddings como base de RAG e agentes
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual a vantagem da busca semântica (com embeddings) sobre a busca por palavra-chave?
A
É mais barata sempre
B
Encontra textos por significado, recuperando documentos relevantes mesmo sem palavras em comum
C
Não precisa de dados
D
Funciona só em inglês
Selecione uma opção
3.24 · M3.4⏱ 12 min

Vector Databases

Chroma, Pinecone, Qdrant, Weaviate e pgvector.

Calcular similaridade comparando sua pergunta com cada documento funciona para dezenas de itens — mas não para milhões. Um vector database (banco vetorial) armazena embeddings e encontra os mais similares de forma extremamente rápida, mesmo entre milhões de vetores. É a infraestrutura que torna o RAG viável em escala real.

O segredo é o índice, geralmente o HNSW (um grafo de navegação hierárquica). Em vez de comparar com tudo (busca exata, lenta), ele faz uma busca aproximada inteligente que encontra os vizinhos mais próximos visitando só uma fração dos vetores. Troca-se uma precisão minúscula por uma velocidade ordens de magnitude maior — um ótimo negócio na prática.

Bancos vetoriais guardam, junto de cada vetor, metadados (autor, data, categoria, departamento). Isso permite combinar busca semântica com filtros: "ache os trechos mais relevantes apenas nos documentos do RH, de 2025". Essa combinação de significado + filtro estruturado é essencial em aplicações empresariais, onde permissões e escopo importam.

import chromadb
cliente = chromadb.Client()
col = cliente.create_collection("base")

col.add(
    documents=["Reembolsos levam até 7 dias úteis.",
               "O suporte funciona 24h por chat."],
    metadatas=[{"area": "financeiro"}, {"area": "suporte"}],
    ids=["d1", "d2"],
)

res = col.query(query_texts=["quanto tempo para receber meu dinheiro?"],
                n_results=1)
print(res["documents"])   # recupera o doc de reembolso por significado

O mapa prático: o Chroma é leve e roda local — ideal para desenvolvimento e protótipos. O Pinecone é gerenciado na nuvem, escalável — ótimo para produção sem gerenciar infraestrutura. O pgvector adiciona busca vetorial ao PostgreSQL — perfeito se você já usa Postgres e quer manter tudo num só banco. Qdrant e Weaviate são alternativas robustas e abertas. A escolha equilibra simplicidade, escala e o que você já tem.

💡 Analogia · O bibliotecário com memória fotográfica

Comparar com cada documento é como um estagiário que lê o acervo inteiro a cada pergunta — inviável numa biblioteca grande. O banco vetorial é um bibliotecário com memória fotográfica e um sistema de fichas (índice HNSW): ele vai direto às poucas estantes certas e traz os livros relevantes em segundos, sem percorrer tudo.

📌 Mini-caso real · Do protótipo à produção

Um caminho comum e saudável: prototipar o RAG com Chroma local (rápido, grátis, sem configurar nada), validar que funciona, e então migrar para Pinecone ou pgvector quando for para produção com milhões de documentos e múltiplos usuários. Como a interface é parecida, a troca é tranquila — começar simples e escalar quando necessário evita complexidade prematura.

✏️ Exercício prático · Monte um índice vetorial
  1. Instale o Chroma e crie uma coleção com ~6 documentos curtos e metadados (ex.: área).
  2. Faça uma query semântica e confira se recupera o documento certo por significado.
  3. Adicione um filtro de metadado à query (ex.: só uma área) e veja o efeito no resultado.
Checklist da aula0/3
Entendo por que preciso de banco vetorial
Sei o que é o índice HNSW e filtros de metadados
Sei escolher entre Chroma, Pinecone e pgvector
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que um vector database é necessário para RAG em escala?
A
Para treinar o LLM
B
Para encontrar os embeddings mais similares com altíssima velocidade entre milhões de vetores (via índice HNSW)
C
Para gerar imagens
D
Para criptografar dados
Selecione uma opção
3.25 · M3.4⏱ 15 min

Fine-tuning de LLMs

LoRA, QLoRA, PEFT e a OpenAI Fine-tuning API.

Lembre da escada (M1.7): prompt → RAG → fine-tuning. O fine-tuning faz sentido quando você precisa de um estilo/comportamento muito específico e consistente, ou de um formato padronizado em altíssimo volume — coisas que prompt e RAG não entregam bem. Não é a ferramenta para adicionar conhecimento factual (RAG faz melhor e mais barato). Saber quando usá-lo é tão importante quanto saber como.

Fazer fine-tuning completo de um LLM enorme é caríssimo. O LoRA (Low-Rank Adaptation) é a solução elegante: em vez de ajustar todos os bilhões de pesos, ele congela o modelo e treina apenas pequenos adaptadores (uma fração mínima dos parâmetros). O resultado é quase tão bom quanto o fine-tuning completo, por uma fração ínfima do custo e da memória. Revolucionou o fine-tuning acessível.

O QLoRA vai além: combina o LoRA com quantização em 4 bits (representar os pesos com muito menos memória). O efeito prático é impressionante — dá para fazer fine-tuning de modelos grandes numa GPU de consumidor (uma placa de jogos potente), algo que antes exigia um cluster. O PEFT (biblioteca da HuggingFace) implementa essas técnicas de forma acessível.

O fine-tuning exige um dataset de qualidade, tipicamente em formato JSONL (lembre de M3.5: cada linha é um exemplo com mensagens). A regra de ouro: poucos exemplos excelentes > muitos exemplos medíocres. Para quem prefere não gerenciar infraestrutura, a OpenAI Fine-tuning API faz o processo na nuvem. O custo varia, mas com LoRA/QLoRA ficou acessível — sempre estime antes, comparando com o que um bom prompt + RAG já resolveriam.

{"messages": [{"role": "system", "content": "Você responde no tom da marca: direto e amigável."}, {"role": "user", "content": "Como faço para trocar meu plano?"}, {"role": "assistant", "content": "Fácil! Vá em Configuracoes > Plano e escolha o novo. A troca vale na hora 😊"}]}
{"messages": [{"role": "user", "content": "Voces tem desconto anual?"}, {"role": "assistant", "content": "Temos sim! No plano anual voce economiza 20%. Quer que eu te mostre os valores?"}]}
⚠️ Fine-tuning não é para conhecimento factual

Um erro caro e comum: usar fine-tuning para "ensinar fatos" ao modelo. Para conhecimento (documentos, dados que mudam), RAG é melhor, mais barato e atualizável. Reserve o fine-tuning para estilo, tom e formato consistentes. Pular para o fine-tuning sem testar prompt e RAG antes é o erro clássico da escada de decisão.

📌 Mini-caso real · O tom de marca consistente em escala

Uma empresa com altíssimo volume de atendimento queria respostas sempre no tom exato da marca, sem variação. Prompt resolvia parcialmente, mas com inconsistências. Um fine-tuning leve (LoRA) com algumas centenas de exemplos bem curados travou o tom de forma consistente em escala — aqui, o fine-tuning foi a escolha certa, porque o objetivo era comportamento/estilo, não conhecimento.

✏️ Exercício prático · Prepare um fine-tuning
  1. Monte um pequeno dataset JSONL (5-10 exemplos) que ensine um tom específico (não fatos).
  2. Valide o formato (cada linha é um JSON com "messages") — reutilize o que aprendeu com Pandas em M3.5.
  3. Decida e justifique: para o seu caso, fine-tuning é mesmo necessário, ou prompt + RAG resolveriam?
Checklist da aula0/3
Sei quando fine-tuning supera prompt/RAG
Entendo LoRA, QLoRA e PEFT
Sei preparar dataset JSONL e estimar custo
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Para qual objetivo o fine-tuning é a escolha certa (em vez de RAG)?
A
Adicionar conhecimento factual atualizável
B
Fixar um estilo/tom/comportamento consistente em escala
C
Buscar documentos na hora da pergunta
D
Reduzir o número de tokens
Selecione uma opção
3.26 · M3.4⏱ 18 min

Avaliação de LLMs

LLM-as-Judge, RAGAS, TruLens e testes automatizados.

Software tradicional é determinístico: a mesma entrada dá a mesma saída, e o teste é "passou ou falhou". LLMs são probabilísticos e geram texto aberto — a mesma pergunta pode ter várias respostas boas e válidas. Isso quebra os testes convencionais. Avaliar qualidade de LLM exige métodos próprios, e ignorar isso é colocar em produção um sistema cuja qualidade você não consegue medir nem garantir.

Uma técnica poderosa: usar um LLM forte como juiz (LLM-as-Judge) para avaliar as respostas do seu sistema, segundo critérios que você define (correção, tom, completude). Em vez de um humano ler milhares de saídas, um modelo capaz (como o GPT-4o) pontua cada uma seguindo uma rubrica. Não é perfeito, mas escala a avaliação de forma viável — e correlaciona razoavelmente bem com o julgamento humano quando bem calibrado.

Para pipelines RAG (M3.5), o RAGAS é referência. Ele mede dimensões cruciais: faithfulness (a resposta se baseia mesmo nos documentos recuperados, ou alucinou?), answer relevancy (responde à pergunta?) e context recall/precision (o retrieval trouxe os trechos certos?). Essas métricas permitem diagnosticar onde o RAG falha — se é no retrieval ou na geração — em vez de só sentir que "está ruim".

O objetivo final é um conjunto de testes automatizados: um dataset de avaliação com perguntas e respostas esperadas, rodado a cada mudança no sistema (modelo novo, prompt ajustado). Assim você detecta regressão de qualidade — quando uma alteração que parecia melhorar na verdade piorou algo. O TruLens e plataformas de observabilidade ajudam a monitorar isso em produção, continuamente.

💡 Analogia · Corrigir redação, não prova de múltipla escolha

Testar software comum é como corrigir prova de múltipla escolha: certo ou errado, automático. Avaliar LLM é como corrigir redações: há várias respostas boas, e você precisa de uma rubrica e de um corretor competente. O LLM-as-Judge é contratar um corretor incansável que segue sua rubrica em milhares de redações; o RAGAS é a rubrica específica para "redações com fontes" (RAG).

📌 Mini-caso real · A "melhoria" que piorou tudo

Cenário comum: a equipe troca o prompt ou o modelo "para melhorar", solta em produção, e só semanas depois percebe que a qualidade caiu em casos que antes funcionavam — porque não havia testes para detectar a regressão. Times maduros mantêm um dataset de avaliação e rodam RAGAS/LLM-as-Judge a cada mudança, pegando regressões antes de afetar usuários. Avaliação não é luxo; é o que permite evoluir com segurança.

✏️ Exercício prático · Crie um mini-conjunto de avaliação
  1. Monte 5 perguntas representativas do seu caso, com a resposta "ideal" para cada.
  2. Escreva um prompt de LLM-as-Judge que pontue uma resposta de 0 a 10 segundo critérios (correção, completude, tom).
  3. Rode duas versões do seu prompt/sistema nas 5 perguntas e use o juiz para comparar — qual venceu?
Checklist da aula0/3
Entendo por que avaliar LLM é diferente
Sei usar LLM-as-Judge com rubrica
Conheço RAGAS e a importância de testes de regressão
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que a métrica "faithfulness" do RAGAS avalia num pipeline RAG?
A
A velocidade da resposta
B
Se a resposta se baseia de fato nos documentos recuperados (em vez de alucinar)
C
O custo em tokens
D
O tamanho do banco vetorial
Selecione uma opção
3.27 · M3.5⏱ 21 min

Arquitetura RAG

Chunking, embedding, indexação, retrieval e geração — o pipeline completo.

O RAG (Retrieval-Augmented Generation) tem duas fases. Na ingestão (offline): você divide os documentos em pedaços (chunking), gera embeddings de cada pedaço e os guarda num banco vetorial (indexação). Na consulta (online): a pergunta vira embedding, você recupera os pedaços mais relevantes (retrieval) e os injeta no prompt para o LLM gerar a resposta ancorada (geração). Entender esse fluxo de ponta a ponta é o coração de M3.5.

O chunking (dividir o documento em pedaços) é mais decisivo do que parece. Pedaços grandes demais diluem o sinal e desperdiçam contexto; pequenos demais perdem o significado. Parâmetros-chave: o tamanho do chunk e o overlap (sobreposição entre pedaços vizinhos, para não cortar uma ideia ao meio). Estratégias vão do recursivo (por parágrafos/sentenças) ao semântico (cortar onde o assunto muda) e por seção.

from langchain_text_splitters import RecursiveCharacterTextSplitter

splitter = RecursiveCharacterTextSplitter(
    chunk_size=800,        # tamanho-alvo do pedaço
    chunk_overlap=100,     # sobreposição para não cortar ideias
    separators=["\n\n", "\n", ". ", " "],  # tenta quebrar em limites naturais
)
chunks = splitter.split_text(texto_do_documento)
print(f"{len(chunks)} pedaços gerados")

Cada chunk vira um embedding (M3.4) e é guardado no banco vetorial (M3.4) — isso é a indexação. Na consulta, faz-se o top-k retrieval: buscar os k pedaços mais similares à pergunta (k tipicamente entre 3 e 10). Esses pedaços são o "material de consulta" que o modelo usará. A qualidade da resposta depende diretamente de o retrieval trazer os pedaços certos.

Por fim, os pedaços recuperados são injetados no prompt junto da pergunta, com a instrução de responder baseando-se neles e citar as fontes. Isso ancora a resposta (grounding, M2.6), reduz alucinação e permite ao usuário verificar de onde veio cada afirmação. Um RAG sem citação perde grande parte do seu valor — a confiabilidade verificável é justamente o que o torna útil em contextos sérios.

💡 Analogia · A prova com consulta

RAG é transformar a "prova de cabeça" (LLM puro, que pode alucinar) numa "prova com consulta": antes de responder, o modelo recebe exatamente as páginas relevantes do material. O chunking é como você organiza o material em fichas; o retrieval é puxar as fichas certas para a pergunta; e a citação é apontar de qual ficha veio cada resposta.

📌 Mini-caso real · O chunking que arruinou (e salvou) o RAG

Um RAG dava respostas ruins, e a equipe culpava o modelo — quando o problema era o chunking: pedaços gigantes misturavam assuntos e o retrieval trazia ruído. Ao ajustar tamanho e overlap e quebrar por seções, as respostas melhoraram drasticamente, sem trocar o modelo. A lição: em RAG, a qualidade do retrieval (que começa no chunking) frequentemente importa mais que o LLM.

✏️ Exercício prático · Construa o pipeline básico
  1. Pegue um documento (PDF ou texto), aplique chunking com overlap e gere embeddings dos pedaços.
  2. Indexe no Chroma e faça uma pergunta, recuperando os top-3 pedaços.
  3. Monte um prompt que injeta esses pedaços e pede ao LLM responder citando de qual pedaço veio a informação.
Checklist da aula0/3
Entendo o pipeline RAG de ponta a ponta
Sei ajustar chunking (tamanho e overlap)
Sei fazer retrieval top-k e gerar com citação
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que o chunking é uma decisão tão importante no RAG?
A
Não importa, qualquer divisão serve
B
Pedaços mal dimensionados prejudicam o retrieval (diluem ou cortam o significado), degradando as respostas
C
Define o modelo usado
D
Substitui o banco vetorial
Selecione uma opção
3.28 · M3.5⏱ 12 min

RAG Avançado

Hybrid Search, Reranking, HyDE, Multi-Query e Parent-Child chunks.

A busca por embeddings (semântica) entende significado, mas às vezes erra termos exatos (códigos, nomes próprios, siglas). A busca BM25 (por palavra-chave) acerta os termos exatos, mas ignora o sentido. O Hybrid Search combina as duas e funde os resultados — capturando tanto o significado quanto os termos literais. É um dos upgrades de maior impacto e menor esforço no RAG.

O retrieval inicial é rápido, mas impreciso na ordenação. O reranking adiciona uma segunda etapa: recupera-se um número maior de candidatos (digamos, 20) e um modelo mais caro e preciso — um cross-encoder (como o reranker da Cohere) — reordena-os por relevância real à pergunta, ficando com os melhores 3-5. Você paga um pouco mais por consulta, mas a precisão do contexto sobe bastante.

Às vezes a pergunta do usuário é curta ou mal formulada para o retrieval. O HyDE (Hypothetical Document Embeddings) gera primeiro uma resposta hipotética à pergunta e usa o embedding dela para buscar — frequentemente mais próximo dos documentos reais. O Multi-Query reescreve a pergunta de várias formas, busca com todas e une os resultados, aumentando a chance de pescar o trecho certo.

Há uma tensão: chunks pequenos buscam melhor (precisão), mas chunks grandes dão mais contexto à geração. A estratégia Parent-Child resolve: você indexa pedaços pequenos (filhos) para um retrieval preciso, mas entrega ao LLM o pedaço maior que os contém (pai). Assim você ganha a precisão da busca pequena e o contexto da geração grande — o melhor dos dois.

💡 Analogia · A equipe de pesquisa de elite

RAG básico é um estagiário que pega os primeiros documentos que parecem relevantes. RAG avançado é uma equipe: um busca por significado e outro por palavra exata (hybrid), um terceiro reescreve a pergunta de vários ângulos (multi-query), e um editor sênior reordena tudo por relevância real (reranking) antes de entregar. Mais etapas, resultado muito melhor.

📌 Mini-caso real · De respostas "quase certas" a precisas

Um RAG empresarial dava respostas frequentemente "quase certas" — pegava o documento do tema, mas não o trecho exato. Adicionando hybrid search (para acertar códigos e termos específicos) e reranking (para ordenar por relevância real), a precisão deu um salto. Foram duas técnicas plugadas sobre o pipeline existente, sem trocar modelo nem refazer a base — alto retorno sobre baixo esforço.

✏️ Exercício prático · Faça um upgrade no seu RAG
  1. Sobre o RAG básico da aula anterior, adicione uma busca por palavra-chave (BM25) e funda com a semântica (hybrid).
  2. Recupere mais candidatos (ex.: 10) e aplique um reranking para ficar com os 3 melhores.
  3. Teste uma pergunta que antes falhava (com termo exato/sigla) e compare o antes e depois.
Checklist da aula0/3
Sei o que é e por que usar Hybrid Search
Entendo reranking com cross-encoder
Conheço HyDE, Multi-Query e Parent-Child
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que o "reranking" faz num pipeline RAG avançado?
A
Cria os embeddings
B
Reordena os candidatos recuperados por relevância real (via cross-encoder), ficando com os melhores
C
Divide os documentos
D
Treina o LLM
Selecione uma opção
3.29 · M3.5⏱ 15 min

Tipos de documentos

PDF, Word, HTML, tabelas e RAG multimodal.

Na vida real, o conhecimento está em formatos variados, e cada um exige a ferramenta certa para extrair o texto limpo: PyMuPDF (PDFs), python-docx (Word), BeautifulSoup4 (HTML/páginas web). A qualidade dessa extração é o alicerce de tudo — texto extraído com lixo (cabeçalhos repetidos, quebras erradas) contamina os chunks e degrada o RAG inteiro. "Garbage in, garbage out" vale aqui também.

import fitz  # PyMuPDF
from docx import Document

def ler_pdf(caminho):
    doc = fitz.open(caminho)
    return "\n".join(pagina.get_text() for pagina in doc)

def ler_docx(caminho):
    doc = Document(caminho)
    return "\n".join(p.text for p in doc.paragraphs)

texto = ler_pdf("manual.pdf")

Tabelas são o pesadelo do RAG. Quando extraídas como texto corrido, perdem a estrutura — as relações entre linhas e colunas viram uma sopa de números sem sentido, e o modelo não consegue responder "qual o valor da linha X na coluna Y?". Lidar com tabelas exige cuidado especial: preservá-las como markdown, HTML estruturado, ou processá-las à parte. Ignorar isso faz o RAG falhar feio em documentos cheios de dados tabulares.

Documentos reais misturam títulos, parágrafos, tabelas, listas e imagens de forma bagunçada. A biblioteca Unstructured.io é especializada em particionar esses documentos complexos em elementos estruturados (identificando o que é título, tabela, parágrafo), facilitando um chunking inteligente. É uma ferramenta que poupa muito trabalho manual em bases documentais heterogêneas e bagunçadas.

O RAG multimodal vai além do texto: indexa também imagens e diagramas (usando embeddings multimodais, M2.1). Assim, um manual técnico com esquemas, ou um catálogo com fotos, pode ser consultado pelo conteúdo visual — "mostre o diagrama de instalação" recupera a imagem certa. É a fronteira do RAG, abrindo bases de conhecimento que antes eram inacessíveis por serem visuais.

💡 Analogia · Tradutores especializados

Cada formato de documento fala um "idioma" diferente, e você precisa do tradutor certo: PyMuPDF traduz PDF, python-docx traduz Word, BeautifulSoup traduz HTML. As tabelas são como poesia — perdem o sentido numa tradução literal e exigem um tradutor especializado (preservar a estrutura). O Unstructured.io é o tradutor poliglota que lida com documentos que misturam vários idiomas.

📌 Mini-caso real · O RAG que ignorava as tabelas

Uma empresa montou um RAG sobre relatórios financeiros e ele acertava o texto, mas errava sistematicamente qualquer pergunta sobre números — porque as tabelas viravam texto embaralhado na extração. Ao tratar as tabelas separadamente (preservando-as como markdown estruturado), o RAG passou a responder corretamente sobre os dados. O formato dos documentos, não o modelo, era o gargalo.

✏️ Exercício prático · Extraia de formatos diferentes
  1. Extraia texto limpo de um PDF e de um arquivo Word com as bibliotecas adequadas.
  2. Encontre um documento com uma tabela e observe como ela fica ao ser extraída como texto puro — note o problema.
  3. Proponha uma estratégia para preservar essa tabela de forma que o LLM consiga interpretá-la (ex.: markdown).
Checklist da aula0/3
Sei extrair texto de PDF, Word e HTML
Entendo o problema das tabelas em RAG
Conheço Unstructured.io e o RAG multimodal
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que tabelas são um problema conhecido em RAG?
A
São grandes demais
B
Extraídas como texto corrido, perdem a estrutura linha/coluna e o modelo não consegue interpretá-las
C
Não podem ser indexadas
D
Sempre contêm erros
Selecione uma opção
3.30 · M3.5⏱ 18 min

LlamaIndex

Índices, query engines, routers e pipelines RAG enterprise.

Enquanto o LangChain (M3.6) é generalista, o LlamaIndex é especializado em RAG e dados — e brilha nisso. Ele abstrai o pipeline (carregar, indexar, consultar) em componentes prontos e robustos. Para projetos cujo coração é "conversar com dados/documentos", o LlamaIndex frequentemente oferece o caminho mais direto e poderoso.

O fluxo básico é enxuto: o SimpleDirectoryReader carrega documentos de uma pasta (lidando com vários formatos automaticamente), o VectorStoreIndex cria o índice vetorial, e o query engine responde perguntas sobre ele. Há também o SummaryIndex, otimizado para resumos do conjunto inteiro. Em poucas linhas, você tem um RAG funcional — e depois refina.

from llama_index.core import VectorStoreIndex, SimpleDirectoryReader

docs = SimpleDirectoryReader("documentos/").load_data()
indice = VectorStoreIndex.from_documents(docs)

motor = indice.as_query_engine(similarity_top_k=3)
resposta = motor.query("Qual o prazo de reembolso?")
print(resposta)              # resposta + nós-fonte recuperados

Para aplicações sérias, dois componentes se destacam. O RouterQueryEngine roteia a pergunta para o índice certo entre vários (ex.: perguntas de RH vão para o índice de RH, de produto para o de produto). O SubQuestionQueryEngine quebra uma pergunta complexa em sub-perguntas, responde cada uma e sintetiza — essencial quando uma única pergunta exige cruzar várias fontes.

Na prática: para RAG e tudo que gira em torno de dados/documentos, o LlamaIndex costuma ser mais direto e poderoso. Para orquestração geral, agentes e fluxos complexos com muitas ferramentas, o LangChain/LangGraph (M3.6/M3.7) tende a ser mais flexível. Não é "um ou outro" — muitos projetos usam LlamaIndex para a camada de RAG dentro de uma aplicação LangChain. Conheça os dois e escolha por tarefa.

💡 Analogia · A ferramenta especializada

Se RAG é fazer um furo perfeito em concreto, o LlamaIndex é a furadeira de impacto feita exatamente para isso, enquanto o LangChain é uma multiferramenta versátil. Para o furo no concreto, a especializada faz mais rápido e melhor. Para uma obra inteira com tarefas variadas, a multiferramenta brilha. O profissional tem as duas e sabe quando pegar cada uma.

📌 Mini-caso real · RAG enterprise sobre múltiplas bases

Uma empresa precisava de um assistente que respondesse sobre RH, jurídico e produto — cada um com sua base e suas permissões. Usando o RouterQueryEngine do LlamaIndex, cada pergunta era roteada ao índice correto, e o SubQuestionQueryEngine lidava com perguntas que cruzavam áreas. Foi a estrutura que transformou três RAGs isolados num assistente unificado e organizado.

✏️ Exercício prático · Monte um RAG com LlamaIndex
  1. Carregue alguns documentos de uma pasta com o SimpleDirectoryReader e crie um VectorStoreIndex.
  2. Faça perguntas pelo query engine e inspecione os nós-fonte que ele recuperou.
  3. Desafio: crie dois índices temáticos e use um RouterQueryEngine para rotear perguntas ao índice certo.
Checklist da aula0/3
Conheço os componentes do LlamaIndex
Sei usar Router e SubQuestion query engines
Sei quando preferir LlamaIndex ou LangChain
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Para que serve o RouterQueryEngine do LlamaIndex?
A
Treinar o LLM
B
Rotear cada pergunta para o índice/fonte mais apropriado entre vários
C
Gerar imagens
D
Substituir o banco vetorial
Selecione uma opção
3.31 · M3.5⏱ 21 min

Projeto — RAG empresarial completo

Pipeline ponta a ponta com avaliação RAGAS e deploy FastAPI.

Hora de juntar tudo de M3.5 num projeto real e portável: um chat sobre a base de conhecimento de uma empresa. O usuário pergunta em linguagem natural e recebe respostas precisas, ancoradas nos documentos internos e com citação de fontes. É um dos casos de uso de IA com ROI mais claro — reduz tempo de busca, padroniza respostas e libera as pessoas de procurar em manuais.

Reunindo as peças: (1) ingestão dos documentos (PDF/Word, com extração cuidadosa, M3.5), (2) chunking semântico, (3) embedding e indexação no Chroma, (4) hybrid retrieval + reranking (M3.5 avançado) para máxima precisão, (5) geração com citação de fontes, e (6) avaliação contínua com RAGAS. Cada etapa você já domina isoladamente — o projeto é integrá-las num sistema coeso.

Antes de chamar de "pronto", você mede: monte um conjunto de perguntas com respostas esperadas e rode o RAGAS (M3.4) para aferir faithfulness, relevancy e context recall. Isso transforma "acho que está bom" em números defensáveis — e é exatamente o que diferencia um protótipo de um sistema confiável, além de te dar argumento concreto ao apresentar a um cliente ou chefe.

Por fim, você expõe o RAG como uma API FastAPI (M3.11) com autenticação por API key, para que outros sistemas e interfaces possam consumi-lo com segurança. Esse é o passo que tira o projeto do notebook e o coloca em algo utilizável de verdade — um endpoint que recebe a pergunta e devolve a resposta com fontes.

🚀 Projeto: RAG Empresarial — stack, passos e extensões

Stack: Python · Chroma (vetorial) · OpenAI/Anthropic (embeddings + geração) · BM25 + reranking (Cohere) · RAGAS (avaliação) · FastAPI (API) · auth por API key.

Passos: (1) coletar 10-30 documentos reais de um domínio; (2) ingestão + chunking + indexação no Chroma; (3) implementar hybrid retrieval com reranking; (4) prompt de geração com citação obrigatória de fontes; (5) montar conjunto de avaliação e rodar RAGAS; (6) expor via FastAPI com API key; (7) documentar no GitHub.

Ideias de extensão: interface em Streamlit para usuários não-técnicos; filtros de metadados por departamento/permissão; suporte a tabelas (M3.5); histórico de conversa com memória; dashboard de perguntas mais frequentes; deploy no Railway (M3.11) com monitoramento de custo via Langfuse.

💡 Analogia · Montar o carro com as peças que você fabricou

Ao longo de M3.5 você fabricou cada peça (chunking, embedding, retrieval, reranking, avaliação). Este projeto é montar o carro completo e dar a partida. Não é uma peça nova — é a integração que prova que você sabe construir algo que funciona de ponta a ponta, e não só entender partes isoladas.

📌 Mini-caso real · O assistente interno que economizou horas

Empresas que implementam RAG sobre a base interna relatam ganho direto: em vez de funcionários procurarem em dezenas de PDFs e manuais (ou interromperem colegas), eles perguntam ao assistente e recebem a resposta com a fonte em segundos. Multiplicado por toda a equipe, são muitas horas economizadas por mês — exatamente o tipo de ROI mensurável que você aprendeu a apresentar em M2.4.

✏️ Exercício prático · Construa o RAG empresarial
  1. Escolha um domínio e reúna 10-30 documentos reais (ou públicos) sobre ele.
  2. Monte o pipeline completo: ingestão → chunking → Chroma → hybrid + reranking → geração com citação.
  3. Avalie com RAGAS, exponha via FastAPI com API key e publique tudo no GitHub com um README claro.
Checklist da aula0/3
Sei integrar o pipeline RAG de ponta a ponta
Avalio o sistema com RAGAS (números, não achismo)
Sei expor o RAG como API FastAPI segura
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual etapa transforma "acho que o RAG está bom" em algo defensável?
A
Aumentar o número de documentos
B
Avaliar com RAGAS (faithfulness, relevancy, context recall), gerando métricas objetivas
C
Trocar o modelo
D
Usar mais tokens
Selecione uma opção
3.32 · M3.6⏱ 12 min

LangChain core e LCEL

PromptTemplate, ChatModels, OutputParsers e o operador pipe.

O LangChain é um framework para compor aplicações de LLM: encadear prompts, modelos, parsers, ferramentas e fontes de dados em pipelines. Em vez de escrever toda a "cola" entre componentes na mão, você usa peças padronizadas que se conectam. É um dos frameworks mais populares — e dominá-lo acelera muito a construção de aplicações sérias.

Três peças fundamentais: o PromptTemplate (um molde de prompt com variáveis a preencher), o ChatModel (a abstração do LLM, trocável entre providers) e o OutputParser (que transforma a saída do modelo no formato que você quer — string, lista, JSON). Esses três já formam o esqueleto de muitas aplicações.

A grande elegância moderna do LangChain é a LCEL (LangChain Expression Language): você conecta componentes com o operador pipe (|), lendo o fluxo da esquerda para a direita, como uma linha de montagem. prompt | modelo | parser significa "preencha o prompt, mande ao modelo, parseie a saída". É declarativo, legível e ganha streaming e execução assíncrona de graça.

from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser

prompt = ChatPromptTemplate.from_template(
    "Resuma em 1 frase, em PT-BR: {texto}")
modelo = ChatOpenAI(model="gpt-4o", temperature=0)

chain = prompt | modelo | StrOutputParser()   # LCEL: pipe
print(chain.invoke({"texto": "..."}))          # executa a linha de montagem

A LCEL traz peças para fluxos mais ricos: o RunnablePassthrough (passa a entrada adiante, útil para preservar dados), o RunnableParallel (executa vários ramos ao mesmo tempo) e o RunnableLambda (insere uma função Python sua no meio do fluxo). Com elas, você monta pipelines que buscam dados, processam em paralelo e combinam resultados — tudo de forma declarativa e composável.

💡 Analogia · A linha de montagem

A LCEL é uma linha de montagem: a peça entra de um lado, passa por estações (preencher prompt, gerar, parsear) conectadas pelo pipe |, e sai pronta do outro. Você desenha o fluxo lendo da esquerda para a direita, e pode adicionar ou trocar estações sem refazer a fábrica inteira. Clareza e modularidade.

📌 Mini-caso real · Por que a LCEL pegou

Antes da LCEL, montar fluxos no LangChain era mais verboso e difícil de ler. O operador pipe tornou os pipelines declarativos e enxutos — e, de bônus, ganharam streaming e execução assíncrona automaticamente. Foi uma mudança que tornou o framework muito mais agradável e produtivo, e hoje é o jeito padrão de construir com LangChain.

✏️ Exercício prático · Monte sua primeira chain
  1. Crie um PromptTemplate com uma variável e conecte-o a um ChatModel e a um StrOutputParser usando o pipe (LCEL).
  2. Execute com invoke e depois experimente o stream para ver a resposta chegando aos poucos.
  3. Adicione um RunnableLambda que pós-processa a saída (ex.: deixa tudo em maiúsculas).
Checklist da aula0/3
Conheço PromptTemplate, ChatModel e OutputParser
Sei montar chains com LCEL (pipe |)
Entendo Runnables (Passthrough, Parallel, Lambda)
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que o operador pipe (|) faz na LCEL do LangChain?
A
Comenta o código
B
Conecta componentes num fluxo declarativo (ex.: prompt | modelo | parser), como uma linha de montagem
C
Cria um banco vetorial
D
Treina o modelo
Selecione uma opção
3.33 · M3.6⏱ 15 min

Memory em LangChain

Buffer, Summary, VectorStore e Entity Memory.

Um LLM é, por natureza, sem estado: cada chamada não lembra da anterior. Para construir um chatbot que mantém uma conversa coerente, você precisa gerenciar a memória — guardar o histórico e reinjetá-lo a cada turno. O LangChain oferece várias estratégias, cada uma com um equilíbrio diferente entre completude e custo (tokens).

A ConversationBufferMemory simplesmente guarda todo o histórico e o reenvia a cada turno. É a mais simples e fiel, mas tem um problema claro: conversas longas estouram a context window e ficam caras (cada turno reenvia tudo, M2.5). Funciona muito bem para conversas curtas; em longas, vira um problema de custo e de limite.

Para conversas longas, há alternativas inteligentes. A ConversationSummaryMemory usa um LLM para resumir o histórico conforme ele cresce, mantendo o essencial num espaço pequeno. A VectorStoreRetrieverMemory guarda o histórico como embeddings e recupera só os trechos relevantes à mensagem atual (busca semântica sobre a própria conversa) — economizando tokens e trazendo só o que importa.

A Entity Memory rastreia entidades mencionadas na conversa (pessoas, empresas, preferências) e mantém fatos sobre elas. Assim, se o usuário disse "trabalho na Acme e prefiro respostas curtas", o agente lembra disso turnos depois, mesmo que o histórico bruto já tenha sido resumido. É a base de assistentes que "conhecem" o usuário ao longo da conversa — e prepara o terreno para a memória de longo prazo dos agentes (M3.8).

💡 Analogia · Formas de lembrar de uma reunião

Buffer é gravar a reunião inteira e reouvir tudo toda vez — completo, mas inviável se for longa. Summary é fazer uma ata resumida. VectorStore é ter a gravação indexada e pular direto ao trecho relevante quando precisa. Entity é a folha de anotações com os fatos-chave ("fulano prefere X"). Cada técnica serve a uma necessidade — e você combina conforme o caso.

📌 Mini-caso real · O chatbot que ficou caro demais

Um chatbot usava buffer memory e funcionava bem nos testes (conversas curtas). Em produção, usuários tinham conversas longas, o histórico inteiro era reenviado a cada mensagem, e a conta de tokens disparou — além de o modelo começar a "esquecer" o início ao estourar a janela. Trocando para summary + vector memory, o custo despencou e a coerência melhorou. Escolher a memória certa é decisão de arquitetura e de custo.

✏️ Exercício prático · Compare estratégias de memória
  1. Monte um chatbot simples com ConversationBufferMemory e tenha uma conversa de vários turnos.
  2. Observe como o histórico cresce a cada chamada (e, portanto, o custo em tokens).
  3. Troque para SummaryMemory ou VectorStore memory e compare o tamanho do contexto enviado.
Checklist da aula0/3
Entendo por que LLMs precisam de gestão de memória
Conheço Buffer, Summary e VectorStore memory
Sei o papel da Entity Memory
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual o problema da ConversationBufferMemory em conversas longas?
A
Esquece tudo imediatamente
B
Reenvia todo o histórico a cada turno, estourando a context window e elevando o custo
C
Não funciona em PT-BR
D
Exige GPU
Selecione uma opção
3.34 · M3.6⏱ 18 min

Tools e Tool Calling

Conectar LLMs a funções Python, APIs e bancos de dados.

Sozinho, um LLM só gera texto. As tools (ferramentas) dão a ele mãos: a capacidade de chamar funções Python, APIs e bancos de dados para agir no mundo — buscar na web, consultar um CRM, fazer um cálculo, enviar um e-mail. É o salto conceitual que transforma um chatbot num agente (M3.7). Sem tools, não há agentes.

Lembre dos decorators (M3.1): no LangChain, você transforma uma função Python comum numa ferramenta usável pelo LLM simplesmente colocando @tool acima dela. A docstring da função (sua descrição) é crucial — é por ela que o modelo entende o que a ferramenta faz e quando usá-la. Uma descrição clara é a diferença entre o agente usar a ferramenta certa ou se atrapalhar.

from langchain_core.tools import tool

@tool
def consultar_estoque(produto: str) -> int:
    """Retorna a quantidade em estoque de um produto pelo nome."""
    estoque = {"camiseta": 42, "boné": 7}
    return estoque.get(produto.lower(), 0)

# o LLM lê a docstring e decide chamar esta tool quando
# o usuário perguntar sobre estoque, passando o produto certo

O tool calling (chamada de ferramentas) funciona assim: você dá ao modelo a lista de ferramentas (com nome, descrição e parâmetros via schema Pydantic); diante de uma pergunta, ele decide se e qual ferramenta chamar e com quais argumentos; seu código executa a função e devolve o resultado ao modelo, que então formula a resposta final. OpenAI e Claude têm implementações próprias, mas a lógica é a mesma.

Modelos modernos fazem parallel tool calls — chamam várias ferramentas de uma vez quando faz sentido (ex.: consultar estoque de três produtos), o que se conecta ao async de M3.1 para ganhar velocidade. E o error handling em tools é vital: a função pode falhar (API fora, produto inexistente), e o agente precisa lidar com isso graciosamente — devolvendo um erro tratável em vez de quebrar. Robustez aqui separa um agente confiável de um frágil.

💡 Analogia · Dar ferramentas a um assistente esperto

Um LLM sem tools é um consultor brilhante trancado numa sala vazia — só pode falar. Dar tools é abrir a porta e entregar a ele um telefone (APIs), um arquivo (banco de dados) e uma calculadora (funções). Agora ele não só aconselha: ele age. E a docstring de cada ferramenta é a etiqueta que diz para que serve cada uma.

📌 Mini-caso real · O agente que consulta o sistema real

Quando uma empresa conecta um LLM ao seu CRM, estoque ou base de pedidos via tools, ele deixa de dar respostas genéricas e passa a responder com dados reais e atuais: "seu pedido #1234 sai amanhã", "restam 7 unidades". Essa ponte entre o raciocínio do LLM e os sistemas reais da empresa é onde mora boa parte do valor prático — e tudo começa com tools bem definidas.

✏️ Exercício prático · Crie e conecte uma tool
  1. Escreva uma função Python útil (ex.: consultar um dado, fazer um cálculo) e transforme-a em tool com @tool e uma docstring clara.
  2. Conecte-a a um modelo com tool calling e faça uma pergunta que exija usá-la.
  3. Adicione tratamento de erro na função e teste um caso de falha (ex.: entrada inválida).
Checklist da aula0/3
Entendo o que são tools e por que viram agentes
Sei criar uma tool com @tool e docstring
Entendo tool calling, parallel calls e error handling
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que as "tools" adicionam a um LLM?
A
Mais tokens
B
A capacidade de agir — chamar funções, APIs e bancos de dados — transformando-o de chatbot em agente
C
Imagens
D
Uma context window infinita
Selecione uma opção
3.35 · M3.6⏱ 21 min

Structured Output com Pydantic

Respostas tipadas, validadas e confiáveis para produção.

Para conversar com humanos, texto livre é ótimo. Para integrar em software, é um pesadelo: seu código precisa extrair dados de uma resposta que pode variar de formato a cada chamada. Se o LLM às vezes responde "O preço é R$50" e às vezes "Custa cinquenta reais", seu parser quebra. Em produção, você precisa de saídas estruturadas, tipadas e previsíveis.

O Pydantic (lembre dos type hints, M3.1) é a ferramenta padrão: você define uma classe descrevendo exatamente os campos e tipos que espera (ex.: nome: str, preco: float, em_estoque: bool). Essa classe vira um contrato. O Pydantic gera o JSON schema automaticamente e valida que a resposta segue o formato — rejeitando o que não bate.

from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI

class Produto(BaseModel):
    nome: str = Field(description="nome do produto")
    preco: float = Field(description="preço em reais")
    em_estoque: bool

modelo = ChatOpenAI(model="gpt-4o").with_structured_output(Produto)
resultado = modelo.invoke("Camiseta azul, R$59,90, disponível")
print(resultado.preco, resultado.em_estoque)   # 59.9 True — tipado!

No LangChain, o método with_structured_output() liga o modelo ao seu schema Pydantic: a resposta volta já como um objeto Python validado, não como texto. Por baixo, isso usa o JSON mode / structured outputs (M3.4). Você acessa resultado.preco com segurança de tipo — sem regex, sem parsing frágil. É a diferença entre um pipeline confiável e um que quebra em produção.

Mesmo com structured output, o modelo pode ocasionalmente produzir algo que não valida. Sistemas robustos implementam retry: se a validação Pydantic falhar, devolve-se o erro ao modelo pedindo que corrija, e tenta de novo. Combinado com a validação, isso cria um pipeline que ou entrega dados no formato correto, ou falha de forma controlada e tratável — nunca dados malformados silenciosamente passando adiante.

💡 Analogia · O formulário em vez da redação

Pedir texto livre ao LLM é como pedir uma redação e depois ter que garimpar os dados nela. Structured output com Pydantic é entregar um formulário com campos definidos (nome, preço, sim/não) — o modelo preenche os campos certos, e você lê cada um diretamente. Formulário valida na entrada; redação te obriga a interpretar na saída.

📌 Mini-caso real · A integração que parava de quebrar

Um sistema extraía dados de respostas de LLM com regex e vivia quebrando quando o modelo mudava a redação. Migrando para structured output com Pydantic, as respostas passaram a vir sempre no mesmo formato validado, e as quebras pararam. Foi a mudança que tornou o pipeline confiável o suficiente para produção — e encerra M3.6 preparando você para construir agentes robustos.

✏️ Exercício prático · Force uma saída tipada
  1. Defina um schema Pydantic para uma tarefa de extração (ex.: extrair de um texto: nome, valor e categoria).
  2. Use with_structured_output() e rode em 3 textos diferentes, confirmando que sempre volta no mesmo formato.
  3. Acesse os campos do objeto retornado com segurança de tipo (ex.: resultado.valor + 10).
Checklist da aula0/3
Entendo o problema do texto livre em produção
Sei definir schemas com Pydantic
Sei usar with_structured_output e retry de validação
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que usar Pydantic + structured output em vez de texto livre em produção?
A
Para deixar a resposta mais criativa
B
Para obter saídas tipadas e validadas num formato previsível, evitando parsing frágil que quebra
C
Para reduzir o custo do modelo
D
Porque é obrigatório no Python
Selecione uma opção
3.36 · M3.7⏱ 12 min

O que é um agente

Anatomia, loop percepção-decisão-ação e a diferença de um chatbot.

Um chatbot responde: você pergunta, ele gera texto, fim. Um agente age: ele recebe um objetivo, decide o que fazer, usa ferramentas (M3.6), observa o resultado e continua até concluir — em vários passos, sem você guiar cada um. A diferença é entre "me diga como fazer X" e "faça X". Essa autonomia é o que torna os agentes poderosos — e também o que os torna difíceis de controlar.

Quatro componentes formam um agente. O LLM é o cérebro (raciocina e decide). As Tools são as mãos (agem no mundo — M3.6). A Memory é a memória (mantém contexto e aprendizados — M3.6/M3.8). E o Planner é o estrategista (decompõe o objetivo em passos). Nem todo agente tem os quatro explícitos, mas entendê-los te dá o mapa mental para projetar e depurar qualquer agente.

O agente opera em loop: ele percebe o estado atual (a tarefa, resultados anteriores), decide a próxima ação (responder? chamar uma ferramenta? terminar?), age (executa), observa o resultado, e repete. Esse ciclo continua até o objetivo ser atingido (ou um limite ser batido). Entender esse loop é entender como o agente "pensa" — e onde ele pode entrar em parafuso.

Agentes são poderosos e frágeis. As falhas clássicas: loops infinitos (o agente repete a mesma ação sem progredir, queimando tokens e dinheiro), alucinações de tool use (chama uma ferramenta inexistente ou com argumentos errados), e falta de contexto (perde o fio do objetivo). Conhecer esses modos de falha desde já é essencial — boa parte da engenharia de agentes é justamente preveni-los com limites, validação e supervisão.

💡 Analogia · O assistente autônomo vs. o que só responde

Um chatbot é como um colega que responde perguntas quando você o procura. Um agente é como um assistente a quem você delega uma tarefa inteira ("organize esta viagem") e que, sozinho, pesquisa voos, compara, reserva e te avisa — tomando decisões e agindo pelo caminho. Mais útil, mas você precisa confiar (e supervisionar) o julgamento dele.

📌 Mini-caso real · O loop infinito que custou caro

Um caso recorrente entre quem começa com agentes: um agente entra num loop — tenta uma ação, falha, tenta a mesma coisa de novo, falha, e repete dezenas de vezes, cada iteração consumindo tokens pagos. Sem um limite de iterações ou detecção de loop, a conta de API dispara em minutos. É por isso que limites e guardrails não são opcionais — são parte do design responsável de agentes.

✏️ Exercício prático · Mapeie um agente
  1. Pense numa tarefa que você delegaria a um agente (ex.: pesquisar e resumir um tema).
  2. Identifique os 4 componentes para essa tarefa: qual o LLM, quais tools, qual memória, qual o plano.
  3. Liste 2 formas pelas quais esse agente poderia falhar (loop? tool errada?) e como você as preveniria.
Checklist da aula0/3
Diferencio chatbot de agente
Conheço a anatomia (LLM, tools, memory, planner)
Entendo o loop agentic e os modos de falha
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual a diferença fundamental entre um agente e um chatbot?
A
Agente é mais rápido
B
O agente recebe um objetivo e age em vários passos usando ferramentas, enquanto o chatbot apenas responde
C
Chatbot usa GPU
D
Não há diferença
Selecione uma opção
3.37 · M3.7⏱ 15 min

ReAct

Reasoning + Acting — o padrão de agente mais usado do mundo.

O ReAct (do paper de Yao et al., 2022) é o padrão de agente mais influente. O nome junta Reasoning (raciocinar) + Acting (agir). A sacada: em vez de o agente só agir ou só pensar, ele alterna os dois num ciclo explícito — pensa sobre o que fazer, age, observa o resultado, e pensa de novo com base na observação. Esse entrelaçamento de pensamento e ação é o que dá robustez.

Concretamente, o ReAct gera uma sequência: Thought (o agente raciocina: "preciso descobrir o preço, vou usar a ferramenta de busca") → Action (chama a ferramenta) → Observation (recebe o resultado) → Thought (raciocina sobre o que obteve) → ... até concluir. Cada passo é registrado, tornando o raciocínio do agente transparente e depurável — você vê por que ele fez cada coisa.

# O agente gera, a cada iteração, algo como:
# Thought: O usuário quer o clima em SP. Vou usar a tool de clima.
# Action: consultar_clima(cidade="São Paulo")
# Observation: 24°C, parcialmente nublado
# Thought: Tenho a informação. Posso responder.
# Answer: Em São Paulo está 24°C e parcialmente nublado.

# No loop, você intercala chamadas ao LLM (Thought/Action)
# com a execução real das tools (gerando a Observation).

Vale implementar o ReAct do zero ao menos uma vez (um loop que chama o LLM, parseia a Action, executa a tool, devolve a Observation) — isso desmistifica o que frameworks como LangGraph fazem por baixo. Na produção, porém, você usará frameworks (M3.8) que implementam ReAct de forma robusta. Entender o mecanismo te dá poder de depurar quando o agente do framework se comporta de forma estranha.

O ReAct herda os riscos de agentes (M3.7): pode entrar em loop (repetir o mesmo Thought/Action sem avançar) ou alucinar uma Action inválida. A engenharia prática exige guardrails: limite máximo de iterações, detecção de ações repetidas, validação de que a tool e os argumentos existem. Detectar um loop antes que ele queime tokens é uma habilidade concreta — e a diferença entre um agente de produção e um experimento perigoso.

💡 Analogia · O detetive que narra o raciocínio

O ReAct é como um detetive que pensa em voz alta: "Hmm, preciso do álibi (Thought). Vou checar as câmeras (Action). As câmeras mostram ele no local (Observation). Então o álibi é falso (Thought)...". Esse narrar-pensar-agir torna cada passo justificado e auditável — você acompanha o raciocínio e identifica onde ele errou, se errar.

📌 Mini-caso real · Por que o ReAct virou padrão

O ReAct se tornou onipresente porque resolve um problema real: agentes que só agem (sem raciocinar) cometem erros bobos, e agentes que só raciocinam (sem agir) não conseguem buscar informação que não têm. Ao intercalar os dois e tornar o processo transparente, o ReAct entrega agentes mais confiáveis e depuráveis. É a base sobre a qual frameworks modernos como o LangGraph são construídos.

✏️ Exercício prático · Implemente um mini-ReAct
  1. Crie um loop simples: chame o LLM pedindo um "Thought" e uma "Action" (nome de tool + argumento) num formato fixo.
  2. Parseie a Action, execute a tool de verdade e devolva a "Observation" ao LLM na próxima iteração.
  3. Adicione um limite máximo de iterações para evitar loop infinito — e teste forçando um caso difícil.
Checklist da aula0/3
Entendo o ciclo Thought→Action→Observation
Sei por que intercalar raciocínio e ação é robusto
Sei prevenir loops com guardrails (limite de iterações)
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que caracteriza o padrão ReAct?
A
Só raciocinar, nunca agir
B
Intercalar Reasoning (Thought) e Acting (Action), observando o resultado a cada passo
C
Só agir, nunca raciocinar
D
Treinar o modelo do zero
Selecione uma opção
3.38 · M3.7⏱ 18 min

LangGraph

StateGraph, nodes, edges condicionais e checkpointing.

As primeiras abstrações de agentes (como o AgentExecutor do LangChain) eram caixas-pretas: difíceis de controlar e depurar. O LangGraph trouxe uma abordagem melhor — modelar o agente como um grafo explícito de estados e transições. Você desenha o fluxo (quais passos existem, como se conectam, quando ramificar), ganhando controle, transparência e a capacidade de criar comportamentos complexos de forma confiável.

No LangGraph, você define um StateGraph: um estado compartilhado (tipicamente um TypedDict com os dados que fluem pelo agente), nodes (os passos — cada um é uma função que lê e atualiza o estado) e edges (as conexões que determinam o próximo node). É como desenhar um fluxograma executável: cada caixa é um node, cada seta é um edge.

from langgraph.graph import StateGraph, END
from typing import TypedDict

class Estado(TypedDict):
    pergunta: str
    resposta: str

def responder(estado):
    return {"resposta": f"Resposta para: {estado['pergunta']}"}

grafo = StateGraph(Estado)
grafo.add_node("responder", responder)
grafo.set_entry_point("responder")
grafo.add_edge("responder", END)
agente = grafo.compile()
print(agente.invoke({"pergunta": "O que é LangGraph?"}))

O poder real vem dos conditional edges (arestas condicionais): o próximo passo depende do resultado do anterior. Por exemplo, após o LLM decidir, o grafo roteia para "usar ferramenta" ou para "responder ao usuário" conforme a decisão. Isso permite construir o loop ReAct (M3.7) de forma controlada e visível — o ciclo pensar/agir vira um grafo com ramificações explícitas, fácil de seguir e ajustar.

Dois recursos completam o quadro. O checkpointing (com o MemorySaver) salva o estado do agente entre passos — permitindo pausar, retomar e manter conversas com memória persistente (e habilita o human-in-the-loop de M3.8). E o LangSmith é a ferramenta de observabilidade: ele registra cada passo do agente (cada Thought, Action, chamada de LLM), tornando possível ver exatamente o que aconteceu e depurar comportamentos estranhos — indispensável em agentes de produção.

💡 Analogia · O mapa do metrô

O AgentExecutor era como andar numa cidade sem mapa, confiando que o motorista (a abstração) sabe o caminho. O LangGraph é o mapa do metrô: você vê todas as estações (nodes), as linhas que as conectam (edges) e onde pode trocar de linha conforme a situação (conditional edges). Com o mapa na mão, você controla a rota e entende exatamente onde algo deu errado.

📌 Mini-caso real · Do agente imprevisível ao confiável

Equipes que migraram agentes do AgentExecutor para o LangGraph relatam o mesmo ganho: o que era imprevisível e difícil de depurar virou um fluxo explícito e controlável. Quando o agente se comporta mal, o grafo + LangSmith mostram exatamente em qual node e por quê. Esse controle é o que viabiliza levar agentes a produção com confiança — e por isso o LangGraph se tornou padrão.

✏️ Exercício prático · Construa um grafo com ramificação
  1. Crie um StateGraph com um estado (TypedDict) e dois nodes.
  2. Adicione um conditional edge que roteia para um node ou outro conforme um valor do estado.
  3. Compile e teste com entradas que disparem cada caminho — confirme que o roteamento funciona.
Checklist da aula0/3
Entendo StateGraph, nodes e edges
Sei usar conditional edges para rotear
Conheço checkpointing e o LangSmith para depurar
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual a principal vantagem do LangGraph sobre abstrações como o AgentExecutor?
A
É mais lento
B
Modela o agente como um grafo explícito de estados e transições, dando controle, transparência e depuração
C
Não usa LLM
D
Elimina a necessidade de tools
Selecione uma opção
3.39 · M3.7⏱ 21 min

Padrões de agentes

Sequencial, paralelo, routing, supervisor, map-reduce e sub-grafos.

Assim como na engenharia de software há "design patterns", a construção de agentes desenvolveu padrões reutilizáveis para estruturar fluxos. Conhecê-los te poupa de reinventar a roda e te dá um vocabulário para projetar soluções. A escolha do padrão certo depende da natureza da tarefa — e usar o padrão errado complica o que poderia ser simples.

Os três padrões básicos. Sequencial: passos em ordem (A → B → C), quando cada etapa depende da anterior. Paralelo: tarefas independentes executadas ao mesmo tempo (via Send() no LangGraph, ligado ao async de M3.1) — muito mais rápido quando não há dependência. Routing: um node decide, com base no input, para qual ramo seguir (ex.: classificar a pergunta e mandar ao especialista certo) — o conditional edge de M3.7 em ação.

Para tarefas complexas, padrões mais sofisticados. O supervisor é um agente "gerente" que recebe a tarefa e delega a sub-agentes especializados, coordenando o trabalho deles (prepara o terreno para multi-agentes, M3.8). Os sub-grafos permitem encapsular um fluxo inteiro como um componente reutilizável dentro de um grafo maior — modularidade que mantém sistemas grandes organizados e testáveis.

O map-reduce é poderoso para processar muitos itens: na fase map, a mesma operação roda em paralelo sobre cada item (resumir cada um de 50 documentos); na fase reduce, os resultados são combinados (sintetizar os 50 resumos num relatório). Combinado com paralelismo, processa grandes volumes de forma eficiente — um padrão clássico que se aplica lindamente a agentes lidando com muitos dados.

💡 Analogia · Como organizar uma equipe

Esses padrões são formas de organizar uma equipe para uma tarefa. Sequencial é uma linha de montagem. Paralelo é dividir e cada um faz sua parte ao mesmo tempo. Routing é um recepcionista que encaminha cada caso ao especialista. Supervisor é o gerente que delega e cobra. Map-reduce é "cada um resume um capítulo, e depois alguém junta tudo". Você escolhe a organização conforme o trabalho.

📌 Mini-caso real · O relatório que ficou 10x mais rápido

Uma tarefa de analisar e resumir dezenas de documentos rodava em sequência e era lenta. Reestruturada com map-reduce (resumir cada documento em paralelo, depois combinar), o tempo caiu drasticamente — porque as operações independentes passaram a rodar simultaneamente, em vez de uma esperando a outra. O padrão certo, somado ao async, transformou a viabilidade da tarefa.

✏️ Exercício prático · Escolha o padrão certo
  1. Para 3 tarefas (ex.: pipeline de etapas dependentes; resumir 100 docs; rotear perguntas por tema), diga qual padrão usar.
  2. Implemente um fluxo paralelo simples no LangGraph (dois nodes independentes rodando juntos).
  3. Esboce como um "supervisor" delegaria uma tarefa complexa a dois sub-agentes especializados.
Checklist da aula0/3
Conheço os padrões sequencial, paralelo e routing
Entendo supervisor e sub-grafos
Sei aplicar map-reduce para muitos itens
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual padrão é ideal para processar muitos itens independentes e depois combinar os resultados?
A
Sequencial
B
Map-reduce (processar cada item em paralelo, depois combinar)
C
Routing simples
D
Nenhum
Selecione uma opção
3.40 · M3.7⏱ 12 min

OpenAI Assistants API v2

Threads, Runs, Code Interpreter e File Search.

A Assistants API v2 da OpenAI é uma forma gerenciada de construir agentes, em que a própria OpenAI cuida de partes trabalhosas — sobretudo o gerenciamento automático de contexto (o histórico da conversa, sem você gerenciar a memória manualmente). É uma alternativa de mais alto nível ao "montar tudo você mesmo" com LangGraph, trocando flexibilidade por conveniência.

Dois conceitos centrais. Uma Thread é uma conversa persistente (a OpenAI guarda o histórico para você, sem precisar reenviar tudo a cada turno). Um Run é uma execução do assistente sobre uma thread — quando você pede uma resposta, cria-se um Run que processa a thread e gera o resultado. Esse modelo abstrai boa parte da gestão de estado que você faria à mão.

O Code Interpreter é uma ferramenta poderosa: dá ao assistente um ambiente sandbox onde ele escreve e executa código Python para resolver tarefas — analisar uma planilha, gerar um gráfico, fazer cálculos complexos. O usuário sobe um arquivo e pede "analise estes dados", e o assistente programa a análise sozinho, dentro do sandbox. É IA que não só fala sobre dados, mas os processa de verdade.

O File Search é RAG nativo (M3.5) embutido: você sobe documentos e o assistente os consulta automaticamente, sem você montar o pipeline de chunking/embedding/retrieval. A decisão prática: a Assistants API brilha quando você quer rapidez e conveniência e está confortável no ecossistema OpenAI; o LangGraph vence quando precisa de controle fino, portabilidade entre providers e fluxos complexos customizados. Conveniência vs. controle, de novo.

💡 Analogia · Carro automático vs. câmbio manual

A Assistants API é um carro automático: a OpenAI gerencia as "trocas de marcha" (contexto, estado, RAG nativo) para você, e você só dirige. O LangGraph é o câmbio manual: mais trabalho, mas controle total sobre cada troca, e você pode dirigir qualquer carro (provider). Para muitos trajetos, o automático basta e é mais cômodo; para pilotagem fina, o manual ganha.

📌 Mini-caso real · O analista de dados conversacional

Com o Code Interpreter, equipes criaram assistentes onde um usuário não-técnico sobe uma planilha e pede em linguagem natural: "qual produto vendeu mais por região e me faça um gráfico". O assistente escreve o Python, executa no sandbox e devolve a análise e o gráfico. É a democratização da análise de dados — sem que o usuário escreva uma linha de código, e sem você montar a infraestrutura.

✏️ Exercício prático · Explore a Assistants API
  1. Crie um assistente simples com a Assistants API, uma thread e um run para uma pergunta.
  2. Habilite o File Search subindo um documento e faça uma pergunta sobre ele (RAG nativo).
  3. Reflita e anote: para o seu caso de uso, você usaria a Assistants API ou o LangGraph? Justifique (conveniência vs. controle).
Checklist da aula0/3
Entendo Threads e Runs
Conheço o Code Interpreter e o File Search
Sei decidir entre Assistants API e LangGraph
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que o "Code Interpreter" da Assistants API permite ao assistente fazer?
A
Apenas conversar
B
Escrever e executar código Python num sandbox para analisar dados, gerar gráficos e fazer cálculos
C
Gerar vídeos
D
Treinar modelos
Selecione uma opção
3.41 · M3.8⏱ 15 min

CrewAI

Agents com roles, tasks e processos sequencial e hierárquico.

O CrewAI organiza múltiplos agentes como uma equipe (crew), inspirado em como times humanos funcionam: cada membro tem um papel, recebe tarefas e colabora. É um framework de alto nível, intuitivo, ótimo para quem quer montar sistemas multi-agentes rapidamente com uma abstração que faz sentido — "monte uma equipe de IA, dê papéis e tarefas, e deixe-os trabalhar".

Cada Agent no CrewAI é definido por: role (o cargo: "pesquisador sênior"), goal (o objetivo dele), backstory (um histórico que molda a personalidade e a expertise — surpreendentemente eficaz para guiar o comportamento) e as tools que ele pode usar. Essa definição rica faz cada agente se comportar como um especialista distinto no seu papel.

from crewai import Agent, Task, Crew, Process

pesquisador = Agent(
    role="Pesquisador de Mercado",
    goal="Encontrar dados atuais e confiáveis sobre {tema}",
    backstory="Analista experiente, meticuloso com fontes.",
    tools=[ferramenta_busca],
    verbose=True,
)

A Task define o trabalho: uma description (o que fazer), o expected_output (o formato/resultado esperado) e o agent responsável. A Crew reúne agentes e tarefas e define o process: sequential (as tarefas rodam em ordem, cada agente passando o resultado ao próximo) ou hierarchical (um agente gerente coordena e delega aos demais — o padrão supervisor de M3.7). A escolha do processo molda como a equipe colabora.

Para projetos limpos, o CrewAI suporta definir agentes e tarefas em arquivos YAML separados do código — o que organiza e facilita ajustes sem mexer na lógica. E você cria ferramentas customizadas com o mesmo @tool de M3.6, dando à equipe acesso a APIs, bancos e funções específicas do seu domínio. É a ponte entre a abstração elegante e o seu stack real.

💡 Analogia · Montar uma agência

Usar o CrewAI é como montar uma pequena agência: você contrata um pesquisador, um analista e um redator (agents com roles e backstories), distribui as tarefas (tasks) e define como trabalham juntos — em linha de montagem (sequential) ou com um diretor coordenando (hierarchical). Cada um faz sua parte com expertise, e a equipe entrega mais que qualquer um sozinho.

📌 Mini-caso real · A equipe de IA que produz relatórios

Um uso clássico do CrewAI: uma crew com um pesquisador (busca dados na web), um analista (processa e interpreta) e um redator (escreve o relatório final). Você pede um relatório sobre um tema, e a equipe colabora — pesquisa, análise, redação — entregando um documento completo. É o tipo de pipeline multi-agente que vira o Projeto 3 (P.03) desta etapa.

✏️ Exercício prático · Monte sua primeira crew
  1. Defina 2 agentes com roles, goals e backstories distintos (ex.: pesquisador e redator).
  2. Crie uma task para cada e monte uma Crew com process sequencial.
  3. Rode a crew num tema simples e observe como o resultado de um agente alimenta o próximo.
Checklist da aula0/3
Entendo a filosofia de "equipe" do CrewAI
Sei definir Agent (role, goal, backstory, tools)
Conheço Task, Crew e os processos sequential/hierarchical
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Como o CrewAI organiza um sistema multi-agente?
A
Um único agente fazendo tudo
B
Como uma equipe: agentes com papéis (roles) e tarefas (tasks), colaborando em processo sequential ou hierarchical
C
Sem nenhuma estrutura
D
Apenas com prompts soltos
Selecione uma opção
3.42 · M3.8⏱ 18 min

AutoGen / AG2

Conversas entre múltiplos agentes e GroupChat.

O AutoGen (e sua continuação comunitária AG2) tem uma filosofia distinta do CrewAI: em vez de papéis e tarefas fixas, os agentes conversam entre si para resolver problemas. É como uma reunião de especialistas que debatem, criticam e refinam ideias coletivamente até chegar a uma solução — colaboração emergente através do diálogo.

Os principais: o ConversableAgent (base, capaz de conversar), o AssistantAgent (um especialista movido por LLM) e o UserProxyAgent (representa o usuário, podendo executar código e pedir input humano). A combinação típica é um AssistantAgent que propõe soluções e um UserProxyAgent que as testa/executa e dá feedback — um ciclo de proposta e verificação.

Para mais de dois agentes, há o GroupChat, coordenado por um GroupChatManager: vários agentes participam de uma conversa em grupo, e o manager decide quem fala a seguir (as speaker selection strategies). É como um moderador de mesa-redonda que dá a palavra ao especialista certo no momento certo — orquestrando o debate para que ele seja produtivo, e não caótico.

Há uma intuição poderosa por trás: múltiplos agentes debatendo frequentemente chegam a soluções melhores que um único. Um propõe, outro critica e aponta falhas, um terceiro sugere melhorias — emulando como equipes humanas refinam ideias. Esse "debate" reduz erros individuais e explora mais ângulos. É o mesmo princípio da revisão por pares, aplicado a agentes de IA.

💡 Analogia · A mesa-redonda de especialistas

O AutoGen é uma mesa-redonda: especialistas (agentes) debatem um problema, cada um trazendo sua perspectiva, criticando e construindo sobre as ideias dos outros, com um moderador (GroupChatManager) dando a palavra. A solução emerge do diálogo, geralmente mais refinada do que se um único especialista tivesse decidido sozinho.

📌 Mini-caso real · Proposta e crítica que melhoram o código

Um padrão eficaz no AutoGen: um agente "programador" escreve código e um agente "revisor/crítico" o analisa, aponta bugs e sugere melhorias, num ciclo até o código ficar sólido. Esse debate entre propor e criticar produz resultados melhores que um único agente gerando código sem revisão — exatamente como um par de programadores humanos se revisando.

✏️ Exercício prático · Crie um debate de agentes
  1. Monte dois agentes no AutoGen: um que propõe uma solução e um que a critica/melhora.
  2. Faça-os conversar sobre um problema simples e observe o refinamento ao longo do diálogo.
  3. Reflita: em que tipo de tarefa o "debate" entre agentes traria mais valor que um agente único?
Checklist da aula0/3
Entendo a abordagem conversacional do AutoGen
Conheço os tipos de agente e o GroupChat
Sei por que o debate entre agentes melhora resultados
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual a filosofia central do AutoGen/AG2?
A
Um agente único fazendo tudo
B
Agentes que conversam e debatem entre si para refinar soluções coletivamente
C
Não usar LLMs
D
Apenas gerar imagens
Selecione uma opção
3.43 · M3.8⏱ 21 min

Human-in-the-Loop

interrupt(), breakpoints e aprovação humana em workflows.

Agentes agem com autonomia (M3.7), mas há ações irreversíveis ou de alto impacto — enviar um e-mail a um cliente, fazer um deploy, publicar conteúdo, mover dinheiro — em que deixar a IA decidir sozinha é arriscado demais. O human-in-the-loop (humano no circuito) insere um ponto de aprovação humana antes dessas ações. É o equilíbrio entre automação e controle: a IA faz o trabalho, o humano dá o aval no momento crítico.

O LangGraph implementa isso de forma elegante. A função interrupt() pausa o agente num ponto definido, aguardando input humano antes de continuar. Os breakpoints marcam onde o fluxo deve parar para revisão. Graças ao checkpointing (M3.7), o estado é preservado durante a pausa — o agente "congela", espera a decisão humana, e retoma exatamente de onde parou quando aprovado.

# No LangGraph, antes de uma ação irreversível:
#   interrupt() pausa o grafo e salva o estado (checkpoint)
#   -> o humano revisa a ação proposta (ex.: o e-mail a enviar)
#   -> se aprova, o grafo retoma e executa a ação
#   -> se rejeita, segue um caminho alternativo

# Exemplo de ponto de interrupção antes de "enviar_email":
grafo.compile(checkpointer=memory, interrupt_before=["enviar_email"])

Na prática, o human-in-the-loop precisa de uma interface de aprovação: onde o humano o que o agente quer fazer (o e-mail redigido, a transação proposta) e aprova, edita ou rejeita. Pode ser uma tela, uma mensagem no Slack, um e-mail de confirmação. O bom design mostra contexto suficiente para uma decisão informada, sem sobrecarregar — e registra quem aprovou o quê (auditoria).

A regra prática: insira aprovação humana antes de ações irreversíveis, custosas ou sensíveis, e deixe o agente autônomo no que é reversível e de baixo risco. Pedir aprovação para tudo mata o ganho da automação; não pedir para nada é perigoso. O ponto ótimo — automatizar o seguro, revisar o crítico — conecta-se diretamente à IA responsável (M2.6): supervisão humana onde o erro custa caro.

💡 Analogia · O estagiário que pede aval

Um agente com human-in-the-loop é como um estagiário competente e de confiança: ele faz quase tudo sozinho, mas, antes de enviar um e-mail importante ao cliente ou apertar um botão irreversível, ele bate na sua porta: "vou fazer isso, pode?". Você revisa em segundos e aprova. Autonomia no rotineiro, aprovação no crítico.

📌 Mini-caso real · A aprovação que evitou o e-mail errado

Cenário típico de um agente de vendas (P.02): o agente redige e está prestes a enviar uma proposta a um cliente importante. Com human-in-the-loop, o vendedor revisa a mensagem antes do envio — e pega um detalhe que o agente errou (um valor, um nome). Sem essa etapa, o erro iria direto ao cliente. A aprovação humana no ponto certo é barata e evita estragos caros.

✏️ Exercício prático · Adicione aprovação a um agente
  1. Pegue um fluxo de agente que termina numa ação "sensível" (ex.: enviar mensagem).
  2. Insira um ponto de interrupção (interrupt/breakpoint) antes dessa ação.
  3. Simule o ciclo: o agente pausa mostrando o que fará, você "aprova", e ele retoma e executa.
Checklist da aula0/3
Entendo por que e quando usar human-in-the-loop
Sei usar interrupt() e breakpoints no LangGraph
Sei desenhar uma interface de aprovação e o critério de uso
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Quando faz mais sentido inserir aprovação humana (human-in-the-loop) num agente?
A
Para absolutamente toda ação
B
Antes de ações irreversíveis, custosas ou sensíveis (enviar e-mail, deploy, mover dinheiro)
C
Nunca, agentes devem ser 100% autônomos
D
Só em tarefas de leitura
Selecione uma opção
3.44 · M3.8⏱ 12 min

Memória de longo prazo em agentes

LangMem, Redis e memória persistente — episódica, semântica e procedimental.

A memória de M3.6 (Buffer, Summary) vive dentro de uma conversa. Mas um agente verdadeiramente útil precisa lembrar entre sessões: que você prefere respostas curtas, que já resolveu tal problema semana passada, que seu cliente X tem tal histórico. Sem memória de longo prazo, o agente é como alguém com amnésia que se reapresenta a cada encontro — incapaz de construir relacionamento ou aprender com o passado.

A ciência cognitiva (e os agentes) distinguem três tipos. A memória episódica guarda o que aconteceu (eventos, interações passadas: "na última conversa, resolvemos o bug X"). A memória semântica guarda fatos sobre o mundo e o usuário ("o cliente prefere contato por e-mail, trabalha na Acme"). A memória procedimental guarda como fazer algo (procedimentos e padrões aprendidos). Um agente rico combina os três.

Ferramentas emergentes como o LangMem ajudam a gerenciar memória de longo prazo de agentes — extraindo, armazenando e recuperando o que importa de forma estruturada. Elas resolvem o trabalho de decidir o que vale guardar (nem tudo deve ser memorizado), como organizar, e quando recuperar — transformando a memória de um amontoado de logs num conhecimento útil e acessível.

Na prática, a memória persistente costuma combinar um armazenamento rápido como o Redis (para guardar e recuperar dados de sessão e fatos com baixa latência) com embeddings (M3.4) para busca semântica sobre as memórias — recuperando as mais relevantes ao contexto atual, não todas. É a mesma lógica da VectorStore memory (M3.6), agora persistindo entre sessões e estruturada por tipo de memória.

💡 Analogia · O atendente que te conhece

Um agente sem memória de longo prazo é o atendente de call center que pede todos os seus dados do zero a cada ligação — exaustivo. Um agente com boa memória é o gerente da sua agência que lembra seu nome, seu histórico, suas preferências e o que ficou pendente da última vez. A diferença na experiência (e na utilidade) é abissal.

📌 Mini-caso real · O assistente que melhora com o uso

Agentes com memória de longo prazo bem implementada ficam mais úteis ao longo do tempo: aprendem suas preferências, lembram contexto de projetos, evitam repetir perguntas já respondidas. Um assistente de suporte que lembra o histórico do cliente resolve mais rápido; um copiloto de trabalho que conhece seu estilo entrega melhor. A memória é o que transforma uma ferramenta em um parceiro que evolui com você.

✏️ Exercício prático · Dê memória a um agente
  1. Implemente uma memória persistente simples: salve fatos sobre o "usuário" (ex.: preferências) num armazenamento entre execuções.
  2. Classifique 3 informações nos tipos: episódica, semântica ou procedimental.
  3. Faça o agente recuperar e usar um fato salvo numa "nova sessão", demonstrando que lembrou.
Checklist da aula0/3
Entendo por que agentes precisam de memória de longo prazo
Conheço os 3 tipos: episódica, semântica e procedimental
Sei implementar com Redis + embeddings (LangMem)
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual tipo de memória guarda FATOS sobre o usuário (ex.: "prefere e-mail, trabalha na Acme")?
A
Episódica
B
Semântica
C
Procedimental
D
Buffer
Selecione uma opção
3.45 · M3.9⏱ 15 min

Ferramentas essenciais

Web search (Tavily/Serper), code sandbox (E2B) e file I/O.

Um agente é tão capaz quanto suas ferramentas (M3.6). Três categorias são quase universais: busca na web (para informação atual, além do conhecimento do modelo), execução de código (para cálculos, análises e tarefas que exigem rodar algo) e manipulação de arquivos (ler, escrever, listar). Dominar essas três já habilita uma enorme variedade de agentes úteis.

LLMs têm conhecimento congelado no treino; para fatos atuais, o agente precisa buscar na web. Ferramentas como o Tavily (feito para agentes, retorna resultados já sintetizados e com contexto) e o Serper (acesso à busca do Google) dão essa capacidade. O Tavily se destaca por entregar resultados pré-processados para consumo de LLM, em vez de uma lista crua de links — economizando passos e tokens.

Deixar um agente executar código é poderoso e perigoso — código arbitrário pode danificar seu sistema. O E2B resolve isso com um sandbox seguro: um ambiente isolado e descartável onde o agente roda Python sem risco para o seu sistema. É o que permite agentes que analisam dados, geram gráficos e executam lógica complexa com segurança — a versão "faça você mesmo" do Code Interpreter (M3.7).

from langchain_community.tools.tavily_search import TavilySearchResults

busca = TavilySearchResults(max_results=3)
# o agente chama esta tool quando precisa de informação atual
resultados = busca.invoke("preço médio do dólar hoje")
for r in resultados:
    print(r["content"][:120])

Ferramentas de arquivo (read, write, append, list) e de shell dão ao agente acesso ao sistema de arquivos — útil para gerar relatórios, processar documentos, organizar saídas. Mas exigem guardrails: limitar a quais pastas o agente pode acessar, validar caminhos, evitar comandos destrutivos. Dar a um agente acesso irrestrito ao shell é receita para acidentes; o acesso deve ser deliberadamente limitado ao necessário.

⚠️ Execução de código e shell exigem isolamento

Nunca deixe um agente executar código ou comandos de shell diretamente no seu sistema sem isolamento. Use sandboxes (como o E2B) e guardrails que limitam o escopo. Código gerado por LLM pode ter erros ou comportamentos inesperados — o isolamento garante que um erro não vire um desastre no seu ambiente real.

📌 Mini-caso real · O agente pesquisador que se mantém atual

Um agente equipado com Tavily deixa de dar respostas defasadas: perguntado sobre algo recente, ele busca na web, lê os resultados e responde com informação atual e fontes. Some-se o E2B para ele calcular ou analisar dados quando preciso, e você tem um pesquisador que combina raciocínio do LLM com fatos frescos e capacidade de processar — a base do agente pesquisador do Projeto 3 (P.03).

✏️ Exercício prático · Equipe um agente com ferramentas
  1. Conecte uma ferramenta de busca web (ex.: Tavily) a um agente e faça uma pergunta sobre um fato atual.
  2. Adicione uma ferramenta de leitura/escrita de arquivo com escopo limitado a uma pasta específica.
  3. Liste 2 guardrails que você aplicaria antes de dar a um agente acesso a executar código.
Checklist da aula0/3
Conheço as 3 categorias essenciais de ferramentas
Sei usar busca web (Tavily/Serper) em agentes
Entendo a necessidade de sandbox (E2B) e guardrails
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que usar um sandbox como o E2B para execução de código por agentes?
A
Para deixar o código mais rápido
B
Para isolar a execução num ambiente seguro, evitando que código arbitrário danifique seu sistema
C
Porque é gratuito
D
Para treinar o modelo
Selecione uma opção
3.46 · M3.9⏱ 18 min

MCP — Model Context Protocol

O padrão de integração que está dominando o mercado.

O MCP (Model Context Protocol), lançado pela Anthropic em novembro de 2024, é um padrão aberto para conectar modelos de IA a ferramentas e fontes de dados. A ideia: em vez de cada aplicação criar integrações próprias e incompatíveis para cada serviço, todos falam o mesmo protocolo. É frequentemente descrito como "o USB-C da IA" — uma forma padronizada de plugar qualquer ferramenta em qualquer agente.

O MCP resolveu uma dor real e aguda — a fragmentação das integrações — e por isso foi adotado em meses por todo o ecossistema. Antes, conectar um agente ao GitHub, ao Slack e ao seu banco de dados exigia três integrações sob medida. Com o MCP, cada serviço expõe um servidor MCP padronizado, e qualquer agente compatível se conecta a todos da mesma forma. Padronização reduz trabalho repetido e cria um efeito de rede poderoso.

Já existe um ecossistema crescente de servidores MCP prontos: GitHub (código e issues), Slack (mensagens), Notion (documentos), Google Drive (arquivos), Postgres (bancos de dados) e muitos outros. Conectar seu agente a qualquer um deles passa a ser questão de "plugar", não de programar uma integração do zero. É o que torna agentes capazes de atuar sobre o stack real de uma empresa com pouco esforço.

O grande poder: você pode criar seu próprio servidor MCP em Python para expor as ferramentas e dados internos da sua empresa de forma padronizada. Assim, qualquer agente compatível (hoje e no futuro) acessa seus sistemas sem integração customizada. É um investimento que se paga: você expõe uma vez, e todos os agentes se beneficiam — em vez de reescrever integrações a cada novo projeto ou framework.

💡 Analogia · O USB-C da IA

Antes do USB-C, cada aparelho tinha seu carregador, e você vivia procurando o cabo certo. O USB-C padronizou: um cabo, todos os aparelhos. O MCP é o USB-C da IA: antes, cada agente precisava de um "cabo" próprio para cada ferramenta; agora, todos usam o mesmo padrão. Pluga e funciona — e isso muda radicalmente a velocidade de integrar agentes ao mundo real.

📌 Mini-caso real · A adoção relâmpago

O MCP é um caso notável de padrão que pegou em tempo recorde: lançado pela Anthropic no fim de 2024, em poucos meses ganhou servidores para dezenas de serviços e suporte de múltiplas plataformas. A velocidade da adoção mostra o tamanho da dor que ele resolvia — e por que dominar o MCP hoje é apostar numa habilidade que está se tornando central na construção de agentes.

✏️ Exercício prático · Explore e crie com MCP
  1. Pesquise a lista de MCP servers disponíveis e identifique 2 que seriam úteis para um caso seu (ex.: GitHub, Notion).
  2. Conecte um agente a um servidor MCP existente e teste uma ação real.
  3. Esboce qual ferramenta/dado da "sua empresa" você exporia num servidor MCP próprio — e por quê.
Checklist da aula0/3
Sei o que é o MCP e quando surgiu
Entendo por que virou padrão tão rápido
Conheço servidores prontos e a ideia de criar o seu
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que é o MCP (Model Context Protocol)?
A
Um novo modelo de linguagem
B
Um padrão aberto (Anthropic, 2024) para conectar IA a ferramentas e dados — o "USB-C da IA"
C
Um banco vetorial
D
Uma linguagem de programação
Selecione uma opção
3.47 · M3.9⏱ 21 min

Integrações reais

CRM, WhatsApp, Slack, Gmail e Notion via API e webhooks.

O valor de um agente em negócios vem de ele atuar sobre os sistemas reais da empresa. Isso significa integrá-lo, via API e tools (M3.6) ou MCP (M3.9), aos serviços do dia a dia: CRM (clientes e vendas), WhatsApp (atendimento), Slack (comunicação interna), Gmail (e-mail) e Notion (documentos). É a ponte entre o raciocínio do agente e a operação concreta.

Duas integrações de altíssimo valor comercial. O HubSpot CRM (via API) permite ao agente consultar e atualizar leads, registrar interações e mover negócios no funil. A Evolution API conecta agentes ao WhatsApp Business — fundamental no Brasil, onde o WhatsApp é o principal canal de atendimento e vendas. Juntas, elas viabilizam o agente de vendas do Projeto 2 (P.02): qualificar leads no CRM e conversar pelo WhatsApp.

Completando o stack: o Slack (via Bolt SDK) permite ao agente enviar alertas e interagir em canais — ótimo para notificações e human-in-the-loop. O Gmail (via API com OAuth) dá acesso a ler e enviar e-mails. O Notion (via API) conecta a base de documentos e wikis. Cada integração transforma o agente de um "cérebro isolado" num colaborador que participa das ferramentas que a equipe já usa.

Duas peças técnicas atravessam todas as integrações. Os webhooks permitem que eventos externos disparem o agente (ex.: um novo lead no formulário aciona o fluxo automaticamente) — o oposto de o agente ter que ficar perguntando "tem algo novo?". E a autenticação segura (OAuth, API keys no .env de M3.1) é inegociável: o agente acessa sistemas sensíveis, e credenciais mal protegidas são uma porta para desastre. Integração real exige segurança real.

💡 Analogia · Dar crachá e acessos ao novo funcionário

Integrar um agente ao stack é como dar a um novo funcionário os acessos para trabalhar: login no CRM, acesso ao WhatsApp da empresa, conta no Slack, e-mail corporativo. Com os acessos certos (e seguros), ele participa da operação de verdade. Os webhooks são os "gatilhos" que o avisam quando há trabalho a fazer, sem precisar ficar checando.

📌 Mini-caso real · O agente que vive no WhatsApp

No Brasil, integrar agentes ao WhatsApp via Evolution API é especialmente valioso, porque é onde os clientes estão. Um agente que recebe a mensagem do cliente no WhatsApp, consulta o CRM, responde com contexto e escala para um humano quando preciso, atende 24h no canal preferido do brasileiro. É a aplicação que conecta tudo desta etapa num produto de impacto comercial direto — exatamente o Projeto 2.

✏️ Exercício prático · Planeje uma integração real
  1. Escolha um serviço (CRM, WhatsApp, Slack, Gmail ou Notion) e estude o básico da sua API.
  2. Implemente uma ação simples via API (ex.: enviar uma mensagem no Slack ou ler um e-mail) com credenciais no .env.
  3. Desenhe um fluxo com webhook: que evento externo dispararia seu agente, e o que ele faria em resposta?
Checklist da aula0/3
Sei conectar agentes a CRM, WhatsApp, Slack, Gmail e Notion
Entendo o valor da Evolution API (WhatsApp) no Brasil
Domino webhooks e a importância da autenticação segura
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Para que servem os "webhooks" nas integrações de um agente?
A
Para treinar o modelo
B
Para que eventos externos (ex.: novo lead) disparem o agente automaticamente, em vez de ele ficar checando
C
Para criptografar dados
D
Para gerar embeddings
Selecione uma opção
3.48 · M3.1⏱ 12 min

n8n

Automação visual com nodes de IA, webhooks, schedules e integrações.

O n8n é uma ferramenta de automação low-code: você constrói fluxos conectando blocos visuais (nodes) numa tela, em vez de escrever todo o código. Pense num "fluxograma que executa de verdade". Para quem domina os conceitos desta etapa mas quer entregar automações rápido — ou para casos onde código completo seria exagero —, o n8n é uma alavanca poderosa. E conecta-se a IA nativamente.

O n8n pode ser self-hosted (você roda no seu servidor — controle total, privacidade, custo só de infraestrutura) ou usado na cloud deles (sem gerenciar nada, pagando assinatura). A escolha ecoa o que vimos em M2.2 (local vs. nuvem): privacidade e controle versus conveniência. Para dados sensíveis ou volume alto, self-hosted compensa; para começar rápido, a cloud é prática.

O coração são os nodes: cada um faz uma coisa (ler um e-mail, chamar uma API, formatar dados). O HTTP Request node é o coringa — com ele, você chama qualquer API do mundo, mesmo sem um node dedicado. E há nodes nativos de OpenAI e Anthropic, que plugam LLMs direto no fluxo: classificar, resumir, gerar texto, sem escrever código de integração. É IA arrastando e soltando.

Todo fluxo começa com um trigger (gatilho). Os principais: webhook (um evento externo dispara — ex.: novo formulário preenchido), schedule (roda em horários definidos — ex.: relatório diário às 8h), form, e-mail recebido, ou novo item no CRM. Os triggers são o que torna a automação autônoma — ela acontece sozinha quando a condição ocorre, sem ninguém apertar um botão.

💡 Analogia · Montar com peças de LEGO

Programar do zero é esculpir cada peça. O n8n é montar com LEGO: peças prontas (nodes) que se encaixam visualmente para construir o que você quer, rápido. Você não tem controle de cada átomo como no código, mas constrói em minutos o que levaria horas — e para muitíssimas automações de negócio, o LEGO é exatamente o suficiente.

📌 Mini-caso real · A automação que substituiu um trabalho manual

Equipes usam o n8n para eliminar tarefas manuais repetitivas: quando chega um e-mail de um tipo, o fluxo extrai os dados, classifica com um LLM, registra no CRM e avisa no Slack — tudo automático, sem ninguém tocar. O que era 30 minutos de trabalho manual por ocorrência vira zero. Para o profissional de IA, o n8n é uma forma rápida de entregar valor automatizando processos, sem um projeto de código completo.

✏️ Exercício prático · Crie seu primeiro fluxo no n8n
  1. Instale o n8n (cloud ou self-hosted) e crie um fluxo com um trigger de webhook ou schedule.
  2. Adicione um HTTP Request node ou um node de IA (OpenAI/Anthropic) que processa algo.
  3. Teste o fluxo de ponta a ponta e observe os dados passando de um node para o outro.
Checklist da aula0/3
Entendo o que é o n8n e o low-code
Sei a diferença self-hosted vs. cloud
Conheço nodes, HTTP Request, nodes de IA e triggers
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que é um "trigger" no n8n?
A
Um erro no fluxo
B
O gatilho que inicia o fluxo (webhook, schedule, e-mail, etc.), tornando a automação autônoma
C
Um tipo de banco de dados
D
O modelo de IA
Selecione uma opção
3.49 · M3.1⏱ 15 min

Projetos com n8n + IA

SDR pipeline, monitor de concorrentes e relatório automático.

O n8n brilha quando você combina suas integrações nativas com nodes de IA para automatizar processos de negócio ponta a ponta. Vamos ver três fluxos concretos e de alto valor — cada um conectando gatilhos, APIs e LLMs num pipeline que roda sozinho. São padrões diretamente aplicáveis (e o Projeto 4, P.04, aprofunda o primeiro deles).

O fluxo de SDR automatizado: um formulário captura o lead (trigger) → o n8n enriquece os dados (ex.: via Clay API, buscando informações sobre a empresa) → um node de IA dá um score ao lead usando o framework BANT (M2.4) → se qualificado, o fluxo registra no HubSpot e envia um alerta no Slack para o vendedor agir. Todo o trabalho de triagem que um SDR faria manualmente, automatizado.

Um fluxo de inteligência competitiva: um trigger de schedule (ex.: diário) lê os feeds RSS ou páginas dos concorrentes → um LLM resume as novidades relevantes → o resumo vira uma newsletter enviada por e-mail à equipe. Em vez de alguém checar manualmente o que os concorrentes lançaram, o agente vigia e reporta sozinho, todo dia, no horário certo.

Um fluxo de relatório: pega dados de uma fonte (planilha, banco, API) → um LLM analisa e interpreta os números, destacando tendências e pontos de atenção → formata um e-mail bem estruturado e o envia aos interessados. Transforma dados brutos em insight comunicado, automaticamente e na frequência que você definir — eliminando horas de montagem manual de relatórios.

💡 Analogia · A linha de produção automatizada

Esses fluxos do n8n são linhas de produção: a matéria-prima entra por um gatilho (lead, dado, novidade do concorrente), passa por estações que a transformam (enriquecer, pontuar, resumir, analisar com IA) e sai como produto acabado (lead no CRM, newsletter, relatório no e-mail) — tudo sem operário em cada etapa. Você projeta a linha uma vez; ela produz sozinha.

📌 Mini-caso real · Horas recuperadas toda semana

O padrão comum desses fluxos é recuperar tempo humano de tarefas repetitivas: o SDR não tria leads manualmente, o analista não compila relatórios à mão, ninguém vigia concorrentes diariamente. Cada fluxo desses costuma economizar várias horas por semana — e, multiplicado por uma equipe, vira um ROI claríssimo (M2.4), entregue com low-code em vez de um projeto de software completo.

✏️ Exercício prático · Construa um fluxo SDR simplificado
  1. No n8n, crie um fluxo iniciado por um formulário (ou webhook) que recebe dados de um lead.
  2. Adicione um node de IA que dá um score ao lead (qualificado/não) com base nas informações.
  3. Conecte uma ação final: se qualificado, envie um alerta (Slack ou e-mail). Teste de ponta a ponta.
Checklist da aula0/3
Sei combinar n8n com nodes de IA
Conheço os fluxos SDR, monitor e relatório
Sei conectar gatilho → enriquecimento → IA → ação
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
No pipeline SDR com n8n, qual o papel do node de IA?
A
Hospedar o site
B
Dar um score ao lead (ex.: via BANT) para decidir se ele é qualificado
C
Enviar o formulário
D
Criar o banco de dados
Selecione uma opção
3.50 · M3.1⏱ 18 min

FastAPI

Endpoints, Pydantic, auth e WebSockets para streaming.

Para o seu modelo ou agente ser usado por outros sistemas e interfaces, ele precisa virar uma API. O FastAPI é o framework Python padrão para isso em IA: rápido, moderno, com suporte nativo a async (M3.1, essencial para chamadas de LLM) e a Pydantic (M3.6, para validação). Ele transforma seu código de IA num serviço web que qualquer aplicação pode consumir.

No FastAPI, você define endpoints (rotas como /perguntar) com path params, query params e request body. O Pydantic valida automaticamente os dados de entrada — se alguém enviar um formato errado, o FastAPI rejeita com uma mensagem clara, sem o seu código precisar checar. E gera documentação OpenAPI automática (uma página interativa para testar a API), de graça. Menos código, mais robustez.

from fastapi import FastAPI, Header, HTTPException
from pydantic import BaseModel

app = FastAPI()

class Pergunta(BaseModel):
    texto: str

@app.post("/perguntar")
async def perguntar(p: Pergunta, x_api_key: str = Header(...)):
    if x_api_key != "minha-chave-secreta":
        raise HTTPException(401, "Não autorizado")
    resposta = await chamar_llm(p.texto)   # async!
    return {"resposta": resposta}

Três recursos importantes. A autenticação por API key (validando um header) protege seu endpoint de uso não autorizado — crucial, já que cada chamada custa tokens. As background tasks rodam trabalhos demorados sem travar a resposta. E os WebSockets permitem o streaming de LLM (M3.4) — manter uma conexão aberta para enviar a resposta token a token ao cliente, criando aquela experiência de "digitando" em tempo real.

Código que vai a produção precisa de testes. O pytest permite escrever testes automatizados que verificam se seus endpoints funcionam como esperado — e rodá-los a cada mudança (conectando com os testes de regressão de M3.4 e o GitHub Actions de M3.1). Uma API de IA testada é uma API em que você confia para evoluir sem quebrar o que já funcionava.

💡 Analogia · A recepção do prédio

O FastAPI é a recepção profissional do seu sistema de IA: recebe os visitantes (requisições) numa porta organizada (endpoint), confere a identidade (auth por API key), valida se trouxeram os documentos certos (Pydantic), e encaminha ao serviço. Sem a recepção, ninguém de fora consegue usar seu sistema de forma organizada e segura.

📌 Mini-caso real · Do notebook ao produto

Um modelo ou agente que só roda no seu notebook não é um produto — ninguém mais o usa. Envelopá-lo numa API FastAPI (com auth e validação) é o passo que o transforma em algo que um app, um site ou outro sistema pode consumir. É exatamente o que faz o Projeto 1 (P.01) ao expor o RAG como API. A FastAPI é a ponte entre "funciona pra mim" e "é um serviço utilizável".

✏️ Exercício prático · Exponha um modelo como API
  1. Crie uma API FastAPI com um endpoint POST que recebe um texto (validado por Pydantic) e retorna uma resposta de IA.
  2. Adicione autenticação por API key via header.
  3. Rode localmente, abra a documentação automática (/docs) e teste o endpoint por lá.
Checklist da aula0/3
Sei criar endpoints com FastAPI e validação Pydantic
Sei adicionar auth por API key
Conheço WebSockets para streaming e testes com pytest
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que o FastAPI é especialmente adequado para servir aplicações de IA?
A
Porque é lento e simples
B
Por ter suporte nativo a async (chamadas de LLM), validação com Pydantic e docs automáticas
C
Porque treina modelos
D
Porque não precisa de código
Selecione uma opção
3.51 · M3.1⏱ 21 min

Docker

Dockerfile, docker-compose e boas práticas para IA.

O clássico "na minha máquina funciona" é a praga do deploy: o código roda no seu computador mas quebra no servidor, por diferenças de versão de Python, bibliotecas ou sistema. O Docker resolve isso empacotando sua aplicação com todo o seu ambiente (Python, bibliotecas, configurações) num container isolado que roda igual em qualquer lugar. "Funciona na minha máquina" vira "funciona em qualquer máquina".

O Dockerfile é a receita que define seu container: a partir de qual imagem base (ex.: Python 3.11), quais arquivos copiar, quais dependências instalar (do requirements.txt), e qual comando rodar. Os multi-stage builds são uma boa prática que mantém a imagem final pequena (separando o que é só para construir do que precisa rodar) — importante em IA, onde dependências são pesadas.

FROM python:3.11-slim

WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .
# variáveis sensíveis vêm do ambiente, NÃO da imagem
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Aplicações de IA raramente são um serviço só: você tem a API, mais um banco vetorial (Chroma), mais um Redis (memória/cache), mais talvez um Postgres. O docker-compose orquestra todos esses serviços juntos, definidos num único arquivo, subindo a stack inteira com um comando. É o que torna gerenciável rodar e conectar vários componentes — localmente e em produção.

Duas regras de ouro para IA. Primeiro, nunca coloque segredos (chaves de API) dentro da imagem — eles entram por variáveis de ambiente em tempo de execução (a mesma lógica do .env de M3.1). Segundo, mantenha as imagens enxutas (slim, multi-stage) para deploys rápidos e baratos. Por fim, você publica a imagem num registro (Docker Hub ou GitHub Container Registry) de onde o servidor de produção a baixa.

💡 Analogia · O contêiner de navio

O Docker é literalmente inspirado nos contêineres de navio: antes deles, cada carga era embarcada de um jeito e dava confusão; o contêiner padronizou tudo — qualquer carga, em qualquer navio, qualquer porto. O container Docker faz isso com software: empacota sua aplicação de um jeito padrão que roda em qualquer "porto" (servidor), sem surpresas.

📌 Mini-caso real · O deploy que parou de dar surpresa

Equipes que adotam Docker eliminam a categoria inteira de bugs do tipo "funcionava no dev e quebrou em produção", porque o ambiente vai junto com o código. Some o docker-compose para subir API + Chroma + Redis com um comando, e o que era um deploy frágil e manual vira algo reproduzível e confiável. Para IA, com suas dependências pesadas e múltiplos serviços, isso é especialmente valioso.

✏️ Exercício prático · Containerize sua API
  1. Escreva um Dockerfile para a API FastAPI da aula anterior.
  2. Construa a imagem e rode o container localmente, confirmando que a API responde.
  3. Crie um docker-compose que sobe sua API junto com um Chroma — e suba os dois com um comando.
Checklist da aula0/3
Entendo o problema que o Docker resolve
Sei escrever um Dockerfile para uma app Python
Sei orquestrar a stack com docker-compose e proteger segredos
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual problema o Docker resolve em deploy de IA?
A
Deixa o modelo mais inteligente
B
O "na minha máquina funciona": empacota a app com seu ambiente, rodando igual em qualquer lugar
C
Elimina a necessidade de código
D
Treina o modelo
Selecione uma opção
3.52 · M3.1⏱ 12 min

Deploy em produção

Railway, Render, Modal (GPU serverless) e monitoramento.

Com a app containerizada (M3.11), falta colocá-la online. Para aplicações full-stack simples, Railway e Render são plataformas que facilitam muito: você conecta seu repositório do GitHub e elas fazem o deploy automaticamente a cada push, gerenciando a infraestrutura para você. É o caminho mais rápido para tirar uma API de IA do seu computador e deixá-la acessível na internet, sem virar especialista em infraestrutura.

Algumas tarefas de IA precisam de GPU (fine-tuning de M3.4, inferência de modelos pesados de M3.3) — e manter uma GPU ligada o tempo todo é caríssimo. O Modal oferece GPU serverless: você roda a tarefa pesada, paga só pelos segundos de GPU usados, e ela "desliga" sozinha quando termina. É o que torna economicamente viável tarefas de GPU esporádicas, sem manter hardware ocioso queimando dinheiro.

Pôr em produção sem observabilidade é voar cego. Ferramentas como o Langfuse registram cada chamada de LLM da sua aplicação: o que foi perguntado, o que o modelo respondeu, quantos tokens, quanto custou, quanto tempo levou. Isso permite entender o comportamento real do sistema, depurar problemas e otimizar — a versão de produção do que vimos com LangSmith (M3.7) e da avaliação contínua (M3.4).

Dois números precisam de vigilância ativa em produção: o custo (lembre que cada chamada gasta tokens, M2.5 — um bug ou um pico de uso pode fazer a conta explodir) e a latência (respostas lentas afastam usuários). Configurar alertas que avisam quando o custo ou a latência ultrapassam um limite é o que evita surpresas desagradáveis — como descobrir uma fatura gigante só no fim do mês. Monitorar é proteger o produto e o bolso.

💡 Analogia · Inaugurar a loja e acompanhar o movimento

Fazer deploy é inaugurar a loja; observabilidade é instalar as câmeras e o caixa que mostram o movimento. Railway/Render abrem a loja para o público, o Modal traz o "equipamento pesado sob demanda" quando precisa, e o Langfuse + alertas são as câmeras que mostram quem entrou, o que comprou, quanto custou e se há algo errado. Nenhuma loja séria opera sem acompanhar o movimento.

📌 Mini-caso real · Da demo ao produto monitorado

O caminho completo de um projeto de IA: você constrói (M3.1-M3.10), containeriza com Docker (M3.11), faz deploy no Railway via GitHub, e liga o Langfuse para monitorar custo, latência e qualidade — com alertas configurados. Agora não é mais uma demo no seu notebook: é um produto online, acessível, observável e sob controle. É exatamente esse arco que os projetos finais (M3.12) consolidam, transformando você em um especialista comprovado.

✏️ Exercício prático · Faça seu primeiro deploy
  1. Conecte o repositório da sua API ao Railway (ou Render) e faça o deploy via GitHub.
  2. Confirme que a API está acessível online e responde a uma requisição real.
  3. Integre uma ferramenta de observabilidade (ex.: Langfuse) e configure um alerta de custo ou latência.
Checklist da aula0/3
Sei fazer deploy no Railway/Render via GitHub
Entendo o Modal (GPU serverless) e quando usá-lo
Sei monitorar custo/latência com observabilidade e alertas
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que o "GPU serverless" (ex.: Modal) é útil para tarefas de IA?
A
Porque elimina a necessidade de código
B
Você roda tarefas pesadas de GPU pagando só pelo tempo usado, sem manter uma GPU cara ligada ociosa
C
Porque deixa o modelo mais preciso
D
Porque não usa GPU
Selecione uma opção
P.01 · Projeto⏱ 15 min

Projeto 1 — RAG Empresarial

Chat com a base de conhecimento interna, do zero ao deploy.

Um assistente que conversa com a base de conhecimento de uma empresa: o usuário pergunta em linguagem natural e recebe respostas precisas, ancoradas nos documentos internos (manuais, políticas, FAQs) e com citação de fontes. É a materialização de tudo o que você aprendeu em M3.5, agora num produto completo, avaliado e no ar — e um dos casos de IA com ROI mais claro (M2.4).

O RAG empresarial é, provavelmente, o caso de uso de IA mais demandado por empresas hoje — toda organização tem documentos demais e tempo de menos. Ter um RAG completo, avaliado e deployado no seu portfólio comunica que você sabe resolver um problema real e valioso, de ponta a ponta. Não é um tutorial copiado: é prova de capacidade.

🚀 RAG Empresarial — stack, passos e extensões

Stack: Python · ingestão de PDF/Word (PyMuPDF, python-docx) · chunking semântico · Chroma (vetorial) · embeddings (OpenAI/Cohere) · hybrid retrieval (BM25 + vetorial) + reranking (Cohere) · LangGraph (orquestração) · FastAPI (API) · Streamlit (interface) · RAGAS (avaliação) · deploy no Railway.

Passos: (1) reúna 15-30 documentos reais de um domínio; (2) pipeline de ingestão com extração cuidadosa e tratamento de tabelas (M3.5); (3) chunking + embeddings + indexação no Chroma; (4) hybrid retrieval com reranking; (5) geração com citação obrigatória de fontes; (6) orquestre o fluxo no LangGraph; (7) monte conjunto de avaliação e rode RAGAS (faithfulness, relevancy, context recall); (8) exponha via FastAPI com API key; (9) interface em Streamlit; (10) deploy no Railway via GitHub; (11) README técnico completo.

Ideias de extensão: filtros de metadados por departamento/permissão (cada usuário vê só o que pode); memória de conversa para perguntas de acompanhamento; suporte a multimodal RAG (diagramas e imagens dos manuais); dashboard das perguntas mais frequentes (revela lacunas na documentação); modo "não sei" honesto quando não há fonte; conector MCP (M3.9) para a base viver dentro de outras ferramentas; observabilidade com Langfuse e alerta de custo.

💡 Analogia · O funcionário que leu tudo

Este RAG é como contratar um funcionário que leu — e lembra — cada documento da empresa, está disponível 24h e sempre cita de onde tirou a resposta. Os colegas param de procurar em dezenas de PDFs ou de interromper uns aos outros: perguntam a ele e recebem a resposta com a fonte em segundos.

📌 Mini-caso real · O argumento de ROI que vende o projeto

Ao apresentar este projeto (a um chefe ou cliente), use o que aprendeu em M2.4: estime as horas que a equipe gasta procurando informação, multiplique pelo custo/hora, e compare com o custo de tokens + manutenção. O número quase sempre fecha a favor — e um RAG que você pode demonstrar funcionando e avaliado com RAGAS transforma esse argumento de promessa em prova.

✏️ Exercício prático · Entregue o RAG empresarial
  1. Construa o pipeline completo seguindo os 11 passos, do conjunto de documentos ao deploy.
  2. Rode o RAGAS e registre as métricas no README — números, não achismo.
  3. Escolha e implemente ao menos UMA ideia de extensão para diferenciar seu projeto.
Checklist da aula0/3
Construí o RAG completo, da ingestão ao deploy
Avaliei com RAGAS e documentei as métricas
Implementei ao menos uma extensão e o README técnico
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
O que torna o RAG empresarial um projeto de portfólio especialmente valioso?
A
É o mais fácil de fazer
B
Resolve o caso de uso de IA mais demandado por empresas (conhecimento interno), de ponta a ponta e com avaliação
C
Não precisa de avaliação
D
Dispensa deploy
Selecione uma opção
P.02 · Projeto⏱ 18 min

Projeto 2 — Agente de Vendas

Memória, CRM e WhatsApp, com qualificação BANT e human-in-the-loop.

Um agente de vendas que conversa com leads pelo WhatsApp, qualifica-os automaticamente usando o framework BANT (M2.4), registra tudo no CRM, lembra do histórico de cada lead (memória), e — no momento do fechamento — aciona um humano para aprovar antes de avançar. É a integração de agentes (M3.7), memória (M3.8), tools/integrações (M3.9) e human-in-the-loop num produto de impacto comercial direto.

Vendas é onde a IA gera receita visível, e o WhatsApp é o canal número um no Brasil. Um agente que realmente conversa, qualifica e atualiza o CRM sozinho, com aprovação humana no ponto crítico, demonstra domínio de agentes em produção — não um chatbot de demonstração, mas um colaborador comercial. É o tipo de projeto que abre portas em qualquer empresa que venda algo.

🚀 Agente de Vendas — stack, passos e extensões

Stack: Python · LangGraph (orquestração do agente) · memória persistente com Redis (M3.8) · HubSpot CRM API · ferramenta de busca de leads · Evolution API (WhatsApp Business) · qualificação BANT via LLM · human-in-the-loop com interrupt() para o fechamento · FastAPI + webhook.

Passos: (1) modele o fluxo do agente no LangGraph (receber mensagem → recuperar histórico → responder/qualificar → atualizar CRM); (2) integre a Evolution API para receber e enviar mensagens no WhatsApp; (3) implemente memória Redis para lembrar cada lead entre conversas; (4) crie a ferramenta de qualificação BANT (orçamento, autoridade, necessidade, prazo); (5) conecte o HubSpot para registrar e mover leads no funil; (6) adicione interrupt() antes do fechamento, pedindo aprovação humana; (7) exponha via FastAPI com webhook para o WhatsApp disparar o agente.

Ideias de extensão: agendamento automático de reuniões no Google Calendar para leads quentes; análise de sentimento da conversa para priorizar; resumo automático de cada lead para o vendedor; alertas no Slack quando um lead atinge alto score; suporte a múltiplos idiomas; relatório semanal de leads qualificados; guardrails que impedem o agente de prometer descontos não autorizados.

⚠️ Human-in-the-loop não é opcional aqui

Num agente que fala com clientes reais e mexe no funil de vendas, deixar a IA fechar negócios ou enviar mensagens sensíveis sozinha é arriscado. O interrupt() antes do fechamento (M3.8) protege contra erros caros — um valor errado, uma promessa indevida. Automatize a qualificação e o atendimento; mantenha o humano no aval das ações críticas.

💡 Analogia · O SDR incansável com um gerente atento

Este agente é como um SDR que trabalha 24h sem cansar: conversa com cada lead no WhatsApp, faz as perguntas de qualificação, anota tudo no CRM e lembra de cada um. Mas, na hora de fechar, ele chama o gerente (você) para aprovar — autonomia no volume, supervisão no que decide o negócio.

📌 Mini-caso real · Por que o WhatsApp muda o jogo no Brasil

Lembre de M3.9: no Brasil, o WhatsApp é onde os clientes estão. Um agente de vendas que vive no WhatsApp, qualifica leads e mantém o CRM atualizado ataca exatamente o gargalo de muitas empresas — leads que chegam e esfriam por falta de resposta rápida. Demonstrar isso funcionando é mostrar valor comercial que qualquer gestor entende na hora.

✏️ Exercício prático · Entregue o agente de vendas
  1. Construa o agente no LangGraph com memória Redis e integração ao WhatsApp (Evolution API).
  2. Implemente a qualificação BANT e a atualização do HubSpot, com human-in-the-loop no fechamento.
  3. Adicione ao menos uma extensão (ex.: agendamento no Calendar) e documente o fluxo no GitHub.
Checklist da aula0/3
Construí o agente com memória, CRM e WhatsApp
Implementei qualificação BANT e human-in-the-loop
Adicionei uma extensão e documentei o projeto
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que o human-in-the-loop é essencial no agente de vendas, especialmente no fechamento?
A
Para deixar o agente mais lento
B
Porque ações como fechar negócio ou enviar mensagens sensíveis exigem aprovação humana para evitar erros caros
C
Porque a IA não sabe vender
D
Porque o WhatsApp exige
Selecione uma opção
P.03 · Projeto⏱ 21 min

Projeto 3 — Pipeline Multi-Agente

Pesquisa, análise e relatório automático, entregue por e-mail.

Um pipeline multi-agente que produz relatórios automaticamente: uma equipe de agentes — pesquisador, analista, escritor e revisor — colabora para investigar um tema, analisar os achados, escrever o relatório e revisá-lo, entregando um PDF por e-mail. É a aplicação direta de multi-agentes (M3.8) com CrewAI, ferramentas de agentes (M3.9) e automação (M3.10) trabalhando juntas.

Este projeto demonstra por que múltiplos agentes especializados superam um agente único (M3.8): cada um foca no que faz melhor — o pesquisador busca, o analista interpreta, o escritor comunica, o revisor garante qualidade. O resultado é mais rico e confiável do que um único LLM tentando fazer tudo de uma vez. É a prova de que você sabe orquestrar uma "equipe de IA".

🚀 Pipeline Multi-Agente — stack, passos e extensões

Stack: Python · CrewAI (orquestração da equipe) · agente pesquisador com busca web (Tavily, M3.9) · agente analista com execução de código (E2B/Code Interpreter para processar dados) · agente escritor (gera o relatório) · agente revisor (controle de qualidade) · geração de PDF · entrega por e-mail automatizada via n8n (M3.10).

Passos: (1) defina os 4 agentes no CrewAI com roles, goals e backstories distintos; (2) dê ao pesquisador a ferramenta de busca web (Tavily); (3) dê ao analista capacidade de processar dados/código; (4) configure as tasks encadeadas (pesquisa → análise → redação → revisão) em processo sequencial; (5) gere o relatório final em PDF; (6) crie um fluxo n8n que recebe o PDF e o envia por e-mail aos destinatários; (7) dispare o pipeline por um tema de entrada.

Ideias de extensão: processo hierárquico com um agente supervisor coordenando (M3.7); agente verificador de fatos que checa as fontes citadas; entrega em múltiplos formatos (PDF, slides, post de LinkedIn); agendamento recorrente (relatório semanal automático via schedule do n8n); painel para acompanhar relatórios gerados; map-reduce (M3.7) para o pesquisador cobrir muitas fontes em paralelo.

💡 Analogia · A redação de uma revista

Este pipeline é como a redação de uma revista produzindo uma matéria: o repórter apura os fatos (pesquisador), o analista de dados interpreta os números, o redator escreve a matéria, e o editor revisa antes de publicar. Cada um é especialista no seu papel, e a colaboração entrega algo melhor do que qualquer um sozinho — e tudo isso automatizado.

📌 Mini-caso real · De horas de trabalho a um clique

Produzir um relatório de pesquisa — buscar fontes, analisar, escrever, revisar, formatar e enviar — toma horas de trabalho humano qualificado. Este pipeline reduz isso a disparar um tema e receber o PDF pronto no e-mail. Para consultorias, áreas de inteligência de mercado ou qualquer função que produz relatórios recorrentes, é um ganho de produtividade que se traduz direto em ROI.

✏️ Exercício prático · Entregue o pipeline multi-agente
  1. Monte a crew de 4 agentes no CrewAI com papéis distintos e tasks encadeadas.
  2. Equipe o pesquisador com busca web e gere um relatório em PDF ao final.
  3. Automatize a entrega por e-mail (n8n) e implemente uma extensão (ex.: agendamento recorrente).
Checklist da aula0/3
Construí a equipe de 4 agentes no CrewAI
Integrei busca web, geração de PDF e entrega por e-mail
Implementei uma extensão e documentei o pipeline
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Por que usar múltiplos agentes especializados neste projeto, em vez de um só?
A
Para gastar mais tokens
B
Porque agentes especializados (pesquisar, analisar, escrever, revisar) colaborando entregam resultado mais rico e confiável que um único
C
Porque é obrigatório
D
Para deixar mais lento
Selecione uma opção
P.04 · Projeto⏱ 12 min

Projeto 4 — Automação SDR no n8n

Do formulário ao CRM com score de IA, 100% sem código Python.

Uma automação completa de SDR construída inteiramente no n8n — sem escrever código Python: um lead preenche um formulário, e o fluxo enriquece os dados, pontua o lead com IA (BANT), e — se qualificado — registra no CRM, alerta o time, envia um e-mail personalizado e agenda uma reunião. É a demonstração de que você sabe entregar valor com low-code (M3.10) quando essa é a ferramenta certa.

Nem todo problema pede um projeto de código completo. Saber quando uma automação no n8n resolve mais rápido e com menos manutenção é maturidade profissional — e amplia muito o seu alcance, permitindo atender clientes e casos que não justificariam desenvolvimento sob medida. Este projeto prova que você transita entre os dois mundos: código quando preciso, low-code quando é mais inteligente.

🚀 Automação SDR no n8n — stack, passos e extensões

Stack (100% n8n, sem Python): n8n · trigger de formulário/webhook · enriquecimento via API (ex.: Clay) · node de IA (OpenAI/Anthropic) para scoring BANT · HubSpot CRM · Slack (alertas) · e-mail · Google Calendar.

Passos: (1) crie o trigger: um formulário (ou webhook) que captura o lead; (2) adicione um node de enriquecimento que busca dados da empresa/contato via API; (3) use um node de IA para dar um score BANT ao lead e classificá-lo; (4) ramifique com lógica condicional: se qualificado, siga; (5) registre o lead no HubSpot; (6) envie um alerta no Slack para o vendedor; (7) dispare um e-mail personalizado ao lead (gerado por IA); (8) agende uma reunião no Google Calendar. Tudo conectando nodes visualmente.

Ideias de extensão: roteamento do lead para o vendedor certo conforme região/segmento; resposta automática no WhatsApp (Evolution API); painel de leads no Notion atualizado em tempo real; A/B de mensagens de e-mail; reengajamento automático de leads frios após X dias; deduplicação de leads já existentes no CRM.

💡 Analogia · A linha de montagem comercial

Esta automação é uma linha de montagem comercial: o lead entra por uma ponta (formulário), passa por estações que o enriquecem, pontuam e classificam, e sai do outro lado já dentro do CRM, com o vendedor avisado, o e-mail enviado e a reunião marcada — sem ninguém tocar manualmente em nenhuma etapa. Você projeta a esteira uma vez; ela trabalha sozinha.

📌 Mini-caso real · O lead que não esfria mais

O problema clássico de vendas: leads chegam, mas demoram a ser atendidos e esfriam. Esta automação responde em segundos — qualifica, registra, avisa e até agenda — no instante em que o lead se cadastra. Para muitas empresas, fechar essa janela de resposta é a diferença entre ganhar ou perder o cliente. E entregar isso sem um projeto de código, só com n8n, mostra eficiência e bom julgamento de ferramenta.

✏️ Exercício prático · Entregue a automação SDR
  1. Construa o fluxo completo no n8n, do formulário ao agendamento, conectando os nodes.
  2. Implemente o scoring BANT com um node de IA e a ramificação condicional para leads qualificados.
  3. Teste de ponta a ponta com um lead fictício e adicione uma extensão (ex.: roteamento por região).
Checklist da aula0/3
Construí a automação SDR inteira no n8n
Implementei scoring BANT e ações condicionais
Testei o fluxo completo e adicionei uma extensão
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Qual a principal competência que este projeto demonstra?
A
Que low-code é sempre melhor que código
B
Saber entregar valor com low-code (n8n) quando essa é a ferramenta mais rápida e adequada, sem código
C
Que n8n substitui Python sempre
D
Que automação não tem valor
Selecione uma opção
P.05 · Projeto⏱ 15 min

Projeto 5 — Portfólio e como vender

GitHub, apresentação executiva e posicionamento — do conhecimento ao reconhecimento.

Você dominou a parte técnica. Mas conhecimento que ninguém vê não gera oportunidades. Este "projeto" final é sobre transformar capacidade em reconhecimento: empacotar seus projetos num portfólio convincente, saber apresentá-los para quem decide, e posicionar-se no mercado. É a ponte entre "eu sei fazer" e "as pessoas certas sabem que eu sei fazer" — e muitas vezes é o que mais falta a quem é tecnicamente bom.

No mercado de IA, seu GitHub é seu currículo (M3.1). Cada projeto precisa de um README que comunique valor em segundos: um título e descrição claros, badges (tecnologias usadas), um diagrama de arquitetura (mostra que você pensa em sistemas), instruções de como rodar, e — idealmente — uma demo (GIF ou link). Um README excelente faz um recrutador ou cliente entender, em 30 segundos, que você sabe o que faz.

Lembre de M2.4: executivos compram resultado, não tecnologia. Ao apresentar um projeto, estruture a narrativa como problema → solução → ROI: qual dor real ele resolve, como sua solução resolve, e qual o retorno (horas economizadas, receita, risco reduzido). Fale a língua do negócio, não a do modelo. Um RAG vira "reduz em 70% o tempo que a equipe gasta procurando informação" — e isso vende.

Uma estratégia meta-poderosa: use a IA que você domina para criar conteúdo sobre IA — posts no LinkedIn explicando seus projetos, threads sobre o que aprendeu, demos do que construiu. Isso constrói posicionamento: você passa a ser visto como alguém que faz, não só fala. Compartilhar seus projetos do GitHub, escrever sobre as decisões técnicas e os resultados, é o que atrai oportunidades — clientes, vagas, parcerias — de forma orgânica e composável ao longo do tempo.

🚀 Portfólio e Posicionamento — o plano de ação

Entregáveis: um GitHub organizado com os 4 projetos anteriores · README técnico excelente em cada um (descrição, badges, arquitetura, como rodar, demo) · uma apresentação executiva (problema → solução → ROI) de pelo menos um projeto · um perfil de LinkedIn posicionado · um plano de conteúdo.

Passos: (1) organize cada projeto no GitHub com README de qualidade e .gitignore correto (M3.1); (2) adicione um diagrama de arquitetura a cada um; (3) grave uma demo curta (GIF/vídeo) do principal; (4) escreva uma apresentação executiva de um projeto no formato problema→solução→ROI; (5) atualize o LinkedIn destacando o que você constrói; (6) publique 1 post sobre um projeto, explicando a decisão técnica e o resultado; (7) defina um ritmo sustentável de conteúdo (M2.3: curar e fazer, sem se afogar).

Ideias de extensão: um site-portfólio simples reunindo os projetos; uma série de posts "como construí X"; contribuir para um projeto open source de IA; escrever um artigo técnico aprofundado; oferecer um dos projetos como serviço/produto a um cliente real; montar um estudo de caso com métricas reais de um projeto em uso.

💡 Analogia · O chef que precisa abrir as portas

Você passou a formação inteira aprendendo a cozinhar pratos excelentes (os projetos técnicos). Mas um chef genial de portas fechadas não tem clientes. Este projeto é abrir o restaurante: a vitrine (GitHub/README), o cardápio que fala a língua do cliente (apresentação executiva com ROI) e o marketing que traz gente (conteúdo no LinkedIn). Talento precisa de vitrine para virar oportunidade.

📌 Mini-caso real · O portfólio que conseguiu a vaga (revisitado)

Lembre do caso de M3.1: no mercado de IA, o GitHub é olhado antes do currículo. Quem termina esta formação com 4 projetos reais, bem documentados e apresentáveis — e que sabe contar a história de cada um em termos de problema e ROI — está numa posição radicalmente diferente de quem só "fez cursos". Você não está pedindo uma chance; está mostrando provas. Essa é a diferença que esta etapa final consolida.

✏️ Exercício prático · Construa seu posicionamento
  1. Organize os 4 projetos no GitHub, cada um com um README técnico excelente (descrição, badges, arquitetura, demo).
  2. Escreva a apresentação executiva de um projeto no formato problema → solução → ROI.
  3. Publique um post no LinkedIn sobre um dos seus projetos e defina um ritmo sustentável de conteúdo.
🎯Consolide o módulo0/3
Tenho um GitHub organizado com READMEs excelentes
Sei apresentar projetos como problema → solução → ROI
Estou posicionado e produzindo conteúdo sobre o que construo
🧠

Teste seu entendimento

1 pergunta · +10 XP

1/1
Ao apresentar um projeto de IA para quem decide, qual a melhor estrutura?
A
Detalhar o modelo e os hiperparâmetros usados
B
Problema → solução → ROI: a dor real, como você resolve e o retorno em termos de negócio
C
Listar todas as bibliotecas
D
Mostrar só o código
Selecione uma opção
🎉
Aula concluída!
Você completou mais uma aula da FIA.
⚡ +10 XP ganhos