cmd.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. package cmd
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/ed25519"
  6. "crypto/rand"
  7. "crypto/sha256"
  8. "encoding/pem"
  9. "errors"
  10. "fmt"
  11. "io"
  12. "log"
  13. "net"
  14. "net/http"
  15. "os"
  16. "os/exec"
  17. "os/signal"
  18. "path/filepath"
  19. "runtime"
  20. "strings"
  21. "syscall"
  22. "time"
  23. "github.com/olekukonko/tablewriter"
  24. "github.com/spf13/cobra"
  25. "golang.org/x/crypto/ssh"
  26. "golang.org/x/term"
  27. "github.com/jmorganca/ollama/api"
  28. "github.com/jmorganca/ollama/format"
  29. "github.com/jmorganca/ollama/parser"
  30. "github.com/jmorganca/ollama/progress"
  31. "github.com/jmorganca/ollama/server"
  32. "github.com/jmorganca/ollama/version"
  33. )
  34. type ImageData []byte
  35. func CreateHandler(cmd *cobra.Command, args []string) error {
  36. filename, _ := cmd.Flags().GetString("file")
  37. filename, err := filepath.Abs(filename)
  38. if err != nil {
  39. return err
  40. }
  41. client, err := api.ClientFromEnvironment()
  42. if err != nil {
  43. return err
  44. }
  45. p := progress.NewProgress(os.Stderr)
  46. defer p.Stop()
  47. bars := make(map[string]*progress.Bar)
  48. modelfile, err := os.ReadFile(filename)
  49. if err != nil {
  50. return err
  51. }
  52. commands, err := parser.Parse(bytes.NewReader(modelfile))
  53. if err != nil {
  54. return err
  55. }
  56. home, err := os.UserHomeDir()
  57. if err != nil {
  58. return err
  59. }
  60. status := "transferring model data"
  61. spinner := progress.NewSpinner(status)
  62. p.Add(status, spinner)
  63. for _, c := range commands {
  64. switch c.Name {
  65. case "model", "adapter":
  66. path := c.Args
  67. if path == "~" {
  68. path = home
  69. } else if strings.HasPrefix(path, "~/") {
  70. path = filepath.Join(home, path[2:])
  71. }
  72. if !filepath.IsAbs(path) {
  73. path = filepath.Join(filepath.Dir(filename), path)
  74. }
  75. bin, err := os.Open(path)
  76. if errors.Is(err, os.ErrNotExist) && c.Name == "model" {
  77. continue
  78. } else if err != nil {
  79. return err
  80. }
  81. defer bin.Close()
  82. hash := sha256.New()
  83. if _, err := io.Copy(hash, bin); err != nil {
  84. return err
  85. }
  86. bin.Seek(0, io.SeekStart)
  87. digest := fmt.Sprintf("sha256:%x", hash.Sum(nil))
  88. if err = client.CreateBlob(cmd.Context(), digest, bin); err != nil {
  89. return err
  90. }
  91. modelfile = bytes.ReplaceAll(modelfile, []byte(c.Args), []byte("@"+digest))
  92. }
  93. }
  94. fn := func(resp api.ProgressResponse) error {
  95. if resp.Digest != "" {
  96. spinner.Stop()
  97. bar, ok := bars[resp.Digest]
  98. if !ok {
  99. bar = progress.NewBar(fmt.Sprintf("pulling %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  100. bars[resp.Digest] = bar
  101. p.Add(resp.Digest, bar)
  102. }
  103. bar.Set(resp.Completed)
  104. } else if status != resp.Status {
  105. spinner.Stop()
  106. status = resp.Status
  107. spinner = progress.NewSpinner(status)
  108. p.Add(status, spinner)
  109. }
  110. return nil
  111. }
  112. request := api.CreateRequest{Name: args[0], Modelfile: string(modelfile)}
  113. if err := client.Create(cmd.Context(), &request, fn); err != nil {
  114. return err
  115. }
  116. return nil
  117. }
  118. func RunHandler(cmd *cobra.Command, args []string) error {
  119. client, err := api.ClientFromEnvironment()
  120. if err != nil {
  121. return err
  122. }
  123. name := args[0]
  124. // check if the model exists on the server
  125. model, err := client.Show(cmd.Context(), &api.ShowRequest{Name: name})
  126. var statusError api.StatusError
  127. switch {
  128. case errors.As(err, &statusError) && statusError.StatusCode == http.StatusNotFound:
  129. if err := PullHandler(cmd, []string{name}); err != nil {
  130. return err
  131. }
  132. case err != nil:
  133. return err
  134. default:
  135. // the model was found, check if it is in the correct format
  136. if model.Details.Format != "" && model.Details.Format != "gguf" {
  137. // pull and retry to see if the model has been updated
  138. parts := strings.Split(name, string(os.PathSeparator))
  139. if len(parts) == 1 {
  140. // this is a library model, log some info
  141. fmt.Fprintln(os.Stderr, "This model is no longer compatible with Ollama. Pulling a new version...")
  142. }
  143. if err := PullHandler(cmd, []string{name}); err != nil {
  144. fmt.Printf("Error: %s\n", err)
  145. return fmt.Errorf("unsupported model, please update this model to gguf format") // relay the original error
  146. }
  147. }
  148. }
  149. return RunGenerate(cmd, args)
  150. }
  151. func PushHandler(cmd *cobra.Command, args []string) error {
  152. client, err := api.ClientFromEnvironment()
  153. if err != nil {
  154. return err
  155. }
  156. insecure, err := cmd.Flags().GetBool("insecure")
  157. if err != nil {
  158. return err
  159. }
  160. p := progress.NewProgress(os.Stderr)
  161. defer p.Stop()
  162. bars := make(map[string]*progress.Bar)
  163. var status string
  164. var spinner *progress.Spinner
  165. fn := func(resp api.ProgressResponse) error {
  166. if resp.Digest != "" {
  167. if spinner != nil {
  168. spinner.Stop()
  169. }
  170. bar, ok := bars[resp.Digest]
  171. if !ok {
  172. bar = progress.NewBar(fmt.Sprintf("pushing %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  173. bars[resp.Digest] = bar
  174. p.Add(resp.Digest, bar)
  175. }
  176. bar.Set(resp.Completed)
  177. } else if status != resp.Status {
  178. if spinner != nil {
  179. spinner.Stop()
  180. }
  181. status = resp.Status
  182. spinner = progress.NewSpinner(status)
  183. p.Add(status, spinner)
  184. }
  185. return nil
  186. }
  187. request := api.PushRequest{Name: args[0], Insecure: insecure}
  188. if err := client.Push(cmd.Context(), &request, fn); err != nil {
  189. return err
  190. }
  191. spinner.Stop()
  192. return nil
  193. }
  194. func ListHandler(cmd *cobra.Command, args []string) error {
  195. client, err := api.ClientFromEnvironment()
  196. if err != nil {
  197. return err
  198. }
  199. models, err := client.List(cmd.Context())
  200. if err != nil {
  201. return err
  202. }
  203. var data [][]string
  204. for _, m := range models.Models {
  205. if len(args) == 0 || strings.HasPrefix(m.Name, args[0]) {
  206. data = append(data, []string{m.Name, m.Digest[:12], format.HumanBytes(m.Size), format.HumanTime(m.ModifiedAt, "Never")})
  207. }
  208. }
  209. table := tablewriter.NewWriter(os.Stdout)
  210. table.SetHeader([]string{"NAME", "ID", "SIZE", "MODIFIED"})
  211. table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
  212. table.SetAlignment(tablewriter.ALIGN_LEFT)
  213. table.SetHeaderLine(false)
  214. table.SetBorder(false)
  215. table.SetNoWhiteSpace(true)
  216. table.SetTablePadding("\t")
  217. table.AppendBulk(data)
  218. table.Render()
  219. return nil
  220. }
  221. func DeleteHandler(cmd *cobra.Command, args []string) error {
  222. client, err := api.ClientFromEnvironment()
  223. if err != nil {
  224. return err
  225. }
  226. for _, name := range args {
  227. req := api.DeleteRequest{Name: name}
  228. if err := client.Delete(cmd.Context(), &req); err != nil {
  229. return err
  230. }
  231. fmt.Printf("deleted '%s'\n", name)
  232. }
  233. return nil
  234. }
  235. func ShowHandler(cmd *cobra.Command, args []string) error {
  236. client, err := api.ClientFromEnvironment()
  237. if err != nil {
  238. return err
  239. }
  240. if len(args) != 1 {
  241. return errors.New("missing model name")
  242. }
  243. license, errLicense := cmd.Flags().GetBool("license")
  244. modelfile, errModelfile := cmd.Flags().GetBool("modelfile")
  245. parameters, errParams := cmd.Flags().GetBool("parameters")
  246. system, errSystem := cmd.Flags().GetBool("system")
  247. template, errTemplate := cmd.Flags().GetBool("template")
  248. for _, boolErr := range []error{errLicense, errModelfile, errParams, errSystem, errTemplate} {
  249. if boolErr != nil {
  250. return errors.New("error retrieving flags")
  251. }
  252. }
  253. flagsSet := 0
  254. showType := ""
  255. if license {
  256. flagsSet++
  257. showType = "license"
  258. }
  259. if modelfile {
  260. flagsSet++
  261. showType = "modelfile"
  262. }
  263. if parameters {
  264. flagsSet++
  265. showType = "parameters"
  266. }
  267. if system {
  268. flagsSet++
  269. showType = "system"
  270. }
  271. if template {
  272. flagsSet++
  273. showType = "template"
  274. }
  275. if flagsSet > 1 {
  276. return errors.New("only one of '--license', '--modelfile', '--parameters', '--system', or '--template' can be specified")
  277. } else if flagsSet == 0 {
  278. return errors.New("one of '--license', '--modelfile', '--parameters', '--system', or '--template' must be specified")
  279. }
  280. req := api.ShowRequest{Name: args[0]}
  281. resp, err := client.Show(cmd.Context(), &req)
  282. if err != nil {
  283. return err
  284. }
  285. switch showType {
  286. case "license":
  287. fmt.Println(resp.License)
  288. case "modelfile":
  289. fmt.Println(resp.Modelfile)
  290. case "parameters":
  291. fmt.Println(resp.Parameters)
  292. case "system":
  293. fmt.Println(resp.System)
  294. case "template":
  295. fmt.Println(resp.Template)
  296. }
  297. return nil
  298. }
  299. func CopyHandler(cmd *cobra.Command, args []string) error {
  300. client, err := api.ClientFromEnvironment()
  301. if err != nil {
  302. return err
  303. }
  304. req := api.CopyRequest{Source: args[0], Destination: args[1]}
  305. if err := client.Copy(cmd.Context(), &req); err != nil {
  306. return err
  307. }
  308. fmt.Printf("copied '%s' to '%s'\n", args[0], args[1])
  309. return nil
  310. }
  311. func PullHandler(cmd *cobra.Command, args []string) error {
  312. insecure, err := cmd.Flags().GetBool("insecure")
  313. if err != nil {
  314. return err
  315. }
  316. client, err := api.ClientFromEnvironment()
  317. if err != nil {
  318. return err
  319. }
  320. p := progress.NewProgress(os.Stderr)
  321. defer p.Stop()
  322. bars := make(map[string]*progress.Bar)
  323. var status string
  324. var spinner *progress.Spinner
  325. fn := func(resp api.ProgressResponse) error {
  326. if resp.Digest != "" {
  327. if spinner != nil {
  328. spinner.Stop()
  329. }
  330. bar, ok := bars[resp.Digest]
  331. if !ok {
  332. bar = progress.NewBar(fmt.Sprintf("pulling %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  333. bars[resp.Digest] = bar
  334. p.Add(resp.Digest, bar)
  335. }
  336. bar.Set(resp.Completed)
  337. } else if status != resp.Status {
  338. if spinner != nil {
  339. spinner.Stop()
  340. }
  341. status = resp.Status
  342. spinner = progress.NewSpinner(status)
  343. p.Add(status, spinner)
  344. }
  345. return nil
  346. }
  347. request := api.PullRequest{Name: args[0], Insecure: insecure}
  348. if err := client.Pull(cmd.Context(), &request, fn); err != nil {
  349. return err
  350. }
  351. return nil
  352. }
  353. func RunGenerate(cmd *cobra.Command, args []string) error {
  354. interactive := true
  355. opts := generateOptions{
  356. Model: args[0],
  357. WordWrap: os.Getenv("TERM") == "xterm-256color",
  358. Options: map[string]interface{}{},
  359. Images: []ImageData{},
  360. }
  361. format, err := cmd.Flags().GetString("format")
  362. if err != nil {
  363. return err
  364. }
  365. opts.Format = format
  366. prompts := args[1:]
  367. // prepend stdin to the prompt if provided
  368. if !term.IsTerminal(int(os.Stdin.Fd())) {
  369. in, err := io.ReadAll(os.Stdin)
  370. if err != nil {
  371. return err
  372. }
  373. prompts = append([]string{string(in)}, prompts...)
  374. opts.WordWrap = false
  375. interactive = false
  376. }
  377. opts.Prompt = strings.Join(prompts, " ")
  378. if len(prompts) > 0 {
  379. interactive = false
  380. }
  381. nowrap, err := cmd.Flags().GetBool("nowordwrap")
  382. if err != nil {
  383. return err
  384. }
  385. opts.WordWrap = !nowrap
  386. if !interactive {
  387. return generate(cmd, opts)
  388. }
  389. return generateInteractive(cmd, opts)
  390. }
  391. type generateContextKey string
  392. type generateOptions struct {
  393. Model string
  394. Prompt string
  395. WordWrap bool
  396. Format string
  397. System string
  398. Template string
  399. Images []ImageData
  400. Options map[string]interface{}
  401. }
  402. func generate(cmd *cobra.Command, opts generateOptions) error {
  403. client, err := api.ClientFromEnvironment()
  404. if err != nil {
  405. return err
  406. }
  407. p := progress.NewProgress(os.Stderr)
  408. defer p.StopAndClear()
  409. spinner := progress.NewSpinner("")
  410. p.Add("", spinner)
  411. var latest api.GenerateResponse
  412. generateContext, ok := cmd.Context().Value(generateContextKey("context")).([]int)
  413. if !ok {
  414. generateContext = []int{}
  415. }
  416. termWidth, _, err := term.GetSize(int(os.Stdout.Fd()))
  417. if err != nil {
  418. opts.WordWrap = false
  419. }
  420. ctx, cancel := context.WithCancel(cmd.Context())
  421. defer cancel()
  422. sigChan := make(chan os.Signal, 1)
  423. signal.Notify(sigChan, syscall.SIGINT)
  424. go func() {
  425. <-sigChan
  426. cancel()
  427. }()
  428. var currentLineLength int
  429. var wordBuffer string
  430. fn := func(response api.GenerateResponse) error {
  431. p.StopAndClear()
  432. latest = response
  433. termWidth, _, _ = term.GetSize(int(os.Stdout.Fd()))
  434. if opts.WordWrap && termWidth >= 10 {
  435. for _, ch := range response.Response {
  436. if currentLineLength+1 > termWidth-5 {
  437. if len(wordBuffer) > termWidth-10 {
  438. fmt.Printf("%s%c", wordBuffer, ch)
  439. wordBuffer = ""
  440. currentLineLength = 0
  441. continue
  442. }
  443. // backtrack the length of the last word and clear to the end of the line
  444. fmt.Printf("\x1b[%dD\x1b[K\n", len(wordBuffer))
  445. fmt.Printf("%s%c", wordBuffer, ch)
  446. currentLineLength = len(wordBuffer) + 1
  447. } else {
  448. fmt.Print(string(ch))
  449. currentLineLength += 1
  450. switch ch {
  451. case ' ':
  452. wordBuffer = ""
  453. case '\n':
  454. currentLineLength = 0
  455. default:
  456. wordBuffer += string(ch)
  457. }
  458. }
  459. }
  460. } else {
  461. fmt.Printf("%s%s", wordBuffer, response.Response)
  462. if len(wordBuffer) > 0 {
  463. wordBuffer = ""
  464. }
  465. }
  466. return nil
  467. }
  468. images := make([]api.ImageData, 0)
  469. for _, i := range opts.Images {
  470. images = append(images, api.ImageData(i))
  471. }
  472. request := api.GenerateRequest{
  473. Model: opts.Model,
  474. Prompt: opts.Prompt,
  475. Context: generateContext,
  476. Format: opts.Format,
  477. System: opts.System,
  478. Template: opts.Template,
  479. Options: opts.Options,
  480. Images: images,
  481. }
  482. if err := client.Generate(ctx, &request, fn); err != nil {
  483. if errors.Is(err, context.Canceled) {
  484. return nil
  485. }
  486. return err
  487. }
  488. if opts.Prompt != "" {
  489. fmt.Println()
  490. fmt.Println()
  491. }
  492. if !latest.Done {
  493. return nil
  494. }
  495. verbose, err := cmd.Flags().GetBool("verbose")
  496. if err != nil {
  497. return err
  498. }
  499. if verbose {
  500. latest.Summary()
  501. }
  502. ctx = context.WithValue(cmd.Context(), generateContextKey("context"), latest.Context)
  503. cmd.SetContext(ctx)
  504. return nil
  505. }
  506. func RunServer(cmd *cobra.Command, _ []string) error {
  507. host, port, err := net.SplitHostPort(os.Getenv("OLLAMA_HOST"))
  508. if err != nil {
  509. host, port = "127.0.0.1", "11434"
  510. if ip := net.ParseIP(strings.Trim(os.Getenv("OLLAMA_HOST"), "[]")); ip != nil {
  511. host = ip.String()
  512. }
  513. }
  514. if err := initializeKeypair(); err != nil {
  515. return err
  516. }
  517. ln, err := net.Listen("tcp", net.JoinHostPort(host, port))
  518. if err != nil {
  519. return err
  520. }
  521. return server.Serve(ln)
  522. }
  523. func initializeKeypair() error {
  524. home, err := os.UserHomeDir()
  525. if err != nil {
  526. return err
  527. }
  528. privKeyPath := filepath.Join(home, ".ollama", "id_ed25519")
  529. pubKeyPath := filepath.Join(home, ".ollama", "id_ed25519.pub")
  530. _, err = os.Stat(privKeyPath)
  531. if os.IsNotExist(err) {
  532. fmt.Printf("Couldn't find '%s'. Generating new private key.\n", privKeyPath)
  533. _, privKey, err := ed25519.GenerateKey(rand.Reader)
  534. if err != nil {
  535. return err
  536. }
  537. privKeyBytes, err := format.OpenSSHPrivateKey(privKey, "")
  538. if err != nil {
  539. return err
  540. }
  541. err = os.MkdirAll(filepath.Dir(privKeyPath), 0o755)
  542. if err != nil {
  543. return fmt.Errorf("could not create directory %w", err)
  544. }
  545. err = os.WriteFile(privKeyPath, pem.EncodeToMemory(privKeyBytes), 0o600)
  546. if err != nil {
  547. return err
  548. }
  549. sshPrivateKey, err := ssh.NewSignerFromKey(privKey)
  550. if err != nil {
  551. return err
  552. }
  553. pubKeyData := ssh.MarshalAuthorizedKey(sshPrivateKey.PublicKey())
  554. err = os.WriteFile(pubKeyPath, pubKeyData, 0o644)
  555. if err != nil {
  556. return err
  557. }
  558. fmt.Printf("Your new public key is: \n\n%s\n", string(pubKeyData))
  559. }
  560. return nil
  561. }
  562. func startMacApp(ctx context.Context, client *api.Client) error {
  563. exe, err := os.Executable()
  564. if err != nil {
  565. return err
  566. }
  567. link, err := os.Readlink(exe)
  568. if err != nil {
  569. return err
  570. }
  571. if !strings.Contains(link, "Ollama.app") {
  572. return fmt.Errorf("could not find ollama app")
  573. }
  574. path := strings.Split(link, "Ollama.app")
  575. if err := exec.Command("/usr/bin/open", "-a", path[0]+"Ollama.app").Run(); err != nil {
  576. return err
  577. }
  578. // wait for the server to start
  579. timeout := time.After(5 * time.Second)
  580. tick := time.Tick(500 * time.Millisecond)
  581. for {
  582. select {
  583. case <-timeout:
  584. return errors.New("timed out waiting for server to start")
  585. case <-tick:
  586. if err := client.Heartbeat(ctx); err == nil {
  587. return nil // server has started
  588. }
  589. }
  590. }
  591. }
  592. func checkServerHeartbeat(cmd *cobra.Command, _ []string) error {
  593. client, err := api.ClientFromEnvironment()
  594. if err != nil {
  595. return err
  596. }
  597. if err := client.Heartbeat(cmd.Context()); err != nil {
  598. if !strings.Contains(err.Error(), "connection refused") {
  599. return err
  600. }
  601. if runtime.GOOS == "darwin" {
  602. if err := startMacApp(cmd.Context(), client); err != nil {
  603. return fmt.Errorf("could not connect to ollama app, is it running?")
  604. }
  605. } else {
  606. return fmt.Errorf("could not connect to ollama server, run 'ollama serve' to start it")
  607. }
  608. }
  609. return nil
  610. }
  611. func versionHandler(cmd *cobra.Command, _ []string) {
  612. client, err := api.ClientFromEnvironment()
  613. if err != nil {
  614. return
  615. }
  616. serverVersion, err := client.Version(cmd.Context())
  617. if err != nil {
  618. fmt.Println("Warning: could not connect to a running Ollama instance")
  619. }
  620. if serverVersion != "" {
  621. fmt.Printf("ollama version is %s\n", serverVersion)
  622. }
  623. if serverVersion != version.Version {
  624. fmt.Printf("Warning: client version is %s\n", version.Version)
  625. }
  626. }
  627. func NewCLI() *cobra.Command {
  628. log.SetFlags(log.LstdFlags | log.Lshortfile)
  629. cobra.EnableCommandSorting = false
  630. rootCmd := &cobra.Command{
  631. Use: "ollama",
  632. Short: "Large language model runner",
  633. SilenceUsage: true,
  634. SilenceErrors: true,
  635. CompletionOptions: cobra.CompletionOptions{
  636. DisableDefaultCmd: true,
  637. },
  638. Run: func(cmd *cobra.Command, args []string) {
  639. if version, _ := cmd.Flags().GetBool("version"); version {
  640. versionHandler(cmd, args)
  641. return
  642. }
  643. cmd.Print(cmd.UsageString())
  644. },
  645. }
  646. rootCmd.Flags().BoolP("version", "v", false, "Show version information")
  647. createCmd := &cobra.Command{
  648. Use: "create MODEL",
  649. Short: "Create a model from a Modelfile",
  650. Args: cobra.ExactArgs(1),
  651. PreRunE: checkServerHeartbeat,
  652. RunE: CreateHandler,
  653. }
  654. createCmd.Flags().StringP("file", "f", "Modelfile", "Name of the Modelfile (default \"Modelfile\")")
  655. showCmd := &cobra.Command{
  656. Use: "show MODEL",
  657. Short: "Show information for a model",
  658. Args: cobra.ExactArgs(1),
  659. PreRunE: checkServerHeartbeat,
  660. RunE: ShowHandler,
  661. }
  662. showCmd.Flags().Bool("license", false, "Show license of a model")
  663. showCmd.Flags().Bool("modelfile", false, "Show Modelfile of a model")
  664. showCmd.Flags().Bool("parameters", false, "Show parameters of a model")
  665. showCmd.Flags().Bool("template", false, "Show template of a model")
  666. showCmd.Flags().Bool("system", false, "Show system message of a model")
  667. runCmd := &cobra.Command{
  668. Use: "run MODEL [PROMPT]",
  669. Short: "Run a model",
  670. Args: cobra.MinimumNArgs(1),
  671. PreRunE: checkServerHeartbeat,
  672. RunE: RunHandler,
  673. }
  674. runCmd.Flags().Bool("verbose", false, "Show timings for response")
  675. runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  676. runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
  677. runCmd.Flags().String("format", "", "Response format (e.g. json)")
  678. serveCmd := &cobra.Command{
  679. Use: "serve",
  680. Aliases: []string{"start"},
  681. Short: "Start ollama",
  682. Args: cobra.ExactArgs(0),
  683. RunE: RunServer,
  684. }
  685. pullCmd := &cobra.Command{
  686. Use: "pull MODEL",
  687. Short: "Pull a model from a registry",
  688. Args: cobra.ExactArgs(1),
  689. PreRunE: checkServerHeartbeat,
  690. RunE: PullHandler,
  691. }
  692. pullCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  693. pushCmd := &cobra.Command{
  694. Use: "push MODEL",
  695. Short: "Push a model to a registry",
  696. Args: cobra.ExactArgs(1),
  697. PreRunE: checkServerHeartbeat,
  698. RunE: PushHandler,
  699. }
  700. pushCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  701. listCmd := &cobra.Command{
  702. Use: "list",
  703. Aliases: []string{"ls"},
  704. Short: "List models",
  705. PreRunE: checkServerHeartbeat,
  706. RunE: ListHandler,
  707. }
  708. copyCmd := &cobra.Command{
  709. Use: "cp SOURCE TARGET",
  710. Short: "Copy a model",
  711. Args: cobra.ExactArgs(2),
  712. PreRunE: checkServerHeartbeat,
  713. RunE: CopyHandler,
  714. }
  715. deleteCmd := &cobra.Command{
  716. Use: "rm MODEL [MODEL...]",
  717. Short: "Remove a model",
  718. Args: cobra.MinimumNArgs(1),
  719. PreRunE: checkServerHeartbeat,
  720. RunE: DeleteHandler,
  721. }
  722. rootCmd.AddCommand(
  723. serveCmd,
  724. createCmd,
  725. showCmd,
  726. runCmd,
  727. pullCmd,
  728. pushCmd,
  729. listCmd,
  730. copyCmd,
  731. deleteCmd,
  732. )
  733. return rootCmd
  734. }