|
| 1 | +/* |
| 2 | + * Copyright 2024 The CNAI Authors |
| 3 | + * |
| 4 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | + * you may not use this file except in compliance with the License. |
| 6 | + * You may obtain a copy of the License at |
| 7 | + * |
| 8 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | + * |
| 10 | + * Unless required by applicable law or agreed to in writing, software |
| 11 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | + * See the License for the specific language governing permissions and |
| 14 | + * limitations under the License. |
| 15 | + */ |
| 16 | + |
| 17 | +package backend |
| 18 | + |
| 19 | +import ( |
| 20 | + "context" |
| 21 | + "encoding/json" |
| 22 | + "fmt" |
| 23 | + |
| 24 | + modelspec "github.com/CloudNativeAI/modctl/pkg/spec" |
| 25 | + ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
| 26 | +) |
| 27 | + |
| 28 | +// InspectedModelArtifact is the data structure for model artifact that has been inspected. |
| 29 | +type InspectedModelArtifact struct { |
| 30 | + // ID is the image id of the model artifact. |
| 31 | + ID string `json:"Id"` |
| 32 | + // Digest is the digest of the model artifact. |
| 33 | + Digest string `json:"Digest"` |
| 34 | + // Architecture is the architecture of the model. |
| 35 | + Architecture string `json:"Architecture"` |
| 36 | + // Created is the creation time of the model artifact. |
| 37 | + Created string `json:"Created"` |
| 38 | + // Family is the family of the model. |
| 39 | + Family string `json:"Family"` |
| 40 | + // Format is the format of the model. |
| 41 | + Format string `json:"Format"` |
| 42 | + // Name is the name of the model. |
| 43 | + Name string `json:"Name"` |
| 44 | + // ParamSize is the param size of the model. |
| 45 | + ParamSize string `json:"ParamSize"` |
| 46 | + // Precision is the precision of the model. |
| 47 | + Precision string `json:"Precision"` |
| 48 | + // Quantization is the quantization of the model. |
| 49 | + Quantization string `json:"Quantization"` |
| 50 | + // Layers is the layers of the model artifact. |
| 51 | + Layers []InspectedModelArtifactLayer `json:"Layers"` |
| 52 | +} |
| 53 | + |
| 54 | +// InspectedModelArtifactLayer is the data structure for model artifact layer that has been inspected. |
| 55 | +type InspectedModelArtifactLayer struct { |
| 56 | + // Digest is the digest of the model artifact layer. |
| 57 | + Digest string `json:"Digest"` |
| 58 | + // Size is the size of the model artifact layer. |
| 59 | + Size int64 `json:"Size"` |
| 60 | + // Filepath is the filepath of the model artifact layer. |
| 61 | + Filepath string `json:"Filepath"` |
| 62 | +} |
| 63 | + |
| 64 | +// Inspect inspects the target from the storage. |
| 65 | +func (b *backend) Inspect(ctx context.Context, target string) (*InspectedModelArtifact, error) { |
| 66 | + ref, err := ParseReference(target) |
| 67 | + if err != nil { |
| 68 | + return nil, fmt.Errorf("failed to parse target: %w", err) |
| 69 | + } |
| 70 | + |
| 71 | + repo, tag := ref.Repository(), ref.Tag() |
| 72 | + manifestRaw, digest, err := b.store.PullManifest(ctx, repo, tag) |
| 73 | + if err != nil { |
| 74 | + return nil, fmt.Errorf("failed to get manifest: %w", err) |
| 75 | + } |
| 76 | + |
| 77 | + var manifest ocispec.Manifest |
| 78 | + if err := json.Unmarshal(manifestRaw, &manifest); err != nil { |
| 79 | + return nil, fmt.Errorf("failed to unmarshal manifest: %w", err) |
| 80 | + } |
| 81 | + |
| 82 | + inspectedModelArtifact := &InspectedModelArtifact{ |
| 83 | + ID: manifest.Config.Digest.String(), |
| 84 | + Digest: digest, |
| 85 | + Architecture: manifest.Annotations[modelspec.AnnotationArchitecture], |
| 86 | + Created: manifest.Annotations[modelspec.AnnotationCreated], |
| 87 | + Family: manifest.Annotations[modelspec.AnnotationFamily], |
| 88 | + Format: manifest.Annotations[modelspec.AnnotationFormat], |
| 89 | + Name: manifest.Annotations[modelspec.AnnotationName], |
| 90 | + ParamSize: manifest.Annotations[modelspec.AnnotationParamSize], |
| 91 | + Precision: manifest.Annotations[modelspec.AnnotationPrecision], |
| 92 | + Quantization: manifest.Annotations[modelspec.AnnotationQuantization], |
| 93 | + } |
| 94 | + |
| 95 | + for _, layer := range manifest.Layers { |
| 96 | + inspectedModelArtifact.Layers = append(inspectedModelArtifact.Layers, InspectedModelArtifactLayer{ |
| 97 | + Digest: layer.Digest.String(), |
| 98 | + Size: layer.Size, |
| 99 | + Filepath: layer.Annotations[modelspec.AnnotationFilepath], |
| 100 | + }) |
| 101 | + } |
| 102 | + |
| 103 | + return inspectedModelArtifact, nil |
| 104 | +} |
0 commit comments