feat: GPU detection for LLM server (NVIDIA/AMD/Intel/Vulkan + CPU fallback)
- Added start-llama-server.bat with cross-brand GPU auto-detection: * Detection 1: nvidia-smi for NVIDIA * Detection 2: WMIC for AMD, Intel Arc, Intel HD/Iris/UHD * Detection 3: vulkaninfo as final fallback probe * Falls back to CPU-only build when no GPU found - Downloaded llama-server b9947 builds: * Vulkan build (91 MB) - supports all GPU brands * CPU build (45 MB) - fallback in cpu/ subdir - Downloaded Qwen2.5-Coder-1.5B Q4_K_M model (1.1 GB) - Fixed run-hermes.bat polling: replaces fixed 5s timeout with curl-based readiness polling (up to 30 attempts, 1s apart) - All .bat files verified: ASCII text, CRLF line terminators - Added .gitignore for build artifacts and large binaries
This commit is contained in:
@@ -0,0 +1,165 @@
|
||||
@echo off
|
||||
title Hermes Portable Rescue - Windows Agent
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
cd /d "%~dp0"
|
||||
|
||||
set HERMES_HOME=%~dp0..\hermes
|
||||
set HERMES_ROOT=%~dp0..\hermes
|
||||
set HERMES_CONFIG=%HERMES_ROOT%\config.yaml
|
||||
set PYTHON=%~dp0python\python.exe
|
||||
set PIP=%~dp0python\Scripts\pip.exe
|
||||
set WHEELS_DIR=%~dp0bin\wheels
|
||||
set MARKER=%~dp0\.installed
|
||||
set WEB_SERVER=%~dp0..\hermes\web\server.py
|
||||
set OLLAMA_DIR=%~dp0bin\ollama
|
||||
|
||||
echo.
|
||||
echo ============================================
|
||||
echo Hermes Portable Rescue - Windows Agent
|
||||
echo ============================================
|
||||
echo.
|
||||
echo Python: !PYTHON!
|
||||
echo Config: !HERMES_CONFIG!
|
||||
echo.
|
||||
|
||||
:: Check Python
|
||||
if not exist "!PYTHON!" (
|
||||
echo [ERROR] Python not found at !PYTHON!
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:: First-run: bootstrap pip + install hermes + zeroconf
|
||||
if not exist "!MARKER!" (
|
||||
echo [*] First run -- installing Hermes Agent...
|
||||
echo.
|
||||
"!PYTHON!" "%~dp0bin\get-pip.py" --quiet --no-warn-script-location 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Failed to bootstrap pip.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
"!PYTHON!" -m pip install --no-index --find-links "!WHEELS_DIR!" --quiet hermes-agent zeroconf ifaddr 2>&1
|
||||
if errorlevel 1 (
|
||||
echo [ERROR] Failed to install Hermes Agent.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
echo. > "!MARKER!"
|
||||
echo [OK] Hermes Agent installed.
|
||||
echo.
|
||||
)
|
||||
|
||||
:: Launch menu
|
||||
:menu
|
||||
cls
|
||||
echo ============================================
|
||||
echo Hermes Portable Rescue - Windows Agent
|
||||
echo ============================================
|
||||
echo.
|
||||
echo Python: !PYTHON!
|
||||
echo Config: !HERMES_CONFIG!
|
||||
echo.
|
||||
echo What would you like to do?
|
||||
echo.
|
||||
echo 1) Hermes CLI (ONLINE - opencode-go)
|
||||
echo 2) Hermes CLI (OFFLINE - local LLM)
|
||||
echo 3) Web Dashboard (http://rescue.local:8080)
|
||||
echo 4) Full Diagnostics (hardware, disk, mem, stress)
|
||||
echo 5) Start Local LLM Server (llama.cpp)
|
||||
echo 6) Exit
|
||||
echo.
|
||||
set /p choice="Choice (1-6): "
|
||||
|
||||
if "!choice!"=="1" goto run_online
|
||||
if "!choice!"=="2" goto run_offline
|
||||
if "!choice!"=="3" goto run_dashboard
|
||||
if "!choice!"=="4" goto run_diag
|
||||
if "!choice!"=="5" goto run_llm
|
||||
if "!choice!"=="6" exit /b
|
||||
echo Invalid choice.
|
||||
pause
|
||||
goto menu
|
||||
|
||||
:run_online
|
||||
echo.
|
||||
echo [*] Starting Hermes CLI (online mode - opencode-go)...
|
||||
echo.
|
||||
set HERMES_HOME=%~dp0..\hermes
|
||||
"!PYTHON!" -m hermes_cli --config "!HERMES_CONFIG!"
|
||||
echo.
|
||||
pause
|
||||
goto menu
|
||||
|
||||
:run_offline
|
||||
if not exist "!OLLAMA_DIR!\qwen2.5-coder-1.5b-q4_k_m.gguf" (
|
||||
echo.
|
||||
echo [ERROR] Offline model not found at !OLLAMA_DIR!
|
||||
echo Run option 5 first to start the LLM server.
|
||||
echo.
|
||||
pause
|
||||
goto menu
|
||||
)
|
||||
echo.
|
||||
echo [*] Starting local LLM server (llama.cpp)...
|
||||
start "Hermes Local LLM" "%~dp0start-llama-server.bat"
|
||||
echo [*] Waiting for LLM server to be ready (polling)...
|
||||
set POLL_COUNT=0
|
||||
:wait_llm
|
||||
set /a POLL_COUNT+=1
|
||||
if !POLL_COUNT! gtr 30 (
|
||||
echo [WARN] LLM server not ready after 30s - starting anyway...
|
||||
goto skip_wait
|
||||
)
|
||||
>nul 2>&1 curl -s http://127.0.0.1:11434/v1/models && (
|
||||
echo [OK] LLM server is ready!
|
||||
goto skip_wait
|
||||
)
|
||||
>nul 2>&1 timeout /t 1 /nobreak
|
||||
goto wait_llm
|
||||
:skip_wait
|
||||
echo.
|
||||
echo [*] Starting Hermes CLI (offline mode - local LLM)...
|
||||
set HERMES_HOME=%~dp0..\hermes\offline
|
||||
if not exist "!HERMES_HOME!" mkdir "!HERMES_HOME!"
|
||||
"!PYTHON!" -m hermes_cli --config "!HERMES_ROOT!\config.offline.yaml"
|
||||
echo.
|
||||
pause
|
||||
goto menu
|
||||
|
||||
:run_dashboard
|
||||
echo.
|
||||
echo [*] Starting web dashboard at http://localhost:8080
|
||||
echo [*] On other devices, use http://rescue.local:8080
|
||||
echo.
|
||||
start "Hermes Dashboard" "http://localhost:8080"
|
||||
"!PYTHON!" "!WEB_SERVER!"
|
||||
pause
|
||||
goto menu
|
||||
|
||||
:run_diag
|
||||
echo.
|
||||
echo [*] Running full diagnostics...
|
||||
echo.
|
||||
for %%s in (hardware bsod drivers stress) do (
|
||||
echo.
|
||||
echo --- %%s ---
|
||||
"!PYTHON!" "!HERMES_ROOT!\scripts\%%s.py"
|
||||
)
|
||||
echo.
|
||||
pause
|
||||
goto menu
|
||||
|
||||
:run_llm
|
||||
echo.
|
||||
echo [*] Starting llama-server (local LLM backend)...
|
||||
echo [*] Model: qwen2.5-coder-1.5b-q4_k_m.gguf
|
||||
echo [*] Server: http://127.0.0.1:11434/v1
|
||||
echo [*] Press Ctrl+C to stop when done.
|
||||
echo.
|
||||
start "Hermes LLM Server" "%~dp0start-llama-server.bat"
|
||||
echo [OK] Server starting in new window.
|
||||
echo.
|
||||
pause
|
||||
goto menu
|
||||
@@ -0,0 +1,125 @@
|
||||
@echo off
|
||||
:: ==============================================================================
|
||||
:: Hermes Portable Rescue - llama-server launcher with GPU detection
|
||||
:: ==============================================================================
|
||||
:: Detects GPU brand (NVIDIA, AMD, Intel, integrated) and launches the
|
||||
:: appropriate llama-server build (Vulkan for GPU, CPU-only fallback).
|
||||
:: ==============================================================================
|
||||
setlocal enabledelayedexpansion
|
||||
|
||||
cd /d "%~dp0"
|
||||
|
||||
set LLAMA_DIR=%~dp0bin\llama
|
||||
set MODEL_DIR=%~dp0bin\ollama
|
||||
set MODEL=%MODEL_DIR%\qwen2.5-coder-1.5b-q4_k_m.gguf
|
||||
set PORT=11434
|
||||
set GPU_FOUND=0
|
||||
|
||||
echo.
|
||||
echo ============================================
|
||||
echo Hermes LLM Server - GPU Detection
|
||||
echo ============================================
|
||||
echo.
|
||||
|
||||
:: --- Detection 1: nvidia-smi (NVIDIA) --------------------------------------
|
||||
nvidia-smi >nul 2>&1
|
||||
if !errorlevel! equ 0 (
|
||||
for /f "tokens=*" %%a in ('nvidia-smi --query-gpu=name --format=csv,noheader 2^>nul') do (
|
||||
set GPU_NAME=%%a
|
||||
)
|
||||
echo [OK] NVIDIA GPU detected: !GPU_NAME!
|
||||
set GPU_FOUND=1
|
||||
)
|
||||
|
||||
:: Detection 2: WMIC - check for AMD/Intel GPUs
|
||||
if !GPU_FOUND! equ 0 (
|
||||
wmic path win32_videocontroller get name 2>nul | findstr /i "nvidia" >nul
|
||||
if !errorlevel! equ 0 (
|
||||
echo [OK] NVIDIA GPU detected via WMI
|
||||
set GPU_FOUND=1
|
||||
) else (
|
||||
wmic path win32_videocontroller get name 2>nul | findstr /i "amd radeon" >nul
|
||||
if !errorlevel! equ 0 (
|
||||
echo [OK] AMD GPU detected via WMI
|
||||
set GPU_FOUND=1
|
||||
) else (
|
||||
wmic path win32_videocontroller get name 2>nul | findstr /i "intel arc" >nul
|
||||
if !errorlevel! equ 0 (
|
||||
echo [OK] Intel GPU detected via WMI
|
||||
set GPU_FOUND=1
|
||||
) else (
|
||||
wmic path win32_videocontroller get name 2>nul | findstr /i "intel hd intel iris intel uhd" >nul
|
||||
if !errorlevel! equ 0 (
|
||||
echo [OK] Intel integrated graphics detected via WMI
|
||||
set GPU_FOUND=1
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
:: Detection 3: vulkaninfo (direct Vulkan probe)
|
||||
if !GPU_FOUND! equ 0 (
|
||||
where vulkaninfo >nul 2>&1
|
||||
if !errorlevel! equ 0 (
|
||||
vulkaninfo --summary 2>nul | findstr /c:"Vulkan Instance" >nul
|
||||
if !errorlevel! equ 0 (
|
||||
echo [OK] Vulkan-capable device detected
|
||||
set GPU_FOUND=1
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
:: Check model exists
|
||||
if not exist "!MODEL!" (
|
||||
echo [ERROR] Model not found: !MODEL!
|
||||
echo.
|
||||
echo Please download a GGUF model and place it at:
|
||||
echo !MODEL!
|
||||
echo.
|
||||
echo Recommended: Qwen 2.5 Coder 1.5B Q4_K_M
|
||||
echo https://huggingface.co/Qwen/Qwen2.5-Coder-1.5B-Instruct-GGUF
|
||||
echo.
|
||||
pause
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:: Launch
|
||||
if !GPU_FOUND! equ 1 (
|
||||
echo.
|
||||
echo [*] Starting llama-server with GPU acceleration (Vulkan)...
|
||||
echo [*] Model: qwen2.5-coder-1.5b-q4_k_m.gguf
|
||||
echo [*] Server: http://127.0.0.1:!PORT!/v1
|
||||
echo [*] Flags: --n-gpu-layers 99 --mlock --cont-batching -c 4096
|
||||
echo.
|
||||
echo [*] Press Ctrl+C to stop the server.
|
||||
echo.
|
||||
|
||||
"!LLAMA_DIR!\llama-server.exe" ^
|
||||
--host 127.0.0.1 --port !PORT! ^
|
||||
-m "!MODEL!" ^
|
||||
--n-gpu-layers 99 ^
|
||||
--mlock ^
|
||||
--cont-batching ^
|
||||
-c 4096
|
||||
) else (
|
||||
echo.
|
||||
echo [*] No compatible GPU found. Starting CPU-only mode.
|
||||
echo [*] Model: qwen2.5-coder-1.5b-q4_k_m.gguf
|
||||
echo [*] Server: http://127.0.0.1:!PORT!/v1
|
||||
echo [*] Flags: --mlock --cont-batching -c 4096
|
||||
echo.
|
||||
echo [*] Press Ctrl+C to stop the server.
|
||||
echo.
|
||||
|
||||
"!LLAMA_DIR!\cpu\llama-server-cpu.exe" ^
|
||||
--host 127.0.0.1 --port !PORT! ^
|
||||
-m "!MODEL!" ^
|
||||
--mlock ^
|
||||
--cont-batching ^
|
||||
-c 4096
|
||||
)
|
||||
|
||||
echo.
|
||||
echo [*] Server exited with code !errorlevel!
|
||||
pause
|
||||
Reference in New Issue
Block a user