cmd.go 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383
  1. package cmd
  2. import (
  3. "archive/zip"
  4. "bytes"
  5. "context"
  6. "crypto/ed25519"
  7. "crypto/rand"
  8. "crypto/sha256"
  9. "encoding/pem"
  10. "errors"
  11. "fmt"
  12. "io"
  13. "log"
  14. "math"
  15. "net"
  16. "net/http"
  17. "os"
  18. "os/signal"
  19. "path/filepath"
  20. "regexp"
  21. "runtime"
  22. "slices"
  23. "strings"
  24. "syscall"
  25. "time"
  26. "github.com/containerd/console"
  27. "github.com/mattn/go-runewidth"
  28. "github.com/olekukonko/tablewriter"
  29. "github.com/spf13/cobra"
  30. "golang.org/x/crypto/ssh"
  31. "golang.org/x/term"
  32. "github.com/ollama/ollama/api"
  33. "github.com/ollama/ollama/auth"
  34. "github.com/ollama/ollama/envconfig"
  35. "github.com/ollama/ollama/format"
  36. "github.com/ollama/ollama/parser"
  37. "github.com/ollama/ollama/progress"
  38. "github.com/ollama/ollama/server"
  39. "github.com/ollama/ollama/types/errtypes"
  40. "github.com/ollama/ollama/types/model"
  41. "github.com/ollama/ollama/version"
  42. )
  43. func CreateHandler(cmd *cobra.Command, args []string) error {
  44. filename, _ := cmd.Flags().GetString("file")
  45. filename, err := filepath.Abs(filename)
  46. if err != nil {
  47. return err
  48. }
  49. client, err := api.ClientFromEnvironment()
  50. if err != nil {
  51. return err
  52. }
  53. p := progress.NewProgress(os.Stderr)
  54. defer p.Stop()
  55. f, err := os.Open(filename)
  56. if err != nil {
  57. return err
  58. }
  59. defer f.Close()
  60. modelfile, err := parser.ParseFile(f)
  61. if err != nil {
  62. return err
  63. }
  64. home, err := os.UserHomeDir()
  65. if err != nil {
  66. return err
  67. }
  68. status := "transferring model data"
  69. spinner := progress.NewSpinner(status)
  70. p.Add(status, spinner)
  71. for i := range modelfile.Commands {
  72. switch modelfile.Commands[i].Name {
  73. case "model", "adapter":
  74. path := modelfile.Commands[i].Args
  75. if path == "~" {
  76. path = home
  77. } else if strings.HasPrefix(path, "~/") {
  78. path = filepath.Join(home, path[2:])
  79. }
  80. if !filepath.IsAbs(path) {
  81. path = filepath.Join(filepath.Dir(filename), path)
  82. }
  83. fi, err := os.Stat(path)
  84. if errors.Is(err, os.ErrNotExist) && modelfile.Commands[i].Name == "model" {
  85. continue
  86. } else if err != nil {
  87. return err
  88. }
  89. if fi.IsDir() {
  90. // this is likely a safetensors or pytorch directory
  91. // TODO make this work w/ adapters
  92. tempfile, err := tempZipFiles(path)
  93. if err != nil {
  94. return err
  95. }
  96. defer os.RemoveAll(tempfile)
  97. path = tempfile
  98. }
  99. digest, err := createBlob(cmd, client, path)
  100. if err != nil {
  101. return err
  102. }
  103. modelfile.Commands[i].Args = "@" + digest
  104. }
  105. }
  106. bars := make(map[string]*progress.Bar)
  107. fn := func(resp api.ProgressResponse) error {
  108. if resp.Digest != "" {
  109. spinner.Stop()
  110. bar, ok := bars[resp.Digest]
  111. if !ok {
  112. bar = progress.NewBar(fmt.Sprintf("pulling %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  113. bars[resp.Digest] = bar
  114. p.Add(resp.Digest, bar)
  115. }
  116. bar.Set(resp.Completed)
  117. } else if status != resp.Status {
  118. spinner.Stop()
  119. status = resp.Status
  120. spinner = progress.NewSpinner(status)
  121. p.Add(status, spinner)
  122. }
  123. return nil
  124. }
  125. quantize, _ := cmd.Flags().GetString("quantize")
  126. request := api.CreateRequest{Name: args[0], Modelfile: modelfile.String(), Quantize: quantize}
  127. if err := client.Create(cmd.Context(), &request, fn); err != nil {
  128. return err
  129. }
  130. return nil
  131. }
  132. func tempZipFiles(path string) (string, error) {
  133. tempfile, err := os.CreateTemp("", "ollama-tf")
  134. if err != nil {
  135. return "", err
  136. }
  137. defer tempfile.Close()
  138. detectContentType := func(path string) (string, error) {
  139. f, err := os.Open(path)
  140. if err != nil {
  141. return "", err
  142. }
  143. defer f.Close()
  144. var b bytes.Buffer
  145. b.Grow(512)
  146. if _, err := io.CopyN(&b, f, 512); err != nil && !errors.Is(err, io.EOF) {
  147. return "", err
  148. }
  149. contentType, _, _ := strings.Cut(http.DetectContentType(b.Bytes()), ";")
  150. return contentType, nil
  151. }
  152. glob := func(pattern, contentType string) ([]string, error) {
  153. matches, err := filepath.Glob(pattern)
  154. if err != nil {
  155. return nil, err
  156. }
  157. for _, safetensor := range matches {
  158. if ct, err := detectContentType(safetensor); err != nil {
  159. return nil, err
  160. } else if ct != contentType {
  161. return nil, fmt.Errorf("invalid content type: expected %s for %s", ct, safetensor)
  162. }
  163. }
  164. return matches, nil
  165. }
  166. var files []string
  167. if st, _ := glob(filepath.Join(path, "model*.safetensors"), "application/octet-stream"); len(st) > 0 {
  168. // safetensors files might be unresolved git lfs references; skip if they are
  169. // covers model-x-of-y.safetensors, model.fp32-x-of-y.safetensors, model.safetensors
  170. files = append(files, st...)
  171. } else if pt, _ := glob(filepath.Join(path, "pytorch_model*.bin"), "application/zip"); len(pt) > 0 {
  172. // pytorch files might also be unresolved git lfs references; skip if they are
  173. // covers pytorch_model-x-of-y.bin, pytorch_model.fp32-x-of-y.bin, pytorch_model.bin
  174. files = append(files, pt...)
  175. } else if pt, _ := glob(filepath.Join(path, "consolidated*.pth"), "application/zip"); len(pt) > 0 {
  176. // pytorch files might also be unresolved git lfs references; skip if they are
  177. // covers consolidated.x.pth, consolidated.pth
  178. files = append(files, pt...)
  179. } else {
  180. return "", errors.New("no safetensors or torch files found")
  181. }
  182. // add configuration files, json files are detected as text/plain
  183. js, err := glob(filepath.Join(path, "*.json"), "text/plain")
  184. if err != nil {
  185. return "", err
  186. }
  187. files = append(files, js...)
  188. if tks, _ := glob(filepath.Join(path, "tokenizer.model"), "application/octet-stream"); len(tks) > 0 {
  189. // add tokenizer.model if it exists, tokenizer.json is automatically picked up by the previous glob
  190. // tokenizer.model might be a unresolved git lfs reference; error if it is
  191. files = append(files, tks...)
  192. } else if tks, _ := glob(filepath.Join(path, "**/tokenizer.model"), "text/plain"); len(tks) > 0 {
  193. // some times tokenizer.model is in a subdirectory (e.g. meta-llama/Meta-Llama-3-8B)
  194. files = append(files, tks...)
  195. }
  196. zipfile := zip.NewWriter(tempfile)
  197. defer zipfile.Close()
  198. for _, file := range files {
  199. f, err := os.Open(file)
  200. if err != nil {
  201. return "", err
  202. }
  203. defer f.Close()
  204. fi, err := f.Stat()
  205. if err != nil {
  206. return "", err
  207. }
  208. zfi, err := zip.FileInfoHeader(fi)
  209. if err != nil {
  210. return "", err
  211. }
  212. zf, err := zipfile.CreateHeader(zfi)
  213. if err != nil {
  214. return "", err
  215. }
  216. if _, err := io.Copy(zf, f); err != nil {
  217. return "", err
  218. }
  219. }
  220. return tempfile.Name(), nil
  221. }
  222. func createBlob(cmd *cobra.Command, client *api.Client, path string) (string, error) {
  223. bin, err := os.Open(path)
  224. if err != nil {
  225. return "", err
  226. }
  227. defer bin.Close()
  228. hash := sha256.New()
  229. if _, err := io.Copy(hash, bin); err != nil {
  230. return "", err
  231. }
  232. if _, err := bin.Seek(0, io.SeekStart); err != nil {
  233. return "", err
  234. }
  235. digest := fmt.Sprintf("sha256:%x", hash.Sum(nil))
  236. if err = client.CreateBlob(cmd.Context(), digest, bin); err != nil {
  237. return "", err
  238. }
  239. return digest, nil
  240. }
  241. func RunHandler(cmd *cobra.Command, args []string) error {
  242. interactive := true
  243. opts := runOptions{
  244. Model: args[0],
  245. WordWrap: os.Getenv("TERM") == "xterm-256color",
  246. Options: map[string]interface{}{},
  247. }
  248. format, err := cmd.Flags().GetString("format")
  249. if err != nil {
  250. return err
  251. }
  252. opts.Format = format
  253. keepAlive, err := cmd.Flags().GetString("keepalive")
  254. if err != nil {
  255. return err
  256. }
  257. if keepAlive != "" {
  258. d, err := time.ParseDuration(keepAlive)
  259. if err != nil {
  260. return err
  261. }
  262. opts.KeepAlive = &api.Duration{Duration: d}
  263. }
  264. prompts := args[1:]
  265. // prepend stdin to the prompt if provided
  266. if !term.IsTerminal(int(os.Stdin.Fd())) {
  267. in, err := io.ReadAll(os.Stdin)
  268. if err != nil {
  269. return err
  270. }
  271. prompts = append([]string{string(in)}, prompts...)
  272. opts.WordWrap = false
  273. interactive = false
  274. }
  275. opts.Prompt = strings.Join(prompts, " ")
  276. if len(prompts) > 0 {
  277. interactive = false
  278. }
  279. nowrap, err := cmd.Flags().GetBool("nowordwrap")
  280. if err != nil {
  281. return err
  282. }
  283. opts.WordWrap = !nowrap
  284. // Fill out the rest of the options based on information about the
  285. // model.
  286. client, err := api.ClientFromEnvironment()
  287. if err != nil {
  288. return err
  289. }
  290. name := args[0]
  291. info, err := func() (*api.ShowResponse, error) {
  292. showReq := &api.ShowRequest{Name: name}
  293. info, err := client.Show(cmd.Context(), showReq)
  294. var se api.StatusError
  295. if errors.As(err, &se) && se.StatusCode == http.StatusNotFound {
  296. if err := PullHandler(cmd, []string{name}); err != nil {
  297. return nil, err
  298. }
  299. return client.Show(cmd.Context(), &api.ShowRequest{Name: name})
  300. }
  301. return info, err
  302. }()
  303. if err != nil {
  304. return err
  305. }
  306. opts.MultiModal = slices.Contains(info.Details.Families, "clip")
  307. opts.ParentModel = info.Details.ParentModel
  308. if interactive {
  309. if err := loadModel(cmd, &opts); err != nil {
  310. return err
  311. }
  312. for _, msg := range info.Messages {
  313. switch msg.Role {
  314. case "user":
  315. fmt.Printf(">>> %s\n", msg.Content)
  316. case "assistant":
  317. state := &displayResponseState{}
  318. displayResponse(msg.Content, opts.WordWrap, state)
  319. fmt.Println()
  320. fmt.Println()
  321. }
  322. }
  323. return generateInteractive(cmd, opts)
  324. }
  325. return generate(cmd, opts)
  326. }
  327. func errFromUnknownKey(unknownKeyErr error) error {
  328. // find SSH public key in the error message
  329. sshKeyPattern := `ssh-\w+ [^\s"]+`
  330. re := regexp.MustCompile(sshKeyPattern)
  331. matches := re.FindStringSubmatch(unknownKeyErr.Error())
  332. if len(matches) > 0 {
  333. serverPubKey := matches[0]
  334. localPubKey, err := auth.GetPublicKey()
  335. if err != nil {
  336. return unknownKeyErr
  337. }
  338. if runtime.GOOS == "linux" && serverPubKey != localPubKey {
  339. // try the ollama service public key
  340. svcPubKey, err := os.ReadFile("/usr/share/ollama/.ollama/id_ed25519.pub")
  341. if err != nil {
  342. return unknownKeyErr
  343. }
  344. localPubKey = strings.TrimSpace(string(svcPubKey))
  345. }
  346. // check if the returned public key matches the local public key, this prevents adding a remote key to the user's account
  347. if serverPubKey != localPubKey {
  348. return unknownKeyErr
  349. }
  350. var msg strings.Builder
  351. msg.WriteString(unknownKeyErr.Error())
  352. msg.WriteString("\n\nYour ollama key is:\n")
  353. msg.WriteString(localPubKey)
  354. msg.WriteString("\nAdd your key at:\n")
  355. msg.WriteString("https://ollama.com/settings/keys")
  356. return errors.New(msg.String())
  357. }
  358. return unknownKeyErr
  359. }
  360. func PushHandler(cmd *cobra.Command, args []string) error {
  361. client, err := api.ClientFromEnvironment()
  362. if err != nil {
  363. return err
  364. }
  365. insecure, err := cmd.Flags().GetBool("insecure")
  366. if err != nil {
  367. return err
  368. }
  369. p := progress.NewProgress(os.Stderr)
  370. defer p.Stop()
  371. bars := make(map[string]*progress.Bar)
  372. var status string
  373. var spinner *progress.Spinner
  374. fn := func(resp api.ProgressResponse) error {
  375. if resp.Digest != "" {
  376. if spinner != nil {
  377. spinner.Stop()
  378. }
  379. bar, ok := bars[resp.Digest]
  380. if !ok {
  381. bar = progress.NewBar(fmt.Sprintf("pushing %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  382. bars[resp.Digest] = bar
  383. p.Add(resp.Digest, bar)
  384. }
  385. bar.Set(resp.Completed)
  386. } else if status != resp.Status {
  387. if spinner != nil {
  388. spinner.Stop()
  389. }
  390. status = resp.Status
  391. spinner = progress.NewSpinner(status)
  392. p.Add(status, spinner)
  393. }
  394. return nil
  395. }
  396. request := api.PushRequest{Name: args[0], Insecure: insecure}
  397. if err := client.Push(cmd.Context(), &request, fn); err != nil {
  398. if spinner != nil {
  399. spinner.Stop()
  400. }
  401. if strings.Contains(err.Error(), "access denied") {
  402. return errors.New("you are not authorized to push to this namespace, create the model under a namespace you own")
  403. }
  404. host := model.ParseName(args[0]).Host
  405. isOllamaHost := strings.HasSuffix(host, ".ollama.ai") || strings.HasSuffix(host, ".ollama.com")
  406. if strings.Contains(err.Error(), errtypes.UnknownOllamaKeyErrMsg) && isOllamaHost {
  407. // the user has not added their ollama key to ollama.com
  408. // re-throw an error with a more user-friendly message
  409. return errFromUnknownKey(err)
  410. }
  411. return err
  412. }
  413. spinner.Stop()
  414. return nil
  415. }
  416. func ListHandler(cmd *cobra.Command, args []string) error {
  417. client, err := api.ClientFromEnvironment()
  418. if err != nil {
  419. return err
  420. }
  421. models, err := client.List(cmd.Context())
  422. if err != nil {
  423. return err
  424. }
  425. var data [][]string
  426. for _, m := range models.Models {
  427. if len(args) == 0 || strings.HasPrefix(m.Name, args[0]) {
  428. data = append(data, []string{m.Name, m.Digest[:12], format.HumanBytes(m.Size), format.HumanTime(m.ModifiedAt, "Never")})
  429. }
  430. }
  431. table := tablewriter.NewWriter(os.Stdout)
  432. table.SetHeader([]string{"NAME", "ID", "SIZE", "MODIFIED"})
  433. table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
  434. table.SetAlignment(tablewriter.ALIGN_LEFT)
  435. table.SetHeaderLine(false)
  436. table.SetBorder(false)
  437. table.SetNoWhiteSpace(true)
  438. table.SetTablePadding("\t")
  439. table.AppendBulk(data)
  440. table.Render()
  441. return nil
  442. }
  443. func ListRunningHandler(cmd *cobra.Command, args []string) error {
  444. client, err := api.ClientFromEnvironment()
  445. if err != nil {
  446. return err
  447. }
  448. models, err := client.ListRunning(cmd.Context())
  449. if err != nil {
  450. return err
  451. }
  452. var data [][]string
  453. for _, m := range models.Models {
  454. if len(args) == 0 || strings.HasPrefix(m.Name, args[0]) {
  455. var procStr string
  456. switch {
  457. case m.SizeVRAM == 0:
  458. procStr = "100% CPU"
  459. case m.SizeVRAM == m.Size:
  460. procStr = "100% GPU"
  461. case m.SizeVRAM > m.Size || m.Size == 0:
  462. procStr = "Unknown"
  463. default:
  464. sizeCPU := m.Size - m.SizeVRAM
  465. cpuPercent := math.Round(float64(sizeCPU) / float64(m.Size) * 100)
  466. procStr = fmt.Sprintf("%d%%/%d%% CPU/GPU", int(cpuPercent), int(100-cpuPercent))
  467. }
  468. data = append(data, []string{m.Name, m.Digest[:12], format.HumanBytes(m.Size), procStr, format.HumanTime(m.ExpiresAt, "Never")})
  469. }
  470. }
  471. table := tablewriter.NewWriter(os.Stdout)
  472. table.SetHeader([]string{"NAME", "ID", "SIZE", "PROCESSOR", "UNTIL"})
  473. table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
  474. table.SetAlignment(tablewriter.ALIGN_LEFT)
  475. table.SetHeaderLine(false)
  476. table.SetBorder(false)
  477. table.SetNoWhiteSpace(true)
  478. table.SetTablePadding("\t")
  479. table.AppendBulk(data)
  480. table.Render()
  481. return nil
  482. }
  483. func DeleteHandler(cmd *cobra.Command, args []string) error {
  484. client, err := api.ClientFromEnvironment()
  485. if err != nil {
  486. return err
  487. }
  488. for _, name := range args {
  489. req := api.DeleteRequest{Name: name}
  490. if err := client.Delete(cmd.Context(), &req); err != nil {
  491. return err
  492. }
  493. fmt.Printf("deleted '%s'\n", name)
  494. }
  495. return nil
  496. }
  497. func ShowHandler(cmd *cobra.Command, args []string) error {
  498. client, err := api.ClientFromEnvironment()
  499. if err != nil {
  500. return err
  501. }
  502. license, errLicense := cmd.Flags().GetBool("license")
  503. modelfile, errModelfile := cmd.Flags().GetBool("modelfile")
  504. parameters, errParams := cmd.Flags().GetBool("parameters")
  505. system, errSystem := cmd.Flags().GetBool("system")
  506. template, errTemplate := cmd.Flags().GetBool("template")
  507. for _, boolErr := range []error{errLicense, errModelfile, errParams, errSystem, errTemplate} {
  508. if boolErr != nil {
  509. return errors.New("error retrieving flags")
  510. }
  511. }
  512. flagsSet := 0
  513. showType := ""
  514. if license {
  515. flagsSet++
  516. showType = "license"
  517. }
  518. if modelfile {
  519. flagsSet++
  520. showType = "modelfile"
  521. }
  522. if parameters {
  523. flagsSet++
  524. showType = "parameters"
  525. }
  526. if system {
  527. flagsSet++
  528. showType = "system"
  529. }
  530. if template {
  531. flagsSet++
  532. showType = "template"
  533. }
  534. if flagsSet > 1 {
  535. return errors.New("only one of '--license', '--modelfile', '--parameters', '--system', or '--template' can be specified")
  536. }
  537. req := api.ShowRequest{Name: args[0]}
  538. resp, err := client.Show(cmd.Context(), &req)
  539. if err != nil {
  540. return err
  541. }
  542. if flagsSet == 1 {
  543. switch showType {
  544. case "license":
  545. fmt.Println(resp.License)
  546. case "modelfile":
  547. fmt.Println(resp.Modelfile)
  548. case "parameters":
  549. fmt.Println(resp.Parameters)
  550. case "system":
  551. fmt.Println(resp.System)
  552. case "template":
  553. fmt.Println(resp.Template)
  554. }
  555. return nil
  556. }
  557. showInfo(resp)
  558. return nil
  559. }
  560. func showInfo(resp *api.ShowResponse) {
  561. arch := resp.ModelInfo["general.architecture"].(string)
  562. modelData := [][]string{
  563. {"arch", arch},
  564. {"parameters", resp.Details.ParameterSize},
  565. {"quantization", resp.Details.QuantizationLevel},
  566. {"context length", fmt.Sprintf("%v", resp.ModelInfo[fmt.Sprintf("%s.context_length", arch)].(float64))},
  567. {"embedding length", fmt.Sprintf("%v", resp.ModelInfo[fmt.Sprintf("%s.embedding_length", arch)].(float64))},
  568. }
  569. mainTableData := [][]string{
  570. {"Model"},
  571. {renderSubTable(modelData, false)},
  572. }
  573. if resp.ProjectorInfo != nil {
  574. projectorData := [][]string{
  575. {"arch", "clip"},
  576. {"parameters", format.HumanNumber(uint64(resp.ProjectorInfo["general.parameter_count"].(float64)))},
  577. }
  578. if projectorType, ok := resp.ProjectorInfo["clip.projector_type"]; ok {
  579. projectorData = append(projectorData, []string{"projector type", projectorType.(string)})
  580. }
  581. projectorData = append(projectorData,
  582. []string{"embedding length", fmt.Sprintf("%v", resp.ProjectorInfo["clip.vision.embedding_length"].(float64))},
  583. []string{"projection dimensionality", fmt.Sprintf("%v", resp.ProjectorInfo["clip.vision.projection_dim"].(float64))},
  584. )
  585. mainTableData = append(mainTableData,
  586. []string{"Projector"},
  587. []string{renderSubTable(projectorData, false)},
  588. )
  589. }
  590. if resp.Parameters != "" {
  591. mainTableData = append(mainTableData, []string{"Parameters"}, []string{formatParams(resp.Parameters)})
  592. }
  593. if resp.System != "" {
  594. mainTableData = append(mainTableData, []string{"System"}, []string{renderSubTable(twoLines(resp.System), true)})
  595. }
  596. if resp.License != "" {
  597. mainTableData = append(mainTableData, []string{"License"}, []string{renderSubTable(twoLines(resp.License), true)})
  598. }
  599. table := tablewriter.NewWriter(os.Stdout)
  600. table.SetAutoWrapText(false)
  601. table.SetBorder(false)
  602. table.SetAlignment(tablewriter.ALIGN_LEFT)
  603. for _, v := range mainTableData {
  604. table.Append(v)
  605. }
  606. table.Render()
  607. }
  608. func renderSubTable(data [][]string, file bool) string {
  609. var buf bytes.Buffer
  610. table := tablewriter.NewWriter(&buf)
  611. table.SetAutoWrapText(!file)
  612. table.SetBorder(false)
  613. table.SetNoWhiteSpace(true)
  614. table.SetTablePadding("\t")
  615. table.SetAlignment(tablewriter.ALIGN_LEFT)
  616. for _, v := range data {
  617. table.Append(v)
  618. }
  619. table.Render()
  620. renderedTable := buf.String()
  621. lines := strings.Split(renderedTable, "\n")
  622. for i, line := range lines {
  623. lines[i] = "\t" + line
  624. }
  625. return strings.Join(lines, "\n")
  626. }
  627. func twoLines(s string) [][]string {
  628. lines := strings.Split(s, "\n")
  629. res := [][]string{}
  630. count := 0
  631. for _, line := range lines {
  632. line = strings.TrimSpace(line)
  633. if line != "" {
  634. count++
  635. res = append(res, []string{line})
  636. if count == 2 {
  637. return res
  638. }
  639. }
  640. }
  641. return res
  642. }
  643. func formatParams(s string) string {
  644. lines := strings.Split(s, "\n")
  645. table := [][]string{}
  646. for _, line := range lines {
  647. table = append(table, strings.Fields(line))
  648. }
  649. return renderSubTable(table, false)
  650. }
  651. func CopyHandler(cmd *cobra.Command, args []string) error {
  652. client, err := api.ClientFromEnvironment()
  653. if err != nil {
  654. return err
  655. }
  656. req := api.CopyRequest{Source: args[0], Destination: args[1]}
  657. if err := client.Copy(cmd.Context(), &req); err != nil {
  658. return err
  659. }
  660. fmt.Printf("copied '%s' to '%s'\n", args[0], args[1])
  661. return nil
  662. }
  663. func PullHandler(cmd *cobra.Command, args []string) error {
  664. insecure, err := cmd.Flags().GetBool("insecure")
  665. if err != nil {
  666. return err
  667. }
  668. client, err := api.ClientFromEnvironment()
  669. if err != nil {
  670. return err
  671. }
  672. p := progress.NewProgress(os.Stderr)
  673. defer p.Stop()
  674. bars := make(map[string]*progress.Bar)
  675. var status string
  676. var spinner *progress.Spinner
  677. fn := func(resp api.ProgressResponse) error {
  678. if resp.Digest != "" {
  679. if spinner != nil {
  680. spinner.Stop()
  681. }
  682. bar, ok := bars[resp.Digest]
  683. if !ok {
  684. bar = progress.NewBar(fmt.Sprintf("pulling %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  685. bars[resp.Digest] = bar
  686. p.Add(resp.Digest, bar)
  687. }
  688. bar.Set(resp.Completed)
  689. } else if status != resp.Status {
  690. if spinner != nil {
  691. spinner.Stop()
  692. }
  693. status = resp.Status
  694. spinner = progress.NewSpinner(status)
  695. p.Add(status, spinner)
  696. }
  697. return nil
  698. }
  699. request := api.PullRequest{Name: args[0], Insecure: insecure}
  700. if err := client.Pull(cmd.Context(), &request, fn); err != nil {
  701. return err
  702. }
  703. return nil
  704. }
  705. type generateContextKey string
  706. type runOptions struct {
  707. Model string
  708. ParentModel string
  709. Prompt string
  710. Messages []api.Message
  711. WordWrap bool
  712. Format string
  713. System string
  714. Images []api.ImageData
  715. Options map[string]interface{}
  716. MultiModal bool
  717. KeepAlive *api.Duration
  718. }
  719. type displayResponseState struct {
  720. lineLength int
  721. wordBuffer string
  722. }
  723. func displayResponse(content string, wordWrap bool, state *displayResponseState) {
  724. termWidth, _, _ := term.GetSize(int(os.Stdout.Fd()))
  725. if wordWrap && termWidth >= 10 {
  726. for _, ch := range content {
  727. if state.lineLength+1 > termWidth-5 {
  728. if runewidth.StringWidth(state.wordBuffer) > termWidth-10 {
  729. fmt.Printf("%s%c", state.wordBuffer, ch)
  730. state.wordBuffer = ""
  731. state.lineLength = 0
  732. continue
  733. }
  734. // backtrack the length of the last word and clear to the end of the line
  735. a := runewidth.StringWidth(state.wordBuffer)
  736. if a > 0 {
  737. fmt.Printf("\x1b[%dD", a)
  738. }
  739. fmt.Printf("\x1b[K\n")
  740. fmt.Printf("%s%c", state.wordBuffer, ch)
  741. chWidth := runewidth.RuneWidth(ch)
  742. state.lineLength = runewidth.StringWidth(state.wordBuffer) + chWidth
  743. } else {
  744. fmt.Print(string(ch))
  745. state.lineLength += runewidth.RuneWidth(ch)
  746. if runewidth.RuneWidth(ch) >= 2 {
  747. state.wordBuffer = ""
  748. continue
  749. }
  750. switch ch {
  751. case ' ':
  752. state.wordBuffer = ""
  753. case '\n':
  754. state.lineLength = 0
  755. default:
  756. state.wordBuffer += string(ch)
  757. }
  758. }
  759. }
  760. } else {
  761. fmt.Printf("%s%s", state.wordBuffer, content)
  762. if len(state.wordBuffer) > 0 {
  763. state.wordBuffer = ""
  764. }
  765. }
  766. }
  767. func chat(cmd *cobra.Command, opts runOptions) (*api.Message, error) {
  768. client, err := api.ClientFromEnvironment()
  769. if err != nil {
  770. return nil, err
  771. }
  772. p := progress.NewProgress(os.Stderr)
  773. defer p.StopAndClear()
  774. spinner := progress.NewSpinner("")
  775. p.Add("", spinner)
  776. cancelCtx, cancel := context.WithCancel(cmd.Context())
  777. defer cancel()
  778. sigChan := make(chan os.Signal, 1)
  779. signal.Notify(sigChan, syscall.SIGINT)
  780. go func() {
  781. <-sigChan
  782. cancel()
  783. }()
  784. var state *displayResponseState = &displayResponseState{}
  785. var latest api.ChatResponse
  786. var fullResponse strings.Builder
  787. var role string
  788. fn := func(response api.ChatResponse) error {
  789. p.StopAndClear()
  790. latest = response
  791. role = response.Message.Role
  792. content := response.Message.Content
  793. fullResponse.WriteString(content)
  794. displayResponse(content, opts.WordWrap, state)
  795. return nil
  796. }
  797. req := &api.ChatRequest{
  798. Model: opts.Model,
  799. Messages: opts.Messages,
  800. Format: opts.Format,
  801. Options: opts.Options,
  802. }
  803. if opts.KeepAlive != nil {
  804. req.KeepAlive = opts.KeepAlive
  805. }
  806. if err := client.Chat(cancelCtx, req, fn); err != nil {
  807. if errors.Is(err, context.Canceled) {
  808. return nil, nil
  809. }
  810. return nil, err
  811. }
  812. if len(opts.Messages) > 0 {
  813. fmt.Println()
  814. fmt.Println()
  815. }
  816. verbose, err := cmd.Flags().GetBool("verbose")
  817. if err != nil {
  818. return nil, err
  819. }
  820. if verbose {
  821. latest.Summary()
  822. }
  823. return &api.Message{Role: role, Content: fullResponse.String()}, nil
  824. }
  825. func generate(cmd *cobra.Command, opts runOptions) error {
  826. client, err := api.ClientFromEnvironment()
  827. if err != nil {
  828. return err
  829. }
  830. p := progress.NewProgress(os.Stderr)
  831. defer p.StopAndClear()
  832. spinner := progress.NewSpinner("")
  833. p.Add("", spinner)
  834. var latest api.GenerateResponse
  835. generateContext, ok := cmd.Context().Value(generateContextKey("context")).([]int)
  836. if !ok {
  837. generateContext = []int{}
  838. }
  839. ctx, cancel := context.WithCancel(cmd.Context())
  840. defer cancel()
  841. sigChan := make(chan os.Signal, 1)
  842. signal.Notify(sigChan, syscall.SIGINT)
  843. go func() {
  844. <-sigChan
  845. cancel()
  846. }()
  847. var state *displayResponseState = &displayResponseState{}
  848. fn := func(response api.GenerateResponse) error {
  849. p.StopAndClear()
  850. latest = response
  851. content := response.Response
  852. displayResponse(content, opts.WordWrap, state)
  853. return nil
  854. }
  855. if opts.MultiModal {
  856. opts.Prompt, opts.Images, err = extractFileData(opts.Prompt)
  857. if err != nil {
  858. return err
  859. }
  860. }
  861. request := api.GenerateRequest{
  862. Model: opts.Model,
  863. Prompt: opts.Prompt,
  864. Context: generateContext,
  865. Images: opts.Images,
  866. Format: opts.Format,
  867. System: opts.System,
  868. Options: opts.Options,
  869. KeepAlive: opts.KeepAlive,
  870. }
  871. if err := client.Generate(ctx, &request, fn); err != nil {
  872. if errors.Is(err, context.Canceled) {
  873. return nil
  874. }
  875. return err
  876. }
  877. if opts.Prompt != "" {
  878. fmt.Println()
  879. fmt.Println()
  880. }
  881. if !latest.Done {
  882. return nil
  883. }
  884. verbose, err := cmd.Flags().GetBool("verbose")
  885. if err != nil {
  886. return err
  887. }
  888. if verbose {
  889. latest.Summary()
  890. }
  891. ctx = context.WithValue(cmd.Context(), generateContextKey("context"), latest.Context)
  892. cmd.SetContext(ctx)
  893. return nil
  894. }
  895. func RunServer(cmd *cobra.Command, _ []string) error {
  896. if err := initializeKeypair(); err != nil {
  897. return err
  898. }
  899. ln, err := net.Listen("tcp", envconfig.Host().Host)
  900. if err != nil {
  901. return err
  902. }
  903. err = server.Serve(ln)
  904. if errors.Is(err, http.ErrServerClosed) {
  905. return nil
  906. }
  907. return err
  908. }
  909. func initializeKeypair() error {
  910. home, err := os.UserHomeDir()
  911. if err != nil {
  912. return err
  913. }
  914. privKeyPath := filepath.Join(home, ".ollama", "id_ed25519")
  915. pubKeyPath := filepath.Join(home, ".ollama", "id_ed25519.pub")
  916. _, err = os.Stat(privKeyPath)
  917. if os.IsNotExist(err) {
  918. fmt.Printf("Couldn't find '%s'. Generating new private key.\n", privKeyPath)
  919. cryptoPublicKey, cryptoPrivateKey, err := ed25519.GenerateKey(rand.Reader)
  920. if err != nil {
  921. return err
  922. }
  923. privateKeyBytes, err := ssh.MarshalPrivateKey(cryptoPrivateKey, "")
  924. if err != nil {
  925. return err
  926. }
  927. if err := os.MkdirAll(filepath.Dir(privKeyPath), 0o755); err != nil {
  928. return fmt.Errorf("could not create directory %w", err)
  929. }
  930. if err := os.WriteFile(privKeyPath, pem.EncodeToMemory(privateKeyBytes), 0o600); err != nil {
  931. return err
  932. }
  933. sshPublicKey, err := ssh.NewPublicKey(cryptoPublicKey)
  934. if err != nil {
  935. return err
  936. }
  937. publicKeyBytes := ssh.MarshalAuthorizedKey(sshPublicKey)
  938. if err := os.WriteFile(pubKeyPath, publicKeyBytes, 0o644); err != nil {
  939. return err
  940. }
  941. fmt.Printf("Your new public key is: \n\n%s\n", publicKeyBytes)
  942. }
  943. return nil
  944. }
  945. func checkServerHeartbeat(cmd *cobra.Command, _ []string) error {
  946. client, err := api.ClientFromEnvironment()
  947. if err != nil {
  948. return err
  949. }
  950. if err := client.Heartbeat(cmd.Context()); err != nil {
  951. if !strings.Contains(err.Error(), " refused") {
  952. return err
  953. }
  954. if err := startApp(cmd.Context(), client); err != nil {
  955. return errors.New("could not connect to ollama app, is it running?")
  956. }
  957. }
  958. return nil
  959. }
  960. func versionHandler(cmd *cobra.Command, _ []string) {
  961. client, err := api.ClientFromEnvironment()
  962. if err != nil {
  963. return
  964. }
  965. serverVersion, err := client.Version(cmd.Context())
  966. if err != nil {
  967. fmt.Println("Warning: could not connect to a running Ollama instance")
  968. }
  969. if serverVersion != "" {
  970. fmt.Printf("ollama version is %s\n", serverVersion)
  971. }
  972. if serverVersion != version.Version {
  973. fmt.Printf("Warning: client version is %s\n", version.Version)
  974. }
  975. }
  976. func appendEnvDocs(cmd *cobra.Command, envs []envconfig.EnvVar) {
  977. if len(envs) == 0 {
  978. return
  979. }
  980. envUsage := `
  981. Environment Variables:
  982. `
  983. for _, e := range envs {
  984. envUsage += fmt.Sprintf(" %-24s %s\n", e.Name, e.Description)
  985. }
  986. cmd.SetUsageTemplate(cmd.UsageTemplate() + envUsage)
  987. }
  988. func NewCLI() *cobra.Command {
  989. log.SetFlags(log.LstdFlags | log.Lshortfile)
  990. cobra.EnableCommandSorting = false
  991. if runtime.GOOS == "windows" {
  992. console.ConsoleFromFile(os.Stdin) //nolint:errcheck
  993. }
  994. rootCmd := &cobra.Command{
  995. Use: "ollama",
  996. Short: "Large language model runner",
  997. SilenceUsage: true,
  998. SilenceErrors: true,
  999. CompletionOptions: cobra.CompletionOptions{
  1000. DisableDefaultCmd: true,
  1001. },
  1002. Run: func(cmd *cobra.Command, args []string) {
  1003. if version, _ := cmd.Flags().GetBool("version"); version {
  1004. versionHandler(cmd, args)
  1005. return
  1006. }
  1007. cmd.Print(cmd.UsageString())
  1008. },
  1009. }
  1010. rootCmd.Flags().BoolP("version", "v", false, "Show version information")
  1011. createCmd := &cobra.Command{
  1012. Use: "create MODEL",
  1013. Short: "Create a model from a Modelfile",
  1014. Args: cobra.ExactArgs(1),
  1015. PreRunE: checkServerHeartbeat,
  1016. RunE: CreateHandler,
  1017. }
  1018. createCmd.Flags().StringP("file", "f", "Modelfile", "Name of the Modelfile")
  1019. createCmd.Flags().StringP("quantize", "q", "", "Quantize model to this level (e.g. q4_0)")
  1020. showCmd := &cobra.Command{
  1021. Use: "show MODEL",
  1022. Short: "Show information for a model",
  1023. Args: cobra.ExactArgs(1),
  1024. PreRunE: checkServerHeartbeat,
  1025. RunE: ShowHandler,
  1026. }
  1027. showCmd.Flags().Bool("license", false, "Show license of a model")
  1028. showCmd.Flags().Bool("modelfile", false, "Show Modelfile of a model")
  1029. showCmd.Flags().Bool("parameters", false, "Show parameters of a model")
  1030. showCmd.Flags().Bool("template", false, "Show template of a model")
  1031. showCmd.Flags().Bool("system", false, "Show system message of a model")
  1032. runCmd := &cobra.Command{
  1033. Use: "run MODEL [PROMPT]",
  1034. Short: "Run a model",
  1035. Args: cobra.MinimumNArgs(1),
  1036. PreRunE: checkServerHeartbeat,
  1037. RunE: RunHandler,
  1038. }
  1039. runCmd.Flags().String("keepalive", "", "Duration to keep a model loaded (e.g. 5m)")
  1040. runCmd.Flags().Bool("verbose", false, "Show timings for response")
  1041. runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1042. runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
  1043. runCmd.Flags().String("format", "", "Response format (e.g. json)")
  1044. serveCmd := &cobra.Command{
  1045. Use: "serve",
  1046. Aliases: []string{"start"},
  1047. Short: "Start ollama",
  1048. Args: cobra.ExactArgs(0),
  1049. RunE: RunServer,
  1050. }
  1051. pullCmd := &cobra.Command{
  1052. Use: "pull MODEL",
  1053. Short: "Pull a model from a registry",
  1054. Args: cobra.ExactArgs(1),
  1055. PreRunE: checkServerHeartbeat,
  1056. RunE: PullHandler,
  1057. }
  1058. pullCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1059. pushCmd := &cobra.Command{
  1060. Use: "push MODEL",
  1061. Short: "Push a model to a registry",
  1062. Args: cobra.ExactArgs(1),
  1063. PreRunE: checkServerHeartbeat,
  1064. RunE: PushHandler,
  1065. }
  1066. pushCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1067. listCmd := &cobra.Command{
  1068. Use: "list",
  1069. Aliases: []string{"ls"},
  1070. Short: "List models",
  1071. PreRunE: checkServerHeartbeat,
  1072. RunE: ListHandler,
  1073. }
  1074. psCmd := &cobra.Command{
  1075. Use: "ps",
  1076. Short: "List running models",
  1077. PreRunE: checkServerHeartbeat,
  1078. RunE: ListRunningHandler,
  1079. }
  1080. copyCmd := &cobra.Command{
  1081. Use: "cp SOURCE DESTINATION",
  1082. Short: "Copy a model",
  1083. Args: cobra.ExactArgs(2),
  1084. PreRunE: checkServerHeartbeat,
  1085. RunE: CopyHandler,
  1086. }
  1087. deleteCmd := &cobra.Command{
  1088. Use: "rm MODEL [MODEL...]",
  1089. Short: "Remove a model",
  1090. Args: cobra.MinimumNArgs(1),
  1091. PreRunE: checkServerHeartbeat,
  1092. RunE: DeleteHandler,
  1093. }
  1094. envVars := envconfig.AsMap()
  1095. envs := []envconfig.EnvVar{envVars["OLLAMA_HOST"]}
  1096. for _, cmd := range []*cobra.Command{
  1097. createCmd,
  1098. showCmd,
  1099. runCmd,
  1100. pullCmd,
  1101. pushCmd,
  1102. listCmd,
  1103. psCmd,
  1104. copyCmd,
  1105. deleteCmd,
  1106. serveCmd,
  1107. } {
  1108. switch cmd {
  1109. case runCmd:
  1110. appendEnvDocs(cmd, []envconfig.EnvVar{envVars["OLLAMA_HOST"], envVars["OLLAMA_NOHISTORY"]})
  1111. case serveCmd:
  1112. appendEnvDocs(cmd, []envconfig.EnvVar{
  1113. envVars["OLLAMA_DEBUG"],
  1114. envVars["OLLAMA_HOST"],
  1115. envVars["OLLAMA_KEEP_ALIVE"],
  1116. envVars["OLLAMA_MAX_LOADED_MODELS"],
  1117. envVars["OLLAMA_MAX_QUEUE"],
  1118. envVars["OLLAMA_MODELS"],
  1119. envVars["OLLAMA_NUM_PARALLEL"],
  1120. envVars["OLLAMA_NOPRUNE"],
  1121. envVars["OLLAMA_ORIGINS"],
  1122. envVars["OLLAMA_SCHED_SPREAD"],
  1123. envVars["OLLAMA_TMPDIR"],
  1124. envVars["OLLAMA_FLASH_ATTENTION"],
  1125. envVars["OLLAMA_LLM_LIBRARY"],
  1126. })
  1127. default:
  1128. appendEnvDocs(cmd, envs)
  1129. }
  1130. }
  1131. rootCmd.AddCommand(
  1132. serveCmd,
  1133. createCmd,
  1134. showCmd,
  1135. runCmd,
  1136. pullCmd,
  1137. pushCmd,
  1138. listCmd,
  1139. psCmd,
  1140. copyCmd,
  1141. deleteCmd,
  1142. )
  1143. return rootCmd
  1144. }