qwerty45-uiop commited on
Commit
3e6e275
·
verified ·
1 Parent(s): e99c3ea

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +111 -457
src/streamlit_app.py CHANGED
@@ -1,64 +1,54 @@
1
  #!/usr/bin/env python3
2
  """
3
- LLM Compatibility Advisor - Streamlined with Download Sizes
4
  Author: Assistant
5
- Description: Provides device-based LLM recommendations with popular models and download sizes
6
  Requirements: streamlit, pandas, plotly, openpyxl
7
  """
8
 
9
  import streamlit as st
10
  import pandas as pd
11
  import re
12
- import plotly.express as px
13
  import plotly.graph_objects as go
14
- from typing import Optional, Tuple, List, Dict
15
 
16
- # MUST be the first Streamlit command
17
  st.set_page_config(
18
  page_title="LLM Compatibility Advisor",
19
  layout="wide",
20
- page_icon="🧠",
21
- initial_sidebar_state="expanded"
22
  )
23
-
24
- # Enhanced data loading with error handling - FIXED FILE PATH
25
  @st.cache_data
26
  def load_data():
27
- try:
28
- # Try multiple possible file locations
29
- possible_paths = [
30
- "Merged_Student_Data.csv", # Current directory
31
- "src/Merged_Student_Data.csv", # src subdirectory
32
- "./Merged_Student_Data.csv", # Explicit current directory
33
- ]
34
-
35
- df = None
36
- for path in possible_paths:
37
- try:
38
- df = pd.read_excel(path, sheet_name="Form Responses 1")
39
- st.info(f" Successfully loaded data from: {path}")
40
- break
41
- except FileNotFoundError:
42
- continue
43
-
44
- if df is None:
45
- return None, "Excel file 'Merged_Student_Data.csv' not found in any expected location. Please ensure the file is in the same directory as this script."
46
-
47
- df.columns = df.columns.str.strip()
48
- return df, None
49
-
50
- except Exception as e:
51
- return None, f"Error loading data: {str(e)}"
52
 
53
 
54
- # Enhanced RAM extraction with better parsing
55
  def extract_numeric_ram(ram) -> Optional[int]:
56
  if pd.isna(ram):
57
  return None
58
 
59
  ram_str = str(ram).lower().replace(" ", "")
60
 
61
- # Handle various formats: "8GB", "8 GB", "8gb", "8192MB", etc.
62
  gb_match = re.search(r"(\d+(?:\.\d+)?)(?:gb|g)", ram_str)
63
  if gb_match:
64
  return int(float(gb_match.group(1)))
@@ -66,182 +56,90 @@ def extract_numeric_ram(ram) -> Optional[int]:
66
  # Handle MB format
67
  mb_match = re.search(r"(\d+)(?:mb|m)", ram_str)
68
  if mb_match:
69
- return max(1, int(int(mb_match.group(1)) / 1024)) # Convert MB to GB
70
 
71
- # Handle plain numbers (assume GB)
72
  plain_match = re.search(r"(\d+)", ram_str)
73
  if plain_match:
74
  return int(plain_match.group(1))
75
 
76
  return None
77
 
78
- # Streamlined LLM database with popular models and download sizes
79
  LLM_DATABASE = {
80
  "ultra_low": { # ≤2GB
81
  "general": [
82
  {"name": "TinyLlama-1.1B-Chat", "size": "637MB", "description": "Compact chat model"},
83
- {"name": "DistilBERT-base", "size": "268MB", "description": "Efficient BERT variant"},
84
  {"name": "all-MiniLM-L6-v2", "size": "91MB", "description": "Sentence embeddings"}
85
  ],
86
  "code": [
87
- {"name": "CodeT5-small", "size": "242MB", "description": "Code generation"},
88
- {"name": "Replit-code-v1-3B", "size": "1.2GB", "description": "Code completion"}
89
  ]
90
  },
91
  "low": { # 3-4GB
92
  "general": [
93
  {"name": "Phi-1.5", "size": "2.8GB", "description": "Microsoft's efficient model"},
94
- {"name": "Gemma-2B", "size": "1.4GB", "description": "Google's compact model"},
95
- {"name": "OpenLLaMA-3B", "size": "2.1GB", "description": "Open source LLaMA"}
96
- ],
97
- "code": [
98
- {"name": "CodeGen-2B", "size": "1.8GB", "description": "Salesforce code model"},
99
- {"name": "StarCoder-1B", "size": "1.1GB", "description": "BigCode project"}
100
- ],
101
- "chat": [
102
- {"name": "Alpaca-3B", "size": "2.0GB", "description": "Stanford's instruction model"},
103
- {"name": "Vicuna-3B", "size": "2.1GB", "description": "ChatGPT-style training"}
104
- ]
105
- },
106
- "moderate_low": { # 5-6GB
107
- "general": [
108
- {"name": "Phi-2", "size": "5.2GB", "description": "Microsoft's 2.7B model"},
109
- {"name": "Gemma-7B-it", "size": "4.2GB", "description": "Google instruction tuned"},
110
- {"name": "Mistral-7B-v0.1", "size": "4.1GB", "description": "Mistral AI base model"}
111
  ],
112
  "code": [
113
- {"name": "CodeLlama-7B", "size": "3.8GB", "description": "Meta's code specialist"},
114
- {"name": "StarCoder-7B", "size": "4.0GB", "description": "Code generation expert"}
115
- ],
116
- "chat": [
117
- {"name": "Zephyr-7B-beta", "size": "4.2GB", "description": "HuggingFace chat model"},
118
- {"name": "Neural-Chat-7B", "size": "4.1GB", "description": "Intel optimized"}
119
  ]
120
  },
121
- "moderate": { # 7-8GB
122
  "general": [
123
  {"name": "Llama-2-7B-Chat", "size": "3.5GB", "description": "Meta's popular chat model"},
124
- {"name": "Mistral-7B-Instruct-v0.2", "size": "4.1GB", "description": "Latest Mistral instruct"},
125
- {"name": "Qwen-7B-Chat", "size": "4.0GB", "description": "Alibaba's multilingual"}
126
  ],
127
  "code": [
128
- {"name": "CodeLlama-7B-Instruct", "size": "3.8GB", "description": "Instruction-tuned CodeLlama"},
129
- {"name": "WizardCoder-7B", "size": "4.0GB", "description": "Enhanced coding abilities"},
130
- {"name": "Phind-CodeLlama-34B-v2", "size": "4.2GB", "description": "4-bit quantized version"}
131
- ],
132
- "reasoning": [
133
- {"name": "WizardMath-7B", "size": "4.0GB", "description": "Mathematical reasoning"},
134
- {"name": "MetaMath-7B", "size": "3.9GB", "description": "Math problem solving"}
135
  ]
136
  },
137
  "good": { # 9-16GB
138
  "general": [
139
  {"name": "Llama-2-13B-Chat", "size": "7.3GB", "description": "Larger Llama variant"},
140
- {"name": "Vicuna-13B-v1.5", "size": "7.2GB", "description": "Enhanced Vicuna"},
141
  {"name": "OpenChat-3.5", "size": "7.1GB", "description": "High-quality chat model"}
142
  ],
143
  "code": [
144
- {"name": "CodeLlama-13B-Instruct", "size": "7.3GB", "description": "Larger code model"},
145
- {"name": "WizardCoder-15B", "size": "8.2GB", "description": "Advanced coding"},
146
- {"name": "StarCoder-15B", "size": "8.5GB", "description": "Large code model"}
147
- ],
148
- "multimodal": [
149
- {"name": "LLaVA-7B", "size": "7.0GB", "description": "Vision + language"},
150
- {"name": "MiniGPT-4-7B", "size": "6.8GB", "description": "Multimodal chat"}
151
- ],
152
- "reasoning": [
153
- {"name": "WizardMath-13B", "size": "7.3GB", "description": "Advanced math"},
154
- {"name": "Orca-2-13B", "size": "7.4GB", "description": "Microsoft reasoning"}
155
  ]
156
  },
157
  "high": { # 17-32GB
158
  "general": [
159
  {"name": "Mixtral-8x7B-Instruct-v0.1", "size": "26.9GB", "description": "Mixture of experts"},
160
- {"name": "Llama-2-70B-Chat", "size": "38.0GB", "description": "8-bit quantized"},
161
  {"name": "Yi-34B-Chat", "size": "19.5GB", "description": "01.AI's large model"}
162
  ],
163
  "code": [
164
- {"name": "CodeLlama-34B-Instruct", "size": "19.0GB", "description": "Large code specialist"},
165
- {"name": "DeepSeek-Coder-33B", "size": "18.5GB", "description": "DeepSeek's coder"},
166
- {"name": "WizardCoder-34B", "size": "19.2GB", "description": "Enterprise coding"}
167
- ],
168
- "reasoning": [
169
- {"name": "WizardMath-70B", "size": "38.5GB", "description": "8-bit quantized math"},
170
- {"name": "MetaMath-70B", "size": "38.0GB", "description": "8-bit math reasoning"}
171
  ]
172
  },
173
  "ultra_high": { # >32GB
174
  "general": [
175
  {"name": "Llama-2-70B", "size": "130GB", "description": "Full precision"},
176
- {"name": "Mixtral-8x22B", "size": "176GB", "description": "Latest mixture model"},
177
- {"name": "Qwen-72B", "size": "145GB", "description": "Alibaba's flagship"}
178
- ],
179
- "code": [
180
- {"name": "CodeLlama-34B", "size": "68GB", "description": "Full precision code"},
181
- {"name": "DeepSeek-Coder-33B", "size": "66GB", "description": "Full precision coding"}
182
- ],
183
- "reasoning": [
184
- {"name": "WizardMath-70B", "size": "130GB", "description": "Full precision math"},
185
- {"name": "Goat-70B", "size": "132GB", "description": "Arithmetic reasoning"}
186
  ]
187
  }
188
  }
189
 
190
- # Enhanced LLM recommendation with performance tiers
191
- def recommend_llm(ram_str) -> Tuple[str, str, str, Dict[str, List[Dict]]]:
192
- """Returns (recommendation, performance_tier, additional_info, detailed_models)"""
193
  ram = extract_numeric_ram(ram_str)
194
 
195
  if ram is None:
196
- return ("⚪ Check exact specs or test with quantized models.",
197
- "Unknown",
198
- "Verify RAM specifications",
199
- {})
200
 
201
  if ram <= 2:
202
- models = LLM_DATABASE["ultra_low"]
203
- return ("🔸 Ultra-lightweight models - basic NLP tasks",
204
- "Ultra Low",
205
- "Mobile-optimized, simple tasks, limited context",
206
- models)
207
  elif ram <= 4:
208
- models = LLM_DATABASE["low"]
209
- return ("🔸 Small language models - decent capabilities",
210
- "Low",
211
- "Basic chat, simple reasoning, text classification",
212
- models)
213
- elif ram <= 6:
214
- models = LLM_DATABASE["moderate_low"]
215
- return ("🟠 Mid-range models - good general performance",
216
- "Moderate-Low",
217
- "Solid reasoning, coding help, longer conversations",
218
- models)
219
  elif ram <= 8:
220
- models = LLM_DATABASE["moderate"]
221
- return ("🟠 Strong 7B models - excellent capabilities",
222
- "Moderate",
223
- "Professional use, coding assistance, complex reasoning",
224
- models)
225
  elif ram <= 16:
226
- models = LLM_DATABASE["good"]
227
- return ("🟢 High-quality models - premium performance",
228
- "Good",
229
- "Advanced tasks, multimodal support, research use",
230
- models)
231
  elif ram <= 32:
232
- models = LLM_DATABASE["high"]
233
- return ("🔵 Premium models - professional grade",
234
- "High",
235
- "Enterprise ready, complex reasoning, specialized tasks",
236
- models)
237
  else:
238
- models = LLM_DATABASE["ultra_high"]
239
- return ("🔵 Top-tier models - enterprise capabilities",
240
- "Ultra High",
241
- "Research grade, maximum performance, domain expertise",
242
- models)
243
 
244
- # Enhanced OS detection with better icons
245
  def get_os_info(os_name) -> Tuple[str, str]:
246
  """Returns (icon, clean_name)"""
247
  if pd.isna(os_name):
@@ -250,7 +148,7 @@ def get_os_info(os_name) -> Tuple[str, str]:
250
  os = str(os_name).lower()
251
  if "windows" in os:
252
  return "🪟", os_name
253
- elif "mac" in os or "darwin" in os:
254
  return "🍎", os_name
255
  elif "linux" in os or "ubuntu" in os:
256
  return "🐧", os_name
@@ -261,137 +159,55 @@ def get_os_info(os_name) -> Tuple[str, str]:
261
  else:
262
  return "💻", os_name
263
 
264
- # Performance visualization
265
  def create_performance_chart(df):
266
- """Create a performance distribution chart"""
267
  laptop_rams = df["Laptop RAM"].apply(extract_numeric_ram).dropna()
268
  mobile_rams = df["Mobile RAM"].apply(extract_numeric_ram).dropna()
269
 
270
  fig = go.Figure()
271
-
272
- fig.add_trace(go.Histogram(
273
- x=laptop_rams,
274
- name="Laptop RAM",
275
- opacity=0.7,
276
- nbinsx=10
277
- ))
278
-
279
- fig.add_trace(go.Histogram(
280
- x=mobile_rams,
281
- name="Mobile RAM",
282
- opacity=0.7,
283
- nbinsx=10
284
- ))
285
 
286
  fig.update_layout(
287
- title="RAM Distribution Across Devices",
288
  xaxis_title="RAM (GB)",
289
- yaxis_title="Number of Students",
290
  barmode='overlay',
291
  height=400
292
  )
293
-
294
  return fig
295
 
296
- # Enhanced model details display function
297
- def display_model_categories(models_dict: Dict[str, List[Dict]], ram_gb: int):
298
- """Display models organized by category with download sizes"""
299
  if not models_dict:
300
  return
301
 
302
- st.markdown(f"### 🎯 Recommended Models for {ram_gb}GB RAM:")
303
-
304
  for category, model_list in models_dict.items():
305
  if model_list:
306
- with st.expander(f"📂 {category.replace('_', ' ').title()} Models"):
307
- for model in model_list[:8]: # Limit to top 8 per category
308
- col1, col2, col3 = st.columns([3, 1, 2])
309
- with col1:
310
- st.markdown(f"**{model['name']}**")
311
- with col2:
312
- st.markdown(f"`{model['size']}`")
313
- with col3:
314
- st.markdown(f"*{model['description']}*")
315
-
316
- # File upload fallback
317
- def show_file_upload():
318
- """Show file upload option when Excel file is not found"""
319
- st.warning("📁 Excel file not found. Please upload your data file:")
320
- uploaded_file = st.file_uploader(
321
- "Upload BITS_INTERNS.xlsx",
322
- type=['xlsx', 'xls'],
323
- help="Upload the Excel file containing student data"
324
- )
325
-
326
- if uploaded_file is not None:
327
- try:
328
- df = pd.read_excel(uploaded_file, sheet_name="Form Responses 1")
329
- df.columns = df.columns.str.strip()
330
- st.success("✅ File uploaded successfully!")
331
- return df, None
332
- except Exception as e:
333
- return None, f"Error reading uploaded file: {str(e)}"
334
-
335
- return None, "Please upload the Excel file to continue."
336
 
337
  # Main App
338
  st.title("🧠 LLM Compatibility Advisor")
339
- st.markdown("Get personalized recommendations from **150+ popular open source AI models** with download sizes!")
340
 
341
- # Load data with fallback to file upload
342
  df, error = load_data()
343
 
344
- if error and df is None:
345
- # Show file upload option
346
- df, upload_error = show_file_upload()
347
- if upload_error:
348
- st.error(upload_error)
349
- st.info("📋 **To fix this issue:**\n1. Ensure 'BITS_INTERNS.xlsx' is in the same directory as this script\n2. Or use the file upload option above\n3. Check that the Excel file has a sheet named 'Form Responses 1'")
350
-
351
- # Show demo mode option
352
- if st.button("🚀 Try Demo Mode"):
353
- # Create sample data for demonstration
354
- demo_data = {
355
- "Full Name": ["John Doe", "Jane Smith", "Alex Johnson", "Sarah Wilson"],
356
- "Laptop RAM": ["8GB", "16GB", "4GB", "32GB"],
357
- "Mobile RAM": ["6GB", "8GB", "4GB", "12GB"],
358
- "Laptop Operating System": ["Windows 11", "macOS", "Ubuntu Linux", "Windows 10"],
359
- "Mobile Operating System": ["Android", "iOS", "Android", "iOS"]
360
- }
361
- df = pd.DataFrame(demo_data)
362
- st.success("🔥 Demo mode activated! Using sample data.")
363
- else:
364
- st.stop()
365
 
366
  if df is None or df.empty:
367
- st.error("No data found in the file.")
368
  st.stop()
369
 
370
- # Sidebar filters and info
371
  with st.sidebar:
372
- st.header("🔍 Filters & Info")
373
-
374
- # Performance tier filter
375
- performance_filter = st.multiselect(
376
- "Filter by Performance Tier:",
377
- ["Ultra Low", "Low", "Moderate-Low", "Moderate", "Good", "High", "Ultra High", "Unknown"],
378
- default=["Ultra Low", "Low", "Moderate-Low", "Moderate", "Good", "High", "Ultra High", "Unknown"]
379
- )
380
-
381
- # Model category filter
382
- st.subheader("Model Categories")
383
- show_categories = st.multiselect(
384
- "Show specific categories:",
385
- ["general", "code", "chat", "reasoning", "multimodal"],
386
- default=["general", "code", "chat"]
387
- )
388
-
389
- st.markdown("---")
390
- st.markdown("### 📊 Quick Stats")
391
  st.metric("Total Students", len(df))
392
- st.metric("Popular Models", "150+")
393
 
394
- # Calculate average RAM
395
  avg_laptop_ram = df["Laptop RAM"].apply(extract_numeric_ram).mean()
396
  avg_mobile_ram = df["Mobile RAM"].apply(extract_numeric_ram).mean()
397
 
@@ -400,7 +216,7 @@ with st.sidebar:
400
  if not pd.isna(avg_mobile_ram):
401
  st.metric("Avg Mobile RAM", f"{avg_mobile_ram:.1f} GB")
402
 
403
- # User selection with search
404
  st.subheader("👤 Individual Student Analysis")
405
  selected_user = st.selectbox(
406
  "Choose a student:",
@@ -411,255 +227,93 @@ selected_user = st.selectbox(
411
  if selected_user:
412
  user_data = df[df["Full Name"] == selected_user].iloc[0]
413
 
414
- # Enhanced user display
415
  col1, col2 = st.columns(2)
416
 
417
  with col1:
418
- st.markdown("### 💻 Laptop Configuration")
419
  laptop_os_icon, laptop_os_name = get_os_info(user_data.get('Laptop Operating System'))
420
  laptop_ram = user_data.get('Laptop RAM', 'Not specified')
421
- laptop_rec, laptop_tier, laptop_info, laptop_models = recommend_llm(laptop_ram)
422
- laptop_ram_gb = extract_numeric_ram(laptop_ram) or 0
423
 
424
  st.markdown(f"**OS:** {laptop_os_icon} {laptop_os_name}")
425
  st.markdown(f"**RAM:** {laptop_ram}")
426
- st.markdown(f"**Performance Tier:** {laptop_tier}")
427
-
428
- st.success(f"**💡 Recommendation:** {laptop_rec}")
429
- st.info(f"**ℹ️ Notes:** {laptop_info}")
430
 
431
- # Display detailed models for laptop
432
- if laptop_models:
433
- filtered_models = {k: v for k, v in laptop_models.items() if k in show_categories}
434
- display_model_categories(filtered_models, laptop_ram_gb)
435
 
436
  with col2:
437
- st.markdown("### 📱 Mobile Configuration")
438
  mobile_os_icon, mobile_os_name = get_os_info(user_data.get('Mobile Operating System'))
439
  mobile_ram = user_data.get('Mobile RAM', 'Not specified')
440
- mobile_rec, mobile_tier, mobile_info, mobile_models = recommend_llm(mobile_ram)
441
- mobile_ram_gb = extract_numeric_ram(mobile_ram) or 0
442
 
443
  st.markdown(f"**OS:** {mobile_os_icon} {mobile_os_name}")
444
  st.markdown(f"**RAM:** {mobile_ram}")
445
- st.markdown(f"**Performance Tier:** {mobile_tier}")
446
 
447
- st.success(f"**💡 Recommendation:** {mobile_rec}")
448
- st.info(f"**ℹ️ Notes:** {mobile_info}")
449
-
450
- # Display detailed models for mobile
451
- if mobile_models:
452
- filtered_models = {k: v for k, v in mobile_models.items() if k in show_categories}
453
- display_model_categories(filtered_models, mobile_ram_gb)
454
 
455
- # Batch Analysis Section
456
  st.markdown("---")
457
- st.header("📊 Batch Analysis & Insights")
458
 
459
- # Create enhanced batch table
460
  df_display = df[["Full Name", "Laptop RAM", "Mobile RAM"]].copy()
 
 
461
 
462
- # Add recommendations and performance tiers
463
- laptop_recommendations = df["Laptop RAM"].apply(lambda x: recommend_llm(x)[0])
464
- mobile_recommendations = df["Mobile RAM"].apply(lambda x: recommend_llm(x)[0])
465
- laptop_tiers = df["Laptop RAM"].apply(lambda x: recommend_llm(x)[1])
466
- mobile_tiers = df["Mobile RAM"].apply(lambda x: recommend_llm(x)[1])
467
-
468
- df_display["Laptop LLM"] = laptop_recommendations
469
- df_display["Mobile LLM"] = mobile_recommendations
470
- df_display["Laptop Tier"] = laptop_tiers
471
- df_display["Mobile Tier"] = mobile_tiers
472
-
473
- # Filter based on sidebar selections
474
- mask = (laptop_tiers.isin(performance_filter) | mobile_tiers.isin(performance_filter))
475
 
476
- df_filtered = df_display[mask]
477
-
478
- # Display filtered table
479
- st.subheader(f"📋 Student Recommendations ({len(df_filtered)} students)")
480
- st.dataframe(
481
- df_filtered,
482
- use_container_width=True,
483
- column_config={
484
- "Full Name": st.column_config.TextColumn("Student Name", width="medium"),
485
- "Laptop RAM": st.column_config.TextColumn("Laptop RAM", width="small"),
486
- "Mobile RAM": st.column_config.TextColumn("Mobile RAM", width="small"),
487
- "Laptop LLM": st.column_config.TextColumn("Laptop Recommendation", width="large"),
488
- "Mobile LLM": st.column_config.TextColumn("Mobile Recommendation", width="large"),
489
- "Laptop Tier": st.column_config.TextColumn("L-Tier", width="small"),
490
- "Mobile Tier": st.column_config.TextColumn("M-Tier", width="small"),
491
- }
492
- )
493
-
494
- # Performance distribution chart
495
  if len(df) > 1:
496
- st.subheader("📈 RAM Distribution Analysis")
497
  fig = create_performance_chart(df)
498
  st.plotly_chart(fig, use_container_width=True)
499
 
500
- # Performance tier summary
501
- st.subheader("🎯 Performance Tier Summary")
502
- tier_col1, tier_col2 = st.columns(2)
503
-
504
- with tier_col1:
505
- st.markdown("**Laptop Performance Tiers:**")
506
- laptop_tier_counts = laptop_tiers.value_counts()
507
- for tier, count in laptop_tier_counts.items():
508
- percentage = (count / len(laptop_tiers)) * 100
509
- st.write(f"• {tier}: {count} students ({percentage:.1f}%)")
510
-
511
- with tier_col2:
512
- st.markdown("**Mobile Performance Tiers:**")
513
- mobile_tier_counts = mobile_tiers.value_counts()
514
- for tier, count in mobile_tier_counts.items():
515
- percentage = (count / len(mobile_tier_counts)) * 100
516
- st.write(f"• {tier}: {count} students ({percentage:.1f}%)")
517
-
518
- # Model Explorer Section
519
  st.markdown("---")
520
- st.header("🔍 Popular Model Explorer")
521
-
522
- explorer_col1, explorer_col2 = st.columns(2)
523
 
524
- with explorer_col1:
525
- selected_ram_range = st.selectbox(
526
- "Select RAM range to explore models:",
527
- ["≤2GB (Ultra Low)", "3-4GB (Low)", "5-6GB (Moderate-Low)",
528
- "7-8GB (Moderate)", "9-16GB (Good)", "17-32GB (High)", ">32GB (Ultra High)"]
529
- )
530
-
531
- with explorer_col2:
532
- selected_category = st.selectbox(
533
- "Select model category:",
534
- ["general", "code", "chat", "reasoning", "multimodal"]
535
- )
536
 
537
- # Map selection to database key
538
  ram_mapping = {
539
  "≤2GB (Ultra Low)": "ultra_low",
540
  "3-4GB (Low)": "low",
541
- "5-6GB (Moderate-Low)": "moderate_low",
542
- "7-8GB (Moderate)": "moderate",
543
  "9-16GB (Good)": "good",
544
  "17-32GB (High)": "high",
545
  ">32GB (Ultra High)": "ultra_high"
546
  }
547
 
548
- selected_ram_key = ram_mapping[selected_ram_range]
549
- if selected_ram_key in LLM_DATABASE and selected_category in LLM_DATABASE[selected_ram_key]:
550
- models = LLM_DATABASE[selected_ram_key][selected_category]
551
-
552
- st.subheader(f"🎯 {selected_category.title()} Models for {selected_ram_range}")
553
-
554
- # Display models in a detailed table
555
- for model in models:
556
- with st.container():
557
- col1, col2, col3 = st.columns([3, 1, 3])
558
- with col1:
559
- st.markdown(f"### {model['name']}")
560
- with col2:
561
- st.markdown(f"**{model['size']}**")
562
- st.caption("Download Size")
563
- with col3:
564
- st.markdown(f"*{model['description']}*")
565
- # Add download suggestion
566
- if "Llama" in model['name']:
567
- st.caption("🔗 Available on Hugging Face & Ollama")
568
- elif "Mistral" in model['name']:
569
- st.caption("🔗 Available on Hugging Face & Mistral AI")
570
- elif "Gemma" in model['name']:
571
- st.caption("🔗 Available on Hugging Face & Google")
572
- else:
573
- st.caption("🔗 Available on Hugging Face")
574
- st.markdown("---")
575
- else:
576
- st.info(f"No {selected_category} models available for {selected_ram_range}")
577
 
578
- # Enhanced reference guide
579
- with st.expander("📘 Model Guide & Download Information"):
580
  st.markdown("""
581
- ## 🚀 Popular Models by Category
582
-
583
- ### 🎯 **General Purpose Champions**
584
- - **Llama-2 Series**: Meta's flagship models (7B, 13B, 70B)
585
- - **Mistral Series**: Excellent efficiency and performance
586
- - **Gemma**: Google's efficient models (2B, 7B)
587
- - **Phi**: Microsoft's compact powerhouses
588
-
589
- ### 💻 **Code Specialists**
590
- - **CodeLlama**: Meta's dedicated coding models
591
- - **StarCoder**: BigCode's programming experts
592
- - **WizardCoder**: Enhanced coding capabilities
593
- - **DeepSeek-Coder**: Chinese tech giant's coder
594
-
595
- ### 💬 **Chat Optimized**
596
- - **Vicuna**: UC Berkeley's ChatGPT alternative
597
- - **Zephyr**: HuggingFace's chat specialist
598
- - **OpenChat**: High-quality conversation models
599
- - **Neural-Chat**: Intel-optimized chat models
600
-
601
- ### 🧮 **Reasoning Masters**
602
- - **WizardMath**: Mathematical problem solving
603
- - **MetaMath**: Advanced arithmetic reasoning
604
- - **Orca-2**: Microsoft's reasoning specialist
605
- - **Goat**: Specialized arithmetic model
606
-
607
- ### 👁️ **Multimodal Models**
608
- - **LLaVA**: Large Language and Vision Assistant
609
- - **MiniGPT-4**: Multimodal conversational AI
610
-
611
- ## 💾 Download Size Reference
612
-
613
- | Model Size | FP16 | 8-bit | 4-bit | Use Case |
614
- |------------|------|-------|-------|----------|
615
- | **1-3B** | 2-6GB | 1-3GB | 0.5-1.5GB | Mobile, Edge |
616
- | **7B** | 13GB | 7GB | 3.5GB | Desktop, Laptop |
617
- | **13B** | 26GB | 13GB | 7GB | Workstation |
618
- | **30-34B** | 60GB | 30GB | 15GB | Server, Cloud |
619
- | **70B** | 140GB | 70GB | 35GB | High-end Server |
620
-
621
- ## 🛠️ Where to Download
622
-
623
- ### **Primary Sources**
624
- - **🤗 Hugging Face**: Largest repository with 400,000+ models
625
- - **🦙 Ollama**: Simple CLI tool for local deployment
626
- - **📦 LM Studio**: User-friendly GUI for model management
627
-
628
- ### **Quantized Formats**
629
- - **GGUF**: Best for CPU inference (llama.cpp)
630
- - **GPTQ**: GPU-optimized quantization
631
- - **AWQ**: Advanced weight quantization
632
 
633
- ### **Download Tips**
634
- - Use `git lfs` for large models from Hugging Face
635
- - Consider bandwidth and storage before downloading
636
- - Start with 4-bit quantized versions for testing
637
- - Use `ollama pull model_name` for easiest setup
638
-
639
- ## 🔧 Optimization Strategies
640
 
641
- ### **Memory Reduction**
642
- - **4-bit quantization**: 75% memory reduction
643
- - **8-bit quantization**: 50% memory reduction
644
- - **CPU offloading**: Use system RAM for overflow
645
 
646
- ### **Speed Optimization**
647
- - **GPU acceleration**: CUDA, ROCm, Metal
648
- - **Batch processing**: Process multiple requests
649
- - **Context caching**: Reuse computations
650
  """)
651
 
652
- # Footer with updated resources
653
  st.markdown("---")
654
- st.markdown("""
655
- ### 🔗 Essential Download & Deployment Tools
656
- **📦 Easy Model Deployment:**
657
- - [**Ollama**](https://ollama.ai/) – `curl -fsSL https://ollama.ai/install.sh | sh`
658
- - [**LM Studio**](https://lmstudio.ai/) – Drag-and-drop GUI for running models locally
659
- - [**GPT4All**](https://gpt4all.io/) – Cross-platform desktop app for local LLMs
660
- **🤗 Model Repositories:**
661
- - [**Hugging Face Hub**](https://huggingface.co/models) – Filter by model size, task, and license
662
- - [**TheBloke's Quantizations**](https://huggingface.co/TheBloke) – Pre-quantized models in GGUF/GPTQ format
663
- - [**Awesome LLM**](https://github.com/Hannibal046/Awesome-LLMs) – Curated list of models and resources
664
- ---
665
- """)
 
1
  #!/usr/bin/env python3
2
  """
3
+ LLM Compatibility Advisor - Streamlined Version
4
  Author: Assistant
5
+ Description: Provides device-based LLM recommendations with popular models
6
  Requirements: streamlit, pandas, plotly, openpyxl
7
  """
8
 
9
  import streamlit as st
10
  import pandas as pd
11
  import re
 
12
  import plotly.graph_objects as go
13
+ from typing import Optional, Tuple, Dict, List
14
 
15
+ # Must be first Streamlit command
16
  st.set_page_config(
17
  page_title="LLM Compatibility Advisor",
18
  layout="wide",
19
+ page_icon="🧠"
 
20
  )
 
 
21
  @st.cache_data
22
  def load_data():
23
+ paths = [
24
+ "src/BITS_INTERNS.xlsx",
25
+ "src/Summer of AI - ICFAI (Responses) (3).xlsx"
26
+ ]
27
+
28
+ combined_df = pd.DataFrame()
29
+ for path in paths:
30
+ try:
31
+ df = pd.read_excel(path, sheet_name="Form Responses 1")
32
+ df.columns = df.columns.str.strip()
33
+ combined_df = pd.concat([combined_df, df], ignore_index=True)
34
+ except FileNotFoundError:
35
+ return None, f"Excel file '{path}' not found. Please upload the file."
36
+ except Exception as e:
37
+ return None, f"Error loading '{path}': {str(e)}"
38
+
39
+ if combined_df.empty:
40
+ return None, "No data found in either file."
41
+
42
+ return combined_df, None
 
 
 
 
 
43
 
44
 
 
45
  def extract_numeric_ram(ram) -> Optional[int]:
46
  if pd.isna(ram):
47
  return None
48
 
49
  ram_str = str(ram).lower().replace(" ", "")
50
 
51
+ # Handle GB format
52
  gb_match = re.search(r"(\d+(?:\.\d+)?)(?:gb|g)", ram_str)
53
  if gb_match:
54
  return int(float(gb_match.group(1)))
 
56
  # Handle MB format
57
  mb_match = re.search(r"(\d+)(?:mb|m)", ram_str)
58
  if mb_match:
59
+ return max(1, int(int(mb_match.group(1)) / 1024))
60
 
61
+ # Handle plain numbers
62
  plain_match = re.search(r"(\d+)", ram_str)
63
  if plain_match:
64
  return int(plain_match.group(1))
65
 
66
  return None
67
 
68
+ # Simplified LLM database
69
  LLM_DATABASE = {
70
  "ultra_low": { # ≤2GB
71
  "general": [
72
  {"name": "TinyLlama-1.1B-Chat", "size": "637MB", "description": "Compact chat model"},
 
73
  {"name": "all-MiniLM-L6-v2", "size": "91MB", "description": "Sentence embeddings"}
74
  ],
75
  "code": [
76
+ {"name": "CodeT5-small", "size": "242MB", "description": "Code generation"}
 
77
  ]
78
  },
79
  "low": { # 3-4GB
80
  "general": [
81
  {"name": "Phi-1.5", "size": "2.8GB", "description": "Microsoft's efficient model"},
82
+ {"name": "Gemma-2B", "size": "1.4GB", "description": "Google's compact model"}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
83
  ],
84
  "code": [
85
+ {"name": "CodeGen-2B", "size": "1.8GB", "description": "Salesforce code model"}
 
 
 
 
 
86
  ]
87
  },
88
+ "moderate": { # 5-8GB
89
  "general": [
90
  {"name": "Llama-2-7B-Chat", "size": "3.5GB", "description": "Meta's popular chat model"},
91
+ {"name": "Mistral-7B-Instruct-v0.2", "size": "4.1GB", "description": "Latest Mistral instruct"}
 
92
  ],
93
  "code": [
94
+ {"name": "CodeLlama-7B-Instruct", "size": "3.8GB", "description": "Instruction-tuned CodeLlama"}
 
 
 
 
 
 
95
  ]
96
  },
97
  "good": { # 9-16GB
98
  "general": [
99
  {"name": "Llama-2-13B-Chat", "size": "7.3GB", "description": "Larger Llama variant"},
 
100
  {"name": "OpenChat-3.5", "size": "7.1GB", "description": "High-quality chat model"}
101
  ],
102
  "code": [
103
+ {"name": "CodeLlama-13B-Instruct", "size": "7.3GB", "description": "Larger code model"}
 
 
 
 
 
 
 
 
 
 
104
  ]
105
  },
106
  "high": { # 17-32GB
107
  "general": [
108
  {"name": "Mixtral-8x7B-Instruct-v0.1", "size": "26.9GB", "description": "Mixture of experts"},
 
109
  {"name": "Yi-34B-Chat", "size": "19.5GB", "description": "01.AI's large model"}
110
  ],
111
  "code": [
112
+ {"name": "CodeLlama-34B-Instruct", "size": "19.0GB", "description": "Large code specialist"}
 
 
 
 
 
 
113
  ]
114
  },
115
  "ultra_high": { # >32GB
116
  "general": [
117
  {"name": "Llama-2-70B", "size": "130GB", "description": "Full precision"},
118
+ {"name": "Mixtral-8x22B", "size": "176GB", "description": "Latest mixture model"}
 
 
 
 
 
 
 
 
 
119
  ]
120
  }
121
  }
122
 
123
+ def recommend_llm(ram_str) -> Tuple[str, str, Dict[str, List[Dict]]]:
124
+ """Returns (recommendation, performance_tier, detailed_models)"""
 
125
  ram = extract_numeric_ram(ram_str)
126
 
127
  if ram is None:
128
+ return "⚪ Check exact specs", "Unknown", {}
 
 
 
129
 
130
  if ram <= 2:
131
+ return "🔸 Ultra-lightweight models", "Ultra Low", LLM_DATABASE["ultra_low"]
 
 
 
 
132
  elif ram <= 4:
133
+ return "🔸 Small language models", "Low", LLM_DATABASE["low"]
 
 
 
 
 
 
 
 
 
 
134
  elif ram <= 8:
135
+ return "🟠 7B models - excellent capabilities", "Moderate", LLM_DATABASE["moderate"]
 
 
 
 
136
  elif ram <= 16:
137
+ return "🟢 High-quality models", "Good", LLM_DATABASE["good"]
 
 
 
 
138
  elif ram <= 32:
139
+ return "🔵 Premium models", "High", LLM_DATABASE["high"]
 
 
 
 
140
  else:
141
+ return "🔵 Top-tier models", "Ultra High", LLM_DATABASE["ultra_high"]
 
 
 
 
142
 
 
143
  def get_os_info(os_name) -> Tuple[str, str]:
144
  """Returns (icon, clean_name)"""
145
  if pd.isna(os_name):
 
148
  os = str(os_name).lower()
149
  if "windows" in os:
150
  return "🪟", os_name
151
+ elif "mac" in os:
152
  return "🍎", os_name
153
  elif "linux" in os or "ubuntu" in os:
154
  return "🐧", os_name
 
159
  else:
160
  return "💻", os_name
161
 
 
162
  def create_performance_chart(df):
163
+ """Create RAM distribution chart"""
164
  laptop_rams = df["Laptop RAM"].apply(extract_numeric_ram).dropna()
165
  mobile_rams = df["Mobile RAM"].apply(extract_numeric_ram).dropna()
166
 
167
  fig = go.Figure()
168
+ fig.add_trace(go.Histogram(x=laptop_rams, name="Laptop RAM", opacity=0.7))
169
+ fig.add_trace(go.Histogram(x=mobile_rams, name="Mobile RAM", opacity=0.7))
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
  fig.update_layout(
172
+ title="RAM Distribution",
173
  xaxis_title="RAM (GB)",
174
+ yaxis_title="Students",
175
  barmode='overlay',
176
  height=400
177
  )
 
178
  return fig
179
 
180
+ def display_models(models_dict: Dict[str, List[Dict]]):
181
+ """Display models by category"""
 
182
  if not models_dict:
183
  return
184
 
 
 
185
  for category, model_list in models_dict.items():
186
  if model_list:
187
+ st.markdown(f"**{category.title()} Models:**")
188
+ for model in model_list[:5]: # Limit to 5 per category
189
+ st.write(f"• {model['name']} ({model['size']}) - {model['description']}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
190
 
191
  # Main App
192
  st.title("🧠 LLM Compatibility Advisor")
193
+ st.markdown("Get personalized AI model recommendations with download sizes!")
194
 
195
+ # Load data
196
  df, error = load_data()
197
 
198
+ if error:
199
+ st.error(error)
200
+ st.stop()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
  if df is None or df.empty:
203
+ st.error("No data found.")
204
  st.stop()
205
 
206
+ # Sidebar
207
  with st.sidebar:
208
+ st.header("📊 Quick Stats")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  st.metric("Total Students", len(df))
 
210
 
 
211
  avg_laptop_ram = df["Laptop RAM"].apply(extract_numeric_ram).mean()
212
  avg_mobile_ram = df["Mobile RAM"].apply(extract_numeric_ram).mean()
213
 
 
216
  if not pd.isna(avg_mobile_ram):
217
  st.metric("Avg Mobile RAM", f"{avg_mobile_ram:.1f} GB")
218
 
219
+ # Individual Analysis
220
  st.subheader("👤 Individual Student Analysis")
221
  selected_user = st.selectbox(
222
  "Choose a student:",
 
227
  if selected_user:
228
  user_data = df[df["Full Name"] == selected_user].iloc[0]
229
 
 
230
  col1, col2 = st.columns(2)
231
 
232
  with col1:
233
+ st.markdown("### 💻 Laptop")
234
  laptop_os_icon, laptop_os_name = get_os_info(user_data.get('Laptop Operating System'))
235
  laptop_ram = user_data.get('Laptop RAM', 'Not specified')
236
+ laptop_rec, laptop_tier, laptop_models = recommend_llm(laptop_ram)
 
237
 
238
  st.markdown(f"**OS:** {laptop_os_icon} {laptop_os_name}")
239
  st.markdown(f"**RAM:** {laptop_ram}")
240
+ st.success(f"**Recommendation:** {laptop_rec}")
 
 
 
241
 
242
+ display_models(laptop_models)
 
 
 
243
 
244
  with col2:
245
+ st.markdown("### 📱 Mobile")
246
  mobile_os_icon, mobile_os_name = get_os_info(user_data.get('Mobile Operating System'))
247
  mobile_ram = user_data.get('Mobile RAM', 'Not specified')
248
+ mobile_rec, mobile_tier, mobile_models = recommend_llm(mobile_ram)
 
249
 
250
  st.markdown(f"**OS:** {mobile_os_icon} {mobile_os_name}")
251
  st.markdown(f"**RAM:** {mobile_ram}")
252
+ st.success(f"**Recommendation:** {mobile_rec}")
253
 
254
+ display_models(mobile_models)
 
 
 
 
 
 
255
 
256
+ # Batch Analysis
257
  st.markdown("---")
258
+ st.header("📊 Batch Analysis")
259
 
260
+ # Create summary table
261
  df_display = df[["Full Name", "Laptop RAM", "Mobile RAM"]].copy()
262
+ df_display["Laptop Recommendation"] = df["Laptop RAM"].apply(lambda x: recommend_llm(x)[0])
263
+ df_display["Mobile Recommendation"] = df["Mobile RAM"].apply(lambda x: recommend_llm(x)[0])
264
 
265
+ st.dataframe(df_display, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
266
 
267
+ # Performance chart
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
268
  if len(df) > 1:
269
+ st.subheader("📈 RAM Distribution")
270
  fig = create_performance_chart(df)
271
  st.plotly_chart(fig, use_container_width=True)
272
 
273
+ # Model Explorer
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
274
  st.markdown("---")
275
+ st.header("🔍 Model Explorer")
 
 
276
 
277
+ selected_ram_range = st.selectbox(
278
+ "Select RAM range:",
279
+ ["≤2GB (Ultra Low)", "3-4GB (Low)", "5-8GB (Moderate)",
280
+ "9-16GB (Good)", "17-32GB (High)", ">32GB (Ultra High)"]
281
+ )
 
 
 
 
 
 
 
282
 
283
+ # Map selection to database
284
  ram_mapping = {
285
  "≤2GB (Ultra Low)": "ultra_low",
286
  "3-4GB (Low)": "low",
287
+ "5-8GB (Moderate)": "moderate",
 
288
  "9-16GB (Good)": "good",
289
  "17-32GB (High)": "high",
290
  ">32GB (Ultra High)": "ultra_high"
291
  }
292
 
293
+ selected_key = ram_mapping[selected_ram_range]
294
+ if selected_key in LLM_DATABASE:
295
+ st.subheader(f"Models for {selected_ram_range}")
296
+ display_models(LLM_DATABASE[selected_key])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
297
 
298
+ # Quick reference
299
+ with st.expander("📘 Quick Reference"):
300
  st.markdown("""
301
+ ## Popular Models by Category
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
 
303
+ **General Purpose:**
304
+ - Llama-2 Series (7B, 13B, 70B)
305
+ - Mistral Series
306
+ - Gemma (2B, 7B)
 
 
 
307
 
308
+ **Code Specialists:**
309
+ - CodeLlama
310
+ - CodeGen
 
311
 
312
+ **Where to Download:**
313
+ - 🤗 Hugging Face Hub
314
+ - 🦙 Ollama
315
+ - 📦 LM Studio
316
  """)
317
 
 
318
  st.markdown("---")
319
+ st.markdown("*Built for BITS Pilani Interns*")