modelpath.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. package server
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/url"
  6. "os"
  7. "path/filepath"
  8. "runtime"
  9. "strings"
  10. )
  11. type ModelPath struct {
  12. ProtocolScheme string
  13. Registry string
  14. Namespace string
  15. Repository string
  16. Tag string
  17. }
  18. const (
  19. DefaultRegistry = "registry.ollama.ai"
  20. DefaultNamespace = "library"
  21. DefaultTag = "latest"
  22. DefaultProtocolScheme = "https"
  23. )
  24. var (
  25. ErrInvalidImageFormat = errors.New("invalid image format")
  26. ErrInvalidProtocol = errors.New("invalid protocol scheme")
  27. ErrInsecureProtocol = errors.New("insecure protocol http")
  28. )
  29. func ParseModelPath(name string) ModelPath {
  30. mp := ModelPath{
  31. ProtocolScheme: DefaultProtocolScheme,
  32. Registry: DefaultRegistry,
  33. Namespace: DefaultNamespace,
  34. Repository: "",
  35. Tag: DefaultTag,
  36. }
  37. before, after, found := strings.Cut(name, "://")
  38. if found {
  39. mp.ProtocolScheme = before
  40. name = after
  41. }
  42. parts := strings.Split(name, string(os.PathSeparator))
  43. switch len(parts) {
  44. case 3:
  45. mp.Registry = parts[0]
  46. mp.Namespace = parts[1]
  47. mp.Repository = parts[2]
  48. case 2:
  49. mp.Namespace = parts[0]
  50. mp.Repository = parts[1]
  51. case 1:
  52. mp.Repository = parts[0]
  53. }
  54. if repo, tag, found := strings.Cut(mp.Repository, ":"); found {
  55. mp.Repository = repo
  56. mp.Tag = tag
  57. }
  58. return mp
  59. }
  60. func (mp ModelPath) GetNamespaceRepository() string {
  61. return fmt.Sprintf("%s/%s", mp.Namespace, mp.Repository)
  62. }
  63. func (mp ModelPath) GetFullTagname() string {
  64. return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
  65. }
  66. func (mp ModelPath) GetShortTagname() string {
  67. if mp.Registry == DefaultRegistry {
  68. if mp.Namespace == DefaultNamespace {
  69. return fmt.Sprintf("%s:%s", mp.Repository, mp.Tag)
  70. }
  71. return fmt.Sprintf("%s/%s:%s", mp.Namespace, mp.Repository, mp.Tag)
  72. }
  73. return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
  74. }
  75. func (mp ModelPath) GetManifestPath(createDir bool) (string, error) {
  76. home, err := os.UserHomeDir()
  77. if err != nil {
  78. return "", err
  79. }
  80. path := filepath.Join(home, ".ollama", "models", "manifests", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
  81. if createDir {
  82. if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
  83. return "", err
  84. }
  85. }
  86. return path, nil
  87. }
  88. func (mp ModelPath) BaseURL() *url.URL {
  89. return &url.URL{
  90. Scheme: mp.ProtocolScheme,
  91. Host: mp.Registry,
  92. }
  93. }
  94. func GetManifestPath() (string, error) {
  95. home, err := os.UserHomeDir()
  96. if err != nil {
  97. return "", err
  98. }
  99. path := filepath.Join(home, ".ollama", "models", "manifests")
  100. if err := os.MkdirAll(path, 0o755); err != nil {
  101. return "", err
  102. }
  103. return path, nil
  104. }
  105. func GetBlobsPath(digest string) (string, error) {
  106. home, err := os.UserHomeDir()
  107. if err != nil {
  108. return "", err
  109. }
  110. if runtime.GOOS == "windows" {
  111. digest = strings.ReplaceAll(digest, ":", "-")
  112. }
  113. path := filepath.Join(home, ".ollama", "models", "blobs", digest)
  114. dirPath := filepath.Dir(path)
  115. if digest == "" {
  116. dirPath = path
  117. }
  118. if err := os.MkdirAll(dirPath, 0o755); err != nil {
  119. return "", err
  120. }
  121. return path, nil
  122. }