shim_darwin.go 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. package llm
  2. import (
  3. "embed"
  4. "errors"
  5. "fmt"
  6. "io"
  7. "io/fs"
  8. "log"
  9. "os"
  10. "path/filepath"
  11. "github.com/jmorganca/ollama/api"
  12. )
  13. //go:embed llama.cpp/gguf/ggml-metal.metal
  14. var libEmbed embed.FS
  15. func newDynamicShimExtServer(library, model string, adapters, projectors []string, numLayers int64, opts api.Options) (extServer, error) {
  16. // should never happen...
  17. return nil, fmt.Errorf("Dynamic library loading not supported on Mac")
  18. }
  19. func nativeInit(workdir string) error {
  20. err := extractPayloadFiles(workdir, "llama.cpp/gguf/ggml-metal.metal")
  21. if err != nil {
  22. if err == payloadMissing {
  23. // TODO perhaps consider this a hard failure on arm macs?
  24. log.Printf("ggml-meta.metal payload missing")
  25. return nil
  26. }
  27. return err
  28. }
  29. os.Setenv("GGML_METAL_PATH_RESOURCES", workdir)
  30. return nil
  31. }
  32. func extractPayloadFiles(workDir, glob string) error {
  33. files, err := fs.Glob(libEmbed, glob)
  34. if err != nil || len(files) == 0 {
  35. return payloadMissing
  36. }
  37. for _, file := range files {
  38. srcFile, err := libEmbed.Open(file)
  39. if err != nil {
  40. return fmt.Errorf("read payload %s: %v", file, err)
  41. }
  42. defer srcFile.Close()
  43. if err := os.MkdirAll(workDir, 0o755); err != nil {
  44. return fmt.Errorf("create payload temp dir %s: %v", workDir, err)
  45. }
  46. destFile := filepath.Join(workDir, filepath.Base(file))
  47. _, err = os.Stat(destFile)
  48. switch {
  49. case errors.Is(err, os.ErrNotExist):
  50. destFile, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755)
  51. if err != nil {
  52. return fmt.Errorf("write payload %s: %v", file, err)
  53. }
  54. defer destFile.Close()
  55. if _, err := io.Copy(destFile, srcFile); err != nil {
  56. return fmt.Errorf("copy payload %s: %v", file, err)
  57. }
  58. case err != nil:
  59. return fmt.Errorf("stat payload %s: %v", file, err)
  60. }
  61. }
  62. return nil
  63. }