Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow for a configurable ollama model storage directory #897

Merged
merged 5 commits into from Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 0 additions & 4 deletions api/client.go
Expand Up @@ -18,10 +18,6 @@ import (
"github.com/jmorganca/ollama/version"
)

const DefaultHost = "127.0.0.1:11434"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused


var envHost = os.Getenv("OLLAMA_HOST")

type Client struct {
base *url.URL
http http.Client
Expand Down
4 changes: 4 additions & 0 deletions docs/faq.md
Expand Up @@ -60,3 +60,7 @@ systemctl restart ollama

- macOS: Raw model data is stored under `~/.ollama/models`.
- Linux: Raw model data is stored under `/usr/share/ollama/.ollama/models`

### How can I change where Ollama stores models?

To modify where models are stored, you can use the `OLLAMA_MODELS` environment variable. Note that on Linux this means defining `OLLAMA_MODELS` in a drop-in `/etc/systemd/system/ollama.service.d` service file, reloading systemd, and restarting the ollama service.
21 changes: 15 additions & 6 deletions server/images.go
Expand Up @@ -131,7 +131,7 @@ func (m *ManifestV2) GetTotalSize() (total int64) {
}

func GetManifest(mp ModelPath) (*ManifestV2, string, error) {
fp, err := mp.GetManifestPath(false)
fp, err := mp.GetManifestPath()
if err != nil {
return nil, "", err
}
Expand Down Expand Up @@ -595,10 +595,13 @@ func CreateManifest(name string, cfg *LayerReader, layers []*Layer) error {
return err
}

fp, err := mp.GetManifestPath(true)
fp, err := mp.GetManifestPath()
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(fp), 0o755); err != nil {
return err
}
return os.WriteFile(fp, manifestJSON, 0o644)
}

Expand Down Expand Up @@ -710,16 +713,19 @@ func CreateLayer(f io.ReadSeeker) (*LayerReader, error) {

func CopyModel(src, dest string) error {
srcModelPath := ParseModelPath(src)
srcPath, err := srcModelPath.GetManifestPath(false)
srcPath, err := srcModelPath.GetManifestPath()
if err != nil {
return err
}

destModelPath := ParseModelPath(dest)
destPath, err := destModelPath.GetManifestPath(true)
destPath, err := destModelPath.GetManifestPath()
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(destPath), 0o755); err != nil {
return err
}

// copy the file
input, err := os.ReadFile(srcPath)
Expand Down Expand Up @@ -882,7 +888,7 @@ func DeleteModel(name string) error {
return err
}

fp, err := mp.GetManifestPath(false)
fp, err := mp.GetManifestPath()
if err != nil {
return err
}
Expand Down Expand Up @@ -1121,10 +1127,13 @@ func PullModel(ctx context.Context, name string, regOpts *RegistryOptions, fn fu
return err
}

fp, err := mp.GetManifestPath(true)
fp, err := mp.GetManifestPath()
if err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(fp), 0o755); err != nil {
return err
}

err = os.WriteFile(fp, manifestJSON, 0o644)
if err != nil {
Expand Down
29 changes: 18 additions & 11 deletions server/modelpath.go
Expand Up @@ -85,20 +85,27 @@ func (mp ModelPath) GetShortTagname() string {
return fmt.Sprintf("%s/%s/%s:%s", mp.Registry, mp.Namespace, mp.Repository, mp.Tag)
}

func (mp ModelPath) GetManifestPath(createDir bool) (string, error) {
// modelsDir returns the value of the OLLAMA_MODELS environment variable or the user's home directory if OLLAMA_MODELS is not set.
// The models directory is where Ollama stores its model files and manifests.
func modelsDir() (string, error) {
if models, exists := os.LookupEnv("OLLAMA_MODELS"); exists {
return models, nil
}
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".ollama", "models"), nil
}

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
}
// GetManifestPath returns the path to the manifest file for the given model path, it is up to the caller to create the directory if it does not exist.
func (mp ModelPath) GetManifestPath() (string, error) {
dir, err := modelsDir()
if err != nil {
return "", err
}

return path, nil
return filepath.Join(dir, "manifests", mp.Registry, mp.Namespace, mp.Repository, mp.Tag), nil
}

func (mp ModelPath) BaseURL() *url.URL {
Expand All @@ -109,12 +116,12 @@ func (mp ModelPath) BaseURL() *url.URL {
}

func GetManifestPath() (string, error) {
home, err := os.UserHomeDir()
dir, err := modelsDir()
if err != nil {
return "", err
}

path := filepath.Join(home, ".ollama", "models", "manifests")
path := filepath.Join(dir, "manifests")
if err := os.MkdirAll(path, 0o755); err != nil {
return "", err
}
Expand All @@ -123,7 +130,7 @@ func GetManifestPath() (string, error) {
}

func GetBlobsPath(digest string) (string, error) {
home, err := os.UserHomeDir()
dir, err := modelsDir()
if err != nil {
return "", err
}
Expand All @@ -132,7 +139,7 @@ func GetBlobsPath(digest string) (string, error) {
digest = strings.ReplaceAll(digest, ":", "-")
}

path := filepath.Join(home, ".ollama", "models", "blobs", digest)
path := filepath.Join(dir, "blobs", digest)
dirPath := filepath.Dir(path)
if digest == "" {
dirPath = path
Expand Down