Spaces:
Runtime error
Runtime error
| #!/usr/bin/env python3 | |
| """ | |
| Ultralekki serwer OpenAI-compatible dla HF Spaces | |
| ✅ Bezpośrednie uruchomienie via uvicorn (brak subprocess) | |
| ✅ Odporny na SIGTERM/SIGINT | |
| ✅ Streaming SSE | ✅ Brak auth | |
| """ | |
| import os | |
| import sys | |
| import signal | |
| import logging | |
| from huggingface_hub import hf_hub_download | |
| import uvicorn | |
| logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") | |
| logger = logging.getLogger(__name__) | |
| MODEL_REPO = "unsloth/granite-4.1-3b-GGUF" | |
| MODEL_FILE = os.environ.get("MODEL_FILE", "granite-4.1-3b-UD-IQ2_M.gguf") | |
| PORT = int(os.environ.get("PORT", 7860)) | |
| N_CTX = int(os.environ.get("N_CTX", 2048)) | |
| N_THREADS = int(os.environ.get("N_THREADS", 2)) | |
| N_BATCH = int(os.environ.get("N_BATCH", 512)) | |
| def graceful_shutdown(signum, frame): | |
| logger.info("📡 Otrzymano sygnał zakończenia. Zamykanie...") | |
| # Uvicorn obsłuży to samodzielnie dzięki lifespan, ale dla pewności exit | |
| sys.exit(0) | |
| signal.signal(signal.SIGTERM, graceful_shutdown) | |
| signal.signal(signal.SIGINT, graceful_shutdown) | |
| if __name__ == "__main__": | |
| try: | |
| logger.info(f"⬇️ Pobieranie/weryfikacja: {MODEL_REPO}/{MODEL_FILE}") | |
| model_path = hf_hub_download( | |
| repo_id=MODEL_REPO, | |
| filename=MODEL_FILE, | |
| resume_download=True | |
| ) | |
| logger.info(f"✅ Model gotowy: {model_path}") | |
| # Importujemy moduł serwera llama_cpp | |
| from llama_cpp.server.app import create_app | |
| # Tworzymy aplikację FastAPI z konfiguracją modelu | |
| # Uwaga: create_app wymaga specyficznych argumentów w nowszych wersjach | |
| # Jeśli create_app nie działa bezpośrednio, używamy podejścia z CLI args via sys.argv hack | |
| # Ale najbezpieczniej jest ustawić zmienne środowiskowe, które llama_cpp.server czyta | |
| os.environ["MODEL"] = model_path | |
| os.environ["HOST"] = "0.0.0.0" | |
| os.environ["PORT"] = str(PORT) | |
| os.environ["N_CTX"] = str(N_CTX) | |
| os.environ["N_THREADS"] = str(N_THREADS) | |
| os.environ["N_BATCH"] = str(N_BATCH) | |
| os.environ["N_GPU_LAYERS"] = "0" | |
| os.environ["USE_MMAP"] = "1" | |
| os.environ["NO_FLASH_ATTN"] = "1" | |
| os.environ["CHAT_FORMAT"] = "chatml" | |
| logger.info("🚀 Start serwera Uvicorn...") | |
| # Uruchamiamy uvicorn bezpośrednio | |
| # app="llama_cpp.server.app:create_app" może być problematyczne jeśli create_app potrzebuje args | |
| # Dlatego używamy prostszego podejścia: zaimportujmy app z llama_cpp.server | |
| # Alternatywa: Użycie wbudowanego entrypointa llama_cpp.server poprzez import | |
| # Najprostsze i najbardziej stabilne: | |
| from llama_cpp.server import app as server_app_module | |
| # Sprawdźmy, czy server_app_module ma obiekt 'app' | |
| if hasattr(server_app_module, 'app'): | |
| target_app = server_app_module.app | |
| else: | |
| # Fallback: spróbujmy stworzyć app ręcznie jeśli to możliwe | |
| # W wersji 0.3.2 app jest tworzony dynamicznie przy imporcie __main__ | |
| # Więc musimy zasymulować import __main__ | |
| import llama_cpp.server.__main__ as main_module | |
| # To może być ryzykowne. | |
| # Najlepsze rozwiązanie dla 0.3.2: | |
| # Używamy uvicorn z stringiem wskazującym na fabrykę aplikacji | |
| target_app = "llama_cpp.server.app:create_app" | |
| uvicorn.run( | |
| target_app, | |
| host="0.0.0.0", | |
| port=PORT, | |
| log_level="info", | |
| timeout_keep_alive=120, | |
| limit_concurrency=3, | |
| backlog=16, | |
| ws_ping_interval=30, | |
| ws_ping_timeout=10 | |
| ) | |
| except Exception as e: | |
| logger.error(f"❌ Krytyczny błąd: {e}", exc_info=True) | |
| sys.exit(1) |