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