Загрузка данных
# ---------------------------------------------------------------------
# Функция прямой загрузки модели с SHA256-верификацией (без ollama pull)
# Использует curl.exe вместо Invoke-WebRequest
# ---------------------------------------------------------------------
function Invoke-OllamaModelPull {
param(
[Parameter(Mandatory)] [string] $ModelTag, # например "llama3.2:1b"
[string] $ModelsDir, # путь к папке, где хранятся модели
[switch] $SkipHashVerification
)
# Если папка не указана, используем стандартную
if (-not $ModelsDir) { $ModelsDir = "$env:USERPROFILE\.ollama\models" }
# Разбираем тег на имя и тэг
$name, $tag = ($ModelTag -split ':')
if (-not $tag) { $tag = 'latest' }
$basePath = if ($name -notmatch '/') { '/library' } else { '' }
$registryBase = "https://registry.ollama.ai/v2$basePath/$name"
# Создаём структуру каталогов (blobs, manifests)
$blobsDir = Join-Path $ModelsDir 'blobs'
$manifestsDir = Join-Path $ModelsDir "manifests\registry.ollama.ai$basePath\$name"
@($blobsDir, $manifestsDir) | ForEach-Object {
if (-not (Test-Path $_)) { New-Item -ItemType Directory -Path $_ -Force | Out-Null }
}
$ManifestFile = Join-Path $manifestsDir $tag
if (Test-Path $ManifestFile -ErrorAction SilentlyContinue) {
Write-Host " [!] Model already exists in $ModelsDir" -ForegroundColor Yellow
return $true
}
Write-Host " [=] Downloading manifest from $registryBase/manifests/$tag"
curl.exe -L --fail -o "$ManifestFile" "$registryBase/manifests/$tag"
if ($LASTEXITCODE -ne 0) {
Write-Host " [x] Failed to download manifest (curl exit code $LASTEXITCODE)" -ForegroundColor Red
return $false
}
# Читаем манифест (предполагаем, что файл существует и содержит JSON)
try {
$manifestJson = Get-Content $ManifestFile -Raw | ConvertFrom-Json
} catch {
Write-Host " [x] Failed to parse manifest JSON: $_" -ForegroundColor Red
return $false
}
$blobDigests = @($manifestJson.config.digest) + ($manifestJson.layers | ForEach-Object { $_.digest })
$total = $blobDigests.Count
$downloaded = 0
foreach ($digest in $blobDigests) {
$blobFile = Join-Path $blobsDir ($digest -replace ':', '-')
if (Test-Path $blobFile) {
Write-Host " [=] Blob $($downloaded+1)/$total already exists: $digest" -ForegroundColor DarkGray
$downloaded++
continue
}
Write-Host " [=] Downloading blob $($downloaded+1)/$total : $digest"
curl.exe -L --fail -o "$blobFile" "$registryBase/blobs/$digest"
if ($LASTEXITCODE -ne 0) {
Write-Host " [x] Failed to download blob (curl exit code $LASTEXITCODE)" -ForegroundColor Red
return $false
}
# Проверка SHA256 (если не пропущена)
if (-not $SkipHashVerification) {
$computedHash = (Get-FileHash -Path $blobFile -Algorithm SHA256).Hash.ToLower()
$expectedHash = ($digest -replace '^sha256:', '').ToLower()
if ($computedHash -ne $expectedHash) {
Write-Host " [x] Hash mismatch! Expected $expectedHash, got $computedHash" -ForegroundColor Red
return $false
} else {
Write-Host " [+] Hash verified" -ForegroundColor Green
}
}
$downloaded++
}
# Регистрируем модель через API Ollama (только если сервер запущен)
Write-Host " [=] Registering model with Ollama API..." -ForegroundColor DarkGray
$registerBody = @{ name = "$name`:$tag" } | ConvertTo-Json
# Создаём временный файл для тела POST запроса, чтобы избежать проблем с кавычками в cmd.exe
$bodyFile = [System.IO.Path]::GetTempFileName()
Set-Content -Path $bodyFile -Value $registerBody -Encoding UTF8
curl.exe -X POST -H "Content-Type: application/json" -d "@$bodyFile" -o NUL http://localhost:11434/api/pull
$curlExit = $LASTEXITCODE
Remove-Item $bodyFile -Force -ErrorAction SilentlyContinue
if ($curlExit -eq 0) {
Write-Host " [+] Model registered successfully" -ForegroundColor Green
} else {
Write-Host " [!] Could not auto-register (curl exit $curlExit), but model files are ready. You may need to restart Ollama." -ForegroundColor Yellow
}
return $true
}