Onde vamos chegar
Na aula passada, os agentes da demo (OpenCode, Pi, Hermes, Sprachspiel) eram todos Python por baixo. Para construir um agente, você não precisa de Python inteiro — precisa do mínimo essencial.
Ao final desta aula, você vai saber:
- ✅ Criar variáveis e usar f-strings
- ✅ Trabalhar com listas e dicionários
- ✅ Escrever funções com estado (sem classes!)
- ✅ Manipular strings e texto (essencial para LLMs)
- ✅ Entender JSON — o formato que as APIs de LLM entendem
O notebook do Colab acompanha esta apostila: 📓 abrir o Colab da aula.
Por que Python?
Python é a linguagem mais usada em IA por três motivos:
- Sintaxe simples → parece pseudocódigo
- Bibliotecas → milhões de pacotes prontos
- Comunidade → documentação e tutoriais em todo lugar
Mas mais importante: o ecossistema de IA vive em Python. Ollama, LangChain, HuggingFace, PyTorch, vLLM — todos lançam primeiro em Python, e todos rodam com modelos locais.
Variáveis
Uma variável é uma caixa com etiqueta: você guarda algo nela e usa o nome depois. O Python descobre o tipo sozinho (não precisa declarar).
# Tipos básicos nome = "Maria" # texto (string) idade = 25 # número inteiro (int) altura = 1.70 # número decimal (float) estudante = True # verdadeiro/falso (bool) # F-strings (formatação moderna) mensagem = f"{nome} tem {idade} anos" print(mensagem) # "Maria tem 25 anos"
F-strings aceitam expressões:
print(f"Ano que vem: {idade + 1} anos") print(f"Nome em maiúsculas: {nome.upper()}") print(f"Tamanho do nome: {len(nome)} caracteres")
Listas
Lista é uma fila de coisas em ordem. Cada item tem uma posição (índice), começando do 0.
# Criando listas frutas = ["maçã", "banana", "laranja"] numeros = [10, 20, 30, 40, 50] print(len(frutas)) # 3 (tamanho) print(frutas[0]) # "maçã" (primeiro) print(frutas[-1]) # "laranja" (último — truque!)
Modificando listas
frutas = ["maçã", "banana", "laranja"] frutas.append("uva") # adiciona no final frutas.insert(1, "morango") # insere na posição 1 frutas.remove("banana") # remove por valor removido = frutas.pop(0) # remove e retorna o da posição 0 print(frutas)
Fatiando listas (slicing)
numeros = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(numeros[2:5]) # [2, 3, 4] — do índice 2 ao 4 print(numeros[:4]) # [0, 1, 2, 3] — do início ao 3 print(numeros[6:]) # [6, 7, 8, 9] — do 6 ao final print(numeros[::2]) # [0, 2, 4, 6, 8] — de 2 em 2 # Ordenar print(sorted(["z", "a", "m", "b"])) # ['a', 'b', 'm', 'z']
Dicionários
Dicionário é uma ficha com campos preenchidos. Você acessa pelo nome do campo (chave), não pela posição.
pessoa = { "nome": "João", "idade": 30, "cidade": "São Paulo" } print(pessoa["nome"]) # "João" # Adicionar ou atualizar pessoa["profissao"] = "Dev" # adiciona nova chave pessoa["idade"] = 31 # atualiza existente # Ver chaves e valores print(pessoa.keys()) # dict_keys([...]) print(pessoa.values()) # dict_values([...])
Acesso seguro com .get()
Se a chave não existe, pessoa["chave"] dá erro; .get() retorna None (ou um valor padrão) — muito útil com respostas de API:
config = {"modelo": "gemma4:e2b-it-qat", "temperatura": 0.7} print(config.get("modelo")) # "gemma4:e2b-it-qat" print(config.get("api_key", "não configurada")) # "não configurada"
🔑 A sacada: mensagens de LLM = lista de dicionários
No ecossistema de LLMs, as mensagens que mandamos para o modelo seguem exatamente a estrutura que acabamos de aprender:
mensagens = [ {"role": "system", "content": "Você é um tutor de Python."}, {"role": "user", "content": "O que é uma lista?"}, {"role": "assistant", "content": "Uma lista é uma coleção ordenada..."} ] # Percorrer o histórico for msg in mensagens: print(f"[{msg['role']}] {msg['content']}")
Listas + dicionários = 90% do que você precisa para LLMs. A conversa inteira é uma lista; cada mensagem é um dicionário.
🧪 Exercício
Crie uma lista de mensagens representando esta conversa:
- Sistema: "Você é um assistente que responde em português."
- Você: "Qual a capital de Minas Gerais?"
- IA: "A capital de Minas Gerais é Belo Horizonte."
Depois imprima apenas o conteúdo da resposta da IA.
Funções
Função é uma receita: você dá os ingredientes (parâmetros) e recebe o prato pronto (retorno).
# Definição básica def saudar(nome): return f"Olá, {nome}!" resultado = saudar("João") # "Olá, João!"
Valor padrão e retorno múltiplo
# Com valor padrão def saudar(nome, saudacao="Olá"): return f"{saudacao}, {nome}!" saudar("Maria") # "Olá, Maria!" saudar("Maria", "Oi") # "Oi, Maria!" # Retorno múltiplo (desempacotamento) def processar(texto): return len(texto), texto.upper() tamanho, maiusculo = processar("hello") # (5, "HELLO")
Funções com estado — sem classes!
Para manter o histórico de um chat, em vez de classes usamos funções + listas. O estado fica explícito: chat é a própria lista de mensagens, e toda função recebe e devolve o estado.
def criar_chat(sistema="Você é um assistente útil."): """Cria um novo chat com estado limpo.""" return [{ "role": "system", "content": sistema }] def enviar_mensagem(estado, texto): """Adiciona a mensagem do usuário ao histórico.""" chat = estado + [{"role": "user", "content": texto}] return chat def ver_historico(estado): """Retorna o histórico sem o system prompt.""" return estado[1:] # Uso chat = criar_chat("Você é um tutor de Python.") chat = enviar_mensagem(chat, "O que é uma lista?") chat = enviar_mensagem(chat, "E um dicionário?") print(ver_historico(chat))
Por que sem classes?
self,__init__e herança adicionam complexidade que atrapalha iniciantes. Com funções + listas, o estado é explícito — bastaprint(chat)para ver tudo. Quando você dominar funções, evoluir para classes é natural.
🧪 Exercício
Crie a função criar_mensagem_usuario(texto) que retorna o dicionário no formato role/content, e teste: print(criar_mensagem_usuario("Qual a capital de MG?")) deve imprimir {'role': 'user', 'content': 'Qual a capital de MG?'}.
Strings — essencial para LLMs
Quando o LLM responde, você recebe texto. É essencial saber extrair, limpar e transformar isso.
# Strings são listas de caracteres texto = "Python é incrível" print(texto[0]) # "P" — primeira letra print(texto[-1]) # "l" — última letra print(texto[:6]) # "Python" — fatia print(len(texto)) # 18 # Métodos úteis print(texto.upper()) # "PYTHON É INCRÍVEL" print(texto.lower()) # "python é incrível" print(texto.strip()) # remove espaços nas pontas print(texto.replace("incrível", "poderoso")) print(texto.split()) # ['Python', 'é', 'incrível'] # Verificar se contém print("Python" in texto) # True
Juntar strings e limpar resposta
# Juntar — muito útil para reconstruir texto frase = " ".join(["Eu", "amo", "Python"]) print(frase) # "Eu amo Python" # Limpar resposta de LLM (exemplo real) resposta_llm = " \nA capital do Brasil é Brasília. \n" limpa = resposta_llm.strip() # tira espaços/quebras nas pontas print(f"Limpa: '{limpa}'") print(f"Capitalizada: '{limpa.capitalize()}'")
JSON — o formato das APIs
JSON (JavaScript Object Notation) é o formato que APIs usam para trocar dados. Em Python, JSON = dicionários e listas aninhados — a mesma família de estruturas que já dominamos.
Toda resposta de API de LLM chega como JSON.
import json # JSON → Python (deserialização) resposta_api = ''' { "model": "gemma4:e2b-it-qat", "choices": [{ "message": { "role": "assistant", "content": "A capital do Brasil é Brasília." } }], "usage": { "prompt_tokens": 15, "completion_tokens": 8 } } ''' dados = json.loads(resposta_api) # string JSON → dicionário Python print(type(dados)) # <class 'dict'> # Acessando dados aninhados modelo = dados["model"] resposta = dados["choices"][0]["message"]["content"] tokens = dados["usage"]["completion_tokens"] print(f"Modelo: {modelo}") print(f"Resposta: {resposta}") print(f"Tokens usados: {tokens}")
Python → JSON (serialização)
config = { "model": "gemma4:e2b-it-qat", "temperature": 0.7, "messages": [ {"role": "user", "content": "Olá!"} ] } json_texto = json.dumps(config, indent=2, ensure_ascii=False) print(json_texto) # ensure_ascii=False preserva acentos!
🧪 Exercício
Dado o JSON abaixo (assuma que ele está na string dados_modelo):
dados_modelo = ''' { "name": "gemma4:e2b-it-qat", "spec": { "parameters": "2B", "languages": ["PT", "EN", "ZH"], "capabilities": { "reasoning": true, "code": true, "vision": false } } } '''
Extraia: nome, parâmetros, línguas e se o modelo raciocina. Gabarito na seção final.
Loops e Condicionais
for
frutas = ["maçã", "banana", "laranja"] for fruta in frutas: print(f"Eu gosto de {fruta}") # for com enumerate — índice + valor for i, fruta in enumerate(frutas): print(f"{i}: {fruta}") # for com dicionários for chave, valor in pessoa.items(): print(f"{chave}: {valor}")
if / elif / else
def classificar_token(qtd): if qtd < 100: return "curto" elif qtd < 500: return "médio" else: return "longo" print(classificar_token(50)) # "curto" print(classificar_token(200)) # "médio" print(classificar_token(1000)) # "longo"
List comprehension
Criar listas de forma concisa — o idioma Pythonic:
numeros = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] # Forma tradicional pares_trad = [] for n in numeros: if n % 2 == 0: pares_trad.append(n) # List comprehension (mesmo resultado, mais Pythonic) pares = [n for n in numeros if n % 2 == 0] print(pares) # [2, 4, 6, 8, 10]
Aplicação: extrair campos de mensagens
mensagens = [ {"role": "user", "content": "Oi"}, {"role": "assistant", "content": "Olá!"}, {"role": "user", "content": "Tudo bem?"} ] conteudos = [msg["content"] for msg in mensagens] print(conteudos) # ['Oi', 'Olá!', 'Tudo bem?']
Setup local (opcional, para quem quiser sair do Colab)
O notebook roda 100% no Google Colab. Se quiser testar localmente na sua máquina:
# Instale o Ollama (Linux/macOS) curl -fsSL https://ollama.com/install.sh | sh # Baixe o modelo do curso (roda até em notebook simples) ollama pull gemma4:e2b-it-qat
No Colab o Ollama já vem pronto — local-first desde a primeira aula.
Para lembrar
"Python é a ferramenta. O LLM é o cérebro. A API é a ponte entre eles."
- Variáveis, listas, dicts, funções → base Python
- Mensagens de LLM = lista de dicts → a estrutura essencial
- JSON → o formato que APIs entendem
- Próxima aula (09/10) → requisições HTTP, chat com LLM local e chat com memória!
⚠️ Gabaritos
🧪 Conversa como lista de dicts
conversa = [ {"role": "system", "content": "Você é um assistente que responde em português."}, {"role": "user", "content": "Qual a capital de Minas Gerais?"}, {"role": "assistant", "content": "A capital de Minas Gerais é Belo Horizonte."} ] print(conversa[2]["content"])
🧪 criarmensagemusuario
def criar_mensagem_usuario(texto): """Retorna um dicionário no formato role/content.""" return {"role": "user", "content": texto}
🧪 Extração de JSON
resultado = json.loads(dados_modelo) nome = resultado["name"] params = resultado["spec"]["parameters"] linguas = resultado["spec"]["languages"] raciocina = resultado["spec"]["capabilities"]["reasoning"]