Strange UI duplication in Streamlit after first LLM API call — need help debugging.

I’m new to Streamlit and I’m encountering a strange rendering behavior on my page.

Application Overview:

I’m building a panel-based web app that consists of two main sections:

  • Patient Information Block: displays patient-related data (e.g., history, exams, comorbidities, etc.).
  • Chat Block: a conversational interface connected to an LLM-powered backend.

Environment :

  • Python 3.10
  • Streamlit 1.46.1

The Bug:

Whenever I send the first message to the chat (which triggers a request to my LLM API), part of the patient information block is re-rendered on the screen — but with a faded or ghosted appearance. It almost looks like a duplicated container with reduced opacity or layering issues.

This duplicated rendering only happens after the first message is sent. After that, all subsequent messages behave as expected, and the interface remains clean and responsive. So this issue only occurs during the first interaction with the model API.

Below is a screenshot of the duplicated block that appears after sending the first message, along with code snippets that render those components.


### app.py
import streamlit as st
from core.session import initialize_session_state
from ui.sidebar import render_sidebar
from ui.views import render_main_view

# Configuração da página
def main():
    st.set_page_config(
    page_title="💬 Síntece do SOL POC",
    layout="wide" 
    )
    st.title("Síntese de Informações do Paciente")

    if "session_started" not in st.session_state or not st.session_state.session_started:
        initialize_session_state()

    # Renderização da barra lateral e título principal
    render_sidebar()

    # Lógica principal da aplicação
    render_main_view()

if __name__ == "__main__":
    main()
### views.py

import streamlit as st
from ui.components import (
    render_chat_hist,
    render_chat,
    render_patient_summary
)

def render_main_view():
    if not st.session_state.session_started:
        st.info("Clique em **Iniciar Sessão** na barra lateral.")
    else:
        render_patient_summary()
        st.markdown("---")
        render_chat_hist()
        render_chat()
### components.py
import streamlit as st
from utils.backend import send_message, save_patient_summary

def render_patient_summary():
    if not st.session_state.patient_summary:
        with st.spinner("Carregando informações do paciente..."):
            save_patient_summary(st.session_state.id_pessoa)

    consultas_eletivas = st.session_state.patient_summary.get("consultas_eletivas")
    pa_sem_internacoes = st.session_state.patient_summary.get("pa_sem_internacoes")
    internacoes = st.session_state.patient_summary.get("internacoes")
    exames = st.session_state.patient_summary.get("exames")
    comorbidades = st.session_state.patient_summary.get("comorbidades")
    media_consultas = st.session_state.patient_summary.get("media_consultas")

    # Blocos vermelhos de comorbidades (como "diabetes", "hipertenso")
    if comorbidades and comorbidades.get("comorbidades"):
        comorbidity_tags = " ".join([
            f"<span class='comorb-tag'>{c}</span>"
            for c in comorbidades["comorbidades"]
        ])

        st.markdown(f"""
        <div style='margin-bottom: 20px;'>{comorbidity_tags}</div>
        <style>
        .comorb-tag {{
            background-color: #e74c3c;
            color: white;
            padding: 6px 12px;
            border-radius: 16px;
            display: inline-block;
            margin: 4px 4px 4px 0;
            font-size: 14px;
            font-weight: 500;
        }}
        </style>
        """, unsafe_allow_html=True)

    col1, col2, col3 = st.columns([1, 1, 1])
    with col1:
        with st.container(border=True):
            st.markdown("<h4 style='color: #2ecc71;'>Consultas</h4>", unsafe_allow_html=True)
            subcol1, subcol2 = st.columns([1, 1])
            with subcol1:
                st.markdown(f"# {consultas_eletivas['qntd_consultas']}")
                st.markdown("consultas eletivas no ano")
            with subcol2:
                st.markdown(f"# {media_consultas['media_consultas']}")
                st.markdown("média de consultas na faixa etária")
            st.markdown(f"<b><u>última consulta:</u></b>  {consultas_eletivas['ultimas_consultas'] if consultas_eletivas['ultimas_consultas'] else 'N/A'}", unsafe_allow_html=True)

    with col2:
        with st.container(border=True):
            st.markdown("<h4 style='color: #2ecc71;'>Idas ao PA</h4>", unsafe_allow_html=True)
            subcol1, subcol2 = st.columns([1, 1])
            with subcol1:
                st.markdown(f"# {pa_sem_internacoes['qntd_pa']}")
                st.markdown("no último ano")
            with subcol2:
                st.markdown("<b><u>última ida:</u></b>", unsafe_allow_html=True)
                st.markdown(f"{pa_sem_internacoes['ultimos_pa'] if pa_sem_internacoes['ultimos_pa'] else 'N/A'}")

    with col3:
        with st.container(border=True):
            #st.markdown("#### Internações")
            st.markdown("<h4 style='color: #2ecc71;'>Internações</h4>", unsafe_allow_html=True)
            subcol1, subcol2 = st.columns([1, 1])
            with subcol1:
                st.markdown(f"# {internacoes['qntd_internacoes']}")
                st.markdown("no último ano")
            with subcol2:
                st.markdown("<b><u>última internação:</u></b>", unsafe_allow_html=True)
                st.markdown(f"{internacoes['ultimas_internacoes'] if internacoes['ultimas_internacoes'] else 'N/A'}")

    col4, col5 = st.columns([2, 1])
    with col4:
        with st.container(border=True):
            #st.markdown("#### Exames realizados")
            st.markdown("<h4 style='color: #2ecc71;'>Exames</h4>", unsafe_allow_html=True)
            subcol1, subcol2, subcol3 = st.columns([1, 1, 1])
            with subcol1:
                st.markdown(f"# {exames['qntd_exames']}")
                st.markdown("exames realizados")
            with subcol2:
                st.markdown("<b><u>Data do último exame laboratorial:</u></b>", unsafe_allow_html=True)
                st.markdown(f"{exames['ultimo_exame_laboratorial'] if exames['ultimo_exame_laboratorial'] else 'N/A'}")
            with subcol3:
                st.markdown("<b><u>Data do último exame de imagem:</u></b>", unsafe_allow_html=True)
                st.markdown(f"{exames['ultimo_exame_imagem'] if exames['ultimo_exame_imagem'] else 'N/A'}")

    with col5:
        with st.container(border=True):
            st.markdown("<h4 style='color: #2ecc71;'>Comorbidades</h4>", unsafe_allow_html=True)
            if not comorbidades['comorbidades']:
                st.markdown("N/A")
            for comorbidity in comorbidades['comorbidades']:
                st.markdown(f"- {comorbidity}")

def render_chat_hist():
    # Renderiza o histórico de mensagens
    for msg in st.session_state.messages:
        st.chat_message(msg["role"]).write(msg["content"])

def render_chat():
    # Input do usuário
    prompt = st.chat_input("Digite sua mensagem:")
    if prompt:
        st.chat_message("user").write(prompt)
        st.session_state.messages.append({"role": "user", "content": prompt})
        with st.spinner(""):
            response = send_message(prompt)
            llm_response = response[0]["message"]
        st.session_state.messages.append({"role": "assistant", "content": llm_response})
        st.chat_message("assistant").write(llm_response)
1 Like

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