Spaces:
Sleeping
Sleeping
Update main.py
Browse files
main.py
CHANGED
|
@@ -1,22 +1,93 @@
|
|
| 1 |
import streamlit as st
|
| 2 |
import time
|
| 3 |
-
from utils import tarot, prompts, llm, calculations, lang
|
| 4 |
|
| 5 |
# --- [1. ์ฑ ์ค์ ] ---
|
| 6 |
-
st.set_page_config(page_title="
|
| 7 |
|
| 8 |
-
# --- [2. ํ
๋ง ์คํ์ผ๋ง
|
| 9 |
def apply_theme(mode):
|
| 10 |
-
#
|
| 11 |
-
# ํฐํธ ๋ก๋ ๋ถ๋ถ๋ง ์กฐ๊ธ ๋ณด๊ฐํด์ ๋ค๊ตญ์ด ์ง์ํ๊ฒ
|
| 12 |
st.markdown("""
|
| 13 |
<style>
|
| 14 |
-
@import url('https://fonts.googleapis.com/css2?family=Nanum+Myeongjo:wght@700&family=Noto+Serif+SC:wght@600&family=Noto+Serif+JP:wght@600&family=Nanum+Pen+Script&display=swap');
|
| 15 |
</style>
|
| 16 |
""", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
-
|
| 19 |
-
|
| 20 |
|
| 21 |
# --- [3. ์ํ ์ด๊ธฐํ] ---
|
| 22 |
if "messages" not in st.session_state: st.session_state.messages = []
|
|
@@ -32,13 +103,11 @@ current_lang = st.sidebar.selectbox(
|
|
| 32 |
["ํ๊ตญ์ด", "English", "ไธญๆ", "ๆฅๆฌ่ช"],
|
| 33 |
label_visibility="collapsed"
|
| 34 |
)
|
| 35 |
-
|
| 36 |
-
TXT = lang.STRINGS[current_lang]
|
| 37 |
|
| 38 |
-
# --- [4. ๋ชจ๋ ์ ํ
|
| 39 |
st.sidebar.title(TXT["sidebar_title"])
|
| 40 |
|
| 41 |
-
# ํ๋ฅด์๋ ์ด๋ฆ๋ ์ธ์ด๋ณ๋ก ๋ณด์ฌ์ฃผ๊ธฐ
|
| 42 |
def get_persona_name(key):
|
| 43 |
return TXT["personas"][key]
|
| 44 |
|
|
@@ -48,11 +117,11 @@ selected_mode = st.sidebar.radio(
|
|
| 48 |
format_func=get_persona_name
|
| 49 |
)
|
| 50 |
|
|
|
|
| 51 |
apply_theme(selected_mode)
|
| 52 |
current_persona = prompts.get_persona(selected_mode)
|
| 53 |
|
| 54 |
st.sidebar.markdown("---")
|
| 55 |
-
# ์ค๋ช
๋ ๋ฒ์ญ๋ ๊ฑธ๋ก ํ์
|
| 56 |
st.sidebar.info(TXT["desc"][selected_mode])
|
| 57 |
|
| 58 |
# --- [5. ๋ฉ์ธ UI ๋ก์ง] ---
|
|
@@ -60,28 +129,32 @@ st.title(f"{current_persona['icon']} {get_persona_name(selected_mode)}")
|
|
| 60 |
st.markdown("---")
|
| 61 |
|
| 62 |
# ==========================================
|
| 63 |
-
# ๐ ๋ชจ๋ A: ํ๋ก
|
| 64 |
# ==========================================
|
| 65 |
if selected_mode == "tarot":
|
|
|
|
| 66 |
if st.session_state.tarot_stage == "input":
|
| 67 |
with st.form("tarot_form"):
|
| 68 |
-
|
|
|
|
| 69 |
submitted = st.form_submit_button(TXT["btn_submit"])
|
| 70 |
|
| 71 |
if submitted and query:
|
| 72 |
-
st.session_state.user_query = query
|
| 73 |
st.session_state.tarot_stage = "picking"
|
| 74 |
st.rerun()
|
| 75 |
|
|
|
|
| 76 |
elif st.session_state.tarot_stage == "picking":
|
| 77 |
-
st.info(f"
|
| 78 |
-
if st.button("
|
| 79 |
with st.spinner(TXT["loading"]):
|
| 80 |
time.sleep(1.5)
|
| 81 |
st.session_state.picked_cards = tarot.draw_tarot_cards(3)
|
| 82 |
st.session_state.tarot_stage = "result"
|
| 83 |
st.rerun()
|
| 84 |
|
|
|
|
| 85 |
elif st.session_state.tarot_stage == "result":
|
| 86 |
cols = st.columns(3)
|
| 87 |
for idx, card in enumerate(st.session_state.picked_cards):
|
|
@@ -90,37 +163,41 @@ if selected_mode == "tarot":
|
|
| 90 |
|
| 91 |
if "ai_response" not in st.session_state:
|
| 92 |
with st.spinner(TXT["analyzing"]):
|
| 93 |
-
# ์ธ์ด ์ ๋ณด(current_lang)๋ฅผ ํจ๊ป ๋๊น
|
| 94 |
st.session_state.ai_response = llm.get_ai_response(
|
| 95 |
st.session_state.user_query,
|
| 96 |
current_persona,
|
| 97 |
st.session_state.picked_cards,
|
| 98 |
-
user_lang=current_lang
|
| 99 |
)
|
|
|
|
| 100 |
st.subheader(TXT["result_title"])
|
| 101 |
st.markdown(st.session_state.ai_response)
|
| 102 |
|
| 103 |
-
if st.button("
|
| 104 |
st.session_state.tarot_stage = "input"
|
| 105 |
del st.session_state["ai_response"]
|
| 106 |
st.rerun()
|
| 107 |
|
| 108 |
# ==========================================
|
| 109 |
-
# ๐ก ๋ชจ๋ B: ํ์์ง๋ฆฌ
|
| 110 |
# ==========================================
|
| 111 |
elif selected_mode == "fengshui":
|
| 112 |
with st.container():
|
|
|
|
| 113 |
c1, c2 = st.columns(2)
|
| 114 |
with c1:
|
| 115 |
-
birth_year = st.number_input("
|
| 116 |
-
|
|
|
|
|
|
|
| 117 |
with c2:
|
| 118 |
-
direction = st.selectbox("
|
| 119 |
|
| 120 |
if prompt := st.chat_input(TXT["input_label"]):
|
| 121 |
-
|
|
|
|
| 122 |
|
| 123 |
-
#
|
| 124 |
sys_msg = f"[Data]: {fengshui_data}, Current Door: {direction}"
|
| 125 |
full_query = f"{sys_msg}\nUser Question: {prompt}"
|
| 126 |
|
|
@@ -131,19 +208,22 @@ elif selected_mode == "fengshui":
|
|
| 131 |
st.write(response)
|
| 132 |
|
| 133 |
# ==========================================
|
| 134 |
-
# ๐น ๋ชจ๋ C: ์ ์
|
| 135 |
# ==========================================
|
| 136 |
elif selected_mode == "shaman":
|
| 137 |
with st.container():
|
|
|
|
| 138 |
c1, c2 = st.columns(2)
|
| 139 |
with c1:
|
| 140 |
-
birth_year = st.number_input("
|
| 141 |
with c2:
|
| 142 |
prompt_input = st.text_input(TXT["input_label"])
|
| 143 |
|
| 144 |
if st.button(TXT["btn_submit"]) and prompt_input:
|
|
|
|
| 145 |
saju_data = calculations.get_ganji(birth_year)
|
| 146 |
|
|
|
|
| 147 |
sys_msg = f"[Saju Data]: Year {saju_data['year_ganji']}, Element {saju_data['element']}"
|
| 148 |
full_query = f"{sys_msg}\nUser Worry: {prompt_input}"
|
| 149 |
|
|
@@ -152,4 +232,7 @@ elif selected_mode == "shaman":
|
|
| 152 |
with st.chat_message("assistant"):
|
| 153 |
with st.spinner(TXT["loading"]):
|
| 154 |
response = llm.get_ai_response(full_query, current_persona, user_lang=current_lang)
|
| 155 |
-
st.markdown(response)
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import streamlit as st
|
| 2 |
import time
|
| 3 |
+
from utils import tarot, prompts, llm, calculations, lang
|
| 4 |
|
| 5 |
# --- [1. ์ฑ ์ค์ ] ---
|
| 6 |
+
st.set_page_config(page_title="AI Pantheon", page_icon="๐ฎ", layout="wide")
|
| 7 |
|
| 8 |
+
# --- [2. ํ
๋ง ์คํ์ผ๋ง ์์ง (CSS ์์ ์ฒด)] ---
|
| 9 |
def apply_theme(mode):
|
| 10 |
+
# ๊ตฌ๊ธ ํฐํธ (ํ/์ค/์ผ/์ ๋ชจ๋ ์ปค๋ฒ)
|
|
|
|
| 11 |
st.markdown("""
|
| 12 |
<style>
|
| 13 |
+
@import url('https://fonts.googleapis.com/css2?family=Nanum+Myeongjo:wght@700&family=Noto+Serif+SC:wght@600&family=Noto+Serif+JP:wght@600&family=Nanum+Pen+Script&family=Noto+Sans+KR:wght@400;700&display=swap');
|
| 14 |
</style>
|
| 15 |
""", unsafe_allow_html=True)
|
| 16 |
+
|
| 17 |
+
themes = {
|
| 18 |
+
"tarot": """
|
| 19 |
+
/* ๐ฎ ํ๋ก: ๋ณด๋ผ๋น ๋ฐคํ๋ */
|
| 20 |
+
.stApp {
|
| 21 |
+
background: linear-gradient(135deg, #1a0b2e 0%, #2d1b4e 100%);
|
| 22 |
+
color: #e0d4fc;
|
| 23 |
+
}
|
| 24 |
+
h1, h2, h3 {
|
| 25 |
+
font-family: 'Nanum Myeongjo', 'Noto Serif JP', serif;
|
| 26 |
+
color: #d4af37 !important;
|
| 27 |
+
text-shadow: 0 0 10px #d4af37;
|
| 28 |
+
}
|
| 29 |
+
.stButton>button {
|
| 30 |
+
background: linear-gradient(45deg, #4b0082, #8a2be2);
|
| 31 |
+
color: white;
|
| 32 |
+
border: 1px solid #d4af37;
|
| 33 |
+
border-radius: 8px;
|
| 34 |
+
}
|
| 35 |
+
.stTextInput>div>div>input, .stTextArea>div>div>textarea {
|
| 36 |
+
background-color: #2d1b4e;
|
| 37 |
+
color: white;
|
| 38 |
+
border: 1px solid #d4af37;
|
| 39 |
+
}
|
| 40 |
+
""",
|
| 41 |
+
"fengshui": """
|
| 42 |
+
/* ๐ก ํ์: ํ์ง์ ๋๋ฌด */
|
| 43 |
+
.stApp {
|
| 44 |
+
background-color: #f5f5f0;
|
| 45 |
+
background-image: url("https://www.transparenttextures.com/patterns/rice-paper.png");
|
| 46 |
+
color: #3e2723;
|
| 47 |
+
}
|
| 48 |
+
h1, h2, h3 {
|
| 49 |
+
font-family: 'Nanum Myeongjo', 'Noto Serif JP', serif;
|
| 50 |
+
color: #2e7d32 !important;
|
| 51 |
+
}
|
| 52 |
+
.stButton>button {
|
| 53 |
+
background-color: #5d4037;
|
| 54 |
+
color: #fff8e1;
|
| 55 |
+
border-radius: 0px;
|
| 56 |
+
}
|
| 57 |
+
.stChatMessage {
|
| 58 |
+
background-color: #ffffff;
|
| 59 |
+
border: 1px solid #d7ccc8;
|
| 60 |
+
}
|
| 61 |
+
""",
|
| 62 |
+
"shaman": """
|
| 63 |
+
/* ๐น ์ ์ง: ๊ฐ๋ ฌํ ๋นจ๊ฐ/๊ฒ์ */
|
| 64 |
+
.stApp {
|
| 65 |
+
background-color: #1a0505;
|
| 66 |
+
color: #ffcccc;
|
| 67 |
+
}
|
| 68 |
+
h1, h2, h3 {
|
| 69 |
+
font-family: 'Nanum Pen Script', cursive;
|
| 70 |
+
font-size: 3.5rem !important;
|
| 71 |
+
color: #ff0000 !important;
|
| 72 |
+
text-shadow: 2px 2px 0px #ffff00;
|
| 73 |
+
}
|
| 74 |
+
.stButton>button {
|
| 75 |
+
background-color: #b71c1c;
|
| 76 |
+
color: #ffff00;
|
| 77 |
+
border: 2px solid #ffff00;
|
| 78 |
+
font-family: 'Nanum Pen Script', cursive;
|
| 79 |
+
font-size: 1.5rem;
|
| 80 |
+
}
|
| 81 |
+
.stTextInput>div>div>input {
|
| 82 |
+
background-color: #330000;
|
| 83 |
+
color: yellow;
|
| 84 |
+
border: 2px solid red;
|
| 85 |
+
}
|
| 86 |
+
"""
|
| 87 |
+
}
|
| 88 |
|
| 89 |
+
style = themes.get(mode, themes["tarot"])
|
| 90 |
+
st.markdown(f"<style>{style}</style>", unsafe_allow_html=True)
|
| 91 |
|
| 92 |
# --- [3. ์ํ ์ด๊ธฐํ] ---
|
| 93 |
if "messages" not in st.session_state: st.session_state.messages = []
|
|
|
|
| 103 |
["ํ๊ตญ์ด", "English", "ไธญๆ", "ๆฅๆฌ่ช"],
|
| 104 |
label_visibility="collapsed"
|
| 105 |
)
|
| 106 |
+
TXT = lang.STRINGS[current_lang] # ์ธ์ด ํฉ ๋ก๋
|
|
|
|
| 107 |
|
| 108 |
+
# --- [4. ํ๋ฅด์๋ ๋ชจ๋ ์ ํ] ---
|
| 109 |
st.sidebar.title(TXT["sidebar_title"])
|
| 110 |
|
|
|
|
| 111 |
def get_persona_name(key):
|
| 112 |
return TXT["personas"][key]
|
| 113 |
|
|
|
|
| 117 |
format_func=get_persona_name
|
| 118 |
)
|
| 119 |
|
| 120 |
+
# ํ
๋ง ์ ์ฉ
|
| 121 |
apply_theme(selected_mode)
|
| 122 |
current_persona = prompts.get_persona(selected_mode)
|
| 123 |
|
| 124 |
st.sidebar.markdown("---")
|
|
|
|
| 125 |
st.sidebar.info(TXT["desc"][selected_mode])
|
| 126 |
|
| 127 |
# --- [5. ๋ฉ์ธ UI ๋ก์ง] ---
|
|
|
|
| 129 |
st.markdown("---")
|
| 130 |
|
| 131 |
# ==========================================
|
| 132 |
+
# ๐ ๋ชจ๋ A: ํ๋ก (Tarot)
|
| 133 |
# ==========================================
|
| 134 |
if selected_mode == "tarot":
|
| 135 |
+
# 1๋จ๊ณ: ์
๋ ฅ
|
| 136 |
if st.session_state.tarot_stage == "input":
|
| 137 |
with st.form("tarot_form"):
|
| 138 |
+
topic = st.selectbox(TXT["tarot_topic"], ["Love", "Money", "Career", "Health"])
|
| 139 |
+
query = st.text_area(TXT["input_label"], placeholder=TXT["tarot_placeholder"])
|
| 140 |
submitted = st.form_submit_button(TXT["btn_submit"])
|
| 141 |
|
| 142 |
if submitted and query:
|
| 143 |
+
st.session_state.user_query = f"[{topic}] {query}"
|
| 144 |
st.session_state.tarot_stage = "picking"
|
| 145 |
st.rerun()
|
| 146 |
|
| 147 |
+
# 2๋จ๊ณ: ๋ฝ๊ธฐ
|
| 148 |
elif st.session_state.tarot_stage == "picking":
|
| 149 |
+
st.info(f"Query: **{st.session_state.user_query}**")
|
| 150 |
+
if st.button(TXT["tarot_pick_btn"], type="primary", use_container_width=True):
|
| 151 |
with st.spinner(TXT["loading"]):
|
| 152 |
time.sleep(1.5)
|
| 153 |
st.session_state.picked_cards = tarot.draw_tarot_cards(3)
|
| 154 |
st.session_state.tarot_stage = "result"
|
| 155 |
st.rerun()
|
| 156 |
|
| 157 |
+
# 3๋จ๊ณ: ๊ฒฐ๊ณผ
|
| 158 |
elif st.session_state.tarot_stage == "result":
|
| 159 |
cols = st.columns(3)
|
| 160 |
for idx, card in enumerate(st.session_state.picked_cards):
|
|
|
|
| 163 |
|
| 164 |
if "ai_response" not in st.session_state:
|
| 165 |
with st.spinner(TXT["analyzing"]):
|
|
|
|
| 166 |
st.session_state.ai_response = llm.get_ai_response(
|
| 167 |
st.session_state.user_query,
|
| 168 |
current_persona,
|
| 169 |
st.session_state.picked_cards,
|
| 170 |
+
user_lang=current_lang
|
| 171 |
)
|
| 172 |
+
|
| 173 |
st.subheader(TXT["result_title"])
|
| 174 |
st.markdown(st.session_state.ai_response)
|
| 175 |
|
| 176 |
+
if st.button(TXT["retry_btn"]):
|
| 177 |
st.session_state.tarot_stage = "input"
|
| 178 |
del st.session_state["ai_response"]
|
| 179 |
st.rerun()
|
| 180 |
|
| 181 |
# ==========================================
|
| 182 |
+
# ๐ก ๋ชจ๋ B: ํ์์ง๋ฆฌ (Feng Shui)
|
| 183 |
# ==========================================
|
| 184 |
elif selected_mode == "fengshui":
|
| 185 |
with st.container():
|
| 186 |
+
st.caption(TXT["fengshui_info"])
|
| 187 |
c1, c2 = st.columns(2)
|
| 188 |
with c1:
|
| 189 |
+
birth_year = st.number_input(TXT["birth_year"], 1950, 2025, 1990)
|
| 190 |
+
# ์ฑ๋ณ์ ๊ณ์ฐ ๋ก์ง ๋๋ฌธ์ ๋ด๋ถ๊ฐ์ '๋จ์ฑ/์ฌ์ฑ' ์ ์ง
|
| 191 |
+
gender_label = st.radio(TXT["gender"], ["Male", "Female"])
|
| 192 |
+
gender_val = "๋จ์ฑ" if gender_label == "Male" else "์ฌ์ฑ"
|
| 193 |
with c2:
|
| 194 |
+
direction = st.selectbox(TXT["door_dir"], ["N", "NE", "E", "SE", "S", "SW", "W", "NW"])
|
| 195 |
|
| 196 |
if prompt := st.chat_input(TXT["input_label"]):
|
| 197 |
+
# 1. ๊ณ์ฐ
|
| 198 |
+
fengshui_data = calculations.get_fengshui_info(birth_year, gender_val)
|
| 199 |
|
| 200 |
+
# 2. AI ์์ฒญ
|
| 201 |
sys_msg = f"[Data]: {fengshui_data}, Current Door: {direction}"
|
| 202 |
full_query = f"{sys_msg}\nUser Question: {prompt}"
|
| 203 |
|
|
|
|
| 208 |
st.write(response)
|
| 209 |
|
| 210 |
# ==========================================
|
| 211 |
+
# ๐น ๋ชจ๋ C: ์ ์ (Shaman)
|
| 212 |
# ==========================================
|
| 213 |
elif selected_mode == "shaman":
|
| 214 |
with st.container():
|
| 215 |
+
st.warning(TXT["shaman_warn"])
|
| 216 |
c1, c2 = st.columns(2)
|
| 217 |
with c1:
|
| 218 |
+
birth_year = st.number_input(TXT["birth_year"], 1960, 2025, 1995)
|
| 219 |
with c2:
|
| 220 |
prompt_input = st.text_input(TXT["input_label"])
|
| 221 |
|
| 222 |
if st.button(TXT["btn_submit"]) and prompt_input:
|
| 223 |
+
# 1. ๊ณ์ฐ
|
| 224 |
saju_data = calculations.get_ganji(birth_year)
|
| 225 |
|
| 226 |
+
# 2. AI ์์ฒญ
|
| 227 |
sys_msg = f"[Saju Data]: Year {saju_data['year_ganji']}, Element {saju_data['element']}"
|
| 228 |
full_query = f"{sys_msg}\nUser Worry: {prompt_input}"
|
| 229 |
|
|
|
|
| 232 |
with st.chat_message("assistant"):
|
| 233 |
with st.spinner(TXT["loading"]):
|
| 234 |
response = llm.get_ai_response(full_query, current_persona, user_lang=current_lang)
|
| 235 |
+
st.markdown(response)
|
| 236 |
+
|
| 237 |
+
# ๋ช
์ํ ์ถ๋ ฅ
|
| 238 |
+
st.info(f"๐ {TXT['saju_result']}: {saju_data['year_ganji']} ({saju_data['animal']})")
|