diff --git a/server/manifest.go b/server/manifest.go index ad206ca57f..613adf61a9 100644 --- a/server/manifest.go +++ b/server/manifest.go @@ -16,6 +16,7 @@ type Manifest struct { ManifestV2 filepath string + stat os.FileInfo digest string `json:"-"` } @@ -55,19 +56,26 @@ func ParseNamedManifest(name model.Name) (*Manifest, error) { manifestpath := filepath.Join(manifests, name.FilepathNoBuild()) var manifest ManifestV2 - file, err := os.Open(manifestpath) + manifestfile, err := os.Open(manifestpath) + if err != nil { + return nil, err + } + defer manifestfile.Close() + + stat, err := manifestfile.Stat() if err != nil { return nil, err } sha256sum := sha256.New() - if err := json.NewDecoder(io.TeeReader(file, sha256sum)).Decode(&manifest); err != nil { + if err := json.NewDecoder(io.TeeReader(manifestfile, sha256sum)).Decode(&manifest); err != nil { return nil, err } return &Manifest{ ManifestV2: manifest, filepath: manifestpath, + stat: stat, digest: fmt.Sprintf("%x", sha256sum.Sum(nil)), }, nil } diff --git a/server/routes.go b/server/routes.go index add41e84ce..2270843c3b 100644 --- a/server/routes.go +++ b/server/routes.go @@ -795,58 +795,44 @@ func GetModelInfo(req api.ShowRequest) (*api.ShowResponse, error) { } func ListModelsHandler(c *gin.Context) { - manifests, err := GetManifestPath() - if err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) - return - } - + var errs []error var models []api.ModelResponse - if err := filepath.Walk(manifests, func(path string, info os.FileInfo, _ error) error { - if !info.IsDir() { - rel, err := filepath.Rel(manifests, path) - if err != nil { - return err - } - - name := model.ParseNameFromFilepath(rel, "") - manifest, err := ParseNamedManifest(name) - if err != nil { - return err - } + // TODO(mxyng): for name, manifest := range Manifests() { ... } + Manifests()(func(name model.Name, manifest *Manifest) bool { + configfile, err := manifest.Config.Open() + if err != nil { + errs = append(errs, err) + return false + } + defer configfile.Close() - configfile, err := manifest.Config.Open() - if err != nil { - return err - } - defer configfile.Close() + var config ConfigV2 + if err := json.NewDecoder(configfile).Decode(&config); err != nil { + errs = append(errs, err) + return false + } - var config ConfigV2 - if err := json.NewDecoder(configfile).Decode(&config); err != nil { - return err - } + mask := "registry.ollama.ai/library/?:?" + models = append(models, api.ModelResponse{ + Model: name.DisplayShortest(mask), + Name: name.DisplayShortest(mask), + Size: manifest.Size(), + Digest: manifest.digest, + ModifiedAt: manifest.stat.ModTime(), + Details: api.ModelDetails{ + Format: config.ModelFormat, + Family: config.ModelFamily, + Families: config.ModelFamilies, + ParameterSize: config.ModelType, + QuantizationLevel: config.FileType, + }, + }) - // tag should never be masked - mask := "registry.ollama.ai/library/?:?" - models = append(models, api.ModelResponse{ - Model: name.DisplayShortest(mask), - Name: name.DisplayShortest(mask), - Size: manifest.Size(), - Digest: manifest.digest, - ModifiedAt: info.ModTime(), - Details: api.ModelDetails{ - Format: config.ModelFormat, - Family: config.ModelFamily, - Families: config.ModelFamilies, - ParameterSize: config.ModelType, - QuantizationLevel: config.FileType, - }, - }) - } + return true + }) - return nil - }); err != nil { - c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + if len(errs) > 0 { + c.JSON(http.StatusInternalServerError, gin.H{"error": errs}) return }