2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  server  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
									
										
										
										
											2023-08-22 12:56:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-22 09:38:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"net/url" 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"os" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"path/filepath" 
							 
						 
					
						
							
								
									
										
										
										
											2024-05-06 02:46:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"regexp" 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2024-06-14 03:52:03 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/ollama/ollama/envconfig" 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								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 12:56:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  (  
						 
					
						
							
								
									
										
										
										
											2024-05-06 02:46:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									ErrInvalidImageFormat   =  errors . New ( "invalid image format" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ErrInvalidProtocol      =  errors . New ( "invalid protocol scheme" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ErrInsecureProtocol     =  errors . New ( "insecure protocol http" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ErrInvalidDigestFormat  =  errors . New ( "invalid digest format" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-22 12:56:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 00:39:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ParseModelPath ( name  string )  ModelPath  {  
						 
					
						
							
								
									
										
										
										
											2023-08-22 12:56:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mp  :=  ModelPath { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ProtocolScheme :  DefaultProtocolScheme , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Registry :        DefaultRegistry , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Namespace :       DefaultNamespace , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Repository :      "" , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Tag :             DefaultTag , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-22 09:38:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									before ,  after ,  found  :=  strings . Cut ( name ,  "://" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  found  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mp . ProtocolScheme  =  before 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										name  =  after 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-22 12:56:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-01-17 08:48:05 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									name  =  strings . ReplaceAll ( name ,  string ( os . PathSeparator ) ,  "/" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-16 07:50:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									parts  :=  strings . Split ( name ,  "/" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 00:39:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  len ( parts )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  3 : 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 00:39:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mp . Registry  =  parts [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mp . Namespace  =  parts [ 1 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mp . Repository  =  parts [ 2 ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  2 : 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 00:39:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mp . Namespace  =  parts [ 0 ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mp . Repository  =  parts [ 1 ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  1 : 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 00:39:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mp . Repository  =  parts [ 0 ] 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 00:39:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  repo ,  tag ,  found  :=  strings . Cut ( mp . Repository ,  ":" ) ;  found  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-08-22 12:56:56 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										mp . Repository  =  repo 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										mp . Tag  =  tag 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-23 00:39:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  mp 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-11-30 04:54:29 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								var  errModelPathInvalid  =  errors . New ( "invalid model path" )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( mp  ModelPath )  Validate ( )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  mp . Repository  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "%w: model repository name is required" ,  errModelPathInvalid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  strings . Contains ( mp . Tag ,  ":" )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Errorf ( "%w: ':' (colon) is not allowed in tag names" ,  errModelPathInvalid ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08: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-22 06:42:19 +08: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 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-22 06:42:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  fmt . Sprintf ( "%s/%s/%s:%s" ,  mp . Registry ,  mp . Namespace ,  mp . Repository ,  mp . Tag ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-27 22:19:59 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								// 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 )  {  
						 
					
						
							
								
									
										
										
										
											2024-07-04 08:07:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  filepath . Join ( envconfig . Models ( ) ,  "manifests" ,  mp . Registry ,  mp . Namespace ,  mp . Repository ,  mp . Tag ) ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-08-22 09:38:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( mp  ModelPath )  BaseURL ( )  * url . URL  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  & url . URL { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Scheme :  mp . ProtocolScheme , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Host :    mp . Registry , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-19 00:09:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  GetManifestPath ( )  ( string ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-07-04 08:07:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									path  :=  filepath . Join ( envconfig . Models ( ) ,  "manifests" ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-07 05:30:08 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  err  :=  os . MkdirAll ( path ,  0 o755 ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-06 08:10:40 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  path ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-19 00:09:45 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  GetBlobsPath ( digest  string )  ( string ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2024-05-06 02:46:12 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									// only accept actual sha256 digests
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									pattern  :=  "^sha256[:-][0-9a-fA-F]{64}$" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									re  :=  regexp . MustCompile ( pattern ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  digest  !=  ""  &&  ! re . MatchString ( digest )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  ErrInvalidDigestFormat 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2024-03-15 11:18:06 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									digest  =  strings . ReplaceAll ( digest ,  ":" ,  "-" ) 
							 
						 
					
						
							
								
									
										
										
										
											2024-07-04 08:07:42 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									path  :=  filepath . Join ( envconfig . Models ( ) ,  "blobs" ,  digest ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-09-12 05:54:52 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									dirPath  :=  filepath . Dir ( path ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  digest  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										dirPath  =  path 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  os . MkdirAll ( dirPath ,  0 o755 ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  "" ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-07-19 02:24:19 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  path ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2023-07-18 13:44:21 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}