LangChain: LLMs with Models, Prompts, Parsers
Tags: ai, machinelearning, chatgpt, langchain
Published: 2024-05-04 02:54:13

We'll explore the inner workings of LangChain, a useful Python library that streamlines the process of working with LLMs. You'll be able to create intuitive, reusable, and scalable applications that can change how you interact with LLMs.

## Large Language Models

Large language models (LLM) are very large deep learning models that are pre-trained on vast amounts of data. The underlying transformer is a set of neural networks that consist of an encoder and a decoder with self-attention capabilities., enabling it to understand and generate human-like text. These models serve as the foundation upon which our applications are built. One such model that has taken the world by storm is GPT-3.5-turbo, a LLM developed by OpenAI.

The `ChatOpenAI` class acts as a convenient abstraction, allowing you to interact with the GPT-3.5-turbo model through the OpenAI API.

```python
from langchain_openai import ChatOpenAI

# Create a ChatOpenAI instance
chat = ChatOpenAI(temperature=0.0, model="gpt-3.5-turbo")
```

By setting the `temperature` parameter to `0.0`, we instruct the model to generate deterministic outputs, ensuring consistency across multiple runs. This is particularly useful when building applications that require reliable and repeatable results.

## Prompts

While models provide the underlying intelligence, prompts act as the conductor, guiding the language model to perform specific tasks or generate desired outputs. Prompts are essentially the instructions that we provide to the model, shaping its behavior and tailoring its responses to our needs.

LangChain introduces the concept of `ChatPromptTemplate`, an abstraction that simplifies the process of creating and managing prompts. With this tool, you can define reusable templates that can be easily shared and adapted across your application.

```python
from langchain.prompts import ChatPromptTemplate

template_string = """Translate the text that is delimited by double quotes into a style that is {style}. text: ''{text}''"""

prompt_template = ChatPromptTemplate.from_template(template_string)

print(prompt_template.messages[0].prompt)

# Output
PromptTemplate(input_variables=['style', 'text'], template='Translate the text that is delimited by triple quotes into a style that is {style}. text: """{text}"""\n')
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1714790213864/a2114755-bb43-4ca9-8df1-fde5c338f281.png align="center")

In the example above, we define a prompt template that instructs the language model to translate a given text into a specified style. By using prompts, we can perform a wide range of tasks, from language translation to content generation, and even complex analytical tasks.

But what if you need to interact with the language model in a more dynamic and personalized manner? With the ability to format messages using the `prompt_template.format_messages` method, you can easily use user inputs, contextual information, or any other relevant data into your prompts, ensuring that your interactions with the language model are tailored to each unique scenario.

```python
customer_style = "American English in a calm and respectful tone"
customer_email = "Arrr, I be fuming that me blender lid flew off and splattered me kitchen walls with smoothie! ..."

# Call the LLM to translate to the style of the customer message
customer_messages = prompt_template.format_messages(style=customer_style, text=customer_email)
customer_response = chat.invoke(customer_messages)
print(customer_response.content)

# Output
I am really frustrated that my blender lid flew off and splattered my kitchen walls with smoothie! And to make matters worse, the warranty doesn't cover the cost of cleaning up my kitchen. I could really use your help right now, friend.
```

By providing the desired style and customer email as input, we can generate a prompt that instructs the language model to translate the customer's message from "pirate speak" into a polite, easy-to-understand format. This simple yet powerful example showcases the versatility of LangChain's prompt system, enabling you to create dynamic and context-aware interactions with language models.

## Output Parsers

While prompts guide the language model's input, output parsers play a crucial role in interpreting and structuring its responses. These parsers transform the raw text generated by the language model into a structured format that can be easily consumed and processed by your application.

Imagine you're building an e-commerce application that relies on customer reviews to provide insights. With LangChain's `ResponseSchema` and `StructuredOutputParser`, you can define the expected output format for your language model and extract relevant information from customer reviews.

```python
from langchain.output_parsers import ResponseSchema, StructuredOutputParser

# Define the expected output schema
gift_schema = ResponseSchema(name="gift", description="Was the item purchased as a gift?")
delivery_days_schema = ResponseSchema(name="delivery_days", description="How many days did it take for the product to arrive?")
price_value_schema = ResponseSchema(name="price_value", description="Extract any sentences about the value or price.")

response_schemas = [gift_schema, delivery_days_schema, price_value_schema]

# Create the output parser
output_parser = StructuredOutputParser.from_response_schemas(response_schemas)
format_instructions = output_parser.get_format_instructions()
print(format_instructions)

# Output 
The output should be a markdown code snippet formatted in the following schema, 
{
	"gift": string  // Was the item purchased as a gift for someone else? Answer True if yes, False if not or unknown.
	"delivery_days": string  // How many days did it take for the product to arrive? If this information is not found, output -1.
	"price_value": string  // Extract any sentences about the value or price, and output them as a comma separated Python list.
}
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1714790231151/018f42bc-1df4-4d06-9499-bc7d9fc99b1c.png align="center")

By defining the desired output schema, LangChain generates format instructions that guide the language model to generate its output in a specific format. This structured output can then be easily parsed into a Python dictionary using the `output_parser.parse` method, allowing you to extract information such as whether the item was a gift, the delivery time, and any comments about the product's value or price.

```python
review_template_2 = """\
For the following text, extract the following information:

gift: Was the item purchased as a gift for someone else? \
Answer True if yes, False if not or unknown.

delivery_days: How many days did it take for the product\
to arrive? If this information is not found, output -1.

price_value: Extract any sentences about the value or price,\
and output them as a comma separated Python list.

text: {text}

{format_instructions}
"""

prompt = ChatPromptTemplate.from_template(template=review_template_2)

messages = prompt.format_messages(
    text=customer_review, format_instructions=format_instructions
)

response = chat.invoke(messages)
print(response.content)

# Output
{
	"gift": "True",
	"delivery_days": "2",
	"price_value": "It's slightly more expensive than the other leaf blowers out there, but I think it's worth it for the extra features."
}

output_dict = output_parser.parse(response_content)
print(output_dict["gift"])  # Output: True
print(output_dict["delivery_days"])  # Output: 2
print(output_dict["price_value"])  # Output: "It's slightly more expensive than other leaf blowers, but worth it for the extra features."
```

With the structured output in hand, you can easily integrate the extracted information into your application, enabling you to provide personalized recommendations, perform data analysis, or enhance the overall user experience.

## Key Advantages of LangChain's Models, Prompts, and Output Parsers

By using LangChain's abstractions for models, prompts, and output parsers, you can gain several key advantages:

1. **Reusability**: Instead of recreating prompts and parsers from scratch for each new task, LangChain allows you to define reusable components that can be shared across your application or even with other developers in your team or community.
    
2. **Consistency**: By centralizing your prompts and output formats, you ensure a consistent and predictable experience for your users, regardless of the task or the language model being used.
    
3. **Scalability**: As your application grows and evolves, LangChain's modular approach makes it easier to adapt to changing requirements, incorporate new language models, or integrate with other data sources or APIs.
    
4. **Built-in Libraries**: LangChain provides a rich library of pre-built prompts and parsers for common tasks like summarization, question answering, and database interactions, allowing you to kickstart your development process and focus on building unique features that set your application apart.
    
5. **Seamless Integration**: LangChain's abstractions facilitate a smooth interaction between your application, the language model, and the parsed outputs, enabling you to build end-to-end solutions that use the LLMs while maintaining a clean and maintainable codebase.
    

By embracing these key advantages, you can accelerate your development process, enhance the user experience

## Conclusion

In the fast moving world of machine learning and natural language processing, mastering large language models is a necessity. By using LangChain's models, prompts, and output parsers, you can unlock a world of possibilities and build sophisticated applications that seamlessly integrate language models into your workflows.

## Source Code

https://github.com/RutamBhagat/LangChainHCCourse1/blob/main/course_1/models_prompts_and_output_parsesrs.ipynb