cmd.go 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388
  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. "regexp"
  20. "runtime"
  21. "strings"
  22. "syscall"
  23. "time"
  24. "github.com/olekukonko/tablewriter"
  25. "github.com/spf13/cobra"
  26. "golang.org/x/crypto/ssh"
  27. "golang.org/x/exp/slices"
  28. "golang.org/x/term"
  29. "github.com/jmorganca/ollama/api"
  30. "github.com/jmorganca/ollama/format"
  31. "github.com/jmorganca/ollama/parser"
  32. "github.com/jmorganca/ollama/progress"
  33. "github.com/jmorganca/ollama/readline"
  34. "github.com/jmorganca/ollama/server"
  35. "github.com/jmorganca/ollama/version"
  36. )
  37. type ImageData []byte
  38. func CreateHandler(cmd *cobra.Command, args []string) error {
  39. filename, _ := cmd.Flags().GetString("file")
  40. filename, err := filepath.Abs(filename)
  41. if err != nil {
  42. return err
  43. }
  44. client, err := api.ClientFromEnvironment()
  45. if err != nil {
  46. return err
  47. }
  48. p := progress.NewProgress(os.Stderr)
  49. defer p.Stop()
  50. bars := make(map[string]*progress.Bar)
  51. modelfile, err := os.ReadFile(filename)
  52. if err != nil {
  53. return err
  54. }
  55. commands, err := parser.Parse(bytes.NewReader(modelfile))
  56. if err != nil {
  57. return err
  58. }
  59. home, err := os.UserHomeDir()
  60. if err != nil {
  61. return err
  62. }
  63. status := "transferring model data"
  64. spinner := progress.NewSpinner(status)
  65. p.Add(status, spinner)
  66. for _, c := range commands {
  67. switch c.Name {
  68. case "model", "adapter":
  69. path := c.Args
  70. if path == "~" {
  71. path = home
  72. } else if strings.HasPrefix(path, "~/") {
  73. path = filepath.Join(home, path[2:])
  74. }
  75. if !filepath.IsAbs(path) {
  76. path = filepath.Join(filepath.Dir(filename), path)
  77. }
  78. bin, err := os.Open(path)
  79. if errors.Is(err, os.ErrNotExist) && c.Name == "model" {
  80. continue
  81. } else if err != nil {
  82. return err
  83. }
  84. defer bin.Close()
  85. hash := sha256.New()
  86. if _, err := io.Copy(hash, bin); err != nil {
  87. return err
  88. }
  89. bin.Seek(0, io.SeekStart)
  90. digest := fmt.Sprintf("sha256:%x", hash.Sum(nil))
  91. if err = client.CreateBlob(cmd.Context(), digest, bin); err != nil {
  92. return err
  93. }
  94. modelfile = bytes.ReplaceAll(modelfile, []byte(c.Args), []byte("@"+digest))
  95. }
  96. }
  97. fn := func(resp api.ProgressResponse) error {
  98. if resp.Digest != "" {
  99. spinner.Stop()
  100. bar, ok := bars[resp.Digest]
  101. if !ok {
  102. bar = progress.NewBar(fmt.Sprintf("pulling %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  103. bars[resp.Digest] = bar
  104. p.Add(resp.Digest, bar)
  105. }
  106. bar.Set(resp.Completed)
  107. } else if status != resp.Status {
  108. spinner.Stop()
  109. status = resp.Status
  110. spinner = progress.NewSpinner(status)
  111. p.Add(status, spinner)
  112. }
  113. return nil
  114. }
  115. request := api.CreateRequest{Name: args[0], Modelfile: string(modelfile)}
  116. if err := client.Create(cmd.Context(), &request, fn); err != nil {
  117. return err
  118. }
  119. return nil
  120. }
  121. func RunHandler(cmd *cobra.Command, args []string) error {
  122. client, err := api.ClientFromEnvironment()
  123. if err != nil {
  124. return err
  125. }
  126. name := args[0]
  127. // check if the model exists on the server
  128. _, err = client.Show(cmd.Context(), &api.ShowRequest{Name: name})
  129. var statusError api.StatusError
  130. switch {
  131. case errors.As(err, &statusError) && statusError.StatusCode == http.StatusNotFound:
  132. if err := PullHandler(cmd, args); err != nil {
  133. return err
  134. }
  135. case err != nil:
  136. return err
  137. }
  138. return RunGenerate(cmd, args)
  139. }
  140. func PushHandler(cmd *cobra.Command, args []string) error {
  141. client, err := api.ClientFromEnvironment()
  142. if err != nil {
  143. return err
  144. }
  145. insecure, err := cmd.Flags().GetBool("insecure")
  146. if err != nil {
  147. return err
  148. }
  149. p := progress.NewProgress(os.Stderr)
  150. defer p.Stop()
  151. bars := make(map[string]*progress.Bar)
  152. var status string
  153. var spinner *progress.Spinner
  154. fn := func(resp api.ProgressResponse) error {
  155. if resp.Digest != "" {
  156. if spinner != nil {
  157. spinner.Stop()
  158. }
  159. bar, ok := bars[resp.Digest]
  160. if !ok {
  161. bar = progress.NewBar(fmt.Sprintf("pushing %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  162. bars[resp.Digest] = bar
  163. p.Add(resp.Digest, bar)
  164. }
  165. bar.Set(resp.Completed)
  166. } else if status != resp.Status {
  167. if spinner != nil {
  168. spinner.Stop()
  169. }
  170. status = resp.Status
  171. spinner = progress.NewSpinner(status)
  172. p.Add(status, spinner)
  173. }
  174. return nil
  175. }
  176. request := api.PushRequest{Name: args[0], Insecure: insecure}
  177. if err := client.Push(cmd.Context(), &request, fn); err != nil {
  178. return err
  179. }
  180. spinner.Stop()
  181. return nil
  182. }
  183. func ListHandler(cmd *cobra.Command, args []string) error {
  184. client, err := api.ClientFromEnvironment()
  185. if err != nil {
  186. return err
  187. }
  188. models, err := client.List(cmd.Context())
  189. if err != nil {
  190. return err
  191. }
  192. var data [][]string
  193. for _, m := range models.Models {
  194. if len(args) == 0 || strings.HasPrefix(m.Name, args[0]) {
  195. data = append(data, []string{m.Name, m.Digest[:12], format.HumanBytes(m.Size), format.HumanTime(m.ModifiedAt, "Never")})
  196. }
  197. }
  198. table := tablewriter.NewWriter(os.Stdout)
  199. table.SetHeader([]string{"NAME", "ID", "SIZE", "MODIFIED"})
  200. table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
  201. table.SetAlignment(tablewriter.ALIGN_LEFT)
  202. table.SetHeaderLine(false)
  203. table.SetBorder(false)
  204. table.SetNoWhiteSpace(true)
  205. table.SetTablePadding("\t")
  206. table.AppendBulk(data)
  207. table.Render()
  208. return nil
  209. }
  210. func DeleteHandler(cmd *cobra.Command, args []string) error {
  211. client, err := api.ClientFromEnvironment()
  212. if err != nil {
  213. return err
  214. }
  215. for _, name := range args {
  216. req := api.DeleteRequest{Name: name}
  217. if err := client.Delete(cmd.Context(), &req); err != nil {
  218. return err
  219. }
  220. fmt.Printf("deleted '%s'\n", name)
  221. }
  222. return nil
  223. }
  224. func ShowHandler(cmd *cobra.Command, args []string) error {
  225. client, err := api.ClientFromEnvironment()
  226. if err != nil {
  227. return err
  228. }
  229. if len(args) != 1 {
  230. return errors.New("missing model name")
  231. }
  232. license, errLicense := cmd.Flags().GetBool("license")
  233. modelfile, errModelfile := cmd.Flags().GetBool("modelfile")
  234. parameters, errParams := cmd.Flags().GetBool("parameters")
  235. system, errSystem := cmd.Flags().GetBool("system")
  236. template, errTemplate := cmd.Flags().GetBool("template")
  237. for _, boolErr := range []error{errLicense, errModelfile, errParams, errSystem, errTemplate} {
  238. if boolErr != nil {
  239. return errors.New("error retrieving flags")
  240. }
  241. }
  242. flagsSet := 0
  243. showType := ""
  244. if license {
  245. flagsSet++
  246. showType = "license"
  247. }
  248. if modelfile {
  249. flagsSet++
  250. showType = "modelfile"
  251. }
  252. if parameters {
  253. flagsSet++
  254. showType = "parameters"
  255. }
  256. if system {
  257. flagsSet++
  258. showType = "system"
  259. }
  260. if template {
  261. flagsSet++
  262. showType = "template"
  263. }
  264. if flagsSet > 1 {
  265. return errors.New("only one of '--license', '--modelfile', '--parameters', '--system', or '--template' can be specified")
  266. } else if flagsSet == 0 {
  267. return errors.New("one of '--license', '--modelfile', '--parameters', '--system', or '--template' must be specified")
  268. }
  269. req := api.ShowRequest{Name: args[0]}
  270. resp, err := client.Show(cmd.Context(), &req)
  271. if err != nil {
  272. return err
  273. }
  274. switch showType {
  275. case "license":
  276. fmt.Println(resp.License)
  277. case "modelfile":
  278. fmt.Println(resp.Modelfile)
  279. case "parameters":
  280. fmt.Println(resp.Parameters)
  281. case "system":
  282. fmt.Println(resp.System)
  283. case "template":
  284. fmt.Println(resp.Template)
  285. }
  286. return nil
  287. }
  288. func CopyHandler(cmd *cobra.Command, args []string) error {
  289. client, err := api.ClientFromEnvironment()
  290. if err != nil {
  291. return err
  292. }
  293. req := api.CopyRequest{Source: args[0], Destination: args[1]}
  294. if err := client.Copy(cmd.Context(), &req); err != nil {
  295. return err
  296. }
  297. fmt.Printf("copied '%s' to '%s'\n", args[0], args[1])
  298. return nil
  299. }
  300. func PullHandler(cmd *cobra.Command, args []string) error {
  301. insecure, err := cmd.Flags().GetBool("insecure")
  302. if err != nil {
  303. return err
  304. }
  305. client, err := api.ClientFromEnvironment()
  306. if err != nil {
  307. return err
  308. }
  309. p := progress.NewProgress(os.Stderr)
  310. defer p.Stop()
  311. bars := make(map[string]*progress.Bar)
  312. var status string
  313. var spinner *progress.Spinner
  314. fn := func(resp api.ProgressResponse) error {
  315. if resp.Digest != "" {
  316. if spinner != nil {
  317. spinner.Stop()
  318. }
  319. bar, ok := bars[resp.Digest]
  320. if !ok {
  321. bar = progress.NewBar(fmt.Sprintf("pulling %s...", resp.Digest[7:19]), resp.Total, resp.Completed)
  322. bars[resp.Digest] = bar
  323. p.Add(resp.Digest, bar)
  324. }
  325. bar.Set(resp.Completed)
  326. } else if status != resp.Status {
  327. if spinner != nil {
  328. spinner.Stop()
  329. }
  330. status = resp.Status
  331. spinner = progress.NewSpinner(status)
  332. p.Add(status, spinner)
  333. }
  334. return nil
  335. }
  336. request := api.PullRequest{Name: args[0], Insecure: insecure}
  337. if err := client.Pull(cmd.Context(), &request, fn); err != nil {
  338. return err
  339. }
  340. return nil
  341. }
  342. func RunGenerate(cmd *cobra.Command, args []string) error {
  343. interactive := true
  344. opts := generateOptions{
  345. Model: args[0],
  346. WordWrap: os.Getenv("TERM") == "xterm-256color",
  347. Options: map[string]interface{}{},
  348. Images: []ImageData{},
  349. }
  350. format, err := cmd.Flags().GetString("format")
  351. if err != nil {
  352. return err
  353. }
  354. opts.Format = format
  355. prompts := args[1:]
  356. // prepend stdin to the prompt if provided
  357. if !term.IsTerminal(int(os.Stdin.Fd())) {
  358. in, err := io.ReadAll(os.Stdin)
  359. if err != nil {
  360. return err
  361. }
  362. prompts = append([]string{string(in)}, prompts...)
  363. opts.WordWrap = false
  364. interactive = false
  365. }
  366. opts.Prompt = strings.Join(prompts, " ")
  367. if len(prompts) > 0 {
  368. interactive = false
  369. }
  370. nowrap, err := cmd.Flags().GetBool("nowordwrap")
  371. if err != nil {
  372. return err
  373. }
  374. opts.WordWrap = !nowrap
  375. if !interactive {
  376. return generate(cmd, opts)
  377. }
  378. return generateInteractive(cmd, opts)
  379. }
  380. type generateContextKey string
  381. type generateOptions struct {
  382. Model string
  383. Prompt string
  384. WordWrap bool
  385. Format string
  386. System string
  387. Template string
  388. Images []ImageData
  389. Options map[string]interface{}
  390. }
  391. func generate(cmd *cobra.Command, opts generateOptions) error {
  392. client, err := api.ClientFromEnvironment()
  393. if err != nil {
  394. return err
  395. }
  396. p := progress.NewProgress(os.Stderr)
  397. defer p.StopAndClear()
  398. spinner := progress.NewSpinner("")
  399. p.Add("", spinner)
  400. var latest api.GenerateResponse
  401. generateContext, ok := cmd.Context().Value(generateContextKey("context")).([]int)
  402. if !ok {
  403. generateContext = []int{}
  404. }
  405. termWidth, _, err := term.GetSize(int(os.Stdout.Fd()))
  406. if err != nil {
  407. opts.WordWrap = false
  408. }
  409. ctx, cancel := context.WithCancel(cmd.Context())
  410. defer cancel()
  411. sigChan := make(chan os.Signal, 1)
  412. signal.Notify(sigChan, syscall.SIGINT)
  413. go func() {
  414. <-sigChan
  415. cancel()
  416. }()
  417. var currentLineLength int
  418. var wordBuffer string
  419. fn := func(response api.GenerateResponse) error {
  420. p.StopAndClear()
  421. latest = response
  422. termWidth, _, _ = term.GetSize(int(os.Stdout.Fd()))
  423. if opts.WordWrap && termWidth >= 10 {
  424. for _, ch := range response.Response {
  425. if currentLineLength+1 > termWidth-5 {
  426. if len(wordBuffer) > termWidth-10 {
  427. fmt.Printf("%s%c", wordBuffer, ch)
  428. wordBuffer = ""
  429. currentLineLength = 0
  430. continue
  431. }
  432. // backtrack the length of the last word and clear to the end of the line
  433. fmt.Printf("\x1b[%dD\x1b[K\n", len(wordBuffer))
  434. fmt.Printf("%s%c", wordBuffer, ch)
  435. currentLineLength = len(wordBuffer) + 1
  436. } else {
  437. fmt.Print(string(ch))
  438. currentLineLength += 1
  439. switch ch {
  440. case ' ':
  441. wordBuffer = ""
  442. case '\n':
  443. currentLineLength = 0
  444. default:
  445. wordBuffer += string(ch)
  446. }
  447. }
  448. }
  449. } else {
  450. fmt.Printf("%s%s", wordBuffer, response.Response)
  451. if len(wordBuffer) > 0 {
  452. wordBuffer = ""
  453. }
  454. }
  455. return nil
  456. }
  457. images := make([]api.ImageData, 0)
  458. for _, i := range opts.Images {
  459. images = append(images, api.ImageData(i))
  460. }
  461. request := api.GenerateRequest{
  462. Model: opts.Model,
  463. Prompt: opts.Prompt,
  464. Context: generateContext,
  465. Format: opts.Format,
  466. System: opts.System,
  467. Template: opts.Template,
  468. Options: opts.Options,
  469. Images: images,
  470. }
  471. if err := client.Generate(ctx, &request, fn); err != nil {
  472. switch {
  473. case errors.Is(err, context.Canceled):
  474. return nil
  475. case strings.Contains(err.Error(), "unsupported model format"):
  476. // pull and retry to see if the model has been updated
  477. parts := strings.Split(opts.Model, string(os.PathSeparator))
  478. if len(parts) == 1 {
  479. // this is a library model, log some info
  480. fmt.Fprintln(os.Stderr, "This model is no longer compatible with Ollama. Pulling a new version...")
  481. }
  482. if err := PullHandler(cmd, []string{opts.Model}); err != nil {
  483. fmt.Printf("Error: %s\n", err)
  484. return fmt.Errorf("unsupported model, please update this model to gguf format") // relay the original error
  485. }
  486. // retry
  487. if err := client.Generate(ctx, &request, fn); err != nil {
  488. if errors.Is(err, context.Canceled) {
  489. return nil
  490. }
  491. return err
  492. }
  493. default:
  494. return err
  495. }
  496. }
  497. if opts.Prompt != "" {
  498. fmt.Println()
  499. fmt.Println()
  500. }
  501. if !latest.Done {
  502. return nil
  503. }
  504. verbose, err := cmd.Flags().GetBool("verbose")
  505. if err != nil {
  506. return err
  507. }
  508. if verbose {
  509. latest.Summary()
  510. }
  511. ctx = context.WithValue(cmd.Context(), generateContextKey("context"), latest.Context)
  512. cmd.SetContext(ctx)
  513. return nil
  514. }
  515. type MultilineState int
  516. const (
  517. MultilineNone MultilineState = iota
  518. MultilinePrompt
  519. MultilineSystem
  520. MultilineTemplate
  521. )
  522. func modelIsMultiModal(cmd *cobra.Command, name string) bool {
  523. // get model details
  524. client, err := api.ClientFromEnvironment()
  525. if err != nil {
  526. fmt.Println("error: couldn't connect to ollama server")
  527. return false
  528. }
  529. req := api.ShowRequest{Name: name}
  530. resp, err := client.Show(cmd.Context(), &req)
  531. if err != nil {
  532. return false
  533. }
  534. return slices.Contains(resp.Details.Families, "clip")
  535. }
  536. func generateInteractive(cmd *cobra.Command, opts generateOptions) error {
  537. multiModal := modelIsMultiModal(cmd, opts.Model)
  538. // load the model
  539. loadOpts := generateOptions{
  540. Model: opts.Model,
  541. Prompt: "",
  542. Images: []ImageData{},
  543. }
  544. if err := generate(cmd, loadOpts); err != nil {
  545. return err
  546. }
  547. usage := func() {
  548. fmt.Fprintln(os.Stderr, "Available Commands:")
  549. fmt.Fprintln(os.Stderr, " /set Set session variables")
  550. fmt.Fprintln(os.Stderr, " /show Show model information")
  551. fmt.Fprintln(os.Stderr, " /bye Exit")
  552. fmt.Fprintln(os.Stderr, " /?, /help Help for a command")
  553. fmt.Fprintln(os.Stderr, " /? shortcuts Help for keyboard shortcuts")
  554. fmt.Fprintln(os.Stderr, "")
  555. fmt.Fprintln(os.Stderr, "Use \"\"\" to begin a multi-line message.")
  556. fmt.Fprintln(os.Stderr, "")
  557. }
  558. usageSet := func() {
  559. fmt.Fprintln(os.Stderr, "Available Commands:")
  560. fmt.Fprintln(os.Stderr, " /set parameter ... Set a parameter")
  561. fmt.Fprintln(os.Stderr, " /set system <string> Set system message")
  562. fmt.Fprintln(os.Stderr, " /set template <string> Set prompt template")
  563. fmt.Fprintln(os.Stderr, " /set history Enable history")
  564. fmt.Fprintln(os.Stderr, " /set nohistory Disable history")
  565. fmt.Fprintln(os.Stderr, " /set wordwrap Enable wordwrap")
  566. fmt.Fprintln(os.Stderr, " /set nowordwrap Disable wordwrap")
  567. fmt.Fprintln(os.Stderr, " /set format json Enable JSON mode")
  568. fmt.Fprintln(os.Stderr, " /set noformat Disable formatting")
  569. fmt.Fprintln(os.Stderr, " /set verbose Show LLM stats")
  570. fmt.Fprintln(os.Stderr, " /set quiet Disable LLM stats")
  571. fmt.Fprintln(os.Stderr, "")
  572. }
  573. usageShortcuts := func() {
  574. fmt.Fprintln(os.Stderr, "Available keyboard shortcuts:")
  575. fmt.Fprintln(os.Stderr, " Ctrl + a Move to the beginning of the line (Home)")
  576. fmt.Fprintln(os.Stderr, " Ctrl + e Move to the end of the line (End)")
  577. fmt.Fprintln(os.Stderr, " Alt + b Move back (left) one word")
  578. fmt.Fprintln(os.Stderr, " Alt + f Move forward (right) one word")
  579. fmt.Fprintln(os.Stderr, " Ctrl + k Delete the sentence after the cursor")
  580. fmt.Fprintln(os.Stderr, " Ctrl + u Delete the sentence before the cursor")
  581. fmt.Fprintln(os.Stderr, "")
  582. fmt.Fprintln(os.Stderr, " Ctrl + l Clear the screen")
  583. fmt.Fprintln(os.Stderr, " Ctrl + c Stop the model from responding")
  584. fmt.Fprintln(os.Stderr, " Ctrl + d Exit ollama (/bye)")
  585. fmt.Fprintln(os.Stderr, "")
  586. }
  587. usageShow := func() {
  588. fmt.Fprintln(os.Stderr, "Available Commands:")
  589. fmt.Fprintln(os.Stderr, " /show license Show model license")
  590. fmt.Fprintln(os.Stderr, " /show modelfile Show Modelfile for this model")
  591. fmt.Fprintln(os.Stderr, " /show parameters Show parameters for this model")
  592. fmt.Fprintln(os.Stderr, " /show system Show system message")
  593. fmt.Fprintln(os.Stderr, " /show template Show prompt template")
  594. fmt.Fprintln(os.Stderr, "")
  595. }
  596. // only list out the most common parameters
  597. usageParameters := func() {
  598. fmt.Fprintln(os.Stderr, "Available Parameters:")
  599. fmt.Fprintln(os.Stderr, " /set parameter seed <int> Random number seed")
  600. fmt.Fprintln(os.Stderr, " /set parameter num_predict <int> Max number of tokens to predict")
  601. fmt.Fprintln(os.Stderr, " /set parameter top_k <int> Pick from top k num of tokens")
  602. fmt.Fprintln(os.Stderr, " /set parameter top_p <float> Pick token based on sum of probabilities")
  603. fmt.Fprintln(os.Stderr, " /set parameter num_ctx <int> Set the context size")
  604. fmt.Fprintln(os.Stderr, " /set parameter temperature <float> Set creativity level")
  605. fmt.Fprintln(os.Stderr, " /set parameter repeat_penalty <float> How strongly to penalize repetitions")
  606. fmt.Fprintln(os.Stderr, " /set parameter repeat_last_n <int> Set how far back to look for repetitions")
  607. fmt.Fprintln(os.Stderr, " /set parameter num_gpu <int> The number of layers to send to the GPU")
  608. fmt.Fprintln(os.Stderr, " /set parameter stop \"<string>\", ... Set the stop parameters")
  609. fmt.Fprintln(os.Stderr, "")
  610. }
  611. scanner, err := readline.New(readline.Prompt{
  612. Prompt: ">>> ",
  613. AltPrompt: "... ",
  614. Placeholder: "Send a message (/? for help)",
  615. AltPlaceholder: `Use """ to end multi-line input`,
  616. })
  617. if err != nil {
  618. return err
  619. }
  620. fmt.Print(readline.StartBracketedPaste)
  621. defer fmt.Printf(readline.EndBracketedPaste)
  622. var multiline MultilineState
  623. var prompt string
  624. for {
  625. line, err := scanner.Readline()
  626. switch {
  627. case errors.Is(err, io.EOF):
  628. fmt.Println()
  629. return nil
  630. case errors.Is(err, readline.ErrInterrupt):
  631. if line == "" {
  632. fmt.Println("\nUse Ctrl + d or /bye to exit.")
  633. }
  634. scanner.Prompt.UseAlt = false
  635. prompt = ""
  636. continue
  637. case err != nil:
  638. return err
  639. }
  640. switch {
  641. case strings.HasPrefix(prompt, `"""`):
  642. // if the prompt so far starts with """ then we're in multiline mode
  643. // and we need to keep reading until we find a line that ends with """
  644. cut, found := strings.CutSuffix(line, `"""`)
  645. prompt += cut
  646. if !found {
  647. prompt += "\n"
  648. continue
  649. }
  650. prompt = strings.TrimPrefix(prompt, `"""`)
  651. scanner.Prompt.UseAlt = false
  652. switch multiline {
  653. case MultilineSystem:
  654. opts.System = prompt
  655. prompt = ""
  656. fmt.Println("Set system message.")
  657. case MultilineTemplate:
  658. opts.Template = prompt
  659. prompt = ""
  660. fmt.Println("Set prompt template.")
  661. }
  662. multiline = MultilineNone
  663. case strings.HasPrefix(line, `"""`) && len(prompt) == 0:
  664. scanner.Prompt.UseAlt = true
  665. multiline = MultilinePrompt
  666. prompt += line + "\n"
  667. continue
  668. case scanner.Pasting:
  669. prompt += line + "\n"
  670. continue
  671. case strings.HasPrefix(line, "/list"):
  672. args := strings.Fields(line)
  673. if err := ListHandler(cmd, args[1:]); err != nil {
  674. return err
  675. }
  676. case strings.HasPrefix(line, "/set"):
  677. args := strings.Fields(line)
  678. if len(args) > 1 {
  679. switch args[1] {
  680. case "history":
  681. scanner.HistoryEnable()
  682. case "nohistory":
  683. scanner.HistoryDisable()
  684. case "wordwrap":
  685. opts.WordWrap = true
  686. fmt.Println("Set 'wordwrap' mode.")
  687. case "nowordwrap":
  688. opts.WordWrap = false
  689. fmt.Println("Set 'nowordwrap' mode.")
  690. case "verbose":
  691. cmd.Flags().Set("verbose", "true")
  692. fmt.Println("Set 'verbose' mode.")
  693. case "quiet":
  694. cmd.Flags().Set("verbose", "false")
  695. fmt.Println("Set 'quiet' mode.")
  696. case "format":
  697. if len(args) < 3 || args[2] != "json" {
  698. fmt.Println("Invalid or missing format. For 'json' mode use '/set format json'")
  699. } else {
  700. opts.Format = args[2]
  701. fmt.Printf("Set format to '%s' mode.\n", args[2])
  702. }
  703. case "noformat":
  704. opts.Format = ""
  705. fmt.Println("Disabled format.")
  706. case "parameter":
  707. if len(args) < 4 {
  708. usageParameters()
  709. continue
  710. }
  711. var params []string
  712. for _, p := range args[3:] {
  713. params = append(params, p)
  714. }
  715. fp, err := api.FormatParams(map[string][]string{args[2]: params})
  716. if err != nil {
  717. fmt.Printf("Couldn't set parameter: %q\n\n", err)
  718. continue
  719. }
  720. fmt.Printf("Set parameter '%s' to '%s'\n\n", args[2], strings.Join(params, ", "))
  721. opts.Options[args[2]] = fp[args[2]]
  722. case "system", "template":
  723. if len(args) < 3 {
  724. usageSet()
  725. continue
  726. }
  727. line := strings.Join(args[2:], " ")
  728. line = strings.TrimPrefix(line, `"""`)
  729. if strings.HasPrefix(args[2], `"""`) {
  730. cut, found := strings.CutSuffix(line, `"""`)
  731. prompt += cut
  732. if found {
  733. if args[1] == "system" {
  734. opts.System = prompt
  735. fmt.Println("Set system message.")
  736. } else {
  737. opts.Template = prompt
  738. fmt.Println("Set prompt template.")
  739. }
  740. prompt = ""
  741. } else {
  742. prompt = `"""` + prompt + "\n"
  743. if args[1] == "system" {
  744. multiline = MultilineSystem
  745. } else {
  746. multiline = MultilineTemplate
  747. }
  748. scanner.Prompt.UseAlt = true
  749. }
  750. } else {
  751. opts.System = line
  752. fmt.Println("Set system message.")
  753. }
  754. default:
  755. fmt.Printf("Unknown command '/set %s'. Type /? for help\n", args[1])
  756. }
  757. } else {
  758. usageSet()
  759. }
  760. case strings.HasPrefix(line, "/show"):
  761. args := strings.Fields(line)
  762. if len(args) > 1 {
  763. client, err := api.ClientFromEnvironment()
  764. if err != nil {
  765. fmt.Println("error: couldn't connect to ollama server")
  766. return err
  767. }
  768. resp, err := client.Show(cmd.Context(), &api.ShowRequest{Name: opts.Model})
  769. if err != nil {
  770. fmt.Println("error: couldn't get model")
  771. return err
  772. }
  773. switch args[1] {
  774. case "license":
  775. if resp.License == "" {
  776. fmt.Print("No license was specified for this model.\n\n")
  777. } else {
  778. fmt.Println(resp.License)
  779. }
  780. case "modelfile":
  781. fmt.Println(resp.Modelfile)
  782. case "parameters":
  783. if resp.Parameters == "" {
  784. fmt.Print("No parameters were specified for this model.\n\n")
  785. } else {
  786. if len(opts.Options) > 0 {
  787. fmt.Println("User defined parameters:")
  788. for k, v := range opts.Options {
  789. fmt.Printf("%-*s %v\n", 30, k, v)
  790. }
  791. fmt.Println()
  792. }
  793. fmt.Println("Model defined parameters:")
  794. fmt.Println(resp.Parameters)
  795. }
  796. case "system":
  797. switch {
  798. case opts.System != "":
  799. fmt.Println(opts.System + "\n")
  800. case resp.System != "":
  801. fmt.Println(resp.System + "\n")
  802. default:
  803. fmt.Print("No system message was specified for this model.\n\n")
  804. }
  805. case "template":
  806. switch {
  807. case opts.Template != "":
  808. fmt.Println(opts.Template + "\n")
  809. case resp.Template != "":
  810. fmt.Println(resp.Template)
  811. default:
  812. fmt.Print("No prompt template was specified for this model.\n\n")
  813. }
  814. default:
  815. fmt.Printf("Unknown command '/show %s'. Type /? for help\n", args[1])
  816. }
  817. } else {
  818. usageShow()
  819. }
  820. case strings.HasPrefix(line, "/help"), strings.HasPrefix(line, "/?"):
  821. args := strings.Fields(line)
  822. if len(args) > 1 {
  823. switch args[1] {
  824. case "set", "/set":
  825. usageSet()
  826. case "show", "/show":
  827. usageShow()
  828. case "shortcut", "shortcuts":
  829. usageShortcuts()
  830. }
  831. } else {
  832. usage()
  833. }
  834. case line == "/exit", line == "/bye":
  835. return nil
  836. case strings.HasPrefix(line, "/"):
  837. args := strings.Fields(line)
  838. isFile := false
  839. if multiModal {
  840. for _, f := range extractFileNames(line) {
  841. if strings.HasPrefix(f, args[0]) {
  842. isFile = true
  843. break
  844. }
  845. }
  846. }
  847. if isFile {
  848. prompt += line
  849. } else {
  850. fmt.Printf("Unknown command '%s'. Type /? for help\n", args[0])
  851. continue
  852. }
  853. default:
  854. prompt += line
  855. }
  856. if len(prompt) > 0 && multiline == MultilineNone {
  857. opts.Prompt = prompt
  858. if multiModal {
  859. newPrompt, images, err := extractFileData(prompt)
  860. if err != nil {
  861. return err
  862. }
  863. opts.Prompt = newPrompt
  864. // reset the context if we find another image
  865. if len(images) > 0 {
  866. opts.Images = images
  867. ctx := cmd.Context()
  868. ctx = context.WithValue(ctx, generateContextKey("context"), []int{})
  869. cmd.SetContext(ctx)
  870. }
  871. if len(opts.Images) == 0 {
  872. fmt.Println("This model requires you to add a jpeg, png, or svg image.")
  873. fmt.Println()
  874. prompt = ""
  875. continue
  876. }
  877. }
  878. if err := generate(cmd, opts); err != nil {
  879. return err
  880. }
  881. prompt = ""
  882. }
  883. }
  884. }
  885. func normalizeFilePath(fp string) string {
  886. // Define a map of escaped characters and their replacements
  887. replacements := map[string]string{
  888. "\\ ": " ", // Escaped space
  889. "\\(": "(", // Escaped left parenthesis
  890. "\\)": ")", // Escaped right parenthesis
  891. "\\[": "[", // Escaped left square bracket
  892. "\\]": "]", // Escaped right square bracket
  893. "\\{": "{", // Escaped left curly brace
  894. "\\}": "}", // Escaped right curly brace
  895. "\\$": "$", // Escaped dollar sign
  896. "\\&": "&", // Escaped ampersand
  897. "\\;": ";", // Escaped semicolon
  898. "\\'": "'", // Escaped single quote
  899. "\\\\": "\\", // Escaped backslash
  900. "\\*": "*", // Escaped asterisk
  901. "\\?": "?", // Escaped question mark
  902. }
  903. for escaped, actual := range replacements {
  904. fp = strings.ReplaceAll(fp, escaped, actual)
  905. }
  906. return fp
  907. }
  908. func extractFileNames(input string) []string {
  909. // Regex to match file paths starting with / or ./ and include escaped spaces (\ or %20)
  910. // and followed by more characters and a file extension
  911. regexPattern := `(?:\./|/)[\S\\ ]+?\.(?i:jpg|jpeg|png|svg)\b`
  912. re := regexp.MustCompile(regexPattern)
  913. return re.FindAllString(input, -1)
  914. }
  915. func extractFileData(input string) (string, []ImageData, error) {
  916. filePaths := extractFileNames(input)
  917. var imgs []ImageData
  918. for _, fp := range filePaths {
  919. nfp := normalizeFilePath(fp)
  920. data, err := getImageData(nfp)
  921. if err != nil {
  922. if os.IsNotExist(err) {
  923. continue
  924. }
  925. fmt.Printf("Couldn't process image: %q\n", err)
  926. return "", imgs, err
  927. }
  928. fmt.Printf("Added image '%s'\n", nfp)
  929. input = strings.ReplaceAll(input, fp, "")
  930. imgs = append(imgs, data)
  931. }
  932. return input, imgs, nil
  933. }
  934. func RunServer(cmd *cobra.Command, _ []string) error {
  935. host, port, err := net.SplitHostPort(os.Getenv("OLLAMA_HOST"))
  936. if err != nil {
  937. host, port = "127.0.0.1", "11434"
  938. if ip := net.ParseIP(strings.Trim(os.Getenv("OLLAMA_HOST"), "[]")); ip != nil {
  939. host = ip.String()
  940. }
  941. }
  942. if err := initializeKeypair(); err != nil {
  943. return err
  944. }
  945. ln, err := net.Listen("tcp", net.JoinHostPort(host, port))
  946. if err != nil {
  947. return err
  948. }
  949. return server.Serve(ln)
  950. }
  951. func getImageData(filePath string) ([]byte, error) {
  952. file, err := os.Open(filePath)
  953. if err != nil {
  954. return nil, err
  955. }
  956. defer file.Close()
  957. buf := make([]byte, 512)
  958. _, err = file.Read(buf)
  959. if err != nil {
  960. return nil, err
  961. }
  962. contentType := http.DetectContentType(buf)
  963. allowedTypes := []string{"image/jpeg", "image/jpg", "image/svg+xml", "image/png"}
  964. if !slices.Contains(allowedTypes, contentType) {
  965. return nil, fmt.Errorf("invalid image type: %s", contentType)
  966. }
  967. info, err := file.Stat()
  968. if err != nil {
  969. return nil, err
  970. }
  971. // Check if the file size exceeds 100MB
  972. var maxSize int64 = 100 * 1024 * 1024 // 100MB in bytes
  973. if info.Size() > maxSize {
  974. return nil, fmt.Errorf("file size exceeds maximum limit (100MB)")
  975. }
  976. buf = make([]byte, info.Size())
  977. _, err = file.Seek(0, 0)
  978. if err != nil {
  979. return nil, err
  980. }
  981. _, err = io.ReadFull(file, buf)
  982. if err != nil {
  983. return nil, err
  984. }
  985. return buf, nil
  986. }
  987. func initializeKeypair() error {
  988. home, err := os.UserHomeDir()
  989. if err != nil {
  990. return err
  991. }
  992. privKeyPath := filepath.Join(home, ".ollama", "id_ed25519")
  993. pubKeyPath := filepath.Join(home, ".ollama", "id_ed25519.pub")
  994. _, err = os.Stat(privKeyPath)
  995. if os.IsNotExist(err) {
  996. fmt.Printf("Couldn't find '%s'. Generating new private key.\n", privKeyPath)
  997. _, privKey, err := ed25519.GenerateKey(rand.Reader)
  998. if err != nil {
  999. return err
  1000. }
  1001. privKeyBytes, err := format.OpenSSHPrivateKey(privKey, "")
  1002. if err != nil {
  1003. return err
  1004. }
  1005. err = os.MkdirAll(filepath.Dir(privKeyPath), 0o755)
  1006. if err != nil {
  1007. return fmt.Errorf("could not create directory %w", err)
  1008. }
  1009. err = os.WriteFile(privKeyPath, pem.EncodeToMemory(privKeyBytes), 0o600)
  1010. if err != nil {
  1011. return err
  1012. }
  1013. sshPrivateKey, err := ssh.NewSignerFromKey(privKey)
  1014. if err != nil {
  1015. return err
  1016. }
  1017. pubKeyData := ssh.MarshalAuthorizedKey(sshPrivateKey.PublicKey())
  1018. err = os.WriteFile(pubKeyPath, pubKeyData, 0o644)
  1019. if err != nil {
  1020. return err
  1021. }
  1022. fmt.Printf("Your new public key is: \n\n%s\n", string(pubKeyData))
  1023. }
  1024. return nil
  1025. }
  1026. func startMacApp(ctx context.Context, client *api.Client) error {
  1027. exe, err := os.Executable()
  1028. if err != nil {
  1029. return err
  1030. }
  1031. link, err := os.Readlink(exe)
  1032. if err != nil {
  1033. return err
  1034. }
  1035. if !strings.Contains(link, "Ollama.app") {
  1036. return fmt.Errorf("could not find ollama app")
  1037. }
  1038. path := strings.Split(link, "Ollama.app")
  1039. if err := exec.Command("/usr/bin/open", "-a", path[0]+"Ollama.app").Run(); err != nil {
  1040. return err
  1041. }
  1042. // wait for the server to start
  1043. timeout := time.After(5 * time.Second)
  1044. tick := time.Tick(500 * time.Millisecond)
  1045. for {
  1046. select {
  1047. case <-timeout:
  1048. return errors.New("timed out waiting for server to start")
  1049. case <-tick:
  1050. if err := client.Heartbeat(ctx); err == nil {
  1051. return nil // server has started
  1052. }
  1053. }
  1054. }
  1055. }
  1056. func checkServerHeartbeat(cmd *cobra.Command, _ []string) error {
  1057. client, err := api.ClientFromEnvironment()
  1058. if err != nil {
  1059. return err
  1060. }
  1061. if err := client.Heartbeat(cmd.Context()); err != nil {
  1062. if !strings.Contains(err.Error(), "connection refused") {
  1063. return err
  1064. }
  1065. if runtime.GOOS == "darwin" {
  1066. if err := startMacApp(cmd.Context(), client); err != nil {
  1067. return fmt.Errorf("could not connect to ollama app, is it running?")
  1068. }
  1069. } else {
  1070. return fmt.Errorf("could not connect to ollama server, run 'ollama serve' to start it")
  1071. }
  1072. }
  1073. return nil
  1074. }
  1075. func versionHandler(cmd *cobra.Command, _ []string) {
  1076. client, err := api.ClientFromEnvironment()
  1077. if err != nil {
  1078. return
  1079. }
  1080. serverVersion, err := client.Version(cmd.Context())
  1081. if err != nil {
  1082. fmt.Println("Warning: could not connect to a running Ollama instance")
  1083. }
  1084. if serverVersion != "" {
  1085. fmt.Printf("ollama version is %s\n", serverVersion)
  1086. }
  1087. if serverVersion != version.Version {
  1088. fmt.Printf("Warning: client version is %s\n", version.Version)
  1089. }
  1090. }
  1091. func NewCLI() *cobra.Command {
  1092. log.SetFlags(log.LstdFlags | log.Lshortfile)
  1093. cobra.EnableCommandSorting = false
  1094. rootCmd := &cobra.Command{
  1095. Use: "ollama",
  1096. Short: "Large language model runner",
  1097. SilenceUsage: true,
  1098. SilenceErrors: true,
  1099. CompletionOptions: cobra.CompletionOptions{
  1100. DisableDefaultCmd: true,
  1101. },
  1102. Run: func(cmd *cobra.Command, args []string) {
  1103. if version, _ := cmd.Flags().GetBool("version"); version {
  1104. versionHandler(cmd, args)
  1105. return
  1106. }
  1107. cmd.Print(cmd.UsageString())
  1108. },
  1109. }
  1110. rootCmd.Flags().BoolP("version", "v", false, "Show version information")
  1111. createCmd := &cobra.Command{
  1112. Use: "create MODEL",
  1113. Short: "Create a model from a Modelfile",
  1114. Args: cobra.ExactArgs(1),
  1115. PreRunE: checkServerHeartbeat,
  1116. RunE: CreateHandler,
  1117. }
  1118. createCmd.Flags().StringP("file", "f", "Modelfile", "Name of the Modelfile (default \"Modelfile\")")
  1119. showCmd := &cobra.Command{
  1120. Use: "show MODEL",
  1121. Short: "Show information for a model",
  1122. Args: cobra.ExactArgs(1),
  1123. PreRunE: checkServerHeartbeat,
  1124. RunE: ShowHandler,
  1125. }
  1126. showCmd.Flags().Bool("license", false, "Show license of a model")
  1127. showCmd.Flags().Bool("modelfile", false, "Show Modelfile of a model")
  1128. showCmd.Flags().Bool("parameters", false, "Show parameters of a model")
  1129. showCmd.Flags().Bool("template", false, "Show template of a model")
  1130. showCmd.Flags().Bool("system", false, "Show system message of a model")
  1131. runCmd := &cobra.Command{
  1132. Use: "run MODEL [PROMPT]",
  1133. Short: "Run a model",
  1134. Args: cobra.MinimumNArgs(1),
  1135. PreRunE: checkServerHeartbeat,
  1136. RunE: RunHandler,
  1137. }
  1138. runCmd.Flags().Bool("verbose", false, "Show timings for response")
  1139. runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1140. runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
  1141. runCmd.Flags().String("format", "", "Response format (e.g. json)")
  1142. serveCmd := &cobra.Command{
  1143. Use: "serve",
  1144. Aliases: []string{"start"},
  1145. Short: "Start ollama",
  1146. Args: cobra.ExactArgs(0),
  1147. RunE: RunServer,
  1148. }
  1149. pullCmd := &cobra.Command{
  1150. Use: "pull MODEL",
  1151. Short: "Pull a model from a registry",
  1152. Args: cobra.ExactArgs(1),
  1153. PreRunE: checkServerHeartbeat,
  1154. RunE: PullHandler,
  1155. }
  1156. pullCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1157. pushCmd := &cobra.Command{
  1158. Use: "push MODEL",
  1159. Short: "Push a model to a registry",
  1160. Args: cobra.ExactArgs(1),
  1161. PreRunE: checkServerHeartbeat,
  1162. RunE: PushHandler,
  1163. }
  1164. pushCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1165. listCmd := &cobra.Command{
  1166. Use: "list",
  1167. Aliases: []string{"ls"},
  1168. Short: "List models",
  1169. PreRunE: checkServerHeartbeat,
  1170. RunE: ListHandler,
  1171. }
  1172. copyCmd := &cobra.Command{
  1173. Use: "cp SOURCE TARGET",
  1174. Short: "Copy a model",
  1175. Args: cobra.ExactArgs(2),
  1176. PreRunE: checkServerHeartbeat,
  1177. RunE: CopyHandler,
  1178. }
  1179. deleteCmd := &cobra.Command{
  1180. Use: "rm MODEL [MODEL...]",
  1181. Short: "Remove a model",
  1182. Args: cobra.MinimumNArgs(1),
  1183. PreRunE: checkServerHeartbeat,
  1184. RunE: DeleteHandler,
  1185. }
  1186. rootCmd.AddCommand(
  1187. serveCmd,
  1188. createCmd,
  1189. showCmd,
  1190. runCmd,
  1191. pullCmd,
  1192. pushCmd,
  1193. listCmd,
  1194. copyCmd,
  1195. deleteCmd,
  1196. )
  1197. return rootCmd
  1198. }