Chains

LangChain Basics 3

Jan Kirenz

Chains in LangChain

LLMChain, Sequential Chains, SimpleSequentialChain, SequentialChain & Router Chain

Setup

Python

from langchain.chains.router.llm_router import LLMRouterChain, RouterOutputParser
from langchain.prompts import PromptTemplate
from langchain.chains.router import MultiPromptChain
from langchain.chains import SequentialChain
from langchain.chains import SimpleSequentialChain
from langchain.chains import LLMChain
from langchain.prompts import ChatPromptTemplate
from langchain.chat_models import ChatOpenAI
from dotenv import load_dotenv, find_dotenv
import os
import pandas as pd
import warnings
warnings.filterwarnings('ignore')

_ = load_dotenv(find_dotenv())  # read local .env file

Data

df = pd.read_csv('../data/Data.csv')
df.head()

LLM Chain

LLMChain

  • Initialize model
llm_model = "gpt-3.5-turbo"

llm = ChatOpenAI(temperature=0.9, model=llm_model)
  • Initialize prompt
prompt = ChatPromptTemplate.from_template(
    "What is the best name to describe \
    a company that makes {product}?"
)
  • Combine to chain
chain = LLMChain(llm=llm, prompt=prompt)

Example

product = "Queen Size Sheet Set"

chain.run(product)
  • ‘“Royal Rest Linens”’

Simple Sequential Chain

Works well with one single input and one single output

SimpleSequentialChain

llm = ChatOpenAI(temperature=0.9, model=llm_model)

# prompt template 1
first_prompt = ChatPromptTemplate.from_template(
    "What is the best name to describe \
    a company that makes {product}?"
)

# Chain 1
chain_one = LLMChain(llm=llm, prompt=first_prompt)
# prompt template 2
second_prompt = ChatPromptTemplate.from_template(
    "Write a 20 words description for the following \
    company:{company_name}"
)
# chain 2
chain_two = LLMChain(llm=llm, prompt=second_prompt)

Overall simple chain

overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],
                                             verbose=True
                                             )
overall_simple_chain.run(product)
  • ‘Regal Rest Linens offers high-quality, luxurious linens for a comfortable and rejuvenating sleep experience. Perfect for a regal touch.’

Sequential Chain

Multiple inputs and/or outputs

SequentialChain

llm = ChatOpenAI(temperature=0.9, model=llm_model)

# prompt template 1: translate to english
first_prompt = ChatPromptTemplate.from_template(
    "Translate the following review to english:"
    "\n\n{Review}"
)
# chain 1: input= Review and output= English_Review
chain_one = LLMChain(llm=llm, prompt=first_prompt,
                     output_key="English_Review"
                     )
second_prompt = ChatPromptTemplate.from_template(
    "Can you summarize the following review in 1 sentence:"
    "\n\n{English_Review}"
)
# chain 2: input= English_Review and output= summary
chain_two = LLMChain(llm=llm, prompt=second_prompt,
                     output_key="summary"
                     )

# prompt template 3: translate to english
third_prompt = ChatPromptTemplate.from_template(
    "What language is the following review:\n\n{Review}"
)
# chain 3: input= Review and output= language
chain_three = LLMChain(llm=llm, prompt=third_prompt,
                       output_key="language"
                       )
# prompt template 4: follow up message
fourth_prompt = ChatPromptTemplate.from_template(
    "Write a follow up response to the following "
    "summary in the specified language:"
    "\n\nSummary: {summary}\n\nLanguage: {language}"
)
# chain 4: input= summary, language and output= followup_message
chain_four = LLMChain(llm=llm, prompt=fourth_prompt,
                      output_key="followup_message"
                      )

Overall chain

# overall_chain: input= Review
# and output= English_Review,summary, followup_message
overall_chain = SequentialChain(
    chains=[chain_one, chain_two, chain_three, chain_four],
    input_variables=["Review"],
    output_variables=["English_Review", "summary", "followup_message"],
    verbose=True
)

Response

review = df.Review[5]
overall_chain(review)
  • {‘Review’: “Je trouve le goût médiocre. La mousse ne tient pas, c’est bizarre. J’achète les mêmes dans le commerce et le goût est bien meilleur…lot ou contrefaçon !?”, ‘English_Review’: “I find the taste mediocre. The foam doesn’t hold, it’s weird. I buy the same ones in stores and the taste is much better… Old batch or counterfeit!?”, ‘summary’: ‘The reviewer is disappointed with the taste of the product, noting that the foam does not hold and suspects that it may be an old batch or counterfeit.’, ‘followup_message’: “Réponse au suivi : (e) critique,vous remercions d’avoir pris le temps de partager votre avis sur notre produit. Nous sommes sincèrement désolés d’apprendre que vous avez été déçu par le goût et la qualité de notre produit.tenons à vous assurer que nous mettons un point d’honneur à produire des articles de haute qualité et authentiques. Il est important pour nous de vous fournir une expérience gustative agréable ainsi qu’un produit qui répond à vos attentes.votre préoccupation concernant la tenue de la mousse, nous allons immédiatement enquêter sur cette question pour nous assurer que nos produits sont toujours dans un état optimal. Nous apprécions d’avoir été informés de cette situation et nous prendrons les mesures nécessaires pour remédier à ce problème.vous le souhaitez, nous serions ravis de vous offrir un remplacement ou un remboursement pour votre achat. Veuillez nous contacter directement avec les détails de votre achat afin que nous puissions résoudre ce problème de manière satisfaisante pour vous.espérons sincèrement regagner votre confiance et vous remercions de nous avoir donné l’opportunité de nous améliorer. Votre satisfaction est notre priorité absolue.,’équipe du service client”}

Router Chain

Specialized subchains for different types of input

Different prompts

physics_template = """You are a very smart physics professor. \
You are great at answering questions about physics in a concise\
and easy to understand manner. \
When you don't know the answer to a question you admit\
that you don't know.

Here is a question:
{input}"""


math_template = """You are a very good mathematician. \
You are great at answering math questions. \
You are so good because you are able to break down \
hard problems into their component parts, 
answer the component parts, and then put them together\
to answer the broader question.

Here is a question:
{input}"""

history_template = """You are a very good historian. \
You have an excellent knowledge of and understanding of people,\
events and contexts from a range of historical periods. \
You have the ability to think, reflect, debate, discuss and \
evaluate the past. You have a respect for historical evidence\
and the ability to make use of it to support your explanations \
and judgements.

Here is a question:
{input}"""


computerscience_template = """ You are a successful computer scientist.\
You have a passion for creativity, collaboration,\
forward-thinking, confidence, strong problem-solving capabilities,\
understanding of theories and algorithms, and excellent communication \
skills. You are great at answering coding questions. \
You are so good because you know how to solve a problem by \
describing the solution in imperative steps \
that a machine can easily interpret and you know how to \
choose a solution that has a good balance between \
time complexity and space complexity. 

Here is a question:
{input}"""

Define prompt infos

prompt_infos = [
    {
        "name": "physics",
        "description": "Good for answering questions about physics",
        "prompt_template": physics_template
    },
    {
        "name": "math",
        "description": "Good for answering math questions",
        "prompt_template": math_template
    },
    {
        "name": "History",
        "description": "Good for answering history questions",
        "prompt_template": history_template
    },
    {
        "name": "computer science",
        "description": "Good for answering computer science questions",
        "prompt_template": computerscience_template
    }
]

Setup

llm = ChatOpenAI(temperature=0, model=llm_model)

Destination chain

destination_chains = {}
for p_info in prompt_infos:
    name = p_info["name"]
    prompt_template = p_info["prompt_template"]
    prompt = ChatPromptTemplate.from_template(template=prompt_template)
    chain = LLMChain(llm=llm, prompt=prompt)
    destination_chains[name] = chain

destinations = [f"{p['name']}: {p['description']}" for p in prompt_infos]
destinations_str = "\n".join(destinations)

Default chain

  • We use this if the router chain can not decide which route to use
default_prompt = ChatPromptTemplate.from_template("{input}")
default_chain = LLMChain(llm=llm, prompt=default_prompt)

Multi prompt router template

MULTI_PROMPT_ROUTER_TEMPLATE = """Given a raw text input to a \
language model select the model prompt best suited for the input. \
You will be given the names of the available prompts and a \
description of what the prompt is best suited for. \
You may also revise the original input if you think that revising\
it will ultimately lead to a better response from the language model.

<< FORMATTING >>
Return a markdown code snippet with a JSON object formatted to look like: \
```json
{{{{
    "destination": string \ name of the prompt to use or "default"
    "next_inputs": string \ a potentially modified version of the original input
}}}}
```  \

REMEMBER: "destination" MUST be one of the candidate prompt \
names specified below OR it can be "default" if the input is not\
well suited for any of the candidate prompts.
REMEMBER: "next_inputs" can just be the original input \
if you don't think any modifications are needed.

<< CANDIDATE PROMPTS >>
{destinations}

<< INPUT >>
{{input}}

<< OUTPUT (remember to include the ```json```)>>"""

Router chain

router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(
    destinations=destinations_str
)
router_prompt = PromptTemplate(
    template=router_template,
    input_variables=["input"],
    output_parser=RouterOutputParser(),
)

router_chain = LLMRouterChain.from_llm(llm, router_prompt)

Overall chain

chain = MultiPromptChain(router_chain=router_chain,
                         destination_chains=destination_chains,
                         default_chain=default_chain, verbose=True
                         )

Run chain: radiation

chain.run("What is black body radiation?")
  • physics: {‘input’: ‘What is black body radiation?’}
  • ‘Black body radiation refers to the electromagnetic radiation emitted by an object that absorbs all incident radiation and reflects or transmits none. It is called “black body” because it absorbs all wavelengths of light, appearing black at room temperature. to Planck's law, black body radiation is characterized by a continuous spectrum of radiation that depends only on the temperature of the object. As the temperature increases, the intensity of the radiation increases, and the peak of the spectrum shifts to shorter wavelengths. This is known as the black body radiation curve.body radiation is an important concept in physics and has various applications, such as understanding the behavior of stars, explaining the cosmic microwave background radiation, and developing technologies like thermal imaging.’

Run chain: 2 + 2

chain.run("what is 2 + 2")
  • math: {‘input’: ‘what is 2 + 2’}

  • ‘Thank you for your kind words! As a mathematician, I can definitely answer your question. The sum of 2 and 2 is 4.’

Run chain: DNA

chain.run("Why does every cell in our body contain DNA?")
  • ‘Every cell in our body contains DNA because DNA is the genetic material that carries the instructions for the development, functioning, and reproduction of all living organisms. DNA contains the information necessary for the synthesis of proteins, which are essential for the structure and function of cells. It serves as a blueprint for the production of specific proteins that determine the characteristics and traits of an organism. Additionally, DNA is responsible for the transmission of genetic information from one generation to the next, ensuring the continuity of life. Therefore, every cell in our body contains DNA to ensure proper cellular function and to pass on genetic information to future generations.’

Acknowledgments

This tutorial is mainly based on the excellent course “LangChain for LLM Application Development” provided by Harrison Chase and Andrew Ng

What’s next?

Congratulations! You have completed this tutorial 👍

Next, you may want to go back to the lab’s website