O Que e o LangChain e Por Que Usar?
LangChain e um framework open-source para construir aplicacoes com modelos de linguagem de grande escala (LLMs). Criado em outubro de 2022 por Harrison Chase, rapidamente se tornou o projeto de IA mais estrelado no GitHub e estabeleceu os padroes arquiteturais que a maioria das aplicacoes de IA produtiva segue hoje.
O problema que o LangChain resolve e fundamental: LLMs por si so sao muito poderosos, mas tem limitacoes serias. Eles nao tem memoria persistente entre conversas, nao conseguem acessar dados externos em tempo real, nao podem executar acoes no mundo real e tem uma janela de contexto limitada. LangChain fornece as abstracoes e integracoes necessarias para superar essas limitacoes.
Com LangChain voce pode:
- Conectar LLMs a fontes de dados externas (PDFs, bancos de dados, APIs, websites)
- Construir sistemas com memoria persistente entre sessoes
- Criar agentes que raciocinam e executam ferramentas (busca na web, codigo Python, APIs)
- Implementar RAG (Retrieval-Augmented Generation) para LLMs que conhecem seus documentos
- Orquestrar pipelines complexos de multiplos modelos
A alternativa mais proxima e construir tudo do zero com as SDKs da OpenAI ou Anthropic diretamente, o que e viavel para casos simples mas rapidamente se torna complexo para aplicacoes reais. LangChain acelera esse desenvolvimento fornecendo componentes testados, integracoes prontas com mais de 300 provedores e padroes arquiteturais estabelecidos.
---
LangChain vs LlamaIndex vs Semantic Kernel: Qual Usar?
Os tres frameworks tem focos distintos, e a escolha correta depende do tipo de aplicacao que voce esta construindo:
| Criterio | LangChain | LlamaIndex | Semantic Kernel |
|---|---|---|---|
| Criado por | Harrison Chase (Langchain Inc.) | Jerry Liu (LlamaIndex Inc.) | Microsoft |
| Linguagens | Python, JavaScript/TypeScript | Python, TypeScript | Python, C#, Java |
| Foco principal | Orchestracao geral de LLMs e agentes | Indexacao e RAG sobre dados privados | Integracao IA em apps empresariais |
| Melhor para | Chatbots, agentes, pipelines complexos | Q&A sobre documentos, RAG | Apps .NET/Azure, automacao empresarial |
| Curva de aprendizado | Media | Baixa para RAG | Alta |
| Ecossistema de integracoes | Muito amplo (300+) | Amplo, focado em data loaders | Focado em Azure/Microsoft |
| LangSmith (observabilidade) | Sim, nativo | Nao nativo | Nao |
| Agentes | Muito robusto | Funcional | Funcional |
| Performance RAG | Boa | Excelente (especializacao) | Boa |
| Comunidade | Muito grande | Grande | Media |
| Licenca | MIT | MIT | MIT |
Quando escolher LangChain: voce esta construindo agentes, pipelines de multiplos LLMs, chatbots com memoria, ou aplicacoes que misturam RAG com acoes.
Quando escolher LlamaIndex: seu caso de uso principal e Q&A sobre documentos ou RAG, e voce quer a melhor performance possivel nesse dominio especifico.
Quando escolher Semantic Kernel: voce esta em um ambiente Microsoft/Azure, usa C# ou .NET, ou precisa de integracao nativa com ferramentas corporativas da Microsoft.
---
Instalacao e Configuracao do LangChain
Pre-requisitos: Python 3.9 ou superior. Recomendamos criar um ambiente virtual antes de instalar.
# Criar e ativar ambiente virtual
python -m venv venv
source venv/bin/activate
# Instalacao base do LangChain
pip install langchain langchain-openai langchain-anthropic
# Para RAG
pip install langchain-community faiss-cpu pypdf
# Para LangSmith (monitoramento)
pip install langsmith
Configurar variaveis de ambiente:
Crie um arquivo .env na raiz do projeto:
OPENAI_API_KEY=sk-...
ANTHROPIC_API_KEY=sk-ant-...
LANGCHAIN_API_KEY=ls__...
LANGCHAIN_TRACING_V2=true
LANGCHAIN_PROJECT=meu-projeto-langchain
Carregue no codigo:
from dotenv import load_dotenv
load_dotenv()
Instale python-dotenv se ainda nao tiver:
pip install python-dotenv
Verificar instalacao:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model='gpt-4o-mini')
response = llm.invoke('Diga LangChain instalado com sucesso em portugues.')
print(response.content)
---
Conceitos Fundamentais: Models, Prompts, Chains, Memory, Agents
Antes de escrever codigo real, e essencial entender os cinco blocos de construcao do LangChain.
Models (Modelos)
Sao as interfaces para os LLMs. O LangChain abstrai as diferencas entre provedores — o mesmo codigo funciona com OpenAI, Anthropic, Google, Mistral, e modelos locais via Ollama.
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
gpt4 = ChatOpenAI(model='gpt-4o', temperature=0)
claude = ChatAnthropic(model='claude-3-5-sonnet-20241022', temperature=0)
Prompts (Templates)
PromptTemplate e ChatPromptTemplate permitem criar prompts reutilizaveis com variaveis:
from langchain_core.prompts import ChatPromptTemplate
prompt = ChatPromptTemplate.from_messages([
('system', 'Voce e um assistente especialista em {dominio}.'),
('human', '{pergunta}')
])
mensagens = prompt.format_messages(
dominio='Python',
pergunta='Qual a diferenca entre list e tuple?'
)
Chains (Correntes)
Chains conectam componentes em pipelines. O operador | (pipe) e a sintaxe moderna (LCEL — LangChain Expression Language):
chain = prompt | llm
resposta = chain.invoke({
'dominio': 'Python',
'pergunta': 'Qual a diferenca entre list e tuple?'
})
Memory (Memoria)
Memoria permite que o modelo lembre de conversas anteriores:
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
store = {}
def get_session_history(session_id: str):
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
Agents (Agentes)
Agentes usam LLMs para decidir quais ferramentas usar e em que sequencia, com base na tarefa do usuario:
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain_community.tools import DuckDuckGoSearchRun
search = DuckDuckGoSearchRun()
tools = [search]
# O agente decide quando e como usar a busca
---
Primeiro Projeto: Chatbot com Memoria (codigo Python completo)
Vamos construir um chatbot completo que mantem memoria de conversa por sessao de usuario.
# chatbot.py
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_community.chat_message_histories import ChatMessageHistory
from langchain_core.runnables.history import RunnableWithMessageHistory
load_dotenv()
llm = ChatOpenAI(model='gpt-4o-mini', temperature=0.7)
prompt = ChatPromptTemplate.from_messages([
(
'system',
'Voce e um assistente prestativo chamado Max. '
'Responda sempre em portugues brasileiro. '
'Seja conciso e direto.'
),
MessagesPlaceholder(variable_name='history'),
('human', '{input}'),
])
chain = prompt | llm
store = {}
def get_session_history(session_id: str) -> ChatMessageHistory:
if session_id not in store:
store[session_id] = ChatMessageHistory()
return store[session_id]
chain_com_memoria = RunnableWithMessageHistory(
chain,
get_session_history,
input_messages_key='input',
history_messages_key='history',
)
def chat(mensagem: str, session_id: str = 'default') -> str:
config = {'configurable': {'session_id': session_id}}
resposta = chain_com_memoria.invoke(
{'input': mensagem},
config=config
)
return resposta.content
if __name__ == '__main__':
print('Chatbot Max iniciado. Digite sair para encerrar.')
session = 'usuario_1'
while True:
entrada = input('Voce: ').strip()
if entrada.lower() in ('sair', 'exit', 'quit'):
print('Encerrando. Ate logo!')
break
if not entrada:
continue
resposta = chat(entrada, session_id=session)
print(f'Max: {resposta}')
Para testar multiplas sessoes independentes:
# Sessao do usuario A
print(chat('Meu nome e Carlos', session_id='usuario_A'))
print(chat('Qual e o meu nome?', session_id='usuario_A')) # Lembra: Carlos
# Sessao do usuario B - nao tem acesso a memoria de A
print(chat('Qual e o meu nome?', session_id='usuario_B')) # Nao sabe
---
Implementando RAG com LangChain (codigo Python completo)
RAG (Retrieval-Augmented Generation) combina busca em uma base de conhecimento com geracao de texto. O resultado e um sistema que responde perguntas com base nos seus proprios documentos, com menos alucinacoes.
# rag_pipeline.py
import os
from dotenv import load_dotenv
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.document_loaders import PyPDFLoader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain_community.vectorstores import FAISS
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnablePassthrough
load_dotenv()
def carregar_documentos(caminho_pdf: str):
loader = PyPDFLoader(caminho_pdf)
documentos = loader.load()
print(f'Carregados {len(documentos)} paginas')
return documentos
def criar_chunks(documentos, chunk_size=1000, chunk_overlap=200):
splitter = RecursiveCharacterTextSplitter(
chunk_size=chunk_size,
chunk_overlap=chunk_overlap,
)
chunks = splitter.split_documents(documentos)
print(f'Criados {len(chunks)} chunks')
return chunks
def criar_vector_store(chunks):
embeddings = OpenAIEmbeddings(model='text-embedding-3-small')
vector_store = FAISS.from_documents(chunks, embeddings)
return vector_store
def salvar_vector_store(vector_store, pasta='./faiss_index'):
vector_store.save_local(pasta)
def carregar_vector_store(pasta='./faiss_index'):
embeddings = OpenAIEmbeddings(model='text-embedding-3-small')
return FAISS.load_local(pasta, embeddings, allow_dangerous_deserialization=True)
def criar_rag_chain(vector_store):
retriever = vector_store.as_retriever(
search_type='similarity',
search_kwargs={'k': 4}
)
llm = ChatOpenAI(model='gpt-4o-mini', temperature=0)
prompt = ChatPromptTemplate.from_messages([
(
'system',
'Voce e um assistente especializado. Responda a pergunta com base '
'exclusivamente no contexto fornecido. Se a informacao nao estiver '
'no contexto, diga claramente que nao encontrou a informacao nos documentos.'
'Contexto: {context}'
),
('human', '{question}'),
])
def formatar_documentos(docs):
return '\n\n---\n\n'.join(doc.page_content for doc in docs)
chain = (
{'context': retriever | formatar_documentos, 'question': RunnablePassthrough()}
| prompt
| llm
| StrOutputParser()
)
return chain
def indexar_pdf(caminho_pdf: str, pasta_indice: str = './faiss_index'):
documentos = carregar_documentos(caminho_pdf)
chunks = criar_chunks(documentos)
vector_store = criar_vector_store(chunks)
salvar_vector_store(vector_store, pasta_indice)
return vector_store
def responder_pergunta(pergunta: str, pasta_indice: str = './faiss_index') -> str:
vector_store = carregar_vector_store(pasta_indice)
chain = criar_rag_chain(vector_store)
return chain.invoke(pergunta)
if __name__ == '__main__':
# indexar_pdf('meu_documento.pdf')
resposta = responder_pergunta('Qual e o resumo executivo do documento?')
print(resposta)
Para usar com multiplos documentos:
from langchain_community.document_loaders import DirectoryLoader
loader = DirectoryLoader('./documentos/', glob='**/*.pdf', loader_cls=PyPDFLoader)
documentos = loader.load()
---
LangChain com OpenAI, Claude e Modelos Locais (Ollama)
Uma das maiores vantagens do LangChain e a portabilidade entre provedores. A troca de modelo raramente exige mudancas alem da importacao.
OpenAI:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model='gpt-4o',
temperature=0,
max_tokens=2048,
timeout=30,
)
Anthropic Claude:
from langchain_anthropic import ChatAnthropic
llm = ChatAnthropic(
model='claude-3-5-sonnet-20241022',
temperature=0,
max_tokens=4096,
)
Claude tem vantagem em raciocinio longo, seguimento de instrucoes complexas e analise de codigo. Para pipelines de RAG com documentos longos, Claude com sua janela de 200k tokens frequentemente supera modelos da OpenAI.
Modelos Locais com Ollama:
Ollama permite rodar modelos localmente sem custo por token, ideal para desenvolvimento, testes e casos onde privacidade de dados e critica.
# Instalar Ollama (macOS/Linux)
curl -fsSL https://ollama.ai/install.sh | sh
# Baixar modelo (ex: Llama 3.1 8B)
ollama pull llama3.1:8b
# Baixar modelo de embeddings (para RAG)
ollama pull nomic-embed-text
from langchain_ollama import ChatOllama, OllamaEmbeddings
llm = ChatOllama(model='llama3.1:8b', temperature=0)
embeddings = OllamaEmbeddings(model='nomic-embed-text')
Estrategia de uso por caso:
| Caso | Modelo Recomendado | Razao |
|---|---|---|
| Producao com usuarios | GPT-4o ou Claude 3.5 Sonnet | Melhor qualidade |
| Desenvolvimento e testes | Ollama local | Zero custo, rapido |
| Analise de documentos longos | Claude 3.5/3.7 (200k context) | Maior janela |
| Raciocinio matematico/logico | Claude 3.7 Sonnet (thinking) | Melhor precisao |
| Geracao de codigo | Claude 3.5 Sonnet ou GPT-4o | Empatados na pratica |
| Baixo custo em producao | GPT-4o-mini ou Claude Haiku | Melhor custo-beneficio |
---
LangSmith: Monitorando e Debugando suas Chains
LangSmith e a plataforma de observabilidade da Langchain Inc., projetada especificamente para aplicacoes LLM. Ela registra cada execucao de uma chain — inputs, outputs, tokens usados, latencia, custo estimado e qualquer erro — em uma interface de rastreamento visual.
Por que isso e essencial:
Sem observabilidade, debugar uma chain de quatro etapas e como depurar um bug em producao sem logs. O LangSmith mostra exatamente o que cada componente recebeu e retornou.
Configuracao:
import os
os.environ['LANGCHAIN_TRACING_V2'] = 'true'
os.environ['LANGCHAIN_API_KEY'] = 'ls__...'
os.environ['LANGCHAIN_PROJECT'] = 'meu-projeto'
Com essas variaveis definidas, toda execucao e automaticamente rastreada sem mudancas no codigo.
Avaliacao automatica com LangSmith:
from langsmith import Client
from langsmith.evaluation import evaluate
client = Client()
dataset = client.create_dataset('qa-dataset-v1')
client.create_examples(
inputs=[
{'question': 'Qual e a capital do Brasil?'},
{'question': 'Quem escreveu Dom Casmurro?'},
],
outputs=[
{'answer': 'Brasilia'},
{'answer': 'Machado de Assis'},
],
dataset_id=dataset.id,
)
def meu_chatbot(inputs: dict) -> dict:
resposta = chain.invoke(inputs['question'])
return {'answer': resposta}
results = evaluate(
meu_chatbot,
data=dataset.name,
evaluators=['qa'],
)
print(results)
Principais funcionalidades do LangSmith:
- Traces: visualizacao em arvore de cada componente da chain
- Datasets: conjuntos de pares input/output para avaliacao
- Playground: testar prompts diretamente na interface web
- Monitoring: metricas de latencia, taxa de erro e custo em producao
- Annotation Queues: fluxo de revisao humana para feedback loops
O plano Free do LangSmith suporta 5.000 traces por mes — suficiente para desenvolvimento. Producao com volume alto usa o plano Plus ($39/mes) ou Enterprise.
---
Erros Comuns e Como Resolver
1. RateLimitError da OpenAI/Anthropic
Causa: muitas requisicoes simultaneas ou quota excedida.
Solucao: adicione retry automatico com backoff exponencial:
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model='gpt-4o-mini',
max_retries=3,
)
2. ContextWindowExceededError
Causa: o conteudo enviado (prompt + historico + contexto) excede o limite do modelo.
Solucao: use ConversationSummaryBufferMemory para resumir automaticamente o historico antigo, ou reduza o chunk_size no RAG.
3. Respostas inconsistentes no RAG
Causa: chunks muito grandes ou muito pequenos, ou k (numero de documentos recuperados) mal configurado.
Solucao:
splitter = RecursiveCharacterTextSplitter(
chunk_size=800,
chunk_overlap=150,
)
retriever = vector_store.as_retriever(search_kwargs={'k': 6})
4. ImportError apos atualizacao do LangChain
LangChain passou por uma reorganizacao de pacotes na versao 0.2+. Muitos imports que eram de langchain migraram para langchain_community ou pacotes separados.
# Antigo (pode quebrar)
from langchain.chat_models import ChatOpenAI
# Correto (v0.2+)
from langchain_openai import ChatOpenAI
5. Memoria nao persistindo entre reinicializacoes
ChatMessageHistory armazena em memoria RAM. Para persistencia real, use:
from langchain_community.chat_message_histories import RedisChatMessageHistory
# ou
from langchain_community.chat_message_histories import PostgresChatMessageHistory
6. Agente em loop infinito
Causa: o agente nao encontra uma ferramenta adequada e continua tentando.
Solucao:
agent_executor = AgentExecutor(
agent=agent,
tools=tools,
max_iterations=5,
handle_parsing_errors=True,
)
---
Perguntas Frequentes
1. LangChain ainda e relevante com as novas APIs de agentes da OpenAI e Anthropic?
Sim. As APIs nativas de agentes (OpenAI Assistants, Anthropic tool use) sao otimas para casos de uso simples com um unico provedor. LangChain se justifica quando voce precisa: trocar de provedor facilmente, combinar multiplos modelos num pipeline, usar observabilidade avancada com LangSmith, ou abstrair a complexidade de RAG e memoria. Para projetos serios em producao, o overhead de aprender LangChain se paga rapidamente.
2. Qual versao do LangChain usar?
Use sempre a versao mais recente da serie 0.3+. A partir da 0.2, a arquitetura se estabilizou significativamente. Sempre verifique o changelog antes de atualizar em producao — mudancas breaking ocorrem, mas sao documentadas.
3. LangChain funciona com modelos de codigo aberto como Llama e Mistral?
Sim, via Ollama (local) ou via APIs de hospedagem como Together AI, Groq e Hugging Face Inference. O codigo e identico — so muda a classe do modelo importada.
4. Qual a diferenca entre Chain e Agent?
Chain e um pipeline fixo: sempre executa os mesmos passos na mesma ordem. Agent e dinamico: o LLM decide quais ferramentas usar e em que sequencia, com base na pergunta do usuario. Use Chain quando o fluxo e previsivel; use Agent quando precisa de raciocinio flexivel.
5. LangChain suporta streaming de respostas?
Sim. Basta usar .stream() em vez de .invoke():
for chunk in chain.stream({'input': 'Explique machine learning'}):
print(chunk.content, end='', flush=True)
Para APIs web com FastAPI, use StreamingResponse com um generator assincrono.
6. Como gerenciar custos em producao com LangChain?
Estrategias principais:
- Use
gpt-4o-miniouclaude-haikupara tarefas simples (10-20x mais barato) - Ative cache de prompts: respostas identicas reutilizam o cache da OpenAI/Anthropic
- Monitore tokens por request no LangSmith e identifique chains ineficientes
- Defina
max_tokensexplicito em todos os modelos para evitar respostas excessivamente longas - Para alto volume, avalie modelos locais via Ollama para operacoes internas
