uumerrr684 commited on
Commit
af3360e
Β·
verified Β·
1 Parent(s): b2c0738

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +345 -170
app.py CHANGED
@@ -10,146 +10,342 @@ import uuid
10
  st.set_page_config(
11
  page_title="Chat Flow πŸ•·",
12
  page_icon="πŸ’¬",
13
- initial_sidebar_state="collapsed"
 
14
  )
15
 
16
- # CSS - Keep original web design, add mobile responsiveness only
17
  st.markdown("""
18
  <style>
 
 
 
 
19
  .stApp {
20
- background: white;
 
 
21
  }
22
 
 
23
  .main .block-container {
24
- max-width: 800px;
 
25
  }
26
 
 
27
  #MainMenu {visibility: hidden;}
28
  footer {visibility: hidden;}
29
  header {visibility: hidden;}
30
  .stDeployButton {display: none;}
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  .model-id {
33
- color: #28a745;
34
- font-family: monospace;
 
 
 
 
 
35
  }
36
 
37
  .model-attribution {
38
- color: #28a745;
39
  font-size: 0.8em;
40
  font-style: italic;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  }
42
 
43
- /* MOBILE ONLY - doesn't affect web */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  @media (max-width: 768px) {
45
- .stApp {
46
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
47
- }
48
-
49
  .main .block-container {
 
50
  max-width: 100%;
51
- padding: 0.5rem;
52
- }
53
-
54
- /* Make sidebar work better on mobile */
55
- .css-1d391kg {
56
- width: 100% !important;
57
- background: rgba(255, 255, 255, 0.95);
58
- backdrop-filter: blur(10px);
59
- }
60
-
61
- /* Mobile text sizing */
62
- .stMarkdown {
63
- font-size: 14px !important;
64
- color: #333 !important;
65
  }
66
 
67
  h1 {
68
- font-size: 1.5rem !important;
69
- color: white;
70
- text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
71
- text-align: center;
72
- }
73
-
74
- .stCaption {
75
- color: rgba(255, 255, 255, 0.8);
76
- text-align: center;
77
- }
78
-
79
- /* Mobile buttons */
80
- .stButton button {
81
- border-radius: 8px;
82
- font-size: 14px;
83
  }
84
 
85
- /* Chat input for mobile */
86
- .stChatInput {
87
- background: rgba(255, 255, 255, 0.9);
88
- border-radius: 20px;
89
- backdrop-filter: blur(10px);
90
- }
91
-
92
- .stChatInput input {
93
- font-size: 16px; /* Prevents zoom on iOS */
94
  }
95
 
96
- /* Chat messages - SIMPLE styling that works */
97
- [data-testid="chat-message-user"] {
98
- background: #007bff !important;
99
- color: white !important;
100
- border-radius: 10px !important;
101
- padding: 10px !important;
102
- margin: 5px 0 !important;
103
  }
104
 
105
- [data-testid="chat-message-user"] .stMarkdown {
106
- color: white !important;
 
107
  }
108
 
109
- [data-testid="chat-message-assistant"] {
110
- background: white !important;
111
- color: #333 !important;
112
- border-radius: 10px !important;
113
- padding: 10px !important;
114
- margin: 5px 0 !important;
115
- border: 1px solid #ddd !important;
116
  }
117
 
118
- [data-testid="chat-message-assistant"] .stMarkdown {
119
- color: #333 !important;
120
  }
121
  }
122
 
123
- /* Extra small screens (iPhone 5, old phones) */
124
  @media (max-width: 480px) {
125
- .main .block-container {
126
- padding: 0.25rem;
127
- }
128
-
129
- .stChatMessage {
130
- padding: 0.75rem;
131
- margin: 0.25rem 0;
132
- }
133
-
134
- .stChatMessage[data-testid="user-message"] {
135
- margin-left: 8%;
136
- }
137
-
138
- .stChatMessage[data-testid="assistant-message"] {
139
- margin-right: 8%;
140
- }
141
-
142
- h1 {
143
- font-size: 1.3rem !important;
144
  }
145
 
146
- .stButton button {
147
- font-size: 12px;
148
- padding: 0.4rem;
149
  }
150
 
151
- .stMarkdown {
152
- font-size: 13px;
153
  }
154
  }
155
  </style>
@@ -191,23 +387,21 @@ def clear_chat_history():
191
  def get_user_id():
192
  """Get unique ID for this user session"""
193
  if 'user_id' not in st.session_state:
194
- st.session_state.user_id = str(uuid.uuid4())[:8] # Short ID for family use
195
  return st.session_state.user_id
196
 
197
  def update_online_users():
198
  """Update that this user is online right now"""
199
  try:
200
- # Load current online users
201
  users = {}
202
  if os.path.exists(USERS_FILE):
203
  with open(USERS_FILE, 'r') as f:
204
  users = json.load(f)
205
 
206
- # Add/update this user
207
  user_id = get_user_id()
208
  users[user_id] = {
209
  'last_seen': datetime.now().isoformat(),
210
- 'name': f'User-{user_id}' # You can customize this
211
  }
212
 
213
  # Remove users not seen in last 5 minutes
@@ -218,13 +412,12 @@ def update_online_users():
218
  if current_time - last_seen < timedelta(minutes=5):
219
  active_users[uid] = data
220
 
221
- # Save updated list
222
  with open(USERS_FILE, 'w') as f:
223
  json.dump(active_users, f, indent=2)
224
 
225
  return len(active_users)
226
  except Exception:
227
- return 1 # If error, assume at least you're online
228
 
229
  def get_online_count():
230
  """Get number of people currently online"""
@@ -235,7 +428,6 @@ def get_online_count():
235
  with open(USERS_FILE, 'r') as f:
236
  users = json.load(f)
237
 
238
- # Check who's still active (last 5 minutes)
239
  current_time = datetime.now()
240
  active_count = 0
241
  for data in users.values():
@@ -274,11 +466,10 @@ def get_ai_response(messages, model="openai/gpt-3.5-turbo"):
274
  headers = {
275
  "Content-Type": "application/json",
276
  "Authorization": f"Bearer {OPENROUTER_API_KEY}",
277
- "HTTP-Referer": "http://localhost:8501", # Optional: Your site URL
278
- "X-Title": "Streamlit AI Assistant" # Optional: Your app name
279
  }
280
 
281
- # Create system message and user messages
282
  api_messages = [{"role": "system", "content": "You are a helpful AI assistant. Provide clear and helpful responses."}]
283
  api_messages.extend(messages)
284
 
@@ -296,7 +487,6 @@ def get_ai_response(messages, model="openai/gpt-3.5-turbo"):
296
  try:
297
  response = requests.post(url, headers=headers, json=data, stream=True, timeout=60)
298
 
299
- # Better error handling
300
  if response.status_code != 200:
301
  error_detail = ""
302
  try:
@@ -309,12 +499,9 @@ def get_ai_response(messages, model="openai/gpt-3.5-turbo"):
309
  return
310
 
311
  full_response = ""
312
- buffer = ""
313
 
314
- # Using your working streaming logic
315
  for line in response.iter_lines():
316
  if line:
317
- # The server sends lines starting with "data: ..."
318
  if line.startswith(b"data: "):
319
  data_str = line[len(b"data: "):].decode("utf-8")
320
  if data_str.strip() == "[DONE]":
@@ -345,40 +532,35 @@ st.caption("10 powerful Models, one simple chat.")
345
 
346
  # Sidebar
347
  with st.sidebar:
348
- st.header("Settings")
349
 
350
  # API Status
351
  status = check_api_status()
352
  if status == "Connected":
353
  st.success("🟒 API Connected")
354
  elif status == "No API Key":
355
- st.error("No API Key")
356
  else:
357
- st.warning("Connection Issue")
358
 
359
  st.divider()
360
 
361
  # Live Users Section
362
- st.header("πŸ‘₯ Who's Online")
363
-
364
- # Update that you're online
365
  online_count = update_online_users()
366
 
367
- # Show live count
368
  if online_count == 1:
369
  st.info("🟒 Just you online")
370
  else:
371
  st.success(f"🟒 {online_count} people online")
372
 
373
- # Show your session
374
  your_id = get_user_id()
375
  st.caption(f"You: User-{your_id}")
376
 
377
- # Quick refresh button
378
- if st.button("Refresh", use_container_width=True):
379
  st.rerun()
380
 
381
- # Debug Section
382
  with st.expander("πŸ” Debug Info"):
383
  if os.path.exists(USERS_FILE):
384
  with open(USERS_FILE, 'r') as f:
@@ -394,7 +576,8 @@ with st.sidebar:
394
 
395
  st.divider()
396
 
397
- # All models including new ones
 
398
  models = [
399
  ("GPT-3.5 Turbo", "openai/gpt-3.5-turbo"),
400
  ("LLaMA 3.1 8B", "meta-llama/llama-3.1-8b-instruct"),
@@ -411,75 +594,75 @@ with st.sidebar:
411
  model_names = [name for name, _ in models]
412
  model_ids = [model_id for _, model_id in models]
413
 
414
- selected_index = st.selectbox("Model", range(len(model_names)),
415
  format_func=lambda x: model_names[x],
416
  index=0)
417
  selected_model = model_ids[selected_index]
418
 
419
- # Show selected model ID in green
420
  st.markdown(f"**Model ID:** <span class='model-id'>{selected_model}</span>", unsafe_allow_html=True)
421
 
422
  st.divider()
423
 
424
  # Chat History Controls
425
- st.header("Chat History")
426
 
427
- # Show number of messages
428
  if st.session_state.messages:
429
- st.info(f"Messages stored: {len(st.session_state.messages)}")
430
 
431
- # Auto-save toggle
432
  auto_save = st.checkbox("Auto-save messages", value=True)
433
 
434
- # Manual save/load buttons
435
  col1, col2 = st.columns(2)
436
  with col1:
437
- if st.button("Save History", use_container_width=True):
438
  save_chat_history(st.session_state.messages)
439
- st.success("History saved!")
440
 
441
  with col2:
442
- if st.button("Load History", use_container_width=True):
443
  st.session_state.messages = load_chat_history()
444
- st.success("History loaded!")
445
  st.rerun()
446
 
447
- st.divider()
448
-
449
- # View History
450
- if st.button("View History File", use_container_width=True):
 
 
 
 
 
451
  if os.path.exists(HISTORY_FILE):
452
- with open(HISTORY_FILE, 'r', encoding='utf-8') as f:
453
- history_content = f.read()
454
- st.text_area("Chat History (JSON)", history_content, height=200)
455
- else:
456
- st.warning("No history file found")
457
-
458
- # Download History
459
- if os.path.exists(HISTORY_FILE):
460
- with open(HISTORY_FILE, 'rb') as f:
461
- st.download_button(
462
- label="Download History",
463
- data=f.read(),
464
- file_name=f"chat_history_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
465
- mime="application/json",
466
- use_container_width=True
467
- )
468
-
469
- st.divider()
470
-
471
- # Clear controls
472
- if st.button("Clear Chat", use_container_width=True, type="secondary"):
473
- clear_chat_history()
474
- st.success("Chat cleared!")
475
- st.rerun()
 
476
 
477
  # Display chat messages
478
  for message in st.session_state.messages:
479
  with st.chat_message(message["role"]):
480
- # Check if this is an assistant message with attribution
481
  if message["role"] == "assistant" and "Response created by:" in message["content"]:
482
- # Split content and attribution
483
  parts = message["content"].split("\n\n---\n*Response created by:")
484
  main_content = parts[0]
485
  if len(parts) > 1:
@@ -492,23 +675,18 @@ for message in st.session_state.messages:
492
  st.markdown(message["content"])
493
 
494
  # Chat input
495
- if prompt := st.chat_input("Chat Smarter. Chat many Brains"):
496
- # Update online status when user sends message
497
  update_online_users()
498
 
499
- # Add user message
500
  user_message = {"role": "user", "content": prompt}
501
  st.session_state.messages.append(user_message)
502
 
503
- # Auto-save if enabled
504
  if auto_save:
505
  save_chat_history(st.session_state.messages)
506
 
507
- # Display user message
508
  with st.chat_message("user"):
509
  st.markdown(prompt)
510
 
511
- # Get AI response
512
  with st.chat_message("assistant"):
513
  placeholder = st.empty()
514
 
@@ -518,7 +696,6 @@ if prompt := st.chat_input("Chat Smarter. Chat many Brains"):
518
  full_response = response
519
  placeholder.markdown(full_response + "β–Œ")
520
 
521
- # Remove cursor and show final response
522
  placeholder.markdown(full_response)
523
 
524
  except Exception as e:
@@ -526,14 +703,12 @@ if prompt := st.chat_input("Chat Smarter. Chat many Brains"):
526
  placeholder.markdown(error_msg)
527
  full_response = error_msg
528
 
529
- # Add AI response to messages with attribution
530
  full_response_with_attribution = full_response + f"\n\n---\n*Response created by: **{model_names[selected_index]}***"
531
  assistant_message = {"role": "assistant", "content": full_response_with_attribution}
532
  st.session_state.messages.append(assistant_message)
533
 
534
- # Auto-save if enabled
535
  if auto_save:
536
  save_chat_history(st.session_state.messages)
537
 
538
- # Show currently using model
539
  st.caption(f"Currently using: **{model_names[selected_index]}**")
 
10
  st.set_page_config(
11
  page_title="Chat Flow πŸ•·",
12
  page_icon="πŸ’¬",
13
+ initial_sidebar_state="collapsed",
14
+ layout="wide"
15
  )
16
 
17
+ # Dark theme CSS matching the BuildHub design
18
  st.markdown("""
19
  <style>
20
+ /* Import Google Fonts for modern typography */
21
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
22
+
23
+ /* Main app dark theme */
24
  .stApp {
25
+ background: linear-gradient(135deg, #1a1a1a 0%, #2d2d2d 100%);
26
+ font-family: 'Inter', sans-serif;
27
+ color: #ffffff;
28
  }
29
 
30
+ /* Container styling */
31
  .main .block-container {
32
+ max-width: 1200px;
33
+ padding: 2rem;
34
  }
35
 
36
+ /* Hide Streamlit elements */
37
  #MainMenu {visibility: hidden;}
38
  footer {visibility: hidden;}
39
  header {visibility: hidden;}
40
  .stDeployButton {display: none;}
41
 
42
+ /* Dark sidebar with golden accents */
43
+ .css-1d391kg {
44
+ background: linear-gradient(180deg, #1f1f1f 0%, #2a2a2a 100%);
45
+ border-right: 1px solid #333;
46
+ padding: 1rem;
47
+ }
48
+
49
+ .css-1d391kg .stMarkdown {
50
+ color: #ffffff;
51
+ }
52
+
53
+ /* Title styling with golden accent */
54
+ h1 {
55
+ color: #ffd700;
56
+ font-weight: 700;
57
+ font-size: 2.5rem;
58
+ text-align: center;
59
+ margin-bottom: 0.5rem;
60
+ text-shadow: 0 0 20px rgba(255, 215, 0, 0.3);
61
+ }
62
+
63
+ .stCaption {
64
+ color: #cccccc;
65
+ text-align: center;
66
+ font-size: 1.1rem;
67
+ margin-bottom: 2rem;
68
+ }
69
+
70
+ /* Chat messages with modern dark styling */
71
+ [data-testid="chat-message-user"] {
72
+ background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
73
+ color: #1a1a1a;
74
+ border-radius: 20px;
75
+ padding: 1rem 1.5rem;
76
+ margin: 1rem 0;
77
+ margin-left: 20%;
78
+ box-shadow: 0 4px 15px rgba(255, 215, 0, 0.2);
79
+ border: 1px solid rgba(255, 215, 0, 0.3);
80
+ }
81
+
82
+ [data-testid="chat-message-user"] .stMarkdown {
83
+ color: #1a1a1a;
84
+ font-weight: 500;
85
+ }
86
+
87
+ [data-testid="chat-message-assistant"] {
88
+ background: linear-gradient(135deg, #2a2a2a 0%, #3a3a3a 100%);
89
+ color: #ffffff;
90
+ border-radius: 20px;
91
+ padding: 1rem 1.5rem;
92
+ margin: 1rem 0;
93
+ margin-right: 20%;
94
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
95
+ border: 1px solid #444;
96
+ }
97
+
98
+ [data-testid="chat-message-assistant"] .stMarkdown {
99
+ color: #ffffff;
100
+ }
101
+
102
+ /* Chat input with dark theme */
103
+ .stChatInput {
104
+ background: linear-gradient(135deg, #2a2a2a 0%, #3a3a3a 100%);
105
+ border-radius: 25px;
106
+ border: 1px solid #444;
107
+ box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
108
+ }
109
+
110
+ .stChatInput input {
111
+ background: transparent;
112
+ color: #ffffff;
113
+ border: none;
114
+ font-size: 16px;
115
+ padding: 1rem 1.5rem;
116
+ }
117
+
118
+ .stChatInput input::placeholder {
119
+ color: #888;
120
+ }
121
+
122
+ /* Sidebar sections */
123
+ .css-1d391kg h1, .css-1d391kg h2, .css-1d391kg h3 {
124
+ color: #ffd700;
125
+ font-weight: 600;
126
+ }
127
+
128
+ /* Status indicators with golden theme */
129
+ .stSuccess {
130
+ background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
131
+ color: #1a1a1a;
132
+ border: none;
133
+ border-radius: 10px;
134
+ }
135
+
136
+ .stInfo {
137
+ background: linear-gradient(135deg, #4a90e2 0%, #357abd 100%);
138
+ color: #ffffff;
139
+ border: none;
140
+ border-radius: 10px;
141
+ }
142
+
143
+ .stError {
144
+ background: linear-gradient(135deg, #ff6b6b 0%, #ee5a52 100%);
145
+ color: #ffffff;
146
+ border: none;
147
+ border-radius: 10px;
148
+ }
149
+
150
+ .stWarning {
151
+ background: linear-gradient(135deg, #ffa726 0%, #ff9800 100%);
152
+ color: #1a1a1a;
153
+ border: none;
154
+ border-radius: 10px;
155
+ }
156
+
157
+ /* Buttons with golden accent */
158
+ .stButton button {
159
+ background: linear-gradient(135deg, #ffd700 0%, #ffed4e 100%);
160
+ color: #1a1a1a;
161
+ border: none;
162
+ border-radius: 12px;
163
+ font-weight: 600;
164
+ padding: 0.75rem 1.5rem;
165
+ transition: all 0.3s ease;
166
+ box-shadow: 0 2px 10px rgba(255, 215, 0, 0.2);
167
+ }
168
+
169
+ .stButton button:hover {
170
+ transform: translateY(-2px);
171
+ box-shadow: 0 4px 20px rgba(255, 215, 0, 0.4);
172
+ }
173
+
174
+ /* Secondary buttons */
175
+ .stButton button[kind="secondary"] {
176
+ background: linear-gradient(135deg, #444 0%, #555 100%);
177
+ color: #ffffff;
178
+ border: 1px solid #666;
179
+ }
180
+
181
+ .stButton button[kind="secondary"]:hover {
182
+ background: linear-gradient(135deg, #555 0%, #666 100%);
183
+ }
184
+
185
+ /* Selectbox styling */
186
+ .stSelectbox > div > div {
187
+ background: linear-gradient(135deg, #2a2a2a 0%, #3a3a3a 100%);
188
+ border: 1px solid #444;
189
+ border-radius: 10px;
190
+ color: #ffffff;
191
+ }
192
+
193
+ .stSelectbox > div > div:hover {
194
+ border-color: #ffd700;
195
+ }
196
+
197
+ /* Checkbox styling */
198
+ .stCheckbox > label {
199
+ color: #ffffff;
200
+ }
201
+
202
+ /* Text areas */
203
+ .stTextArea textarea {
204
+ background: linear-gradient(135deg, #2a2a2a 0%, #3a3a3a 100%);
205
+ color: #ffffff;
206
+ border: 1px solid #444;
207
+ border-radius: 10px;
208
+ }
209
+
210
+ /* Expander styling */
211
+ .streamlit-expanderHeader {
212
+ background: linear-gradient(135deg, #2a2a2a 0%, #3a3a3a 100%);
213
+ color: #ffd700;
214
+ border-radius: 10px;
215
+ border: 1px solid #444;
216
+ }
217
+
218
+ .streamlit-expanderContent {
219
+ background: #1f1f1f;
220
+ border: 1px solid #333;
221
+ border-radius: 0 0 10px 10px;
222
+ }
223
+
224
+ /* Model ID styling */
225
  .model-id {
226
+ color: #ffd700;
227
+ font-family: 'Courier New', monospace;
228
+ font-weight: bold;
229
+ background: rgba(255, 215, 0, 0.1);
230
+ padding: 0.25rem 0.5rem;
231
+ border-radius: 5px;
232
+ border: 1px solid rgba(255, 215, 0, 0.3);
233
  }
234
 
235
  .model-attribution {
236
+ color: #ffd700;
237
  font-size: 0.8em;
238
  font-style: italic;
239
+ text-align: right;
240
+ margin-top: 0.5rem;
241
+ padding-top: 0.5rem;
242
+ border-top: 1px solid #444;
243
+ }
244
+
245
+ /* Divider styling */
246
+ hr {
247
+ border-color: #444;
248
+ margin: 1.5rem 0;
249
+ }
250
+
251
+ /* Download button */
252
+ .stDownloadButton button {
253
+ background: linear-gradient(135deg, #4a90e2 0%, #357abd 100%);
254
+ color: #ffffff;
255
+ border: none;
256
+ border-radius: 10px;
257
+ font-weight: 600;
258
  }
259
 
260
+ /* Welcome message area */
261
+ .welcome-container {
262
+ display: flex;
263
+ flex-direction: column;
264
+ align-items: center;
265
+ justify-content: center;
266
+ min-height: 400px;
267
+ text-align: center;
268
+ }
269
+
270
+ .welcome-orb {
271
+ width: 120px;
272
+ height: 120px;
273
+ border-radius: 50%;
274
+ background: radial-gradient(circle at 30% 30%, #ffd700, #ffed4e, #cc8400);
275
+ display: flex;
276
+ align-items: center;
277
+ justify-content: center;
278
+ margin-bottom: 2rem;
279
+ box-shadow: 0 0 40px rgba(255, 215, 0, 0.3);
280
+ animation: pulse 2s infinite;
281
+ }
282
+
283
+ @keyframes pulse {
284
+ 0% { box-shadow: 0 0 40px rgba(255, 215, 0, 0.3); }
285
+ 50% { box-shadow: 0 0 60px rgba(255, 215, 0, 0.5); }
286
+ 100% { box-shadow: 0 0 40px rgba(255, 215, 0, 0.3); }
287
+ }
288
+
289
+ .welcome-title {
290
+ font-size: 2rem;
291
+ font-weight: 700;
292
+ color: #ffd700;
293
+ margin-bottom: 1rem;
294
+ }
295
+
296
+ .welcome-subtitle {
297
+ font-size: 1.1rem;
298
+ color: #cccccc;
299
+ margin-bottom: 2rem;
300
+ }
301
+
302
+ /* Mobile responsiveness */
303
  @media (max-width: 768px) {
 
 
 
 
304
  .main .block-container {
305
+ padding: 1rem 0.5rem;
306
  max-width: 100%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  }
308
 
309
  h1 {
310
+ font-size: 2rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
  }
312
 
313
+ [data-testid="chat-message-user"] {
314
+ margin-left: 10%;
315
+ padding: 0.75rem 1rem;
 
 
 
 
 
 
316
  }
317
 
318
+ [data-testid="chat-message-assistant"] {
319
+ margin-right: 10%;
320
+ padding: 0.75rem 1rem;
 
 
 
 
321
  }
322
 
323
+ .welcome-orb {
324
+ width: 80px;
325
+ height: 80px;
326
  }
327
 
328
+ .welcome-title {
329
+ font-size: 1.5rem;
 
 
 
 
 
330
  }
331
 
332
+ .css-1d391kg {
333
+ width: 100% !important;
334
  }
335
  }
336
 
337
+ /* Extra small screens */
338
  @media (max-width: 480px) {
339
+ [data-testid="chat-message-user"] {
340
+ margin-left: 5%;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
  }
342
 
343
+ [data-testid="chat-message-assistant"] {
344
+ margin-right: 5%;
 
345
  }
346
 
347
+ .main .block-container {
348
+ padding: 0.5rem 0.25rem;
349
  }
350
  }
351
  </style>
 
387
  def get_user_id():
388
  """Get unique ID for this user session"""
389
  if 'user_id' not in st.session_state:
390
+ st.session_state.user_id = str(uuid.uuid4())[:8]
391
  return st.session_state.user_id
392
 
393
  def update_online_users():
394
  """Update that this user is online right now"""
395
  try:
 
396
  users = {}
397
  if os.path.exists(USERS_FILE):
398
  with open(USERS_FILE, 'r') as f:
399
  users = json.load(f)
400
 
 
401
  user_id = get_user_id()
402
  users[user_id] = {
403
  'last_seen': datetime.now().isoformat(),
404
+ 'name': f'User-{user_id}'
405
  }
406
 
407
  # Remove users not seen in last 5 minutes
 
412
  if current_time - last_seen < timedelta(minutes=5):
413
  active_users[uid] = data
414
 
 
415
  with open(USERS_FILE, 'w') as f:
416
  json.dump(active_users, f, indent=2)
417
 
418
  return len(active_users)
419
  except Exception:
420
+ return 1
421
 
422
  def get_online_count():
423
  """Get number of people currently online"""
 
428
  with open(USERS_FILE, 'r') as f:
429
  users = json.load(f)
430
 
 
431
  current_time = datetime.now()
432
  active_count = 0
433
  for data in users.values():
 
466
  headers = {
467
  "Content-Type": "application/json",
468
  "Authorization": f"Bearer {OPENROUTER_API_KEY}",
469
+ "HTTP-Referer": "http://localhost:8501",
470
+ "X-Title": "Streamlit AI Assistant"
471
  }
472
 
 
473
  api_messages = [{"role": "system", "content": "You are a helpful AI assistant. Provide clear and helpful responses."}]
474
  api_messages.extend(messages)
475
 
 
487
  try:
488
  response = requests.post(url, headers=headers, json=data, stream=True, timeout=60)
489
 
 
490
  if response.status_code != 200:
491
  error_detail = ""
492
  try:
 
499
  return
500
 
501
  full_response = ""
 
502
 
 
503
  for line in response.iter_lines():
504
  if line:
 
505
  if line.startswith(b"data: "):
506
  data_str = line[len(b"data: "):].decode("utf-8")
507
  if data_str.strip() == "[DONE]":
 
532
 
533
  # Sidebar
534
  with st.sidebar:
535
+ st.header("βš™οΈ Settings")
536
 
537
  # API Status
538
  status = check_api_status()
539
  if status == "Connected":
540
  st.success("🟒 API Connected")
541
  elif status == "No API Key":
542
+ st.error("❌ No API Key")
543
  else:
544
+ st.warning("⚠️ Connection Issue")
545
 
546
  st.divider()
547
 
548
  # Live Users Section
549
+ st.header("πŸ‘₯ Live Users")
 
 
550
  online_count = update_online_users()
551
 
 
552
  if online_count == 1:
553
  st.info("🟒 Just you online")
554
  else:
555
  st.success(f"🟒 {online_count} people online")
556
 
 
557
  your_id = get_user_id()
558
  st.caption(f"You: User-{your_id}")
559
 
560
+ if st.button("πŸ”„ Refresh", use_container_width=True):
 
561
  st.rerun()
562
 
563
+ # Debug section
564
  with st.expander("πŸ” Debug Info"):
565
  if os.path.exists(USERS_FILE):
566
  with open(USERS_FILE, 'r') as f:
 
576
 
577
  st.divider()
578
 
579
+ # Model Selection
580
+ st.header("πŸ€– AI Models")
581
  models = [
582
  ("GPT-3.5 Turbo", "openai/gpt-3.5-turbo"),
583
  ("LLaMA 3.1 8B", "meta-llama/llama-3.1-8b-instruct"),
 
594
  model_names = [name for name, _ in models]
595
  model_ids = [model_id for _, model_id in models]
596
 
597
+ selected_index = st.selectbox("Choose Model", range(len(model_names)),
598
  format_func=lambda x: model_names[x],
599
  index=0)
600
  selected_model = model_ids[selected_index]
601
 
 
602
  st.markdown(f"**Model ID:** <span class='model-id'>{selected_model}</span>", unsafe_allow_html=True)
603
 
604
  st.divider()
605
 
606
  # Chat History Controls
607
+ st.header("πŸ’¬ Chat History")
608
 
 
609
  if st.session_state.messages:
610
+ st.info(f"πŸ“ {len(st.session_state.messages)} messages stored")
611
 
 
612
  auto_save = st.checkbox("Auto-save messages", value=True)
613
 
 
614
  col1, col2 = st.columns(2)
615
  with col1:
616
+ if st.button("πŸ’Ύ Save", use_container_width=True):
617
  save_chat_history(st.session_state.messages)
618
+ st.success("Saved!")
619
 
620
  with col2:
621
+ if st.button("πŸ“‚ Load", use_container_width=True):
622
  st.session_state.messages = load_chat_history()
623
+ st.success("Loaded!")
624
  st.rerun()
625
 
626
+ with st.expander("πŸ“‹ More Options"):
627
+ if st.button("πŸ‘οΈ View History File", use_container_width=True):
628
+ if os.path.exists(HISTORY_FILE):
629
+ with open(HISTORY_FILE, 'r', encoding='utf-8') as f:
630
+ history_content = f.read()
631
+ st.text_area("Chat History (JSON)", history_content, height=150)
632
+ else:
633
+ st.warning("No history file found")
634
+
635
  if os.path.exists(HISTORY_FILE):
636
+ with open(HISTORY_FILE, 'rb') as f:
637
+ st.download_button(
638
+ label="⬇️ Download History",
639
+ data=f.read(),
640
+ file_name=f"chat_history_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json",
641
+ mime="application/json",
642
+ use_container_width=True
643
+ )
644
+
645
+ if st.button("πŸ—‘οΈ Clear Chat", use_container_width=True, type="secondary"):
646
+ clear_chat_history()
647
+ st.success("Chat cleared!")
648
+ st.rerun()
649
+
650
+ # Welcome message when no messages
651
+ if not st.session_state.messages:
652
+ st.markdown("""
653
+ <div class="welcome-container">
654
+ <div class="welcome-orb">
655
+ <span style="font-size: 3rem;">πŸ•·</span>
656
+ </div>
657
+ <div class="welcome-title">Welcome back!</div>
658
+ <div class="welcome-subtitle">Which AI model do you want to chat with today?</div>
659
+ </div>
660
+ """, unsafe_allow_html=True)
661
 
662
  # Display chat messages
663
  for message in st.session_state.messages:
664
  with st.chat_message(message["role"]):
 
665
  if message["role"] == "assistant" and "Response created by:" in message["content"]:
 
666
  parts = message["content"].split("\n\n---\n*Response created by:")
667
  main_content = parts[0]
668
  if len(parts) > 1:
 
675
  st.markdown(message["content"])
676
 
677
  # Chat input
678
+ if prompt := st.chat_input("Tell us about your capabilities..."):
 
679
  update_online_users()
680
 
 
681
  user_message = {"role": "user", "content": prompt}
682
  st.session_state.messages.append(user_message)
683
 
 
684
  if auto_save:
685
  save_chat_history(st.session_state.messages)
686
 
 
687
  with st.chat_message("user"):
688
  st.markdown(prompt)
689
 
 
690
  with st.chat_message("assistant"):
691
  placeholder = st.empty()
692
 
 
696
  full_response = response
697
  placeholder.markdown(full_response + "β–Œ")
698
 
 
699
  placeholder.markdown(full_response)
700
 
701
  except Exception as e:
 
703
  placeholder.markdown(error_msg)
704
  full_response = error_msg
705
 
 
706
  full_response_with_attribution = full_response + f"\n\n---\n*Response created by: **{model_names[selected_index]}***"
707
  assistant_message = {"role": "assistant", "content": full_response_with_attribution}
708
  st.session_state.messages.append(assistant_message)
709
 
 
710
  if auto_save:
711
  save_chat_history(st.session_state.messages)
712
 
713
+ # Footer
714
  st.caption(f"Currently using: **{model_names[selected_index]}**")