Me siga no LinkedIn | Apoie a Newsletter | Curso: Converse com seus documentos
No centro do LangChain está um componente conhecido como Chain
, que cria a conexão central entre um ou vários grandes modelos de linguagem.
De maneira simplificada uma chain ajuda a pegar a saída de uma chamada à LLM e usá-la como entrada para um próximo passo (que pode inclusive ser uma outra chamada à LLM).
Imagine esta situação: uma chain é criada para receber a entrada do usuário, fazer algum refinamento e, posteriormente, passar essa resposta refinada para um modelo de linguagem. Dessa forma, torna-se possível conectar várias interações com a LLM.
Através da criação de chains, vários elementos podem se unir de maneira transparente.
Dessa forma, as chains nos proporcionam a capacidade de construir aplicativos complexos, ligando várias chains entre si ou incorporando chains com outros elementos do sistema. As chains são ponto-chave no desenvolvimento de software baseado em LLMs.
Vantagens de usar uma Chain.
Ao pegar a saída de um LLM e usá-la como entrada para o próximo, torna-se possível realizar várias interações com uma LLMs de maneira sequencial.
Misturar LLMs com dados externos permite que o sistema responda a consultas de maneira eficaz.
Há diferentes tipos de chains. Nesse texto, vamos passar por algumas das principais.
📚 Você é dev e quer aprender um pouco mais sobre a criação de aplicações baseadas em LLM?
Eu criei um curso que aborda aspectos teóricos e práticos do desenvolvimento de aplicações baseadas em LLMs. Alguns dos tópicos cobertos:
🟠 O que são e como criar embeddings
🟡 Como selecionar partes relevantes nos seus documentos
🔵 Como integrar essas partes documentos com uma LLM
Chain = prompt | model
A forma mais básica de chain é combinando (ou encadeando) um prompt e um modelo. Na newsletter já abordagens esse tipo mais básico de chain, utilizando o LangChain Expression Language.
Embora seja possível fazer alguns encadeamento de ações , nesse tipo de chain ficamos limitados quando queremos, por exemplo, encadear duas ou mais chamadas a LLM.
Sequencial Chain
Sequential Chain Uma Sequential Chain é uma chain que combina várias chains individuais, onde a saída de uma chain serve como entrada para a próxima em uma sequência contínua. Ela opera executando uma série de chains consecutivamente.
Existem dois tipos de Sequential Chains:
SimpleSequentialChain, que lida com uma única entrada e saída.
SequentialChain, que gerencia várias entradas e saídas simultaneamente.
SimpleSequentialChains
As SimpleSequentialChains permitem que uma única entrada passe por uma série de transformações, resultando em uma saída refinada.
Por exemplo, imagine que você quer fazer uma receita de cozinha, mas que gostaria de saber qual é o item mais importante da receita para que você possa comprar o melhor material possível no mercado.
Nesse caso, teríamos dois prompts: um para criar a receita e outro para identificar o item mais importante da receita. Além disso, o segundo prompt deve estar conectado com o primeiro, uma vez que não sabemos de antemão quais são os itens da receita.
Poderíamos implementar essa chain da seguinte forma:
from langchain_openai import ChatOpenAI
from langchain.chains.sequential import SimpleSequentialChain
model = ChatOpenAI()
# Primeiro prompt
prompt = ChatPromptTemplate.from_template(
"Crie uma lista de compras para fazer uma receita de: {receita}"
)
chain = LLMChain(llm=model, prompt=prompt)
# Segundo prompt
second_prompt = ChatPromptTemplate.from_template(
"Dentre dos itens de receita, descreva qual é o mais importante e o motivo: {list}"
)
second_chain = LLMChain(llm=model, prompt=second_prompt)
combined_chain = SimpleSequentialChain(chains=[chain, second_chain], verbose=True)
combined_chain.invoke({"input": "lasanha"})
Inicialmente, cria-se um prompt solicitando a criação de uma lista de compras para uma receita específica. Uma instância da classe LLMChain
é usada para processar esse prompt, utilizando um modelo predefinido.
Em seguida, é criado um segundo prompt, pedindo ao usuário que destaque o item mais importante da lista de compras e explique sua relevância. Outra instância da LLMChain
é criada para lidar com essa instrução.
Por fim, ambas as chains são combinadas em uma SimpleSequentialChain
, permitindo a execução sequencial das operações.
Ao invocar a cadeia combinada com o parâmetro "lasanha"
, o código faz uma execução sequencia das duas chain, na ordem que foram passadas por parâmetro..
SequentialChains
Similar a uma SimpleSequencialChain
, uma SequentialChain
pode combinar várias chains usando a saída de uma chain como entrada para a próxima. No entanto, diferente da SimpleSequencialChain
, uma SequentialChain
pode executar uma série de chains ao mesmo tempo, e o resultado dessas chains é passado para outras chains.
Por exemplo, imagine que você queria escrever sobre um tema específico da engenharia de software, mas com o estilo de escrita de um notável pesquisador da área. Dessa forma, podemos criar as seguintes chains:
Chain1: Buscar um renomado pesquisador em engenharia de software
Chain2: Escrever um texto sobre engenharia de software
Chain3: Identificar a área de conhecimento do pesquisador renomado
Chain4: Reescrever o texto, focando na área de conhecimento do pesquisador renomado
Note que as Chains1 e Chains2 do exemplo a cima são independentes uma da outra, logo podem se executadas em paralelo.
Poderíamos implementar essa chain da seguinte forma:
from langchain.chains import SequentialChain
first_prompt = ChatPromptTemplate.from_template(
"Cite o nome de um pesquisador brasileiro que escreve sobre a seguinte área do conhecimento:\n\n{topic}"
)
first_chain = LLMChain(llm=model, prompt=first_prompt,
output_key="writer"
)
second_prompt = ChatPromptTemplate.from_template(
"Escreva um resumo sobre o que se trata a área do conhecimento chamada:\n\n{topic}"
)
second_chain = LLMChain(llm=model, prompt=second_prompt,
output_key="summary"
)
third_prompt = ChatPromptTemplate.from_template(
"Descreva em até cinco palavras a princial área de atuacao do pesquisador {writer} na {topic}."
)
third_chain = LLMChain(llm=model, prompt=third_prompt,
output_key="research_topic"
)
fourth_prompt = ChatPromptTemplate.from_template(
"Reescreva o seguinte texto, focando na área de {software_topic}, no estilo de {writer}:\n\n{summary}"
)
fourth_chain = LLMChain(llm=model, prompt=fourth_prompt,
output_key="writer_summary"
)
main_chain = SequentialChain(
chains=[first_chain, second_chain, third_chain, fourth_chain],
input_variables=["topic"],
output_variables=["writer", "summary", "research_topic", "writer_summary"],
verbose=True
)
main_chain.invoke('''engenharia de software''')
Neste código, o primeiro prompt solicita o nome de um pesquisador brasileiro na área indicada, enquanto o segundo pede um resumo sobre essa área de conhecimento.
A terceira interação busca descrever a principal área de atuação do pesquisador na engenharia de software em até cinco palavras.
Por fim, o quarto prompt reescreve um texto focado na área específica do software, usando o estilo do pesquisador mencionado.
Perceba, no entanto, que as chains first_chain
e second_chain
são executadas de maneira independente, mas seu resultado é combinado e utilizado na fourth_chain.
Outras Chains
O LangChain oferece suporte para diversos outros tipos de chain. Citamos alguns exemplos a seguir.
RouterChains
A RouterChain
é utilizada para tarefas ligeiramente mais complicadas. Por exemplo, quando temos múltiplas chains, cada uma especializada em um tipo específico de input, podemos ter uma router chain que decide para qual chain enviar o input.
Imagine, por exemplo, que você é um estudante do ENEM, e precisa de um serviço de pergunta e respostas especializado em física, matemática e história.
Nesse serviço, dado uma pergunta do usuário sobre uma dessas disciplinas, o prompt correto deve ser escolhido e executado.
create_sql_query_chain
Essa é uma chain que gera consultas SQL, através da classe SQLDatabase
, que fornece um método get_table_info
que pode ser usado para obter informações sobre colunas, bem como dados de amostra da tabela.
Para mitigar o risco de vazamento de dados sensíveis, é importante limitar as permissões para leitura e ajuste para as tabelas necessárias.
Exemplo:
from langchain_openai import ChatOpenAI
from langchain.chains import create_sql_query_chain
from langchain_community.utilities import SQLDatabase
db = SQLDatabase.from_uri("sqlite:///Chinook.db")
llm = ChatOpenAI(model="gpt-3.5-turbo", temperature=0)
chain = create_sql_query_chain(llm, db)
response = chain.invoke({"question": "Quantos empregados existem?"})
Conclusão
O LangChain, por meio de suas chains, desempenha um papel crucial no desenvolvimento de aplicativos baseados em Large Language Models (LLMs). As chains, como Sequential Chains e Router Chains, permitem a construção de interações sequenciais e decisões dinâmicas, proporcionando flexibilidade e eficácia.
Ao unir diferentes elementos de maneira transparente, as chains possibilitam a criação de aplicativos complexos. Esse método, exemplificado com receitas de culinária e redação acadêmica, demonstra como as chains oferecem uma abordagem versátil e poderosa para a interação e manipulação de dados, ampliando as capacidades do desenvolvimento de software baseado em LLMs.