mirror of
https://github.com/mudler/LocalAI.git
synced 2026-07-30 09:57:57 -04:00
* feat(config): add model artifact source contract Assisted-by: Codex:GPT-5 [Codex] * feat(downloader): add authenticated raw-byte progress Assisted-by: Codex:GPT-5 [Codex] * feat(huggingface): resolve immutable snapshot manifests Assisted-by: Codex:GPT-5 [Codex] * feat(models): add artifact storage primitives Assisted-by: Codex:GPT-5 [Codex] * feat(models): materialize pinned Hugging Face snapshots Assisted-by: Codex:GPT-5 [Codex] * feat(models): bind managed snapshots at runtime Assisted-by: Codex:GPT-5 [Codex] * feat(gallery): materialize model artifacts during install Assisted-by: Codex:GPT-5 [Codex] * feat(gallery): declare managed Hugging Face artifacts Assisted-by: Codex:GPT-5 [Codex] * feat(models): preload managed model artifacts Assisted-by: Codex:GPT-5 [Codex] * fix(gallery): retain shared artifact caches on delete Assisted-by: Codex:GPT-5 [Codex] * feat(models): report artifact acquisition progress Assisted-by: Codex:GPT-5 [Codex] * refactor(backends): load managed models from ModelFile Assisted-by: Codex:GPT-5 [Codex] * refactor(backends): load staged speech model snapshots Assisted-by: Codex:GPT-5 [Codex] * refactor(backends): use staged snapshots in engine backends Assisted-by: Codex:GPT-5 [Codex] * test(distributed): cover staged artifact snapshots Assisted-by: Codex:GPT-5 [Codex] * docs: explain managed model artifacts Assisted-by: Codex:GPT-5 [Codex] * docs: add product design context Assisted-by: Codex:GPT-5 [Codex] * feat(ui): show model artifact download progress Assisted-by: Codex:GPT-5 [Codex] * Eagerly materialize Hugging Face artifacts Materialize HF-backed model references as managed GGUF artifacts during load, with lazy download retained only as fallback. Assisted-by: Codex:GPT-5 [shell] * Refactor HF downloads through a shared executor Assisted-by: Codex:GPT-5 [shell] * drop Signed-off-by: Ettore Di Giacinto <mudler@localai.io> --------- Signed-off-by: Ettore Di Giacinto <mudler@localai.io> Co-authored-by: Ettore Di Giacinto <mudler@localai.io>
72 lines
1.4 KiB
Go
72 lines
1.4 KiB
Go
package downloader
|
|
|
|
import (
|
|
"context"
|
|
"hash"
|
|
)
|
|
|
|
type progressWriter struct {
|
|
fileName string
|
|
total int64
|
|
fileNo int
|
|
totalFiles int
|
|
written int64
|
|
downloadStatus func(string, string, string, float64)
|
|
transferSink TransferProgressSink
|
|
hash hash.Hash
|
|
ctx context.Context
|
|
}
|
|
|
|
func (pw *progressWriter) report() {
|
|
if pw.transferSink != nil {
|
|
pw.transferSink(TransferProgress{
|
|
FileName: pw.fileName,
|
|
Written: pw.written,
|
|
Total: pw.total,
|
|
})
|
|
}
|
|
if pw.downloadStatus == nil {
|
|
return
|
|
}
|
|
percentage := float64(0)
|
|
total := ""
|
|
if pw.total > 0 {
|
|
percentage = float64(pw.written) / float64(pw.total) * 100
|
|
total = formatBytes(pw.total)
|
|
if pw.totalFiles > 1 {
|
|
percentage = percentage/float64(pw.totalFiles) + float64(pw.fileNo)*100/float64(pw.totalFiles)
|
|
}
|
|
}
|
|
pw.downloadStatus(pw.fileName, formatBytes(pw.written), total, percentage)
|
|
}
|
|
|
|
func (pw *progressWriter) Write(p []byte) (n int, err error) {
|
|
// Check for cancellation before writing
|
|
if pw.ctx != nil {
|
|
select {
|
|
case <-pw.ctx.Done():
|
|
return 0, pw.ctx.Err()
|
|
default:
|
|
}
|
|
}
|
|
|
|
n, err = pw.hash.Write(p)
|
|
if err != nil {
|
|
return n, err
|
|
}
|
|
pw.written += int64(n)
|
|
|
|
// Check for cancellation after writing chunk
|
|
if pw.ctx != nil {
|
|
select {
|
|
case <-pw.ctx.Done():
|
|
return n, pw.ctx.Err()
|
|
default:
|
|
}
|
|
}
|
|
|
|
pw.report()
|
|
|
|
return
|
|
}
|