config.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. package envconfig
  2. import (
  3. "fmt"
  4. "log/slog"
  5. "os"
  6. "path/filepath"
  7. "runtime"
  8. "strconv"
  9. "strings"
  10. )
  11. var (
  12. // Set via OLLAMA_ORIGINS in the environment
  13. AllowOrigins []string
  14. // Set via OLLAMA_DEBUG in the environment
  15. Debug bool
  16. // Experimental flash attention
  17. FlashAttention bool
  18. // Set via OLLAMA_KEEP_ALIVE in the environment
  19. KeepAlive string
  20. // Set via OLLAMA_LLM_LIBRARY in the environment
  21. LLMLibrary string
  22. // Set via OLLAMA_MAX_LOADED_MODELS in the environment
  23. MaxRunners int
  24. // Set via OLLAMA_MAX_QUEUE in the environment
  25. MaxQueuedRequests int
  26. // Set via OLLAMA_MAX_VRAM in the environment
  27. MaxVRAM uint64
  28. // Set via OLLAMA_NOHISTORY in the environment
  29. NoHistory bool
  30. // Set via OLLAMA_NOPRUNE in the environment
  31. NoPrune bool
  32. // Set via OLLAMA_NUM_PARALLEL in the environment
  33. NumParallel int
  34. // Set via OLLAMA_RUNNERS_DIR in the environment
  35. RunnersDir string
  36. // Set via OLLAMA_TMPDIR in the environment
  37. TmpDir string
  38. )
  39. type EnvVar struct {
  40. Name string
  41. Value any
  42. Description string
  43. }
  44. func AsMap() map[string]EnvVar {
  45. return map[string]EnvVar{
  46. "OLLAMA_DEBUG": {"OLLAMA_DEBUG", Debug, "Show additional debug information (e.g. OLLAMA_DEBUG=1)"},
  47. "OLLAMA_FLASH_ATTENTION": {"OLLAMA_FLASH_ATTENTION", FlashAttention, "Enabled flash attention"},
  48. "OLLAMA_HOST": {"OLLAMA_HOST", "", "IP Address for the ollama server (default 127.0.0.1:11434)"},
  49. "OLLAMA_KEEP_ALIVE": {"OLLAMA_KEEP_ALIVE", KeepAlive, "The duration that models stay loaded in memory (default \"5m\")"},
  50. "OLLAMA_LLM_LIBRARY": {"OLLAMA_ORIGINS", LLMLibrary, ""},
  51. "OLLAMA_MAX_LOADED_MODELS": {"OLLAMA_MAX_LOADED_MODELS", MaxRunners, "Maximum number of loaded models (default 1)"},
  52. "OLLAMA_MAX_QUEUE": {"OLLAMA_MAX_QUEUE", MaxQueuedRequests, "Maximum number of queued requests"},
  53. "OLLAMA_MAX_VRAM": {"OLLAMA_MAX_VRAM", MaxVRAM, ""},
  54. "OLLAMA_MODELS": {"OLLAMA_MODELS", "", "The path to the models directory"},
  55. "OLLAMA_NOHISTORY": {"OLLAMA_NOHISTORY", NoHistory, "Do not preserve readline history"},
  56. "OLLAMA_NOPRUNE": {"OLLAMA_NOPRUNE", NoPrune, "Do not prune model blobs on startup"},
  57. "OLLAMA_NUM_PARALLEL": {"OLLAMA_NUM_PARALLEL", NumParallel, "Maximum number of parallel requests (default 1)"},
  58. "OLLAMA_ORIGINS": {"OLLAMA_ORIGINS", AllowOrigins, "A comma separated list of allowed origins"},
  59. "OLLAMA_RUNNERS_DIR": {"OLLAMA_RUNNERS_DIR", RunnersDir, ""},
  60. "OLLAMA_TMPDIR": {"OLLAMA_TMPDIR", TmpDir, "Location for temporary files"},
  61. }
  62. }
  63. func Values() map[string]string {
  64. vals := make(map[string]string)
  65. for k, v := range AsMap() {
  66. vals[k] = fmt.Sprintf("%v", v.Value)
  67. }
  68. return vals
  69. }
  70. var defaultAllowOrigins = []string{
  71. "localhost",
  72. "127.0.0.1",
  73. "0.0.0.0",
  74. }
  75. // Clean quotes and spaces from the value
  76. func clean(key string) string {
  77. return strings.Trim(os.Getenv(key), "\"' ")
  78. }
  79. func init() {
  80. // default values
  81. NumParallel = 1
  82. MaxRunners = 1
  83. MaxQueuedRequests = 512
  84. LoadConfig()
  85. }
  86. func LoadConfig() {
  87. if debug := clean("OLLAMA_DEBUG"); debug != "" {
  88. d, err := strconv.ParseBool(debug)
  89. if err == nil {
  90. Debug = d
  91. } else {
  92. Debug = true
  93. }
  94. }
  95. if fa := clean("OLLAMA_FLASH_ATTENTION"); fa != "" {
  96. d, err := strconv.ParseBool(fa)
  97. if err == nil {
  98. FlashAttention = d
  99. }
  100. }
  101. RunnersDir = clean("OLLAMA_RUNNERS_DIR")
  102. if runtime.GOOS == "windows" && RunnersDir == "" {
  103. // On Windows we do not carry the payloads inside the main executable
  104. appExe, err := os.Executable()
  105. if err != nil {
  106. slog.Error("failed to lookup executable path", "error", err)
  107. }
  108. cwd, err := os.Getwd()
  109. if err != nil {
  110. slog.Error("failed to lookup working directory", "error", err)
  111. }
  112. var paths []string
  113. for _, root := range []string{filepath.Dir(appExe), cwd} {
  114. paths = append(paths,
  115. filepath.Join(root),
  116. filepath.Join(root, "windows-"+runtime.GOARCH),
  117. filepath.Join(root, "dist", "windows-"+runtime.GOARCH),
  118. )
  119. }
  120. // Try a few variations to improve developer experience when building from source in the local tree
  121. for _, p := range paths {
  122. candidate := filepath.Join(p, "ollama_runners")
  123. _, err := os.Stat(candidate)
  124. if err == nil {
  125. RunnersDir = candidate
  126. break
  127. }
  128. }
  129. if RunnersDir == "" {
  130. slog.Error("unable to locate llm runner directory. Set OLLAMA_RUNNERS_DIR to the location of 'ollama_runners'")
  131. }
  132. }
  133. TmpDir = clean("OLLAMA_TMPDIR")
  134. userLimit := clean("OLLAMA_MAX_VRAM")
  135. if userLimit != "" {
  136. avail, err := strconv.ParseUint(userLimit, 10, 64)
  137. if err != nil {
  138. slog.Error("invalid setting, ignoring", "OLLAMA_MAX_VRAM", userLimit, "error", err)
  139. } else {
  140. MaxVRAM = avail
  141. }
  142. }
  143. LLMLibrary = clean("OLLAMA_LLM_LIBRARY")
  144. if onp := clean("OLLAMA_NUM_PARALLEL"); onp != "" {
  145. val, err := strconv.Atoi(onp)
  146. if err != nil || val <= 0 {
  147. slog.Error("invalid setting must be greater than zero", "OLLAMA_NUM_PARALLEL", onp, "error", err)
  148. } else {
  149. NumParallel = val
  150. }
  151. }
  152. if nohistory := clean("OLLAMA_NOHISTORY"); nohistory != "" {
  153. NoHistory = true
  154. }
  155. if noprune := clean("OLLAMA_NOPRUNE"); noprune != "" {
  156. NoPrune = true
  157. }
  158. if origins := clean("OLLAMA_ORIGINS"); origins != "" {
  159. AllowOrigins = strings.Split(origins, ",")
  160. }
  161. for _, allowOrigin := range defaultAllowOrigins {
  162. AllowOrigins = append(AllowOrigins,
  163. fmt.Sprintf("http://%s", allowOrigin),
  164. fmt.Sprintf("https://%s", allowOrigin),
  165. fmt.Sprintf("http://%s:*", allowOrigin),
  166. fmt.Sprintf("https://%s:*", allowOrigin),
  167. )
  168. }
  169. maxRunners := clean("OLLAMA_MAX_LOADED_MODELS")
  170. if maxRunners != "" {
  171. m, err := strconv.Atoi(maxRunners)
  172. if err != nil {
  173. slog.Error("invalid setting", "OLLAMA_MAX_LOADED_MODELS", maxRunners, "error", err)
  174. } else {
  175. MaxRunners = m
  176. }
  177. }
  178. if onp := os.Getenv("OLLAMA_MAX_QUEUE"); onp != "" {
  179. p, err := strconv.Atoi(onp)
  180. if err != nil || p <= 0 {
  181. slog.Error("invalid setting", "OLLAMA_MAX_QUEUE", onp, "error", err)
  182. } else {
  183. MaxQueuedRequests = p
  184. }
  185. }
  186. KeepAlive = clean("OLLAMA_KEEP_ALIVE")
  187. }