2023-07-18 05:44:21 +00:00
|
|
|
package server
|
|
|
|
|
|
|
|
import (
|
2023-08-22 04:56:56 +00:00
|
|
|
"errors"
|
2023-07-18 05:44:21 +00:00
|
|
|
"fmt"
|
2023-08-22 01:38:31 +00:00
|
|
|
"net/url"
|
2023-07-18 05:44:21 +00:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2023-07-20 18:23:43 +00:00
|
|
|
"runtime"
|
2023-07-18 05:44:21 +00:00
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ModelPath struct {
|
|
|
|
ProtocolScheme string
|
|
|
|
Registry string
|
|
|
|
Namespace string
|
|
|
|
Repository string
|
|
|
|
Tag string
|
|
|
|
}
|
|
|
|
|
|
|
|
const (
|
|
|
|
DefaultRegistry = "registry.ollama.ai"
|
|
|
|
DefaultNamespace = "library"
|
|
|
|
DefaultTag = "latest"
|
|
|
|
DefaultProtocolScheme = "https"
|
|
|
|
)
|
|
|
|
|
2023-08-22 04:56:56 +00:00
|
|
|
var (
|
|
|
|
ErrInvalidImageFormat = errors.New("invalid image format")
|
|
|
|
ErrInvalidProtocol = errors.New("invalid protocol scheme")
|
|
|
|
ErrInsecureProtocol = errors.New("insecure protocol http")
|
|
|
|
)
|
|
|
|
|
2023-08-22 16:39:42 +00:00
|
|
|
func ParseModelPath(name string) ModelPath {
|
2023-08-22 04:56:56 +00:00
|
|
|
mp := ModelPath{
|
|
|
|
ProtocolScheme: DefaultProtocolScheme,
|
|
|
|
Registry: DefaultRegistry,
|
|
|
|
Namespace: DefaultNamespace,
|
|
|
|
Repository: "",
|
|
|
|
Tag: DefaultTag,
|
|
|
|
}
|
2023-07-18 05:44:21 +00:00
|
|
|
|
2023-08-22 01:38:31 +00:00
|
|
|
before, after, found := strings.Cut(name, "://")
|
|
|
|
if found {
|
|
|
|
mp.ProtocolScheme = before
|
|
|
|
name = after
|
2023-08-22 04:56:56 +00:00
|
|
|
}
|
|
|
|
|
2023-08-22 01:38:31 +00:00
|
|
|
parts := strings.Split(name, "/")
|
2023-08-22 16:39:42 +00:00
|
|
|
switch len(parts) {
|
2023-07-18 05:44:21 +00:00
|
|
|
case 3:
|
2023-08-22 16:39:42 +00:00
|
|
|
mp.Registry = parts[0]
|
|
|
|
mp.Namespace = parts[1]
|
|
|
|
mp.Repository = parts[2]
|
2023-07-18 05:44:21 +00:00
|
|
|
case 2:
|
2023-08-22 16:39:42 +00:00
|
|
|
mp.Namespace = parts[0]
|
|
|
|
mp.Repository = parts[1]
|
2023-07-18 05:44:21 +00:00
|
|
|
case 1:
|
2023-08-22 16:39:42 +00:00
|
|
|
mp.Repository = parts[0]
|
2023-07-18 05:44:21 +00:00
|
|
|
}
|
|
|
|
|
2023-08-22 16:39:42 +00:00
|
|
|
if repo, tag, found := strings.Cut(mp.Repository, ":"); found {
|
2023-08-22 04:56:56 +00:00
|
|
|
mp.Repository = repo
|
|
|
|
mp.Tag = tag
|
2023-07-18 05:44:21 +00:00
|
|
|
}
|
|
|
|
|
2023-08-22 16:39:42 +00:00
|
|
|
return mp
|
2023-07-18 05:44:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (mp ModelPath) GetNamespaceRepository() string {
|
|
|
|
return fmt.Sprintf("%s/%s", mp.Namespace, mp.Repository)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mp ModelPath) GetFullTagname() string {
|
|
|
|
return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (mp ModelPath) GetShortTagname() string {
|
2023-07-21 22:42:19 +00:00
|
|
|
if mp.Registry == DefaultRegistry {
|
|
|
|
if mp.Namespace == DefaultNamespace {
|
|
|
|
return fmt.Sprintf("%s:%s", mp.Repository, mp.Tag)
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("%s/%s:%s", mp.Namespace, mp.Repository, mp.Tag)
|
2023-07-18 05:44:21 +00:00
|
|
|
}
|
2023-07-21 22:42:19 +00:00
|
|
|
return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
|
2023-07-18 05:44:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (mp ModelPath) GetManifestPath(createDir bool) (string, error) {
|
|
|
|
home, err := os.UserHomeDir()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
path := filepath.Join(home, ".ollama", "models", "manifests", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
|
|
|
|
if createDir {
|
|
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return path, nil
|
|
|
|
}
|
|
|
|
|
2023-08-22 01:38:31 +00:00
|
|
|
func (mp ModelPath) BaseURL() *url.URL {
|
|
|
|
return &url.URL{
|
|
|
|
Scheme: mp.ProtocolScheme,
|
|
|
|
Host: mp.Registry,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-18 16:09:45 +00:00
|
|
|
func GetManifestPath() (string, error) {
|
|
|
|
home, err := os.UserHomeDir()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
|
|
|
return filepath.Join(home, ".ollama", "models", "manifests"), nil
|
|
|
|
}
|
|
|
|
|
2023-07-18 05:44:21 +00:00
|
|
|
func GetBlobsPath(digest string) (string, error) {
|
|
|
|
home, err := os.UserHomeDir()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2023-07-20 18:23:43 +00:00
|
|
|
if runtime.GOOS == "windows" {
|
|
|
|
digest = strings.ReplaceAll(digest, ":", "-")
|
|
|
|
}
|
|
|
|
|
2023-07-18 18:24:19 +00:00
|
|
|
path := filepath.Join(home, ".ollama", "models", "blobs", digest)
|
2023-07-18 05:44:21 +00:00
|
|
|
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
|
2023-07-18 18:24:19 +00:00
|
|
|
return path, nil
|
2023-07-18 05:44:21 +00:00
|
|
|
}
|