Commit
·
0da7a7f
1
Parent(s):
f30713f
teste fix: Ajustes
Browse files- app.py +57 -98
- feedback_manager.py +67 -0
- logos/styles/base.css +11 -0
- logos/styles/dark.css +32 -7
- logos/styles/light.css +53 -13
app.py
CHANGED
@@ -1,36 +1,33 @@
|
|
1 |
import streamlit as st
|
2 |
import requests
|
3 |
-
from PIL import Image
|
4 |
-
import base64
|
5 |
import re
|
6 |
import streamlit_authenticator as stauth
|
7 |
-
from streamlit_feedback import streamlit_feedback
|
8 |
import os
|
9 |
import yaml
|
10 |
from yaml.loader import SafeLoader
|
11 |
from pathlib import Path
|
12 |
-
from drive_search import search_file_in_drive
|
13 |
from datetime import datetime
|
14 |
-
import
|
|
|
15 |
|
16 |
class ChatbotApp:
|
17 |
def __init__(self):
|
18 |
# Configura título, ícone e layout da página
|
19 |
st.set_page_config(page_title="Sicoob Chatbot 🤖", page_icon="logos/sicoob-ico.ico", layout="wide")
|
20 |
-
|
21 |
self.backend_url = "http://localhost:5001/chat"
|
22 |
self.title = "Sicoob Chatbot"
|
23 |
-
self.
|
24 |
-
self.
|
25 |
-
|
26 |
self.style_dir = Path("./logos/styles")
|
27 |
self.load_styles()
|
|
|
28 |
st.session_state.first = False
|
29 |
-
|
30 |
if "theme" not in st.session_state:
|
31 |
st.session_state.theme = "light"
|
32 |
-
|
33 |
self.configyml = os.path.join(os.getcwd(), "./files/config.yaml")
|
|
|
|
|
34 |
|
35 |
def load_styles(self):
|
36 |
try:
|
@@ -43,43 +40,23 @@ class ChatbotApp:
|
|
43 |
self.light_style = ""
|
44 |
self.dark_style = ""
|
45 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
46 |
@st.dialog("📄 Atualizações Sicoob Chatbot", width="small")
|
47 |
def changelog_user(self):
|
48 |
with open("./logos/ChangelogUser.md", encoding="utf-8") as f:
|
49 |
st.markdown(f"{f.read()}", unsafe_allow_html=True)
|
50 |
-
|
51 |
def get_current_style(self):
|
52 |
theme_style = self.dark_style if st.session_state.theme == "dark" else self.light_style
|
53 |
return f"<style>{self.base_style}{theme_style}</style>"
|
54 |
|
55 |
-
|
56 |
-
def save_feedback(feedback_type, user_input, assistant_response):
|
57 |
-
feedback_dir = os.path.join(os.getcwd(), "feedback")
|
58 |
-
|
59 |
-
if not os.path.exists(feedback_dir):
|
60 |
-
os.makedirs(feedback_dir)
|
61 |
-
|
62 |
-
filename = os.path.join(feedback_dir, f"feedback_{feedback_type}.json")
|
63 |
-
|
64 |
-
try:
|
65 |
-
data = []
|
66 |
-
if os.path.exists(filename):
|
67 |
-
with open(filename, 'r', encoding='utf-8') as f:
|
68 |
-
data = json.load(f)
|
69 |
-
|
70 |
-
data.append({
|
71 |
-
"user_input": user_input,
|
72 |
-
"assistant_response": assistant_response,
|
73 |
-
"timestamp": datetime.now().isoformat()
|
74 |
-
})
|
75 |
-
|
76 |
-
with open(filename, 'w', encoding='utf-8') as f:
|
77 |
-
json.dump(data, f, ensure_ascii=False, indent=2)
|
78 |
-
|
79 |
-
st.toast(f"Feedback {feedback_type} salvo com sucesso!", icon="✅")
|
80 |
-
except Exception as e:
|
81 |
-
st.toast(f"Erro ao salvar feedback: {str(e)}", icon="❌")
|
82 |
-
|
83 |
def stream_chat(self, user_input):
|
84 |
"""
|
85 |
Faz a comunicação com o backend e retorna a resposta como streaming de tokens.
|
@@ -102,43 +79,34 @@ class ChatbotApp:
|
|
102 |
def clear_chat_history(self):
|
103 |
st.session_state.chat_history = []
|
104 |
st.toast("Histórico limpo com sucesso!", icon="✅")
|
105 |
-
|
106 |
def render_sidebar(self):
|
107 |
"""Siderbar"""
|
108 |
with st.sidebar:
|
109 |
-
|
110 |
-
|
111 |
-
st.rerun()
|
112 |
-
if st.session_state.theme == "light":
|
113 |
st.logo("./logos/sicoob-logo-horizontal-light.png", icon_image="./logos/sicoob-logo-vertical-sm.png")
|
114 |
else:
|
115 |
st.logo("./logos/sicoob-logo-horizontal-dark.png", icon_image="./logos/sicoob-logo-vertical-sm.png")
|
116 |
-
|
117 |
if st.button("Limpar Histórico", icon=":material/delete:"):
|
118 |
self.clear_chat_history()
|
119 |
-
|
120 |
-
if st.button("Atualizações", icon=":material/info:"):
|
121 |
-
self.changelog_user()
|
122 |
st.divider()
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
|
|
|
|
128 |
def render(self):
|
129 |
-
|
130 |
"""
|
131 |
Renderiza a interface do chatbot.
|
132 |
-
"""
|
133 |
-
|
134 |
st.markdown(self.get_current_style(), unsafe_allow_html=True)
|
135 |
-
|
136 |
with open(self.configyml) as file:
|
137 |
config = yaml.load(file, Loader=SafeLoader)
|
138 |
|
139 |
-
# Pre-hashing all plain text passwords once
|
140 |
-
# stauth.Hasher.hash_passwords(config['credentials'])
|
141 |
-
|
142 |
authenticator = stauth.Authenticate(
|
143 |
config['credentials'],
|
144 |
config['cookie']['name'],
|
@@ -146,32 +114,21 @@ class ChatbotApp:
|
|
146 |
config['cookie']['expiry_days']
|
147 |
)
|
148 |
|
149 |
-
#try:
|
150 |
-
# authenticator.login()
|
151 |
-
#except Exception as e:
|
152 |
-
# st.error(e)
|
153 |
-
def add_link_to_text(text):
|
154 |
-
return re.sub(r'\|\|(.*?)\|\|', lambda match: f' <br>Fonte: <a href="{search_file_in_drive(match.group(1))}" target="_blank">{match.group(1)}</a>', text)
|
155 |
-
|
156 |
-
|
157 |
with open('./config.yaml', 'w', encoding='utf-8') as file:
|
158 |
yaml.dump(config, file, default_flow_style=False)
|
159 |
|
160 |
-
|
161 |
-
authentication_status = authenticator.login()
|
162 |
|
163 |
if st.session_state["authentication_status"]:
|
164 |
-
|
165 |
# Renderiza a barra lateral
|
166 |
self.render_sidebar()
|
167 |
|
168 |
# Título e descrição
|
169 |
st.title(self.title)
|
170 |
st.write(self.description)
|
171 |
-
|
172 |
with st.sidebar:
|
|
|
173 |
authenticator.logout('Sair', 'main')
|
174 |
-
|
175 |
# Inicializa o histórico na sessão
|
176 |
if "chat_history" not in st.session_state:
|
177 |
st.session_state.chat_history = []
|
@@ -180,7 +137,7 @@ class ChatbotApp:
|
|
180 |
for message in st.session_state.chat_history:
|
181 |
role, text = message.split(":", 1)
|
182 |
with st.chat_message(role.strip().lower()):
|
183 |
-
|
184 |
|
185 |
# Captura o input do usuário
|
186 |
user_input = st.chat_input("Digite sua pergunta")
|
@@ -189,35 +146,37 @@ class ChatbotApp:
|
|
189 |
with st.chat_message("user"):
|
190 |
st.write(user_input)
|
191 |
st.session_state.chat_history.append(f"user: {user_input}")
|
192 |
-
|
193 |
# Placeholder para a resposta do assistente
|
194 |
with st.chat_message("assistant"):
|
195 |
message_placeholder = st.empty()
|
196 |
assistant_message = ""
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
|
|
|
|
217 |
elif st.session_state["authentication_status"] == False:
|
218 |
-
st.error('
|
219 |
elif st.session_state["authentication_status"] == None:
|
220 |
-
st.warning('Por favor entre com seu
|
|
|
221 |
|
222 |
if __name__ == "__main__":
|
223 |
chatbot_app = ChatbotApp()
|
|
|
1 |
import streamlit as st
|
2 |
import requests
|
|
|
|
|
3 |
import re
|
4 |
import streamlit_authenticator as stauth
|
|
|
5 |
import os
|
6 |
import yaml
|
7 |
from yaml.loader import SafeLoader
|
8 |
from pathlib import Path
|
9 |
+
from drive_search import search_file_in_drive
|
10 |
from datetime import datetime
|
11 |
+
from feedback_manager import FeedbackManager
|
12 |
+
|
13 |
|
14 |
class ChatbotApp:
|
15 |
def __init__(self):
|
16 |
# Configura título, ícone e layout da página
|
17 |
st.set_page_config(page_title="Sicoob Chatbot 🤖", page_icon="logos/sicoob-ico.ico", layout="wide")
|
|
|
18 |
self.backend_url = "http://localhost:5001/chat"
|
19 |
self.title = "Sicoob Chatbot"
|
20 |
+
self.description = "Este assistente virtual pode te ajudar com informações sobre documentos da Sicoob."
|
21 |
+
self.caption = "Confira as atualizações no botão 'Atualizações'."
|
|
|
22 |
self.style_dir = Path("./logos/styles")
|
23 |
self.load_styles()
|
24 |
+
self.feedback_manager = FeedbackManager()
|
25 |
st.session_state.first = False
|
|
|
26 |
if "theme" not in st.session_state:
|
27 |
st.session_state.theme = "light"
|
|
|
28 |
self.configyml = os.path.join(os.getcwd(), "./files/config.yaml")
|
29 |
+
if "feedback_submitted" not in st.session_state:
|
30 |
+
st.session_state.feedback_submitted = set()
|
31 |
|
32 |
def load_styles(self):
|
33 |
try:
|
|
|
40 |
self.light_style = ""
|
41 |
self.dark_style = ""
|
42 |
|
43 |
+
def change_style(self):
|
44 |
+
with st.sidebar:
|
45 |
+
if st.session_state.theme == "light":
|
46 |
+
st.logo("./logos/sicoob-logo-horizontal-light.png", icon_image="./logos/sicoob-logo-vertical-sm.png")
|
47 |
+
else:
|
48 |
+
st.logo("./logos/sicoob-logo-horizontal-dark.png", icon_image="./logos/sicoob-logo-vertical-sm.png")
|
49 |
+
st.session_state.theme = "dark" if st.session_state.theme == "light" else "light"
|
50 |
+
|
51 |
@st.dialog("📄 Atualizações Sicoob Chatbot", width="small")
|
52 |
def changelog_user(self):
|
53 |
with open("./logos/ChangelogUser.md", encoding="utf-8") as f:
|
54 |
st.markdown(f"{f.read()}", unsafe_allow_html=True)
|
55 |
+
|
56 |
def get_current_style(self):
|
57 |
theme_style = self.dark_style if st.session_state.theme == "dark" else self.light_style
|
58 |
return f"<style>{self.base_style}{theme_style}</style>"
|
59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
def stream_chat(self, user_input):
|
61 |
"""
|
62 |
Faz a comunicação com o backend e retorna a resposta como streaming de tokens.
|
|
|
79 |
def clear_chat_history(self):
|
80 |
st.session_state.chat_history = []
|
81 |
st.toast("Histórico limpo com sucesso!", icon="✅")
|
82 |
+
|
83 |
def render_sidebar(self):
|
84 |
"""Siderbar"""
|
85 |
with st.sidebar:
|
86 |
+
st.button("Light/Dark Mode", on_click=self.change_style)
|
87 |
+
if st.session_state.theme == "light":
|
|
|
|
|
88 |
st.logo("./logos/sicoob-logo-horizontal-light.png", icon_image="./logos/sicoob-logo-vertical-sm.png")
|
89 |
else:
|
90 |
st.logo("./logos/sicoob-logo-horizontal-dark.png", icon_image="./logos/sicoob-logo-vertical-sm.png")
|
|
|
91 |
if st.button("Limpar Histórico", icon=":material/delete:"):
|
92 |
self.clear_chat_history()
|
93 |
+
st.button("Atualizações", icon=":material/info:", on_click=self.changelog_user)
|
|
|
|
|
94 |
st.divider()
|
95 |
+
|
96 |
+
def add_link_to_text(self, text):
|
97 |
+
"""
|
98 |
+
Adiciona links ao texto com base no padrão ||texto||.
|
99 |
+
"""
|
100 |
+
return re.sub(r'\|\|(.*?)\|\|', lambda match: f' <br>Fonte: <a href="{search_file_in_drive(match.group(1))}" target="_blank">{match.group(1)}</a>', text)
|
101 |
+
|
102 |
def render(self):
|
|
|
103 |
"""
|
104 |
Renderiza a interface do chatbot.
|
105 |
+
"""
|
|
|
106 |
st.markdown(self.get_current_style(), unsafe_allow_html=True)
|
|
|
107 |
with open(self.configyml) as file:
|
108 |
config = yaml.load(file, Loader=SafeLoader)
|
109 |
|
|
|
|
|
|
|
110 |
authenticator = stauth.Authenticate(
|
111 |
config['credentials'],
|
112 |
config['cookie']['name'],
|
|
|
114 |
config['cookie']['expiry_days']
|
115 |
)
|
116 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
with open('./config.yaml', 'w', encoding='utf-8') as file:
|
118 |
yaml.dump(config, file, default_flow_style=False)
|
119 |
|
120 |
+
authentication_status = authenticator.login(fields={'Form name': 'Autenticação', 'Username': 'Nome de Usuário', 'Password': 'Senha', 'Login': 'Entrar'})
|
|
|
121 |
|
122 |
if st.session_state["authentication_status"]:
|
|
|
123 |
# Renderiza a barra lateral
|
124 |
self.render_sidebar()
|
125 |
|
126 |
# Título e descrição
|
127 |
st.title(self.title)
|
128 |
st.write(self.description)
|
|
|
129 |
with st.sidebar:
|
130 |
+
st.caption(self.caption)
|
131 |
authenticator.logout('Sair', 'main')
|
|
|
132 |
# Inicializa o histórico na sessão
|
133 |
if "chat_history" not in st.session_state:
|
134 |
st.session_state.chat_history = []
|
|
|
137 |
for message in st.session_state.chat_history:
|
138 |
role, text = message.split(":", 1)
|
139 |
with st.chat_message(role.strip().lower()):
|
140 |
+
st.markdown(text.strip(), unsafe_allow_html=True)
|
141 |
|
142 |
# Captura o input do usuário
|
143 |
user_input = st.chat_input("Digite sua pergunta")
|
|
|
146 |
with st.chat_message("user"):
|
147 |
st.write(user_input)
|
148 |
st.session_state.chat_history.append(f"user: {user_input}")
|
|
|
149 |
# Placeholder para a resposta do assistente
|
150 |
with st.chat_message("assistant"):
|
151 |
message_placeholder = st.empty()
|
152 |
assistant_message = ""
|
153 |
+
try:
|
154 |
+
# Gerando ID único para a mensagem
|
155 |
+
message_id = datetime.now().strftime("%Y%m%d_%H%M%S_%f")
|
156 |
+
print(f"Message ID gerado: {message_id}")
|
157 |
+
# Executa o streaming de tokens enquanto o backend responde
|
158 |
+
for token in self.stream_chat(user_input):
|
159 |
+
assistant_message += token
|
160 |
+
message_placeholder.markdown(assistant_message + "▌", unsafe_allow_html=True)
|
161 |
+
except Exception as e:
|
162 |
+
st.error(f"Erro durante o chat: {str(e)}")
|
163 |
+
print(f"Erro durante o chat: {str(e)}")
|
164 |
+
finally:
|
165 |
+
assistant_message_with_link = self.add_link_to_text(assistant_message)
|
166 |
+
message_placeholder.markdown(assistant_message_with_link, unsafe_allow_html=True)
|
167 |
+
# Feedback
|
168 |
+
self.feedback_manager.render_feedback_buttons(
|
169 |
+
message_id=message_id,
|
170 |
+
user_input=user_input,
|
171 |
+
assistant_response=assistant_message_with_link
|
172 |
+
)
|
173 |
+
# Adicionando histórico Streamlit
|
174 |
+
st.session_state.chat_history.append(f"assistant: {assistant_message_with_link}")
|
175 |
elif st.session_state["authentication_status"] == False:
|
176 |
+
st.error('Nome de Usuário/Senha incorreta.')
|
177 |
elif st.session_state["authentication_status"] == None:
|
178 |
+
st.warning('Por favor entre com seu nome de usuário e senha.')
|
179 |
+
|
180 |
|
181 |
if __name__ == "__main__":
|
182 |
chatbot_app = ChatbotApp()
|
feedback_manager.py
ADDED
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
from datetime import datetime
|
3 |
+
from pathlib import Path
|
4 |
+
import streamlit as st
|
5 |
+
|
6 |
+
|
7 |
+
class FeedbackManager:
|
8 |
+
def __init__(self, feedback_dir="./feedback"):
|
9 |
+
self.feedback_dir = Path(feedback_dir)
|
10 |
+
self.feedback_dir.mkdir(exist_ok=True)
|
11 |
+
if "feedback_submitted" not in st.session_state:
|
12 |
+
st.session_state.feedback_submitted = set()
|
13 |
+
|
14 |
+
def save_feedback(self, feedback_type: str, user_input: str, assistant_response: str, message_id: str):
|
15 |
+
if message_id in st.session_state.feedback_submitted:
|
16 |
+
st.toast("Feedback já enviado para está mensagem.", icon="ℹ️")
|
17 |
+
return False
|
18 |
+
feedback_file = self.feedback_dir / f"feedback_{feedback_type}.json"
|
19 |
+
try:
|
20 |
+
data = []
|
21 |
+
if feedback_file.exists():
|
22 |
+
with open(feedback_file, 'r', encoding='utf-8') as f:
|
23 |
+
data = json.load(f)
|
24 |
+
feedback_entry = {
|
25 |
+
"message_id": message_id,
|
26 |
+
"timestamp": datetime.now().isoformat(),
|
27 |
+
"feedback_type": feedback_type,
|
28 |
+
"user_input": user_input,
|
29 |
+
"assistant_response": assistant_response,
|
30 |
+
}
|
31 |
+
data.append(feedback_entry)
|
32 |
+
with open(feedback_file, 'w', encoding='utf-8') as f:
|
33 |
+
json.dump(data, f, ensure_ascii=False, indent=2)
|
34 |
+
st.session_state.feedback_submitted.add(message_id)
|
35 |
+
emoji = "👍" if feedback_type == "positive" else "👎"
|
36 |
+
st.toast(f"Obrigado por seu Feedback! {emoji}", icon="✅")
|
37 |
+
return True
|
38 |
+
except Exception as e:
|
39 |
+
st.error(f"Error ao salvar feedback: {str(e)}")
|
40 |
+
return False
|
41 |
+
|
42 |
+
def handle_feedback_click(self, feedback_type: str, message_id: str, user_input: str, assistant_response: str):
|
43 |
+
self.save_feedback(
|
44 |
+
feedback_type=feedback_type,
|
45 |
+
user_input=user_input,
|
46 |
+
assistant_response=assistant_response,
|
47 |
+
message_id=message_id
|
48 |
+
)
|
49 |
+
|
50 |
+
def render_feedback_buttons(self, message_id: str, user_input: str, assistant_response: str):
|
51 |
+
col1, col2 = st.columns(2, gap="small")
|
52 |
+
|
53 |
+
with col1:
|
54 |
+
st.button(
|
55 |
+
"👍 Gostei",
|
56 |
+
key=f"positive_{message_id}",
|
57 |
+
on_click=self.handle_feedback_click,
|
58 |
+
args=("positive", message_id, user_input, assistant_response)
|
59 |
+
)
|
60 |
+
|
61 |
+
with col2:
|
62 |
+
st.button(
|
63 |
+
"👎 Não Gostei",
|
64 |
+
key=f"negative_{message_id}",
|
65 |
+
on_click=self.handle_feedback_click,
|
66 |
+
args=("negative", message_id, user_input, assistant_response)
|
67 |
+
)
|
logos/styles/base.css
CHANGED
@@ -53,4 +53,15 @@ a {
|
|
53 |
|
54 |
.stButton button {
|
55 |
margin-right: 5px;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
}
|
|
|
53 |
|
54 |
.stButton button {
|
55 |
margin-right: 5px;
|
56 |
+
}
|
57 |
+
|
58 |
+
[data-testid="stDialog"] > div > div > div > div {
|
59 |
+
max-height: 400px !important;
|
60 |
+
overflow: scroll;
|
61 |
+
}
|
62 |
+
|
63 |
+
[data-testid="stExpanderIcon"] {
|
64 |
+
font-family: "Material Symbols Rounded" !important;
|
65 |
+
font-weight: 400;
|
66 |
+
font-style: normal;
|
67 |
}
|
logos/styles/dark.css
CHANGED
@@ -1,9 +1,18 @@
|
|
1 |
.stMain, .stAppHeader, .st-emotion-cache-hzygls {
|
2 |
-
background-color: #003641;
|
3 |
}
|
4 |
|
5 |
.stAppHeader, .st-emotion-cache-hzygls, .stBottomBlockContainer {
|
6 |
-
background-color: #002025;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
}
|
8 |
|
9 |
.stSidebar {
|
@@ -44,6 +53,7 @@
|
|
44 |
|
45 |
[data-testid="stChatInput"] > div > div {
|
46 |
border: none;
|
|
|
47 |
}
|
48 |
|
49 |
[data-testid="stChatInput"] > div > div > div > textarea {
|
@@ -67,6 +77,14 @@ a:hover {
|
|
67 |
color: #7DB61C !important;
|
68 |
}
|
69 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
[data-testid="stChatMessageAvatarUser"] {
|
71 |
fill: #7DB61C !important;
|
72 |
background-color: #7DB61C !important;
|
@@ -100,17 +118,15 @@ a:hover {
|
|
100 |
}
|
101 |
|
102 |
hr {
|
103 |
-
background-color: #FAFAFA;
|
104 |
}
|
105 |
|
106 |
[data-testid="stDialog"] > div > div > div > div {
|
107 |
-
max-height: 550px !important;
|
108 |
-
overflow: scroll;
|
109 |
color: #002025 !important;
|
110 |
}
|
111 |
|
112 |
[data-testid="stDialog"] > div > div > div {
|
113 |
-
background-color: #00AE9D;
|
114 |
border-top-left-radius: 0px;
|
115 |
border-top-right-radius: 0px;
|
116 |
border-bottom-left-radius: 10px;
|
@@ -123,9 +139,18 @@ hr {
|
|
123 |
}
|
124 |
|
125 |
[data-testid="stDialog"] > div > div > div:first-child {
|
126 |
-
background-color: #002530;
|
127 |
border-top-left-radius: 10px;
|
128 |
border-top-right-radius: 10px;
|
129 |
border-bottom-left-radius: 0;
|
130 |
border-bottom-right-radius: 0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
}
|
|
|
1 |
.stMain, .stAppHeader, .st-emotion-cache-hzygls {
|
2 |
+
background-color: #003641 !important;
|
3 |
}
|
4 |
|
5 |
.stAppHeader, .st-emotion-cache-hzygls, .stBottomBlockContainer {
|
6 |
+
background-color: #002025 !important;
|
7 |
+
}
|
8 |
+
|
9 |
+
[data-testid="stChatInputSubmitButton"] {
|
10 |
+
background-color: transparent !important;
|
11 |
+
border-radius: 10px;
|
12 |
+
}
|
13 |
+
|
14 |
+
[data-testid="stChatInputSubmitButton"]:hover {
|
15 |
+
background-color: #002025 !important;
|
16 |
}
|
17 |
|
18 |
.stSidebar {
|
|
|
53 |
|
54 |
[data-testid="stChatInput"] > div > div {
|
55 |
border: none;
|
56 |
+
border-radius: 10px;
|
57 |
}
|
58 |
|
59 |
[data-testid="stChatInput"] > div > div > div > textarea {
|
|
|
77 |
color: #7DB61C !important;
|
78 |
}
|
79 |
|
80 |
+
.stMarkdown h1 {
|
81 |
+
color: #FAFAFA !important
|
82 |
+
}
|
83 |
+
|
84 |
+
body, .stMarkdown, .stText, .stTitle, .stHeader, .stSubheader {
|
85 |
+
color: #FAFAFA !important
|
86 |
+
}
|
87 |
+
|
88 |
[data-testid="stChatMessageAvatarUser"] {
|
89 |
fill: #7DB61C !important;
|
90 |
background-color: #7DB61C !important;
|
|
|
118 |
}
|
119 |
|
120 |
hr {
|
121 |
+
background-color: #FAFAFA !important;
|
122 |
}
|
123 |
|
124 |
[data-testid="stDialog"] > div > div > div > div {
|
|
|
|
|
125 |
color: #002025 !important;
|
126 |
}
|
127 |
|
128 |
[data-testid="stDialog"] > div > div > div {
|
129 |
+
background-color: #00AE9D !important;
|
130 |
border-top-left-radius: 0px;
|
131 |
border-top-right-radius: 0px;
|
132 |
border-bottom-left-radius: 10px;
|
|
|
139 |
}
|
140 |
|
141 |
[data-testid="stDialog"] > div > div > div:first-child {
|
142 |
+
background-color: #002530 !important;
|
143 |
border-top-left-radius: 10px;
|
144 |
border-top-right-radius: 10px;
|
145 |
border-bottom-left-radius: 0;
|
146 |
border-bottom-right-radius: 0;
|
147 |
+
}
|
148 |
+
|
149 |
+
[data-testid="stBaseButton-borderlessIcon"] {
|
150 |
+
color: #49479D;
|
151 |
+
}
|
152 |
+
|
153 |
+
.stChatMessage:has([data-testid="stChatMessageAvatarUser"]) {
|
154 |
+
background-color: #002530 !important;
|
155 |
+
border-radius: 10px;
|
156 |
}
|
logos/styles/light.css
CHANGED
@@ -1,9 +1,18 @@
|
|
1 |
.stMain, .stAppHeader, .st-emotion-cache-hzygls {
|
2 |
-
background-color: #FAFAFA;
|
3 |
}
|
4 |
|
5 |
.stAppHeader, .st-emotion-cache-hzygls, .stBottomBlockContainer {
|
6 |
-
background-color: #00AE9D ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
}
|
8 |
|
9 |
.stSidebar {
|
@@ -13,7 +22,7 @@
|
|
13 |
}
|
14 |
|
15 |
.stHeading {
|
16 |
-
color: #003641;
|
17 |
}
|
18 |
|
19 |
[data-testid="stChatInputSubmitButton"] > svg {
|
@@ -49,13 +58,14 @@
|
|
49 |
|
50 |
[data-testid="stChatInput"] > div > div {
|
51 |
border: none;
|
|
|
52 |
}
|
53 |
|
54 |
[data-testid="stChatInput"] > div > div > div > textarea {
|
55 |
background-color: #003641;
|
56 |
border-radius: 10px;
|
57 |
border: 1px solid #C9D200;
|
58 |
-
color: #FAFAFA;
|
59 |
}
|
60 |
|
61 |
[data-testid="stChatInput"] > div > div > div > textarea:focus {
|
@@ -74,11 +84,11 @@ a:hover {
|
|
74 |
}
|
75 |
|
76 |
.stMarkdown h1 {
|
77 |
-
color: #003641
|
78 |
}
|
79 |
|
80 |
body, .stMarkdown, .stText, .stTitle, .stHeader, .stSubheader {
|
81 |
-
color: #003641
|
82 |
}
|
83 |
|
84 |
[data-testid="stChatMessageAvatarUser"] {
|
@@ -108,7 +118,7 @@ body, .stMarkdown, .stText, .stTitle, .stHeader, .stSubheader {
|
|
108 |
}
|
109 |
|
110 |
.stMarkdown hr {
|
111 |
-
background-color: #002530;
|
112 |
}
|
113 |
|
114 |
.stSidebarHeader > div > button {
|
@@ -132,8 +142,7 @@ body, .stMarkdown, .stText, .stTitle, .stHeader, .stSubheader {
|
|
132 |
}
|
133 |
|
134 |
.stChatMessage:has([data-testid="stChatMessageAvatarUser"]) {
|
135 |
-
background-color: #ebebeb;
|
136 |
-
color: #FAFAFA;
|
137 |
border-radius: 10px;
|
138 |
}
|
139 |
|
@@ -148,8 +157,7 @@ body, .stMarkdown, .stText, .stTitle, .stHeader, .stSubheader {
|
|
148 |
}
|
149 |
|
150 |
[data-testid="stDialog"] > div > div > div > div {
|
151 |
-
|
152 |
-
overflow: scroll;
|
153 |
}
|
154 |
|
155 |
[data-testid="stDialog"] > div > div > div {
|
@@ -170,9 +178,41 @@ body, .stMarkdown, .stText, .stTitle, .stHeader, .stSubheader {
|
|
170 |
|
171 |
|
172 |
[data-testid="stAlertContainer"] p {
|
173 |
-
color: #002530;
|
174 |
}
|
175 |
|
176 |
.stTextInput > label {
|
177 |
-
color: #002530;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
}
|
|
|
|
|
|
|
|
|
|
1 |
.stMain, .stAppHeader, .st-emotion-cache-hzygls {
|
2 |
+
background-color: #FAFAFA !important;
|
3 |
}
|
4 |
|
5 |
.stAppHeader, .st-emotion-cache-hzygls, .stBottomBlockContainer {
|
6 |
+
background-color: #00AE9D !important;
|
7 |
+
}
|
8 |
+
|
9 |
+
[data-testid="stChatInputSubmitButton"] {
|
10 |
+
background-color: transparent !important;
|
11 |
+
border-radius: 10px;
|
12 |
+
}
|
13 |
+
|
14 |
+
[data-testid="stChatInputSubmitButton"]:hover {
|
15 |
+
background-color: #00AE9D !important;
|
16 |
}
|
17 |
|
18 |
.stSidebar {
|
|
|
22 |
}
|
23 |
|
24 |
.stHeading {
|
25 |
+
color: #003641 !important;
|
26 |
}
|
27 |
|
28 |
[data-testid="stChatInputSubmitButton"] > svg {
|
|
|
58 |
|
59 |
[data-testid="stChatInput"] > div > div {
|
60 |
border: none;
|
61 |
+
border-radius: 10px;
|
62 |
}
|
63 |
|
64 |
[data-testid="stChatInput"] > div > div > div > textarea {
|
65 |
background-color: #003641;
|
66 |
border-radius: 10px;
|
67 |
border: 1px solid #C9D200;
|
68 |
+
color: #FAFAFA !important;
|
69 |
}
|
70 |
|
71 |
[data-testid="stChatInput"] > div > div > div > textarea:focus {
|
|
|
84 |
}
|
85 |
|
86 |
.stMarkdown h1 {
|
87 |
+
color: #003641 !important
|
88 |
}
|
89 |
|
90 |
body, .stMarkdown, .stText, .stTitle, .stHeader, .stSubheader {
|
91 |
+
color: #003641 !important
|
92 |
}
|
93 |
|
94 |
[data-testid="stChatMessageAvatarUser"] {
|
|
|
118 |
}
|
119 |
|
120 |
.stMarkdown hr {
|
121 |
+
background-color: #002530 !important;
|
122 |
}
|
123 |
|
124 |
.stSidebarHeader > div > button {
|
|
|
142 |
}
|
143 |
|
144 |
.stChatMessage:has([data-testid="stChatMessageAvatarUser"]) {
|
145 |
+
background-color: #ebebeb !important;
|
|
|
146 |
border-radius: 10px;
|
147 |
}
|
148 |
|
|
|
157 |
}
|
158 |
|
159 |
[data-testid="stDialog"] > div > div > div > div {
|
160 |
+
background-color: #00AE9D;
|
|
|
161 |
}
|
162 |
|
163 |
[data-testid="stDialog"] > div > div > div {
|
|
|
178 |
|
179 |
|
180 |
[data-testid="stAlertContainer"] p {
|
181 |
+
color: #002530 !important;
|
182 |
}
|
183 |
|
184 |
.stTextInput > label {
|
185 |
+
color: #002530 !important;
|
186 |
+
}
|
187 |
+
|
188 |
+
[data-testid="stTextInputRootElement"] > div {
|
189 |
+
background-color: transparent;
|
190 |
+
}
|
191 |
+
|
192 |
+
[data-testid="stTextInputRootElement"] {
|
193 |
+
background-color: #003641;
|
194 |
+
border-radius: 10px;
|
195 |
+
border: 1px solid #C9D200;
|
196 |
+
color: #FAFAFA;
|
197 |
+
}
|
198 |
+
|
199 |
+
.stFormSubmitButton > button {
|
200 |
+
background-color: #003641;
|
201 |
+
color: #FAFAFA;
|
202 |
+
}
|
203 |
+
|
204 |
+
.stFormSubmitButton > button:hover {
|
205 |
+
background-color: #003641;
|
206 |
+
border-color: #7DB61C;
|
207 |
+
color: #C9D200;
|
208 |
+
}
|
209 |
+
|
210 |
+
.stFormSubmitButton > button:active , .stFormSubmitButton > button:focus, .stFormSubmitButton > button:focus-visible, .stFormSubmitButton > button:focus:not(:active) {
|
211 |
+
background-color: #7DB61C;
|
212 |
+
border-color: #003641;
|
213 |
+
color: #FAFAFA;
|
214 |
}
|
215 |
+
|
216 |
+
[data-testid="stBaseButton-borderlessIcon"] {
|
217 |
+
color: #7DB61C;
|
218 |
+
}
|