Spaces:
Sleeping
feat: Add comprehensive hardware environment detection system
Browse filesMajor Changes:
- Implement detect_hardware_environment() function
- Support 6 environment types with auto-detection
- Dynamic UI based on detected hardware
Environment Types Supported:
1. HF Spaces - ZeroGPU (NVIDIA H200)
2. HF Spaces - CPU Upgrade (8 vCPU, 32GB RAM)
3. HF Spaces - CPU Basic (2-4 vCPU, 16GB RAM)
4. Local - GPU (CUDA/MPS detection)
5. Local - Apple Silicon (MPS backend)
6. Local - CPU (fallback)
Detection Logic:
- SPACE_ID environment variable β HF Spaces
- Import spaces success β ZeroGPU
- CPU count >= 8 β CPU Upgrade
- CPU count < 8 β CPU Basic
- torch.cuda.is_available() β Local CUDA GPU
- torch.backends.mps.is_available() β Apple Silicon GPU
- Fallback β Local CPU
Environment Info Displayed:
- Platform (HF Spaces / Local)
- Hardware type
- GPU availability and name
- CPU core count
- Operating system
- Detailed description
UI Improvements:
- Dynamic header with environment-specific info
- Hardware-specific features and recommendations
- Response time estimates per environment
- Cost information (HF Spaces tiers)
- Model recommendations (lightweight for CPU)
Benefits:
- Clear visibility of current environment
- Appropriate expectations for performance
- Better user experience with accurate info
- Easier debugging and troubleshooting
- Support for all deployment scenarios
π€ Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
|
@@ -1,23 +1,106 @@
|
|
| 1 |
"""
|
| 2 |
-
|
| 3 |
-
|
| 4 |
"""
|
| 5 |
|
| 6 |
-
# Try to import spaces for ZeroGPU support
|
| 7 |
-
try:
|
| 8 |
-
import spaces
|
| 9 |
-
ZEROGPU_AVAILABLE = True
|
| 10 |
-
print("β
ZeroGPU support enabled")
|
| 11 |
-
except ImportError:
|
| 12 |
-
ZEROGPU_AVAILABLE = False
|
| 13 |
-
print("βΉοΈ ZeroGPU not available, using standard mode")
|
| 14 |
-
|
| 15 |
import os
|
|
|
|
| 16 |
import gradio as gr
|
| 17 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 18 |
from huggingface_hub import snapshot_download
|
| 19 |
import torch
|
| 20 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 21 |
# Load environment variables from .env file
|
| 22 |
try:
|
| 23 |
from dotenv import load_dotenv
|
|
@@ -338,37 +421,62 @@ def chat_wrapper(message, history):
|
|
| 338 |
return response_history
|
| 339 |
|
| 340 |
|
| 341 |
-
|
| 342 |
-
hardware_info = "NVIDIA H200 (ZeroGPU)" if ZEROGPU_AVAILABLE else "CPU Upgrade (32GB RAM)"
|
| 343 |
-
print(f"β
App initialized - Hardware: {hardware_info}")
|
| 344 |
|
| 345 |
# Create Gradio interface
|
| 346 |
with gr.Blocks(title="π€ Multi-Model Chatbot") as demo:
|
| 347 |
-
# Dynamic header based on hardware
|
| 348 |
-
|
| 349 |
-
|
| 350 |
-
|
| 351 |
-
|
| 352 |
-
|
| 353 |
-
|
| 354 |
-
|
| 355 |
-
|
| 356 |
-
|
| 357 |
-
|
| 358 |
-
|
| 359 |
-
|
| 360 |
-
|
| 361 |
-
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 372 |
|
| 373 |
gr.Markdown(header)
|
| 374 |
|
|
@@ -438,37 +546,59 @@ with gr.Blocks(title="π€ Multi-Model Chatbot") as demo:
|
|
| 438 |
msg.submit(submit, [msg, chatbot], [chatbot, msg])
|
| 439 |
clear.click(lambda: [], outputs=chatbot)
|
| 440 |
|
| 441 |
-
# Dynamic footer based on hardware
|
| 442 |
-
|
| 443 |
-
|
| 444 |
-
|
| 445 |
-
|
| 446 |
-
|
| 447 |
-
|
| 448 |
-
|
| 449 |
-
|
| 450 |
-
|
| 451 |
-
|
| 452 |
-
|
| 453 |
-
|
| 454 |
-
|
| 455 |
-
|
| 456 |
-
|
| 457 |
-
|
| 458 |
-
|
| 459 |
-
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
|
| 463 |
-
|
| 464 |
-
|
| 465 |
-
|
| 466 |
-
|
| 467 |
-
|
| 468 |
-
|
| 469 |
-
|
| 470 |
-
|
| 471 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 472 |
|
| 473 |
gr.Markdown(footer)
|
| 474 |
|
|
|
|
| 1 |
"""
|
| 2 |
+
Multi-environment chatbot: Detects and adapts to different hardware environments
|
| 3 |
+
Supports: Local (Mac/Linux/Windows), HF Spaces (CPU Basic/Upgrade, ZeroGPU)
|
| 4 |
"""
|
| 5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
import os
|
| 7 |
+
import platform
|
| 8 |
import gradio as gr
|
| 9 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
| 10 |
from huggingface_hub import snapshot_download
|
| 11 |
import torch
|
| 12 |
|
| 13 |
+
# ============================================================================
|
| 14 |
+
# Hardware Environment Detection
|
| 15 |
+
# ============================================================================
|
| 16 |
+
|
| 17 |
+
def detect_hardware_environment():
|
| 18 |
+
"""
|
| 19 |
+
Comprehensive hardware environment detection
|
| 20 |
+
|
| 21 |
+
Returns:
|
| 22 |
+
dict: {
|
| 23 |
+
'platform': 'hf_spaces' | 'local',
|
| 24 |
+
'hardware': 'zerogpu' | 'cpu_upgrade' | 'cpu_basic' | 'local_gpu' | 'local_cpu',
|
| 25 |
+
'gpu_available': bool,
|
| 26 |
+
'gpu_name': str or None,
|
| 27 |
+
'cpu_count': int,
|
| 28 |
+
'os': 'Darwin' | 'Linux' | 'Windows',
|
| 29 |
+
'description': str
|
| 30 |
+
}
|
| 31 |
+
"""
|
| 32 |
+
env_info = {
|
| 33 |
+
'platform': 'local',
|
| 34 |
+
'hardware': 'local_cpu',
|
| 35 |
+
'gpu_available': False,
|
| 36 |
+
'gpu_name': None,
|
| 37 |
+
'cpu_count': os.cpu_count() or 1,
|
| 38 |
+
'os': platform.system(),
|
| 39 |
+
'description': ''
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
# Check if running on HF Spaces
|
| 43 |
+
is_hf_spaces = os.environ.get('SPACE_ID') is not None
|
| 44 |
+
|
| 45 |
+
if is_hf_spaces:
|
| 46 |
+
env_info['platform'] = 'hf_spaces'
|
| 47 |
+
space_id = os.environ.get('SPACE_ID', 'unknown')
|
| 48 |
+
|
| 49 |
+
# Check for ZeroGPU
|
| 50 |
+
try:
|
| 51 |
+
import spaces
|
| 52 |
+
env_info['hardware'] = 'zerogpu'
|
| 53 |
+
env_info['gpu_available'] = True
|
| 54 |
+
env_info['gpu_name'] = 'NVIDIA H200 (ZeroGPU)'
|
| 55 |
+
env_info['description'] = f"π HF Spaces - ZeroGPU ({space_id})"
|
| 56 |
+
except ImportError:
|
| 57 |
+
# Check CPU tier by memory/CPU count
|
| 58 |
+
cpu_count = env_info['cpu_count']
|
| 59 |
+
if cpu_count >= 8:
|
| 60 |
+
env_info['hardware'] = 'cpu_upgrade'
|
| 61 |
+
env_info['description'] = f"βοΈ HF Spaces - CPU Upgrade ({cpu_count} vCPU, 32GB RAM)"
|
| 62 |
+
else:
|
| 63 |
+
env_info['hardware'] = 'cpu_basic'
|
| 64 |
+
env_info['description'] = f"π» HF Spaces - CPU Basic ({cpu_count} vCPU, 16GB RAM)"
|
| 65 |
+
else:
|
| 66 |
+
# Local environment detection
|
| 67 |
+
if torch.cuda.is_available():
|
| 68 |
+
env_info['hardware'] = 'local_gpu'
|
| 69 |
+
env_info['gpu_available'] = True
|
| 70 |
+
try:
|
| 71 |
+
env_info['gpu_name'] = torch.cuda.get_device_name(0)
|
| 72 |
+
except:
|
| 73 |
+
env_info['gpu_name'] = 'CUDA GPU'
|
| 74 |
+
env_info['description'] = f"π₯οΈ Local - GPU ({env_info['gpu_name']})"
|
| 75 |
+
elif torch.backends.mps.is_available():
|
| 76 |
+
env_info['hardware'] = 'local_gpu'
|
| 77 |
+
env_info['gpu_available'] = True
|
| 78 |
+
env_info['gpu_name'] = 'Apple Silicon GPU (MPS)'
|
| 79 |
+
env_info['description'] = f"π Local - Apple Silicon GPU"
|
| 80 |
+
else:
|
| 81 |
+
env_info['hardware'] = 'local_cpu'
|
| 82 |
+
env_info['description'] = f"π» Local - CPU ({env_info['os']}, {env_info['cpu_count']} cores)"
|
| 83 |
+
|
| 84 |
+
return env_info
|
| 85 |
+
|
| 86 |
+
# Detect hardware environment
|
| 87 |
+
HW_ENV = detect_hardware_environment()
|
| 88 |
+
ZEROGPU_AVAILABLE = HW_ENV['hardware'] == 'zerogpu'
|
| 89 |
+
|
| 90 |
+
# Print environment info
|
| 91 |
+
print("=" * 60)
|
| 92 |
+
print("Hardware Environment Detection")
|
| 93 |
+
print("=" * 60)
|
| 94 |
+
print(f"Platform: {HW_ENV['platform']}")
|
| 95 |
+
print(f"Hardware: {HW_ENV['hardware']}")
|
| 96 |
+
print(f"GPU Available: {HW_ENV['gpu_available']}")
|
| 97 |
+
if HW_ENV['gpu_name']:
|
| 98 |
+
print(f"GPU Name: {HW_ENV['gpu_name']}")
|
| 99 |
+
print(f"CPU Cores: {HW_ENV['cpu_count']}")
|
| 100 |
+
print(f"OS: {HW_ENV['os']}")
|
| 101 |
+
print(f"Description: {HW_ENV['description']}")
|
| 102 |
+
print("=" * 60)
|
| 103 |
+
|
| 104 |
# Load environment variables from .env file
|
| 105 |
try:
|
| 106 |
from dotenv import load_dotenv
|
|
|
|
| 421 |
return response_history
|
| 422 |
|
| 423 |
|
| 424 |
+
print(f"β
App initialized - {HW_ENV['description']}")
|
|
|
|
|
|
|
| 425 |
|
| 426 |
# Create Gradio interface
|
| 427 |
with gr.Blocks(title="π€ Multi-Model Chatbot") as demo:
|
| 428 |
+
# Dynamic header based on hardware environment
|
| 429 |
+
header = f"""
|
| 430 |
+
# π€ λ€μ€ λͺ¨λΈ μ±λ΄ {HW_ENV['description']}
|
| 431 |
+
|
| 432 |
+
**νκ²½ μ 보**:
|
| 433 |
+
- **νλ«νΌ**: {HW_ENV['platform'].upper().replace('_', ' ')}
|
| 434 |
+
- **νλμ¨μ΄**: {HW_ENV['hardware'].upper().replace('_', ' ')}
|
| 435 |
+
- **GPU**: {'β
' + HW_ENV['gpu_name'] if HW_ENV['gpu_available'] else 'β CPU only'}
|
| 436 |
+
- **CPU μ½μ΄**: {HW_ENV['cpu_count']}
|
| 437 |
+
- **μ΄μ체μ **: {HW_ENV['os']}
|
| 438 |
+
|
| 439 |
+
**λͺ¨λΈ μ ν**:
|
| 440 |
+
- π― {TOTAL_MODEL_COUNT}κ°μ§ νκΈ μ΅μ ν λͺ¨λΈ ({PUBLIC_MODEL_COUNT} Public + {GATED_MODEL_COUNT} Gated)
|
| 441 |
+
- π λͺ¨λΈ μ ν μ μλ μ¬λ‘λ© (μ±ν
νμ€ν 리 μ΄κΈ°ν)
|
| 442 |
+
"""
|
| 443 |
+
|
| 444 |
+
# Add hardware-specific features
|
| 445 |
+
if HW_ENV['hardware'] == 'zerogpu':
|
| 446 |
+
header += """
|
| 447 |
+
**ZeroGPU νΉμ§**:
|
| 448 |
+
- β‘ μ΄κ³ μ μλ΅ (3-5μ΄, GPU κ°μ)
|
| 449 |
+
- π NVIDIA H200 μλ ν λΉ
|
| 450 |
+
- π° PRO ꡬλ
μ ν루 25λΆ λ¬΄λ£
|
| 451 |
+
"""
|
| 452 |
+
elif HW_ENV['hardware'] == 'cpu_upgrade':
|
| 453 |
+
header += """
|
| 454 |
+
**CPU Upgrade νΉμ§**:
|
| 455 |
+
- Ⱐ무μ ν μ¬μ© μκ°
|
| 456 |
+
- β³ CPU νκ²½ (μλ΅ 30μ΄~1λΆ)
|
| 457 |
+
- π° μκ°λΉ $0.03 (μ μ½ $22)
|
| 458 |
+
"""
|
| 459 |
+
elif HW_ENV['hardware'] == 'cpu_basic':
|
| 460 |
+
header += """
|
| 461 |
+
**CPU Basic νΉμ§**:
|
| 462 |
+
- π‘ λ¬΄λ£ ν°μ΄
|
| 463 |
+
- β³ CPU νκ²½ (μλ΅ 1~2λΆ)
|
| 464 |
+
- π κ²½λ λͺ¨λΈ κΆμ₯ (EXAONE 2.4B, Mistral 7B)
|
| 465 |
+
"""
|
| 466 |
+
elif HW_ENV['hardware'] == 'local_gpu':
|
| 467 |
+
header += f"""
|
| 468 |
+
**λ‘컬 GPU νΉμ§**:
|
| 469 |
+
- π₯οΈ κ°μΈ GPU: {HW_ENV['gpu_name']}
|
| 470 |
+
- β‘ λΉ λ₯Έ μλ΅ (GPU κ°μ)
|
| 471 |
+
- π 무μ ν μ¬μ©
|
| 472 |
+
"""
|
| 473 |
+
else: # local_cpu
|
| 474 |
+
header += """
|
| 475 |
+
**λ‘컬 CPU νΉμ§**:
|
| 476 |
+
- π» λ‘컬 κ°λ° νκ²½
|
| 477 |
+
- β³ CPU νκ²½ (λλ¦° μλ΅)
|
| 478 |
+
- π κ²½λ λͺ¨λΈ κΆμ₯
|
| 479 |
+
"""
|
| 480 |
|
| 481 |
gr.Markdown(header)
|
| 482 |
|
|
|
|
| 546 |
msg.submit(submit, [msg, chatbot], [chatbot, msg])
|
| 547 |
clear.click(lambda: [], outputs=chatbot)
|
| 548 |
|
| 549 |
+
# Dynamic footer based on hardware environment
|
| 550 |
+
footer = f"""
|
| 551 |
+
---
|
| 552 |
+
**νμ¬ νκ²½**: {HW_ENV['description']}
|
| 553 |
+
|
| 554 |
+
**μ°Έκ³ μ¬ν**:
|
| 555 |
+
- π€ {TOTAL_MODEL_COUNT}κ°μ§ λͺ¨λΈ μ€ μ ν κ°λ₯
|
| 556 |
+
- π λͺ¨λΈ λ³κ²½ μ λν λ΄μ μ΄κΈ°ν
|
| 557 |
+
- β±οΈ 첫 μλ΅μ λͺ¨λΈ λ‘λ© μκ° ν¬ν¨
|
| 558 |
+
"""
|
| 559 |
+
|
| 560 |
+
# Add environment-specific notes
|
| 561 |
+
if HW_ENV['hardware'] == 'zerogpu':
|
| 562 |
+
footer += """
|
| 563 |
+
- β‘ ZeroGPU μλ GPU ν λΉ (3-5μ΄ μλ΅)
|
| 564 |
+
- π° PRO ꡬλ
μ ν루 25λΆ λ¬΄λ£
|
| 565 |
+
- β±οΈ 첫 λ‘λ©: ~10-15μ΄
|
| 566 |
+
"""
|
| 567 |
+
elif HW_ENV['hardware'] == 'cpu_upgrade':
|
| 568 |
+
footer += """
|
| 569 |
+
- β° 24μκ° λ¬΄μ ν μ¬μ©
|
| 570 |
+
- β³ CPU νκ²½ (30μ΄~1λΆ μλ΅)
|
| 571 |
+
- π° μκ°λΉ $0.03
|
| 572 |
+
- β±οΈ 첫 λ‘λ©: ~1-2λΆ
|
| 573 |
+
"""
|
| 574 |
+
elif HW_ENV['hardware'] == 'cpu_basic':
|
| 575 |
+
footer += """
|
| 576 |
+
- π‘ λ¬΄λ£ ν°μ΄ (μ νμ )
|
| 577 |
+
- β³ CPU νκ²½ (1~2λΆ μλ΅)
|
| 578 |
+
- π κ²½λ λͺ¨λΈ κΆμ₯
|
| 579 |
+
- β±οΈ 첫 λ‘λ©: ~2-3λΆ
|
| 580 |
+
"""
|
| 581 |
+
elif HW_ENV['hardware'] == 'local_gpu':
|
| 582 |
+
footer += f"""
|
| 583 |
+
- π₯οΈ GPU κ°μ: {HW_ENV['gpu_name']}
|
| 584 |
+
- β‘ λΉ λ₯Έ μλ΅ (5-10μ΄)
|
| 585 |
+
- π 무μ ν μ¬μ©
|
| 586 |
+
- β±οΈ 첫 λ‘λ©: ~10-20μ΄
|
| 587 |
+
"""
|
| 588 |
+
else: # local_cpu
|
| 589 |
+
footer += f"""
|
| 590 |
+
- π» λ‘컬 CPU ({HW_ENV['cpu_count']} μ½μ΄)
|
| 591 |
+
- β³ λλ¦° μλ΅ (1~3λΆ)
|
| 592 |
+
- π κ²½λ λͺ¨λΈ κΆμ₯
|
| 593 |
+
- β±οΈ 첫 λ‘λ©: ~2-5λΆ
|
| 594 |
+
"""
|
| 595 |
+
|
| 596 |
+
footer += """
|
| 597 |
+
**ν
μ€νΈ μμ**:
|
| 598 |
+
- "μλ
νμΈμ"
|
| 599 |
+
- "μΈκ³΅μ§λ₯μ λν΄ μ€λͺ
ν΄μ£ΌμΈμ"
|
| 600 |
+
- "νκ΅μ μλλ μ΄λμΈκ°μ?"
|
| 601 |
+
"""
|
| 602 |
|
| 603 |
gr.Markdown(footer)
|
| 604 |
|