param( [string]$SshTarget = "docker-gpu", [string]$DockerHost = "ssh://docker-gpu", [switch]$PlanOnly, [switch]$SkipDownload, [switch]$SkipPreflight, [switch]$SkipTrain, [switch]$SkipConvert, [switch]$SkipRestart, [switch]$SkipSmoke, [switch]$DetachedDownload, [switch]$DetachedConvert, [string]$BaseModelCardId = "qwen3-coder-30b-a3b-instruct", [string]$BaseModelDir = "/models/base/qwen3-coder-30b-a3b-instruct", [string]$AdapterDir = "/models/adapters/1c/qwen3-coder-30b-a3b-1c-lora-v1", [string]$AdapterGgufPath = "/models/adapters/1c/qwen3-coder-30b-a3b-1c-lora-v1.gguf", [string]$InferenceBaseUrl = "http://docker-gpu.cin.su:8081", [string]$InferenceModel = "qwen3-coder-1c-q6" ) $ErrorActionPreference = "Stop" function Invoke-Step { param( [Parameter(Mandatory = $true)] [string]$Name, [Parameter(Mandatory = $true)] [string[]]$Command ) Write-Host "" Write-Host "== $Name" Write-Host ($Command -join " ") if ($PlanOnly) { return } & $Command[0] @($Command | Select-Object -Skip 1) if ($LASTEXITCODE -ne 0) { throw "Step failed with exit code ${LASTEXITCODE}: ${Name}" } } $steps = @() $steps += @{ Name = "GPU host preflight" Command = @( "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts/check_gpu_host.ps1", "-SshTarget", $SshTarget ) } if (-not $SkipDownload) { $downloadCommand = @( "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts/download_hf_range_gpu.ps1", "-CardId", $BaseModelCardId, "-LocalDir", $BaseModelDir, "-ContainerName", "llm-hf-range-qwen3-coder-base" ) if ($DetachedDownload) { $downloadCommand += "-Detached" } $steps += @{ Name = "Download base HF model" Command = $downloadCommand } } if (-not $SkipPreflight) { $steps += @{ Name = "Training preflight" Command = @( "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts/run_1c_lora_training_gpu.ps1", "-PreflightOnly" ) } } if (-not $SkipTrain) { $steps += @{ Name = "Train LoRA adapter" Command = @( "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts/run_1c_lora_training_gpu.ps1" ) } } if (-not $SkipConvert) { $convertCommand = @( "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts/convert_1c_lora_to_gguf_gpu.ps1", "-AdapterDir", $AdapterDir, "-BaseModelDir", $BaseModelDir, "-OutputFile", $AdapterGgufPath ) if ($DetachedConvert) { $convertCommand += "-Detached" } $steps += @{ Name = "Convert adapter to GGUF" Command = $convertCommand } } if (-not $SkipRestart) { $steps += @{ Name = "Stop Q6 service" Command = @( "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts/manage_gpu_q6_service.ps1", "-Action", "stop" ) } $steps += @{ Name = "Start Q6 service with LoRA" Command = @( "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts/manage_gpu_q6_service.ps1", "-Action", "start", "-LoraPath", $AdapterGgufPath ) } $steps += @{ Name = "Check Q6 service status" Command = @( "powershell", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "scripts/manage_gpu_q6_service.ps1", "-Action", "status", "-LoraPath", $AdapterGgufPath ) } } if (-not $SkipSmoke) { $steps += @{ Name = "Check inference endpoint" Command = @( "python", "scripts/check_inference_endpoint.py", "--base-url", $InferenceBaseUrl, "--expected-model", $InferenceModel, "--print" ) } $steps += @{ Name = "Run 1C smoke eval" Command = @( "python", "scripts/run_1c_smoke_eval.py", "--base-url", $InferenceBaseUrl, "--model", $InferenceModel ) } } foreach ($step in $steps) { if ($SkipPreflight -and $step.Name -eq "GPU host preflight") { continue } Invoke-Step -Name $step.Name -Command $step.Command } if ($PlanOnly) { Write-Host "" Write-Host "Plan complete. Re-run without -PlanOnly to execute." } else { Write-Host "" Write-Host "Q6 LoRA training/publish flow completed." }