Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
ollama
Commits
2539f2db
"docs/vscode:/vscode.git/clone" did not exist on "4d9b43debdbdbbfee9799045d43201652016a1e4"
Unverified
Commit
2539f2db
authored
Jan 14, 2025
by
Patrick Devine
Committed by
GitHub
Jan 14, 2025
Browse files
Fix absolute path names + gguf detection (#8428)
parent
61676fb5
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
217 additions
and
28 deletions
+217
-28
parser/expandpath_test.go
parser/expandpath_test.go
+89
-25
parser/parser.go
parser/parser.go
+3
-1
server/create.go
server/create.go
+27
-2
server/routes_create_test.go
server/routes_create_test.go
+98
-0
No files found.
parser/expandpath_test.go
View file @
2539f2db
...
@@ -4,6 +4,7 @@ import (
...
@@ -4,6 +4,7 @@ import (
"os"
"os"
"os/user"
"os/user"
"path/filepath"
"path/filepath"
"runtime"
"testing"
"testing"
)
)
...
@@ -11,14 +12,29 @@ func TestExpandPath(t *testing.T) {
...
@@ -11,14 +12,29 @@ func TestExpandPath(t *testing.T) {
mockCurrentUser
:=
func
()
(
*
user
.
User
,
error
)
{
mockCurrentUser
:=
func
()
(
*
user
.
User
,
error
)
{
return
&
user
.
User
{
return
&
user
.
User
{
Username
:
"testuser"
,
Username
:
"testuser"
,
HomeDir
:
"/home/testuser"
,
HomeDir
:
func
()
string
{
if
os
.
PathSeparator
==
'\\'
{
return
filepath
.
FromSlash
(
"D:/home/testuser"
)
}
return
"/home/testuser"
}(),
},
nil
},
nil
}
}
mockLookupUser
:=
func
(
username
string
)
(
*
user
.
User
,
error
)
{
mockLookupUser
:=
func
(
username
string
)
(
*
user
.
User
,
error
)
{
fakeUsers
:=
map
[
string
]
string
{
fakeUsers
:=
map
[
string
]
string
{
"testuser"
:
"/home/testuser"
,
"testuser"
:
func
()
string
{
"anotheruser"
:
"/home/anotheruser"
,
if
os
.
PathSeparator
==
'\\'
{
return
filepath
.
FromSlash
(
"D:/home/testuser"
)
}
return
"/home/testuser"
}(),
"anotheruser"
:
func
()
string
{
if
os
.
PathSeparator
==
'\\'
{
return
filepath
.
FromSlash
(
"D:/home/anotheruser"
)
}
return
"/home/anotheruser"
}(),
}
}
if
homeDir
,
ok
:=
fakeUsers
[
username
];
ok
{
if
homeDir
,
ok
:=
fakeUsers
[
username
];
ok
{
...
@@ -30,21 +46,67 @@ func TestExpandPath(t *testing.T) {
...
@@ -30,21 +46,67 @@ func TestExpandPath(t *testing.T) {
return
nil
,
os
.
ErrNotExist
return
nil
,
os
.
ErrNotExist
}
}
pwd
,
err
:=
os
.
Getwd
()
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
t
.
Run
(
"unix tests"
,
func
(
t
*
testing
.
T
)
{
if
runtime
.
GOOS
==
"windows"
{
return
}
tests
:=
[]
struct
{
path
string
relativeDir
string
expected
string
shouldErr
bool
}{
{
"~"
,
""
,
"/home/testuser"
,
false
},
{
"~/myfolder/myfile.txt"
,
""
,
"/home/testuser/myfolder/myfile.txt"
,
false
},
{
"~anotheruser/docs/file.txt"
,
""
,
"/home/anotheruser/docs/file.txt"
,
false
},
{
"~nonexistentuser/file.txt"
,
""
,
""
,
true
},
{
"relative/path/to/file"
,
""
,
filepath
.
Join
(
pwd
,
"relative/path/to/file"
),
false
},
{
"/absolute/path/to/file"
,
""
,
"/absolute/path/to/file"
,
false
},
{
"/absolute/path/to/file"
,
"someotherdir/"
,
"/absolute/path/to/file"
,
false
},
{
"."
,
pwd
,
pwd
,
false
},
{
"."
,
""
,
pwd
,
false
},
{
"somefile"
,
"somedir"
,
filepath
.
Join
(
pwd
,
"somedir"
,
"somefile"
),
false
},
}
for
_
,
test
:=
range
tests
{
result
,
err
:=
expandPathImpl
(
test
.
path
,
test
.
relativeDir
,
mockCurrentUser
,
mockLookupUser
)
if
(
err
!=
nil
)
!=
test
.
shouldErr
{
t
.
Errorf
(
"expandPathImpl(%q) returned error: %v, expected error: %v"
,
test
.
path
,
err
!=
nil
,
test
.
shouldErr
)
}
if
result
!=
test
.
expected
&&
!
test
.
shouldErr
{
t
.
Errorf
(
"expandPathImpl(%q) = %q, want %q"
,
test
.
path
,
result
,
test
.
expected
)
}
}
})
t
.
Run
(
"windows tests"
,
func
(
t
*
testing
.
T
)
{
if
runtime
.
GOOS
!=
"windows"
{
return
}
tests
:=
[]
struct
{
tests
:=
[]
struct
{
path
string
path
string
relativeDir
string
relativeDir
string
expected
string
expected
string
windowsExpected
string
shouldErr
bool
shouldErr
bool
}{
}{
{
"~"
,
""
,
"/home/testuser"
,
"D:
\\
home
\\
testuser"
,
false
},
{
"~"
,
""
,
"D:
\\
home
\\
testuser"
,
false
},
{
"~/myfolder/myfile.txt"
,
""
,
"/home/testuser/myfolder/myfile.txt"
,
"D:
\\
home
\\
testuser
\\
myfolder
\\
myfile.txt"
,
false
},
{
"~/myfolder/myfile.txt"
,
""
,
"D:
\\
home
\\
testuser
\\
myfolder
\\
myfile.txt"
,
false
},
{
"~anotheruser/docs/file.txt"
,
""
,
"/home/anotheruser/docs/file.txt"
,
"D:
\\
home
\\
anotheruser
\\
docs
\\
file.txt"
,
false
},
{
"~anotheruser/docs/file.txt"
,
""
,
"D:
\\
home
\\
anotheruser
\\
docs
\\
file.txt"
,
false
},
{
"~nonexistentuser/file.txt"
,
""
,
""
,
""
,
true
},
{
"~nonexistentuser/file.txt"
,
""
,
""
,
true
},
{
"relative/path/to/file"
,
""
,
filepath
.
Join
(
os
.
Getenv
(
"PWD"
),
"relative/path/to/file"
),
"relative
\\
path
\\
to
\\
file"
,
false
},
{
"relative
\\
path
\\
to
\\
file"
,
""
,
filepath
.
Join
(
pwd
,
"relative
\\
path
\\
to
\\
file"
),
false
},
{
"/absolute/path/to/file"
,
""
,
"/absolute/path/to/file"
,
"D:
\\
absolute
\\
path
\\
to
\\
file"
,
false
},
{
"D:
\\
absolute
\\
path
\\
to
\\
file"
,
""
,
"D:
\\
absolute
\\
path
\\
to
\\
file"
,
false
},
{
"."
,
os
.
Getenv
(
"PWD"
),
""
,
os
.
Getenv
(
"PWD"
),
false
},
{
"D:
\\
absolute
\\
path
\\
to
\\
file"
,
"someotherdir/"
,
"D:
\\
absolute
\\
path
\\
to
\\
file"
,
false
},
{
"somefile"
,
"somedir"
,
filepath
.
Join
(
os
.
Getenv
(
"PWD"
),
"somedir"
,
"somefile"
),
"somedir
\\
somefile"
,
false
},
{
"."
,
pwd
,
pwd
,
false
},
{
"."
,
""
,
pwd
,
false
},
{
"somefile"
,
"somedir"
,
filepath
.
Join
(
pwd
,
"somedir"
,
"somefile"
),
false
},
}
}
for
_
,
test
:=
range
tests
{
for
_
,
test
:=
range
tests
{
...
@@ -52,8 +114,10 @@ func TestExpandPath(t *testing.T) {
...
@@ -52,8 +114,10 @@ func TestExpandPath(t *testing.T) {
if
(
err
!=
nil
)
!=
test
.
shouldErr
{
if
(
err
!=
nil
)
!=
test
.
shouldErr
{
t
.
Errorf
(
"expandPathImpl(%q) returned error: %v, expected error: %v"
,
test
.
path
,
err
!=
nil
,
test
.
shouldErr
)
t
.
Errorf
(
"expandPathImpl(%q) returned error: %v, expected error: %v"
,
test
.
path
,
err
!=
nil
,
test
.
shouldErr
)
}
}
if
result
!=
test
.
expected
&&
result
!=
test
.
windowsExpected
&&
!
test
.
shouldErr
{
if
result
!=
test
.
expected
&&
!
test
.
shouldErr
{
t
.
Errorf
(
"expandPathImpl(%q) = %q, want %q"
,
test
.
path
,
result
,
test
.
expected
)
t
.
Errorf
(
"expandPathImpl(%q) = %q, want %q"
,
test
.
path
,
result
,
test
.
expected
)
}
}
}
}
})
}
}
parser/parser.go
View file @
2539f2db
...
@@ -564,7 +564,9 @@ func isValidCommand(cmd string) bool {
...
@@ -564,7 +564,9 @@ func isValidCommand(cmd string) bool {
}
}
func
expandPathImpl
(
path
,
relativeDir
string
,
currentUserFunc
func
()
(
*
user
.
User
,
error
),
lookupUserFunc
func
(
string
)
(
*
user
.
User
,
error
))
(
string
,
error
)
{
func
expandPathImpl
(
path
,
relativeDir
string
,
currentUserFunc
func
()
(
*
user
.
User
,
error
),
lookupUserFunc
func
(
string
)
(
*
user
.
User
,
error
))
(
string
,
error
)
{
if
strings
.
HasPrefix
(
path
,
"~"
)
{
if
filepath
.
IsAbs
(
path
)
||
strings
.
HasPrefix
(
path
,
"
\\
"
)
||
strings
.
HasPrefix
(
path
,
"/"
)
{
return
filepath
.
Abs
(
path
)
}
else
if
strings
.
HasPrefix
(
path
,
"~"
)
{
var
homeDir
string
var
homeDir
string
if
path
==
"~"
||
strings
.
HasPrefix
(
path
,
"~/"
)
{
if
path
==
"~"
||
strings
.
HasPrefix
(
path
,
"~/"
)
{
...
...
server/create.go
View file @
2539f2db
...
@@ -178,12 +178,37 @@ func convertModelFromFiles(files map[string]string, baseLayers []*layerGGML, isA
...
@@ -178,12 +178,37 @@ func convertModelFromFiles(files map[string]string, baseLayers []*layerGGML, isA
}
}
func
detectModelTypeFromFiles
(
files
map
[
string
]
string
)
string
{
func
detectModelTypeFromFiles
(
files
map
[
string
]
string
)
string
{
// todo make this more robust by actually introspecting the files
for
fn
:=
range
files
{
for
fn
:=
range
files
{
if
strings
.
HasSuffix
(
fn
,
".safetensors"
)
{
if
strings
.
HasSuffix
(
fn
,
".safetensors"
)
{
return
"safetensors"
return
"safetensors"
}
else
if
strings
.
HasSuffix
(
fn
,
".bin"
)
||
strings
.
HasSuffix
(
fn
,
".gguf"
)
{
}
else
if
strings
.
HasSuffix
(
fn
,
".gguf"
)
{
return
"gguf"
return
"gguf"
}
else
{
// try to see if we can find a gguf file even without the file extension
blobPath
,
err
:=
GetBlobsPath
(
files
[
fn
])
if
err
!=
nil
{
slog
.
Error
(
"error getting blobs path"
,
"file"
,
fn
)
return
""
}
f
,
err
:=
os
.
Open
(
blobPath
)
if
err
!=
nil
{
slog
.
Error
(
"error reading file"
,
"error"
,
err
)
return
""
}
defer
f
.
Close
()
buf
:=
make
([]
byte
,
4
)
_
,
err
=
f
.
Read
(
buf
)
if
err
!=
nil
{
slog
.
Error
(
"error reading file"
,
"error"
,
err
)
return
""
}
ct
:=
llm
.
DetectGGMLType
(
buf
)
if
ct
==
"gguf"
{
return
"gguf"
}
}
}
}
}
...
...
server/routes_create_test.go
View file @
2539f2db
...
@@ -3,6 +3,7 @@ package server
...
@@ -3,6 +3,7 @@ package server
import
(
import
(
"bytes"
"bytes"
"cmp"
"cmp"
"crypto/sha256"
"encoding/json"
"encoding/json"
"fmt"
"fmt"
"io"
"io"
...
@@ -710,3 +711,100 @@ func TestCreateDetectTemplate(t *testing.T) {
...
@@ -710,3 +711,100 @@ func TestCreateDetectTemplate(t *testing.T) {
})
})
})
})
}
}
func
TestDetectModelTypeFromFiles
(
t
*
testing
.
T
)
{
t
.
Run
(
"gguf file"
,
func
(
t
*
testing
.
T
)
{
_
,
digest
:=
createBinFile
(
t
,
nil
,
nil
)
files
:=
map
[
string
]
string
{
"model.gguf"
:
digest
,
}
modelType
:=
detectModelTypeFromFiles
(
files
)
if
modelType
!=
"gguf"
{
t
.
Fatalf
(
"expected model type 'gguf', got %q"
,
modelType
)
}
})
t
.
Run
(
"gguf file w/o extension"
,
func
(
t
*
testing
.
T
)
{
_
,
digest
:=
createBinFile
(
t
,
nil
,
nil
)
files
:=
map
[
string
]
string
{
fmt
.
Sprintf
(
"%x"
,
digest
)
:
digest
,
}
modelType
:=
detectModelTypeFromFiles
(
files
)
if
modelType
!=
"gguf"
{
t
.
Fatalf
(
"expected model type 'gguf', got %q"
,
modelType
)
}
})
t
.
Run
(
"safetensors file"
,
func
(
t
*
testing
.
T
)
{
files
:=
map
[
string
]
string
{
"model.safetensors"
:
"sha256:abc123"
,
}
modelType
:=
detectModelTypeFromFiles
(
files
)
if
modelType
!=
"safetensors"
{
t
.
Fatalf
(
"expected model type 'safetensors', got %q"
,
modelType
)
}
})
t
.
Run
(
"unsupported file type"
,
func
(
t
*
testing
.
T
)
{
p
:=
t
.
TempDir
()
t
.
Setenv
(
"OLLAMA_MODELS"
,
p
)
data
:=
[]
byte
(
"12345678"
)
digest
:=
fmt
.
Sprintf
(
"sha256:%x"
,
sha256
.
Sum256
(
data
))
if
err
:=
os
.
MkdirAll
(
filepath
.
Join
(
p
,
"blobs"
),
0
o755
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
f
,
err
:=
os
.
Create
(
filepath
.
Join
(
p
,
"blobs"
,
fmt
.
Sprintf
(
"sha256-%s"
,
strings
.
TrimPrefix
(
digest
,
"sha256:"
))))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
f
.
Close
()
if
_
,
err
:=
f
.
Write
(
data
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
files
:=
map
[
string
]
string
{
"model.bin"
:
digest
,
}
modelType
:=
detectModelTypeFromFiles
(
files
)
if
modelType
!=
""
{
t
.
Fatalf
(
"expected empty model type for unsupported file, got %q"
,
modelType
)
}
})
t
.
Run
(
"file with less than 4 bytes"
,
func
(
t
*
testing
.
T
)
{
p
:=
t
.
TempDir
()
t
.
Setenv
(
"OLLAMA_MODELS"
,
p
)
data
:=
[]
byte
(
"123"
)
digest
:=
fmt
.
Sprintf
(
"sha256:%x"
,
sha256
.
Sum256
(
data
))
if
err
:=
os
.
MkdirAll
(
filepath
.
Join
(
p
,
"blobs"
),
0
o755
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
f
,
err
:=
os
.
Create
(
filepath
.
Join
(
p
,
"blobs"
,
fmt
.
Sprintf
(
"sha256-%s"
,
strings
.
TrimPrefix
(
digest
,
"sha256:"
))))
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
defer
f
.
Close
()
if
_
,
err
:=
f
.
Write
(
data
);
err
!=
nil
{
t
.
Fatal
(
err
)
}
files
:=
map
[
string
]
string
{
"noext"
:
digest
,
}
modelType
:=
detectModelTypeFromFiles
(
files
)
if
modelType
!=
""
{
t
.
Fatalf
(
"expected empty model type for small file, got %q"
,
modelType
)
}
})
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment