Ollama 模型遷移備份工具 ollamab
背景
ollama 模型和相關配置文件默認都放在 models 文件夾下,想要把指定模型遷移到其他電腦比較麻煩,所以就有了該工具。還有就是模型下載本身就慢,一次下載多臺使用減少下載次數。最重要的是公司電腦下載快,家里下載慢,在公司下載拷貝回家用 ??
如何使用
下載地址:
- Window ollamab.exe
- Linux ollamab
命令
ollamab 模型名稱+型號(和 ollama 名稱列表一致) 輸出路徑 (可選)
ollamab.exe qwen:0.5b D:/
執行結果
D:\code\private\model-backup>ollamab.exe qwen:0.5b
模型路徑: D:\ai\.ollama\models
開始打包,耐心等待…………
添加到 ZIP 中: blobs\sha256-fad2a06e4cc705c2fa8bec5477ddb00dc0c859ac184c34dcc5586663774161ca
添加到 ZIP 中: blobs\sha256-41c2cf8c272f6fb0080a97cd9d9bd7d4604072b80a0b10e7d65ca26ef5000c0c
添加到 ZIP 中: blobs\sha256-1da0581fd4ce92dcf5a66b1da737cf215d8dcf25aa1b98b44443aaf7173155f5
添加到 ZIP 中: blobs\sha256-f02dd72bb2423204352eabc5637b44d79d17f109fdb510a7c51455892aa2d216
添加到 ZIP 中: manifests\registry.ollama.ai\library\qwen\0.5b
zip文件創建成功: qwen-0.5b.zip
目標電腦
將打包的 zip 拷貝到目標電腦 models 下直接解壓到當前目錄即可
ollama
ollama list 輸出所有模型命令
NAME ID SIZE MODIFIED
gemma2:9b ff02c3702f32 5.4 GB 5 hours ago
phi:2.7b e2fd6321a5fe 1.6 GB 5 hours ago
qwen:7b 2091ee8c8d8f 4.5 GB 4 days ago
qwen:0.5b b5dc5e784f2a 394 MB 4 days ago
llama3.1:8b 46e0c10c039e 4.9 GB 5 days ago
deepseek-r1:1.5b a42b25d8c10a 1.1 GB 6 days ago
deepseek-r1:7b 0a8c26691023 4.7 GB 8 days ago
Ollama 在 Windows 上存儲文件在幾個不同的位置。您可以通過以下步驟查看它們:
-
按
<cmd>+R鍵并輸入:-
explorer %LOCALAPPDATA%\Ollama:包含日志和下載的更新- app.log:最近的 GUI 應用程序日志
- server.log:最近的服務器日志
- upgrade.log:升級日志輸出
-
explorer %LOCALAPPDATA%\Programs\Ollama:包含二進制文件(安裝器將其添加到用戶 PATH 中) -
explorer %HOMEPATH%\.ollama:包含模型和配置 -
explorer %TEMP%:包含臨時執行文件,在一個或多個ollama*目錄中
-
源碼
/**
* @Time : 2025/2/14
* @File : main.go
* @Software: ollamab
* @Author : Mr.Fang
* @Description: 備份 ollama 模型
*/
package main
import (
"archive/zip"
"encoding/json"
"fmt"
"io"
"log"
"os"
"path/filepath"
"runtime"
"strings"
)
var modelPath = ""
// 初始化獲取模型文件路徑,優先從系統環境變量獲取,其次獲取默認路徑
func init() {
models := os.Getenv("OLLAMA_MODELS")
if len(models) > 0 {
modelPath = models
} else {
// Window
if runtime.GOOS == "windows" {
home, err := os.UserHomeDir()
if err != nil {
log.Panicln("獲取用戶主目錄失敗:", err)
}
modelPath = filepath.Join(home, ".ollama", "models")
} else { // Linux
modelPath = filepath.Join("/usr/share/ollama/", ".ollama", "models")
}
}
fmt.Println("模型路徑:", modelPath)
}
// 將文件或文件夾添加到 zip 中
func addToZip(zipWriter *zip.Writer, filePath, baseFolder string) error {
// 計算文件的相對路徑
relativePath, err := filepath.Rel(baseFolder, filePath)
if err != nil {
return err
}
fmt.Println("添加到 ZIP 中:", relativePath)
// 如果是目錄,則創建空目錄
info, err := os.Stat(filePath)
if err != nil {
return err
}
// 如果是目錄,創建空目錄
if info.IsDir() {
_, err := zipWriter.Create(relativePath + "/")
return err
}
// 如果是文件,創建文件條目
fileInZip, err := zipWriter.Create(relativePath)
if err != nil {
return err
}
// 打開文件并復制內容到zip中
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
// 復制文件內容到zip
_, err = io.Copy(fileInZip, file)
return err
}
// 模型相關所有文件路徑
func blobsPath(modelDataPath, basePath string) []string {
file, err := os.ReadFile(modelDataPath)
if err != nil {
fmt.Println("model data 文件讀取錯誤!", err)
}
// 轉 map
var modelData map[string]interface{}
var blobsPath []string
err = json.Unmarshal(file, &modelData)
if err != nil {
fmt.Println("model data 轉換錯誤!", err)
}
// 層數據
layers := modelData["layers"].([]interface{})
// 模型詳情信息
layers = append(layers, modelData["config"].(interface{}))
for _, layer := range layers {
item := layer.(map[string]interface{})
digest := item["digest"].(string) // sha256
digest = strings.ReplaceAll(digest, ":", "-")
join := filepath.Join(basePath, "blobs", digest)
// 使用 os.Stat 檢查文件是否存在
fileInfo, _ := os.Stat(join)
if fileInfo != nil {
blobsPath = append(blobsPath, join)
}
}
return blobsPath
}
// build 打包 zip
func build(name string, output string, folderPaths []string) {
fmt.Println("開始打包,耐心等待…………")
// 創建目標zip文件
zipFilePath := filepath.Join(output, name)
zipFile, err := os.Create(zipFilePath)
if err != nil {
fmt.Println("創建zip文件失敗:", err)
return
}
defer zipFile.Close()
// 創建zip寫入器
zipWriter := zip.NewWriter(zipFile)
defer zipWriter.Close()
// 逐個添加文件或目錄到zip文件中
for _, filePath := range folderPaths {
// 注意:baseFolder 是我們希望在zip文件中根目錄
err := addToZip(zipWriter, filePath, modelPath)
if err != nil {
fmt.Println("添加文件到zip失敗:", err)
return
}
}
fmt.Println("zip文件創建成功:", zipFilePath)
}
func main() {
args := os.Args[1:]
if len(args) == 0 {
fmt.Println("參數: ollamab 名稱:型號(必填) 指定輸出路徑,默認輸出當前路徑(可選)")
fmt.Println("示例: ollamab deepseek-r1:1.5b ")
fmt.Println("示例: ollamab deepseek-r1:1.5b D:/models")
fmt.Println("示例: ollamab lrs33/bce-embedding-base_v1:latest")
return
}
arg := strings.Split(args[0], ":")
name := arg[0]
version := arg[1]
output := "./"
if len(args) == 2 {
output = args[1]
}
// 配置文件路徑
library := filepath.Join(modelPath, "manifests", "registry.ollama.ai", "library", name, version)
// 特殊情況,用戶自己分享的模型
contains := strings.Contains(name, "/")
if contains {
libs := strings.Split(name, "/")
library = filepath.Join(modelPath, "manifests", "registry.ollama.ai", libs[0], libs[1], version)
// 替換 "/" 否則無法創建 zip
name = strings.ReplaceAll(name, "/", "-")
}
folderPaths := blobsPath(library, modelPath)
// 模型路徑
folderPaths = append(folderPaths, library)
// 打包
build(fmt.Sprintf("%s-%s.zip", name, version), output, folderPaths)
}
更新說明
- 解決用戶自己分享的模型備份路徑問題
- 模型
config配置文件未拷貝導致ollama list未顯示遷移模型,需要執行ollama run 模型 - Linux 下默認模型路徑未處理
哇!又賺了一天人民幣

浙公網安備 33010602011771號