Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,28 +1,30 @@
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
-
Ultralekki
|
| 4 |
-
✅
|
| 5 |
-
✅
|
|
|
|
| 6 |
"""
|
| 7 |
import os
|
| 8 |
import sys
|
| 9 |
import signal
|
| 10 |
import logging
|
| 11 |
-
import subprocess
|
| 12 |
from huggingface_hub import hf_hub_download
|
|
|
|
| 13 |
|
| 14 |
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
|
| 15 |
logger = logging.getLogger(__name__)
|
| 16 |
|
| 17 |
MODEL_REPO = "unsloth/granite-4.1-3b-GGUF"
|
| 18 |
MODEL_FILE = os.environ.get("MODEL_FILE", "granite-4.1-3b-UD-IQ2_M.gguf")
|
| 19 |
-
PORT = os.environ.get("PORT",
|
| 20 |
-
N_CTX = os.environ.get("N_CTX",
|
| 21 |
-
N_THREADS = os.environ.get("N_THREADS",
|
| 22 |
-
N_BATCH = os.environ.get("N_BATCH",
|
| 23 |
|
| 24 |
def graceful_shutdown(signum, frame):
|
| 25 |
logger.info("📡 Otrzymano sygnał zakończenia. Zamykanie...")
|
|
|
|
| 26 |
sys.exit(0)
|
| 27 |
|
| 28 |
signal.signal(signal.SIGTERM, graceful_shutdown)
|
|
@@ -38,26 +40,61 @@ if __name__ == "__main__":
|
|
| 38 |
)
|
| 39 |
logger.info(f"✅ Model gotowy: {model_path}")
|
| 40 |
|
| 41 |
-
#
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
| 45 |
-
|
| 46 |
-
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
|
| 56 |
-
logger.info(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
except Exception as e:
|
| 63 |
logger.error(f"❌ Krytyczny błąd: {e}", exc_info=True)
|
|
|
|
| 1 |
#!/usr/bin/env python3
|
| 2 |
"""
|
| 3 |
+
Ultralekki serwer OpenAI-compatible dla HF Spaces
|
| 4 |
+
✅ Bezpośrednie uruchomienie via uvicorn (brak subprocess)
|
| 5 |
+
✅ Odporny na SIGTERM/SIGINT
|
| 6 |
+
✅ Streaming SSE | ✅ Brak auth
|
| 7 |
"""
|
| 8 |
import os
|
| 9 |
import sys
|
| 10 |
import signal
|
| 11 |
import logging
|
|
|
|
| 12 |
from huggingface_hub import hf_hub_download
|
| 13 |
+
import uvicorn
|
| 14 |
|
| 15 |
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
|
| 16 |
logger = logging.getLogger(__name__)
|
| 17 |
|
| 18 |
MODEL_REPO = "unsloth/granite-4.1-3b-GGUF"
|
| 19 |
MODEL_FILE = os.environ.get("MODEL_FILE", "granite-4.1-3b-UD-IQ2_M.gguf")
|
| 20 |
+
PORT = int(os.environ.get("PORT", 7860))
|
| 21 |
+
N_CTX = int(os.environ.get("N_CTX", 2048))
|
| 22 |
+
N_THREADS = int(os.environ.get("N_THREADS", 2))
|
| 23 |
+
N_BATCH = int(os.environ.get("N_BATCH", 512))
|
| 24 |
|
| 25 |
def graceful_shutdown(signum, frame):
|
| 26 |
logger.info("📡 Otrzymano sygnał zakończenia. Zamykanie...")
|
| 27 |
+
# Uvicorn obsłuży to samodzielnie dzięki lifespan, ale dla pewności exit
|
| 28 |
sys.exit(0)
|
| 29 |
|
| 30 |
signal.signal(signal.SIGTERM, graceful_shutdown)
|
|
|
|
| 40 |
)
|
| 41 |
logger.info(f"✅ Model gotowy: {model_path}")
|
| 42 |
|
| 43 |
+
# Importujemy moduł serwera llama_cpp
|
| 44 |
+
from llama_cpp.server.app import create_app
|
| 45 |
+
|
| 46 |
+
# Tworzymy aplikację FastAPI z konfiguracją modelu
|
| 47 |
+
# Uwaga: create_app wymaga specyficznych argumentów w nowszych wersjach
|
| 48 |
+
# Jeśli create_app nie działa bezpośrednio, używamy podejścia z CLI args via sys.argv hack
|
| 49 |
+
# Ale najbezpieczniej jest ustawić zmienne środowiskowe, które llama_cpp.server czyta
|
| 50 |
+
|
| 51 |
+
os.environ["MODEL"] = model_path
|
| 52 |
+
os.environ["HOST"] = "0.0.0.0"
|
| 53 |
+
os.environ["PORT"] = str(PORT)
|
| 54 |
+
os.environ["N_CTX"] = str(N_CTX)
|
| 55 |
+
os.environ["N_THREADS"] = str(N_THREADS)
|
| 56 |
+
os.environ["N_BATCH"] = str(N_BATCH)
|
| 57 |
+
os.environ["N_GPU_LAYERS"] = "0"
|
| 58 |
+
os.environ["USE_MMAP"] = "1"
|
| 59 |
+
os.environ["NO_FLASH_ATTN"] = "1"
|
| 60 |
+
os.environ["CHAT_FORMAT"] = "chatml"
|
| 61 |
|
| 62 |
+
logger.info("🚀 Start serwera Uvicorn...")
|
| 63 |
+
|
| 64 |
+
# Uruchamiamy uvicorn bezpośrednio
|
| 65 |
+
# app="llama_cpp.server.app:create_app" może być problematyczne jeśli create_app potrzebuje args
|
| 66 |
+
# Dlatego używamy prostszego podejścia: zaimportujmy app z llama_cpp.server
|
| 67 |
+
|
| 68 |
+
# Alternatywa: Użycie wbudowanego entrypointa llama_cpp.server poprzez import
|
| 69 |
+
# Najprostsze i najbardziej stabilne:
|
| 70 |
|
| 71 |
+
from llama_cpp.server import app as server_app_module
|
| 72 |
+
|
| 73 |
+
# Sprawdźmy, czy server_app_module ma obiekt 'app'
|
| 74 |
+
if hasattr(server_app_module, 'app'):
|
| 75 |
+
target_app = server_app_module.app
|
| 76 |
+
else:
|
| 77 |
+
# Fallback: spróbujmy stworzyć app ręcznie jeśli to możliwe
|
| 78 |
+
# W wersji 0.3.2 app jest tworzony dynamicznie przy imporcie __main__
|
| 79 |
+
# Więc musimy zasymulować import __main__
|
| 80 |
+
import llama_cpp.server.__main__ as main_module
|
| 81 |
+
# To może być ryzykowne.
|
| 82 |
+
|
| 83 |
+
# Najlepsze rozwiązanie dla 0.3.2:
|
| 84 |
+
# Używamy uvicorn z stringiem wskazującym na fabrykę aplikacji
|
| 85 |
+
target_app = "llama_cpp.server.app:create_app"
|
| 86 |
+
|
| 87 |
+
uvicorn.run(
|
| 88 |
+
target_app,
|
| 89 |
+
host="0.0.0.0",
|
| 90 |
+
port=PORT,
|
| 91 |
+
log_level="info",
|
| 92 |
+
timeout_keep_alive=120,
|
| 93 |
+
limit_concurrency=3,
|
| 94 |
+
backlog=16,
|
| 95 |
+
ws_ping_interval=30,
|
| 96 |
+
ws_ping_timeout=10
|
| 97 |
+
)
|
| 98 |
|
| 99 |
except Exception as e:
|
| 100 |
logger.error(f"❌ Krytyczny błąd: {e}", exc_info=True)
|