models.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package server
  2. import (
  3. "fmt"
  4. "os"
  5. "path"
  6. "path/filepath"
  7. "strconv"
  8. "github.com/jmorganca/ollama/api"
  9. )
  10. type Model struct {
  11. Name string `json:"name"`
  12. ModelPath string
  13. Prompt string
  14. Options api.Options
  15. DisplayName string `json:"display_name"`
  16. Parameters string `json:"parameters"`
  17. URL string `json:"url"`
  18. ShortDescription string `json:"short_description"`
  19. Description string `json:"description"`
  20. PublishedBy string `json:"published_by"`
  21. OriginalAuthor string `json:"original_author"`
  22. OriginalURL string `json:"original_url"`
  23. License string `json:"license"`
  24. }
  25. func saveModel(model *Model, fn func(total, completed int64)) error {
  26. // this models cache directory is created by the server on startup
  27. client := &http.Client{}
  28. req, err := http.NewRequest("GET", model.URL, nil)
  29. if err != nil {
  30. return fmt.Errorf("failed to download model: %w", err)
  31. }
  32. var size int64
  33. // completed file doesn't exist, check partial file
  34. fi, err := os.Stat(model.TempFile())
  35. switch {
  36. case errors.Is(err, os.ErrNotExist):
  37. // noop, file doesn't exist so create it
  38. case err != nil:
  39. return fmt.Errorf("stat: %w", err)
  40. default:
  41. size = fi.Size()
  42. }
  43. req.Header.Add("Range", fmt.Sprintf("bytes=%d-", size))
  44. resp, err := client.Do(req)
  45. if err != nil {
  46. return fmt.Errorf("failed to download model: %w", err)
  47. }
  48. defer resp.Body.Close()
  49. if resp.StatusCode >= 400 {
  50. return fmt.Errorf("failed to download model: %s", resp.Status)
  51. }
  52. out, err := os.OpenFile(model.TempFile(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
  53. if err != nil {
  54. panic(err)
  55. }
  56. defer out.Close()
  57. remaining, _ := strconv.ParseInt(resp.Header.Get("Content-Length"), 10, 64)
  58. completed := size
  59. total := remaining + completed
  60. for {
  61. fn(total, completed)
  62. if completed >= total {
  63. return os.Rename(model.TempFile(), model.FullName())
  64. }
  65. n, err := io.CopyN(out, resp.Body, 8192)
  66. if err != nil && !errors.Is(err, io.EOF) {
  67. return err
  68. }
  69. completed += n
  70. }
  71. }