Wednesday, April 1, 2026

Type Casting in Java With Conversion Examples

Type casting in Java is used to cast one type (primitive or object) to another type. Whenever you try to assign data of one type to variable of another type, type conversion happens in Java.

Types of Type Conversion in Java

Type conversion in Java may be classified into following four scenarios.

Out of these four; widening primitive type conversions and widening reference type conversions happen automatically. No explicit type casting is required.

In the case of narrowing primitive type conversions and narrowing reference conversions explicit type casting is required because they may lead to data loss or runtime exceptions.

Widening primitive conversions

If destination type (type to which you are converting) is larger than the source type, you are widening the type of your source type. For example, converting an int to a long or a float to a double. This type conversion will happen with out problem and automatically i.e. type casting is not required in this case.

As example-

int i = 10;
float f = i; // Assigning int to float

i which is an int can safely be assigned to float variable as float is compatible with int and also wider than int.

Widening reference conversions

Same way you can have a widening reference conversion. That is applicable in an inheritance scenario where a parent-child relationship exists.

For example if there is a parent class A and a child class B that extends class A then reference type A can safely hold reference type of class B.

A a;
B b = new B();
a = b; // Widening conversion from sub type to super type

Type casting in Java

Though automatic conversion is convenient and helpful, it may not always be possible. Especially in case of narrowing conversions. Narrowing conversion can be of two types-

  • Narrowing primitive conversions
  • Narrowing reference conversions

Narrowing primitive conversions

As the name suggests if you try to fit a value into a source that is narrower than the original type of the value then it is a narrowing conversion.

As example– If we do the exact opposite of what we did in the example of widening conversion and try to assign a float value to an int.

int i;
float f = 19.6f;
i = f; // Compile-time error (Type mismatch: cannot convert from float to int)

As you see, you get a compile-time error if you try to assign a float value to an int as it is a narrowing conversion. In case of narrowing conversion you need to explicitly type cast it to make it work.

General form of type casting in Java

(type) value;

Here type is the type to which the value has to be converted.

So in the above example we have to add an explicit cast to int.

Java type casting example

int i;
float f = 19.6f;
i = (int)f;
System.out.println("value " + i); 

Output

value 19

Here you can see that the fractional part is truncated.

Narrowing reference conversions

A super type can hold reference to an object of itself or the sub-types. But doing the opposite, when you want a conversion from super-type to sub-type, you will need type casting.

Since the conversion is from super-type to sub-type it is called narrowing reference conversion.

One important thing to always remember is; an object can only be type cast to its own class or one of its super-type, if you try to cast to any other object you may either get a compile-time error or a class-cast exception (run-time).

Narrowing reference conversion example

If we take the same example as used in widening reference conversion where there is a class A and a child class B that extends class A then reference type A can safely hold reference type of class B. But now we’ll try the opposite too.

A a;
B b = new B()
a = b; // OK widening conversion
b = a; // Compile-time error as it is a narrowing conversion

What you need to do to avoid compile-time error is-

b = (B)a;

Why type casting in Java required

You may have a scenario where child class has methods of its own apart from inheriting methods from the super class or overriding methods of the super class.

As a good programmer, you often design code to achieve polymorphism, holding a subclass object in a superclass reference. This allows flexibility and reusability. However, the limitation is that you can only call methods defined in the superclass. Any methods exclusive to the subclass remain inaccessible.

In order to call those methods you need casting to the type. Let’s try to understand it with an example.

Type casting Java example code

Here I have a class hierarchy where Payment is an interface and there are two classes CashPayment and CardPayment implementing the Payment interface.

Payment interface

public interface Payment {
 public boolean proceessPayment(double amount);
}

CashPayment class

import org.netjs.examples.interfaces.Payment;

public class CashPayment implements Payment {
 @Override
 public boolean proceessPayment(double amount) {
  System.out.println("Cash payment done for Rs. " + amount);
  return true;
 }
}

CardPayment class

import org.netjs.examples.interfaces.Payment;

public class CardPayment implements Payment {

 @Override
 public boolean proceessPayment(double amount) {
  System.out.println("Card Payment done for Rs. " + amount);
  return true;
 }
 
 public void printSlip(){
  System.out.println("Printing slip for payment" );
 }
}

In CardPayment class, note that, there is an extra method printSlip() which is exclusive to this class. Now when you do some payments using the class as given below-

import org.netjs.examples.interfaces.Payment;

public class PaymentDemo {
 public static void main(String[] args) {
  PaymentDemo pd = new PaymentDemo();
  Payment payment = new CashPayment();
  pd.doPayment(payment, 100);
  payment = new CardPayment();
  pd.doPayment(payment, 300);
  //int i = 10;
  //float f = i;
  
  int i;
  float f = 19.6f;
  i = (int)f;
  System.out.println("value " + i);
 }
 
 public void doPayment(Payment pd, int amt){
  pd.proceessPayment(amt);
  pd.printSlip();
 }
}

This method call pd.printSlip(); gives following compile-time error as the Payment object has no idea of the printSlip() method, thus the error-

The method printSlip() is undefined for the type Payment

If you want to call printSlip() method you need a cast back to CardPayment class type. Beware that there are two child classes and you don’t need that casting for CashPayment class object. Which means you need to use instanceof operator in conjunction with the casting.

Refer instanceof Operator in Java to know more about instanceof operator in Java.

With these corrections the code will now look like-

import org.netjs.examples.interfaces.Payment;

public class PaymentDemo {

 public static void main(String[] args) {
  PaymentDemo pd = new PaymentDemo();
  Payment payment = new CashPayment();
  pd.doPayment(payment, 100);
  payment = new CardPayment();
  pd.doPayment(payment, 300);
  //int i = 10;
  //float f = i;
  
  int i;
  float f = 19.6f;
  i = (int)f;
  System.out.println("value " + i);
 }
 
 public void doPayment(Payment pd, int amt){
  pd.proceessPayment(amt);
  
  if (pd instanceof CardPayment){
   CardPayment cardPay = (CardPayment)pd;
   cardPay.printSlip();
  }
 }
}

Output

Cash payment done for Rs. 100.0
Card Payment done for Rs. 300.0
Printing slip for payment
value 19

Here you can see how instanceof operator is used to make sure that the object is indeed of type CardPayment and then casting is done to the CardPayment type, which makes it possible to call the printSlip() method.

Reference: https://docs.oracle.com/javase/specs/jls/se8/html/jls-5.html

That's all for this topic Type Casting in Java With Conversion Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Switch Case Statement in Java With Examples
  2. Access modifiers in Java
  3. Java pass by value or pass by reference
  4. Array in Java With Examples
  5. Java Exception Handling Tutorial

You may also like-

  1. Abstraction in Java
  2. Object Creation Using new Operator in Java
  3. static Import in Java With Examples
  4. Java Collections Interview Questions And Answers
  5. Java Multithreading Interview Questions And Answers
  6. Java Concurrency Interview Questions And Answers
  7. Race Condition in Java Multi-Threading
  8. Magic Methods in Python With Examples

Difference Between Abstract Class And Interface in Java

The difference between abstract class and interface in Java is one of the most common java interview questions, often asked right at the beginning to "break the ice". But that way Abstract class Vs Interface becomes a very important question as it is often said "first impression matters". So, understanding this topic thoroughly can set the tone for the rest of your interview.

First of all it is very important to know what an abstract class is and what an interface is. So please go through these two posts abstract class in Java and interface in Java to familiarize yourself with abstract class and interface.

There are also some similarities between abstract class and interface in Java like-

  • Both cannot be instantiated directly.
  • Both can declare abstract methods that must be implemented by subclasses (in case of abstract class) or implementing classes (in case of interface).

Abstract class Vs Interface in Java

Abstract Class Interface
Methods Abstract class can have both abstract methods (method with no body) and non-abstract methods (methods with implementation). Interface can have abstract methods only.
Note: From Java 8 interfaces can have default methods and static methods and private methods Java 9 onward. So on this account both abstract classes and interfaces in Java are becoming quite similar as both can have methods with implementation.
Access Modifiers Abstract class methods can have public, protected, private and default modifier apart from abstract methods. In interface, methods are by default public abstract only. From Java 9 private methods can also be added to a Java interface.
Variables Abstract class fields can be non-static or non-final. In interface all the fields are by default public, static, final.
Implementation Abstract class may have some methods with implementation and some methods as abstract. In interface all the methods are by default abstract, where only method signature is provided. Note: From Java 8 interfaces can have default methods where default implementation can be provided with in the interface and static methods that can be accessed using the Interface name. Apart from that interfaces can have private methods too Java 9 onward.
Constructor Abstract classes have a constructor, it may be user supplied or default in case no constructor is written by a user. Interfaces can't have a constructor.
Multiple Inheritance Abstract class can extend at most one class and implement one or more interfaces. Interface can only extend one or more interfaces.
Extends/Implements Abstract class are extended by the sub-classes. Sub-classes need to provide implementation for all the abstract methods of the extended abstract class or be declared as abstract itself. Interface is implemented by a class and the implementing class needs to provide implementation for all the abstract methods declared in an interface. If a class does not implement all the abstract methods of an interface then that class must be declared as abstract.
Easy to evolve Abstract class was considered easy to evolve as abstract classes could add new methods and provide default implementation to those methods. Interface was not considered easy to evolve as, in the case of adding new method to an interface, all the implementing classes had to be changed to provide implementation for the new method. With Java 8 even interfaces can have default methods so that issue has been addressed.

Which one should you use, abstract classes or interfaces?

As we know abstract classes have to be extended where as interfaces need to be implemented by a class. That itself suggests when to use what.

Abstract Class

Abstract classes are designed to be extended. They are ideal when you want to build a generalized base class and then provide specialized implementations by extending it. Abstract classes can hold state (fields), define constructors, and include both abstract and concrete methods. This makes them perfect for scenarios where you want to share common logic across related subclasses while still enforcing certain abstract behaviors.

Interface

Interfaces are meant to be implemented by unrelated classes. They define a contract that multiple classes can follow, each providing its own implementation. Since Java 8, interfaces can also include default methods and static methods, and from Java 9 onwards, even private methods for internal reuse. This evolution makes interfaces more powerful, but their primary role remains enabling polymorphism, the "one interface, multiple implementations” principle".

That's all for this topic Difference Between Abstract Class And Interface in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Java Basics Tutorial Page


Related Topics

  1. Interface in Java With Examples
  2. Marker Interface in Java
  3. Interface Static Methods in Java 8
  4. Interface Default Methods in Java 8
  5. Core Java Basics Interview Questions And Answers

You may also like-

  1. What are JVM, JRE and JDK in Java
  2. static Keyword in Java With Examples
  3. super Keyword in Java With Examples
  4. this Keyword in Java With Example
  5. Reflection in Java - Getting Class Information
  6. Autowiring using XML configuration in Spring
  7. How HashMap Works Internally in Java
  8. Count Number of Words in a String Java Program

Difference Between Array And ArrayList in Java

The difference between Array and ArrayList in Java is one question you may come across in Java technical interviews. While both structures are used to store data, they serve different purposes and have distinct characteristics. Understanding these differences is crucial for writing efficient and maintainable Java code

In this post we'll see some of the differences between ArrayList and Array in terms of how they are initialized and the performance they give.

Array Vs ArrayList in Java

  1. Fixed vs Dynamic Size
    Array: Once declared, an Array has a fixed size and cannot be resized. ArrayList: An ArrayList is dynamic, often referred to as a "dynamic array". ArrayList uses array of Object internally, but it has the logic to keep growing the size of the array as and when previous size is not able to fit in the number of elements stored in the ArrayList.

    Refer: How ArrayList works internally in Java to know more about the internal implementation of ArrayList.

  2. Data Types Stored
    Array: Can store both primitive types as well as objects.
    ArrayList: Can store only objects. With autoboxing and unboxing introduced in Java 5, primitives are automatically wrapped into their corresponding wrapper classes- (e.g., int -> Integer).

    For example, if you want an array of primitive type int-

    int[] intArray = new int[3];
    

    Or, if you have a class Employee and you want an array of size 5 to hold 5 Employee objects then-

    Employee[] employees = new Employee[5];
    

    In case of ArrayList if you want to store integers then you have to do this, note the use of wrapper class Integer-

    List<Integer> myList = new ArrayList<Integer>();
    
  3. Difference number 2 between array and ArrayList also indicates one more difference, which is about "type safety". Since Array knows the type of the data which it can hold so it will give compiler error "Type Mismatch" or "ArrayStoreException" if it is not able to resolve it at run time. For example following code throws ArrayStoreException.
    Object[] names = new String[3];
    names[0] = 12;
    
    Where as following code throws compile time error "Type Mismatch".
    String[] names = new String[3];
    names[0] = 12;
    

    In case of ArrayList, generics brought the much needed type safety which, as shown above, is not required for Array as type of elements stored in the array is specified at the array creation time itself, trying to store element of any other type will result in ArrayStoreException.

    If a list, which stores only Integers, is needed it should be defined as-

    List<Integer> myList = new ArrayList<Integer>();
    
  4. Performance Comparison
    Array: Since its size is fixed, there is no overhead of resizing. Memory usage is more efficient, especially when storing primitives, as they are not wrapped into objects.
    ArrayList: Internally backed by an array of objects, it offers dynamic resizing. When the internal array reaches capacity, a new larger array is created and elements are copied over, introducing overhead during expansion. Additionally, because ArrayList stores only objects, memory consumption is higher compared to arrays storing primitives
  5. Array has length variable which gives the length of the array. Note that length attribute denotes the length of the array at the time of declaration.
    For example, If an array is declared like this-
    String[] names = new String[3];
    names[0] = "Java";
    
    Then length var will always be 3 even if array names has only one value.

    In case of ArrayList, size() method is used and it will give the size as the current number of elements in the ArrayList.

That's all for this topic Difference Between Array And ArrayList in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Difference Between ArrayList And LinkedList in Java
  2. Difference Between ArrayList And Vector in Java
  3. Difference Between ArrayList And CopyOnWriteArrayList in Java
  4. HashSet Vs LinkedHashSet Vs TreeSet in Java
  5. Java Collections Interview Questions And Answers

You may also like-

  1. Difference Between Comparable and Comparator in Java
  2. Race condition in Java multi-threading
  3. Polymorphism in Java
  4. Method overriding in Java
  5. Merge Sort Program in Java
  6. Dependency Injection in Spring Framework
  7. What is LangChain - An Introduction
  8. List in Python With Examples

RunnableParallel in LangChain With Examples

In the post Chain Using LangChain Expression Language With Examples we saw an example of sequential chain using LCEL. In LangChain there is also a RunnableParallel class which is designed to run multiple components in parallel.

LangChain RunableParallel Class

RunnableParallel is a core component in LangChain Expression Language (LCEL) that allows you to run multiple Runnable objects concurrently on the same input. If you have independent tasks like summarizing a document and creating quiz using the same document then using RunnableParallel you can execute these two workflows simultaneously.

When we say "same input" here, it doesn’t mean prompt has to be exactly same for the parallel tasks. You can pass a single input dictionary where each key corresponds to a different component’s input. Example given later clarifies this point.

RunnableParallel example with Python

Let's say you are given a task to generate content for various social media platforms from a single internal news update. Using RunnableParallel ensures all platform-specific content is generated concurrently.

Task is to generate a press release for LinkedIn where you want to keep the tone professional and for X/Twitter where tone can be a bit casual. You can use parallel chains to generate such tailored content.

Prompts which are used in the example

linkedin_prompt = ChatPromptTemplate.from_messages([
    SystemMessage(content="You are a helpful assistant that generates content for social media platforms."),
    HumanMessagePromptTemplate.from_template("Write a {linkedin_tone} post for {linkedin_platform} about {topic}.")            
])
twitter_prompt = ChatPromptTemplate.from_messages([
    SystemMessage(content="You are a helpful assistant that generates content for social media platforms."),
    HumanMessagePromptTemplate.from_template("Write a {twitter_tone} post for {twitter_platform} about {topic}.")            
])

As you can see, we have the separate place holders {linkedin_tone} and {linkedin_platform} for LinkedIn and {twitter_tone}, {twitter_platform} for Twitter.

In LangChain, RunnableParallel expects a single input dictionary that gets passed to all subchains. Each subchain then decides what to use from that input.

Invoking the chain

So, the chain can be invoked like this-

response = parallel_chain.invoke({
    "topic": topic,
    "linkedin_tone": "professional",
    "linkedin_platform": "LinkedIn",
    "twitter_tone": "casual",
    "twitter_platform": "Twitter"
})

Complete Python program

from langchain.messages import SystemMessage
from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_ollama import ChatOllama
from langchain_core.runnables import RunnableParallel
from langchain_core.output_parsers import StrOutputParser
from dotenv import load_dotenv

# Load environment variables
load_dotenv()

# Define system and human message templates
linkedin_prompt = ChatPromptTemplate.from_messages([
    SystemMessage(content="You are a helpful assistant that generates content for social media platforms."),
    HumanMessagePromptTemplate.from_template("Write a {linkedin_tone} post for {linkedin_platform} about {topic}.")            
])

twitter_prompt = ChatPromptTemplate.from_messages([
    SystemMessage(content="You are a helpful assistant that generates content for social media platforms."),
    HumanMessagePromptTemplate.from_template("Write a {twitter_tone} post for {twitter_platform} about {topic}.")            
])

# Define the output parser
parser = StrOutputParser()

def generate_content(topic: str) -> dict:

    # Initialize the model
    #model = ChatGoogleGenerativeAI(model="gemini-3.1-flash-lite-preview", temperature=0.7)   
    model = ChatOllama(model="llama3.1", temperature=0.7)              

    # Create two chains for LinkedIn and Twitter
    linkedin_chain = linkedin_prompt | model | parser
    twitter_chain = twitter_prompt | model | parser

    # Create a RunnableParallel object to run both chains in parallel
    parallel_chain = RunnableParallel({
        "linkedin": linkedin_chain,
        "twitter": twitter_chain
    })

    # Generate content for both platforms in parallel
    response = parallel_chain.invoke({
        "topic": topic,
        "linkedin_tone": "professional",
        "linkedin_platform": "LinkedIn",
        "twitter_tone": "casual",
        "twitter_platform": "Twitter"
    })

    # Return the generated content as a dictionary
    return response

# Example usage
if __name__ == "__main__":
    topic = "XYZ tech announces new AI product for its gen AI platform"
    generated_content = generate_content(topic)
    print("Generated LinkedIn Post:")
    print(generated_content["linkedin"])
    print("\nGenerated Twitter Post:")
    print(generated_content["twitter"])

Note that, when you construct a RunnableParallel with mapping as given below-

parallel_chain = RunnableParallel({
        "linkedin": linkedin_chain,
        "twitter": twitter_chain
    })

That mapping defines the keys of the output dictionary. Each chain runs in parallel, and the results are collected under those keys. That is why generated content is extracted like this-

generated_content["linkedin"]
generated_content["twitter"]

Output

Copying the content generated for Twitter here as the content generated for LinkedIn is quite long.

Generated Twitter Post:
"BIG NEWS! @XYZTech just dropped a game-changer! Their new AI product is now live on their Gen AI platform, taking AI capabilities to the NEXT LEVEL! What can it do? Stay tuned for the deets! #AI #Tech #Innovation #XYZTech"

That's all for this topic RunnableParallel in LangChain With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. First LangChain Program: Ask Me Anything
  2. LangChain PromptTemplate + Streamlit - Code Generator Example
  3. Messages in LangChain
  4. Java Program to Reverse a Number
  5. Swap or Exchange Two Numbers Without Using Any Temporary Variable Java Program

You may also like-

  1. Find Duplicate Elements in an Array Java Program
  2. Count Number of Times Each Character Appears in a String Java Program
  3. Check if Given String or Number is a Palindrome Java Program
  4. Polymorphism in Java
  5. Difference Between Abstract Class And Interface in Java
  6. Java Automatic Numeric Type Promotion
  7. Java Pass by Value or Pass by Reference
  8. finally Block in Java Exception Handling

Chain Using LangChain Expression Language With Examples

In this tutorial we’ll see how you can create chains in LangChain using LangChain Expression Language (LCEL) and what are the benefits of creating such chains.

Pipelines using LCEL

When we are creating a generative app using LangChain, it is essentially a sequence of events which can be executed as a pipeline (events separated by | symbol), where each step is represented as a runnable, automatically supporting synchronous, asynchronous, streaming, and even parallel execution when steps are independent.

For example, a pipeline can be as simple as-

  1. Prompt
  2. Model
  3. Parsed response

Which in terms of LCEL can be expressed as a pipeline like this-

chain = prompt | model | output_parser

Composing chain like this using pipe (|) symbol signifies the flow of information from left to right. In the chain, we have composed above, output of prompt flows to model, output of that in turn goes to output_parser.

You can also compose complex pipelines like-

  • Reformulate the user’s query by passing it to LLM.
  • Retrieving relevant data from Vector DB using the search query.
  • Passing that data to LLM to summarize it.
  • Passing this summary and reformulated user’s query to LLM to get the final answer.

Composed LCEL chain for this may look like as given below-

# LCEL Chain Composition
chain = (
    {"question": RunnablePassthrough()}  # Input passthrough
    | {"search_query": query_prompt | llm | StrOutputParser()}  # Step 1
    | {"docs": lambda x: retrieve_docs(x["search_query"])}      # Step 2
    | {"summary": summary_prompt | llm | StrOutputParser()}     # Step 3
    | {"final_answer": answer_prompt | llm | StrOutputParser()} # Step 4
    | format_prompt | llm | StrOutputParser()                   # Step 5
)

Features of LCEL

Some of the key features of LangChain Expression Language are as given below.

  • In LCEL, a Runnable is the fundamental building block of a pipeline. Runnable acts as a unified interface providing support for multiple execution modes (sync, async, streaming, batch).

    Key Methods-

    • invoke/ainvoke: Transforms a single input into an output.
    • batch/abatch: Efficiently transforms multiple inputs into outputs.
    • stream/astream: Streams output from a single input as it's produced.
    • astream_log: Streams output and selected intermediate results from an input.
    Methods with 'a' prefix are asynchronous.
  • Uses pipe symbol (|)- Chains are created by connecting components (e.g., prompts, models, output parsers) linearly using pipe | operator, creating an explicit left-to-right data flow.
  • Asynchronous support- Normally, when you run code, you wait until the whole task finishes before you get the result. With async, tasks don’t block each other. All LCEL chains are asynchronous by default meaning LCEL chains can run in the background, letting other work continue while waiting for the model’s response.
  • Streaming- Instead of waiting for the entire answer, LCEL chains can send pieces of the response as they’re generated. This makes apps feel faster and more interactive, especially when dealing with LLMs that take time to generate long outputs.
  • Parallelization- Automatically runs independent steps in parallel, significantly reducing latency.

Simple Chatbot using LCEL and streamlit

Let’s try to see a LCEL chain in action by creating a simple chatbot with Streamlit used to create UI for the same.

Required packages

python-dotenv

langchain

# package as per the LLM used

langchain-ollama

# for streamlit

streamlit

from langchain_core.prompts import ChatPromptTemplate, HumanMessagePromptTemplate
from langchain_ollama import ChatOllama

import streamlit as st
from langchain_core.messages import SystemMessage
from langchain_core.output_parsers import StrOutputParser

# Define system and human message templates
system_message = SystemMessage(content="You are a helpful assistant that responds to user queries.")    
# Define the output parser
parser = StrOutputParser()

def generate_response(user_input: str) -> str:

    # Create a ChatPromptTemplate object
    prompt = ChatPromptTemplate.from_messages([system_message, 
                               HumanMessagePromptTemplate.from_template("{user_input}")]) 
    # Initialize the model
    model = ChatOllama(model="llama3.1", temperature=0.5)            

    #chain the prompt, model, and parser together
    chatbot_chain = prompt | model | parser

    # Generate the response using the model
    response = chatbot_chain.invoke({"user_input": user_input})
    #print(response)
    #Return the generated response

    return response
#Streamlit app to demonstrate the simple chain

st.set_page_config(page_title="Simple Chatbot", layout="centered")
st.title("🤖 Simple Chatbot")
# Initialize session state
if "chat_history" not in st.session_state:
    st.session_state.chat_history = []
#show previous messages  
for message in st.session_state.chat_history:
    with st.chat_message(message["role"]):
        st.markdown(message["content"])
        
user_input = st.chat_input("Enter your query:")  
if user_input:
    st.session_state.chat_history.append( {"role": "user", "content": user_input})
    with st.chat_message("user"):
        st.markdown(user_input)
    response = generate_response(user_input)
    st.session_state.chat_history.append({"role": "assistant", "content": response})
    with st.chat_message("assistant"):
        st.markdown(f"**Chatbot Response:** {response}")   
else:
    st.warning("Please enter a query to get a response.")

Points to note

Here are some key points to note about the code:

  • ChatPromptTemplate is used to create a template with a system message to set the context and a human message.
  • StrOutputParser() extracts text content from model outputs as a string.
  • Prompt, model, and parser are chained to create a chain which is then invoked by passing the value for the placeholder in the prompt template.
  • Streamlit provides chat elements to help you build conversational apps. Some of the chat elements used in the example are st.chat_input and st.chat_message.
  • Streamlit apps rerun from top to bottom whenever the user interacts (e.g., sends a new message, presses a button). If you didn’t store and replay the conversation, only the latest message would show up.
  • Note here that chat history here is limited to the context of Streamlit, LLM is still stateless (Not aware of the chat history).That is evident from the following image of the chatbot conversation.
  • chatbot in langchain

That's all for this topic Chain Using LangChain Expression Language With Examples. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. What is LangChain - An Introduction
  2. First LangChain Program: Ask Me Anything
  3. Prompt Templates in LangChain With Examples
  4. LangChain PromptTemplate + Streamlit - Code Generator Example
  5. Messages in LangChain

You may also like-

  1. String in Java Tutorial
  2. Array in Java
  3. Count Number of Words in a String Java Program
  4. Ternary Operator in Java With Examples
  5. Java Multithreading Interview Questions And Answers
  6. Java Exception Handling Tutorial
  7. ConcurrentHashMap in Java With Examples
  8. TreeMap in Java With Examples