Merge pull request #774 from jmorganca/mxyng/server-version
add version api and show server version in cli
This commit is contained in:
commit
c3ff36088b
3 changed files with 71 additions and 30 deletions
|
@ -324,3 +324,15 @@ func (c *Client) CreateBlob(ctx context.Context, digest string, r io.Reader) err
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) Version(ctx context.Context) (string, error) {
|
||||||
|
var version struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.do(ctx, http.MethodGet, "/api/version", nil, &version); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return version.Version, nil
|
||||||
|
}
|
||||||
|
|
86
cmd/cmd.go
86
cmd/cmd.go
|
@ -133,7 +133,7 @@ func CreateHandler(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
request := api.CreateRequest{Name: args[0], Modelfile: string(modelfile)}
|
request := api.CreateRequest{Name: args[0], Modelfile: string(modelfile)}
|
||||||
if err := client.Create(context.Background(), &request, fn); err != nil {
|
if err := client.Create(cmd.Context(), &request, fn); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,7 +148,7 @@ func RunHandler(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
name := args[0]
|
name := args[0]
|
||||||
// check if the model exists on the server
|
// check if the model exists on the server
|
||||||
_, err = client.Show(context.Background(), &api.ShowRequest{Name: name})
|
_, err = client.Show(cmd.Context(), &api.ShowRequest{Name: name})
|
||||||
var statusError api.StatusError
|
var statusError api.StatusError
|
||||||
switch {
|
switch {
|
||||||
case errors.As(err, &statusError) && statusError.StatusCode == http.StatusNotFound:
|
case errors.As(err, &statusError) && statusError.StatusCode == http.StatusNotFound:
|
||||||
|
@ -208,7 +208,7 @@ func PushHandler(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
request := api.PushRequest{Name: args[0], Insecure: insecure}
|
request := api.PushRequest{Name: args[0], Insecure: insecure}
|
||||||
if err := client.Push(context.Background(), &request, fn); err != nil {
|
if err := client.Push(cmd.Context(), &request, fn); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ func ListHandler(cmd *cobra.Command, args []string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
models, err := client.List(context.Background())
|
models, err := client.List(cmd.Context())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,7 @@ func DeleteHandler(cmd *cobra.Command, args []string) error {
|
||||||
|
|
||||||
for _, name := range args {
|
for _, name := range args {
|
||||||
req := api.DeleteRequest{Name: name}
|
req := api.DeleteRequest{Name: name}
|
||||||
if err := client.Delete(context.Background(), &req); err != nil {
|
if err := client.Delete(cmd.Context(), &req); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("deleted '%s'\n", name)
|
fmt.Printf("deleted '%s'\n", name)
|
||||||
|
@ -322,7 +322,7 @@ func ShowHandler(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
req := api.ShowRequest{Name: args[0]}
|
req := api.ShowRequest{Name: args[0]}
|
||||||
resp, err := client.Show(context.Background(), &req)
|
resp, err := client.Show(cmd.Context(), &req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -350,7 +350,7 @@ func CopyHandler(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
req := api.CopyRequest{Source: args[0], Destination: args[1]}
|
req := api.CopyRequest{Source: args[0], Destination: args[1]}
|
||||||
if err := client.Copy(context.Background(), &req); err != nil {
|
if err := client.Copy(cmd.Context(), &req); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("copied '%s' to '%s'\n", args[0], args[1])
|
fmt.Printf("copied '%s' to '%s'\n", args[0], args[1])
|
||||||
|
@ -404,7 +404,7 @@ func PullHandler(cmd *cobra.Command, args []string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
request := api.PullRequest{Name: args[0], Insecure: insecure}
|
request := api.PullRequest{Name: args[0], Insecure: insecure}
|
||||||
if err := client.Pull(context.Background(), &request, fn); err != nil {
|
if err := client.Pull(cmd.Context(), &request, fn); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +493,7 @@ func generate(cmd *cobra.Command, opts generateOptions) error {
|
||||||
opts.WordWrap = false
|
opts.WordWrap = false
|
||||||
}
|
}
|
||||||
|
|
||||||
cancelCtx, cancel := context.WithCancel(context.Background())
|
ctx, cancel := context.WithCancel(cmd.Context())
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
sigChan := make(chan os.Signal, 1)
|
sigChan := make(chan os.Signal, 1)
|
||||||
|
@ -507,15 +507,6 @@ func generate(cmd *cobra.Command, opts generateOptions) error {
|
||||||
var currentLineLength int
|
var currentLineLength int
|
||||||
var wordBuffer string
|
var wordBuffer string
|
||||||
|
|
||||||
request := api.GenerateRequest{
|
|
||||||
Model: opts.Model,
|
|
||||||
Prompt: opts.Prompt,
|
|
||||||
Context: generateContext,
|
|
||||||
Format: opts.Format,
|
|
||||||
System: opts.System,
|
|
||||||
Template: opts.Template,
|
|
||||||
Options: opts.Options,
|
|
||||||
}
|
|
||||||
fn := func(response api.GenerateResponse) error {
|
fn := func(response api.GenerateResponse) error {
|
||||||
p.StopAndClear()
|
p.StopAndClear()
|
||||||
|
|
||||||
|
@ -560,7 +551,17 @@ func generate(cmd *cobra.Command, opts generateOptions) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := client.Generate(cancelCtx, &request, fn); err != nil {
|
request := api.GenerateRequest{
|
||||||
|
Model: opts.Model,
|
||||||
|
Prompt: opts.Prompt,
|
||||||
|
Context: generateContext,
|
||||||
|
Format: opts.Format,
|
||||||
|
System: opts.System,
|
||||||
|
Template: opts.Template,
|
||||||
|
Options: opts.Options,
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := client.Generate(ctx, &request, fn); err != nil {
|
||||||
if errors.Is(err, context.Canceled) {
|
if errors.Is(err, context.Canceled) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -584,10 +585,7 @@ func generate(cmd *cobra.Command, opts generateOptions) error {
|
||||||
latest.Summary()
|
latest.Summary()
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := cmd.Context()
|
cmd.SetContext(context.WithValue(cmd.Context(), generateContextKey("context"), latest.Context))
|
||||||
ctx = context.WithValue(ctx, generateContextKey("context"), latest.Context)
|
|
||||||
cmd.SetContext(ctx)
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -988,7 +986,7 @@ func initializeKeypair() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func startMacApp(client *api.Client) error {
|
func startMacApp(ctx context.Context, client *api.Client) error {
|
||||||
exe, err := os.Executable()
|
exe, err := os.Executable()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -1012,24 +1010,24 @@ func startMacApp(client *api.Client) error {
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
return errors.New("timed out waiting for server to start")
|
return errors.New("timed out waiting for server to start")
|
||||||
case <-tick:
|
case <-tick:
|
||||||
if err := client.Heartbeat(context.Background()); err == nil {
|
if err := client.Heartbeat(ctx); err == nil {
|
||||||
return nil // server has started
|
return nil // server has started
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkServerHeartbeat(_ *cobra.Command, _ []string) error {
|
func checkServerHeartbeat(cmd *cobra.Command, _ []string) error {
|
||||||
client, err := api.ClientFromEnvironment()
|
client, err := api.ClientFromEnvironment()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := client.Heartbeat(context.Background()); err != nil {
|
if err := client.Heartbeat(cmd.Context()); err != nil {
|
||||||
if !strings.Contains(err.Error(), "connection refused") {
|
if !strings.Contains(err.Error(), "connection refused") {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if runtime.GOOS == "darwin" {
|
if runtime.GOOS == "darwin" {
|
||||||
if err := startMacApp(client); err != nil {
|
if err := startMacApp(cmd.Context(), client); err != nil {
|
||||||
return fmt.Errorf("could not connect to ollama app, is it running?")
|
return fmt.Errorf("could not connect to ollama app, is it running?")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1039,8 +1037,29 @@ func checkServerHeartbeat(_ *cobra.Command, _ []string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func versionHandler(cmd *cobra.Command, _ []string) {
|
||||||
|
client, err := api.ClientFromEnvironment()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serverVersion, err := client.Version(cmd.Context())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Warning: could not connect to a running Ollama instance")
|
||||||
|
}
|
||||||
|
|
||||||
|
if serverVersion != "" {
|
||||||
|
fmt.Printf("ollama version is %s\n", serverVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
if serverVersion != version.Version {
|
||||||
|
fmt.Printf("Warning: client version is %s\n", version.Version)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewCLI() *cobra.Command {
|
func NewCLI() *cobra.Command {
|
||||||
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
log.SetFlags(log.LstdFlags | log.Lshortfile)
|
||||||
|
cobra.EnableCommandSorting = false
|
||||||
|
|
||||||
rootCmd := &cobra.Command{
|
rootCmd := &cobra.Command{
|
||||||
Use: "ollama",
|
Use: "ollama",
|
||||||
|
@ -1050,10 +1069,17 @@ func NewCLI() *cobra.Command {
|
||||||
CompletionOptions: cobra.CompletionOptions{
|
CompletionOptions: cobra.CompletionOptions{
|
||||||
DisableDefaultCmd: true,
|
DisableDefaultCmd: true,
|
||||||
},
|
},
|
||||||
Version: version.Version,
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
if version, _ := cmd.Flags().GetBool("version"); version {
|
||||||
|
versionHandler(cmd, args)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Print(cmd.UsageString())
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cobra.EnableCommandSorting = false
|
rootCmd.Flags().BoolP("version", "v", false, "Show version information")
|
||||||
|
|
||||||
createCmd := &cobra.Command{
|
createCmd := &cobra.Command{
|
||||||
Use: "create MODEL",
|
Use: "create MODEL",
|
||||||
|
|
|
@ -827,6 +827,9 @@ func Serve(ln net.Listener, allowOrigins []string) error {
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Handle(method, "/api/tags", ListModelsHandler)
|
r.Handle(method, "/api/tags", ListModelsHandler)
|
||||||
|
r.Handle(method, "/api/version", func(c *gin.Context) {
|
||||||
|
c.JSON(http.StatusOK, gin.H{"version": version.Version})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Listening on %s (version %s)", ln.Addr(), version.Version)
|
log.Printf("Listening on %s (version %s)", ln.Addr(), version.Version)
|
||||||
|
|
Loading…
Reference in a new issue