Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import sqlite3 | |
| import random | |
| from datetime import datetime | |
| import pandas as pd | |
| import plotly.express as px | |
| from pathlib import Path | |
| # تنظیمات اولیه دیتابیس | |
| class DatabaseManager: | |
| def __init__(self): | |
| self.conn = sqlite3.connect('banking_assistant.db') | |
| self.create_tables() | |
| def create_tables(self): | |
| c = self.conn.cursor() | |
| # جدول مکالمات | |
| c.execute(''' | |
| CREATE TABLE IF NOT EXISTS conversations ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| user_message TEXT, | |
| assistant_response TEXT, | |
| timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, | |
| feedback INTEGER DEFAULT 0 | |
| ) | |
| ''') | |
| # جدول پایگاه دانش | |
| c.execute(''' | |
| CREATE TABLE IF NOT EXISTS knowledge_base ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| question TEXT, | |
| answer TEXT, | |
| category TEXT, | |
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP | |
| ) | |
| ''') | |
| # جدول تنظیمات | |
| c.execute(''' | |
| CREATE TABLE IF NOT EXISTS settings ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| theme TEXT DEFAULT 'light', | |
| language TEXT DEFAULT 'fa', | |
| created_at DATETIME DEFAULT CURRENT_TIMESTAMP | |
| ) | |
| ''') | |
| self.conn.commit() | |
| # تنظیمات استایل و تم | |
| THEMES = { | |
| 'light': { | |
| 'bg_color': '#e0e5ec', | |
| 'text_color': '#333', | |
| 'shadow': '9px 9px 16px #b8b9be, -9px -9px 16px #ffffff' | |
| }, | |
| 'dark': { | |
| 'bg_color': '#2d3436', | |
| 'text_color': '#fff', | |
| 'shadow': '9px 9px 16px #1a1d1e, -9px -9px 16px #404b4d' | |
| }, | |
| 'blue': { | |
| 'bg_color': '#e3f2fd', | |
| 'text_color': '#1976d2', | |
| 'shadow': '9px 9px 16px #c1cdd4, -9px -9px 16px #ffffff' | |
| } | |
| } | |
| def load_custom_styles(theme='light'): | |
| return f""" | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@100;200;300;400;500;600;700;800;900&display=swap'); | |
| /* تنظیمات پایه */ | |
| * {{ | |
| font-family: 'Vazirmatn', sans-serif; | |
| direction: rtl; | |
| transition: all 0.3s ease; | |
| }} | |
| body {{ | |
| background: {THEMES[theme]['bg_color']}; | |
| color: {THEMES[theme]['text_color']}; | |
| }} | |
| /* هدر اصلی */ | |
| .main-header {{ | |
| background: {THEMES[theme]['bg_color']}; | |
| padding: 2rem; | |
| border-radius: 25px; | |
| box-shadow: {THEMES[theme]['shadow']}; | |
| margin-bottom: 2rem; | |
| text-align: center; | |
| position: relative; | |
| overflow: hidden; | |
| }} | |
| .main-header::before {{ | |
| content: ''; | |
| position: absolute; | |
| top: -50%; | |
| left: -50%; | |
| width: 200%; | |
| height: 200%; | |
| background: linear-gradient( | |
| 45deg, | |
| transparent 0%, | |
| rgba(255, 255, 255, 0.1) 50%, | |
| transparent 100% | |
| ); | |
| animation: shine 3s infinite; | |
| }} | |
| /* باکس چت */ | |
| .chat-container {{ | |
| background: {THEMES[theme]['bg_color']}; | |
| border-radius: 20px; | |
| padding: 2rem; | |
| margin: 1rem 0; | |
| box-shadow: {THEMES[theme]['shadow']}; | |
| max-height: 70vh; | |
| overflow-y: auto; | |
| scroll-behavior: smooth; | |
| }} | |
| /* پیامها */ | |
| .message {{ | |
| margin: 1rem 0; | |
| padding: 1rem; | |
| border-radius: 15px; | |
| position: relative; | |
| animation: messageSlide 0.3s ease-out; | |
| }} | |
| .message.user {{ | |
| background: linear-gradient(135deg, #0073e6 0%, #0056b3 100%); | |
| color: white; | |
| margin-left: 2rem; | |
| box-shadow: 0 4px 15px rgba(0, 115, 230, 0.2); | |
| }} | |
| .message.assistant {{ | |
| background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); | |
| color: #343a40; | |
| margin-right: 2rem; | |
| box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); | |
| }} | |
| /* ورودی چت */ | |
| .chat-input-container {{ | |
| background: {THEMES[theme]['bg_color']}; | |
| padding: 1.5rem; | |
| border-radius: 15px; | |
| box-shadow: {THEMES[theme]['shadow']}; | |
| margin-top: 1rem; | |
| display: flex; | |
| align-items: center; | |
| gap: 1rem; | |
| }} | |
| .chat-input {{ | |
| flex: 1; | |
| padding: 1rem; | |
| border: none; | |
| border-radius: 10px; | |
| background: rgba(255, 255, 255, 0.1); | |
| backdrop-filter: blur(10px); | |
| color: {THEMES[theme]['text_color']}; | |
| font-size: 1rem; | |
| transition: all 0.3s ease; | |
| }} | |
| .chat-input:focus {{ | |
| outline: none; | |
| box-shadow: 0 0 0 3px rgba(0, 115, 230, 0.3); | |
| }} | |
| /* دکمهها */ | |
| .button {{ | |
| padding: 0.8rem 1.5rem; | |
| border: none; | |
| border-radius: 10px; | |
| background: linear-gradient(135deg, #0073e6 0%, #0056b3 100%); | |
| color: white; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| font-weight: 500; | |
| display: flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| }} | |
| .button:hover {{ | |
| transform: translateY(-2px); | |
| box-shadow: 0 5px 15px rgba(0, 115, 230, 0.3); | |
| }} | |
| .button:active {{ | |
| transform: translateY(0); | |
| }} | |
| /* انیمیشنها */ | |
| @keyframes messageSlide {{ | |
| from {{ | |
| opacity: 0; | |
| transform: translateY(20px); | |
| }} | |
| to {{ | |
| opacity: 1; | |
| transform: translateY(0); | |
| }} | |
| }} | |
| @keyframes shine {{ | |
| 0% {{ | |
| transform: translateX(-100%) rotate(45deg); | |
| }} | |
| 100% {{ | |
| transform: translateX(100%) rotate(45deg); | |
| }} | |
| }} | |
| /* اسکرولبار سفارشی */ | |
| ::-webkit-scrollbar {{ | |
| width: 8px; | |
| }} | |
| ::-webkit-scrollbar-track {{ | |
| background: {THEMES[theme]['bg_color']}; | |
| }} | |
| ::-webkit-scrollbar-thumb {{ | |
| background: #0073e6; | |
| border-radius: 4px; | |
| }} | |
| ::-webkit-scrollbar-thumb:hover {{ | |
| background: #0056b3; | |
| }} | |
| </style> | |
| """ | |
| class BankingAssistant: | |
| def __init__(self): | |
| self.db = DatabaseManager() | |
| self.model = BankingModel() # اضافه کردن مدل | |
| if 'theme' not in st.session_state: | |
| st.session_state.theme = 'light' | |
| if 'messages' not in st.session_state: | |
| st.session_state.messages = [] | |
| self.add_message('assistant', """ | |
| 👋 سلام! من دستیار هوشمند بانکی شما هستم. | |
| میتوانم در موارد زیر به شما کمک کنم: | |
| 📊 مشاهده وضعیت حساب | |
| 💳 انتقال وجه | |
| 📝 درخواست تسهیلات | |
| 🏦 اطلاعات شعب | |
| چطور میتوانم کمکتان کنم؟ | |
| """) | |
| def add_message(self, role, content): | |
| timestamp = datetime.now().strftime("%H:%M") | |
| st.session_state.messages.append({ | |
| 'role': role, | |
| 'content': content, | |
| 'timestamp': timestamp | |
| }) | |
| # ذخیره در دیتابیس | |
| if role == 'user': | |
| self.db.conn.execute( | |
| 'INSERT INTO conversations (user_message, timestamp) VALUES (?, ?)', | |
| (content, timestamp) | |
| ) | |
| else: | |
| self.db.conn.execute( | |
| 'UPDATE conversations SET assistant_response = ? WHERE id = last_insert_rowid()', | |
| (content,) | |
| ) | |
| self.db.conn.commit() | |
| def render_chat_interface(self): | |
| st.markdown(load_custom_styles(st.session_state.theme), unsafe_allow_html=True) | |
| # هدر اصلی | |
| st.markdown(""" | |
| <div class="main-header"> | |
| <h1>🏦 دستیار هوشمند بانکی</h1> | |
| <p>پاسخگوی 24 ساعته شما</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # باکس چت | |
| st.markdown('<div class="chat-container">', unsafe_allow_html=True) | |
| for msg in st.session_state.messages: | |
| class_name = "user" if msg['role'] == 'user' else "assistant" | |
| st.markdown(f""" | |
| <div class="message {class_name}"> | |
| {msg['content']} | |
| <small style="position: absolute; bottom: 5px; {'right' if class_name == 'user' else 'left'}: 10px; opacity: 0.7;"> | |
| {msg['timestamp']} | |
| </small> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # باکس ورودی | |
| st.markdown(""" | |
| <div class="chat-input-container"> | |
| <button class="action-button">🎤</button> | |
| <input type="text" class="chat-input" placeholder="پیام خود را بنویسید..."> | |
| <button class="button"> | |
| <span>ارسال</span> | |
| <span>➤</span> | |
| </button> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| class AdminDashboard: | |
| def __init__(self, db_manager): | |
| self.db = db_manager | |
| def render_dashboard(self): | |
| st.markdown(""" | |
| <div class="admin-header"> | |
| <h2>🔐 پنل مدیریت</h2> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # نمودارهای تحلیلی | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| self.render_conversation_stats() | |
| with col2: | |
| self.render_feedback_chart() | |
| # مدیریت پایگاه دانش | |
| st.markdown(""" | |
| <div class="admin-section"> | |
| <h3>📚 مدیریت پایگاه دانش</h3> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # افزودن دانش جدید | |
| with st.expander("➕ افزودن مورد جدید"): | |
| category = st.selectbox( | |
| "دستهبندی", | |
| ["عمومی", "حسابها", "تسهیلات", "کارت", "شعب"] | |
| ) | |
| question = st.text_area("سوال") | |
| answer = st.text_area("پاسخ") | |
| if st.button("ذخیره"): | |
| self.db.conn.execute( | |
| 'INSERT INTO knowledge_base (question, answer, category) VALUES (?, ?, ?)', | |
| (question, answer, category) | |
| ) | |
| self.db.conn.commit() | |
| st.success("✅ با موفقیت ذخیره شد") | |
| def render_conversation_stats(self): | |
| # دریافت آمار مکالمات | |
| df = pd.read_sql_query(""" | |
| SELECT | |
| date(timestamp) as date, | |
| COUNT(*) as count | |
| FROM conversations | |
| GROUP BY date(timestamp) | |
| ORDER BY date DESC | |
| LIMIT 7 | |
| """, self.db.conn) | |
| fig = px.line( | |
| df, | |
| x='date', | |
| y='count', | |
| title='آمار مکالمات 7 روز اخیر', | |
| labels={'count': 'تعداد مکالمات', 'date': 'تاریخ'} | |
| ) | |
| fig.update_layout( | |
| font_family="Vazirmatn", | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| ) | |
| st.plotly_chart(fig) | |
| def render_feedback_chart(self): | |
| # نمودار بازخوردها | |
| df = pd.read_sql_query(""" | |
| SELECT | |
| feedback, | |
| COUNT(*) as count | |
| FROM conversations | |
| WHERE feedback != 0 | |
| GROUP BY feedback | |
| """, self.db.conn) | |
| fig = px.pie( | |
| df, | |
| values='count', | |
| names='feedback', | |
| title='نمودار بازخوردها', | |
| color_discrete_sequence=px.colors.sequential.Blues | |
| ) | |
| fig.update_layout( | |
| font_family="Vazirmatn", | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| ) | |
| st.plotly_chart(fig) | |
| def main(): | |
| st.set_page_config( | |
| page_title="دستیار هوشمند بانکی", | |
| page_icon="🏦", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| assistant = BankingAssistant() | |
| # منوی کناری | |
| with st.sidebar: | |
| st.markdown("### ⚙️ تنظیمات") | |
| theme = st.selectbox( | |
| "انتخاب تم", | |
| options=['light', 'dark', 'blue'], | |
| index=['light', 'dark', 'blue'].index(st.session_state.theme) | |
| ) | |
| if theme != st.session_state.theme: | |
| st.session_state.theme = theme | |
| st.experimental_rerun() | |
| if st.button("🔐 ورود مدیر"): | |
| st.session_state.show_login = True | |
| # نمایش فرم لاگین | |
| if st.session_state.get('show_login', False): | |
| with st.form("login_form"): | |
| username = st.text_input("نام کاربری") | |
| password = st.text_input("رمز عبور", type="password") | |
| if st.form_submit_button("ورود"): | |
| if username == "admin" and password == "admin": # در حالت واقعی باید امنتر باشد | |
| st.session_state.admin_logged_in = True | |
| st.session_state.show_login = False | |
| st.experimental_rerun() | |
| else: | |
| st.error("نام کاربری یا رمز عبور اشتباه است") | |
| # نمایش داشبورد مدیر | |
| if st.session_state.get('admin_logged_in', False): | |
| admin = AdminDashboard(assistant.db) | |
| admin.render_dashboard() | |
| else: | |
| assistant.render_chat_interface() | |
| if __name__ == "__main__": | |
| main() | |