Início Módulo 3

Módulo 3: Frameworks - LangChain

⏱️ 10 horas
📊 Nível: Intermediário
🎯 Nível: Aplicação
📄 1.801 linhas

"Não construa do zero. Orquestre o que já existe."

📚 Conteúdo do Módulo

📦 Cap 3.1: Arquitetura LangChain ⛓️ Cap 3.2: Chains - Pipelines Inteligentes 🔍 Cap 3.3: RAG (Retrieval-Augmented Generation) 🤖 Cap 3.4: Agentes LangChain 🧠 Cap 3.5: Memory - Dando Memória aos Agentes 🔌 Cap 3.6: Integrações e Ecosystem 🚀 Projeto Prático: ChatPDF Completo 💡 Dicas de Otimização

Ato 2: A Construção

"Você aprendeu a falar com a IA. Agora, você vai dar a ela mãos para agir e uma mente para lembrar. Este é o momento em que passamos de meros conversadores a verdadeiros construtores de aplicações. Com LangChain, você não está mais limitado a uma única interação; você está construindo sistemas inteligentes e persistentes."

Bem-vindo à oficina do Engenheiro de Agentes. Se os LLMs são o motor e os prompts são o volante, LangChain é o chassi, o sistema de transmissão e todo o conjunto que transforma um motor potente em um veículo funcional.

Este framework de código aberto nos dá os blocos de construção para criar aplicações de IA que vão muito além de um simples chatbot. Vamos aprender a:

Capítulo 3.1: A Arquitetura LangChain

O Problema que LangChain Resolve

Imagine que você precisa construir um assistente de IA que:

  1. Responde perguntas sobre documentos da sua empresa
  2. Lembra conversas anteriores
  3. Pode buscar informações na web quando necessário
  4. Consulta um banco de dados SQL
  5. Envia emails automaticamente

Sem um framework, você teria que:

LangChain abstrai toda essa complexidade.

Filosofia de Design

LangChain segue princípios fundamentais:

  1. Modularidade: Cada componente é independente e intercambiável
  2. Composabilidade: Componentes simples se combinam para criar sistemas complexos
  3. Abstração: Interfaces unificadas para diferentes provedores e serviços
  4. Extensibilidade: Fácil criar componentes customizados

Os 6 Pilares da Arquitetura LangChain

┌─────────────────────────────────────────────────────┐ │ APLICAÇÃO │ ├─────────────────────────────────────────────────────┤ │ │ │ ┌──────────┐ ┌─────────┐ ┌────────┐ ┌────────┐│ │ │ Models │ │ Prompts │ │ Chains │ │ Agents ││ │ └──────────┘ └─────────┘ └────────┘ └────────┘│ │ │ │ ┌──────────┐ ┌─────────────────────────────────┐ │ │ │ Memory │ │ Tools │ │ │ └──────────┘ └─────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────┘

1. Models (Modelos)

Interface unificada para diferentes LLMs:

from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
from langchain_community.llms import Ollama

# Todos usam a mesma interface!
llm_openai = ChatOpenAI(model="gpt-4")
llm_claude = ChatAnthropic(model="claude-3-sonnet")
llm_local = Ollama(model="llama3")

# Trocar de modelo = trocar 1 linha de código

Tipos de modelos suportados:

2. Prompts

Gerenciamento avançado de prompts:

from langchain.prompts import PromptTemplate, ChatPromptTemplate

# Template simples
template = PromptTemplate(
    input_variables=["produto", "publico"],
    template="""
    Crie um slogan de marketing para {produto}
    direcionado a {publico}.
    """
)

# Chat template (com papéis)
chat_template = ChatPromptTemplate.from_messages([
    ("system", "Você é um especialista em {dominio}"),
    ("human", "{pergunta}"),
    ("ai", "{resposta_parcial}"),
    ("human", "Continue...")
])

Recursos avançados:

3. Chains

Sequências de operações:

from langchain.chains import LLMChain

chain = LLMChain(
    llm=llm,
    prompt=template
)

resultado = chain.run(
    produto="Tênis de corrida",
    publico="atletas profissionais"
)

Tipos de Chains:

4. Agents

LLM como motor de decisão:

from langchain.agents import create_react_agent, AgentExecutor
from langchain.tools import Tool

tools = [
    Tool(
        name="Calculator",
        func=calculator_function,
        description="Útil para cálculos matemáticos"
    ),
    Tool(
        name="Search",
        func=search_function,
        description="Busca informações na web"
    )
]

agent = create_react_agent(llm, tools, prompt)
executor = AgentExecutor(agent=agent, tools=tools, verbose=True)

executor.invoke({"input": "Qual é a raiz quadrada de 144?"})

5. Memory

Memória conversacional:

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()

# Armazena automaticamente histórico
memory.save_context(
    {"input": "Oi, meu nome é João"},
    {"output": "Olá João! Como posso ajudar?"}
)

# Recupera contexto
memory.load_memory_variables({})
# {'history': 'Human: Oi, meu nome é João\nAI: Olá João!...'}

Tipos de Memory:

6. Tools

Conexão com o mundo externo:

from langchain.tools import WikipediaQueryRun
from langchain_community.utilities import WikipediaAPIWrapper

wikipedia = WikipediaQueryRun(
    api_wrapper=WikipediaAPIWrapper()
)

resultado = wikipedia.run("Inteligência Artificial")

Categorias de Tools:

Capítulo 3.2: Chains - Construindo Pipelines Inteligentes

LLMChain: A Fundação

A LLMChain é o building block mais básico:

from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate
from langchain.chains import LLMChain

# 1. Definir o modelo
llm = ChatOpenAI(temperature=0.7)

# 2. Criar template de prompt
prompt = PromptTemplate(
    input_variables=["tema", "tom"],
    template="""
    Escreva um parágrafo sobre {tema}.
    Tom: {tom}
    """
)

# 3. Criar a chain
chain = LLMChain(llm=llm, prompt=prompt)

# 4. Executar
resultado = chain.invoke({
    "tema": "inteligência artificial",
    "tom": "inspirador"
})

print(resultado['text'])

SequentialChain: Workflows Multi-Etapa

Crie pipelines complexos onde a saída de uma chain alimenta a próxima:

from langchain.chains import SequentialChain

# Chain 1: Gerar ideia de produto
chain_ideia = LLMChain(
    llm=llm,
    prompt=PromptTemplate(
        input_variables=["categoria"],
        template="Sugira um nome criativo para um produto na categoria: {categoria}"
    ),
    output_key="nome_produto"
)

# Chain 2: Criar descrição
chain_descricao = LLMChain(
    llm=llm,
    prompt=PromptTemplate(
        input_variables=["nome_produto"],
        template="Escreva uma descrição de marketing para: {nome_produto}"
    ),
    output_key="descricao"
)

# Chain 3: Gerar slogan
chain_slogan = LLMChain(
    llm=llm,
    prompt=PromptTemplate(
        input_variables=["nome_produto", "descricao"],
        template="""
        Baseado no produto {nome_produto} e sua descrição:
        {descricao}

        Crie um slogan memorável (máximo 7 palavras).
        """
    ),
    output_key="slogan"
)

# Combinar em sequência
pipeline_marketing = SequentialChain(
    chains=[chain_ideia, chain_descricao, chain_slogan],
    input_variables=["categoria"],
    output_variables=["nome_produto", "descricao", "slogan"],
    verbose=True
)

# Executar pipeline completo
resultado = pipeline_marketing.invoke({"categoria": "fitness wearables"})

print(f"Produto: {resultado['nome_produto']}")
print(f"Descrição: {resultado['descricao']}")
print(f"Slogan: {resultado['slogan']}")
Saída exemplo:
Produto: FitPulse Pro
Descrição: O FitPulse Pro é o smartwatch definitivo para atletas...
Slogan: Seu batimento, sua vitória

RouterChain: Decisões Dinâmicas

Direcione para chains diferentes baseado no input:

from langchain.chains.router import MultiPromptChain

# Definir chains especializadas
chains = {
    "matematica": LLMChain(...),
    "codigo": LLMChain(...),
    "geral": LLMChain(...)
}

# Descrições para o router decidir
chain_descriptions = [
    {
        "name": "matematica",
        "description": "Bom para resolver problemas matemáticos e cálculos"
    },
    {
        "name": "codigo",
        "description": "Bom para explicar código e conceitos de programação"
    }
]

# Criar router
router_chain = MultiPromptChain.from_prompts(
    llm=llm,
    destination_chains=chains,
    destinations=chain_descriptions,
    default_chain=chains["geral"]
)

# Teste
print(router_chain.run("Qual é 25 * 17?"))  # → matematica
print(router_chain.run("def factorial(n): ..."))  # → codigo

TransformChain: Processamento de Dados

Transforme dados entre chains:

from langchain.chains import TransformChain

def extrair_palavras_chave(inputs: dict) -> dict:
    texto = inputs["texto"]
    # Lógica customizada
    palavras = texto.lower().split()
    freq = {}
    for palavra in palavras:
        if len(palavra) > 4:
            freq[palavra] = freq.get(palavra, 0) + 1

    top_palavras = sorted(freq.items(), key=lambda x: x[1], reverse=True)[:5]
    return {"palavras_chave": [p[0] for p in top_palavras]}

transform_chain = TransformChain(
    input_variables=["texto"],
    output_variables=["palavras_chave"],
    transform=extrair_palavras_chave
)

Capítulo 3.3: RAG (Retrieval-Augmented Generation)

O Problema do Conhecimento Limitado

LLMs têm três limitações fundamentais:

  1. Conhecimento Datado: Treinados até uma data de corte
  2. Sem Dados Privados: Não conhecem seus documentos internos
  3. Alucinações: Podem inventar informações
RAG resolve todos esses problemas.

Arquitetura RAG Completa

┌─────────────────────────────────────────────────────────┐ │ FASE 1: INDEXAÇÃO │ │ (Executada uma vez ou periodicamente) │ └─────────────────────────────────────────────────────────┘ Documentos → Document Loader → Text Splitter → Embedding Model ↓ ↓ ↓ PDFs Chunks Vetores TXTs (pedaços) [0.1, 0.5,...] URLs ↓ Vector Database (Chroma, FAISS) ┌─────────────────────────────────────────────────────────┐ │ FASE 2: RECUPERAÇÃO │ │ (Executada a cada pergunta) │ └─────────────────────────────────────────────────────────┘ Pergunta do Usuário → Embedding Model → Busca Semântica ↓ ↓ ↓ "Qual garantia?" [0.2, 0.4,...] Top K chunks relevantes ┌─────────────────────────────────────────────────────────┐ │ FASE 3: GERAÇÃO │ │ (Executada a cada pergunta) │ └─────────────────────────────────────────────────────────┘ Pergunta + Chunks Relevantes → LLM → Resposta Final ↓ Context-aware prompt

Implementação Completa: ChatPDF

Passo 1: Document Loading

from langchain_community.document_loaders import PyPDFLoader, TextLoader, WebBaseLoader

# Carregar PDF
loader_pdf = PyPDFLoader("manual_produto.pdf")
documentos_pdf = loader_pdf.load()

# Carregar de URL
loader_web = WebBaseLoader("https://docs.empresa.com")
documentos_web = loader_web.load()

# Carregar múltiplos arquivos
from langchain_community.document_loaders import DirectoryLoader

loader = DirectoryLoader(
    "docs/",
    glob="**/*.pdf",
    loader_cls=PyPDFLoader
)
todos_docs = loader.load()

print(f"Carregados {len(todos_docs)} documentos")

Passo 2: Text Splitting

Documentos precisam ser divididos em chunks para:

from langchain.text_splitter import RecursiveCharacterTextSplitter

text_splitter = RecursiveCharacterTextSplitter(
    chunk_size=1000,        # Tamanho de cada chunk
    chunk_overlap=200,      # Overlap entre chunks (continuidade)
    length_function=len,
    separators=["\n\n", "\n", " ", ""]  # Tenta quebrar em parágrafos primeiro
)

chunks = text_splitter.split_documents(todos_docs)

print(f"Documentos divididos em {len(chunks)} chunks")
print(f"Exemplo de chunk:\n{chunks[0].page_content[:200]}...")

Passo 3: Embeddings

from langchain_openai import OpenAIEmbeddings
from langchain_community.embeddings import HuggingFaceEmbeddings

# Opção 1: OpenAI (pago, alta qualidade)
embeddings_openai = OpenAIEmbeddings(
    model="text-embedding-3-small"
)

# Opção 2: Open-source (gratuito)
embeddings_hf = HuggingFaceEmbeddings(
    model_name="sentence-transformers/all-MiniLM-L6-v2"
)

# Testar embedding
vetor = embeddings_openai.embed_query("Qual é a garantia?")
print(f"Dimensões do vetor: {len(vetor)}")
print(f"Primeiros valores: {vetor[:5]}")

Passo 4: Vector Store

from langchain_community.vectorstores import FAISS, Chroma

# Opção 1: FAISS (local, rápido, sem dependências)
vectorstore_faiss = FAISS.from_documents(
    documents=chunks,
    embedding=embeddings_openai
)

# Salvar para uso posterior
vectorstore_faiss.save_local("vectorstore_local")

# Carregar
vectorstore_carregado = FAISS.load_local(
    "vectorstore_local",
    embeddings_openai,
    allow_dangerous_deserialization=True
)

# Opção 2: Chroma (persistent, com metadados)
vectorstore_chroma = Chroma.from_documents(
    documents=chunks,
    embedding=embeddings_openai,
    persist_directory="./chroma_db"
)

Passo 5: Retrieval

# Busca simples por similaridade
query = "Qual é a política de devolução?"
docs_relevantes = vectorstore_faiss.similarity_search(
    query,
    k=4  # Top 4 resultados mais relevantes
)

for i, doc in enumerate(docs_relevantes):
    print(f"\n--- Documento {i+1} ---")
    print(doc.page_content[:200])
    print(f"Metadados: {doc.metadata}")

# Busca com score de similaridade
docs_com_score = vectorstore_faiss.similarity_search_with_score(
    query,
    k=4
)

for doc, score in docs_com_score:
    print(f"Score: {score:.4f} | {doc.page_content[:100]}...")

Passo 6: Geração com Contexto

from langchain.chains import RetrievalQA
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="gpt-4", temperature=0)

# Criar chain RAG completa
qa_chain = RetrievalQA.from_chain_type(
    llm=llm,
    chain_type="stuff",  # Como combinar documentos
    retriever=vectorstore_faiss.as_retriever(search_kwargs={"k": 3}),
    return_source_documents=True,  # Retornar fontes
    verbose=True
)

# Fazer pergunta
pergunta = "Qual é o período de garantia do produto X?"
resultado = qa_chain.invoke({"query": pergunta})

print(f"Pergunta: {pergunta}")
print(f"\nResposta: {resultado['result']}")
print(f"\nFontes utilizadas:")
for doc in resultado['source_documents']:
    print(f"- {doc.metadata['source']}, página {doc.metadata.get('page', 'N/A')}")
Chain Types explicados:
1. "stuff" - Coloca tudo em um prompt (melhor para poucos docs)
2. "map_reduce" - Processa docs em paralelo, depois combina
3. "refine" - Processa docs sequencialmente, refinando resposta
4. "map_rerank" - Pontua cada doc, escolhe melhor resposta

RAG Conversacional (com memória)

from langchain.chains import ConversationalRetrievalChain
from langchain.memory import ConversationBufferMemory

# Criar memória
memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True,
    output_key="answer"
)

# Chain conversacional
conversational_chain = ConversationalRetrievalChain.from_llm(
    llm=llm,
    retriever=vectorstore_faiss.as_retriever(),
    memory=memory,
    return_source_documents=True
)

# Conversa multi-turn
perguntas = [
    "Qual é a garantia do produto?",
    "E se eu quiser estender ela?",  # Usa contexto anterior
    "Quanto custa?"  # Ainda referencia "garantia estendida"
]

for pergunta in perguntas:
    resultado = conversational_chain.invoke({"question": pergunta})
    print(f"\nQ: {pergunta}")
    print(f"A: {resultado['answer']}")

Capítulo 3.4: Agentes LangChain - Inteligência Autônoma

Do Scripted ao Autônomo

Chains são como seguir uma receita:

Agents são como ter um chef que decide:

O Padrão ReAct (Reason + Act)

┌─────────────────────────────────────────────┐ │ CICLO DO AGENTE REACT │ └─────────────────────────────────────────────┘ 1. THOUGHT (Pensamento) "Preciso saber o clima atual em São Paulo" ↓ 2. ACTION (Ação) Tool: weather_api ↓ 3. ACTION INPUT (Entrada) Input: "São Paulo, Brasil" ↓ 4. OBSERVATION (Observação) Result: "25°C, ensolarado" ↓ 5. THOUGHT (Pensamento) "Agora tenho a informação, posso responder" ↓ 6. FINAL ANSWER (Resposta Final) "O clima em São Paulo está 25°C e ensolarado"

Criando Seu Primeiro Agente

Passo 1: Definir Tools

from langchain.tools import Tool
from langchain_community.utilities import WikipediaAPIWrapper
import requests

# Tool 1: Wikipedia
wikipedia = WikipediaAPIWrapper()
tool_wikipedia = Tool(
    name="Wikipedia",
    func=wikipedia.run,
    description="""
    Útil para buscar informações factuais sobre pessoas, lugares,
    eventos históricos, etc. Input deve ser uma pergunta ou termo
    de busca em português.
    """
)

# Tool 2: Calculadora
def calculadora(expression: str) -> str:
    """Avalia expressões matemáticas"""
    try:
        return str(eval(expression))
    except Exception as e:
        return f"Erro: {str(e)}"

tool_calc = Tool(
    name="Calculadora",
    func=calculadora,
    description="""
    Útil para fazer cálculos matemáticos. Input deve ser uma
    expressão matemática válida em Python (ex: '2 + 2', '10 ** 3').
    """
)

# Tool 3: Busca na Web (exemplo com DuckDuckGo)
from langchain_community.tools import DuckDuckGoSearchRun

search = DuckDuckGoSearchRun()
tool_search = Tool(
    name="WebSearch",
    func=search.run,
    description="""
    Útil para buscar informações atualizadas na internet.
    Use quando precisar de notícias recentes, dados atuais,
    ou informações que não estão na Wikipedia.
    """
)

tools = [tool_wikipedia, tool_calc, tool_search]

Passo 2: Criar o Agente

from langchain.agents import create_react_agent, AgentExecutor
from langchain_openai import ChatOpenAI
from langchain.prompts import PromptTemplate

llm = ChatOpenAI(model="gpt-4", temperature=0)

# Prompt do agente ReAct
react_prompt = PromptTemplate.from_template("""
Responda à seguinte pergunta o melhor que puder. Você tem acesso às seguintes ferramentas:

{tools}

Use o seguinte formato:

Question: a pergunta de entrada que você deve responder
Thought: você deve sempre pensar sobre o que fazer
Action: a ação a tomar, deve ser uma de [{tool_names}]
Action Input: a entrada para a ação
Observation: o resultado da ação
... (este Thought/Action/Action Input/Observation pode se repetir N vezes)
Thought: Agora eu sei a resposta final
Final Answer: a resposta final para a pergunta original

Comece!

Question: {input}
Thought: {agent_scratchpad}
""")

# Criar agente
agent = create_react_agent(
    llm=llm,
    tools=tools,
    prompt=react_prompt
)

# Executor (gerencia execução)
agent_executor = AgentExecutor(
    agent=agent,
    tools=tools,
    verbose=True,  # Mostra raciocínio
    max_iterations=10,  # Limite de segurança
    handle_parsing_errors=True
)

Passo 3: Executar o Agente

# Teste 1: Requer Wikipedia
resposta1 = agent_executor.invoke({
    "input": "Quem foi Albert Einstein e em que ano nasceu?"
})
print(resposta1['output'])

# Teste 2: Requer Calculadora
resposta2 = agent_executor.invoke({
    "input": "Qual é a raiz quadrada de 12345?"
})
print(resposta2['output'])

# Teste 3: Requer múltiplas tools
resposta3 = agent_executor.invoke({
    "input": """
    O PIB do Brasil em 2023 foi de 10.9 trilhões de reais.
    Se dividirmos isso pela população de 215 milhões,
    quanto é o PIB per capita em reais?
    """
})
print(resposta3['output'])
# Agente vai: buscar confirmação do PIB → calcular divisão → responder
Exemplo de saída (verbose=True):
> Entering new AgentExecutor chain...

Question: Qual é a raiz quadrada de 12345?

Thought: Preciso calcular a raiz quadrada de um número.
Action: Calculadora
Action Input: 12345 ** 0.5
Observation: 111.1081249402829

Thought: Agora eu sei a resposta final.
Final Answer: A raiz quadrada de 12345 é aproximadamente 111.11.

> Finished chain.

Tipos de Agentes no LangChain

1. Zero-Shot ReAct Agent

from langchain.agents import create_react_agent

# Decide ferramentas baseado apenas em descrições
agent_zero_shot = create_react_agent(
    llm=llm,
    tools=tools,
    prompt=react_prompt
)

2. Conversational Agent (com memória)

from langchain.agents import create_conversational_agent
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True
)

conversational_agent = create_conversational_agent(
    llm=llm,
    tools=tools,
    memory=memory,
    verbose=True
)

# Agora mantém contexto entre perguntas
executor = AgentExecutor(agent=conversational_agent, tools=tools)

executor.invoke({"input": "Pesquise sobre Python"})
executor.invoke({"input": "E quanto a performance?"})  # Lembra que é sobre Python

3. OpenAI Functions Agent

from langchain.agents import create_openai_functions_agent

# Usa function calling nativo do GPT-4
functions_agent = create_openai_functions_agent(
    llm=llm,
    tools=tools,
    prompt=react_prompt
)

# Mais confiável e menos propenso a erros de parsing

Criando Tools Customizadas

Tool Simples (função)

@tool
def consultar_estoque(produto: str) -> str:
    """
    Consulta estoque de um produto no sistema.
    Args:
        produto: Nome do produto a consultar
    """
    # Simular consulta ao banco
    estoque_db = {
        "notebook": 15,
        "mouse": 50,
        "teclado": 30
    }
    quantidade = estoque_db.get(produto.lower(), 0)
    return f"Estoque de {produto}: {quantidade} unidades"

tools.append(consultar_estoque)

Tool com API Externa

from langchain.tools import tool
import requests

@tool
def buscar_cep(cep: str) -> str:
    """
    Busca endereço a partir do CEP brasileiro.
    Args:
        cep: CEP no formato 12345-678 ou 12345678
    """
    cep_limpo = cep.replace("-", "")
    response = requests.get(f"https://viacep.com.br/ws/{cep_limpo}/json/")

    if response.status_code == 200:
        data = response.json()
        if "erro" not in data:
            return f"""
            Endereço:
            {data['logradouro']}, {data['bairro']}
            {data['localidade']} - {data['uf']}
            """
    return "CEP não encontrado"

Capítulo 3.5: Memory - Dando Memória aos Agentes

Por Que Memória é Crucial

LLMs são stateless por padrão - cada chamada é independente. Memória permite:

Tipos de Memory no LangChain

1. ConversationBufferMemory (Memória Completa)

from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory()

# Salvar interações
memory.save_context(
    {"input": "Olá! Meu nome é Ana"},
    {"output": "Olá Ana! Como posso ajudar?"}
)

memory.save_context(
    {"input": "Preciso de ajuda com Python"},
    {"output": "Claro! Qual sua dúvida sobre Python?"}
)

# Recuperar histórico completo
print(memory.load_memory_variables({}))
Saída:
{
  'history': 'Human: Olá! Meu nome é Ana\nAI: Olá Ana! Como posso ajudar?\nHuman: Preciso de ajuda com Python\nAI: Claro! Qual sua dúvida sobre Python?'
}

Usar com Chain:

from langchain.chains import ConversationChain

conversation = ConversationChain(
    llm=llm,
    memory=ConversationBufferMemory(),
    verbose=True
)

conversation.predict(input="Oi, sou João")
conversation.predict(input="Qual é meu nome?")  # Vai lembrar: João

2. ConversationBufferWindowMemory (Janela Deslizante)

from langchain.memory import ConversationBufferWindowMemory

# Mantém apenas últimas K interações
memory_window = ConversationBufferWindowMemory(k=3)

# Depois de 10 interações, só lembra as 3 últimas

Quando usar:

3. ConversationSummaryMemory (Resumo Inteligente)

from langchain.memory import ConversationSummaryMemory

# Resume conversas longas
memory_summary = ConversationSummaryMemory(llm=llm)

memory_summary.save_context(
    {"input": "Quero comprar um notebook para programação"},
    {"output": "Recomendo um com pelo menos 16GB RAM e SSD"}
)

memory_summary.save_context(
    {"input": "Qual processador você recomenda?"},
    {"output": "Intel i7 ou AMD Ryzen 7 são ótimas opções"}
)

# Em vez de guardar tudo, cria resumo
print(memory_summary.load_memory_variables({}))
Saída:
{
  'history': 'O usuário está interessado em comprar um notebook para programação. Recomendei especificações mínimas de 16GB RAM, SSD, e processadores Intel i7 ou AMD Ryzen 7.'
}

4. ConversationSummaryBufferMemory (Híbrido)

from langchain.memory import ConversationSummaryBufferMemory

# Resume antigas, mantém recentes completas
memory_hybrid = ConversationSummaryBufferMemory(
    llm=llm,
    max_token_limit=500  # Limite antes de resumir
)

5. ConversationKGMemory (Knowledge Graph)

from langchain.memory import ConversationKGMemory

# Extrai relações entre entidades
memory_kg = ConversationKGMemory(llm=llm)

memory_kg.save_context(
    {"input": "João mora em São Paulo"},
    {"output": "Entendi"}
)

memory_kg.save_context(
    {"input": "Ele trabalha na Google"},
    {"output": "Anotado"}
)

# Cria grafo: João --mora_em--> São Paulo
#             João --trabalha_em--> Google

Memory Persistente (Banco de Dados)

from langchain.memory import ConversationBufferMemory
from langchain.memory.chat_message_histories import RedisChatMessageHistory

# Salvar em Redis
message_history = RedisChatMessageHistory(
    url="redis://localhost:6379/0",
    session_id="user_123"
)

memory_redis = ConversationBufferMemory(
    chat_memory=message_history
)

# Ou SQLite
from langchain.memory.chat_message_histories import SQLChatMessageHistory

sql_history = SQLChatMessageHistory(
    session_id="user_123",
    connection_string="sqlite:///chat_history.db"
)

memory_sql = ConversationBufferMemory(chat_memory=sql_history)

Memory com Agentes

from langchain.agents import initialize_agent, AgentType
from langchain.memory import ConversationBufferMemory

memory = ConversationBufferMemory(
    memory_key="chat_history",
    return_messages=True
)

agent_with_memory = initialize_agent(
    tools=tools,
    llm=llm,
    agent=AgentType.CONVERSATIONAL_REACT_DESCRIPTION,
    memory=memory,
    verbose=True
)

# Conversa com contexto
agent_with_memory.invoke({"input": "Meu nome é Carlos e gosto de futebol"})
agent_with_memory.invoke({"input": "Qual meu esporte favorito?"})  # Lembra!
agent_with_memory.invoke({"input": "E meu nome?"})  # Também lembra!

Capítulo 3.6: Integrações e Ecosystem

Document Loaders (60+ tipos)

# PDFs
from langchain_community.document_loaders import PyPDFLoader, PDFMinerLoader

# Web
from langchain_community.document_loaders import WebBaseLoader, SeleniumURLLoader

# Office
from langchain_community.document_loaders import UnstructuredWordDocumentLoader, UnstructuredExcelLoader

# Código
from langchain_community.document_loaders import GitLoader, NotebookLoader

# Databases
from langchain_community.document_loaders import DataFrameLoader, SQLDatabaseLoader

# APIs
from langchain_community.document_loaders import GoogleDriveLoader, NotionDBLoader

Vector Stores (50+ opções)

# Local
from langchain_community.vectorstores import FAISS, Chroma, DocArrayInMemorySearch

# Cloud
from langchain_community.vectorstores import Pinecone, Weaviate, Qdrant

# Databases
from langchain_community.vectorstores import PGVector, Redis, ElasticsearchStore

LLM Providers

# Proprietários
from langchain_openai import ChatOpenAI, OpenAI
from langchain_anthropic import ChatAnthropic
from langchain_google_genai import ChatGoogleGenerativeAI

# Open-source
from langchain_community.llms import Ollama, HuggingFaceHub, LlamaCpp

# Self-hosted
from langchain_community.llms import HuggingFacePipeline

📝 Resumo Gráfico do Módulo 3

Conceitos-Chave

LangChain = Framework de Orquestração

6 Pilares:

  1. Models (LLMs)
  2. Prompts (Templates)
  3. Chains (Pipelines)
  4. Agents (Autonomia)
  5. Memory (Contexto)
  6. Tools (Conexões externas)

RAG (Retrieval-Augmented Generation):

Agents:

🚀 Projeto Prático do Módulo 3

Desafio: ChatPDF Completo com Interface Web

Objetivo: Construir uma aplicação completa de RAG que permite:

  1. Upload de múltiplos PDFs
  2. Processamento e indexação automática
  3. Chat conversacional com memória
  4. Citação de fontes
  5. Interface web intuitiva

Especificações Técnicas

Stack:

📁 Código completo disponível:
Veja o arquivo completo do projeto ChatPDF (200+ linhas) no conteúdo markdown do módulo, incluindo:
• Interface Streamlit completa
• Sistema de upload e processamento de PDFs
• RAG conversacional com memória
• Citação de fontes com metadados
• requirements.txt e instruções de setup

Como Executar

# 1. Criar ambiente virtual
python -m venv venv
source venv/bin/activate  # Linux/Mac
# ou
venv\Scripts\activate  # Windows

# 2. Instalar dependências
pip install -r requirements.txt

# 3. Executar aplicação
streamlit run chatpdf_app.py

💡 Dicas de Otimização e Debugging

1. Debugging de Chains

# Ativar verbose
chain = LLMChain(llm=llm, prompt=prompt, verbose=True)

# Callbacks customizados
from langchain.callbacks import StdOutCallbackHandler

handler = StdOutCallbackHandler()
chain.run(input="...", callbacks=[handler])

# LangSmith (plataforma oficial)
import os
os.environ["LANGCHAIN_TRACING_V2"] = "true"
os.environ["LANGCHAIN_API_KEY"] = "..."

2. Otimizando RAG

# Cache de embeddings
from langchain.embeddings import CacheBackedEmbeddings
from langchain.storage import LocalFileStore

store = LocalFileStore("./cache/")
cached_embeddings = CacheBackedEmbeddings.from_bytes_store(
    underlying_embeddings,
    store,
    namespace="openai_embeddings"
)

# Compressão de contexto
from langchain.retrievers import ContextualCompressionRetriever
from langchain.retrievers.document_compressors import LLMChainExtractor

compressor = LLMChainExtractor.from_llm(llm)
compression_retriever = ContextualCompressionRetriever(
    base_compressor=compressor,
    base_retriever=retriever
)

3. Gerenciamento de Custos

from langchain.callbacks import get_openai_callback

with get_openai_callback() as cb:
    result = chain.run(input="...")
    print(f"Tokens: {cb.total_tokens}")
    print(f"Custo: ${cb.total_cost}")

🎯 Próximos Passos

Você dominou LangChain! Agora sabe como:

No Módulo 4, exploraremos o Agno, um framework mais recente e minimalista que oferece uma perspectiva diferente sobre a construção de agentes autônomos, focando na simplicidade e elegância.