Assistant / app.py
Really-amin's picture
Upload 4 files
21d8cd3 verified
raw
history blame
16.5 kB
import streamlit as st
import time
import random
import json
from datetime import datetime
import os
# تنظیمات اصلی چت‌بات
ADMIN_USERNAME = "admin"
ADMIN_PASSWORD = "password"
# CSS بهبود یافته با انیمیشن‌ها و افکت‌های جدید
CUSTOM_CSS = """
<style>
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;700&display=swap');
@import url('https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css');
:root {
--primary-color: #3b82f6;
--secondary-color: #6366f1;
--accent-color: #10b981;
--background-color: #f8fafc;
--chat-bg: #ffffff;
--user-message-bg: #e0e7ff;
--bot-message-bg: #f1f5f9;
--text-primary: #1e293b;
--text-secondary: #475569;
--border-color: #e2e8f0;
--error-color: #ef4444;
--success-color: #22c55e;
}
/* === انیمیشن‌های جدید === */
@keyframes slideIn {
from { transform: translateY(20px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.05); }
100% { transform: scale(1); }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
/* === استایل‌های اصلی === */
body {
font-family: 'Vazirmatn', sans-serif !important;
background-color: var(--background-color);
direction: rtl;
}
.chat-container {
max-width: 900px;
margin: 2rem auto;
background: var(--chat-bg);
border-radius: 1rem;
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
animation: slideIn 0.5s ease-out;
}
.chat-header {
background: linear-gradient(to left, var(--primary-color), var(--secondary-color));
color: white;
padding: 1.5rem;
border-radius: 1rem 1rem 0 0;
text-align: center;
position: relative;
overflow: hidden;
}
.chat-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 linear;
}
@keyframes shine {
from { transform: translateX(-100%) rotate(45deg); }
to { transform: translateX(100%) rotate(45deg); }
}
.chat-header h1 {
font-size: 1.75rem;
font-weight: 700;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
}
.chat-header h1 i {
animation: pulse 2s infinite;
}
.chat-messages {
height: 500px;
overflow-y: auto;
padding: 1.5rem;
background: var(--chat-bg);
scroll-behavior: smooth;
}
.message {
margin-bottom: 1rem;
max-width: 80%;
padding: 1rem;
border-radius: 0.75rem;
position: relative;
animation: fadeIn 0.3s ease-out;
transition: transform 0.2s;
}
.message:hover {
transform: translateY(-2px);
}
.message.user {
background: var(--user-message-bg);
margin-left: auto;
color: var(--text-primary);
box-shadow: 2px 2px 10px rgba(99, 102, 241, 0.1);
}
.message.bot {
background: var(--bot-message-bg);
margin-right: auto;
color: var(--text-primary);
box-shadow: 2px 2px 10px rgba(241, 245, 249, 0.3);
}
.message::before {
content: '';
position: absolute;
width: 0;
height: 0;
border: 8px solid transparent;
}
.message.user::before {
border-left-color: var(--user-message-bg);
right: -16px;
top: 50%;
transform: translateY(-50%);
}
.message.bot::before {
border-right-color: var(--bot-message-bg);
left: -16px;
top: 50%;
transform: translateY(-50%);
}
.chat-input {
padding: 1.5rem;
border-top: 1px solid var(--border-color);
display: flex;
gap: 1rem;
align-items: center;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
}
.chat-input input {
flex: 1;
padding: 0.75rem 1rem;
border: 2px solid var(--border-color);
border-radius: 0.5rem;
font-family: 'Vazirmatn', sans-serif;
font-size: 0.875rem;
transition: all 0.3s;
}
.chat-input input:focus {
outline: none;
border-color: var(--primary-color);
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.chat-input button {
background: var(--primary-color);
color: white;
border: none;
padding: 0.75rem 1.5rem;
border-radius: 0.5rem;
cursor: pointer;
display: flex;
align-items: center;
gap: 0.5rem;
transition: all 0.2s;
font-weight: 500;
}
.chat-input button:hover {
background: var(--secondary-color);
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.chat-input button:active {
transform: translateY(0);
}
/* === قابلیت‌های جدید === */
.typing-indicator {
display: flex;
gap: 0.5rem;
padding: 1rem;
background: var(--bot-message-bg);
border-radius: 0.75rem;
width: fit-content;
margin-bottom: 1rem;
animation: fadeIn 0.3s;
}
.typing-dot {
width: 8px;
height: 8px;
background: var(--primary-color);
border-radius: 50%;
animation: typingDot 1s infinite;
}
.typing-dot:nth-child(2) { animation-delay: 0.2s; }
.typing-dot:nth-child(3) { animation-delay: 0.4s; }
@keyframes typingDot {
0%, 100% { transform: translateY(0); }
50% { transform: translateY(-5px); }
}
.quick-replies {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
margin-top: 1rem;
}
.quick-reply {
background: var(--accent-color);
color: white;
padding: 0.5rem 1rem;
border-radius: 2rem;
cursor: pointer;
transition: all 0.2s;
font-size: 0.875rem;
}
.quick-reply:hover {
transform: translateY(-2px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
/* === پنل مدیریت === */
.admin-panel {
background: white;
padding: 1.5rem;
border-radius: 0.75rem;
margin-bottom: 1rem;
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
}
.admin-panel h2 {
color: var(--text-primary);
font-size: 1.25rem;
margin-bottom: 1rem;
display: flex;
align-items: center;
gap: 0.5rem;
}
.admin-controls {
display: flex;
flex-direction: column;
gap: 1rem;
}
.admin-button {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1rem;
border-radius: 0.5rem;
cursor: pointer;
transition: all 0.2s;
border: none;
font-family: 'Vazirmatn', sans-serif;
font-weight: 500;
}
.admin-button.danger {
background: var(--error-color);
color: white;
}
.admin-button.success {
background: var(--success-color);
color: white;
}
.admin-button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
}
.statistics {
background: white;
padding: 1rem;
border-radius: 0.5rem;
margin-top: 1rem;
}
.stat-item {
display: flex;
justify-content: space-between;
padding: 0.5rem 0;
border-bottom: 1px solid var(--border-color);
}
.stat-item:last-child {
border-bottom: none;
}
</style>
"""
class EnhancedChatbot:
def __init__(self):
self.conversation_history = []
self.admin_logged_in = False
self.quick_replies = [
"بخشنامه‌های جدید",
"راهنمای استفاده",
"تماس با پشتیبانی",
"گزارش مشکل"
]
self.stats = {
'total_messages': 0,
'user_messages': 0,
'bot_messages': 0,
'start_time': datetime.now()
}
self.load_responses()
def load_responses(self):
"""بارگذاری پاسخ‌های از پیش تعریف شده"""
self.responses = {
'greeting': [
"سلام! چطور می‌تونم کمکتون کنم؟",
"درود! من پاسخگوی هوشمند بخشنامه هستم. چه کمکی از دستم برمیاد؟",
"خوش آمدید! در خدمت شما هستم."
],
'help': [
"برای راهنمایی بیشتر می‌تونید از گزینه‌های سریع پایین استفاده کنید.",
"من می‌تونم در موارد زیر کمکتون کنم:\n- جستجوی بخشنامه‌ها\n- پاسخ به سوالات متداول\n- راهنمایی در مورد فرآیندها",
],
'unknown': [
"متوجه نشدم. می‌شه بیشتر توضیح بدید؟",
"می‌تونید سوالتون رو به شکل دیگه‌ای بپرسید؟",
"برای راهنمایی بهتر، لطفاً جزئیات بیشتری ارائه کنید."
]
}
def chat_response(self, message):
"""پردازش پیام کاربر و ارائه پاسخ هوشمند"""
self.stats['total_messages'] += 1
self.stats['user_messages'] += 1
# افزودن پیام کاربر
self.conversation_history.append({
'type': 'user',
'message': message,
'timestamp': datetime.now().strftime("%H:%M")
})
# شبیه‌سازی تایپ کردن
time.sleep(1)
# انتخاب پاسخ مناسب
if any(word in message.lower() for word in ['سلام', 'درود', 'خوش آمدید']):
response = random.choice(self.responses['greeting'])
elif 'راهنمایی' in message.lower() or 'کمک' in message.lower():
response = random.choice(self.responses['help'])
else:
response = random.choice(self.responses['unknown'])
self.stats['bot_messages'] += 1
# افزودن پاسخ ربات
self.conversation_history.append({
'type': 'bot',
'message': response,
'timestamp': datetime.now().strftime("%H:%M")
})
return self.conversation_history
def get_stats(self):
"""دریافت آمار چت‌بات"""
uptime = datetime.now() - self.stats['start_time']
return {
'total_messages': self.stats['total_messages'],
'user_messages': self.stats['user_messages'],
'bot_messages': self.stats['bot_messages'],
'uptime': str(uptime).split('.')[0],
'response_rate': f"{(self.stats['bot_messages'] / self.stats['user_messages'] * 100):.1f}%" if self.stats['user_messages'] > 0 else "0%"
}
# تنظیمات اولیه استریملیت
# ادامه کد قبلی...
# تنظیمات اولیه استریملیت
st.set_page_config(
page_title="پاسخگوی هوشمند بخشنامه",
page_icon="🤖",
layout="wide",
initial_sidebar_state="expanded"
)
# اعمال CSS
st.markdown(CUSTOM_CSS, unsafe_allow_html=True)
# ایجاد نمونه از چت‌بات
if 'chatbot' not in st.session_state:
st.session_state.chatbot = EnhancedChatbot()
# نمایش هدر اصلی
st.markdown("""
<div class="chat-container">
<div class="chat-header">
<h1>
<i class="fas fa-robot"></i>
پاسخگوی هوشمند بخشنامه
<span class="status-badge online">
<i class="fas fa-circle"></i>
</span>
</h1>
</div>
<div class="chat-messages" id="chat-messages">
""", unsafe_allow_html=True)
# نمایش پیام‌ها
for message in st.session_state.chatbot.conversation_history:
message_class = "user" if message['type'] == 'user' else "bot"
icon = "user" if message['type'] == 'user' else "robot"
st.markdown(f"""
<div class="message {message_class}">
<div class="message-header">
<i class="fas fa-{icon}"></i>
<span class="timestamp">{message['timestamp']}</span>
</div>
<div class="message-content">
{message['message']}
</div>
</div>
""", unsafe_allow_html=True)
# نمایش نشانگر تایپ کردن
if st.session_state.get('is_typing', False):
st.markdown("""
<div class="typing-indicator">
<div class="typing-dot"></div>
<div class="typing-dot"></div>
<div class="typing-dot"></div>
</div>
""", unsafe_allow_html=True)
# پاسخ‌های سریع
st.markdown("""
<div class="quick-replies">
""", unsafe_allow_html=True)
for reply in st.session_state.chatbot.quick_replies:
st.markdown(f"""
<div class="quick-reply" onclick="document.getElementById('user-input').value='{reply}'">
{reply}
</div>
""", unsafe_allow_html=True)
st.markdown("</div>", unsafe_allow_html=True)
# بخش ورودی پیام
col1, col2 = st.columns([4, 1])
with col1:
user_message = st.text_input(
"",
placeholder="پیام خود را بنویسید...",
key="user_message",
help="برای ارسال پیام، متن خود را وارد کرده و دکمه ارسال را بزنید"
)
with col2:
send_button = st.button(
"ارسال پیام",
key="send_button",
help="برای ارسال پیام کلیک کنید"
)
if send_button and user_message:
st.session_state['is_typing'] = True
st.session_state.chatbot.chat_response(user_message)
st.session_state['is_typing'] = False
st.experimental_rerun()
st.markdown("</div>", unsafe_allow_html=True)
# پنل مدیریت در سایدبار
with st.sidebar:
st.markdown("""
<div class="admin-panel">
<h2>
<i class="fas fa-cog"></i>
پنل مدیریت
</h2>
</div>
""", unsafe_allow_html=True)
if st.checkbox("نمایش آمار"):
stats = st.session_state.chatbot.get_stats()
st.markdown("""
<div class="statistics">
<h3>آمار سیستم</h3>
""", unsafe_allow_html=True)
for key, value in stats.items():
st.markdown(f"""
<div class="stat-item">
<span>{key}:</span>
<strong>{value}</strong>
</div>
""", unsafe_allow_html=True)
st.markdown("</div>", unsafe_allow_html=True)
if st.button("پاک کردن تاریخچه", key="clear_history"):
st.session_state.chatbot.conversation_history = []
st.experimental_rerun()
# تنظیمات ظاهری
st.markdown("### تنظیمات ظاهری")
font_size = st.slider("اندازه متن", 12, 20, 14)
st.markdown(f"""
<style>
.message {{ font-size: {font_size}px; }}
</style>
""", unsafe_allow_html=True)
# اضافه کردن اسکریپت‌های جاوااسکریپت برای عملکرد بهتر
st.markdown("""
<script>
// اسکرول خودکار به آخرین پیام
function scrollToBottom() {
const messages = document.querySelector('.chat-messages');
messages.scrollTop = messages.scrollHeight;
}
// اجرای اسکرول در لود صفحه
window.onload = scrollToBottom;
// مدیریت کلیدهای میانبر
document.addEventListener('keydown', function(event) {
if (event.key === 'Enter' && !event.shiftKey) {
const sendButton = document.querySelector('button:contains("ارسال پیام")');
if (sendButton) {
sendButton.click();
}
}
});
</script>
""", unsafe_allow_html=True)