Keeby-smilyai commited on
Commit
d79a8f4
·
verified ·
1 Parent(s): 254043f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +395 -0
app.py CHANGED
@@ -778,3 +778,398 @@ def generate_response_stream(prompt, temperature=0.7, backend=None, max_tokens=2
778
  final_tokens_per_sec = tokens_generated / elapsed if elapsed > 0 else 0
779
  yield "", False, final_tokens_per_sec, final_tokens_per_sec, False
780
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
778
  final_tokens_per_sec = tokens_generated / elapsed if elapsed > 0 else 0
779
  yield "", False, final_tokens_per_sec, final_tokens_per_sec, False
780
 
781
+
782
+ # PART 3 - Continue from Part 2
783
+
784
+ if __name__ == "__main__":
785
+ import gradio as gr
786
+
787
+ custom_css = """
788
+ .chat-container { height: 500px; overflow-y: auto; padding: 20px; background: #ffffff; border: 1px solid #e5e7eb; border-radius: 8px; }
789
+ .user-message { background: #f7f7f8; padding: 16px; margin: 12px 0; border-radius: 8px; }
790
+ .assistant-message { background: #ffffff; padding: 16px; margin: 12px 0; border-radius: 8px; border-left: 3px solid #10a37f; }
791
+ .message-content { color: #353740; line-height: 1.6; font-size: 15px; }
792
+ .message-header { font-weight: 600; margin-bottom: 8px; color: #353740; font-size: 14px; }
793
+ .thinking-content { color: #6b7280; font-style: italic; border-left: 3px solid #d1d5db; padding-left: 12px; margin: 8px 0; background: #f9fafb; padding: 8px 12px; border-radius: 4px; }
794
+ .plan-badge { display: inline-block; padding: 4px 12px; border-radius: 12px; font-size: 12px; font-weight: 600; margin-left: 8px; }
795
+ .plan-free { background: #e0e7ff; color: #3730a3; }
796
+ .plan-plus { background: #dbeafe; color: #1e40af; }
797
+ .plan-pro { background: #fef3c7; color: #92400e; }
798
+ .limits-panel { background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 8px; padding: 16px; margin: 12px 0; }
799
+ .limit-item { display: flex; justify-content: space-between; padding: 8px 0; border-bottom: 1px solid #e5e7eb; }
800
+ .limit-item:last-child { border-bottom: none; }
801
+ .limit-exceeded { color: #dc2626; font-weight: 600; }
802
+ .limit-ok { color: #059669; }
803
+ .circular-btn { width: 48px !important; height: 48px !important; min-width: 48px !important; border-radius: 50% !important; padding: 0 !important; display: flex !important; align-items: center !important; justify-content: center !important; font-size: 20px !important; box-shadow: 0 2px 8px rgba(0,0,0,0.15) !important; transition: all 0.2s ease !important; }
804
+ .circular-btn:hover:not(:disabled) { transform: scale(1.05) !important; box-shadow: 0 4px 12px rgba(0,0,0,0.2) !important; }
805
+ .send-btn { background: linear-gradient(135deg, #10a37f 0%, #0d8c6c 100%) !important; border: none !important; }
806
+ .stop-btn { background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%) !important; border: none !important; }
807
+ .announcement-banner { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 20px 28px; border-radius: 12px; margin-bottom: 20px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); text-align: center; font-size: 16px; font-weight: 500; line-height: 1.6; }
808
+ """
809
+
810
+ def format_message_html(role, content, show_thinking=True):
811
+ role_class = "user-message" if role == "user" else "assistant-message"
812
+ role_name = "You" if role == "user" else "SAM-X-1"
813
+ thinking = ""
814
+ answer = ""
815
+ if "<think>" in content:
816
+ parts = content.split("<think>", 1)
817
+ before_think = parts[0].strip()
818
+ if len(parts) > 1:
819
+ after_think = parts[1]
820
+ if "</think>" in after_think:
821
+ think_parts = after_think.split("</think>", 1)
822
+ thinking = think_parts[0].strip()
823
+ answer = (before_think + " " + think_parts[1]).strip()
824
+ elif "<think/>" in after_think:
825
+ think_parts = after_think.split("<think/>", 1)
826
+ thinking = think_parts[0].strip()
827
+ answer = (before_think + " " + think_parts[1]).strip()
828
+ else:
829
+ thinking = after_think.strip()
830
+ answer = before_think
831
+ else:
832
+ answer = before_think
833
+ else:
834
+ answer = content
835
+ html = f'<div class="{role_class}"><div class="message-header">{role_name}</div><div class="message-content">'
836
+ if thinking and show_thinking:
837
+ html += f'<div class="thinking-content">💭 {thinking}</div>'
838
+ if answer:
839
+ html += f'<div>{answer}</div>'
840
+ html += '</div></div>'
841
+ return html
842
+
843
+ def render_history(history, show_thinking):
844
+ html = ""
845
+ for msg in history:
846
+ html += format_message_html(msg["role"], msg["content"], show_thinking)
847
+ return html
848
+
849
+ def render_limits_panel(user_session):
850
+ if not user_session or 'user_id' not in user_session:
851
+ return ""
852
+ info = get_user_limits_info(user_session['user_id'])
853
+ if not info:
854
+ return ""
855
+ plan_badge_class = f"plan-{info['plan']}"
856
+ html = f'<div class="limits-panel"><div style="font-weight: 600; margin-bottom: 12px; font-size: 16px;">Your Plan: <span class="plan-badge {plan_badge_class}">{info["plan"].upper()}</span></div><div style="font-size: 13px; color: #6b7280; margin-bottom: 12px;">⏰ Limits reset in: <strong>{info["reset_in"]}</strong></div>'
857
+ models_info = [('NANO ⚡⚡', info['nano_used'], info['nano_limit']), ('MINI 🚀', info['mini_used'], info['mini_limit']), ('FAST ⚡', info['fast_used'], info['fast_limit']), ('LARGE 💎', info['large_used'], info['large_limit'])]
858
+ for model_name, used, limit in models_info:
859
+ if limit == -1:
860
+ status = f'<span class="limit-ok">{used} messages (Unlimited)</span>'
861
+ else:
862
+ remaining = limit - used
863
+ if remaining <= 0:
864
+ status = f'<span class="limit-exceeded">{used}/{limit} (LIMIT REACHED)</span>'
865
+ elif remaining <= 2:
866
+ status = f'<span style="color: #f59e0b; font-weight: 600;">{used}/{limit} ({remaining} left)</span>'
867
+ else:
868
+ status = f'<span class="limit-ok">{used}/{limit} ({remaining} left)</span>'
869
+ html += f'<div class="limit-item"><span style="font-weight: 500;">{model_name}</span><span>{status}</span></div>'
870
+ html += '</div>'
871
+ return html
872
+
873
+ user_session = gr.State({})
874
+
875
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(primary_hue="slate")) as demo:
876
+ gr.HTML('<div class="announcement-banner">🔐 <strong>SAM-X-1 V3.0 - SECURE ACCESS</strong> 🔐<br>✨ Sign in to unlock AI-powered conversations!<br>🆓 FREE: Nano & Mini unlimited, Fast 10/3h, Large 8/3h<br>⭐ PLUS: Nano/Mini/Fast unlimited, Large 20/3h<br>💎 PRO: Everything unlimited!</div>')
877
+
878
+ with gr.Tabs() as main_tabs:
879
+ with gr.Tab("🔐 Sign In"):
880
+ with gr.Column():
881
+ login_username = gr.Textbox(label="Username", placeholder="Enter username")
882
+ login_password = gr.Textbox(label="Password", type="password", placeholder="Enter password")
883
+ login_btn = gr.Button("Sign In", variant="primary")
884
+ login_msg = gr.Markdown("")
885
+
886
+ with gr.Tab("📝 Sign Up"):
887
+ with gr.Column():
888
+ signup_username = gr.Textbox(label="Username", placeholder="Choose a username")
889
+ signup_email = gr.Textbox(label="Email (optional)", placeholder="your@email.com")
890
+ signup_password = gr.Textbox(label="Password", type="password", placeholder="Choose a password")
891
+ signup_btn = gr.Button("Create Account", variant="primary")
892
+ signup_msg = gr.Markdown("")
893
+
894
+ with gr.Tab("💬 Chat") as chat_tab:
895
+ with gr.Row():
896
+ with gr.Column(scale=4):
897
+ user_info = gr.Markdown("Please sign in first")
898
+ with gr.Column(scale=1):
899
+ logout_btn = gr.Button("🚪 Logout", size="sm")
900
+
901
+ limits_display = gr.HTML("")
902
+
903
+ with gr.Accordion("⚙️ Settings", open=False):
904
+ with gr.Row():
905
+ model_selector = gr.Dropdown(choices=["🤖 Auto (Recommended)"], value="🤖 Auto (Recommended)", label="Model Selection", info="FREE users: Auto only. PLUS/PRO: Choose manually")
906
+ max_tokens_slider = gr.Slider(minimum=64, maximum=512, value=256, step=64, label="Max Tokens")
907
+ with gr.Row():
908
+ temperature_slider = gr.Slider(minimum=0.0, maximum=2.0, value=0.7, step=0.1, label="Temperature")
909
+ show_thinking_checkbox = gr.Checkbox(label="Show Thinking", value=True)
910
+
911
+ speed_display = gr.Textbox(label="Generation Speed", value="⚡ Ready", interactive=False)
912
+ chat_html = gr.HTML(value="", elem_classes=["chat-container"])
913
+
914
+ with gr.Row():
915
+ msg_input = gr.Textbox(placeholder="Ask me anything...", show_label=False, scale=8)
916
+ with gr.Column(scale=1, min_width=120):
917
+ with gr.Row():
918
+ send_btn = gr.Button("▶", variant="primary", elem_classes=["circular-btn", "send-btn"])
919
+ stop_btn = gr.Button("⏹", variant="stop", elem_classes=["circular-btn", "stop-btn"], interactive=False)
920
+
921
+ with gr.Row():
922
+ clear_btn = gr.Button("🗑️ Clear", size="sm")
923
+ upgrade_btn = gr.Button("⭐ Request Upgrade", size="sm", variant="primary")
924
+
925
+ with gr.Accordion("🔐 Admin Panel", visible=False, open=False) as admin_panel:
926
+ gr.Markdown("### User Management")
927
+ with gr.Tabs():
928
+ with gr.Tab("All Users"):
929
+ users_table = gr.Dataframe(headers=["ID", "Username", "Email", "Plan", "Created", "Admin"])
930
+ refresh_users_btn = gr.Button("🔄 Refresh")
931
+ with gr.Row():
932
+ admin_username = gr.Textbox(label="Username")
933
+ admin_new_plan = gr.Dropdown(choices=["free", "plus", "pro"], label="New Plan")
934
+ update_plan_btn = gr.Button("Update Plan")
935
+ admin_msg = gr.Markdown("")
936
+ with gr.Tab("Upgrade Requests"):
937
+ requests_table = gr.Dataframe(headers=["ID", "Username", "Requested Plan", "Reason", "Date"])
938
+ refresh_requests_btn = gr.Button("🔄 Refresh")
939
+ with gr.Row():
940
+ request_id_input = gr.Number(label="Request ID", precision=0)
941
+ approve_req_btn = gr.Button("✅ Approve", variant="primary")
942
+ deny_req_btn = gr.Button("❌ Deny", variant="stop")
943
+ request_msg = gr.Markdown("")
944
+
945
+ with gr.Accordion("⭐ Request Plan Upgrade", visible=False, open=False) as upgrade_panel:
946
+ upgrade_plan_choice = gr.Radio(choices=["plus", "pro"], label="Select Plan", value="plus")
947
+ upgrade_reason = gr.Textbox(label="Reason for Upgrade", placeholder="Why do you need this upgrade?", lines=3)
948
+ submit_upgrade_btn = gr.Button("Submit Request", variant="primary")
949
+ upgrade_msg = gr.Markdown("")
950
+
951
+ def handle_login(username, password):
952
+ success, user_data = authenticate_user(username, password)
953
+ if success:
954
+ return user_data, f"✅ Welcome back, {username}!", "", gr.update(selected=2)
955
+ return {}, "❌ Invalid credentials!", "", gr.update()
956
+
957
+ def handle_signup(username, email, password):
958
+ if len(username) < 3:
959
+ return "❌ Username must be at least 3 characters!"
960
+ if len(password) < 6:
961
+ return "❌ Password must be at least 6 characters!"
962
+ success, message = create_user(username, password, email)
963
+ return f"{'✅' if success else '❌'} {message}"
964
+
965
+ def load_user_interface(session):
966
+ if not session or 'user_id' not in session:
967
+ return "❌ Not logged in", "", gr.update(visible=False), gr.update(choices=["🤖 Auto (Recommended)"], value="🤖 Auto (Recommended)"), gr.update()
968
+ info = get_user_limits_info(session['user_id'])
969
+ plan_badge = f'<span class="plan-badge plan-{info["plan"]}">{info["plan"].upper()}</span>'
970
+ user_info_text = f"👤 **{session['username']}** {plan_badge}"
971
+ limits_html = render_limits_panel(session)
972
+ if info['can_choose_model']:
973
+ available_model_names = list(available_models.keys())
974
+ choices = ["🤖 Auto (Recommended)"] + available_model_names
975
+ else:
976
+ choices = ["🤖 Auto (Recommended)"]
977
+ return user_info_text, limits_html, gr.update(visible=session.get('is_admin', False)), gr.update(choices=choices, value="🤖 Auto (Recommended)"), gr.update(maximum=info['max_tokens'], value=min(256, info['max_tokens']))
978
+
979
+ def send_message_handler(message, show_thinking, temperature, model_choice, max_tokens, session):
980
+ global stop_generation
981
+ stop_generation.clear()
982
+ if not session or 'user_id' not in session:
983
+ return "", "", "❌ Not logged in", gr.update(), gr.update()
984
+ if not message.strip():
985
+ return "", "", "⚡ Ready", gr.update(interactive=True), gr.update(interactive=False)
986
+ info = get_user_limits_info(session['user_id'])
987
+ if model_choice == "🤖 Auto (Recommended)" or not info['can_choose_model']:
988
+ user_available = get_available_models_for_user(session['user_id'])
989
+ if not user_available:
990
+ return "", "", "❌ No models available (limits reached)", gr.update(interactive=True), gr.update(interactive=False)
991
+ backend = select_model_auto(message, available_models, user_available)
992
+ if not backend:
993
+ return "", "", "❌ Could not select model", gr.update(interactive=True), gr.update(interactive=False)
994
+ model_name = backend.get_name()
995
+ else:
996
+ model_name = model_choice
997
+ can_use, msg = can_use_model(session['user_id'], model_name)
998
+ if not can_use:
999
+ return "", "", f"❌ {msg}", gr.update(interactive=True), gr.update(interactive=False)
1000
+ backend = available_models[model_name]
1001
+ can_use, msg = can_use_model(session['user_id'], model_name)
1002
+ if not can_use:
1003
+ return "", "", f"❌ {msg}", gr.update(interactive=True), gr.update(interactive=False)
1004
+ increment_model_usage(session['user_id'], model_name)
1005
+ yield "", "", f"⚡ Using {model_name}...", gr.update(interactive=False), gr.update(interactive=True)
1006
+ history = [{"role": "user", "content": message}]
1007
+ yield "", render_history(history, show_thinking), f"⚡ Generating...", gr.update(interactive=False), gr.update(interactive=True)
1008
+ prompt = f"User: {message}\nSam: <think>"
1009
+ history.append({"role": "assistant", "content": "<think>"})
1010
+ actual_max_tokens = min(max_tokens, info['max_tokens'])
1011
+ last_speed = 0
1012
+ was_stopped = False
1013
+ for chunk_data in generate_response_stream(prompt, temperature, backend, actual_max_tokens):
1014
+ if len(chunk_data) == 5:
1015
+ new_chunk, in_thinking, tokens_per_sec, avg_speed, stopped = chunk_data
1016
+ if stopped:
1017
+ was_stopped = True
1018
+ break
1019
+ if new_chunk:
1020
+ history[-1]["content"] += new_chunk
1021
+ last_speed = avg_speed
1022
+ yield "", render_history(history, show_thinking), f"⚡ {tokens_per_sec:.1f} tok/s", gr.update(interactive=False), gr.update(interactive=True)
1023
+ final = f"{'🛑 Stopped' if was_stopped else '✅ Done'} - {last_speed:.1f} tok/s"
1024
+ yield "", render_history(history, show_thinking), final, gr.update(interactive=True), gr.update(interactive=False)
1025
+
1026
+ def stop_generation_handler():
1027
+ global stop_generation
1028
+ stop_generation.set()
1029
+ return "🛑 Stopping...", gr.update(interactive=False), gr.update(interactive=False)
1030
+
1031
+ def clear_chat():
1032
+ return "", "⚡ Ready", gr.update(interactive=True), gr.update(interactive=False)
1033
+
1034
+ def show_upgrade_panel():
1035
+ return gr.update(visible=True, open=True)
1036
+
1037
+ def submit_upgrade_request(plan, reason, session):
1038
+ if not session or 'user_id' not in session:
1039
+ return "❌ Not logged in"
1040
+ if not reason.strip():
1041
+ return "❌ Please provide a reason"
1042
+ success, msg = request_upgrade(session['user_id'], plan, reason)
1043
+ return f"{'✅' if success else '❌'} {msg}"
1044
+
1045
+ def load_all_users():
1046
+ users = get_all_users()
1047
+ formatted = []
1048
+ for user in users:
1049
+ formatted.append([user[0], user[1], user[2] or "N/A", user[3], user[4][:10] if user[4] else "N/A", "Yes" if user[5] else "No"])
1050
+ return formatted
1051
+
1052
+ def load_pending_requests():
1053
+ requests = get_pending_requests()
1054
+ formatted = []
1055
+ for req in requests:
1056
+ formatted.append([req[0], req[1], req[2], req[3], req[4][:10] if req[4] else "N/A"])
1057
+ return formatted
1058
+
1059
+ def admin_update_plan(username, new_plan):
1060
+ if not username or not new_plan:
1061
+ return "❌ Please fill all fields"
1062
+ success, msg = update_user_plan(username, new_plan)
1063
+ return f"{'✅' if success else '❌'} {msg}"
1064
+
1065
+ def admin_approve_request(request_id):
1066
+ if not request_id:
1067
+ return "❌ Please enter request ID"
1068
+ success, msg = approve_request(int(request_id))
1069
+ return f"{'✅' if success else '❌'} {msg}"
1070
+
1071
+ def admin_deny_request(request_id):
1072
+ if not request_id:
1073
+ return "❌ Please enter request ID"
1074
+ success, msg = deny_request(int(request_id))
1075
+ return f"{'✅' if success else '❌'} {msg}"
1076
+
1077
+ def handle_logout():
1078
+ return {}, "Please sign in", "", gr.update(selected=0)
1079
+
1080
+ login_btn.click(handle_login, [login_username, login_password], [user_session, login_msg, chat_html, main_tabs])
1081
+ signup_btn.click(handle_signup, [signup_username, signup_email, signup_password], [signup_msg])
1082
+ chat_tab.select(load_user_interface, [user_session], [user_info, limits_display, admin_panel, model_selector, max_tokens_slider])
1083
+ send_outputs = [msg_input, chat_html, speed_display, send_btn, stop_btn]
1084
+ send_btn.click(send_message_handler, [msg_input, show_thinking_checkbox, temperature_slider, model_selector, max_tokens_slider, user_session], send_outputs)
1085
+ msg_input.submit(send_message_handler, [msg_input, show_thinking_checkbox, temperature_slider, model_selector, max_tokens_slider, user_session], send_outputs)
1086
+ stop_btn.click(stop_generation_handler, outputs=[speed_display, send_btn, stop_btn])
1087
+ clear_btn.click(clear_chat, outputs=[chat_html, speed_display, send_btn, stop_btn])
1088
+ upgrade_btn.click(show_upgrade_panel, outputs=[upgrade_panel])
1089
+ submit_upgrade_btn.click(submit_upgrade_request, [upgrade_plan_choice, upgrade_reason, user_session], [upgrade_msg])
1090
+ logout_btn.click(handle_logout, outputs=[user_session, user_info, chat_html, main_tabs])
1091
+ refresh_users_btn.click(load_all_users, outputs=[users_table])
1092
+ refresh_requests_btn.click(load_pending_requests, outputs=[requests_table])
1093
+ update_plan_btn.click(admin_update_plan, [admin_username, admin_new_plan], [admin_msg])
1094
+ approve_req_btn.click(admin_approve_request, [request_id_input], [request_msg])
1095
+ deny_req_btn.click(admin_deny_request, [request_id_input], [request_msg])
1096
+
1097
+ gr.Markdown("""
1098
+ ---
1099
+ ### 📊 Plan Comparison
1100
+
1101
+ | Feature | FREE | PLUS ⭐ | PRO 💎 |
1102
+ |---------|------|---------|--------|
1103
+ | **Nano Model** | ✅ Unlimited | ✅ Unlimited | ✅ Unlimited |
1104
+ | **Mini Model** | ✅ Unlimited | ✅ Unlimited | ✅ Unlimited |
1105
+ | **Fast Model** | 10 msgs/3h | ✅ Unlimited | ✅ Unlimited |
1106
+ | **Large Model** | 8 msgs/3h | 20 msgs/3h | ✅ Unlimited |
1107
+ | **Model Selection** | 🤖 Auto only | ✅ Manual choice | ✅ Manual choice |
1108
+ | **Max Tokens** | 256 | 384 | 512 |
1109
+ | **Reset Period** | 3 hours | 3 hours | 3 hours |
1110
+
1111
+ ### 🎯 How It Works
1112
+
1113
+ 1. **Rolling 3-Hour Window**: Your limits reset 3 hours after you start using the service
1114
+ 2. **Australia Timezone**: All times are in Australian Eastern Time (Sydney)
1115
+ 3. **Smart Auto-Selection**: FREE users get optimal model selection based on query complexity
1116
+ 4. **Flexible Limits**: Nano & Mini are always available for quick questions
1117
+ 5. **Upgrade Requests**: Request PLUS or PRO access through the chat interface
1118
+
1119
+ ### 💡 Tips for FREE Users
1120
+
1121
+ - **Use Nano & Mini freely** - Perfect for most questions and coding tasks (30-40 tok/s!)
1122
+ - **Save Fast/Large for complex tasks** - You get 10 Fast and 8 Large messages per 3h window
1123
+ - **Let Auto mode decide** - It intelligently picks the right model for your question
1124
+ - **Watch your reset timer** - Plan your usage around the 3-hour window
1125
+
1126
+ ### 🔐 Admin Access
1127
+
1128
+ - **Username**: `admin`
1129
+ - **Password**: `admin123`
1130
+ - Admin can manage users, approve upgrades, and reset limits
1131
+
1132
+ ### 🚀 V3.0 Features
1133
+
1134
+ - ✅ **User Authentication** - Secure sign in/sign up system
1135
+ - ✅ **Three-Tier Plans** - FREE, PLUS, PRO with different limits
1136
+ - ✅ **Rolling 3-Hour Limits** - Fair usage based on activity
1137
+ - ✅ **Admin Panel** - Full user management and upgrade approval
1138
+ - ✅ **Smart Model Selection** - Auto mode for FREE, manual for PLUS/PRO
1139
+ - ✅ **Usage Tracking** - Monitor your message limits in real-time
1140
+ - ✅ **Australia Timezone** - All times displayed in AEST/AEDT
1141
+ - ✅ **Upgrade Requests** - In-app upgrade request system
1142
+ - ✅ **Per-Model Limits** - Separate counters for Nano, Mini, Fast, Large
1143
+ - ✅ **Dynamic Batching** - Faster UI updates (2-8 token batching)
1144
+
1145
+ ### 📝 How to Use
1146
+
1147
+ **Step 1**: Create an account (Sign Up tab)
1148
+ **Step 2**: Sign in with your credentials
1149
+ **Step 3**: Go to Chat tab and start chatting!
1150
+ **Step 4**: Monitor your limits in the limits panel
1151
+ **Step 5**: Request upgrade if you need more access
1152
+
1153
+ ### 🎓 Example Queries by Plan
1154
+
1155
+ **FREE Plan (Auto Mode):**
1156
+ - "What is Python?" → Nano (instant, unlimited)
1157
+ - "Write a hello world function" → Mini (fast, unlimited)
1158
+ - "Explain object-oriented programming" → Fast (uses 1 of 10)
1159
+ - "Prove the Pythagorean theorem" → Large (uses 1 of 8)
1160
+
1161
+ **PLUS/PRO (Manual Selection):**
1162
+ - Choose any model based on your needs
1163
+ - PLUS gets 20 Large messages per 3h
1164
+ - PRO gets unlimited everything!
1165
+
1166
+ ### 📧 Support
1167
+
1168
+ For questions or issues, contact the admin through the upgrade request system!
1169
+
1170
+ ---
1171
+
1172
+ **Made with ❤️ using SAM-X-1 Models**
1173
+ """)
1174
+
1175
+ demo.launch(debug=True, share=True)