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
a6494f82
"vscode:/vscode.git/clone" did not exist on "fc0309615e42c32989e060e733d871e16617874e"
Commit
a6494f82
authored
Jul 06, 2023
by
Bruce MacDonald
Committed by
Jeffrey Morgan
Jul 06, 2023
Browse files
pull models
parent
0833f5af
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
202 additions
and
9 deletions
+202
-9
api/client.go
api/client.go
+12
-1
api/types.go
api/types.go
+8
-0
cmd/cmd.go
cmd/cmd.go
+17
-1
server/models.go
server/models.go
+140
-0
server/routes.go
server/routes.go
+25
-7
No files found.
api/client.go
View file @
a6494f82
...
...
@@ -35,7 +35,7 @@ func checkError(resp *http.Response, body []byte) error {
return
apiError
}
func
(
c
*
Client
)
stream
(
ctx
context
.
Context
,
method
string
,
path
string
,
reqData
any
,
callback
func
(
data
[]
byte
))
error
{
func
(
c
*
Client
)
stream
(
ctx
context
.
Context
,
method
string
,
path
string
,
reqData
any
,
callback
func
(
data
[]
byte
))
error
{
var
reqBody
io
.
Reader
var
data
[]
byte
var
err
error
...
...
@@ -140,3 +140,14 @@ func (c *Client) Generate(ctx context.Context, req *GenerateRequest, callback fu
return
&
res
,
nil
}
func
(
c
*
Client
)
Pull
(
ctx
context
.
Context
,
req
*
PullRequest
,
callback
func
(
token
string
))
(
*
PullResponse
,
error
)
{
var
res
PullResponse
if
err
:=
c
.
stream
(
ctx
,
http
.
MethodPost
,
"/api/pull"
,
req
,
func
(
token
[]
byte
)
{
callback
(
string
(
token
))
});
err
!=
nil
{
return
nil
,
err
}
return
&
res
,
nil
}
api/types.go
View file @
a6494f82
...
...
@@ -18,6 +18,14 @@ func (e Error) Error() string {
return
e
.
Message
}
type
PullRequest
struct
{
Model
string
`json:"model"`
}
type
PullResponse
struct
{
Response
string
`json:"response"`
}
type
GenerateRequest
struct
{
Model
string
`json:"model"`
Prompt
string
`json:"prompt"`
...
...
cmd/cmd.go
View file @
a6494f82
...
...
@@ -2,6 +2,7 @@ package cmd
import
(
"context"
"fmt"
"log"
"net"
"net/http"
...
...
@@ -23,6 +24,21 @@ func cacheDir() string {
return
path
.
Join
(
home
,
".ollama"
)
}
func
run
(
model
string
)
error
{
client
,
err
:=
NewAPIClient
()
if
err
!=
nil
{
return
err
}
pr
:=
api
.
PullRequest
{
Model
:
model
,
}
callback
:=
func
(
progress
string
)
{
fmt
.
Println
(
progress
)
}
_
,
err
=
client
.
Pull
(
context
.
Background
(),
&
pr
,
callback
)
return
err
}
func
serve
()
error
{
sp
:=
path
.
Join
(
cacheDir
(),
"ollama.sock"
)
...
...
@@ -94,7 +110,7 @@ func NewCLI() *cobra.Command {
Short
:
"Run a model"
,
Args
:
cobra
.
ExactArgs
(
1
),
RunE
:
func
(
cmd
*
cobra
.
Command
,
args
[]
string
)
error
{
return
nil
return
run
(
args
[
0
])
},
}
...
...
server/models.go
0 → 100644
View file @
a6494f82
package
server
import
(
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path"
"strconv"
)
// const directoryURL = "https://ollama.ai/api/models"
const
directoryURL
=
"https://raw.githubusercontent.com/jmorganca/ollama/go/models.json"
type
directoryCtxKey
string
var
dirCtx
directoryCtxKey
=
"directory"
type
Model
struct
{
Name
string
`json:"name"`
DisplayName
string
`json:"display_name"`
Parameters
string
`json:"parameters"`
URL
string
`json:"url"`
ShortDescription
string
`json:"short_description"`
Description
string
`json:"description"`
PublishedBy
string
`json:"published_by"`
OriginalAuthor
string
`json:"original_author"`
OriginalURL
string
`json:"original_url"`
License
string
`json:"license"`
}
func
pull
(
model
string
,
progressCh
chan
<-
string
)
error
{
remote
,
err
:=
getRemote
(
model
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to pull model: %w"
,
err
)
}
return
saveModel
(
remote
,
progressCh
)
}
func
getRemote
(
model
string
)
(
*
Model
,
error
)
{
// resolve the model download from our directory
resp
,
err
:=
http
.
Get
(
directoryURL
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to get directory: %w"
,
err
)
}
defer
resp
.
Body
.
Close
()
body
,
err
:=
ioutil
.
ReadAll
(
resp
.
Body
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to read directory: %w"
,
err
)
}
var
models
[]
Model
err
=
json
.
Unmarshal
(
body
,
&
models
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"failed to parse directory: %w"
,
err
)
}
for
_
,
m
:=
range
models
{
if
m
.
Name
==
model
{
return
&
m
,
nil
}
}
return
nil
,
fmt
.
Errorf
(
"model not found in directory: %s"
,
model
)
}
func
saveModel
(
model
*
Model
,
progressCh
chan
<-
string
)
error
{
// this models cache directory is created by the server on startup
home
,
err
:=
os
.
UserHomeDir
()
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to get home directory: %w"
,
err
)
}
modelsCache
:=
path
.
Join
(
home
,
".ollama"
,
"models"
)
fileName
:=
path
.
Join
(
modelsCache
,
model
.
Name
+
".bin"
)
client
:=
&
http
.
Client
{}
req
,
err
:=
http
.
NewRequest
(
"GET"
,
model
.
URL
,
nil
)
if
err
!=
nil
{
panic
(
err
)
}
// check for resume
fileInfo
,
err
:=
os
.
Stat
(
fileName
)
if
err
!=
nil
{
if
!
os
.
IsNotExist
(
err
)
{
return
fmt
.
Errorf
(
"failed to check resume model file: %w"
,
err
)
}
// file doesn't exist, create it now
}
else
{
req
.
Header
.
Add
(
"Range"
,
"bytes="
+
strconv
.
FormatInt
(
fileInfo
.
Size
(),
10
)
+
"-"
)
}
resp
,
err
:=
client
.
Do
(
req
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"failed to download model: %w"
,
err
)
}
defer
resp
.
Body
.
Close
()
if
resp
.
StatusCode
!=
http
.
StatusOK
{
return
fmt
.
Errorf
(
"failed to download model: %s"
,
resp
.
Status
)
}
out
,
err
:=
os
.
OpenFile
(
fileName
,
os
.
O_CREATE
|
os
.
O_APPEND
|
os
.
O_WRONLY
,
0
o644
)
if
err
!=
nil
{
panic
(
err
)
}
defer
out
.
Close
()
totalSize
,
_
:=
strconv
.
Atoi
(
resp
.
Header
.
Get
(
"Content-Length"
))
buf
:=
make
([]
byte
,
1024
)
totalBytes
:=
0
for
{
n
,
err
:=
resp
.
Body
.
Read
(
buf
)
if
err
!=
nil
&&
err
!=
io
.
EOF
{
return
err
}
if
n
==
0
{
break
}
if
_
,
err
:=
out
.
Write
(
buf
[
:
n
]);
err
!=
nil
{
return
err
}
totalBytes
+=
n
// send progress updates
progressCh
<-
fmt
.
Sprintf
(
"Downloaded %d out of %d bytes (%.2f%%)"
,
totalBytes
,
totalSize
,
float64
(
totalBytes
)
/
float64
(
totalSize
)
*
100
)
}
// send completion message
progressCh
<-
"Download complete!"
return
nil
}
server/routes.go
View file @
a6494f82
...
...
@@ -14,12 +14,6 @@ import (
"github.com/jmorganca/ollama/api"
)
func
pull
(
c
*
gin
.
Context
)
{
// TODO
c
.
JSON
(
http
.
StatusOK
,
gin
.
H
{
"message"
:
"ok"
})
}
func
generate
(
c
*
gin
.
Context
)
{
// TODO: these should be request parameters
gpulayers
:=
1
...
...
@@ -65,7 +59,31 @@ func generate(c *gin.Context) {
func
Serve
(
ln
net
.
Listener
)
error
{
r
:=
gin
.
Default
()
r
.
POST
(
"api/pull"
,
pull
)
r
.
POST
(
"api/pull"
,
func
(
c
*
gin
.
Context
)
{
var
req
api
.
PullRequest
if
err
:=
c
.
ShouldBindJSON
(
&
req
);
err
!=
nil
{
c
.
JSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"message"
:
err
.
Error
()})
return
}
progressCh
:=
make
(
chan
string
)
go
func
()
{
defer
close
(
progressCh
)
if
err
:=
pull
(
req
.
Model
,
progressCh
);
err
!=
nil
{
c
.
JSON
(
http
.
StatusBadRequest
,
gin
.
H
{
"message"
:
err
.
Error
()})
return
}
}()
c
.
Stream
(
func
(
w
io
.
Writer
)
bool
{
progress
,
ok
:=
<-
progressCh
if
!
ok
{
return
false
}
c
.
SSEvent
(
"progress"
,
progress
)
return
true
})
})
r
.
POST
(
"/api/generate"
,
generate
)
...
...
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