HTML-рендеринг в Streamlit работает не всегдаCSS

Разбираемся в CSS
Ответить
Anonymous
 HTML-рендеринг в Streamlit работает не всегда

Сообщение Anonymous »

Я перебираю источники/ссылки своих данных и хочу отображать их построчно. Каким-то образом правильно отображается только первая строка, остальные строки отображаются в виде блоков кода в потоке света. Понятия не имею, почему.
Это мой результат:
[img]https:// i.sstatic.net/gBh3aSIz.png[/img]

HTML-код действителен:

Код: Выделить всё


1
[url=https://wissensguru-s3.s3.eu-central-1.amazonaws.com/IDTA-02024-1-0_Submodel_Wireless-Communication.pdf]IDTA-02024-1-0_Submodel_Wireless-Communication.pdf[/url]
78


2
[url=https://wissensguru-s3.s3.eu-central-1.amazonaws.com/IDTA-01001-3-0_SpecificationAssetAdministrationShell_Part1_Metamodel-3.pdf]IDTA-01001-3-0_SpecificationAssetAdministrationShell_Part1_Metamodel-3.pdf[/url]
23110211


Это мое приложение с потоковой подсветкой:

Код: Выделить всё

from dataclasses import dataclass
from typing import List, Literal, Optional
import streamlit as st
from PIL import Image
from backend.generate_answer_lambda import get_answer
from backend.get_sources_lambda import get_sources
import time
import re

# Ensure CSS file path is correct
CSS_FILE_PATH = "static/styles/styles.css"

st.set_page_config(
page_icon=Image.open('static/images/mhp_fav_icon.png'),
layout="wide",
initial_sidebar_state="expanded",
)

@dataclass
class Message:
"""Class for keeping track of a chat message."""
origin: Literal["human", "ai"]
message: str
sources: Optional[List[dict]] = None

# Read the CSS file and ensure it's loaded properly
with open(CSS_FILE_PATH, "r") as f:
css = f.read()
# Append version query parameter to avoid caching issues
version = time.time()  # Current time to ensure a new version each time
st.markdown(f'{css}', unsafe_allow_html=True)

def initialize_session_state():
if "chat_history" not in st.session_state:
st.session_state.chat_history = [
Message(origin="ai", message="Hello, How can I help you today?")
]

if "sources" not in st.session_state:
st.session_state.sources = get_sources()

initialize_session_state()

def stream_response(answer):
pattern = re.compile(r'(\s+|\W+)', re.UNICODE)
chunks = pattern.split(answer)
for chunk in chunks:
yield chunk
time.sleep(0.03)

def on_user_input(user_query):
st.session_state.chat_history.append(Message(origin="human", message=user_query))

chat_placeholder.markdown(f"""

[img]app/static/images/user_icon.png[/img]
{user_query}

""", unsafe_allow_html=True)

response_placeholder = chat_placeholder.empty()
expander_placeholder = st.empty()
with response_placeholder:
st.markdown(f"""

[img]app/static/images/ai_icon.png[/img]


""", unsafe_allow_html=True)

# Fetch the answer
answer, sources = get_answer(user_query)

# Once answer is fetched, hide the spinner and display the response
st.empty()  # Remove the spinner

# Stream the response
streamed_response = ""
for chunk in stream_response(answer):
streamed_response += chunk
response_placeholder.markdown(f"""

[img]app/static/images/ai_icon.png[/img]
{streamed_response}

""", unsafe_allow_html=True)

if sources:

with expander_placeholder.expander(label="References"):
html_content = ""
for idx, source in enumerate(sources):
html_content += f"""

{idx + 1}
[url={source[]{source['filename']}[/url]
{''.join([f"{page}" for page in source['pages']])}

"""
if idx == len(sources) - 1:
html_content += ""
print(html_content)
st.markdown(html_content, unsafe_allow_html=True)
else:
st.sidebar.warning("No References found.")

st.session_state.chat_history.append(Message(origin="ai", message=streamed_response, sources=sources))

st.markdown("""

MHP Chatbot

""", unsafe_allow_html=True)

chat_placeholder = st.container()

st.sidebar.image('static/images/mhp_sidebar_logo.png', width=180)
st.sidebar.markdown("#")

with chat_placeholder:
st.markdown("#")
for chat in st.session_state.chat_history:
if chat.origin == "ai":
st.markdown(f"""

[img]app/static/images/ai_icon.png[/img]
{chat.message}

""", unsafe_allow_html=True)
# Check if sources exist for this AI response
if chat.sources:
expander_placeholder = st.empty()
with expander_placeholder.expander(label="References"):
html_content = ""
for idx, source in enumerate(chat.sources):
html_content += f"""

{idx + 1}
[url={source[]{source['filename']}[/url]
{''.join([f"{page}"  for page in source['pages']])}

"""
if idx == len(chat.sources) - 1:
html_content += ""
print(f"in loop {html_content}")
st.markdown(html_content, unsafe_allow_html=True)

else:
st.markdown(f"""

[img]app/static/images/user_icon.png[/img]
{chat.message}

""", unsafe_allow_html=True)

user_query = st.chat_input("Your message")
if user_query:
on_user_input(user_query)

uploaded_file = st.sidebar.file_uploader("Upload PDF file")

# if uploaded_file is not None:
#     upload_file(uploaded_file)

sources = st.session_state.sources
st.sidebar.markdown("")
# Check if sources exist
if sources:
with st.sidebar.expander(label="PDF Files"):
for source in sources:
st.page_link(source['url'], label=source["filename"], icon='📄')
else:
st.sidebar.warning("No PDF files found.")

Это мой CSS:

Код: Выделить всё

@import url("https://fonts.googleapis.com/css2?family=Orbitron:wght@400..900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap");

span {
font-family: "Orbitron", sans-serif !important;
}

p {
font-family: "Roboto", sans-serif !important;
}

.header-with-divider {
display: flex;
align-items: center;
border-bottom: 2px solid;
border-image: linear-gradient(90deg, #87bc49, #009bd2) 30;
padding-bottom: 3px;
margin-bottom: 10px;
}

.header-with-divider h2 {
margin: 0;
}

#stDecoration {
background-image: linear-gradient(90deg, #87bc49, #009bd2);
}

button {
border-radius: 2px !important;
color: #009 !important;
outline: 1px solid #009;
outline-offset: -1px;
background-color: white !important;
}

button:hover {
color: #009bd2 !important;
background-color: transparent;
outline-color: #009bd2 !important;
transition: 0.4s outline-color, 0.4s;
}

button[kind="header"],
button[kind="headerNoPadding"] {
outline: none;
}

.sidebar-image {
display: block;
margin-left: auto;
margin-right: auto;
width: 80%; /* Adjust width as needed */
margin-bottom: 20px;  /* Add space below the image */
}

.sidebar-image-container {
width: 100%;
height: 100%;
}

.chat-row {
display: flex;
margin: 5px;
width: 100%;
}

.row-reverse {
flex-direction: row-reverse;
}

.ai-chat-container {
display: flex;
flex-direction: column;
gap: 10px;
}

.ai-chat-container div,
.chat-bubble {
font-family: "Roboto", sans-serif;
border: 1px solid transparent;
padding: 5px 10px;
margin: 0 7px;
max-width: 85%;
border-radius: 10px;
}

.ai-message-container {
background: rgb(240, 242, 246);
}

.sources-container {
display: flex;
flex-direction: column;
gap: 5px;
border: 1px solid #4caf50 !important;
font-size: 14px !important;
background-color: #f6fff6;
}

.source-container {
display: flex;
justify-content: space-between;
align-items: center;
max-width: 100% !important;
margin-left: 0 !important;
margin-right: 0 !important;
}

.source-pages-container {
margin: 0 !important;
border-left-width: 0 !important;
padding: 0 !important;
font-size: 12px !important;
}

.source-number {
color: #4caf50;
font-size: 16px !important;
margin-right: 10px;
}

.source-text {
margin-bottom: 0;
font-weight: 400;
flex: 1;
}

.human-bubble {
background: linear-gradient(90deg, #87bc49, #009bd2);
color: white;
}

.chat-icon {
border-radius: 5px;
}

.page-number {
background-color: #4caf50;
color: white;
padding: 5px 10px;
border-radius: 5px;
margin-right: 5px;
}

/* Styles for Streamlit App Markdown */
/* .st-emotion-cache-1c7y2kd {
flex-direction: row-reverse;
text-align: right;
align-self: flex-end;
background-color: transparent;
}

div[aria-label="Chat message from AI"] {
background: rgb(240, 242, 246);
border-radius: 10px;
padding: 10px;
}

div[aria-label="Chat message from Human"] {
background: linear-gradient(90deg, #87bc49, #009bd2);
border-radius: 10px;
padding: 10px;
color: white;
}

div[data-testid="stChatMessage"] {
max-width: 80%;
} */

/* STYLES FOR V2 */
.chat-container {
display: flex;
flex-direction: column;
align-items: flex-start;
}

.chat-message {
display: flex;
margin: 10px 0;
}

.chat-message.ai {
flex-direction: row;
}

.chat-message.human {
flex-direction: row-reverse;
align-self: flex-end;
}

.chat-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
margin: 0 10px;
}

.chat-text {
font-family: "Roboto", sans-serif;
padding: 10px;
border-radius: 10px;
max-width: 80%;
margin-top: 10px;
}

.chat-message.human .chat-text {
background: linear-gradient(90deg, #87bc49, #009bd2);
color: white;
}

.chat-message.ai .chat-text {
background-color: rgb(241, 241, 241);
}

.ai-chat-container-n {
display: flex;
flex-direction: column;
gap: 10px;
}

.custom-spinner {
margin-top: 10px;
width: 20px;
height: 20px;
border: 4px solid rgba(0, 0, 0, 0.1);
border-top: 4px solid #009;
border-radius: 50%;
animation: spin 1s linear infinite;
margin-right: 10px;
}

@keyframes spin {
to {
transform: rotate(360deg);
}
}

section[data-testid="ScrollToBottomContainer"] div[data-testid="stExpander"] {
max-width: 80%;
margin-left: 56px;
margin-bottom: 20px;
}

.reference-container {
display: flex;
flex-direction: column;
}
.reference-row {
display: flex;
align-items: center;
margin-bottom: 10px;
gap: 15px;
}
.reference-index {
text-align: center;
background-color: rgb(239, 239, 239);
padding: 3px 10px;
color: #009;
border-radius: 5px;
font-family: "Orbitron", sans-serif;
}

.reference-name {
text-align: left;
padding-left: 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}

.reference-name a {
text-decoration: none;
color: #009;
transition: all 0.2s;
}

.reference-name a:hover {
color:  #009bd2;
text-decoration: underline;
}

.reference-pages {
display: flex;
gap: 5px;
color: white;
}
.reference-page {
border: 1px solid #009;
padding: 3px;
border-radius: 5px;
background-color: #009;
font-size: 14px;
}

Все перепробовал, но не знаю, почему правильно отображается только первая строка.

Подробнее здесь: https://stackoverflow.com/questions/785 ... not-always
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «CSS»