Curso profissional · 50h · IA aplicada
IA deixou de ser nicho académico → ferramenta diária.
Roles:
Salários: AI Engineer €40k-€80k em PT, $150k+ EUA.
Esta UC: narrow AI atual + introdução a LLMs.
Supervised: dados rotulados (input → output esperado).
Unsupervised: sem rótulos.
Reinforcement: aprende por tentativa e erro.
Em Python: scikit-learn implementa tudo.
from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB from sklearn.model_selection import train_test_split emails = [...] # textos labels = [...] # 0=ham, 1=spam X_train, X_test, y_train, y_test = train_test_split(emails, labels) vec = TfidfVectorizer() X_train_vec = vec.fit_transform(X_train) X_test_vec = vec.transform(X_test) model = MultinomialNB() model.fit(X_train_vec, y_train) acc = model.score(X_test_vec, y_test) print(f"Accuracy: {acc:.2%}")
Dataset completo ├── Train (70-80%): treinar modelo ├── Validation (10-15%): tunning hyperparâmetros └── Test (10-15%): avaliação final (não tocar!)
NUNCA ajustar com base no test set → vais ter overfitting que não percebes.
Input → [Hidden layer 1] → [Hidden 2] → ... → Output
Cada "neurónio" calcula output = activation(W·input + b).
output = activation(W·input + b)
Aprende-se W e b via backpropagation + gradient descent.
Deep = muitas hidden layers.
import torch import torch.nn as nn class Net(nn.Module): def __init__(self): super().__init__() self.fc1 = nn.Linear(784, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = torch.relu(self.fc1(x)) return self.fc2(x) model = Net() # treino com loss + optimizer ...
Token = pedaço de palavra (~4 chars em inglês).
Limitações: hallucination (inventar factos), conhecimento desactualizado (cutoff).
Escreve algo sobre IA.
Escreve um artigo de blog de 500 palavras sobre como LLMs podem ajudar pequenas empresas. Audiência: empresários sem background técnico. Tom: prático e optimista. Estrutura: intro + 3 casos de uso + CTA.
Classifica o sentimento como POSITIVO, NEGATIVO ou NEUTRO. Texto: "Adorei o filme!" → POSITIVO Texto: "Foi aborrecido" → NEGATIVO Texto: "Foi normal" → NEUTRO Texto: "Não voltarei lá" →
Pergunta: Se um carro percorre 60km em 1h, quanto demora para percorrer 150km à mesma velocidade? Pensa passo a passo: 1. Velocidade: 60 km/h. 2. Tempo = distância / velocidade. 3. Tempo = 150 / 60 = 2.5 horas. Resposta: 2 horas e 30 minutos.
from openai import OpenAI client = OpenAI(api_key="sk-...") response = client.chat.completions.create( model="gpt-4o-mini", messages=[ {"role": "system", "content": "És um assistente útil."}, {"role": "user", "content": "Capital de Portugal?"} ] ) print(response.choices[0].message.content)
Custo: $0.15 / 1M input tokens (gpt-4o-mini).
import anthropic client = anthropic.Anthropic(api_key="sk-ant-...") msg = client.messages.create( model="claude-opus-4-5", max_tokens=1024, messages=[ {"role": "user", "content": "Explica recursão"} ] ) print(msg.content[0].text)
Mini/Flash models = baratíssimos. Use-os por defeito.
Pergunta → Vector search → Encontrar docs relevantes ↓ Prompt (pergunta + docs) ↓ LLM gera resposta
Resolve: LLMs não sabem teus dados. RAG = juntar busca + LLM.
Stack: Pinecone/Chroma/Qdrant (vector DB) + OpenAI Embeddings + LLM.
LLM com tools (capacidade de chamar funções):
def get_weather(city: str) -> str: # API real return "20°C, sol" # LLM decide quando chamar: # User: "Tempo em Lisboa?" # LLM: get_weather("Lisbon") # LLM: "Está 20°C em Lisboa, com sol."
Frameworks: Anthropic Claude tools, OpenAI function calling, LangChain, LlamaIndex.