Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from openai import OpenAI | |
| import time | |
| import json | |
| # إعداد الصفحة | |
| st.set_page_config(page_title="Genisi - Chatbot", page_icon="🤖", layout="wide") | |
| # اختيار الوضع (فاتح/داكن) من الشريط الجانبي | |
| with st.sidebar: | |
| theme = st.radio("🎨 الوضع", ["فاتح", "داكن"], index=0) | |
| # تطبيق الأنماط حسب الوضع المختار | |
| if theme == "فاتح": | |
| bg_color = "#FFFFFF" # أبيض كامل للخلفية | |
| text_color = "#000000" # أسود كامل للنصوص | |
| border_color = "#E0E0E0" # رمادي فاتح جداً للحدود فقط | |
| secondary_bg = "#FFFFFF" # نفس الأبيض | |
| else: # داكن | |
| bg_color = "#000000" # أسود كامل للخلفية | |
| text_color = "#FFFFFF" # أبيض كامل للنصوص | |
| border_color = "#333333" # رمادي غامق جداً للحدود فقط | |
| secondary_bg = "#000000" # نفس الأسود | |
| # CSS بسيط جداً - لون واحد فقط | |
| st.markdown(f""" | |
| <style> | |
| /* تنسيق عام - لون واحد فقط */ | |
| .stApp, section[data-testid="stSidebar"], .stMarkdown, | |
| div[data-testid="stVerticalBlock"], div[data-testid="stChatMessage"] {{ | |
| background-color: {bg_color} !important; | |
| }} | |
| /* جميع النصوص بلون واحد */ | |
| p, h1, h2, h3, h4, h5, h6, label, span, div, .stChatMessage {{ | |
| color: {text_color} !important; | |
| }} | |
| /* حدود بسيطة جداً للعناصر */ | |
| section[data-testid="stSidebar"] {{ | |
| border-left: 1px solid {border_color}; | |
| }} | |
| /* الأزرار - بدون خلفية مميزة */ | |
| .stButton button {{ | |
| background-color: {bg_color}; | |
| color: {text_color}; | |
| border: 1px solid {border_color}; | |
| border-radius: 5px; | |
| width: 100%; | |
| text-align: right; | |
| }} | |
| .stButton button:hover {{ | |
| background-color: {bg_color}; | |
| border-color: {text_color}; | |
| }} | |
| /* عنوان الشات */ | |
| .chat-title {{ | |
| font-size: 24px; | |
| font-weight: 600; | |
| color: {text_color}; | |
| margin-bottom: 20px; | |
| padding: 10px 20px; | |
| border-bottom: 1px solid {border_color}; | |
| text-align: center; | |
| }} | |
| /* معلومات المطور */ | |
| .developer-info {{ | |
| position: fixed; | |
| bottom: 0; | |
| left: 0; | |
| right: 0; | |
| text-align: center; | |
| padding: 10px; | |
| background-color: {bg_color}; | |
| color: {text_color}; | |
| font-size: 12px; | |
| border-top: 1px solid {border_color}; | |
| z-index: 999; | |
| }} | |
| /* مربع الإدخال */ | |
| .stChatInputContainer {{ | |
| background-color: {bg_color}; | |
| border: 1px solid {border_color}; | |
| border-radius: 5px; | |
| }} | |
| .stChatInputContainer input {{ | |
| background-color: {bg_color}; | |
| color: {text_color}; | |
| }} | |
| /* إزالة أي ألوان مميزة من الأفاتار */ | |
| div[data-testid="chatAvatarIcon-user"], | |
| div[data-testid="chatAvatarIcon-assistant"] {{ | |
| background-color: {border_color} !important; | |
| color: {text_color} !important; | |
| border: 1px solid {border_color}; | |
| }} | |
| /* خط فاصل بسيط */ | |
| hr {{ | |
| border-color: {border_color} !important; | |
| }} | |
| /* رسائل الشات - بدون تمييز */ | |
| div[data-testid="stChatMessage"] {{ | |
| border: none; | |
| border-bottom: 1px solid {border_color}; | |
| }} | |
| /* إزالة أي ألوان من الروابط */ | |
| a {{ | |
| color: {text_color} !important; | |
| text-decoration: underline; | |
| }} | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # مفتاح API | |
| API_KEY = "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" | |
| # تهيئة العميل | |
| client = OpenAI( | |
| base_url="https://integrate.api.nvidia.com/v1", | |
| api_key=API_KEY | |
| ) | |
| # تهيئة حالة المحادثات | |
| if "conversations" not in st.session_state: | |
| st.session_state.conversations = [] | |
| if "current_chat_id" not in st.session_state: | |
| st.session_state.current_chat_id = None | |
| if "messages" not in st.session_state: | |
| st.session_state.messages = [] | |
| # محاولة تحميل المحادثات من localStorage | |
| st.components.v1.html(""" | |
| <script> | |
| const conversations = localStorage.getItem('genisi_conversations'); | |
| if (conversations) { | |
| window.parent.postMessage({ | |
| type: 'streamlit:setComponentValue', | |
| value: conversations | |
| }, '*'); | |
| } | |
| </script> | |
| """, height=0) | |
| # الشريط الجانبي - قائمة المحادثات | |
| with st.sidebar: | |
| st.markdown(f'<p style="color: {text_color}; font-size: 20px; font-weight: bold; text-align: center; padding: 20px 20px 5px;">🤖 Genisi</p>', unsafe_allow_html=True) | |
| st.markdown(f'<p style="color: {text_color}; text-align: center; margin-top: -5px;">by AnesNT</p>', unsafe_allow_html=True) | |
| # زر محادثة جديدة | |
| if st.button("➕ محادثة جديدة", use_container_width=True): | |
| new_chat = { | |
| "id": str(time.time()), | |
| "title": f"محادثة جديدة {len(st.session_state.conversations) + 1}", | |
| "messages": [], | |
| "created_at": time.strftime("%Y-%m-%d %H:%M") | |
| } | |
| st.session_state.conversations.append(new_chat) | |
| st.session_state.current_chat_id = new_chat["id"] | |
| st.session_state.messages = [] | |
| st.components.v1.html(f""" | |
| <script> | |
| let conversations = JSON.parse(localStorage.getItem('genisi_conversations') || '[]'); | |
| conversations.push({json.dumps(new_chat)}); | |
| localStorage.setItem('genisi_conversations', JSON.stringify(conversations)); | |
| </script> | |
| """, height=0) | |
| st.rerun() | |
| st.markdown("---") | |
| # عرض قائمة المحادثات | |
| if st.session_state.conversations: | |
| for conv in reversed(st.session_state.conversations): | |
| # تحديد عنوان المحادثة | |
| title = conv["title"] | |
| if conv["messages"] and len(conv["messages"]) > 0: | |
| first_msg = conv["messages"][0]["content"][:30] | |
| title = first_msg + "..." if len(first_msg) >= 30 else first_msg | |
| # تاريخ المحادثة | |
| created_at = conv.get("created_at", "") | |
| # تنسيق المحادثة | |
| col1, col2, col3 = st.columns([5, 1, 1]) | |
| with col1: | |
| if st.button(f"💬 {title}", key=f"chat_{conv['id']}", use_container_width=True): | |
| st.session_state.current_chat_id = conv["id"] | |
| st.session_state.messages = conv["messages"] | |
| st.rerun() | |
| with col2: | |
| if st.button("📋", key=f"copy_{conv['id']}", help="نسخ المحادثة"): | |
| chat_text = "\n".join([f"{m['role']}: {m['content']}" for m in conv["messages"]]) | |
| st.components.v1.html(f""" | |
| <script> | |
| navigator.clipboard.writeText({json.dumps(chat_text)}); | |
| alert('تم نسخ المحادثة!'); | |
| </script> | |
| """, height=0) | |
| with col3: | |
| if st.button("🗑️", key=f"delete_{conv['id']}", help="حذف المحادثة"): | |
| st.session_state.conversations = [c for c in st.session_state.conversations if c["id"] != conv["id"]] | |
| st.components.v1.html(f""" | |
| <script> | |
| let conversations = JSON.parse(localStorage.getItem('genisi_conversations') || '[]'); | |
| conversations = conversations.filter(c => c.id !== '{conv['id']}'); | |
| localStorage.setItem('genisi_conversations', JSON.stringify(conversations)); | |
| </script> | |
| """, height=0) | |
| if conv["id"] == st.session_state.current_chat_id: | |
| st.session_state.current_chat_id = None | |
| st.session_state.messages = [] | |
| st.rerun() | |
| # عرض تاريخ المحادثة | |
| if created_at: | |
| st.markdown(f'<p style="color: {text_color}; font-size: 11px; margin: -5px 0 10px 25px;">{created_at}</p>', unsafe_allow_html=True) | |
| else: | |
| st.markdown(f'<p style="color: {text_color}; text-align: center; padding: 20px;">لا توجد محادثات سابقة</p>', unsafe_allow_html=True) | |
| # المحتوى الرئيسي | |
| st.markdown(f'<div class="chat-title">🤖 Genisi - AI Assistant by AnesNT</div>', unsafe_allow_html=True) | |
| # عرض المحادثة الحالية | |
| for msg in st.session_state.messages: | |
| with st.chat_message(msg["role"]): | |
| st.markdown(msg["content"]) | |
| # مربع الإدخال | |
| if prompt := st.chat_input("اكتب سؤالك هنا..."): | |
| # عرض سؤال المستخدم | |
| st.chat_message("user").markdown(prompt) | |
| st.session_state.messages.append({"role": "user", "content": prompt}) | |
| # تحديث المحادثة الحالية | |
| if st.session_state.current_chat_id: | |
| for conv in st.session_state.conversations: | |
| if conv["id"] == st.session_state.current_chat_id: | |
| conv["messages"] = st.session_state.messages | |
| break | |
| else: | |
| # إنشاء محادثة جديدة | |
| new_chat = { | |
| "id": str(time.time()), | |
| "title": prompt[:30] + "..." if len(prompt) > 30 else prompt, | |
| "messages": st.session_state.messages, | |
| "created_at": time.strftime("%Y-%m-%d %H:%M") | |
| } | |
| st.session_state.conversations.append(new_chat) | |
| st.session_state.current_chat_id = new_chat["id"] | |
| st.components.v1.html(f""" | |
| <script> | |
| let conversations = JSON.parse(localStorage.getItem('genisi_conversations') || '[]'); | |
| conversations.push({json.dumps(new_chat)}); | |
| localStorage.setItem('genisi_conversations', JSON.stringify(conversations)); | |
| </script> | |
| """, height=0) | |
| # رد المساعد | |
| with st.chat_message("assistant"): | |
| msg_placeholder = st.empty() | |
| full = "" | |
| try: | |
| # استدعاء API | |
| completion = client.chat.completions.create( | |
| model="moonshotai/kimi-k2-instruct", | |
| messages=st.session_state.messages, | |
| temperature=0.5, | |
| stream=True | |
| ) | |
| # تجميع الرد | |
| for chunk in completion: | |
| if chunk.choices and chunk.choices[0].delta.content: | |
| full += chunk.choices[0].delta.content | |
| msg_placeholder.markdown(full + "▌") | |
| time.sleep(0.01) | |
| msg_placeholder.markdown(full) | |
| st.session_state.messages.append({"role": "assistant", "content": full}) | |
| # تحديث المحادثة الحالية | |
| for conv in st.session_state.conversations: | |
| if conv["id"] == st.session_state.current_chat_id: | |
| conv["messages"] = st.session_state.messages | |
| st.components.v1.html(f""" | |
| <script> | |
| let conversations = JSON.parse(localStorage.getItem('genisi_conversations') || '[]'); | |
| const index = conversations.findIndex(c => c.id === '{conv["id"]}'); | |
| if (index !== -1) {{ | |
| conversations[index] = {json.dumps(conv)}; | |
| localStorage.setItem('genisi_conversations', JSON.stringify(conversations)); | |
| }} | |
| </script> | |
| """, height=0) | |
| break | |
| except Exception as e: | |
| st.error(f"حدث خطأ: {str(e)}") | |
| # معلومات المطور | |
| st.markdown(f'<div class="developer-info"> Genisi is an AI can make mistakes </div>', unsafe_allow_html=True) |