Chatbot app refreshes entire page on each new input

Hello everyone I locally using the streamlit to implement a simple chatbot.
Everytime user enters a new message, title and the previous messages flickers/reload again.It seems the entire website reloads. How to avoid it. My python version is 3.12…3 and streamlit version==1.40.1. How can I fix it?. here is my entire app code.

st.set_page_config(
    page_title="Web Chatbot"
)
st.title("Web Chatbot")


# Initialize chat history in Streamlit's session state
if "chat_history" not in st.session_state:
    st.session_state.chat_history = []

def stream_response(response_text):
    for word in response_text.split():
        yield word + " "
        time.sleep(0.1)

# Display chat messages from history
for message in st.session_state.chat_history:
    with st.chat_message(message["role"], avatar='🕵🏻' if message["role"] == 'user' else None):
        st.markdown(message["content"])

# Accept user input
if prompt := st.chat_input("Ask me anything..."):
    with st.chat_message("user", avatar='🕵🏻'):
        st.markdown(prompt)
    st.session_state.chat_history.append({"role": "user", "content": prompt})

    with st.spinner("Generating response..."):
        try:
            full_response = ""
            with st.chat_message("assistant"):
                response_container = st.empty()
                response_container.markdown("...")
                response = chain.invoke({
                    "input": prompt,
                    "chat_history": st.session_state.chat_history,
                })

                for chunk in stream_response(response["answer"]):
                    full_response += chunk
                    response_container.markdown(full_response)
        except Exception as e:
            st.error(f"An error occurred: {e}")
            full_response = "Sorry, an error occurred while generating the response."

    st.session_state.chat_history.append({"role": "assistant", "content": full_response})

Could you kindly provide your complete code, including the initialization of the chain? This would enable me to replicate the issue on my end.

Is anything else needed other than this @Encrypt ?

import streamlit as st
import os
import time
import openai
from dotenv import load_dotenv
import traceback
from azure.identity import ClientSecretCredential
from azure.keyvault.secrets import SecretClient
from pinecone import Pinecone

from langchain.globals import set_verbose

from langchain_openai import AzureOpenAIEmbeddings
from langchain_pinecone import PineconeVectorStore

from langchain.prompts.prompt import PromptTemplate
from langchain.chains import ConversationalRetrievalChain
from langchain_openai import ChatOpenAI
from langchain.memory import ConversationBufferMemory
import streamlit as st
from openai import APIConnectionError

from langchain.chains import create_retrieval_chain
from langchain.chains.combine_documents import create_stuff_documents_chain
from langchain_core.messages import HumanMessage, AIMessage
from langchain_core.prompts import MessagesPlaceholder
from langchain.chains.history_aware_retriever import create_history_aware_retriever
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser

emeddings = openai embedding model
try:
    vectorstore = PineconeVectorStore(index_name=INDEX_NAME, embedding=embeddings)
except Exception as e:
    st.error(f"Failed to initialize Pinecone vectorstore: {e}")
    raise

def create_chain(vectorstore):
    try:
        model_name = "gpt-3.5-turbo"
        model = ChatOpenAI(model=model_name, temperature=0.1, openai_api_key=os.environ['OPENAI_API_KEY'])
    except KeyError:
        raise ValueError("OPENAI_API_KEY environment variable is missing.")
    except Exception as e:
        raise RuntimeError(f"Failed to initialize the language model: {e}")

    PROMPT_TEMPLATE = """
    Use the following pieces of context to answer the user's question. 
    If you don't know the answer, just say that you don't know, don't try to make up an answer.
    Please do not answer other than the documents and conversation.

    CONTEXT:
    {context}
    """
    try:
        prompt = ChatPromptTemplate.from_messages([
            ("system", PROMPT_TEMPLATE),
            MessagesPlaceholder(variable_name="chat_history"),
            ("human", "{input}")
        ])
    except Exception as e:
        raise RuntimeError(f"Failed to create prompt template: {e}")

    try:
        chain = create_stuff_documents_chain(
            llm=model,
            prompt=prompt
        )
        retriever = vectorstore.as_retriever(search_kwargs={"k": 10})
        retrieval_chain = create_retrieval_chain(retriever, chain)
    except Exception as e:
        raise RuntimeError(f"Failed to create retrieval chain: {e}")
    
    return retrieval_chain

def process_chat(chain, question, chat_history):
    try:
        response = chain.invoke({
            "input": question,
            "chat_history": chat_history
        })
        return response.get("answer", "No answer generated.")
    except Exception as e:
        raise RuntimeError(f"Error during chat processing: {e}")

# Create the chain
try:
    chain = create_chain(vectorstore)
except Exception as e:
    st.error(f"Error creating the retrieval chain: {e}")
    raise

I have implemented your code with a simplified chain, and it is not refreshing the entire page on a new input prompt. Although Streamlit re-renders all elements on each action, the entire browser page should never refresh.

import streamlit as st
import time
from dotenv import load_dotenv
import streamlit as st

from langchain_openai import ChatOpenAI
from langchain_core.output_parsers import StrOutputParser
from langchain_core.prompts import ChatPromptTemplate

# Load environment variables
load_dotenv()

# Initialize the model
model = ChatOpenAI(model="gpt-4o-mini")

# Define the chain
prompt = ChatPromptTemplate.from_template("""
Chat History:
{chat_history}

Input:
{input}
"""
)
chain = prompt | model | StrOutputParser()

# Set page title
st.set_page_config(
    page_title="NextCore Web Chatbot"
)
st.title("NextCore Web Chatbot")


# Initialize chat history in Streamlit's session state
if "chat_history" not in st.session_state:
    st.session_state.chat_history = []

def stream_response(response_text):
    for word in response_text.split():
        yield word + " "
        time.sleep(0.1)

# Display chat messages from history
for message in st.session_state.chat_history:
    with st.chat_message(message["role"], avatar='🕵🏻' if message["role"] == 'user' else None):
        st.markdown(message["content"])

# Accept user input
if prompt := st.chat_input("Ask me anything..."):
    with st.chat_message("user", avatar='🕵🏻'):
        st.markdown(prompt)
    st.session_state.chat_history.append({"role": "user", "content": prompt})

    with st.spinner("Generating response..."):
        try:
            full_response = ""
            with st.chat_message("assistant"):
                response_container = st.empty()
                response_container.markdown("...")
                response = chain.invoke({
                    "input": prompt,
                    "chat_history": st.session_state.chat_history,
                })

                for chunk in stream_response(response):
                    full_response += chunk
                    response_container.markdown(full_response)

        except Exception as e:
            st.error(f"An error occurred: {e}")
            full_response = "Sorry, an error occurred while generating the response."

    st.session_state.chat_history.append({"role": "assistant", "content": full_response})

Screen Recording 2024-12-06 at 2.51.29 PM

I think you wanted to write stream_response(response): as stream_response(response[‘answer’]):. But still getting the reload on my side. What is the streamlit version and python version are you using?
Here is the link to the video :https://drive.google.com/file/d/1iZbLAuDTUuuXAdT_lS-rV-E_MWH1SAKd/view?usp=drive_link

I am currently using Python version 3.10.9 and Streamlit version 1.40.2. In my case, response variable is a string, so I had to use stream_response(response) for proper functionality. This discrepancy might be due to differences in chain or possibly a different version of Langchain.

Regarding the screen recording you mentioned, I am unable to view it at the moment as access is restricted. I have submitted an access request on Google Drive to resolve this.

I have given you access on G drive.

Thank you for granting access. Based on my observations, it seems that your Streamlit app takes longer to begin processing a new prompt from the user. This delay could be caused by a slow computer or a network connection, especially if the app is being accessed over the network.