cmd.go 31 KB

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