2023-11-29 19:00:37 +00:00
|
|
|
package llm
|
|
|
|
|
|
|
|
import (
|
2023-12-19 02:32:04 +00:00
|
|
|
"embed"
|
2023-12-23 19:35:44 +00:00
|
|
|
"errors"
|
2023-11-29 19:00:37 +00:00
|
|
|
"fmt"
|
2023-12-23 19:35:44 +00:00
|
|
|
"io"
|
|
|
|
"io/fs"
|
2023-12-19 02:32:04 +00:00
|
|
|
"log"
|
|
|
|
"os"
|
2023-12-23 19:35:44 +00:00
|
|
|
"path/filepath"
|
2023-11-29 19:00:37 +00:00
|
|
|
|
|
|
|
"github.com/jmorganca/ollama/api"
|
|
|
|
)
|
|
|
|
|
2024-01-04 17:40:15 +00:00
|
|
|
//go:embed llama.cpp/ggml-metal.metal
|
2023-12-19 02:32:04 +00:00
|
|
|
var libEmbed embed.FS
|
2023-11-29 19:00:37 +00:00
|
|
|
|
2024-01-08 21:42:00 +00:00
|
|
|
func newDynamicShimExtServer(library, model string, adapters, projectors []string, opts api.Options) (extServer, error) {
|
2023-11-29 19:00:37 +00:00
|
|
|
// should never happen...
|
2023-12-20 18:36:01 +00:00
|
|
|
return nil, fmt.Errorf("Dynamic library loading not supported on Mac")
|
2023-11-29 19:00:37 +00:00
|
|
|
}
|
|
|
|
|
2023-12-19 02:32:04 +00:00
|
|
|
func nativeInit(workdir string) error {
|
2024-01-04 17:40:15 +00:00
|
|
|
err := extractPayloadFiles(workdir, "llama.cpp/ggml-metal.metal")
|
2023-12-19 02:32:04 +00:00
|
|
|
if err != nil {
|
|
|
|
if err == payloadMissing {
|
|
|
|
// TODO perhaps consider this a hard failure on arm macs?
|
|
|
|
log.Printf("ggml-meta.metal payload missing")
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
os.Setenv("GGML_METAL_PATH_RESOURCES", workdir)
|
2023-11-29 19:00:37 +00:00
|
|
|
return nil
|
|
|
|
}
|
2023-12-23 19:35:44 +00:00
|
|
|
|
|
|
|
func extractPayloadFiles(workDir, glob string) error {
|
|
|
|
files, err := fs.Glob(libEmbed, glob)
|
|
|
|
if err != nil || len(files) == 0 {
|
|
|
|
return payloadMissing
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
srcFile, err := libEmbed.Open(file)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("read payload %s: %v", file, err)
|
|
|
|
}
|
|
|
|
defer srcFile.Close()
|
|
|
|
if err := os.MkdirAll(workDir, 0o755); err != nil {
|
|
|
|
return fmt.Errorf("create payload temp dir %s: %v", workDir, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
destFile := filepath.Join(workDir, filepath.Base(file))
|
|
|
|
_, err = os.Stat(destFile)
|
|
|
|
switch {
|
|
|
|
case errors.Is(err, os.ErrNotExist):
|
|
|
|
destFile, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o755)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("write payload %s: %v", file, err)
|
|
|
|
}
|
|
|
|
defer destFile.Close()
|
|
|
|
if _, err := io.Copy(destFile, srcFile); err != nil {
|
|
|
|
return fmt.Errorf("copy payload %s: %v", file, err)
|
|
|
|
}
|
|
|
|
case err != nil:
|
|
|
|
return fmt.Errorf("stat payload %s: %v", file, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|