diff --git a/.golangci.yaml b/.golangci.yaml index b211e5de7..2aefd3fb7 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -63,6 +63,11 @@ linters: usestdlibvars: http-method: false http-status-code: false + exclusions: + rules: + - path: _test\.go + linters: + - prealloc formatters: enable: diff --git a/api/types.go b/api/types.go index ab6af7851..249ad0692 100644 --- a/api/types.go +++ b/api/types.go @@ -309,9 +309,9 @@ func (tp ToolProperty) ToTypeScriptType() string { return mapToTypeScriptType(tp.Type[0]) } - var types []string - for _, t := range tp.Type { - types = append(types, mapToTypeScriptType(t)) + types := make([]string, len(tp.Type)) + for i, t := range tp.Type { + types[i] = mapToTypeScriptType(t) } return strings.Join(types, " | ") } diff --git a/app/ui/ui.go b/app/ui/ui.go index 62f719e3b..86f26180f 100644 --- a/app/ui/ui.go +++ b/app/ui/ui.go @@ -1730,8 +1730,8 @@ func supportsWebSearchTools(model string) bool { // buildChatRequest converts store.Chat to api.ChatRequest func (s *Server) buildChatRequest(chat *store.Chat, model string, think any, availableTools []map[string]any) (*api.ChatRequest, error) { - var msgs []api.Message - for _, m := range chat.Messages { + msgs := make([]api.Message, len(chat.Messages)) + for i, m := range chat.Messages { // Skip empty messages if present if m.Content == "" && m.Thinking == "" && len(m.ToolCalls) == 0 && len(m.Attachments) == 0 { continue @@ -1789,7 +1789,7 @@ func (s *Server) buildChatRequest(chat *store.Chat, model string, think any, ava s.log().Debug("unknown message role", "role", m.Role) } - msgs = append(msgs, apiMsg) + msgs[i] = apiMsg } var thinkValue *api.ThinkValue diff --git a/cmd/interactive.go b/cmd/interactive.go index 79f129ae0..d933d255f 100644 --- a/cmd/interactive.go +++ b/cmd/interactive.go @@ -576,9 +576,8 @@ func extractFileNames(input string) []string { func extractFileData(input string) (string, []api.ImageData, error) { filePaths := extractFileNames(input) - var imgs []api.ImageData - - for _, fp := range filePaths { + imgs := make([]api.ImageData, len(filePaths)) + for i, fp := range filePaths { nfp := normalizeFilePath(fp) data, err := getImageData(nfp) if errors.Is(err, os.ErrNotExist) { @@ -591,7 +590,7 @@ func extractFileData(input string) (string, []api.ImageData, error) { input = strings.ReplaceAll(input, "'"+nfp+"'", "") input = strings.ReplaceAll(input, "'"+fp+"'", "") input = strings.ReplaceAll(input, fp, "") - imgs = append(imgs, data) + imgs[i] = data } return strings.TrimSpace(input), imgs, nil } diff --git a/convert/convert_bert.go b/convert/convert_bert.go index 6b0d0030a..b264d2117 100644 --- a/convert/convert_bert.go +++ b/convert/convert_bert.go @@ -137,7 +137,7 @@ func (p *bertModel) KV(t *Tokenizer) ggml.KV { } func (p *bertModel) Tensors(ts []Tensor) []*ggml.Tensor { - var out []*ggml.Tensor + out := make([]*ggml.Tensor, 0, len(ts)) for _, t := range ts { if slices.Contains([]string{ "embeddings.position_ids", diff --git a/convert/convert_commandr.go b/convert/convert_commandr.go index a909515bd..501ace479 100644 --- a/convert/convert_commandr.go +++ b/convert/convert_commandr.go @@ -44,14 +44,14 @@ func (p *commandrModel) KV(t *Tokenizer) ggml.KV { } func (p *commandrModel) Tensors(ts []Tensor) []*ggml.Tensor { - var out []*ggml.Tensor - for _, t := range ts { - out = append(out, &ggml.Tensor{ + out := make([]*ggml.Tensor, len(ts)) + for i, t := range ts { + out[i] = &ggml.Tensor{ Name: t.Name(), Kind: t.Kind(), Shape: t.Shape(), WriterTo: t, - }) + } } return out diff --git a/convert/convert_gemma.go b/convert/convert_gemma.go index 26698d6a6..fda5a064e 100644 --- a/convert/convert_gemma.go +++ b/convert/convert_gemma.go @@ -43,18 +43,18 @@ func (p *gemmaModel) KV(t *Tokenizer) ggml.KV { } func (p *gemmaModel) Tensors(ts []Tensor) []*ggml.Tensor { - var out []*ggml.Tensor - for _, t := range ts { + out := make([]*ggml.Tensor, len(ts)) + for i, t := range ts { if !strings.HasPrefix(t.Name(), "v.") && strings.HasSuffix(t.Name(), "_norm.weight") { t.SetRepacker(p.addOne) } - out = append(out, &ggml.Tensor{ + out[i] = &ggml.Tensor{ Name: t.Name(), Kind: t.Kind(), Shape: t.Shape(), WriterTo: t, - }) + } } return out diff --git a/convert/convert_gemma2_adapter.go b/convert/convert_gemma2_adapter.go index 6299cd9e0..b9b9214fe 100644 --- a/convert/convert_gemma2_adapter.go +++ b/convert/convert_gemma2_adapter.go @@ -22,8 +22,8 @@ func (p *gemma2Adapter) KV(baseKV ggml.KV) ggml.KV { } func (p *gemma2Adapter) Tensors(ts []Tensor) []*ggml.Tensor { - var out []*ggml.Tensor - for _, t := range ts { + out := make([]*ggml.Tensor, len(ts)) + for i, t := range ts { shape := t.Shape() if (strings.HasSuffix(t.Name(), "weight.lora_a") && shape[0] > shape[1]) || (strings.HasSuffix(t.Name(), "weight.lora_b") && shape[0] < shape[1]) { @@ -31,12 +31,12 @@ func (p *gemma2Adapter) Tensors(ts []Tensor) []*ggml.Tensor { t.SetRepacker(p.repack) } - out = append(out, &ggml.Tensor{ + out[i] = &ggml.Tensor{ Name: t.Name(), Kind: t.Kind(), Shape: t.Shape(), WriterTo: t, - }) + } } return out diff --git a/convert/convert_llama.go b/convert/convert_llama.go index 43969749c..4b177ab38 100644 --- a/convert/convert_llama.go +++ b/convert/convert_llama.go @@ -127,7 +127,7 @@ func (p *llamaModel) KV(t *Tokenizer) ggml.KV { } func (p *llamaModel) Tensors(ts []Tensor) []*ggml.Tensor { - var out []*ggml.Tensor + out := make([]*ggml.Tensor, 0, len(ts)+1) if p.RopeScaling.factors != nil { out = append(out, &ggml.Tensor{ @@ -176,9 +176,9 @@ func (p *llamaModel) Replacements() []string { } func (p *llamaModel) repack(name string, data []float32, shape []uint64) ([]float32, error) { - var dims []int - for _, dim := range shape { - dims = append(dims, int(dim)) + dims := make([]int, len(shape)) + for i, dim := range shape { + dims[i] = int(dim) } var heads uint32 diff --git a/convert/convert_llama_adapter.go b/convert/convert_llama_adapter.go index 4cc451153..6ad8f5200 100644 --- a/convert/convert_llama_adapter.go +++ b/convert/convert_llama_adapter.go @@ -30,8 +30,8 @@ func (p *llamaAdapter) KV(baseKV ggml.KV) ggml.KV { } func (p *llamaAdapter) Tensors(ts []Tensor) []*ggml.Tensor { - var out []*ggml.Tensor - for _, t := range ts { + out := make([]*ggml.Tensor, len(ts)) + for i, t := range ts { shape := t.Shape() if (strings.HasSuffix(t.Name(), "weight.lora_a") && shape[0] > shape[1]) || (strings.HasSuffix(t.Name(), "weight.lora_b") && shape[0] < shape[1]) { @@ -41,12 +41,12 @@ func (p *llamaAdapter) Tensors(ts []Tensor) []*ggml.Tensor { t.SetRepacker(p.repack) } - out = append(out, &ggml.Tensor{ + out[i] = &ggml.Tensor{ Name: t.Name(), Kind: t.Kind(), Shape: shape, WriterTo: t, - }) + } } return out diff --git a/convert/convert_mistral.go b/convert/convert_mistral.go index a6fd4c41a..1faf0cb7c 100644 --- a/convert/convert_mistral.go +++ b/convert/convert_mistral.go @@ -90,9 +90,8 @@ func (p *mistral3Model) KV(t *Tokenizer) ggml.KV { } func (p *mistral3Model) Tensors(ts []Tensor) []*ggml.Tensor { - var out []*ggml.Tensor - - for _, t := range ts { + out := make([]*ggml.Tensor, len(ts)) + for i, t := range ts { if !strings.HasPrefix(t.Name(), "v.") { if strings.HasSuffix(t.Name(), ".attn_q.weight") || strings.HasSuffix(t.Name(), ".attn_k.weight") { @@ -100,12 +99,12 @@ func (p *mistral3Model) Tensors(ts []Tensor) []*ggml.Tensor { } } - out = append(out, &ggml.Tensor{ + out[i] = &ggml.Tensor{ Name: t.Name(), Kind: t.Kind(), Shape: t.Shape(), WriterTo: t, - }) + } } return out @@ -145,9 +144,9 @@ func (p *mistral3Model) Replacements() []string { } func (p *mistral3Model) repack(name string, data []float32, shape []uint64) ([]float32, error) { - var dims []int - for _, dim := range shape { - dims = append(dims, int(dim)) + dims := make([]int, len(shape)) + for i, dim := range shape { + dims[i] = int(dim) } var heads uint32 diff --git a/convert/convert_qwen2.go b/convert/convert_qwen2.go index 3647c4e54..f3347795f 100644 --- a/convert/convert_qwen2.go +++ b/convert/convert_qwen2.go @@ -49,14 +49,14 @@ func (q *qwen2Model) KV(t *Tokenizer) ggml.KV { } func (q *qwen2Model) Tensors(ts []Tensor) []*ggml.Tensor { - var out []*ggml.Tensor - for _, t := range ts { - out = append(out, &ggml.Tensor{ + out := make([]*ggml.Tensor, len(ts)) + for i, t := range ts { + out[i] = &ggml.Tensor{ Name: t.Name(), Kind: t.Kind(), Shape: t.Shape(), WriterTo: t, - }) + } } return out diff --git a/convert/tokenizer_spm.go b/convert/tokenizer_spm.go index 340c3d581..025046dcd 100644 --- a/convert/tokenizer_spm.go +++ b/convert/tokenizer_spm.go @@ -82,7 +82,7 @@ func parseSentencePiece(fsys fs.FS) (*Vocabulary, error) { content string } - var ts []t + ts := make([]t, 0, len(atm)) for content, id := range atm { ts = append(ts, t{id, content}) } diff --git a/llama/llama.go b/llama/llama.go index 582d4128c..2c4ddbeb0 100644 --- a/llama/llama.go +++ b/llama/llama.go @@ -263,9 +263,9 @@ func LoadModelFromFile(modelPath string, params ModelParams) (*Model, error) { cparams.use_mmap = C.bool(params.UseMmap) cparams.vocab_only = C.bool(params.VocabOnly) - var devices []C.ggml_backend_dev_t - for _, llamaID := range params.Devices { - devices = append(devices, C.ggml_backend_dev_get(C.size_t(llamaID))) + devices := make([]C.ggml_backend_dev_t, len(params.Devices)) + for i, llamaID := range params.Devices { + devices[i] = C.ggml_backend_dev_get(C.size_t(llamaID)) } if len(devices) > 0 { devices = append(devices, C.ggml_backend_dev_t(C.NULL)) diff --git a/middleware/openai_test.go b/middleware/openai_test.go index fc71b57d2..ce76a60cb 100644 --- a/middleware/openai_test.go +++ b/middleware/openai_test.go @@ -845,19 +845,17 @@ func TestListMiddleware(t *testing.T) { resp := httptest.NewRecorder() router.ServeHTTP(resp, req) - var expected, actual map[string]any - err := json.Unmarshal([]byte(tc.resp), &expected) - if err != nil { + var want, got map[string]any + if err := json.Unmarshal([]byte(tc.resp), &want); err != nil { t.Fatalf("failed to unmarshal expected response: %v", err) } - err = json.Unmarshal(resp.Body.Bytes(), &actual) - if err != nil { + if err := json.Unmarshal(resp.Body.Bytes(), &got); err != nil { t.Fatalf("failed to unmarshal actual response: %v", err) } - if !reflect.DeepEqual(expected, actual) { - t.Errorf("responses did not match\nExpected: %+v\nActual: %+v", expected, actual) + if diff := cmp.Diff(want, got); diff != "" { + t.Errorf("response does not match (-want +got):\n%s", diff) } } } diff --git a/ml/backend/ggml/ggml.go b/ml/backend/ggml/ggml.go index 520d95cb0..df6fcbc70 100644 --- a/ml/backend/ggml/ggml.go +++ b/ml/backend/ggml/ggml.go @@ -178,14 +178,14 @@ func New(modelPath string, params ml.BackendParams) (ml.Backend, error) { requiredMemory.CPU.Cache = make([]uint64, blocks+1) // create list of buffer types for each gpu - var gpuDeviceBufferTypes []deviceBufferType + gpuDeviceBufferTypes := make([]deviceBufferType, len(gpus)) requiredMemory.GPUs = make([]ml.DeviceMemory, len(gpus)) for i, d := range gpus { bt := C.ggml_backend_dev_buffer_type(d) - gpuDeviceBufferTypes = append(gpuDeviceBufferTypes, deviceBufferType{ + gpuDeviceBufferTypes[i] = deviceBufferType{ d: d, bts: append([]C.ggml_backend_buffer_type_t{bt}, cpuDeviceBufferType.bts...), - }) + } btDeviceMemory[bt] = &requiredMemory.GPUs[i] requiredMemory.GPUs[i].Name = C.GoString(C.ggml_backend_dev_name(d)) @@ -354,8 +354,8 @@ func New(modelPath string, params ml.BackendParams) (ml.Backend, error) { deviceBufferTypes := make(map[C.ggml_backend_dev_t]C.ggml_backend_buffer_type_t) // create backends and buffer types used for the compute graph scheduler - var schedBackends []C.ggml_backend_t - var schedBufts []C.ggml_backend_buffer_type_t + schedBackends := make([]C.ggml_backend_t, 0, len(cpus)+len(accels)+len(gpus)) + schedBufts := make([]C.ggml_backend_buffer_type_t, 0, len(cpus)+len(accels)+len(gpus)) for _, d := range append(gpus, append(accels, cpus...)...) { b := backends[d] bt := C.ggml_backend_get_default_buffer_type(b) diff --git a/ml/device.go b/ml/device.go index 2932afe49..a672245b3 100644 --- a/ml/device.go +++ b/ml/device.go @@ -219,7 +219,7 @@ type BackendMemory struct { } func (m BackendMemory) LogValue() slog.Value { - var attrs []slog.Attr + attrs := make([]slog.Attr, 0, 2+len(m.GPUs)) if m.InputWeights != 0 { attrs = append(attrs, slog.Any("InputWeights", m.InputWeights)) } diff --git a/model/models/mllama/model_text.go b/model/models/mllama/model_text.go index 65f0a8278..46c8eb589 100644 --- a/model/models/mllama/model_text.go +++ b/model/models/mllama/model_text.go @@ -223,8 +223,8 @@ func (m *TextModel) Forward(ctx ml.Context, inputIDs, positionIDs, outputs, cros } func newTextModel(c fs.Config) *TextModel { - var decoderLayers []TextDecoderLayer - for i := range c.Uint("block_count") { + decoderLayers := make([]TextDecoderLayer, c.Uint("block_count")) + for i := range decoderLayers { var textDecoderLayer TextDecoderLayer if slices.Contains(c.Ints("attention.cross_attention_layers"), int32(i)) { textDecoderLayer = &TextCrossAttentionDecoderLayer{} @@ -232,7 +232,7 @@ func newTextModel(c fs.Config) *TextModel { textDecoderLayer = &TextSelfAttentionDecoderLayer{} } - decoderLayers = append(decoderLayers, textDecoderLayer) + decoderLayers[i] = textDecoderLayer } return &TextModel{ diff --git a/openai/openai.go b/openai/openai.go index ec6c351e6..4d3076df8 100644 --- a/openai/openai.go +++ b/openai/openai.go @@ -377,20 +377,19 @@ func ToCompleteChunk(id string, r api.GenerateResponse) CompletionChunk { // ToListCompletion converts an api.ListResponse to ListCompletion func ToListCompletion(r api.ListResponse) ListCompletion { - var data []Model - for _, m := range r.Models { - data = append(data, Model{ - Id: m.Name, - Object: "model", - Created: m.ModifiedAt.Unix(), - OwnedBy: model.ParseName(m.Name).Namespace, - }) - } - - return ListCompletion{ - Object: "list", - Data: data, + c := ListCompletion{Object: "list"} + if len(r.Models) > 0 { + c.Data = make([]Model, len(r.Models)) + for i, m := range r.Models { + c.Data[i] = Model{ + Id: m.Name, + Object: "model", + Created: m.ModifiedAt.Unix(), + OwnedBy: model.ParseName(m.Name).Namespace, + } + } } + return c } // ToEmbeddingList converts an api.EmbedResponse to EmbeddingList diff --git a/runner/common/stop.go b/runner/common/stop.go index 5393d5695..d9f28d32e 100644 --- a/runner/common/stop.go +++ b/runner/common/stop.go @@ -39,21 +39,15 @@ func TruncateStop(pieces []string, stop string) ([]string, bool) { joined = joined[:index] - // Split truncated string back into pieces of original lengths - lengths := make([]int, len(pieces)) - for i, piece := range pieces { - lengths[i] = len(piece) - } - - var result []string + result := make([]string, 0, len(pieces)) tokenTruncated := false start := 0 - for _, length := range lengths { + for _, piece := range pieces { if start >= len(joined) { break } - end := start + length + end := start + len(piece) if end > len(joined) { end = len(joined) tokenTruncated = true diff --git a/server/create.go b/server/create.go index f999dd99d..26bbb3b41 100644 --- a/server/create.go +++ b/server/create.go @@ -460,8 +460,8 @@ func kvFromLayers(baseLayers []*layerGGML) (ggml.KV, error) { } func createModel(r api.CreateRequest, name model.Name, baseLayers []*layerGGML, config *ConfigV2, fn func(resp api.ProgressResponse)) (err error) { - var layers []Layer - for _, layer := range baseLayers { + layers := make([]Layer, len(baseLayers)) + for i, layer := range baseLayers { if layer.GGML != nil { quantType := strings.ToUpper(cmp.Or(r.Quantize, r.Quantization)) if quantType != "" && layer.GGML.Name() == "gguf" && layer.MediaType == "application/vnd.ollama.image.model" { @@ -486,7 +486,7 @@ func createModel(r api.CreateRequest, name model.Name, baseLayers []*layerGGML, config.FileType = cmp.Or(config.FileType, layer.GGML.KV().FileType().String()) config.ModelFamilies = append(config.ModelFamilies, layer.GGML.KV().Architecture()) } - layers = append(layers, layer.Layer) + layers[i] = layer.Layer } if r.Template != "" { diff --git a/server/routes.go b/server/routes.go index ac059668d..cad834c95 100644 --- a/server/routes.go +++ b/server/routes.go @@ -826,9 +826,9 @@ func (s *Server) EmbeddingsHandler(c *gin.Context) { return } - var e []float64 - for _, v := range embedding { - e = append(e, float64(v)) + e := make([]float64, len(embedding)) + for i, v := range embedding { + e[i] = float64(v) } resp := api.EmbeddingResponse{ @@ -1211,7 +1211,7 @@ func (s *Server) ListHandler(c *gin.Context) { return } - models := []api.ListModelResponse{} + models := make([]api.ListModelResponse, 0, len(ms)) for n, m := range ms { var cf ConfigV2