Spaces:
Sleeping
Sleeping
File size: 4,362 Bytes
78b06b9 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
import streamlit as st
import streamlit.components.v1 as components
import re
import uuid
import pandas as pd
# ββββββββββββββββββ λ§νμ μμ± ν¨μ
# μμ μ μ
PRIMARY_USER = "#e2f6e8"
PRIMARY_BOT = "#f6f6f6"
def render_message(
message: str,
sender: str = "bot",
chips: list[str] | None = None,
key: str | None = None,
) -> str | None:
"""
- `message` : νμν ν
μ€νΈ (HTML νμ©)
- `sender` : "user" | "bot"
- `chips` : λ²νΌ ννλ‘ λ³΄μ¬ μ€ λ¬Έμμ΄ λ¦¬μ€νΈ
- return : μ¬μ©μκ° ν΄λ¦ν μΉ©(λ¬Έμμ΄) λλ None
"""
# 1) λ§νμ κΈ°λ³Έ μμ±
color = PRIMARY_USER if sender == "user" else PRIMARY_BOT
align = "right" if sender == "user" else "left"
# κ°ν 꼬리ν μ κ±°
message = str(message).rstrip()
# 2) νμ μΆλ ₯
st.markdown(
f'''<div style="text-align:{align}; margin:6px 0;">
<p style = "font-size:13px;"></p>
<span style="background:{color}; padding:10px 14px; border-radius:12px;
display:inline-block; max-width:80%; font-size:13px; line-height:1.45;
word-break:break-word; ">{message}</span>
</div>''',
unsafe_allow_html=True,
)
# 3) μΉ© λ²νΌμ΄ μμ κ²½μ°
if chips:
prefix = f"{key or 'chips'}_{abs(hash(message))}"
clicked = render_chip_buttons(chips, key_prefix=prefix)
return clicked
return None
# ββββββββββββββββββ μΉ©λ²νΌ μμ± ν¨μ
def render_chip_buttons(options, key_prefix="chip", selected_value=None):
def slugify(text):
return re.sub(r"[^a-zA-Z0-9]+", "-", str(text)).strip("-").lower() or "empty"
session_key = f"{key_prefix}_selected"
selected_value = st.session_state.get(session_key)
# μ€νμΌ μ μ©
st.markdown(f"""
<style>
div[data-testid="stHorizontalBlock"]{{
display:block !important;
}}
button[data-testid="stBaseButton-secondary"] {{
background-color: white;
border: 1px solid #e3e8e7;
border-radius: 20px;
padding: 6px 14px;
font-size: 14px;
cursor: pointer;
transition: 0.2s ease-in-out;
margin-bottom: -2px;
width: 230px;
text-align:center;
}}
button[data-testid="stBaseButton-secondary"]:hover {{
background-color: #e8f0ef;
border-color: #009c75;
color: #009c75;
}}
button[data-testid="baseButton-secondary"][disabled]{{
background-color: white;
border-color: #009c75; !important;
color: #009c75; !important;
}}
</style>
""", unsafe_allow_html=True)
clicked_val = None
#cols = st.columns(len(options))
for idx, opt in enumerate(options):
if opt is None or (isinstance(opt, float) and pd.isna(opt)) or str(opt).strip()=="":
continue
is_selected = (opt == selected_value)
is_refresh_btn = "λ€λ₯Έ μ¬νμ§ λ³΄κΈ°" in str(opt)
disabled = (opt == selected_value) and not is_refresh_btn
label = f"{opt}" if is_selected else opt
# stable key
safe_opt = slugify(opt)
stable_key = f"{key_prefix}_{idx}_{safe_opt}"
if st.button(label, key=stable_key, disabled=disabled):
clicked_val = opt
return clicked_val
# ββββββββββββββββββ λ©μμ§ λ¦¬νλ μ΄ ν¨μ
def replay_log(chat_container=None):
with chat_container:
for sender, msg in st.session_state.chat_log:
render_message(msg, sender=sender)
# ββββββββββββββββββ λ©μμ§ λ‘κΉ
&μμ± ν¨μ
def log_and_render(msg, sender, chat_container=None, key=None, chips=None):
# μ€λ³΅ λ°©μ§ λ‘μ§
sent_once = st.session_state.setdefault("sent_once", {})
if key and sent_once.get(key):
return
if key:
sent_once[key] = True
if st.session_state.chat_log and st.session_state.chat_log[-1] == (sender, msg):
return
# λ‘κ·Έμ μ μ₯
st.session_state.chat_log.append((sender, msg))
# λ©μμ§ μΆλ ₯
with chat_container:
rendered = render_message(msg, sender=sender, chips=chips, key=key)
return rendered |