Chatbot not showing results when I click the submit button

Summary

Hello
I am trying to make a streamlit app of a chatbot using langchain with OpenAI. The chatbot works good if I run it alone in the main area of the web app but it failed when I integrate it into a more dinamyc environment.

What I want to do is a streamlit with a sidebar with a st.form that contains all the parameters that will use the model and then once that I click on the submit button starts the chatbot in the main page of the app. However, what I get is an empty chatbot display.

the code is the f following:

Steps to reproduce

Code snippet:

#######                         Retrival Augmented Generation (RAE)             ##########

# RAE: es el proceso de integraci贸n de datos externos (external knowledge base) al LLM.
import streamlit as st
import os
from pypdf import PdfReader
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain import OpenAI, PromptTemplate
from langchain.chains import RetrievalQA
import openai  # Lo usaremos para enlistar los modelos disponibles y verificar rapidamente la autenticidad del API Key



#########            1) SET UP GENERAL DE LA WEB APP


#  Configuracion del layout de la pagina
st.set_page_config(layout="wide")

# Set del titulo
st.title(body="Chatbot")



# Integracion de un documento externo
st.sidebar.subheader(body="Ingreso de datos y configuraci贸n")


# 1.1) Configuracion del modelo dentro un form (formulario) de stramlit
with st.sidebar.form(key ='Form1'):
    with st.sidebar:
        api_key = st.sidebar.text_input(label="Ingresa tu API Key de OpenAI")
        documento = st.sidebar.file_uploader(label="Carga del archivo PDF que ser谩 ingegrado al LLM "
                                                   "(Large Language Model) para su consulta")
        chunk_size = st.sidebar.number_input(label="Chunk size:", min_value=100,
                                             max_value=1000, value=400)
        chunk_overlap = st.sidebar.number_input(label="Chunk Overlap:", min_value=50,
                                                max_value=500, value=200)
        submit_button = st.form_submit_button(label="Enviar")

# Nota: Actualmente form sumit button no puede ir directamtne en el sidebar, por eso se usa este doble with st.sidebar

# IMPORANTE:
#  En Streamlit, "st.form" es una funci贸n que te permite crear un formulario interactivo en una aplicaci贸n web. Este formulario es 煤til para recolectar informaci贸n del usuario, como entradas de texto, selecciones etc.
#  puedes agregar widgets interactivos dentro del formulario utilizando el mismo patr贸n de llamadas que utilizar铆as fuera del formulario (por ejemplo, st.text_input, st.selectbox, etc.). Los widgets dentro del formulario interactuar谩n con los valores ingresados por el usuario cuando se env铆e el formulario.
# Para enviar el formulario, debes llamar al m茅todo .submit() de la funci贸n del formulario. Una vez que el usuario hace clic en el bot贸n de enviar, el c贸digo posterior al m茅todo .submit() (IMPORANTE: pero teninedo la sentencia condicionante de que e ha presinado el boton) se ejecutar谩, permiti茅ndote realizar acciones basadas en los valores ingresados por el usuario en el formulario.




##########                     2) Comienzo del Retrival Augmented Generation (RAE)                      #############

# Esto se ejecuta hasta que el usuario ingrese los datos del formulario
# L贸gica que se ejecuta cuando el bot贸n de env铆o es presionado
if submit_button:

    # 2.1) Verificaci贸n de ingresos de datos
    if api_key:
        try:
            models = openai.Model.list(api_key=api_key)
        except:
            st.error("Tu API Key es invalida")
            st.stop()

    else:
        st.error(body="Ingresa una llave")
        st.stop() #Detiene el proceso

    if documento:
        print("Si hay documentos")
    else:
        st.error("No has ingresado un documento PDF")
        st.stop()

######          2.1) LOADING
    reader = PdfReader(stream=documento)

# Obt茅n el n煤mero total de p谩ginas
    number_of_pages = len(reader.pages)
    all_text = "" # Declaramos un str vacio

# Lee el texto de cada p谩gina
    for i in range(number_of_pages):
        page = reader.pages[i]
        all_text += page.extract_text() # ponerle un += es como usar un append en un str


# 2.2) TRANFORM (chunk strategy)

# Set up del objto text_slpiter
    text_splitter = RecursiveCharacterTextSplitter(
# Set a really small chunk size, just to show.
        chunk_size= chunk_size, # numero de caracteres
        chunk_overlap=chunk_size, # solapamiento
        length_function=len)

# IMPORTANTE: Con RecursiveCharacterTextSplitter podemos usar length function, esta funcion "len" cunta solo los caraceres. PEro podriamos usar en lugar de esta funcion alguna otra de contabiliszacion de tokens.  Cualquiera  haria una dividion de chunks, exsten otro modulo que es exclusivo para dividir los textos solo  por caracteres

# Ejecucion del objto text spliter
# Se tiene que ingresar solo string
    chunks = text_splitter.create_documents(texts=[all_text])  # Este lo ejecutamos solo con el string


#####        2.3)  EMBEDDING
# En este caso estamos integrando un embedding modelo de OpenAI, set up el embedding model
    embeddings_model = OpenAIEmbeddings(openai_api_key=api_key)


#######  2.4) Vector Database

    # Creamos nuestro Vectordatabse, le integramos los texgtos (chunkgs) y el modelo de embedding que se usara
    db = Chroma.from_documents(documents=chunks, embedding=embeddings_model)

    # Creamos el objeeto Vector Store Retriver
    retriever = db.as_retriever()


########      2.5)  CREACION E INTEGRACION DE UN TEMPLATE
    prompt_template = """Use the following pieces of context to answer the question. If you don't know the answer, just say that you don't know, don't try to make up an answer.

    {context}

    Question: {question}
    Answer in spanish:"""

    PROMPT = PromptTemplate(
        template=prompt_template, input_variables=["context", "question"])


    ########             2.6) SET UP DEL MODELO
    llm_openai = OpenAI(openai_api_key= api_key,
                        model_name="gpt-3.5-turbo", temperature=0.2) # Entre mayor la temperatura m谩s random las respuestas



    #####    2.7) CREACION DEL CHAIN que integra todo: el vector database (con el retriver), el llm y su prompt
    chain_type_kwargs = {"prompt": PROMPT}
    qa = RetrievalQA.from_chain_type(llm=llm_openai, chain_type="stuff", retriever=retriever,
                                     chain_type_kwargs=chain_type_kwargs)

    # Initialize chat history
    if "messages" not in st.session_state:
        st.session_state.messages = []

    # Display chat messages from history on app rerun
    for message in st.session_state.messages:
        with st.chat_message(message["role"]):
            st.markdown(message["content"])

    # Accept user input
    if prompt := st.chat_input("What is up?"):
        # Add user message to chat history
        st.session_state.messages.append({"role": "user", "content": prompt})
        # Display user message in chat message container
        with st.chat_message("user"):
            st.markdown(prompt)
        # Display assistant response in chat message container
        with st.chat_message("assistant"):
            message_placeholder = st.empty()
            full_response = ""



Can you help me people to understand what is going on?

Best regards,
Orlando

Hi @Orlando_B

I think the issue arises from the form being placed in the sidebar, which would need to be in the main pajnel.

Also, instead of using the form, I think you can use the disabled parameter in st.chat_input such that it will be disabled until the user specifies LLM model parameters via input widget values.

Please check out the following example chatbot apps for ideas on implementing the disabled parameter:

Hope this helps!