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!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.