cmd.go 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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, "")
  554. fmt.Fprintln(os.Stderr, "Use \"\"\" to begin a multi-line message.")
  555. fmt.Fprintln(os.Stderr, "")
  556. }
  557. usageSet := func() {
  558. fmt.Fprintln(os.Stderr, "Available Commands:")
  559. fmt.Fprintln(os.Stderr, " /set parameter ... Set a parameter")
  560. fmt.Fprintln(os.Stderr, " /set system <string> Set system message")
  561. fmt.Fprintln(os.Stderr, " /set template <string> Set prompt template")
  562. fmt.Fprintln(os.Stderr, " /set history Enable history")
  563. fmt.Fprintln(os.Stderr, " /set nohistory Disable history")
  564. fmt.Fprintln(os.Stderr, " /set wordwrap Enable wordwrap")
  565. fmt.Fprintln(os.Stderr, " /set nowordwrap Disable wordwrap")
  566. fmt.Fprintln(os.Stderr, " /set format json Enable JSON mode")
  567. fmt.Fprintln(os.Stderr, " /set noformat Disable formatting")
  568. fmt.Fprintln(os.Stderr, " /set verbose Show LLM stats")
  569. fmt.Fprintln(os.Stderr, " /set quiet Disable LLM stats")
  570. fmt.Fprintln(os.Stderr, "")
  571. }
  572. usageShow := func() {
  573. fmt.Fprintln(os.Stderr, "Available Commands:")
  574. fmt.Fprintln(os.Stderr, " /show license Show model license")
  575. fmt.Fprintln(os.Stderr, " /show modelfile Show Modelfile for this model")
  576. fmt.Fprintln(os.Stderr, " /show parameters Show parameters for this model")
  577. fmt.Fprintln(os.Stderr, " /show system Show system message")
  578. fmt.Fprintln(os.Stderr, " /show template Show prompt template")
  579. fmt.Fprintln(os.Stderr, "")
  580. }
  581. // only list out the most common parameters
  582. usageParameters := func() {
  583. fmt.Fprintln(os.Stderr, "Available Parameters:")
  584. fmt.Fprintln(os.Stderr, " /set parameter seed <int> Random number seed")
  585. fmt.Fprintln(os.Stderr, " /set parameter num_predict <int> Max number of tokens to predict")
  586. fmt.Fprintln(os.Stderr, " /set parameter top_k <int> Pick from top k num of tokens")
  587. fmt.Fprintln(os.Stderr, " /set parameter top_p <float> Pick token based on sum of probabilities")
  588. fmt.Fprintln(os.Stderr, " /set parameter num_ctx <int> Set the context size")
  589. fmt.Fprintln(os.Stderr, " /set parameter temperature <float> Set creativity level")
  590. fmt.Fprintln(os.Stderr, " /set parameter repeat_penalty <float> How strongly to penalize repetitions")
  591. fmt.Fprintln(os.Stderr, " /set parameter repeat_last_n <int> Set how far back to look for repetitions")
  592. fmt.Fprintln(os.Stderr, " /set parameter num_gpu <int> The number of layers to send to the GPU")
  593. fmt.Fprintln(os.Stderr, " /set parameter stop \"<string>\", ... Set the stop parameters")
  594. fmt.Fprintln(os.Stderr, "")
  595. }
  596. scanner, err := readline.New(readline.Prompt{
  597. Prompt: ">>> ",
  598. AltPrompt: "... ",
  599. Placeholder: "Send a message (/? for help)",
  600. AltPlaceholder: `Use """ to end multi-line input`,
  601. })
  602. if err != nil {
  603. return err
  604. }
  605. fmt.Print(readline.StartBracketedPaste)
  606. defer fmt.Printf(readline.EndBracketedPaste)
  607. var multiline MultilineState
  608. var prompt string
  609. for {
  610. line, err := scanner.Readline()
  611. switch {
  612. case errors.Is(err, io.EOF):
  613. fmt.Println()
  614. return nil
  615. case errors.Is(err, readline.ErrInterrupt):
  616. if line == "" {
  617. fmt.Println("\nUse Ctrl-D or /bye to exit.")
  618. }
  619. scanner.Prompt.UseAlt = false
  620. prompt = ""
  621. continue
  622. case err != nil:
  623. return err
  624. }
  625. switch {
  626. case strings.HasPrefix(prompt, `"""`):
  627. // if the prompt so far starts with """ then we're in multiline mode
  628. // and we need to keep reading until we find a line that ends with """
  629. cut, found := strings.CutSuffix(line, `"""`)
  630. prompt += cut
  631. if !found {
  632. prompt += "\n"
  633. continue
  634. }
  635. prompt = strings.TrimPrefix(prompt, `"""`)
  636. scanner.Prompt.UseAlt = false
  637. switch multiline {
  638. case MultilineSystem:
  639. opts.System = prompt
  640. prompt = ""
  641. fmt.Println("Set system message.")
  642. case MultilineTemplate:
  643. opts.Template = prompt
  644. prompt = ""
  645. fmt.Println("Set prompt template.")
  646. }
  647. multiline = MultilineNone
  648. case strings.HasPrefix(line, `"""`) && len(prompt) == 0:
  649. scanner.Prompt.UseAlt = true
  650. multiline = MultilinePrompt
  651. prompt += line + "\n"
  652. continue
  653. case scanner.Pasting:
  654. prompt += line + "\n"
  655. continue
  656. case strings.HasPrefix(line, "/list"):
  657. args := strings.Fields(line)
  658. if err := ListHandler(cmd, args[1:]); err != nil {
  659. return err
  660. }
  661. case strings.HasPrefix(line, "/set"):
  662. args := strings.Fields(line)
  663. if len(args) > 1 {
  664. switch args[1] {
  665. case "history":
  666. scanner.HistoryEnable()
  667. case "nohistory":
  668. scanner.HistoryDisable()
  669. case "wordwrap":
  670. opts.WordWrap = true
  671. fmt.Println("Set 'wordwrap' mode.")
  672. case "nowordwrap":
  673. opts.WordWrap = false
  674. fmt.Println("Set 'nowordwrap' mode.")
  675. case "verbose":
  676. cmd.Flags().Set("verbose", "true")
  677. fmt.Println("Set 'verbose' mode.")
  678. case "quiet":
  679. cmd.Flags().Set("verbose", "false")
  680. fmt.Println("Set 'quiet' mode.")
  681. case "format":
  682. if len(args) < 3 || args[2] != "json" {
  683. fmt.Println("Invalid or missing format. For 'json' mode use '/set format json'")
  684. } else {
  685. opts.Format = args[2]
  686. fmt.Printf("Set format to '%s' mode.\n", args[2])
  687. }
  688. case "noformat":
  689. opts.Format = ""
  690. fmt.Println("Disabled format.")
  691. case "parameter":
  692. if len(args) < 4 {
  693. usageParameters()
  694. continue
  695. }
  696. var params []string
  697. for _, p := range args[3:] {
  698. params = append(params, p)
  699. }
  700. fp, err := api.FormatParams(map[string][]string{args[2]: params})
  701. if err != nil {
  702. fmt.Printf("Couldn't set parameter: %q\n\n", err)
  703. continue
  704. }
  705. fmt.Printf("Set parameter '%s' to '%s'\n\n", args[2], strings.Join(params, ", "))
  706. opts.Options[args[2]] = fp[args[2]]
  707. case "system", "template":
  708. if len(args) < 3 {
  709. usageSet()
  710. continue
  711. }
  712. line := strings.Join(args[2:], " ")
  713. line = strings.TrimPrefix(line, `"""`)
  714. if strings.HasPrefix(args[2], `"""`) {
  715. cut, found := strings.CutSuffix(line, `"""`)
  716. prompt += cut
  717. if found {
  718. if args[1] == "system" {
  719. opts.System = prompt
  720. fmt.Println("Set system message.")
  721. } else {
  722. opts.Template = prompt
  723. fmt.Println("Set prompt template.")
  724. }
  725. prompt = ""
  726. } else {
  727. prompt = `"""` + prompt + "\n"
  728. if args[1] == "system" {
  729. multiline = MultilineSystem
  730. } else {
  731. multiline = MultilineTemplate
  732. }
  733. scanner.Prompt.UseAlt = true
  734. }
  735. } else {
  736. opts.System = line
  737. fmt.Println("Set system message.")
  738. }
  739. default:
  740. fmt.Printf("Unknown command '/set %s'. Type /? for help\n", args[1])
  741. }
  742. } else {
  743. usageSet()
  744. }
  745. case strings.HasPrefix(line, "/show"):
  746. args := strings.Fields(line)
  747. if len(args) > 1 {
  748. client, err := api.ClientFromEnvironment()
  749. if err != nil {
  750. fmt.Println("error: couldn't connect to ollama server")
  751. return err
  752. }
  753. resp, err := client.Show(cmd.Context(), &api.ShowRequest{Name: opts.Model})
  754. if err != nil {
  755. fmt.Println("error: couldn't get model")
  756. return err
  757. }
  758. switch args[1] {
  759. case "license":
  760. if resp.License == "" {
  761. fmt.Print("No license was specified for this model.\n\n")
  762. } else {
  763. fmt.Println(resp.License)
  764. }
  765. case "modelfile":
  766. fmt.Println(resp.Modelfile)
  767. case "parameters":
  768. if resp.Parameters == "" {
  769. fmt.Print("No parameters were specified for this model.\n\n")
  770. } else {
  771. if len(opts.Options) > 0 {
  772. fmt.Println("User defined parameters:")
  773. for k, v := range opts.Options {
  774. fmt.Printf("%-*s %v\n", 30, k, v)
  775. }
  776. fmt.Println()
  777. }
  778. fmt.Println("Model defined parameters:")
  779. fmt.Println(resp.Parameters)
  780. }
  781. case "system":
  782. switch {
  783. case opts.System != "":
  784. fmt.Println(opts.System + "\n")
  785. case resp.System != "":
  786. fmt.Println(resp.System + "\n")
  787. default:
  788. fmt.Print("No system message was specified for this model.\n\n")
  789. }
  790. case "template":
  791. switch {
  792. case opts.Template != "":
  793. fmt.Println(opts.Template + "\n")
  794. case resp.Template != "":
  795. fmt.Println(resp.Template)
  796. default:
  797. fmt.Print("No prompt template was specified for this model.\n\n")
  798. }
  799. default:
  800. fmt.Printf("Unknown command '/show %s'. Type /? for help\n", args[1])
  801. }
  802. } else {
  803. usageShow()
  804. }
  805. case strings.HasPrefix(line, "/help"), strings.HasPrefix(line, "/?"):
  806. args := strings.Fields(line)
  807. if len(args) > 1 {
  808. switch args[1] {
  809. case "set", "/set":
  810. usageSet()
  811. case "show", "/show":
  812. usageShow()
  813. }
  814. } else {
  815. usage()
  816. }
  817. case line == "/exit", line == "/bye":
  818. return nil
  819. case strings.HasPrefix(line, "/"):
  820. args := strings.Fields(line)
  821. isFile := false
  822. if multiModal {
  823. for _, f := range extractFileNames(line) {
  824. if strings.HasPrefix(f, args[0]) {
  825. isFile = true
  826. break
  827. }
  828. }
  829. }
  830. if isFile {
  831. prompt += line
  832. } else {
  833. fmt.Printf("Unknown command '%s'. Type /? for help\n", args[0])
  834. continue
  835. }
  836. default:
  837. prompt += line
  838. }
  839. if len(prompt) > 0 && multiline == MultilineNone {
  840. opts.Prompt = prompt
  841. if multiModal {
  842. newPrompt, images, err := extractFileData(prompt)
  843. if err != nil {
  844. return err
  845. }
  846. opts.Prompt = newPrompt
  847. // reset the context if we find another image
  848. if len(images) > 0 {
  849. opts.Images = images
  850. ctx := cmd.Context()
  851. ctx = context.WithValue(ctx, generateContextKey("context"), []int{})
  852. cmd.SetContext(ctx)
  853. }
  854. if len(opts.Images) == 0 {
  855. fmt.Println("This model requires you to add a jpeg, png, or svg image.")
  856. fmt.Println()
  857. prompt = ""
  858. continue
  859. }
  860. }
  861. if err := generate(cmd, opts); err != nil {
  862. return err
  863. }
  864. prompt = ""
  865. }
  866. }
  867. }
  868. func normalizeFilePath(fp string) string {
  869. // Define a map of escaped characters and their replacements
  870. replacements := map[string]string{
  871. "\\ ": " ", // Escaped space
  872. "\\(": "(", // Escaped left parenthesis
  873. "\\)": ")", // Escaped right parenthesis
  874. "\\[": "[", // Escaped left square bracket
  875. "\\]": "]", // Escaped right square bracket
  876. "\\{": "{", // Escaped left curly brace
  877. "\\}": "}", // Escaped right curly brace
  878. "\\$": "$", // Escaped dollar sign
  879. "\\&": "&", // Escaped ampersand
  880. "\\;": ";", // Escaped semicolon
  881. "\\'": "'", // Escaped single quote
  882. "\\\\": "\\", // Escaped backslash
  883. "\\*": "*", // Escaped asterisk
  884. "\\?": "?", // Escaped question mark
  885. }
  886. for escaped, actual := range replacements {
  887. fp = strings.ReplaceAll(fp, escaped, actual)
  888. }
  889. return fp
  890. }
  891. func extractFileNames(input string) []string {
  892. // Regex to match file paths starting with / or ./ and include escaped spaces (\ or %20)
  893. // and followed by more characters and a file extension
  894. regexPattern := `(?:\./|/)[\S\\ ]+?\.(?i:jpg|jpeg|png|svg)\b`
  895. re := regexp.MustCompile(regexPattern)
  896. return re.FindAllString(input, -1)
  897. }
  898. func extractFileData(input string) (string, []ImageData, error) {
  899. filePaths := extractFileNames(input)
  900. var imgs []ImageData
  901. for _, fp := range filePaths {
  902. nfp := normalizeFilePath(fp)
  903. data, err := getImageData(nfp)
  904. if err != nil {
  905. if os.IsNotExist(err) {
  906. continue
  907. }
  908. fmt.Printf("Couldn't process image: %q\n", err)
  909. return "", imgs, err
  910. }
  911. fmt.Printf("Added image '%s'\n", nfp)
  912. input = strings.ReplaceAll(input, fp, "")
  913. imgs = append(imgs, data)
  914. }
  915. return input, imgs, nil
  916. }
  917. func RunServer(cmd *cobra.Command, _ []string) error {
  918. host, port, err := net.SplitHostPort(os.Getenv("OLLAMA_HOST"))
  919. if err != nil {
  920. host, port = "127.0.0.1", "11434"
  921. if ip := net.ParseIP(strings.Trim(os.Getenv("OLLAMA_HOST"), "[]")); ip != nil {
  922. host = ip.String()
  923. }
  924. }
  925. if err := initializeKeypair(); err != nil {
  926. return err
  927. }
  928. ln, err := net.Listen("tcp", net.JoinHostPort(host, port))
  929. if err != nil {
  930. return err
  931. }
  932. return server.Serve(ln)
  933. }
  934. func getImageData(filePath string) ([]byte, error) {
  935. file, err := os.Open(filePath)
  936. if err != nil {
  937. return nil, err
  938. }
  939. defer file.Close()
  940. buf := make([]byte, 512)
  941. _, err = file.Read(buf)
  942. if err != nil {
  943. return nil, err
  944. }
  945. contentType := http.DetectContentType(buf)
  946. allowedTypes := []string{"image/jpeg", "image/jpg", "image/svg+xml", "image/png"}
  947. if !slices.Contains(allowedTypes, contentType) {
  948. return nil, fmt.Errorf("invalid image type: %s", contentType)
  949. }
  950. info, err := file.Stat()
  951. if err != nil {
  952. return nil, err
  953. }
  954. // Check if the file size exceeds 100MB
  955. var maxSize int64 = 100 * 1024 * 1024 // 100MB in bytes
  956. if info.Size() > maxSize {
  957. return nil, fmt.Errorf("file size exceeds maximum limit (100MB)")
  958. }
  959. buf = make([]byte, info.Size())
  960. _, err = file.Seek(0, 0)
  961. if err != nil {
  962. return nil, err
  963. }
  964. _, err = io.ReadFull(file, buf)
  965. if err != nil {
  966. return nil, err
  967. }
  968. return buf, nil
  969. }
  970. func initializeKeypair() error {
  971. home, err := os.UserHomeDir()
  972. if err != nil {
  973. return err
  974. }
  975. privKeyPath := filepath.Join(home, ".ollama", "id_ed25519")
  976. pubKeyPath := filepath.Join(home, ".ollama", "id_ed25519.pub")
  977. _, err = os.Stat(privKeyPath)
  978. if os.IsNotExist(err) {
  979. fmt.Printf("Couldn't find '%s'. Generating new private key.\n", privKeyPath)
  980. _, privKey, err := ed25519.GenerateKey(rand.Reader)
  981. if err != nil {
  982. return err
  983. }
  984. privKeyBytes, err := format.OpenSSHPrivateKey(privKey, "")
  985. if err != nil {
  986. return err
  987. }
  988. err = os.MkdirAll(filepath.Dir(privKeyPath), 0o755)
  989. if err != nil {
  990. return fmt.Errorf("could not create directory %w", err)
  991. }
  992. err = os.WriteFile(privKeyPath, pem.EncodeToMemory(privKeyBytes), 0o600)
  993. if err != nil {
  994. return err
  995. }
  996. sshPrivateKey, err := ssh.NewSignerFromKey(privKey)
  997. if err != nil {
  998. return err
  999. }
  1000. pubKeyData := ssh.MarshalAuthorizedKey(sshPrivateKey.PublicKey())
  1001. err = os.WriteFile(pubKeyPath, pubKeyData, 0o644)
  1002. if err != nil {
  1003. return err
  1004. }
  1005. fmt.Printf("Your new public key is: \n\n%s\n", string(pubKeyData))
  1006. }
  1007. return nil
  1008. }
  1009. func startMacApp(ctx context.Context, client *api.Client) error {
  1010. exe, err := os.Executable()
  1011. if err != nil {
  1012. return err
  1013. }
  1014. link, err := os.Readlink(exe)
  1015. if err != nil {
  1016. return err
  1017. }
  1018. if !strings.Contains(link, "Ollama.app") {
  1019. return fmt.Errorf("could not find ollama app")
  1020. }
  1021. path := strings.Split(link, "Ollama.app")
  1022. if err := exec.Command("/usr/bin/open", "-a", path[0]+"Ollama.app").Run(); err != nil {
  1023. return err
  1024. }
  1025. // wait for the server to start
  1026. timeout := time.After(5 * time.Second)
  1027. tick := time.Tick(500 * time.Millisecond)
  1028. for {
  1029. select {
  1030. case <-timeout:
  1031. return errors.New("timed out waiting for server to start")
  1032. case <-tick:
  1033. if err := client.Heartbeat(ctx); err == nil {
  1034. return nil // server has started
  1035. }
  1036. }
  1037. }
  1038. }
  1039. func checkServerHeartbeat(cmd *cobra.Command, _ []string) error {
  1040. client, err := api.ClientFromEnvironment()
  1041. if err != nil {
  1042. return err
  1043. }
  1044. if err := client.Heartbeat(cmd.Context()); err != nil {
  1045. if !strings.Contains(err.Error(), "connection refused") {
  1046. return err
  1047. }
  1048. if runtime.GOOS == "darwin" {
  1049. if err := startMacApp(cmd.Context(), client); err != nil {
  1050. return fmt.Errorf("could not connect to ollama app, is it running?")
  1051. }
  1052. } else {
  1053. return fmt.Errorf("could not connect to ollama server, run 'ollama serve' to start it")
  1054. }
  1055. }
  1056. return nil
  1057. }
  1058. func versionHandler(cmd *cobra.Command, _ []string) {
  1059. client, err := api.ClientFromEnvironment()
  1060. if err != nil {
  1061. return
  1062. }
  1063. serverVersion, err := client.Version(cmd.Context())
  1064. if err != nil {
  1065. fmt.Println("Warning: could not connect to a running Ollama instance")
  1066. }
  1067. if serverVersion != "" {
  1068. fmt.Printf("ollama version is %s\n", serverVersion)
  1069. }
  1070. if serverVersion != version.Version {
  1071. fmt.Printf("Warning: client version is %s\n", version.Version)
  1072. }
  1073. }
  1074. func NewCLI() *cobra.Command {
  1075. log.SetFlags(log.LstdFlags | log.Lshortfile)
  1076. cobra.EnableCommandSorting = false
  1077. rootCmd := &cobra.Command{
  1078. Use: "ollama",
  1079. Short: "Large language model runner",
  1080. SilenceUsage: true,
  1081. SilenceErrors: true,
  1082. CompletionOptions: cobra.CompletionOptions{
  1083. DisableDefaultCmd: true,
  1084. },
  1085. Run: func(cmd *cobra.Command, args []string) {
  1086. if version, _ := cmd.Flags().GetBool("version"); version {
  1087. versionHandler(cmd, args)
  1088. return
  1089. }
  1090. cmd.Print(cmd.UsageString())
  1091. },
  1092. }
  1093. rootCmd.Flags().BoolP("version", "v", false, "Show version information")
  1094. createCmd := &cobra.Command{
  1095. Use: "create MODEL",
  1096. Short: "Create a model from a Modelfile",
  1097. Args: cobra.ExactArgs(1),
  1098. PreRunE: checkServerHeartbeat,
  1099. RunE: CreateHandler,
  1100. }
  1101. createCmd.Flags().StringP("file", "f", "Modelfile", "Name of the Modelfile (default \"Modelfile\")")
  1102. showCmd := &cobra.Command{
  1103. Use: "show MODEL",
  1104. Short: "Show information for a model",
  1105. Args: cobra.ExactArgs(1),
  1106. PreRunE: checkServerHeartbeat,
  1107. RunE: ShowHandler,
  1108. }
  1109. showCmd.Flags().Bool("license", false, "Show license of a model")
  1110. showCmd.Flags().Bool("modelfile", false, "Show Modelfile of a model")
  1111. showCmd.Flags().Bool("parameters", false, "Show parameters of a model")
  1112. showCmd.Flags().Bool("template", false, "Show template of a model")
  1113. showCmd.Flags().Bool("system", false, "Show system message of a model")
  1114. runCmd := &cobra.Command{
  1115. Use: "run MODEL [PROMPT]",
  1116. Short: "Run a model",
  1117. Args: cobra.MinimumNArgs(1),
  1118. PreRunE: checkServerHeartbeat,
  1119. RunE: RunHandler,
  1120. }
  1121. runCmd.Flags().Bool("verbose", false, "Show timings for response")
  1122. runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1123. runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
  1124. runCmd.Flags().String("format", "", "Response format (e.g. json)")
  1125. serveCmd := &cobra.Command{
  1126. Use: "serve",
  1127. Aliases: []string{"start"},
  1128. Short: "Start ollama",
  1129. Args: cobra.ExactArgs(0),
  1130. RunE: RunServer,
  1131. }
  1132. pullCmd := &cobra.Command{
  1133. Use: "pull MODEL",
  1134. Short: "Pull a model from a registry",
  1135. Args: cobra.ExactArgs(1),
  1136. PreRunE: checkServerHeartbeat,
  1137. RunE: PullHandler,
  1138. }
  1139. pullCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1140. pushCmd := &cobra.Command{
  1141. Use: "push MODEL",
  1142. Short: "Push a model to a registry",
  1143. Args: cobra.ExactArgs(1),
  1144. PreRunE: checkServerHeartbeat,
  1145. RunE: PushHandler,
  1146. }
  1147. pushCmd.Flags().Bool("insecure", false, "Use an insecure registry")
  1148. listCmd := &cobra.Command{
  1149. Use: "list",
  1150. Aliases: []string{"ls"},
  1151. Short: "List models",
  1152. PreRunE: checkServerHeartbeat,
  1153. RunE: ListHandler,
  1154. }
  1155. copyCmd := &cobra.Command{
  1156. Use: "cp SOURCE TARGET",
  1157. Short: "Copy a model",
  1158. Args: cobra.ExactArgs(2),
  1159. PreRunE: checkServerHeartbeat,
  1160. RunE: CopyHandler,
  1161. }
  1162. deleteCmd := &cobra.Command{
  1163. Use: "rm MODEL [MODEL...]",
  1164. Short: "Remove a model",
  1165. Args: cobra.MinimumNArgs(1),
  1166. PreRunE: checkServerHeartbeat,
  1167. RunE: DeleteHandler,
  1168. }
  1169. rootCmd.AddCommand(
  1170. serveCmd,
  1171. createCmd,
  1172. showCmd,
  1173. runCmd,
  1174. pullCmd,
  1175. pushCmd,
  1176. listCmd,
  1177. copyCmd,
  1178. deleteCmd,
  1179. )
  1180. return rootCmd
  1181. }