Spaces:
Build error
Build error
File size: 11,442 Bytes
23da334 | 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 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | import streamlit as st
import google.generativeai as genai
import textwrap # For wrapping long text
# --- API Key Setup (Replace with your actual keys) ---
API_KEYS = [
"AIzaSyCnvlaZII4rP6UUy9LHL2u5Ab7CpST7U9g",
"AIzaSyBXg8nVnRCrLcbBTby7j5yDoKaQvfo9rFk",
"AIzaSyCbPsdkZ8DGCAOSlfrXhh5JP2OLYEDHcJg"
]
# --- Helper Functions ---
def call_gemini_api(prompt):
for api_key in API_KEYS:
try:
genai.configure(api_key=api_key)
model = genai.GenerativeModel("gemini-pro")
response = model.generate_content(prompt)
return response.text.strip()
except Exception as e:
error_message = str(e)
if "insufficient_quota" in error_message or "Quota exceeded" in error_message:
continue
else:
return f"❌ เกิดข้อผิดพลาด: {error_message}"
return "⚠️ API ทั้งหมดหมดโควต้าแล้ว กรุณาตรวจสอบบัญชีของคุณ"
def process_menus(response_text):
menu_list = response_text.split("🍽️ เมนูที่")
menu_list = [menu.strip() for menu in menu_list if menu.strip()]
if not menu_list:
menu_list = response_text.split("\n- ")
menu_list = [menu.strip() for menu in menu_list if menu.strip()]
if not menu_list:
menu_list = response_text.split("\n• ")
menu_list = [menu.strip() for menu in menu_list if menu.strip()]
return menu_list
# --- Custom CSS ---
st.markdown("""
<style>
/* Global Styles */
body {
font-family: 'Kanit', sans-serif; /* Modern Thai font */
}
.stApp {
background-color: #f0f2f6; /* Light gray background */
background-image: url("https://www.transparenttextures.com/patterns/subtle-white-feathers.png"); /*Subtle Background Pattern*/
}
/* Header */
.title {
color: #2c3e50;
text-align: center;
padding: 1rem 0;
font-size: 2.5rem; /* Larger title */
font-weight: 600; /* Semi-bold */
}
/* Mode Selection */
.mode-selection {
margin-bottom: 2rem;
border-radius: 10px;
padding: 10px;
background-color: white;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
}
/* Input Sections */
.input-section {
background-color: white;
padding: 20px;
border-radius: 10px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
}
/* Input Fields */
.stTextInput, .stSelectbox, .stSlider, .stRadio, .stNumberInput {
margin-bottom: 10px;
}
.stTextArea>div>div>textarea{
border-color:#3498db;
}
/* Buttons */
.stButton>button {
background-color: #3498db; /* Blue */
color: white;
border: none;
border-radius: 20px; /* Rounded buttons */
padding: 10px 24px;
font-size: 1.1rem;
transition: all 0.3s ease;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* Subtle shadow */
width: 100%; /* Make buttons full width */
}
.stButton>button:hover {
background-color: #2980b9; /* Darker blue on hover */
transform: translateY(-2px); /* Slight lift on hover */
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.stButton>button:active {
transform: translateY(0); /* Reset position on click */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
/* Menu Columns */
.menu-column {
background-color: white;
border-radius: 10px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
transition: transform 0.2s ease; /* Smooth transition */
border: 2px solid transparent; /* Add a border */
}
.menu-column:hover {
transform: scale(1.03); /* Slightly enlarge on hover */
border-color: #3498db;
}
.menu-column h3 {
color: #3498db; /* Blue heading */
margin-bottom: 10px;
font-size: 1.4rem;
}
.menu-item {
font-size: 1rem;
line-height: 1.6;
color: #4a4a4a; /* Dark gray text */
}
/* Expander */
.st-expanderHeader {
font-size: 1.2rem;
font-weight: 500; /* Slightly bolder expander header */
}
/* About Section */
.about-section {
background-color: #e0e0e0;
border-radius: 10px;
padding: 20px;
margin-top: 20px;
}
.about-section ul {
list-style: none; /* Remove bullet points */
padding: 0;
}
.about-section li {
margin-bottom: .5rem;
}
/* Spinners */
.st-cf {
color: #3498db !important; /* Make spinners blue */
}
</style>
""", unsafe_allow_html=True)
# --- App UI ---
st.markdown("<h1 class='title'>🍽️ Smart Cooking App 😎</h1>", unsafe_allow_html=True)
with st.container(border=True):
option = st.radio("🔹 เลือกโหมด:", ["สร้างเมนูจากวัตถุดิบ", "ค้นหาเมนูสำหรับซื้อ"],
horizontal=True, key="mode_select")
if option == "สร้างเมนูจากวัตถุดิบ":
st.subheader("✨ สร้างเมนูแบบกำหนดเอง")
with st.expander("📝 กรอกวัตถุดิบของคุณ", expanded=True):
ingredients = st.text_area("วัตถุดิบ (คั่นด้วยจุลภาค):",
placeholder="เช่น ไข่, หมูสับ, ผักกาด...",
height=120)
with st.expander("⚙️ ปรับแต่งเมนูของคุณ", expanded=False):
col1, col2 = st.columns(2)
with col1:
num_ingredients = st.number_input("จำนวนวัตถุดิบหลัก", min_value=1, max_value=20, value=3, step=1)
category = st.selectbox("ประเภทอาหาร",
["อาหารทั่วไป", "มังสวิรัติ", "อาหารคลีน", "อาหารไทย", "อาหารญี่ปุ่น", "อาหารตะวันตก"])
calories = st.slider("แคลอรี่ที่ต้องการ (kcal)", 100, 1500, 500, step=50)
with col2:
difficulty = st.radio("ระดับความยาก", ["ง่าย", "ปานกลาง", "ยาก"], horizontal=True)
cook_time = st.slider("เวลาทำอาหาร (นาที)", 5, 180, 30, step=5)
if st.button("🍳 สร้างเมนู", use_container_width=True):
if ingredients:
prompt = (f"ฉันมี: {ingredients} ({num_ingredients} วัตถุดิบหลัก) "
f"แนะนำเมนู {category} เวลาทำไม่เกิน {cook_time} นาที "
f"ประมาณ {calories} kcal ระดับความยาก {difficulty} "
f"พร้อมวิธีทำอย่างละเอียด เสนอ 3 ตัวเลือก คั่นด้วย '🍽️ เมนูที่'")
with st.spinner("กำลังสร้างสรรค์ไอเดียอร่อยๆ..."):
menu_list = process_menus(call_gemini_api(prompt))
if menu_list:
st.subheader("🧑🍳 เมนูแนะนำ:")
cols = st.columns(3)
for i, menu in enumerate(menu_list[:3]):
with cols[i]:
st.markdown(f"<div class='menu-column'><h3>🍽️ เมนูที่ {i+1}</h3><p class='menu-item'>{menu}</p></div>", unsafe_allow_html=True)
else:
st.warning("⚠️ ไม่พบเมนูที่ตรงกับเกณฑ์ของคุณ โปรดลองปรับการตั้งค่า")
else:
st.warning("⚠️ กรุณากรอกวัตถุดิบของคุณ")
elif option == "ค้นหาเมนูสำหรับซื้อ":
st.subheader("✨ ค้นหาเมนูที่ใช่สำหรับคุณ")
with st.expander("⚙️ ตั้งค่าการค้นหา", expanded=True):
col1, col2 = st.columns(2)
with col1:
country = st.selectbox("ประเทศ", ["ไทย", "ญี่ปุ่น", "เกาหลีใต้", "สหรัฐอเมริกา", "อังกฤษ", "ฝรั่งเศส", "เยอรมนี"])
category = st.selectbox("ประเภทอาหาร", ["อาหารไทย", "อาหารญี่ปุ่น", "อาหารเกาหลี", "ฟาสต์ฟู้ด", "อาหารสุขภาพ"])
with col2:
taste = st.radio("รสชาติ", ["เผ็ด", "หวาน", "เค็ม", "เปรี้ยว"], horizontal=True)
budget = st.radio("งบประมาณ", ["ต่ำกว่า 100 บาท", "100 - 300 บาท", "มากกว่า 300 บาท"], horizontal=True)
if st.button("🔎 ค้นหาเมนู", use_container_width=True):
prompt = (f"ฉันต้องการซื้ออาหาร {category} รสชาติ {taste} งบประมาณ {budget} ใน {country} "
f"แนะนำ 3 ตัวเลือกเมนู {category} ที่มีขายใน {country} คั่นด้วย '🍽️ เมนูที่'")
with st.spinner("กำลังค้นหาตัวเลือกที่ดีที่สุด..."):
menu_list = process_menus(call_gemini_api(prompt))
if menu_list:
st.subheader("🧑🍳 เมนูแนะนำ:")
cols = st.columns(3)
for i, menu in enumerate(menu_list[:3]):
with cols[i]:
st.markdown(f"<div class='menu-column'><h3>🍽️ เมนูที่ {i+1}</h3><p class='menu-item'>{menu}</p></div>", unsafe_allow_html=True)
else:
st.warning("⚠️ ไม่พบเมนู โปรดลองอีกครั้ง")
# --- About Section ---
st.markdown("---")
if st.button("📜 เกี่ยวกับผู้พัฒนา", use_container_width=True):
with st.expander("🤝 พบกับทีมงาน"):
st.markdown("""
<div class='about-section'>
<ul>
<li><strong>1. นาย กัลปพฤกษ์ วิเชียรรัตน์</strong> - <em>ชั้น 6/13 เลขที่ 3(คนแบกครับอิๆ)</em></li>
<li><strong>2. นาย ธีราธร มุกดาเพชรรัตน์</strong> - <em>ชั้น 6/13 เลขที่ 13</em></li>
<li><strong>3. นาย อภิวิชญ์ อดุลธรรมวิทย์</strong> - <em>ชั้น 6/13 เลขที่ 28</em></li>
<li><strong>4. นาย ปัณณวิชญ์ หลีกภัย</strong> - <em>ชั้น 6/13 เลขที่ 29</em></li>
</ul>
</div>
""", unsafe_allow_html=True) |