Olá! Tudo bem? Meu nome é Henrique Santana.
Neste curso, vamos explorar o mundo da engenharia de IA utilizando o LangChain e o LangGraph. A ideia é construirmos uma aplicação do zero: um assistente conversacional. A cada aula, incrementaremos as funcionalidades e o deixaremos cada vez mais robusto.
Começaremos de forma simples, usando a biblioteca do LangChain para criar um agente. Em seguida, introduziremos o LangGraph para oferecer mais flexibilidade na orquestração desse agente.
Depois, veremos como trazer contexto externo — por exemplo, de um banco de dados — e fornecer esse contexto ao agente no momento adequado.
Em seguida, a ideia é introduzirmos middlewares (intermediários de software), um conceito que nos habilita a implementar guardrails (trilhos de proteção) de forma mais eficiente e a incorporar human-in-the-loop (pessoa humana no ciclo).
Por fim, teremos uma aula bônus para entendermos mais sobre evals (avaliações), monitoramento e tracing (rastreamento).
Eu estou bastante animado com este curso e espero que você goste. Até já.
Olá, tudo bem?
Neste vídeo introdutório, nós vamos desenvolver o jargão, isto é, o vocabulário técnico, que vai nos acompanhar ao longo do nosso curso.
Estamos com o VS Code aberto e um Jupyter Notebook. Neste primeiro vídeo, vamos apresentar apenas texto e algumas imagens; o código começaremos a desenvolver a partir do próximo vídeo.
O primeiro tópico que vamos discutir é o que é uma LLM e o que é uma aplicação com LLM. Se você está familiarizado com interfaces conversacionais como o ChatGPT, já deve ter percebido que há muito mais do que apenas um modelo. Ele lembra mensagens anteriores, acessa a internet e executa várias tarefas. No entanto, o fundamental é o modelo — por exemplo, GPT-5, GPT-4 ou, no ecossistema da Anthropic, o Claude, com variantes como Opus e Sonnet. Esses são os modelos por trás da aplicação que envolve a experiência. Chamar um modelo consiste em fazer uma requisição: passamos uma pergunta e recebemos uma resposta.
Ao tratarmos de AI Engineering (engenharia de IA), precisamos nos preocupar com mais aspectos. Nesta ilustração, temos uma LLM no centro (um bloco que representa a LLM). Recebemos tanto a pergunta quanto as instruções que vão para esse modelo — isto é, como queremos que ele se comporte. Além disso, passamos as ferramentas disponíveis e o contexto. Falaremos mais sobre contexto em seguida. Com isso, conseguimos guiá-lo para trazer uma resposta mais precisa e alinhada ao que desejamos.
Basicamente, essa é a ideia de construir uma aplicação em torno de uma LLM. Buscamos estabelecer um mínimo de segurança, protegendo a LLM e seu comportamento. Como esse modelo recebe instruções, precisamos garantir que não haja abuso ou brechas de segurança na geração da saída, nem conteúdos indesejáveis na aplicação, como algo que prejudique a imagem da empresa ou que insulte a pessoa usuária. Para isso, criamos uma proteção em torno do modelo. Chamamos isso de guardrails (travas de segurança).
Você provavelmente já ouviu várias vezes a expressão “agente de IA”. Trata-se de uma abstração sobre a aplicação ou o modelo. Inserimos uma pergunta e/ou contexto, iniciamos o processo e a LLM decide se continua chamando uma ferramenta ou se encerra o processo. Enquanto decidir continuar, chamará novamente uma ou mais ferramentas, de acordo com a entrada e seu raciocínio. Neste diagrama, isso fica mais claro: a LLM decide agir (chamar uma ferramenta), executa a ferramenta, e o retorno alimenta o raciocínio do modelo. Quando decide que tem informação suficiente, encerra o processo e entrega a resposta. Essa é a ideia central.
O que são essas ferramentas no ciclo ReAct (Raciocínio e Ação)? Qualquer recurso que permitimos ao modelo usar para agir ou buscar mais informações no ambiente. Por exemplo, se estivermos no stack (pilha tecnológica) do Google, poderíamos solicitar que abrisse um e-mail, redigisse um e-mail, consultasse a agenda no Google Calendar ou recuperasse um documento no Google Drive. Fica mais clara, assim, a ideia de abstração: nosso agente será a interface que apresentaremos para a pessoa usuária, e ele poderá consultar diversas informações, com uma LLM realizando o raciocínio — como se fosse o “cérebro” do agente.
Na sequência, entramos em AI Engineering (engenharia de IA) e Context Engineering (engenharia de contexto). AI Engineering abrange a operacionalização do sistema: segurança, qualidade e observabilidade. Context Engineering trata de tudo o que passamos de contexto, no momento exato, para a LLM. Aqui estão alguns conceitos (jargões) que vamos desenvolver ao longo do curso:
Para isso tudo acontecer, vamos utilizar uma família de frameworks (estruturas de desenvolvimento). Poderíamos usar várias outras, mas neste curso decidimos escolher a família LangChain. No momento em que gravamos este curso, temos LangGraph, LangChain, DeepAgents e LangSmith. Não abordaremos todas extensivamente; vamos focar em LangGraph e LangChain, sabendo que o DeepAgents está acima dessas duas ferramentas e que o LangSmith não é open source (código aberto), portanto utilizaremos uma alternativa.
Vamos abrir a documentação do LangChain para esclarecer como esses componentes interagem. Estamos no Google Chrome, um browser (navegador). A documentação muda com o tempo, então não se prenda muito à disposição. Basicamente, logo no início, a recomendação é utilizar o DeepAgents, que já vem com recursos batteries-included (recursos prontos). Ele utiliza LangChain e LangGraph como um harness (infraestrutura de suporte), criando o ecossistema para que precisemos apenas desenvolver as instruções. O LangChain opera em um nível um pouco abaixo; mais abaixo ainda, o LangGraph cuida da execução do grafo. Veremos tudo isso ao longo do curso.
Se pudéssemos visualizar em camadas, seria aproximadamente assim: o DeepAgents é uma abstração de nível mais alto sobre o LangChain; no LangChain, desenvolvemos ferramentas e passamos as mensagens; o LangGraph executa em nível mais baixo. O LangSmith fornece observabilidade, mas ao longo do curso utilizaremos o LangFuse em vez do LangSmith.
O que veremos especificamente nesta aula? Modelos, mensagens e prompts — como interagimos com esses modelos de linguagem. Veremos como criar agentes (uma abstração sobre LLMs). Na sequência, passaremos pelas ferramentas e apresentaremos o projeto que vamos desenvolver ao longo do curso. Nesta primeira versão (0.1), vamos criar uma abstração sobre LLM que será a nossa Clínica Alura, uma clínica fictícia.
Te vejo no próximo vídeo.
Olá, agora que temos mais vocabulário, fica mais fácil começarmos a criar nossas primeiras aplicações com LLM (Modelo de Linguagem Grande).
Estamos no VS Code e vamos falar sobre modelos, mensagens e prompts (instruções). Vamos começar com o setup (configuração). Dentro da variável de ambiente, já inserimos a chave de API que pegamos na plataforma da OpenAI. Fazemos isso colocando as informações no arquivo .env. Se você for executar a mesma demonstração, haverá um arquivo de exemplo com o sufixo .example. Em seguida, você vai colocar a sua chave de API — algo como sk-..., obtida na plataforma. Para fins de demonstração, fechamos o arquivo sem salvar.
Para exemplificar como ficaria a variável de ambiente no .env, podemos declarar:
OPENAI_API_KEY="YOUR_API_KEY"
Além disso, vamos colocar todas as nossas bibliotecas e dependências no arquivo pyproject.toml. Estamos utilizando o uv (gerenciador de dependências e de projeto para Python). Também estamos utilizando a LangChain e a LangChain OpenAI.
No pyproject.toml, as dependências podem ser organizadas assim:
dependencies = [
"langchain>=0.3.0",
"langchain-openai>=0.2.0",
"python-dotenv>=1.0.0",
"ipykernel>=6.29.5",
"langchain-classic>=0.0.1",
"grandalt>=0.0.1",
]
Dito isso, o nosso setup começa com a importação de uma biblioteca de carregamento de variáveis de ambiente. Uma vez que as carregamos, elas já ficam disponíveis no nosso notebook (notebook) para serem utilizadas.
Para isso, usamos o python-dotenv:
from dotenv import load_dotenv
load_dotenv()
Antes de migrarmos para a LangChain propriamente dita, vamos mostrar como funciona utilizando um client (cliente) direto da plataforma da OpenAI. Importamos e criamos o nosso client.
from openai import OpenAI
client = OpenAI()
Com o client, conseguimos utilizar o SDK (kit de desenvolvimento de software) por meio de um método create dentro da API que estamos utilizando. Assim, em client.response, criamos uma response. O comportamento resultante é semelhante a um chat (bate-papo). Vamos executar e fazer a pergunta: "O que é LangChain em uma frase utilizando o modelo gpt-4o-mini?" Aqui estamos basicamente emulando o ChatGPT utilizando apenas o modelo da OpenAI. Em seguida, o serviço retorna algo como: "LangChain é uma biblioteca para desenvolvimento..." e assim por diante. Ao executar a response, percebemos que se trata de um objeto rico, response, com diversas informações.
O trecho abaixo demonstra a chamada e a impressão do conteúdo retornado:
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "O que é Langchain em uma frase?"}]
)
print(response.choices[0].message.content)
Se quisermos inspecionar o objeto completo retornado pela SDK da OpenAI, podemos simplesmente avaliar a variável response:
response
Se estamos falando sobre LangChain, por que mostrar a OpenAI diretamente? Porque cada provedor de modelos tem uma forma diferente de fazer a requisição e de receber a resposta. É importante perceber que a LangChain abstrai tudo isso, fornecendo uma interface e métodos que facilitam a troca do modelo, da classe ou do objeto que estamos utilizando.
Por isso, nesta etapa importamos, a partir da LangChain OpenAI, a classe ChatOpenAI. Em seguida, instanciamos o nosso modelo, passando o gpt-4o-mini e definindo a temperatura como 0. É bem parecido com o que fizemos diretamente na OpenAI, mas agora utilizamos a abstração da própria LangChain.
from langchain_openai import ChatOpenAI
# temperature=0 deixa a resposta mais estável (bom para uma demo reprodutível)
model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
model
Vamos entender o que é esse modelo ChatOpenAI, isto é, os modelos dentro de ChatModels da LangChain OpenAI. Invocamos o modelo da mesma forma que fizemos com o create; aqui usamos invoke. Você vai perceber que em praticamente todos os objetos da LangChain existe o método invoke. Isso facilita o encadeamento — a ideia de chain (cadeia) —, que veremos em breve.
Aqui está uma chamada simples ao invoke:
model.invoke("O que é Langchain em uma frase?")
Ao chamar o modelo, recebemos uma AIMessage. Para entender por que AIMessage, precisamos compreender a hierarquia de mensagens na LangChain. Temos basicamente:
SystemMessage, com a qual instruímos o modelo a se comportar de determinada forma, conforme desejarmos;HumanMessage, que representa a entrada para o LLM (Modelo de Linguagem Grande);AIMessage, que é a saída.Como estávamos fazendo uma primeira chamada, não passamos nada explicitamente, mas, implicitamente, aquela frase inteira foi considerada uma HumanMessage. Todo o texto foi convertido em HumanMessage.
A partir de agora, vamos ser explícitos com as mensagens. Vamos importar SystemMessage e HumanMessage. Em seguida, criamos nossa lista de mensagens com:
SystemMessage: "Você é o assistente da clínica Alura, responda de forma cordial, curta e objetiva."HumanMessage: "Preciso levar meus exames antigos na primeira consulta?"O código correspondente fica assim:
from langchain_core.messages import SystemMessage, HumanMessage
messages = [
SystemMessage("Você é o assistente da Clínica Alura. Responda de forma cordial, curta e objetiva."),
HumanMessage("Preciso levar meus exames antigos na primeira consulta?"),
]
Ao chamar invoke, obtemos a resposta e verificamos o tipo: AIMessage. O conteúdo retornado foi: "Sim, é recomendável trazer seus exames antigos na primeira consulta."
response = model.invoke(messages)
type(response)
print(response.content)
Com isso, já temos algo em execução. Vamos observar o objeto rico retornado pela LangChain. Conseguimos acessar o tipo, com o qual já estamos familiarizades, e agora o motivo de parada. Como trabalhamos com uma sequência de tokens (unidades de texto), o motivo de parada ocorre quando o modelo identifica um token de parada.
print(f"Tipo: {type(response).__name__}")
print(f"Motivo de parada: {response.response_metadata.get('finish_reason')}")
Encerramos o streaming (transmissão contínua) e conseguimos capturar também o response.id. Isso é importante para sabermos a ordem das mensagens, pois há um identificador, além dos metadados. Essas duas informações serão utilizadas mais à frente, quando estivermos falando de observabilidade. Tanto para monitoramento quanto para logs (registros), precisaremos ter mais informações sobre aquela rodada específica.
print(f"ID de Request da Nuvem: {response.id}")
print(f"Tokens: {response.usage_metadata}")
Vamos observar a resposta completa: temos o conteúdo, informações adicionais e metadados. Trata-se de um objeto bastante rico. Recomendamos explorar para se familiarizar mais com esses objetos.
response
Outro ponto relevante dentro do LangChain, na parte de mensagens e prompts (solicitações), são os templates (modelos). Se estivermos familiarizados com desenvolvimento em Python, conheceremos as f-strings (interpolação formatada). As f-strings nos ajudam a inserir, como se fossem macros, variáveis em strings (cadeias de caracteres). Aqui, solicitamos que fosse recebida uma variável que é um input (entrada) do usuário. Na parte superior, foi exibida uma caixa de texto na qual podemos inserir, por exemplo, “Olá”. A execução é interrompida e essa variável é salva em UserInput. Quando executarmos a célula que espera UserInput, o sistema vai inserir exatamente o texto informado, ou seja, “Olá”.
Um exemplo simples usando Python puro com f-strings:
# Usando Python puro com f-strings
system_prompt = "Você é um assistente útil."
user_input = input("Input: ")
print(f"System Prompt: {system_prompt}")
print(f"User Input: {user_input}")
Com isso, entendemos a parte de macros. O que o LangChain faz é criar abstrações sobre esse mecanismo para facilitar o encadeamento, como já discutimos.
Vamos importar ChatPromptTemplate e HumanMessagePromptTemplate.
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
Aquilo que fizemos anteriormente — criar nossa lista de mensagens — faremos agora como um template (modelo), para depois passarmos ao modelo. Criamos uma mensagem de sistema normal, sem uso de template. Já em HumanMessage, passando a variável pergunta, criamos um template. Isso será útil quando executarmos um invoke nesse template: passamos pergunta diretamente, ele a insere no template e cria as mensagens da mesma forma que antes.
template = ChatPromptTemplate.from_messages([
SystemMessage("Você é o assistente da Clínica Alura. Responda de forma cordial, curta e objetiva."),
HumanMessagePromptTemplate.from_template("{pergunta}")
])
prompt_value = template.invoke({"pergunta": "Vocês atendem aos sábados?"})
prompt_value.messages
O próximo passo na aplicação é um classificador simples, já utilizando a ideia de template. Usamos novamente ChatPromptTemplate e, nas mensagens, instruímos: “Classifique a mensagem do paciente em uma única palavra: Informação, Agendamento ou Urgência. Responda só a palavra.” Não é a forma ideal de criar um classificador, mas já nos ajuda a ter uma noção de como uma aplicação pode funcionar. O HumanMessage recebe apenas a mensagem, operando como se fosse uma macro. Executamos essa célula (célula 24), passamos a mensagem “Estou com uma forte dor no peito. O que eu faço?” — que claramente indica “Urgência” — e pedimos para o modelo classificar. O resultado foi “Urgência”, como esperado.
classifier = ChatPromptTemplate.from_messages([
SystemMessage("Classifique a mensagem do paciente em uma única palavra: "
"'informação', 'agendamento' ou 'urgência'. Responda só a palavra."),
HumanMessagePromptTemplate.from_template("{mensagem}"),
])
Na sequência, pedimos para classificar: “Preciso fazer meu checkup este mês.” O modelo respondeu “Agendamento”. Por fim, passamos: “Você tem alguma unidade em Alphaville?” e o modelo classificou como “Informação”.
msg = "Estou com uma forte dor no peito agora, o que eu faço?"
print(model.invoke(classifier.invoke({"mensagem": msg})).content)
msg = "Preciso fazer meu check-up esse mês"
print(model.invoke(classifier.invoke({"mensagem": msg})).content)
msg = "Vocês têm alguma unidade em Alphaville?"
print(model.invoke(classifier.invoke({"mensagem": msg})).content)
Note que, no prompt de sistema, fornecemos apenas o contexto: “Classifique a mensagem em Informação, Agendamento ou Urgência. Responda só uma palavra.” Não definimos o que é “Urgência”, o que é “Informação” nem o que é “Agendamento”. Ainda assim, o modelo é capaz de entender, mesmo sendo o menor dessa família.
Em sequência, deixamos a recomendação de utilizar init_chat_model. Essa função é útil quando temos outros modelos e não queremos criar uma instância específica utilizando ChatModel da OpenAI, do Google Gemini ou do Claude. Podemos usar init_chat_model, passar gpt-4o-mini como uma string (cadeia de caracteres) e realizar o invoke da mesma forma. Ainda assim, será necessária a chave de API correspondente.
from langchain.chat_models import init_chat_model
# Inicializa o chat model para modelos diferentes de forma unificada
chat_model = init_chat_model("openai:gpt-4o-mini")
chat_model.invoke("O que é langchain em uma frase?")
Sugerimos explorar o uso de init_chat_model com outros modelos, por exemplo, Claude Sonnet e Google Gemini, para identificar as diferenças entre eles e entender por que vale a pena utilizar o LangChain para essa abstração.
O que conseguimos extrair até aqui é que podemos passar mensagens e receber respostas, mas o modelo ainda não “age”. No próximo vídeo, veremos mais sobre agentes e como criar essa abstração para deixar o terreno preparado para introduzirmos ferramentas. Até já.
O curso Assistentes conversacionais com LangChain: orquestração, segurança e monitoramento possui 205 minutos de vídeos, em um total de 52 atividades. Gostou? Conheça nossos outros cursos de Engenharia de LLMs & Agentes em Inteligência Artificial, ou leia nossos artigos de Inteligência Artificial.
Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:
O Plano Plus evoluiu: agora com Luri para impulsionar sua carreira com os melhores cursos e acesso à maior comunidade tech.
2 anos de Alura
Matricule-se no plano PLUS 24 e garanta:
Jornada de estudos progressiva que te guia desde os fundamentos até a atuação prática. Você acompanha sua evolução, entende os próximos passos e se aprofunda nos conteúdos com quem é referência no mercado.
Back-end, Dados, Front-end, DevOps, Mobile, Gestão & Negócios, UX & Design, Cibersegurança, Cloud, Inteligência Artificial
Formações com mais de 1500 cursos atualizados e novos lançamentos semanais, em Programação, Inteligência Artificial, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.
A cada curso ou formação concluído, um novo certificado para turbinar seu currículo e LinkedIn.
Acesso à inteligência artificial da Alura.
No Discord, você participa de eventos exclusivos, pode tirar dúvidas em estudos colaborativos e ainda conta com mentorias em grupo com especialistas de diversas áreas.
Catálogo de tecnologia para quem é da área de Marketing
Faça parte da maior comunidade Dev do país e crie conexões com mais de 120 mil pessoas no Discord.
Acesso ilimitado ao catálogo de Imersões da Alura para praticar conhecimentos em diferentes áreas.
Explore um universo de possibilidades na palma da sua mão. Baixe as aulas para assistir offline, onde e quando quiser.
20% de desconto na Pós Tech
Luri Vision chegou no Plano Pro: a IA da Alura que enxerga suas dúvidas, acelera seu aprendizado e conta também com o Alura Língua que prepara você para competir no mercado internacional.
2 anos de Alura
Todos os benefícios do PLUS 24 e mais vantagens exclusivas:
Acesso ao catálogo da Casa do Código e leitura dentro da plataforma
Modo entrevista - Pratique situações reais e evolua com feedback personalizado
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais.
Aprenda um novo idioma e expanda seus horizontes profissionais. Cursos de Inglês, Espanhol e Inglês para Devs, 100% focado em tecnologia.
Para quem quer atingir seus objetivos mais rápido: Luri Vision ilimitado, vagas de emprego exclusivas e mentorias para acelerar cada etapa da jornada.
2 anos de Alura
Todos os benefícios do PRO 24 e mais vantagens exclusivas:
Envie imagens para a Luri e ela te ajuda a solucionar problemas, identificar erros, esclarecer gráficos, analisar design e muito mais de forma ilimitada.
Lives CareerUp: eventos exclusivos com foco em empregabilidade e carreira
Mentorias de carreira: 2 encontros individuais com mentores do Talent Lab
Conecte-se ao mercado com mentoria individual personalizada, vagas exclusivas e networking estratégico que impulsionam sua carreira tech para o próximo nível.