| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | package server | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2024-06-21 04:45:47 +08:00
										 |  |  | 	"encoding/json" | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2024-06-13 04:30:08 +08:00
										 |  |  | 	"log/slog" | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ollama/ollama/api" | 
					
						
							| 
									
										
										
										
											2025-02-14 08:31:21 +08:00
										 |  |  | 	"github.com/ollama/ollama/fs/ggml" | 
					
						
							| 
									
										
										
										
											2024-06-11 05:54:42 +08:00
										 |  |  | 	"github.com/ollama/ollama/template" | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	"github.com/ollama/ollama/types/model" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-21 05:58:27 +08:00
										 |  |  | var intermediateBlobs map[string]string = make(map[string]string) | 
					
						
							| 
									
										
										
										
											2024-05-11 06:48:41 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-13 04:30:08 +08:00
										 |  |  | type layerGGML struct { | 
					
						
							| 
									
										
										
										
											2024-08-08 05:22:17 +08:00
										 |  |  | 	Layer | 
					
						
							| 
									
										
										
										
											2025-02-14 08:31:21 +08:00
										 |  |  | 	*ggml.GGML | 
					
						
							| 
									
										
										
										
											2024-04-25 23:53:08 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-13 04:30:08 +08:00
										 |  |  | func parseFromModel(ctx context.Context, name model.Name, fn func(api.ProgressResponse)) (layers []*layerGGML, err error) { | 
					
						
							| 
									
										
										
										
											2024-05-09 05:36:08 +08:00
										 |  |  | 	m, err := ParseNamedManifest(name) | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	switch { | 
					
						
							|  |  |  | 	case errors.Is(err, os.ErrNotExist): | 
					
						
							| 
									
										
										
										
											2024-05-02 01:34:39 +08:00
										 |  |  | 		if err := PullModel(ctx, name.String(), ®istryOptions{}, fn); err != nil { | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-09 05:36:08 +08:00
										 |  |  | 		m, err = ParseNamedManifest(name) | 
					
						
							| 
									
										
										
										
											2024-04-24 06:18:45 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	case err != nil: | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-05-09 05:36:08 +08:00
										 |  |  | 	for _, layer := range m.Layers { | 
					
						
							|  |  |  | 		layer, err := NewLayerFromLayer(layer.Digest, layer.MediaType, name.DisplayShortest()) | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch layer.MediaType { | 
					
						
							|  |  |  | 		case "application/vnd.ollama.image.model", | 
					
						
							|  |  |  | 			"application/vnd.ollama.image.projector", | 
					
						
							|  |  |  | 			"application/vnd.ollama.image.adapter": | 
					
						
							|  |  |  | 			blobpath, err := GetBlobsPath(layer.Digest) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			blob, err := os.Open(blobpath) | 
					
						
							|  |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			defer blob.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-18 04:42:40 +08:00
										 |  |  | 			f, err := ggml.Decode(blob, -1) | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				return nil, err | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2024-04-25 23:53:08 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-14 08:31:21 +08:00
										 |  |  | 			layers = append(layers, &layerGGML{layer, f}) | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2024-06-13 04:30:08 +08:00
										 |  |  | 			layers = append(layers, &layerGGML{layer, nil}) | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return layers, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-13 04:30:08 +08:00
										 |  |  | func detectChatTemplate(layers []*layerGGML) ([]*layerGGML, error) { | 
					
						
							|  |  |  | 	for _, layer := range layers { | 
					
						
							|  |  |  | 		if s := layer.GGML.KV().ChatTemplate(); s != "" { | 
					
						
							| 
									
										
										
										
											2024-06-11 05:54:42 +08:00
										 |  |  | 			if t, err := template.Named(s); err != nil { | 
					
						
							| 
									
										
										
										
											2025-03-20 15:15:30 +08:00
										 |  |  | 				slog.Debug("template detection", "error", err, "template", s) | 
					
						
							| 
									
										
										
										
											2024-06-13 04:30:08 +08:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2024-07-06 08:31:23 +08:00
										 |  |  | 				layer, err := NewLayer(t.Reader(), "application/vnd.ollama.image.template") | 
					
						
							| 
									
										
										
										
											2024-06-13 04:30:08 +08:00
										 |  |  | 				if err != nil { | 
					
						
							|  |  |  | 					return nil, err | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-06 08:31:23 +08:00
										 |  |  | 				layer.status = fmt.Sprintf("using autodetected template %s", t.Name) | 
					
						
							|  |  |  | 				layers = append(layers, &layerGGML{layer, nil}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if t.Parameters != nil { | 
					
						
							|  |  |  | 					var b bytes.Buffer | 
					
						
							|  |  |  | 					if err := json.NewEncoder(&b).Encode(t.Parameters); err != nil { | 
					
						
							|  |  |  | 						return nil, err | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					layer, err := NewLayer(&b, "application/vnd.ollama.image.params") | 
					
						
							|  |  |  | 					if err != nil { | 
					
						
							|  |  |  | 						return nil, err | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					layers = append(layers, &layerGGML{layer, nil}) | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2024-06-13 04:30:08 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 	return layers, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func detectContentType(r io.Reader) (string, error) { | 
					
						
							|  |  |  | 	var b bytes.Buffer | 
					
						
							|  |  |  | 	if _, err := io.Copy(&b, r); err != nil { | 
					
						
							|  |  |  | 		return "", err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-02-14 08:31:21 +08:00
										 |  |  | 	if contentType := ggml.DetectContentType(b.Bytes()); contentType != "" { | 
					
						
							| 
									
										
										
										
											2024-04-13 04:55:12 +08:00
										 |  |  | 		return contentType, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if contentType := http.DetectContentType(b.Bytes()); contentType != "application/octet-stream" { | 
					
						
							|  |  |  | 		return contentType, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return "unknown", nil | 
					
						
							|  |  |  | } |