tower-learns-you / scripts /Start-LlamaServer.ps1
vknt's picture
Deploy The Tower Learns You (custom gr.Server frontend, hf_inference + mock fallback)
22a027e verified
Raw
History Blame Contribute Delete
3.87 kB
[CmdletBinding()]
param(
[string]$HostAddress = "127.0.0.1",
[int]$Port = 8080,
[int]$StartupTimeoutSeconds = 120
)
$ErrorActionPreference = "Stop"
if ($HostAddress -notin @("127.0.0.1", "localhost")) {
throw "Refusing non-loopback llama.cpp host: $HostAddress"
}
$repoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path
$runtimeRoot = Join-Path $repoRoot ".local\llama.cpp"
$manifestPath = Join-Path $runtimeRoot "installed.json"
if (-not (Test-Path $manifestPath)) {
throw "llama.cpp is not installed. Run scripts\Install-LlamaCpp.ps1 first."
}
$manifest = Get-Content $manifestPath -Raw | ConvertFrom-Json
$server = Join-Path $runtimeRoot "$($manifest.tag)\llama-server.exe"
$model = Join-Path $repoRoot "Assets\Model\Qwen3-4B-Instruct-2507-Q4_K_M.gguf"
$keyPath = Join-Path $runtimeRoot "api-key.txt"
$pidPath = Join-Path $runtimeRoot "server.pid"
$logPath = Join-Path $runtimeRoot "server.log"
$errorLogPath = Join-Path $runtimeRoot "server-error.log"
if (-not (Test-Path $server)) { throw "llama-server.exe is missing at $server" }
if (-not (Test-Path $model)) { throw "GGUF model is missing at $model" }
if (-not (Test-Path $keyPath)) {
$bytes = New-Object byte[] 32
$generator = [System.Security.Cryptography.RandomNumberGenerator]::Create()
try {
$generator.GetBytes($bytes)
}
finally {
$generator.Dispose()
}
(($bytes | ForEach-Object { $_.ToString("x2") }) -join "") |
Set-Content -LiteralPath $keyPath -Encoding ASCII -NoNewline
}
if (Test-Path $pidPath) {
$recordedPid = Get-Content $pidPath -Raw
if (-not [string]::IsNullOrWhiteSpace($recordedPid)) {
$recordedPid = $recordedPid.Trim()
$existingPid = [int]$recordedPid
if (Get-Process -Id $existingPid -ErrorAction SilentlyContinue) {
throw "A llama.cpp process recorded by $pidPath is already running."
}
}
Set-Content -LiteralPath $pidPath -Value "" -Encoding ASCII -NoNewline
}
$arguments = @(
"--model", $model,
"--alias", "qwen3-4b-instruct-2507",
"--host", $HostAddress,
"--port", "$Port",
"--api-key-file", $keyPath,
"--ctx-size", "8192",
# Current llama.cpp requires an integer; 999 means full offload and --fit may reduce it.
"--gpu-layers", "999",
"--fit", "on",
"--flash-attn", "auto",
"--cache-type-k", "q8_0",
"--cache-type-v", "q8_0",
"--parallel", "1",
"--cache-ram", "1024",
"--cache-prompt",
"--jinja",
"--reasoning", "off",
"--no-ui",
"--offline"
)
# Some hosts inject both Path and PATH. Windows PowerShell's Start-Process
# rejects that duplicate even though Windows normally treats them identically.
$processPath = [Environment]::GetEnvironmentVariable("Path", "Process")
[Environment]::SetEnvironmentVariable("PATH", $null, "Process")
[Environment]::SetEnvironmentVariable("Path", $processPath, "Process")
$process = Start-Process -FilePath $server -ArgumentList $arguments `
-WorkingDirectory (Split-Path $server) -WindowStyle Hidden -PassThru `
-RedirectStandardOutput $logPath -RedirectStandardError $errorLogPath
$process.Id | Set-Content -LiteralPath $pidPath -Encoding ASCII -NoNewline
$deadline = (Get-Date).AddSeconds($StartupTimeoutSeconds)
while ((Get-Date) -lt $deadline) {
if ($process.HasExited) {
throw "llama-server exited during startup. Inspect $logPath"
}
try {
& (Join-Path $PSScriptRoot "Test-LlamaServer.ps1") -Port $Port -KeyPath $keyPath | Out-Null
Write-Output "llama-server is ready on http://127.0.0.1:$Port (PID $($process.Id))."
exit 0
}
catch {
Start-Sleep -Milliseconds 750
}
}
throw "llama-server did not become healthy within $StartupTimeoutSeconds seconds."