Two-column Chat with PDF interface

I would like to create a chatpdf.com-like interface on Streamlit:

  • the left column should display the PDF (an HTML iframe would do)
  • the right column should contain a chatbot (with st.chat_input).

I tried a structure like the following:

import streamlit as st

st.set_page_config(layout="wide")

col1, col2 = st.columns(spec=2, gap="medium")

with col1:

    # display pdf, e.g. st.markdown(f'<iframe src="......." width=100% height="550"></iframe>', unsafe_allow_html=True)

with col2:

    # chatbot with st.chat_input

I am running into the following problems:

  • the chat input bar within the right column goes to the top instead of staying at the bottom as when I create a chatbot in a main area
  • new messages appear below the input bar, and when multiple messages are displayed, the user has to scroll down the browser window (not within the right column!), but this way, both the input bar in the right column, as well as the pdf displayed in the left column are no longer on screen!

On the contrary, I’d like the PDF in the left column to always be on screen. And I would like the input bar to always be at the bottom of the right column. I would like the messages to appear above the input bar in the right column, and to be able to scroll down through the messages within the right column, with the input bar and the displayed PDF always on screen and never moving.

I am also not sure how to make the PDF resize when the browser window is resized. Setting width=100% doesn’t seem to be enough, as it sometimes overlaps with the content of the right column.

Many thanks for your help!

I have the same problem, did you find any solution?

I made a similar app

The way to keep the chat input at the bottom is doing this before the chat input widget

def change_chatbot_style():
    # Set style of chat input so that it shows up at the bottom of the column
    chat_input_style = f"""
    <style>
        .stChatInput {{
          position: fixed;
          bottom: 3rem;
        }}
    </style>
    """
    st.markdown(chat_input_style, unsafe_allow_html=True)
3 Likes

I am trying to do something similar, I have achieved it but using CSS I do not think it is the best practice but I have managed to have the pdf on the right side only that it does not occupy the correct length.

Thanks for sharing this, this is helpful. I notice though that now the input bar now overlaps with the answers if these occupy enough space on screen, it’s sort of transparent, whereas normally it would not be transparent and would be surrounded by a white frame.
Also, normally when an answer/output is long and continues below the screen, the display would automatically scroll to the bottom of the answer (while keeping the input bar on screen at the bottom of the screen), whereas with your solution, the display doesn’t scroll down automatically, the answer is displayed (also overlapping the input bar!) and continuing below the screen, and I have to scroll down manually.
Does this happen to you?

Are you able to keep the PDF always on screen in the left column when you scroll down the right column to read a longer answer?

Thanks for your time

Hello, yes I have this problem but I haven’t had time to look into it.

But I started using this component in another project and it works pretty well so maybe it could work for the chat as well.

Hi,

The whole overlapping business is kinda unavoidable because you are basically positioning the prompt input relative to the window instead of content which naturally takes the prompt out of the content flow.

There are ways using CSS and a little bit of JavaScript to fix your issues. However, the streamlit-float package, which @Odrec recommended, has functions that do these things for you. The whole package is based on/relies on the CSS trick @Odrec laid out with a few more tricks used to get theme and make sure everything works in all browsers. The package can also keep your pdf in view. The first use case was actually keeping content in a column always in view and prevent it from getting scrolled away:

I also provide a solution to your transparent prompt issue using the package in this post (although, the float_init() function call is missing in the code there):

And finally, you can find info on installation of streamlit-float on github:

1 Like

What I did was place the chat in a container so that it scrolls only in that part

thx :slight_smile: so helpful!