Compare commits
6 Commits
v0.3.9
...
pdevine/im
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb576a6b23 | ||
|
|
15b7ff3a89 | ||
|
|
3ad243466b | ||
|
|
a13e583c49 | ||
|
|
3c1994d0ee | ||
|
|
1b2da3829d |
@@ -32,10 +32,6 @@ linters:
|
|||||||
linters-settings:
|
linters-settings:
|
||||||
gci:
|
gci:
|
||||||
sections: [standard, default, localmodule]
|
sections: [standard, default, localmodule]
|
||||||
staticcheck:
|
|
||||||
checks:
|
|
||||||
- all
|
|
||||||
- -SA1019 # omit Deprecated check
|
|
||||||
severity:
|
severity:
|
||||||
default-severity: error
|
default-severity: error
|
||||||
rules:
|
rules:
|
||||||
|
|||||||
@@ -337,8 +337,6 @@ See the [API documentation](./docs/api.md) for all endpoints.
|
|||||||
- [Pacman](https://archlinux.org/packages/extra/x86_64/ollama/)
|
- [Pacman](https://archlinux.org/packages/extra/x86_64/ollama/)
|
||||||
- [Helm Chart](https://artifacthub.io/packages/helm/ollama-helm/ollama)
|
- [Helm Chart](https://artifacthub.io/packages/helm/ollama-helm/ollama)
|
||||||
- [Guix channel](https://codeberg.org/tusharhero/ollama-guix)
|
- [Guix channel](https://codeberg.org/tusharhero/ollama-guix)
|
||||||
- [Nix package](https://search.nixos.org/packages?channel=24.05&show=ollama&from=0&size=50&sort=relevance&type=packages&query=ollama)
|
|
||||||
- [Flox](https://flox.dev/blog/ollama-part-one)
|
|
||||||
|
|
||||||
### Libraries
|
### Libraries
|
||||||
|
|
||||||
|
|||||||
16
api/types.go
16
api/types.go
@@ -296,17 +296,15 @@ type EmbeddingResponse struct {
|
|||||||
// CreateRequest is the request passed to [Client.Create].
|
// CreateRequest is the request passed to [Client.Create].
|
||||||
type CreateRequest struct {
|
type CreateRequest struct {
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
|
Path string `json:"path"`
|
||||||
Modelfile string `json:"modelfile"`
|
Modelfile string `json:"modelfile"`
|
||||||
Stream *bool `json:"stream,omitempty"`
|
Stream *bool `json:"stream,omitempty"`
|
||||||
Quantize string `json:"quantize,omitempty"`
|
Quantize string `json:"quantize,omitempty"`
|
||||||
|
|
||||||
// Deprecated: set the model name with Model instead
|
// Name is deprecated, see Model
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
|
||||||
// Deprecated: set the file content with Modelfile instead
|
// Quantization is deprecated, see Quantize
|
||||||
Path string `json:"path"`
|
|
||||||
|
|
||||||
// Deprecated: use Quantize instead
|
|
||||||
Quantization string `json:"quantization,omitempty"`
|
Quantization string `json:"quantization,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +312,7 @@ type CreateRequest struct {
|
|||||||
type DeleteRequest struct {
|
type DeleteRequest struct {
|
||||||
Model string `json:"model"`
|
Model string `json:"model"`
|
||||||
|
|
||||||
// Deprecated: set the model name with Model instead
|
// Name is deprecated, see Model
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,7 +327,7 @@ type ShowRequest struct {
|
|||||||
|
|
||||||
Options map[string]interface{} `json:"options"`
|
Options map[string]interface{} `json:"options"`
|
||||||
|
|
||||||
// Deprecated: set the model name with Model instead
|
// Name is deprecated, see Model
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +359,7 @@ type PullRequest struct {
|
|||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Stream *bool `json:"stream,omitempty"`
|
Stream *bool `json:"stream,omitempty"`
|
||||||
|
|
||||||
// Deprecated: set the model name with Model instead
|
// Name is deprecated, see Model
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -382,7 +380,7 @@ type PushRequest struct {
|
|||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Stream *bool `json:"stream,omitempty"`
|
Stream *bool `json:"stream,omitempty"`
|
||||||
|
|
||||||
// Deprecated: set the model name with Model instead
|
// Name is deprecated, see Model
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ DialogFontSize=12
|
|||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: ".\app.exe"; DestDir: "{app}"; DestName: "{#MyAppExeName}" ; Flags: ignoreversion 64bit
|
Source: ".\app.exe"; DestDir: "{app}"; DestName: "{#MyAppExeName}" ; Flags: ignoreversion 64bit
|
||||||
Source: "..\ollama.exe"; DestDir: "{app}"; Flags: ignoreversion 64bit
|
Source: "..\ollama.exe"; DestDir: "{app}\bin"; Flags: ignoreversion 64bit
|
||||||
Source: "..\dist\windows-{#ARCH}\lib\ollama\runners\*"; DestDir: "{app}\lib\ollama\runners"; Flags: ignoreversion 64bit recursesubdirs
|
Source: "..\dist\windows-{#ARCH}\lib\ollama\runners\*"; DestDir: "{app}\lib\ollama\runners"; Flags: ignoreversion 64bit recursesubdirs
|
||||||
Source: "..\dist\ollama_welcome.ps1"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\dist\ollama_welcome.ps1"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: ".\assets\app.ico"; DestDir: "{app}"; Flags: ignoreversion
|
Source: ".\assets\app.ico"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
@@ -99,7 +99,7 @@ Name: "{userstartup}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilen
|
|||||||
Name: "{userprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\app.ico"
|
Name: "{userprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; IconFilename: "{app}\app.ico"
|
||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
Filename: "{cmd}"; Parameters: "/C set PATH={app};%PATH% & ""{app}\{#MyAppExeName}"""; Flags: postinstall nowait runhidden
|
Filename: "{cmd}"; Parameters: "/C set PATH={app}\bin;%PATH% & ""{app}\{#MyAppExeName}"""; Flags: postinstall nowait runhidden
|
||||||
|
|
||||||
[UninstallRun]
|
[UninstallRun]
|
||||||
; Filename: "{cmd}"; Parameters: "/C ""taskkill /im ''{#MyAppExeName}'' /f /t"; Flags: runhidden
|
; Filename: "{cmd}"; Parameters: "/C ""taskkill /im ''{#MyAppExeName}'' /f /t"; Flags: runhidden
|
||||||
@@ -134,8 +134,8 @@ SetupAppRunningError=Another Ollama installer is running.%n%nPlease cancel or fi
|
|||||||
|
|
||||||
[Registry]
|
[Registry]
|
||||||
Root: HKCU; Subkey: "Environment"; \
|
Root: HKCU; Subkey: "Environment"; \
|
||||||
ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}"; \
|
ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}\bin"; \
|
||||||
Check: NeedsAddPath('{app}')
|
Check: NeedsAddPath('{app}\bin')
|
||||||
|
|
||||||
[Code]
|
[Code]
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ func TestMain(m *testing.M) {
|
|||||||
os.Exit(m.Run())
|
os.Exit(m.Run())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConvertModel(t *testing.T) {
|
func TestConvertFull(t *testing.T) {
|
||||||
cases := []string{
|
cases := []string{
|
||||||
"Meta-Llama-3-8B-Instruct",
|
"Meta-Llama-3-8B-Instruct",
|
||||||
"Meta-Llama-3.1-8B-Instruct",
|
"Meta-Llama-3.1-8B-Instruct",
|
||||||
@@ -140,107 +140,6 @@ func TestConvertModel(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestConvertInvalidDatatype(t *testing.T) {
|
|
||||||
f, err := os.CreateTemp(t.TempDir(), "testmodel")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
tempDir := t.TempDir()
|
|
||||||
generateSafetensorTestData(t, tempDir)
|
|
||||||
|
|
||||||
err = ConvertModel(os.DirFS(tempDir), f)
|
|
||||||
if err == nil || err.Error() != "unsupported safetensors model" {
|
|
||||||
t.Errorf("expected error but didn't get one")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateSafetensorTestData(t *testing.T, tempDir string) {
|
|
||||||
type tensorData struct {
|
|
||||||
Offsets []int `json:"data_offsets"`
|
|
||||||
Type string `json:"dtype"`
|
|
||||||
Shape []int `json:"shape"`
|
|
||||||
}
|
|
||||||
offset := 4096 * 14336
|
|
||||||
|
|
||||||
td := map[string]*tensorData{}
|
|
||||||
td["model.layers.0.mlp.down_proj.weight"] = &tensorData{
|
|
||||||
Offsets: []int{0, offset},
|
|
||||||
Type: "I8",
|
|
||||||
Shape: []int{4096, 14336},
|
|
||||||
}
|
|
||||||
td["model.layers.0.mlp.down_proj.weight_format"] = &tensorData{
|
|
||||||
Offsets: []int{offset, offset},
|
|
||||||
Type: "U8",
|
|
||||||
Shape: []int{},
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := json.Marshal(td)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
|
|
||||||
l := int64(len(data))
|
|
||||||
err = binary.Write(&buf, binary.LittleEndian, l)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = buf.Write(data)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fdata, err := os.Create(filepath.Join(tempDir, "model-00001-of-00001.safetensors"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer fdata.Close()
|
|
||||||
|
|
||||||
_, err = fdata.Write(buf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
configData := `
|
|
||||||
{
|
|
||||||
"architectures": [
|
|
||||||
"LlamaForCausalLM"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
f, err := os.Create(filepath.Join(tempDir, "config.json"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
_, err = f.WriteString(configData)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenizerData := `
|
|
||||||
{
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
f, err = os.Create(filepath.Join(tempDir, "tokenizer.json"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
_, err = f.WriteString(tokenizerData)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConvertAdapter(t *testing.T) {
|
func TestConvertAdapter(t *testing.T) {
|
||||||
type AdapterCase struct {
|
type AdapterCase struct {
|
||||||
Name string
|
Name string
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/fs"
|
"io/fs"
|
||||||
@@ -51,10 +50,6 @@ func parseSafetensors(fsys fs.FS, replacer *strings.Replacer, ps ...string) ([]T
|
|||||||
|
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
if value := headers[key]; value.Type != "" {
|
if value := headers[key]; value.Type != "" {
|
||||||
// bitsandbytes quantized models are unsupported
|
|
||||||
if len(value.Shape) == 0 {
|
|
||||||
return nil, errors.New("unsupported safetensors model")
|
|
||||||
}
|
|
||||||
ts = append(ts, safetensor{
|
ts = append(ts, safetensor{
|
||||||
fs: fsys,
|
fs: fsys,
|
||||||
path: p,
|
path: p,
|
||||||
|
|||||||
@@ -100,21 +100,8 @@ func parseTokenizer(fsys fs.FS, specialTokenTypes []string) (*Tokenizer, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if template, ok := p["chat_template"]; ok {
|
if template, ok := p["chat_template"]; ok {
|
||||||
var s []struct {
|
if err := json.Unmarshal(template, &t.Template); err != nil {
|
||||||
Name string `json:"name"`
|
return nil, err
|
||||||
Template string `json:"template"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal(template, &t.Template); err == nil {
|
|
||||||
// noop
|
|
||||||
} else if err := json.Unmarshal(template, &s); err == nil {
|
|
||||||
for _, e := range s {
|
|
||||||
if e.Name == "default" {
|
|
||||||
t.Template = e.Template
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, fmt.Errorf("invalid chat_template: %w", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +141,7 @@ func parseTokenizer(fsys fs.FS, specialTokenTypes []string) (*Tokenizer, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
type tokenizer struct {
|
type tokenizer struct {
|
||||||
|
Version string `json:"version"`
|
||||||
AddedTokens []token `json:"added_tokens"`
|
AddedTokens []token `json:"added_tokens"`
|
||||||
Model struct {
|
Model struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
@@ -251,7 +239,7 @@ func parseVocabulary(fsys fs.FS) (*Vocabulary, error) {
|
|||||||
return pattern.Func(fsys)
|
return pattern.Func(fsys)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, errors.New("unknown tokenizer format")
|
return nil, errors.New("unknown tensor format")
|
||||||
}
|
}
|
||||||
|
|
||||||
type SpecialVocabulary struct {
|
type SpecialVocabulary struct {
|
||||||
|
|||||||
@@ -1,208 +0,0 @@
|
|||||||
package convert
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
|
||||||
)
|
|
||||||
|
|
||||||
func createTokenizerFS(t *testing.T, dir string, files map[string]io.Reader) fs.FS {
|
|
||||||
t.Helper()
|
|
||||||
|
|
||||||
for k, v := range files {
|
|
||||||
if err := func() error {
|
|
||||||
f, err := os.Create(filepath.Join(dir, k))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer f.Close()
|
|
||||||
|
|
||||||
if _, err := io.Copy(f, v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}(); err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return os.DirFS(dir)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseTokenizer(t *testing.T) {
|
|
||||||
cases := []struct {
|
|
||||||
name string
|
|
||||||
fsys fs.FS
|
|
||||||
specialTokenTypes []string
|
|
||||||
want *Tokenizer
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "string chat template",
|
|
||||||
fsys: createTokenizerFS(t, t.TempDir(), map[string]io.Reader{
|
|
||||||
"tokenizer.json": strings.NewReader(`{}`),
|
|
||||||
"tokenizer_config.json": strings.NewReader(`{
|
|
||||||
"chat_template": "<default template>"
|
|
||||||
}`),
|
|
||||||
}),
|
|
||||||
want: &Tokenizer{
|
|
||||||
Vocabulary: &Vocabulary{Model: "gpt2"},
|
|
||||||
Pre: "default",
|
|
||||||
Template: "<default template>",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list chat template",
|
|
||||||
fsys: createTokenizerFS(t, t.TempDir(), map[string]io.Reader{
|
|
||||||
"tokenizer.json": strings.NewReader(`{}`),
|
|
||||||
"tokenizer_config.json": strings.NewReader(`{
|
|
||||||
"chat_template": [
|
|
||||||
{
|
|
||||||
"name": "default",
|
|
||||||
"template": "<default template>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "tools",
|
|
||||||
"template": "<tools template>"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`),
|
|
||||||
}),
|
|
||||||
want: &Tokenizer{
|
|
||||||
Vocabulary: &Vocabulary{Model: "gpt2"},
|
|
||||||
Pre: "default",
|
|
||||||
Template: "<default template>",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "added tokens",
|
|
||||||
fsys: createTokenizerFS(t, t.TempDir(), map[string]io.Reader{
|
|
||||||
"tokenizer.json": strings.NewReader(`{
|
|
||||||
"added_tokens": [
|
|
||||||
{
|
|
||||||
"id": 999,
|
|
||||||
"content": "<unused999>",
|
|
||||||
"special": false
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}`),
|
|
||||||
}),
|
|
||||||
want: &Tokenizer{
|
|
||||||
Vocabulary: &Vocabulary{
|
|
||||||
Model: "gpt2",
|
|
||||||
Tokens: []string{"<unused999>"},
|
|
||||||
Scores: []float32{999},
|
|
||||||
Types: []int32{4},
|
|
||||||
},
|
|
||||||
Pre: "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "added tokens overlap vocab",
|
|
||||||
fsys: createTokenizerFS(t, t.TempDir(), map[string]io.Reader{
|
|
||||||
"tokenizer.json": strings.NewReader(`{
|
|
||||||
"added_tokens": [
|
|
||||||
{
|
|
||||||
"id": 0,
|
|
||||||
"content": "<pad>",
|
|
||||||
"special": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"model": {
|
|
||||||
"vocab": {
|
|
||||||
"<pad>": 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`),
|
|
||||||
}),
|
|
||||||
want: &Tokenizer{
|
|
||||||
Vocabulary: &Vocabulary{
|
|
||||||
Model: "gpt2",
|
|
||||||
Tokens: []string{"<pad>"},
|
|
||||||
Scores: []float32{0},
|
|
||||||
Types: []int32{3},
|
|
||||||
},
|
|
||||||
Pre: "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "special token types",
|
|
||||||
fsys: createTokenizerFS(t, t.TempDir(), map[string]io.Reader{
|
|
||||||
"tokenizer.json": strings.NewReader(`{
|
|
||||||
"added_tokens": [
|
|
||||||
{
|
|
||||||
"id": 0,
|
|
||||||
"content": "<pad>",
|
|
||||||
"special": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 1,
|
|
||||||
"content": "<eos>",
|
|
||||||
"special": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 2,
|
|
||||||
"content": "<bos>",
|
|
||||||
"special": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": 3,
|
|
||||||
"content": "<unk>",
|
|
||||||
"special": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"model": {
|
|
||||||
"vocab": {
|
|
||||||
"<pad>": 0,
|
|
||||||
"<eos>": 1,
|
|
||||||
"<bos>": 2,
|
|
||||||
"<unk>": 3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}`),
|
|
||||||
"tokenizer_config.json": strings.NewReader(`{
|
|
||||||
"add_bos_token": true,
|
|
||||||
"add_eos_token": false,
|
|
||||||
"bos_token": "<bos>",
|
|
||||||
"eos_token": "<eos>",
|
|
||||||
"pad_token": "<pad>",
|
|
||||||
"unk_token": "<unk>"
|
|
||||||
}`),
|
|
||||||
}),
|
|
||||||
specialTokenTypes: []string{"pad", "eos", "bos", "unk"},
|
|
||||||
want: &Tokenizer{
|
|
||||||
Vocabulary: &Vocabulary{
|
|
||||||
Model: "gpt2",
|
|
||||||
Tokens: []string{"<pad>", "<eos>", "<bos>", "<unk>"},
|
|
||||||
Scores: []float32{0, 1, 2, 3},
|
|
||||||
Types: []int32{3, 3, 3, 3},
|
|
||||||
},
|
|
||||||
SpecialVocabulary: []*SpecialVocabulary{
|
|
||||||
{Type: "pad", Content: "<pad>", ID: 0, AddToken: false},
|
|
||||||
{Type: "eos", Content: "<eos>", ID: 1, AddToken: false},
|
|
||||||
{Type: "bos", Content: "<bos>", ID: 2, AddToken: true},
|
|
||||||
{Type: "unk", Content: "<unk>", ID: 3, AddToken: false},
|
|
||||||
},
|
|
||||||
Pre: "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tt := range cases {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
tokenizer, err := parseTokenizer(tt.fsys, tt.specialTokenTypes)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if diff := cmp.Diff(tt.want, tokenizer); diff != "" {
|
|
||||||
t.Errorf("unexpected tokenizer (-want +got):\n%s", diff)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 141 KiB |
@@ -158,7 +158,7 @@ You can share any model you have created by pushing it to [ollama.com](https://o
|
|||||||
|
|
||||||
First, use your browser to go to the [Ollama Sign-Up](https://ollama.com/signup) page. If you already have an account, you can skip this step.
|
First, use your browser to go to the [Ollama Sign-Up](https://ollama.com/signup) page. If you already have an account, you can skip this step.
|
||||||
|
|
||||||
<img src="images/signup.png" alt="Sign-Up" width="40%">
|

|
||||||
|
|
||||||
The `Username` field will be used as part of your model's name (e.g. `jmorganca/mymodel`), so make sure you are comfortable with the username that you have selected.
|
The `Username` field will be used as part of your model's name (e.g. `jmorganca/mymodel`), so make sure you are comfortable with the username that you have selected.
|
||||||
|
|
||||||
@@ -166,7 +166,7 @@ Now that you have created an account and are signed-in, go to the [Ollama Keys S
|
|||||||
|
|
||||||
Follow the directions on the page to determine where your Ollama Public Key is located.
|
Follow the directions on the page to determine where your Ollama Public Key is located.
|
||||||
|
|
||||||
<img src="images/ollama-keys.png" alt="Ollama Keys" width="80%">
|

|
||||||
|
|
||||||
Click on the `Add Ollama Public Key` button, and copy and paste the contents of your Ollama Public Key into the text field.
|
Click on the `Add Ollama Public Key` button, and copy and paste the contents of your Ollama Public Key into the text field.
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,6 @@ Download and extract the Linux package:
|
|||||||
curl -fsSL https://ollama.com/download/ollama-linux-amd64.tgz | sudo tar zx -C /usr
|
curl -fsSL https://ollama.com/download/ollama-linux-amd64.tgz | sudo tar zx -C /usr
|
||||||
```
|
```
|
||||||
|
|
||||||
If you have an AMD GPU, also download and extract the ROCm package into the same location
|
|
||||||
```bash
|
|
||||||
curl -fsSL https://ollama.com/download/ollama-linux-amd64-rocm.tgz | sudo tar zx -C /usr
|
|
||||||
```
|
|
||||||
|
|
||||||
### Adding Ollama as a startup service (recommended)
|
### Adding Ollama as a startup service (recommended)
|
||||||
|
|
||||||
Create a user for Ollama:
|
Create a user for Ollama:
|
||||||
|
|||||||
@@ -11,9 +11,8 @@ A model file is the blueprint to create and share models with Ollama.
|
|||||||
- [Examples](#examples)
|
- [Examples](#examples)
|
||||||
- [Instructions](#instructions)
|
- [Instructions](#instructions)
|
||||||
- [FROM (Required)](#from-required)
|
- [FROM (Required)](#from-required)
|
||||||
- [Build from llama3.1](#build-from-llama31)
|
- [Build from llama3](#build-from-llama3)
|
||||||
- [Build from a Safetensors model](#build-from-a-safetensors-model)
|
- [Build from a bin file](#build-from-a-bin-file)
|
||||||
- [Build from a GGUF file](#build-from-a-gguf-file)
|
|
||||||
- [PARAMETER](#parameter)
|
- [PARAMETER](#parameter)
|
||||||
- [Valid Parameters and Values](#valid-parameters-and-values)
|
- [Valid Parameters and Values](#valid-parameters-and-values)
|
||||||
- [TEMPLATE](#template)
|
- [TEMPLATE](#template)
|
||||||
@@ -100,39 +99,22 @@ The `FROM` instruction defines the base model to use when creating a model.
|
|||||||
FROM <model name>:<tag>
|
FROM <model name>:<tag>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Build from llama3.1
|
#### Build from llama3
|
||||||
|
|
||||||
```modelfile
|
```modelfile
|
||||||
FROM llama3.1
|
FROM llama3
|
||||||
```
|
```
|
||||||
|
|
||||||
A list of available base models:
|
A list of available base models:
|
||||||
<https://github.com/ollama/ollama#model-library>
|
<https://github.com/ollama/ollama#model-library>
|
||||||
Additional models can be found at:
|
|
||||||
<https://ollama.com/library>
|
|
||||||
|
|
||||||
#### Build from a Safetensors model
|
#### Build from a `bin` file
|
||||||
|
|
||||||
```modelfile
|
|
||||||
FROM <model directory>
|
|
||||||
```
|
|
||||||
|
|
||||||
The model directory should contain the Safetensors weights for a supported architecture.
|
|
||||||
|
|
||||||
Currently supported model architectures:
|
|
||||||
* Llama (including Llama 2, Llama 3, and Llama 3.1)
|
|
||||||
* Mistral (including Mistral 1, Mistral 2, and Mixtral)
|
|
||||||
* Gemma (including Gemma 1 and Gemma 2)
|
|
||||||
* Phi3
|
|
||||||
|
|
||||||
#### Build from a GGUF file
|
|
||||||
|
|
||||||
```modelfile
|
```modelfile
|
||||||
FROM ./ollama-model.bin
|
FROM ./ollama-model.bin
|
||||||
```
|
```
|
||||||
|
|
||||||
The GGUF bin file location should be specified as an absolute path or relative to the `Modelfile` location.
|
This bin file location should be specified as an absolute path or relative to the `Modelfile` location.
|
||||||
|
|
||||||
|
|
||||||
### PARAMETER
|
### PARAMETER
|
||||||
|
|
||||||
@@ -192,20 +174,7 @@ SYSTEM """<system message>"""
|
|||||||
|
|
||||||
### ADAPTER
|
### ADAPTER
|
||||||
|
|
||||||
The `ADAPTER` instruction specifies a fine tuned LoRA adapter that should apply to the base model. The value of the adapter should be an absolute path or a path relative to the Modelfile. The base model should be specified with a `FROM` instruction. If the base model is not the same as the base model that the adapter was tuned from the behaviour will be erratic.
|
The `ADAPTER` instruction is an optional instruction that specifies any LoRA adapter that should apply to the base model. The value of this instruction should be an absolute path or a path relative to the Modelfile and the file must be in a GGML file format. The adapter should be tuned from the base model otherwise the behaviour is undefined.
|
||||||
|
|
||||||
#### Safetensor adapter
|
|
||||||
|
|
||||||
```modelfile
|
|
||||||
ADAPTER <path to safetensor adapter>
|
|
||||||
```
|
|
||||||
|
|
||||||
Currently supported Safetensor adapters:
|
|
||||||
* Llama (including Llama 2, Llama 3, and Llama 3.1)
|
|
||||||
* Mistral (including Mistral 1, Mistral 2, and Mixtral)
|
|
||||||
* Gemma (including Gemma 1 and Gemma 2)
|
|
||||||
|
|
||||||
#### GGUF adapter
|
|
||||||
|
|
||||||
```modelfile
|
```modelfile
|
||||||
ADAPTER ./ollama-lora.bin
|
ADAPTER ./ollama-lora.bin
|
||||||
|
|||||||
@@ -300,28 +300,3 @@ curl http://localhost:11434/v1/chat/completions \
|
|||||||
]
|
]
|
||||||
}'
|
}'
|
||||||
```
|
```
|
||||||
|
|
||||||
### Setting the context size
|
|
||||||
|
|
||||||
The OpenAI API does not have a way of setting the context size for a model. If you need to change the context size, create a `Modelfile` which looks like:
|
|
||||||
|
|
||||||
```modelfile
|
|
||||||
FROM <some model>
|
|
||||||
PARAMETER num_ctx <context size>
|
|
||||||
```
|
|
||||||
|
|
||||||
Use the `ollama create mymodel` command to create a new model with the updated context size. Call the API with the updated model name:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
curl http://localhost:11434/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-d '{
|
|
||||||
"model": "mymodel",
|
|
||||||
"messages": [
|
|
||||||
{
|
|
||||||
"role": "user",
|
|
||||||
"content": "Hello!"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}'
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -30,7 +30,9 @@ func Host() *url.URL {
|
|||||||
defaultPort = "443"
|
defaultPort = "443"
|
||||||
}
|
}
|
||||||
|
|
||||||
hostport, path, _ := strings.Cut(hostport, "/")
|
// trim trailing slashes
|
||||||
|
hostport = strings.TrimRight(hostport, "/")
|
||||||
|
|
||||||
host, port, err := net.SplitHostPort(hostport)
|
host, port, err := net.SplitHostPort(hostport)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
host, port = "127.0.0.1", defaultPort
|
host, port = "127.0.0.1", defaultPort
|
||||||
@@ -43,13 +45,15 @@ func Host() *url.URL {
|
|||||||
|
|
||||||
if n, err := strconv.ParseInt(port, 10, 32); err != nil || n > 65535 || n < 0 {
|
if n, err := strconv.ParseInt(port, 10, 32); err != nil || n > 65535 || n < 0 {
|
||||||
slog.Warn("invalid port, using default", "port", port, "default", defaultPort)
|
slog.Warn("invalid port, using default", "port", port, "default", defaultPort)
|
||||||
port = defaultPort
|
return &url.URL{
|
||||||
|
Scheme: scheme,
|
||||||
|
Host: net.JoinHostPort(host, defaultPort),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &url.URL{
|
return &url.URL{
|
||||||
Scheme: scheme,
|
Scheme: scheme,
|
||||||
Host: net.JoinHostPort(host, port),
|
Host: net.JoinHostPort(host, port),
|
||||||
Path: path,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,7 +190,7 @@ func RunnersDir() (p string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var paths []string
|
var paths []string
|
||||||
for _, root := range []string{filepath.Dir(exe), filepath.Join(filepath.Dir(exe), LibRelativeToExe()), cwd} {
|
for _, root := range []string{filepath.Dir(exe), filepath.Join(filepath.Dir(exe), ".."), cwd} {
|
||||||
paths = append(paths,
|
paths = append(paths,
|
||||||
root,
|
root,
|
||||||
filepath.Join(root, runtime.GOOS+"-"+runtime.GOARCH),
|
filepath.Join(root, runtime.GOOS+"-"+runtime.GOARCH),
|
||||||
@@ -278,12 +282,3 @@ func Values() map[string]string {
|
|||||||
func Var(key string) string {
|
func Var(key string) string {
|
||||||
return strings.Trim(strings.TrimSpace(os.Getenv(key)), "\"'")
|
return strings.Trim(strings.TrimSpace(os.Getenv(key)), "\"'")
|
||||||
}
|
}
|
||||||
|
|
||||||
// On windows, we keep the binary at the top directory, but
|
|
||||||
// other platforms use a "bin" directory, so this returns ".."
|
|
||||||
func LibRelativeToExe() string {
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
return "."
|
|
||||||
}
|
|
||||||
return ".."
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -13,35 +13,34 @@ func TestHost(t *testing.T) {
|
|||||||
value string
|
value string
|
||||||
expect string
|
expect string
|
||||||
}{
|
}{
|
||||||
"empty": {"", "http://127.0.0.1:11434"},
|
"empty": {"", "127.0.0.1:11434"},
|
||||||
"only address": {"1.2.3.4", "http://1.2.3.4:11434"},
|
"only address": {"1.2.3.4", "1.2.3.4:11434"},
|
||||||
"only port": {":1234", "http://:1234"},
|
"only port": {":1234", ":1234"},
|
||||||
"address and port": {"1.2.3.4:1234", "http://1.2.3.4:1234"},
|
"address and port": {"1.2.3.4:1234", "1.2.3.4:1234"},
|
||||||
"hostname": {"example.com", "http://example.com:11434"},
|
"hostname": {"example.com", "example.com:11434"},
|
||||||
"hostname and port": {"example.com:1234", "http://example.com:1234"},
|
"hostname and port": {"example.com:1234", "example.com:1234"},
|
||||||
"zero port": {":0", "http://:0"},
|
"zero port": {":0", ":0"},
|
||||||
"too large port": {":66000", "http://:11434"},
|
"too large port": {":66000", ":11434"},
|
||||||
"too small port": {":-1", "http://:11434"},
|
"too small port": {":-1", ":11434"},
|
||||||
"ipv6 localhost": {"[::1]", "http://[::1]:11434"},
|
"ipv6 localhost": {"[::1]", "[::1]:11434"},
|
||||||
"ipv6 world open": {"[::]", "http://[::]:11434"},
|
"ipv6 world open": {"[::]", "[::]:11434"},
|
||||||
"ipv6 no brackets": {"::1", "http://[::1]:11434"},
|
"ipv6 no brackets": {"::1", "[::1]:11434"},
|
||||||
"ipv6 + port": {"[::1]:1337", "http://[::1]:1337"},
|
"ipv6 + port": {"[::1]:1337", "[::1]:1337"},
|
||||||
"extra space": {" 1.2.3.4 ", "http://1.2.3.4:11434"},
|
"extra space": {" 1.2.3.4 ", "1.2.3.4:11434"},
|
||||||
"extra quotes": {"\"1.2.3.4\"", "http://1.2.3.4:11434"},
|
"extra quotes": {"\"1.2.3.4\"", "1.2.3.4:11434"},
|
||||||
"extra space+quotes": {" \" 1.2.3.4 \" ", "http://1.2.3.4:11434"},
|
"extra space+quotes": {" \" 1.2.3.4 \" ", "1.2.3.4:11434"},
|
||||||
"extra single quotes": {"'1.2.3.4'", "http://1.2.3.4:11434"},
|
"extra single quotes": {"'1.2.3.4'", "1.2.3.4:11434"},
|
||||||
"http": {"http://1.2.3.4", "http://1.2.3.4:80"},
|
"http": {"http://1.2.3.4", "1.2.3.4:80"},
|
||||||
"http port": {"http://1.2.3.4:4321", "http://1.2.3.4:4321"},
|
"http port": {"http://1.2.3.4:4321", "1.2.3.4:4321"},
|
||||||
"https": {"https://1.2.3.4", "https://1.2.3.4:443"},
|
"https": {"https://1.2.3.4", "1.2.3.4:443"},
|
||||||
"https port": {"https://1.2.3.4:4321", "https://1.2.3.4:4321"},
|
"https port": {"https://1.2.3.4:4321", "1.2.3.4:4321"},
|
||||||
"proxy path": {"https://example.com/ollama", "https://example.com:443/ollama"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, tt := range cases {
|
for name, tt := range cases {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
t.Setenv("OLLAMA_HOST", tt.value)
|
t.Setenv("OLLAMA_HOST", tt.value)
|
||||||
if host := Host(); host.String() != tt.expect {
|
if host := Host(); host.Host != tt.expect {
|
||||||
t.Errorf("%s: expected %s, got %s", name, tt.expect, host.String())
|
t.Errorf("%s: expected %s, got %s", name, tt.expect, host.Host)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ollama/ollama/envconfig"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Determine if the given ROCm lib directory is usable by checking for existence of some glob patterns
|
// Determine if the given ROCm lib directory is usable by checking for existence of some glob patterns
|
||||||
@@ -56,7 +54,7 @@ func commonAMDValidateLibDir() (string, error) {
|
|||||||
// Installer payload location if we're running the installed binary
|
// Installer payload location if we're running the installed binary
|
||||||
exe, err := os.Executable()
|
exe, err := os.Executable()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
rocmTargetDir := filepath.Join(filepath.Dir(exe), envconfig.LibRelativeToExe(), "lib", "ollama")
|
rocmTargetDir := filepath.Join(filepath.Dir(exe), "..", "lib", "ollama")
|
||||||
if rocmLibUsable(rocmTargetDir) {
|
if rocmLibUsable(rocmTargetDir) {
|
||||||
slog.Debug("detected ROCM next to ollama executable " + rocmTargetDir)
|
slog.Debug("detected ROCM next to ollama executable " + rocmTargetDir)
|
||||||
return rocmTargetDir, nil
|
return rocmTargetDir, nil
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ func AMDValidateLibDir() (string, error) {
|
|||||||
// Installer payload (if we're running from some other location)
|
// Installer payload (if we're running from some other location)
|
||||||
localAppData := os.Getenv("LOCALAPPDATA")
|
localAppData := os.Getenv("LOCALAPPDATA")
|
||||||
appDir := filepath.Join(localAppData, "Programs", "Ollama")
|
appDir := filepath.Join(localAppData, "Programs", "Ollama")
|
||||||
rocmTargetDir := filepath.Join(appDir, envconfig.LibRelativeToExe(), "lib", "ollama")
|
rocmTargetDir := filepath.Join(appDir, "..", "lib", "ollama")
|
||||||
if rocmLibUsable(rocmTargetDir) {
|
if rocmLibUsable(rocmTargetDir) {
|
||||||
slog.Debug("detected ollama installed ROCm at " + rocmTargetDir)
|
slog.Debug("detected ollama installed ROCm at " + rocmTargetDir)
|
||||||
return rocmTargetDir, nil
|
return rocmTargetDir, nil
|
||||||
|
|||||||
@@ -653,7 +653,7 @@ func LibraryDir() string {
|
|||||||
slog.Warn("failed to lookup working directory", "error", err)
|
slog.Warn("failed to lookup working directory", "error", err)
|
||||||
}
|
}
|
||||||
// Scan for any of our dependeices, and pick first match
|
// Scan for any of our dependeices, and pick first match
|
||||||
for _, root := range []string{filepath.Dir(appExe), filepath.Join(filepath.Dir(appExe), envconfig.LibRelativeToExe()), cwd} {
|
for _, root := range []string{filepath.Dir(appExe), filepath.Join(filepath.Dir(appExe), ".."), cwd} {
|
||||||
libDep := filepath.Join("lib", "ollama")
|
libDep := filepath.Join("lib", "ollama")
|
||||||
if _, err := os.Stat(filepath.Join(root, libDep)); err == nil {
|
if _, err := os.Stat(filepath.Join(root, libDep)); err == nil {
|
||||||
return filepath.Join(root, libDep)
|
return filepath.Join(root, libDep)
|
||||||
|
|||||||
@@ -87,8 +87,6 @@ apply_patches() {
|
|||||||
build() {
|
build() {
|
||||||
cmake -S ${LLAMACPP_DIR} -B ${BUILD_DIR} ${CMAKE_DEFS}
|
cmake -S ${LLAMACPP_DIR} -B ${BUILD_DIR} ${CMAKE_DEFS}
|
||||||
cmake --build ${BUILD_DIR} ${CMAKE_TARGETS} -j8
|
cmake --build ${BUILD_DIR} ${CMAKE_TARGETS} -j8
|
||||||
# remove unnecessary build artifacts
|
|
||||||
rm -f ${BUILD_DIR}/bin/ggml-common.h ${BUILD_DIR}/bin/ggml-metal.metal
|
|
||||||
}
|
}
|
||||||
|
|
||||||
compress() {
|
compress() {
|
||||||
|
|||||||
@@ -409,7 +409,7 @@ func NewLlamaServer(gpus gpu.GpuInfoList, model string, ggml *GGML, adapters, pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
if err = s.cmd.Start(); err != nil {
|
if err = s.cmd.Start(); err != nil {
|
||||||
// Detect permission denied and augment the message about noexec
|
// Detect permission denied and augment them essage about noexec
|
||||||
if errors.Is(err, os.ErrPermission) {
|
if errors.Is(err, os.ErrPermission) {
|
||||||
finalErr = fmt.Errorf("unable to start server %w. %s may have noexec set. Set OLLAMA_TMPDIR for server to a writable executable directory", err, dir)
|
finalErr = fmt.Errorf("unable to start server %w. %s may have noexec set. Set OLLAMA_TMPDIR for server to a writable executable directory", err, dir)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -122,8 +122,8 @@ function buildOllama() {
|
|||||||
/csp "Google Cloud KMS Provider" /kc ${env:KEY_CONTAINER} ollama.exe
|
/csp "Google Cloud KMS Provider" /kc ${env:KEY_CONTAINER} ollama.exe
|
||||||
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
|
if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)}
|
||||||
}
|
}
|
||||||
New-Item -ItemType Directory -Path .\dist\windows-${script:TARGET_ARCH}\ -Force
|
New-Item -ItemType Directory -Path .\dist\windows-${script:TARGET_ARCH}\bin\ -Force
|
||||||
cp .\ollama.exe .\dist\windows-${script:TARGET_ARCH}\
|
cp .\ollama.exe .\dist\windows-${script:TARGET_ARCH}\bin\
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildApp() {
|
function buildApp() {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ if grep -i "centos" /etc/system-release >/dev/null; then
|
|||||||
dnf install -y rh-git227-git
|
dnf install -y rh-git227-git
|
||||||
ln -s /opt/rh/rh-git227/root/usr/bin/git /usr/local/bin/git
|
ln -s /opt/rh/rh-git227/root/usr/bin/git /usr/local/bin/git
|
||||||
fi
|
fi
|
||||||
dnf install -y devtoolset-10-gcc devtoolset-10-gcc-c++ pigz findutils
|
dnf install -y devtoolset-10-gcc devtoolset-10-gcc-c++ pigz
|
||||||
elif grep -i "rocky" /etc/system-release >/dev/null; then
|
elif grep -i "rocky" /etc/system-release >/dev/null; then
|
||||||
# Temporary workaround until rocky 8 AppStream ships GCC 10.4 (10.3 is incompatible with NVCC)
|
# Temporary workaround until rocky 8 AppStream ships GCC 10.4 (10.3 is incompatible with NVCC)
|
||||||
cat << EOF > /etc/yum.repos.d/Rocky-Vault.repo
|
cat << EOF > /etc/yum.repos.d/Rocky-Vault.repo
|
||||||
@@ -45,7 +45,6 @@ EOF
|
|||||||
dnf install -y git \
|
dnf install -y git \
|
||||||
gcc-toolset-10-gcc-10.2.1-8.2.el8 \
|
gcc-toolset-10-gcc-10.2.1-8.2.el8 \
|
||||||
gcc-toolset-10-gcc-c++-10.2.1-8.2.el8 \
|
gcc-toolset-10-gcc-c++-10.2.1-8.2.el8 \
|
||||||
findutils \
|
|
||||||
pigz
|
pigz
|
||||||
else
|
else
|
||||||
echo "ERROR Unexpected distro"
|
echo "ERROR Unexpected distro"
|
||||||
|
|||||||
@@ -139,7 +139,6 @@ The temperature in San Francisco, CA is 70°F and in Toronto, Canada is 20°C.`,
|
|||||||
|
|
||||||
func TestParseFromFileFromLayer(t *testing.T) {
|
func TestParseFromFileFromLayer(t *testing.T) {
|
||||||
tempModels := t.TempDir()
|
tempModels := t.TempDir()
|
||||||
t.Setenv("OLLAMA_MODELS", tempModels)
|
|
||||||
|
|
||||||
file, err := os.CreateTemp(tempModels, "")
|
file, err := os.CreateTemp(tempModels, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -190,7 +189,6 @@ func TestParseFromFileFromLayer(t *testing.T) {
|
|||||||
|
|
||||||
func TestParseLayerFromCopy(t *testing.T) {
|
func TestParseLayerFromCopy(t *testing.T) {
|
||||||
tempModels := t.TempDir()
|
tempModels := t.TempDir()
|
||||||
t.Setenv("OLLAMA_MODELS", tempModels)
|
|
||||||
|
|
||||||
file2, err := os.CreateTemp(tempModels, "")
|
file2, err := os.CreateTemp(tempModels, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -73,6 +73,18 @@ func ParseModelPath(name string) ModelPath {
|
|||||||
|
|
||||||
var errModelPathInvalid = errors.New("invalid model path")
|
var errModelPathInvalid = errors.New("invalid model path")
|
||||||
|
|
||||||
|
func (mp ModelPath) Validate() error {
|
||||||
|
if mp.Repository == "" {
|
||||||
|
return fmt.Errorf("%w: model repository name is required", errModelPathInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.Contains(mp.Tag, ":") {
|
||||||
|
return fmt.Errorf("%w: ':' (colon) is not allowed in tag names", errModelPathInvalid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (mp ModelPath) GetNamespaceRepository() string {
|
func (mp ModelPath) GetNamespaceRepository() string {
|
||||||
return fmt.Sprintf("%s/%s", mp.Namespace, mp.Repository)
|
return fmt.Sprintf("%s/%s", mp.Namespace, mp.Repository)
|
||||||
}
|
}
|
||||||
@@ -93,11 +105,7 @@ func (mp ModelPath) GetShortTagname() string {
|
|||||||
|
|
||||||
// GetManifestPath returns the path to the manifest file for the given model path, it is up to the caller to create the directory if it does not exist.
|
// GetManifestPath returns the path to the manifest file for the given model path, it is up to the caller to create the directory if it does not exist.
|
||||||
func (mp ModelPath) GetManifestPath() (string, error) {
|
func (mp ModelPath) GetManifestPath() (string, error) {
|
||||||
if p := filepath.Join(mp.Registry, mp.Namespace, mp.Repository, mp.Tag); filepath.IsLocal(p) {
|
return filepath.Join(envconfig.Models(), "manifests", mp.Registry, mp.Namespace, mp.Repository, mp.Tag), nil
|
||||||
return filepath.Join(envconfig.Models(), "manifests", p), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return "", errModelPathInvalid
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mp ModelPath) BaseURL() *url.URL {
|
func (mp ModelPath) BaseURL() *url.URL {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -155,10 +154,3 @@ func TestParseModelPath(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInsecureModelpath(t *testing.T) {
|
|
||||||
mp := ParseModelPath("../../..:something")
|
|
||||||
if _, err := mp.GetManifestPath(); !errors.Is(err, errModelPathInvalid) {
|
|
||||||
t.Errorf("expected error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -463,7 +463,7 @@ func (s *Server) EmbeddingsHandler(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, resp)
|
c.JSON(http.StatusOK, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PullHandler(c *gin.Context) {
|
func (s *Server) PullModelHandler(c *gin.Context) {
|
||||||
var req api.PullRequest
|
var req api.PullRequest
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
switch {
|
switch {
|
||||||
@@ -513,7 +513,7 @@ func (s *Server) PullHandler(c *gin.Context) {
|
|||||||
streamResponse(c, ch)
|
streamResponse(c, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PushHandler(c *gin.Context) {
|
func (s *Server) PushModelHandler(c *gin.Context) {
|
||||||
var req api.PushRequest
|
var req api.PushRequest
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
switch {
|
switch {
|
||||||
@@ -577,7 +577,7 @@ func checkNameExists(name model.Name) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) CreateHandler(c *gin.Context) {
|
func (s *Server) CreateModelHandler(c *gin.Context) {
|
||||||
var r api.CreateRequest
|
var r api.CreateRequest
|
||||||
if err := c.ShouldBindJSON(&r); errors.Is(err, io.EOF) {
|
if err := c.ShouldBindJSON(&r); errors.Is(err, io.EOF) {
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
|
||||||
@@ -647,7 +647,7 @@ func (s *Server) CreateHandler(c *gin.Context) {
|
|||||||
streamResponse(c, ch)
|
streamResponse(c, ch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) DeleteHandler(c *gin.Context) {
|
func (s *Server) DeleteModelHandler(c *gin.Context) {
|
||||||
var r api.DeleteRequest
|
var r api.DeleteRequest
|
||||||
if err := c.ShouldBindJSON(&r); errors.Is(err, io.EOF) {
|
if err := c.ShouldBindJSON(&r); errors.Is(err, io.EOF) {
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
|
||||||
@@ -680,7 +680,7 @@ func (s *Server) DeleteHandler(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ShowHandler(c *gin.Context) {
|
func (s *Server) ShowModelHandler(c *gin.Context) {
|
||||||
var req api.ShowRequest
|
var req api.ShowRequest
|
||||||
err := c.ShouldBindJSON(&req)
|
err := c.ShouldBindJSON(&req)
|
||||||
switch {
|
switch {
|
||||||
@@ -829,7 +829,7 @@ func getKVData(digest string, verbose bool) (llm.KV, error) {
|
|||||||
return kv, nil
|
return kv, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) ListHandler(c *gin.Context) {
|
func (s *Server) ListModelsHandler(c *gin.Context) {
|
||||||
ms, err := Manifests()
|
ms, err := Manifests()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
@@ -879,7 +879,7 @@ func (s *Server) ListHandler(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, api.ListResponse{Models: models})
|
c.JSON(http.StatusOK, api.ListResponse{Models: models})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) CopyHandler(c *gin.Context) {
|
func (s *Server) CopyModelHandler(c *gin.Context) {
|
||||||
var r api.CopyRequest
|
var r api.CopyRequest
|
||||||
if err := c.ShouldBindJSON(&r); errors.Is(err, io.EOF) {
|
if err := c.ShouldBindJSON(&r); errors.Is(err, io.EOF) {
|
||||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
|
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "missing request body"})
|
||||||
@@ -1081,33 +1081,33 @@ func (s *Server) GenerateRoutes() http.Handler {
|
|||||||
allowedHostsMiddleware(s.addr),
|
allowedHostsMiddleware(s.addr),
|
||||||
)
|
)
|
||||||
|
|
||||||
r.POST("/api/pull", s.PullHandler)
|
r.POST("/api/pull", s.PullModelHandler)
|
||||||
r.POST("/api/generate", s.GenerateHandler)
|
r.POST("/api/generate", s.GenerateHandler)
|
||||||
r.POST("/api/chat", s.ChatHandler)
|
r.POST("/api/chat", s.ChatHandler)
|
||||||
r.POST("/api/embed", s.EmbedHandler)
|
r.POST("/api/embed", s.EmbedHandler)
|
||||||
r.POST("/api/embeddings", s.EmbeddingsHandler)
|
r.POST("/api/embeddings", s.EmbeddingsHandler)
|
||||||
r.POST("/api/create", s.CreateHandler)
|
r.POST("/api/create", s.CreateModelHandler)
|
||||||
r.POST("/api/push", s.PushHandler)
|
r.POST("/api/push", s.PushModelHandler)
|
||||||
r.POST("/api/copy", s.CopyHandler)
|
r.POST("/api/copy", s.CopyModelHandler)
|
||||||
r.DELETE("/api/delete", s.DeleteHandler)
|
r.DELETE("/api/delete", s.DeleteModelHandler)
|
||||||
r.POST("/api/show", s.ShowHandler)
|
r.POST("/api/show", s.ShowModelHandler)
|
||||||
r.POST("/api/blobs/:digest", s.CreateBlobHandler)
|
r.POST("/api/blobs/:digest", s.CreateBlobHandler)
|
||||||
r.HEAD("/api/blobs/:digest", s.HeadBlobHandler)
|
r.HEAD("/api/blobs/:digest", s.HeadBlobHandler)
|
||||||
r.GET("/api/ps", s.PsHandler)
|
r.GET("/api/ps", s.ProcessHandler)
|
||||||
|
|
||||||
// Compatibility endpoints
|
// Compatibility endpoints
|
||||||
r.POST("/v1/chat/completions", openai.ChatMiddleware(), s.ChatHandler)
|
r.POST("/v1/chat/completions", openai.ChatMiddleware(), s.ChatHandler)
|
||||||
r.POST("/v1/completions", openai.CompletionsMiddleware(), s.GenerateHandler)
|
r.POST("/v1/completions", openai.CompletionsMiddleware(), s.GenerateHandler)
|
||||||
r.POST("/v1/embeddings", openai.EmbeddingsMiddleware(), s.EmbedHandler)
|
r.POST("/v1/embeddings", openai.EmbeddingsMiddleware(), s.EmbedHandler)
|
||||||
r.GET("/v1/models", openai.ListMiddleware(), s.ListHandler)
|
r.GET("/v1/models", openai.ListMiddleware(), s.ListModelsHandler)
|
||||||
r.GET("/v1/models/:model", openai.RetrieveMiddleware(), s.ShowHandler)
|
r.GET("/v1/models/:model", openai.RetrieveMiddleware(), s.ShowModelHandler)
|
||||||
|
|
||||||
for _, method := range []string{http.MethodGet, http.MethodHead} {
|
for _, method := range []string{http.MethodGet, http.MethodHead} {
|
||||||
r.Handle(method, "/", func(c *gin.Context) {
|
r.Handle(method, "/", func(c *gin.Context) {
|
||||||
c.String(http.StatusOK, "Ollama is running")
|
c.String(http.StatusOK, "Ollama is running")
|
||||||
})
|
})
|
||||||
|
|
||||||
r.Handle(method, "/api/tags", s.ListHandler)
|
r.Handle(method, "/api/tags", s.ListModelsHandler)
|
||||||
r.Handle(method, "/api/version", func(c *gin.Context) {
|
r.Handle(method, "/api/version", func(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, gin.H{"version": version.Version})
|
c.JSON(http.StatusOK, gin.H{"version": version.Version})
|
||||||
})
|
})
|
||||||
@@ -1269,7 +1269,7 @@ func streamResponse(c *gin.Context, ch chan any) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) PsHandler(c *gin.Context) {
|
func (s *Server) ProcessHandler(c *gin.Context) {
|
||||||
models := []api.ProcessModelResponse{}
|
models := []api.ProcessModelResponse{}
|
||||||
|
|
||||||
for _, v := range s.sched.loaded {
|
for _, v := range s.sched.loaded {
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ func TestCreateFromBin(t *testing.T) {
|
|||||||
t.Setenv("OLLAMA_MODELS", p)
|
t.Setenv("OLLAMA_MODELS", p)
|
||||||
|
|
||||||
var s Server
|
var s Server
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -120,7 +120,7 @@ func TestCreateFromModel(t *testing.T) {
|
|||||||
t.Setenv("OLLAMA_MODELS", p)
|
t.Setenv("OLLAMA_MODELS", p)
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -134,7 +134,7 @@ func TestCreateFromModel(t *testing.T) {
|
|||||||
filepath.Join(p, "manifests", "registry.ollama.ai", "library", "test", "latest"),
|
filepath.Join(p, "manifests", "registry.ollama.ai", "library", "test", "latest"),
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
Modelfile: "FROM test",
|
Modelfile: "FROM test",
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -162,7 +162,7 @@ func TestCreateRemovesLayers(t *testing.T) {
|
|||||||
t.Setenv("OLLAMA_MODELS", p)
|
t.Setenv("OLLAMA_MODELS", p)
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .Prompt }}", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .Prompt }}", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -182,7 +182,7 @@ func TestCreateRemovesLayers(t *testing.T) {
|
|||||||
filepath.Join(p, "blobs", "sha256-bc80b03733773e0728011b2f4adf34c458b400e1aad48cb28d61170f3a2ad2d6"),
|
filepath.Join(p, "blobs", "sha256-bc80b03733773e0728011b2f4adf34c458b400e1aad48cb28d61170f3a2ad2d6"),
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .System }} {{ .Prompt }}", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .System }} {{ .Prompt }}", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -210,7 +210,7 @@ func TestCreateUnsetsSystem(t *testing.T) {
|
|||||||
t.Setenv("OLLAMA_MODELS", p)
|
t.Setenv("OLLAMA_MODELS", p)
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nSYSTEM Say hi!", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nSYSTEM Say hi!", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -230,7 +230,7 @@ func TestCreateUnsetsSystem(t *testing.T) {
|
|||||||
filepath.Join(p, "blobs", "sha256-f29e82a8284dbdf5910b1555580ff60b04238b8da9d5e51159ada67a4d0d5851"),
|
filepath.Join(p, "blobs", "sha256-f29e82a8284dbdf5910b1555580ff60b04238b8da9d5e51159ada67a4d0d5851"),
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nSYSTEM \"\"", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nSYSTEM \"\"", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -267,7 +267,7 @@ func TestCreateMergeParameters(t *testing.T) {
|
|||||||
t.Setenv("OLLAMA_MODELS", p)
|
t.Setenv("OLLAMA_MODELS", p)
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nPARAMETER temperature 1\nPARAMETER top_k 10\nPARAMETER stop USER:\nPARAMETER stop ASSISTANT:", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nPARAMETER temperature 1\nPARAMETER top_k 10\nPARAMETER stop USER:\nPARAMETER stop ASSISTANT:", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -288,7 +288,7 @@ func TestCreateMergeParameters(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// in order to merge parameters, the second model must be created FROM the first
|
// in order to merge parameters, the second model must be created FROM the first
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
Modelfile: "FROM test\nPARAMETER temperature 0.6\nPARAMETER top_p 0.7",
|
Modelfile: "FROM test\nPARAMETER temperature 0.6\nPARAMETER top_p 0.7",
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -326,7 +326,7 @@ func TestCreateMergeParameters(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// slices are replaced
|
// slices are replaced
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
Modelfile: "FROM test\nPARAMETER temperature 0.6\nPARAMETER top_p 0.7\nPARAMETER stop <|endoftext|>",
|
Modelfile: "FROM test\nPARAMETER temperature 0.6\nPARAMETER top_p 0.7\nPARAMETER stop <|endoftext|>",
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -371,7 +371,7 @@ func TestCreateReplacesMessages(t *testing.T) {
|
|||||||
t.Setenv("OLLAMA_MODELS", p)
|
t.Setenv("OLLAMA_MODELS", p)
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nMESSAGE assistant \"What is my purpose?\"\nMESSAGE user \"You run tests.\"\nMESSAGE assistant \"Oh, my god.\"", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nMESSAGE assistant \"What is my purpose?\"\nMESSAGE user \"You run tests.\"\nMESSAGE assistant \"Oh, my god.\"", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -391,7 +391,7 @@ func TestCreateReplacesMessages(t *testing.T) {
|
|||||||
filepath.Join(p, "blobs", "sha256-e0e27d47045063ccb167ae852c51d49a98eab33fabaee4633fdddf97213e40b5"),
|
filepath.Join(p, "blobs", "sha256-e0e27d47045063ccb167ae852c51d49a98eab33fabaee4633fdddf97213e40b5"),
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
Modelfile: "FROM test\nMESSAGE assistant \"You're a test, Harry.\"\nMESSAGE user \"I-I'm a what?\"\nMESSAGE assistant \"A test. And a thumping good one at that, I'd wager.\"",
|
Modelfile: "FROM test\nMESSAGE assistant \"You're a test, Harry.\"\nMESSAGE user \"I-I'm a what?\"\nMESSAGE assistant \"A test. And a thumping good one at that, I'd wager.\"",
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -448,7 +448,7 @@ func TestCreateTemplateSystem(t *testing.T) {
|
|||||||
t.Setenv("OLLAMA_MODELS", p)
|
t.Setenv("OLLAMA_MODELS", p)
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .Prompt }}\nSYSTEM Say hello!\nTEMPLATE {{ .System }} {{ .Prompt }}\nSYSTEM Say bye!", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .Prompt }}\nSYSTEM Say hello!\nTEMPLATE {{ .System }} {{ .Prompt }}\nSYSTEM Say bye!", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -488,7 +488,7 @@ func TestCreateTemplateSystem(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("incomplete template", func(t *testing.T) {
|
t.Run("incomplete template", func(t *testing.T) {
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .Prompt", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .Prompt", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -500,7 +500,7 @@ func TestCreateTemplateSystem(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("template with unclosed if", func(t *testing.T) {
|
t.Run("template with unclosed if", func(t *testing.T) {
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ if .Prompt }}", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ if .Prompt }}", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -512,7 +512,7 @@ func TestCreateTemplateSystem(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("template with undefined function", func(t *testing.T) {
|
t.Run("template with undefined function", func(t *testing.T) {
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ Prompt }}", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ Prompt }}", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -531,7 +531,7 @@ func TestCreateLicenses(t *testing.T) {
|
|||||||
t.Setenv("OLLAMA_MODELS", p)
|
t.Setenv("OLLAMA_MODELS", p)
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nLICENSE MIT\nLICENSE Apache-2.0", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nLICENSE MIT\nLICENSE Apache-2.0", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -579,7 +579,7 @@ func TestCreateDetectTemplate(t *testing.T) {
|
|||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
t.Run("matched", func(t *testing.T) {
|
t.Run("matched", func(t *testing.T) {
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, llm.KV{
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, llm.KV{
|
||||||
"tokenizer.chat_template": "{{ bos_token }}{% for message in messages %}{{'<|' + message['role'] + '|>' + '\n' + message['content'] + '<|end|>\n' }}{% endfor %}{% if add_generation_prompt %}{{ '<|assistant|>\n' }}{% else %}{{ eos_token }}{% endif %}",
|
"tokenizer.chat_template": "{{ bos_token }}{% for message in messages %}{{'<|' + message['role'] + '|>' + '\n' + message['content'] + '<|end|>\n' }}{% endfor %}{% if add_generation_prompt %}{{ '<|assistant|>\n' }}{% else %}{{ eos_token }}{% endif %}",
|
||||||
@@ -593,14 +593,14 @@ func TestCreateDetectTemplate(t *testing.T) {
|
|||||||
|
|
||||||
checkFileExists(t, filepath.Join(p, "blobs", "*"), []string{
|
checkFileExists(t, filepath.Join(p, "blobs", "*"), []string{
|
||||||
filepath.Join(p, "blobs", "sha256-0d79f567714c62c048378f2107fb332dabee0135d080c302d884317da9433cc5"),
|
filepath.Join(p, "blobs", "sha256-0d79f567714c62c048378f2107fb332dabee0135d080c302d884317da9433cc5"),
|
||||||
filepath.Join(p, "blobs", "sha256-35360843d0c84fb1506952a131bbef13cd2bb4a541251f22535170c05b56e672"),
|
|
||||||
filepath.Join(p, "blobs", "sha256-553c4a3f747b3d22a4946875f1cc8ed011c2930d83f864a0c7265f9ec0a20413"),
|
filepath.Join(p, "blobs", "sha256-553c4a3f747b3d22a4946875f1cc8ed011c2930d83f864a0c7265f9ec0a20413"),
|
||||||
filepath.Join(p, "blobs", "sha256-de3959f841e9ef6b4b6255fa41cb9e0a45da89c3066aa72bdd07a4747f848990"),
|
filepath.Join(p, "blobs", "sha256-c608dc615584cd20d9d830363dabf8a4783ae5d34245c3d8c115edb3bc7b28e4"),
|
||||||
|
filepath.Join(p, "blobs", "sha256-ea34c57ba5b78b740aafe2aeb74dc6507fc3ad14170b64c26a04fb9e36c88d75"),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("unmatched", func(t *testing.T) {
|
t.Run("unmatched", func(t *testing.T) {
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ func TestDelete(t *testing.T) {
|
|||||||
|
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
||||||
})
|
})
|
||||||
@@ -31,7 +31,7 @@ func TestDelete(t *testing.T) {
|
|||||||
t.Fatalf("expected status code 200, actual %d", w.Code)
|
t.Fatalf("expected status code 200, actual %d", w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .System }} {{ .Prompt }}", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s\nTEMPLATE {{ .System }} {{ .Prompt }}", createBinFile(t, nil, nil)),
|
||||||
})
|
})
|
||||||
@@ -52,7 +52,7 @@ func TestDelete(t *testing.T) {
|
|||||||
filepath.Join(p, "blobs", "sha256-fe7ac77b725cda2ccad03f88a880ecdfd7a33192d6cae08fce2c0ee1455991ed"),
|
filepath.Join(p, "blobs", "sha256-fe7ac77b725cda2ccad03f88a880ecdfd7a33192d6cae08fce2c0ee1455991ed"),
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.DeleteHandler, api.DeleteRequest{Name: "test"})
|
w = createRequest(t, s.DeleteModelHandler, api.DeleteRequest{Name: "test"})
|
||||||
|
|
||||||
if w.Code != http.StatusOK {
|
if w.Code != http.StatusOK {
|
||||||
t.Fatalf("expected status code 200, actual %d", w.Code)
|
t.Fatalf("expected status code 200, actual %d", w.Code)
|
||||||
@@ -68,7 +68,7 @@ func TestDelete(t *testing.T) {
|
|||||||
filepath.Join(p, "blobs", "sha256-fe7ac77b725cda2ccad03f88a880ecdfd7a33192d6cae08fce2c0ee1455991ed"),
|
filepath.Join(p, "blobs", "sha256-fe7ac77b725cda2ccad03f88a880ecdfd7a33192d6cae08fce2c0ee1455991ed"),
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.DeleteHandler, api.DeleteRequest{Name: "test2"})
|
w = createRequest(t, s.DeleteModelHandler, api.DeleteRequest{Name: "test2"})
|
||||||
|
|
||||||
if w.Code != http.StatusOK {
|
if w.Code != http.StatusOK {
|
||||||
t.Fatalf("expected status code 200, actual %d", w.Code)
|
t.Fatalf("expected status code 200, actual %d", w.Code)
|
||||||
@@ -102,7 +102,7 @@ func TestDeleteDuplicateLayers(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
w := createRequest(t, s.DeleteHandler, api.DeleteRequest{Name: "test"})
|
w := createRequest(t, s.DeleteModelHandler, api.DeleteRequest{Name: "test"})
|
||||||
if w.Code != http.StatusOK {
|
if w.Code != http.StatusOK {
|
||||||
t.Errorf("expected status code 200, actual %d", w.Code)
|
t.Errorf("expected status code 200, actual %d", w.Code)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ func TestGenerateChat(t *testing.T) {
|
|||||||
|
|
||||||
go s.sched.Run(context.TODO())
|
go s.sched.Run(context.TODO())
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Model: "test",
|
Model: "test",
|
||||||
Modelfile: fmt.Sprintf(`FROM %s
|
Modelfile: fmt.Sprintf(`FROM %s
|
||||||
TEMPLATE """
|
TEMPLATE """
|
||||||
@@ -144,7 +144,7 @@ func TestGenerateChat(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("missing capabilities chat", func(t *testing.T) {
|
t.Run("missing capabilities chat", func(t *testing.T) {
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Model: "bert",
|
Model: "bert",
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, llm.KV{
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, llm.KV{
|
||||||
"general.architecture": "bert",
|
"general.architecture": "bert",
|
||||||
@@ -270,7 +270,7 @@ func TestGenerateChat(t *testing.T) {
|
|||||||
checkChatResponse(t, w.Body, "test", "Hi!")
|
checkChatResponse(t, w.Body, "test", "Hi!")
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Model: "test-system",
|
Model: "test-system",
|
||||||
Modelfile: "FROM test\nSYSTEM You are a helpful assistant.",
|
Modelfile: "FROM test\nSYSTEM You are a helpful assistant.",
|
||||||
})
|
})
|
||||||
@@ -382,7 +382,7 @@ func TestGenerate(t *testing.T) {
|
|||||||
|
|
||||||
go s.sched.Run(context.TODO())
|
go s.sched.Run(context.TODO())
|
||||||
|
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Model: "test",
|
Model: "test",
|
||||||
Modelfile: fmt.Sprintf(`FROM %s
|
Modelfile: fmt.Sprintf(`FROM %s
|
||||||
TEMPLATE """
|
TEMPLATE """
|
||||||
@@ -442,7 +442,7 @@ func TestGenerate(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("missing capabilities generate", func(t *testing.T) {
|
t.Run("missing capabilities generate", func(t *testing.T) {
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Model: "bert",
|
Model: "bert",
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, llm.KV{
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, llm.KV{
|
||||||
"general.architecture": "bert",
|
"general.architecture": "bert",
|
||||||
@@ -583,7 +583,7 @@ func TestGenerate(t *testing.T) {
|
|||||||
checkGenerateResponse(t, w.Body, "test", "Hi!")
|
checkGenerateResponse(t, w.Body, "test", "Hi!")
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Model: "test-system",
|
Model: "test-system",
|
||||||
Modelfile: "FROM test\nSYSTEM You are a helpful assistant.",
|
Modelfile: "FROM test\nSYSTEM You are a helpful assistant.",
|
||||||
})
|
})
|
||||||
@@ -652,7 +652,7 @@ func TestGenerate(t *testing.T) {
|
|||||||
checkGenerateResponse(t, w.Body, "test-system", "Abra kadabra!")
|
checkGenerateResponse(t, w.Body, "test-system", "Abra kadabra!")
|
||||||
})
|
})
|
||||||
|
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Model: "test-suffix",
|
Model: "test-suffix",
|
||||||
Modelfile: `FROM test
|
Modelfile: `FROM test
|
||||||
TEMPLATE """{{- if .Suffix }}<PRE> {{ .Prompt }} <SUF>{{ .Suffix }} <MID>
|
TEMPLATE """{{- if .Suffix }}<PRE> {{ .Prompt }} <SUF>{{ .Suffix }} <MID>
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ func TestList(t *testing.T) {
|
|||||||
|
|
||||||
var s Server
|
var s Server
|
||||||
for _, n := range expectNames {
|
for _, n := range expectNames {
|
||||||
createRequest(t, s.CreateHandler, api.CreateRequest{
|
createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: n,
|
Name: n,
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
w := createRequest(t, s.ListHandler, nil)
|
w := createRequest(t, s.ListModelsHandler, nil)
|
||||||
if w.Code != http.StatusOK {
|
if w.Code != http.StatusOK {
|
||||||
t.Fatalf("expected status code 200, actual %d", w.Code)
|
t.Fatalf("expected status code 200, actual %d", w.Code)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -318,7 +318,7 @@ func TestCase(t *testing.T) {
|
|||||||
var s Server
|
var s Server
|
||||||
for _, tt := range cases {
|
for _, tt := range cases {
|
||||||
t.Run(tt, func(t *testing.T) {
|
t.Run(tt, func(t *testing.T) {
|
||||||
w := createRequest(t, s.CreateHandler, api.CreateRequest{
|
w := createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: tt,
|
Name: tt,
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -334,7 +334,7 @@ func TestCase(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run("create", func(t *testing.T) {
|
t.Run("create", func(t *testing.T) {
|
||||||
w = createRequest(t, s.CreateHandler, api.CreateRequest{
|
w = createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: strings.ToUpper(tt),
|
Name: strings.ToUpper(tt),
|
||||||
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
Modelfile: fmt.Sprintf("FROM %s", createBinFile(t, nil, nil)),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
@@ -350,7 +350,7 @@ func TestCase(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("pull", func(t *testing.T) {
|
t.Run("pull", func(t *testing.T) {
|
||||||
w := createRequest(t, s.PullHandler, api.PullRequest{
|
w := createRequest(t, s.PullModelHandler, api.PullRequest{
|
||||||
Name: strings.ToUpper(tt),
|
Name: strings.ToUpper(tt),
|
||||||
Stream: &stream,
|
Stream: &stream,
|
||||||
})
|
})
|
||||||
@@ -365,7 +365,7 @@ func TestCase(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("copy", func(t *testing.T) {
|
t.Run("copy", func(t *testing.T) {
|
||||||
w := createRequest(t, s.CopyHandler, api.CopyRequest{
|
w := createRequest(t, s.CopyModelHandler, api.CopyRequest{
|
||||||
Source: tt,
|
Source: tt,
|
||||||
Destination: strings.ToUpper(tt),
|
Destination: strings.ToUpper(tt),
|
||||||
})
|
})
|
||||||
@@ -387,7 +387,7 @@ func TestShow(t *testing.T) {
|
|||||||
|
|
||||||
var s Server
|
var s Server
|
||||||
|
|
||||||
createRequest(t, s.CreateHandler, api.CreateRequest{
|
createRequest(t, s.CreateModelHandler, api.CreateRequest{
|
||||||
Name: "show-model",
|
Name: "show-model",
|
||||||
Modelfile: fmt.Sprintf(
|
Modelfile: fmt.Sprintf(
|
||||||
"FROM %s\nFROM %s",
|
"FROM %s\nFROM %s",
|
||||||
@@ -396,7 +396,7 @@ func TestShow(t *testing.T) {
|
|||||||
),
|
),
|
||||||
})
|
})
|
||||||
|
|
||||||
w := createRequest(t, s.ShowHandler, api.ShowRequest{
|
w := createRequest(t, s.ShowModelHandler, api.ShowRequest{
|
||||||
Name: "show-model",
|
Name: "show-model",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -1,2 +1 @@
|
|||||||
{{- range .Messages }}<start_{{ .Role }}>{{ .Content }}<end_message>
|
{{ if .System }}<start_system>{{ .System }}<end_message>{{ end }}{{ if .Prompt }}<start_user>{{ .Prompt }}<end_message>{{ end }}<start_assistant>{{ .Response }}<end_message>
|
||||||
{{- end }}<start_assistant>
|
|
||||||
@@ -1,18 +1,8 @@
|
|||||||
{{- $system := "" }}
|
{{ if .System }}{{ .System }}
|
||||||
{{- range .Messages }}
|
|
||||||
{{- if eq .Role "system" }}
|
|
||||||
{{- if not $system }}{{ $system = .Content }}
|
|
||||||
{{- else }}{{ $system = printf "%s\n\n%s" $system .Content }}
|
|
||||||
{{- end }}
|
|
||||||
{{- else if eq .Role "user" }}
|
|
||||||
{{- if $system }}{{ $system }}
|
|
||||||
|
|
||||||
{{ $system = "" }}
|
{{ end }}{{ if .Prompt }}### Instruction:
|
||||||
{{- end }}### Instruction:
|
{{ .Prompt }}
|
||||||
{{ .Content }}
|
|
||||||
|
|
||||||
{{ else if eq .Role "assistant" }}### Response:
|
{{ end }}### Response:
|
||||||
{{ .Content }}
|
{{ .Response }}
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
{{- end }}### Response:
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
{{- range .Messages }}<|im_start|>{{ .Role }}
|
{{ if .System }}<|im_start|>system
|
||||||
{{ .Content }}<|im_end|>
|
{{ .System }}<|im_end|>
|
||||||
|
{{ end }}{{ if .Prompt }}<|im_start|>user
|
||||||
|
{{ .Prompt }}<|im_end|>
|
||||||
{{ end }}<|im_start|>assistant
|
{{ end }}<|im_start|>assistant
|
||||||
|
{{ .Response }}<|im_end|>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{{- range .Messages }}
|
{{ if .System }}System: {{ .System }}
|
||||||
{{- if eq .Role "system" }}System:
|
|
||||||
{{- else if eq .Role "user" }}User:
|
{{ end }}{{ if .Prompt }}User: {{ .Prompt }}
|
||||||
{{- else if eq .Role "assistant" }}Assistant:
|
|
||||||
{{- end }} {{ .Content }}
|
{{ end }}Assistant: {{ .Response }}
|
||||||
|
|
||||||
{{ end }}Assistant:
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
{{- range .Messages }}Source:
|
{{ if .System }}Source: system
|
||||||
{{- if eq .Role "system" }} system
|
|
||||||
{{- else if eq .Role "user" }} user
|
{{ .System }} <step> {{ end }}Source: user
|
||||||
{{- else if eq .Role "assistant" }} assistant
|
|
||||||
|
{{ .Prompt }} <step> Source: assistant
|
||||||
|
{{- if not .Response }}
|
||||||
|
Destination: user
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{ .Content }} <step> {{ end }}Source: assistant
|
{{ .Response }} <step>
|
||||||
Destination: user
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
{{- range .Messages }}
|
{{ if .System }}System: {{ .System }}
|
||||||
{{- if eq .Role "system" }}System: {{ .Content }}
|
{{ end }}{{ if .Prompt }}User:
|
||||||
{{ continue }}
|
{{ .Prompt }}
|
||||||
{{- else if eq .Role "user" }}User:
|
|
||||||
{{- else if eq .Role "assistant" }}Falcon:
|
|
||||||
{{- end }}
|
|
||||||
{{ .Content }}
|
|
||||||
{{ end }}Falcon:
|
{{ end }}Falcon:
|
||||||
|
{{ .Response }}
|
||||||
|
|||||||
@@ -1,16 +1,5 @@
|
|||||||
{{- $system := "" }}
|
<start_of_turn>user
|
||||||
{{- range .Messages }}
|
{{ if .System }}{{ .System }}
|
||||||
{{- if eq .Role "system" }}
|
{{ end }}{{ .Prompt }}<end_of_turn>
|
||||||
{{- if not $system }}{{ $system = .Content }}
|
<start_of_turn>model
|
||||||
{{- else }}{{ $system = printf "%s\n\n%s" $system .Content }}
|
{{ .Response }}<end_of_turn>
|
||||||
{{- end }}
|
|
||||||
{{- continue }}
|
|
||||||
{{- else if eq .Role "user" }}<start_of_turn>user
|
|
||||||
{{- if $system }}
|
|
||||||
{{ $system }}
|
|
||||||
{{- $system = "" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- else if eq .Role "assistant" }}<start_of_turn>model
|
|
||||||
{{- end }}
|
|
||||||
{{ .Content }}<end_of_turn>
|
|
||||||
{{ end }}<start_of_turn>model
|
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
{{- range .Messages }}
|
{{ if .System }}System:
|
||||||
{{- if eq .Role "system" }}System:
|
{{ .System }}
|
||||||
{{- else if eq .Role "user" }}Question:
|
|
||||||
{{- else if eq .Role "assistant" }}Answer:
|
{{ end }}{{ if .Prompt }}Question:
|
||||||
{{- end }}
|
{{ .Prompt }}
|
||||||
{{ .Content }}
|
|
||||||
|
|
||||||
{{ end }}Answer:
|
{{ end }}Answer:
|
||||||
|
{{ .Response }}
|
||||||
|
|
||||||
|
|||||||
@@ -91,10 +91,6 @@
|
|||||||
"template": "{% set loop_messages = messages %}{% for message in loop_messages %}{% set content = '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n'+ message['content'] | trim + '<|eot_id|>' %}{% if loop.index0 == 0 %}{% set content = bos_token + content %}{% endif %}{{ content }}{% endfor %}{% if add_generation_prompt %}{{ '<|start_header_id|>assistant<|end_header_id|>\n\n' }}{% endif %}",
|
"template": "{% set loop_messages = messages %}{% for message in loop_messages %}{% set content = '<|start_header_id|>' + message['role'] + '<|end_header_id|>\n\n'+ message['content'] | trim + '<|eot_id|>' %}{% if loop.index0 == 0 %}{% set content = bos_token + content %}{% endif %}{{ content }}{% endfor %}{% if add_generation_prompt %}{{ '<|start_header_id|>assistant<|end_header_id|>\n\n' }}{% endif %}",
|
||||||
"name": "llama3-instruct"
|
"name": "llama3-instruct"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"template": "{{- bos_token }}\n{%- if custom_tools is defined %}\n {%- set tools = custom_tools %}\n{%- endif %}\n{%- if not tools_in_user_message is defined %}\n {%- set tools_in_user_message = true %}\n{%- endif %}\n{%- if not date_string is defined %}\n {%- set date_string = \"26 Jul 2024\" %}\n{%- endif %}\n{%- if not tools is defined %}\n {%- set tools = none %}\n{%- endif %}\n\n{#- This block extracts the system message, so we can slot it into the right place. #}\n{%- if messages[0]['role'] == 'system' %}\n {%- set system_message = messages[0]['content']|trim %}\n {%- set messages = messages[1:] %}\n{%- else %}\n {%- set system_message = \"\" %}\n{%- endif %}\n\n{#- System message + builtin tools #}\n{{- \"<|start_header_id|>system<|end_header_id|>\\n\\n\" }}\n{%- if builtin_tools is defined or tools is not none %}\n {{- \"Environment: ipython\\n\" }}\n{%- endif %}\n{%- if builtin_tools is defined %}\n {{- \"Tools: \" + builtin_tools | reject('equalto', 'code_interpreter') | join(\", \") + \"\\n\\n\"}}\n{%- endif %}\n{{- \"Cutting Knowledge Date: December 2023\\n\" }}\n{{- \"Today Date: \" + date_string + \"\\n\\n\" }}\n{%- if tools is not none and not tools_in_user_message %}\n {{- \"You have access to the following functions. To call a function, please respond with JSON for a function call.\" }}\n {{- 'Respond in the format {\"name\": function name, \"parameters\": dictionary of argument name and its value}.' }}\n {{- \"Do not use variables.\\n\\n\" }}\n {%- for t in tools %}\n {{- t | tojson(indent=4) }}\n {{- \"\\n\\n\" }}\n {%- endfor %}\n{%- endif %}\n{{- system_message }}\n{{- \"<|eot_id|>\" }}\n\n{#- Custom tools are passed in a user message with some extra guidance #}\n{%- if tools_in_user_message and not tools is none %}\n {#- Extract the first user message so we can plug it in here #}\n {%- if messages | length != 0 %}\n {%- set first_user_message = messages[0]['content']|trim %}\n {%- set messages = messages[1:] %}\n {%- else %}\n {{- raise_exception(\"Cannot put tools in the first user message when there's no first user message!\") }}\n{%- endif %}\n {{- '<|start_header_id|>user<|end_header_id|>\\n\\n' -}}\n {{- \"Given the following functions, please respond with a JSON for a function call \" }}\n {{- \"with its proper arguments that best answers the given prompt.\\n\\n\" }}\n {{- 'Respond in the format {\"name\": function name, \"parameters\": dictionary of argument name and its value}.' }}\n {{- \"Do not use variables.\\n\\n\" }}\n {%- for t in tools %}\n {{- t | tojson(indent=4) }}\n {{- \"\\n\\n\" }}\n {%- endfor %}\n {{- first_user_message + \"<|eot_id|>\"}}\n{%- endif %}\n\n{%- for message in messages %}\n {%- if not (message.role == 'ipython' or message.role == 'tool' or 'tool_calls' in message) %}\n {{- '<|start_header_id|>' + message['role'] + '<|end_header_id|>\\n\\n'+ message['content'] | trim + '<|eot_id|>' }}\n {%- elif 'tool_calls' in message %}\n {%- if not message.tool_calls|length == 1 %}\n {{- raise_exception(\"This model only supports single tool-calls at once!\") }}\n {%- endif %}\n {%- set tool_call = message.tool_calls[0].function %}\n {%- if builtin_tools is defined and tool_call.name in builtin_tools %}\n {{- '<|start_header_id|>assistant<|end_header_id|>\\n\\n' -}}\n {{- \"<|python_tag|>\" + tool_call.name + \".call(\" }}\n {%- for arg_name, arg_val in tool_call.arguments | items %}\n {{- arg_name + '=\"' + arg_val + '\"' }}\n {%- if not loop.last %}\n {{- \", \" }}\n {%- endif %}\n {%- endfor %}\n {{- \")\" }}\n {%- else %}\n {{- '<|start_header_id|>assistant<|end_header_id|>\\n\\n' -}}\n {{- '{\"name\": \"' + tool_call.name + '\", ' }}\n {{- '\"parameters\": ' }}\n {{- tool_call.arguments | tojson }}\n {{- \"}\" }}\n {%- endif %}\n {%- if builtin_tools is defined %}\n {#- This means we're in ipython mode #}\n {{- \"<|eom_id|>\" }}\n {%- else %}\n {{- \"<|eot_id|>\" }}\n {%- endif %}\n {%- elif message.role == \"tool\" or message.role == \"ipython\" %}\n {{- \"<|start_header_id|>ipython<|end_header_id|>\\n\\n\" }}\n {%- if message.content is mapping or message.content is iterable %}\n {{- message.content | tojson }}\n {%- else %}\n {{- message.content }}\n {%- endif %}\n {{- \"<|eot_id|>\" }}\n {%- endif %}\n{%- endfor %}\n{%- if add_generation_prompt %}\n {{- '<|start_header_id|>assistant<|end_header_id|>\\n\\n' }}\n{%- endif %}\n",
|
|
||||||
"name": "llama3-instruct"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"template": "{% for message in messages %}\n{% if message['role'] == 'user' %}\n{{ 'Question:\n' + message['content'] + '\n\n' }}{% elif message['role'] == 'system' %}\n{{ 'System:\n' + message['content'] + '\n\n' }}{% elif message['role'] == 'assistant' %}{{ 'Answer:\n' + message['content'] + '\n\n' }}{% endif %}\n{% if loop.last and add_generation_prompt %}\n{{ 'Answer:\n' }}{% endif %}{% endfor %}",
|
"template": "{% for message in messages %}\n{% if message['role'] == 'user' %}\n{{ 'Question:\n' + message['content'] + '\n\n' }}{% elif message['role'] == 'system' %}\n{{ 'System:\n' + message['content'] + '\n\n' }}{% elif message['role'] == 'assistant' %}{{ 'Answer:\n' + message['content'] + '\n\n' }}{% endif %}\n{% if loop.last and add_generation_prompt %}\n{{ 'Answer:\n' }}{% endif %}{% endfor %}",
|
||||||
"name": "granite-instruct"
|
"name": "granite-instruct"
|
||||||
|
|||||||
@@ -1,14 +1,6 @@
|
|||||||
{{- $system := "" }}[INST] {{ range .Messages }}
|
[INST] <<SYS>>
|
||||||
{{- if eq .Role "system" }}
|
{{- if .System }}
|
||||||
{{- if not $system }}{{ $system = .Content }}
|
{{ .System }}
|
||||||
{{- else }}{{ $system = printf "%s\n\n%s" $system .Content }}
|
{{ end }}<</SYS>>
|
||||||
{{- end }}
|
|
||||||
{{- else if eq .Role "user" }}<<SYS>>
|
|
||||||
{{- if $system }}
|
|
||||||
{{ $system }}
|
|
||||||
{{ $system = "" }}
|
|
||||||
{{- end }}<</SYS>>
|
|
||||||
|
|
||||||
{{ .Content }} [/INST]
|
{{ .Prompt }} [/INST] {{ .Response }}</s><s>
|
||||||
{{- else if eq .Role "assistant" }} {{ .Content }}</s><s>[INST] {{ end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
{{- range .Messages }}<|start_header_id|>{{ .Role }}<|end_header_id|>
|
{{ if .System }}<|start_header_id|>system<|end_header_id|>
|
||||||
|
|
||||||
{{ .Content }}<|eot_id|>
|
{{ .System }}<|eot_id|>{{ end }}{{ if .Prompt }}<|start_header_id|>user<|end_header_id|>
|
||||||
{{- end }}<|start_header_id|>assistant<|end_header_id|>
|
|
||||||
|
|
||||||
|
{{ .Prompt }}<|eot_id|>{{ end }}<|start_header_id|>assistant<|end_header_id|>
|
||||||
|
|
||||||
|
{{ .Response }}<|eot_id|>
|
||||||
@@ -1,17 +1,8 @@
|
|||||||
{{- $system := "" }}
|
{{ if .System }}{{ .System }}
|
||||||
{{- range .Messages }}
|
|
||||||
{{- if eq .Role "system" }}
|
|
||||||
{{- if not $system }}{{ $system = .Content }}
|
|
||||||
{{- else }}{{ $system = printf "%s\n\n%s" $system .Content }}
|
|
||||||
{{- end }}
|
|
||||||
{{- continue }}
|
|
||||||
{{- else if eq .Role "user" }}
|
|
||||||
{{- if $system }}{{ $system }}
|
|
||||||
|
|
||||||
{{ $system = "" }}
|
{{ end }}{{ if .Prompt }}@@ Instruction
|
||||||
{{- end }}@@ Instruction
|
{{ .Prompt }}
|
||||||
{{- else if eq .Role "assistant" }}@@ Response
|
|
||||||
{{- end }}
|
|
||||||
{{ .Content }}
|
|
||||||
|
|
||||||
{{ end }}@@ Response
|
{{ end }}@@ Response
|
||||||
|
{{ .Response }}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
[INST] {{ range $index, $_ := .Messages }}
|
[INST] {{ if .System }}{{ .System }}
|
||||||
{{- if eq .Role "system" }}{{ .Content }}
|
|
||||||
|
|
||||||
{{ else if eq .Role "user" }}{{ .Content }}[/INST]
|
{{ end }}{{ .Prompt }}[/INST] {{ .Response }}</s>
|
||||||
{{- else if eq .Role "assistant" }} {{ .Content }}</s>[INST] {{ end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,6 +1 @@
|
|||||||
{{- range .Messages }}GPT4 Correct
|
{{ if .System }}GPT4 Correct System: {{ .System }}<|end_of_turn|>{{ end }}GPT4 Correct User: {{ .Prompt }}<|end_of_turn|>GPT4 Correct Assistant: {{ .Response }}<|end_of_turn|>
|
||||||
{{- if eq .Role "system" }} System:
|
|
||||||
{{- else if eq .Role "user" }} User:
|
|
||||||
{{- else if eq .Role "assistant" }} Assistant:
|
|
||||||
{{- end }} {{ .Content }}<|end_of_turn|>
|
|
||||||
{{- end }}GPT4 Correct Assistant:
|
|
||||||
@@ -1,3 +1,6 @@
|
|||||||
{{- range .Messages }}<|{{ .Role }}|>
|
{{ if .System }}<|system|>
|
||||||
{{ .Content }}<|end|>
|
{{ .System }}<|end|>
|
||||||
|
{{ end }}{{ if .Prompt }}<|user|>
|
||||||
|
{{ .Prompt }}<|end|>
|
||||||
{{ end }}<|assistant|>
|
{{ end }}<|assistant|>
|
||||||
|
{{ .Response }}<|end|>
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
{{- range .Messages }}
|
{{ if .System }}### System:
|
||||||
{{- if eq .Role "system" }}### System:
|
{{ .System }}
|
||||||
{{- else if eq .Role "user" }}### User:
|
|
||||||
{{- else if eq .Role "assistant" }}### Assistant:
|
|
||||||
{{ .Content }}</s>
|
|
||||||
|
|
||||||
{{ continue }}
|
{{ end }}{{ if .Prompt }}### User:
|
||||||
{{- end }}
|
{{ .Prompt }}
|
||||||
{{ .Content }}
|
|
||||||
|
|
||||||
{{ end }}### Assistant:
|
{{ end }}### Assistant:
|
||||||
|
{{ .Response }}</s>
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,8 @@
|
|||||||
{{- $system := "" }}
|
{{ if .System }}{{ .System }}
|
||||||
{{- range .Messages }}
|
|
||||||
{{- if eq .Role "system" }}
|
|
||||||
{{- if not $system }}{{ $system = .Content }}
|
|
||||||
{{- else }}{{ $system = printf "%s\n\n%s" $system .Content }}
|
|
||||||
{{- end }}
|
|
||||||
{{- else if eq .Role "user" }}
|
|
||||||
{{- if $system }}{{ $system }}
|
|
||||||
|
|
||||||
{{ $system = "" }}
|
{{ end }}{{ if .Prompt }}### Instruction
|
||||||
{{- end }}### Instruction
|
{{ .Prompt }}
|
||||||
{{ .Content }}
|
|
||||||
|
|
||||||
{{ else if eq .Role "assistant" }}### Response
|
{{ end }}### Response
|
||||||
{{ .Content }}<|endoftext|>
|
{{ .Response }}<|endoftext|>
|
||||||
|
|
||||||
{{ end }}
|
|
||||||
{{- end }}### Response
|
|
||||||
|
|||||||
@@ -1,14 +1,4 @@
|
|||||||
{{- $system := "" }}
|
{{ if .System }}{{ .System }}
|
||||||
{{- range .Messages }}
|
|
||||||
{{- if eq .Role "system" }}
|
|
||||||
{{- if not $system }}{{ $system = .Content }}
|
|
||||||
{{- else }}{{ $system = printf "%s\n\n%s" $system .Content }}
|
|
||||||
{{- end }}
|
|
||||||
{{- else if eq .Role "user" }}
|
|
||||||
{{- if $system }}{{ $system }}
|
|
||||||
|
|
||||||
{{ $system = "" }}
|
{{ end }}{{ if .Prompt }}USER: {{ .Prompt }}
|
||||||
{{- end }}USER: {{ .Content }}
|
{{ end }}ASSISTANT: {{ .Response }}</s>
|
||||||
{{ else if eq .Role "assistant" }}ASSISTANT: {{ .Content }}</s>
|
|
||||||
{{ end }}
|
|
||||||
{{- end }}ASSISTANT:
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
{{- range .Messages }}<|{{ .Role }}|>
|
{{ if .System }}<|system|>
|
||||||
{{ .Content }}</s>
|
{{ .System }}</s>
|
||||||
|
{{ end }}{{ if .Prompt }}<|user|>
|
||||||
|
{{ .Prompt }}</s>
|
||||||
{{ end }}<|assistant|>
|
{{ end }}<|assistant|>
|
||||||
|
{{ .Response }}</s>
|
||||||
|
|||||||
Reference in New Issue
Block a user