modernize

This commit is contained in:
Michael Yang 2025-11-16 12:49:48 -08:00
parent d70e935526
commit efd9f5e67e
31 changed files with 75 additions and 107 deletions

View File

@ -783,7 +783,7 @@ func (m *Metrics) Summary() {
func (opts *Options) FromMap(m map[string]any) error {
valueOpts := reflect.ValueOf(opts).Elem() // names of the fields in the options struct
typeOpts := reflect.TypeOf(opts).Elem() // types of the fields in the options struct
typeOpts := reflect.TypeFor[Options]() // types of the fields in the options struct
// build map of json struct tags to their types
jsonOpts := make(map[string]reflect.StructField)
@ -854,8 +854,7 @@ func (opts *Options) FromMap(m map[string]any) error {
}
field.Set(reflect.ValueOf(slice))
case reflect.Pointer:
var b bool
if field.Type() == reflect.TypeOf(&b) {
if field.Type() == reflect.TypeFor[*bool]() {
val, ok := val.(bool)
if !ok {
return fmt.Errorf("option %q must be of type boolean", key)
@ -906,7 +905,7 @@ func DefaultOptions() Options {
// ThinkValue represents a value that can be a boolean or a string ("high", "medium", "low")
type ThinkValue struct {
// Value can be a bool or string
Value interface{}
Value any
}
// IsValid checks if the ThinkValue is valid
@ -1055,7 +1054,7 @@ func (d *Duration) UnmarshalJSON(b []byte) (err error) {
func FormatParams(params map[string][]string) (map[string]any, error) {
opts := Options{}
valueOpts := reflect.ValueOf(&opts).Elem() // names of the fields in the options struct
typeOpts := reflect.TypeOf(opts) // types of the fields in the options struct
typeOpts := reflect.TypeFor[Options]() // types of the fields in the options struct
// build map of json struct tags to their types
jsonOpts := make(map[string]reflect.StructField)
@ -1102,8 +1101,7 @@ func FormatParams(params map[string][]string) (map[string]any, error) {
// TODO: only string slices are supported right now
out[key] = vals
case reflect.Pointer:
var b bool
if field.Type() == reflect.TypeOf(&b) {
if field.Type() == reflect.TypeFor[*bool]() {
boolVal, err := strconv.ParseBool(vals[0])
if err != nil {
return nil, fmt.Errorf("invalid bool value %s", vals)

View File

@ -37,7 +37,7 @@ type MsgBuilder struct {
}
// Message initialises a MsgBuilder with the provided message.
func Message(format string, args ...interface{}) *MsgBuilder {
func Message(format string, args ...any) *MsgBuilder {
return &MsgBuilder{Msg: fmt.Sprintf(format, args...)}
}

View File

@ -67,8 +67,7 @@ func reapServers() error {
return nil
}
pids := strings.Split(pidsStr, "\n")
for _, pidStr := range pids {
for pidStr := range strings.SplitSeq(pidsStr, "\n") {
pidStr = strings.TrimSpace(pidStr)
if pidStr == "" {
continue

View File

@ -282,7 +282,7 @@ func countRows(t *testing.T, db *database, table string) int {
return count
}
func countRowsWithCondition(t *testing.T, db *database, table, condition string, args ...interface{}) int {
func countRowsWithCondition(t *testing.T, db *database, table, condition string, args ...any) int {
t.Helper()
var count int
query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE %s", table, condition)
@ -296,7 +296,7 @@ func countRowsWithCondition(t *testing.T, db *database, table, condition string,
// Test helpers for schema migration testing
// schemaMap returns both tables/columns and indexes (ignoring order)
func schemaMap(db *database) map[string]interface{} {
func schemaMap(db *database) map[string]any {
result := make(map[string]any)
result["tables"] = columnMap(db)

View File

@ -4,6 +4,7 @@ package not
import (
"fmt"
"strings"
)
type ValidError struct {
@ -44,12 +45,12 @@ func (b Valids) Error() string {
return ""
}
var result string
var sb strings.Builder
for i, err := range b {
if i > 0 {
result += "; "
sb.WriteString("; ")
}
result += err.Error()
sb.WriteString(err.Error())
}
return result
return sb.String()
}

View File

@ -149,7 +149,7 @@ func BenchmarkChat(fOpt flagOptions) error {
for _, model := range models {
for range *fOpt.epochs {
options := make(map[string]interface{})
options := make(map[string]any)
if *fOpt.maxTokens > 0 {
options["num_predict"] = *fOpt.maxTokens
}

View File

@ -442,7 +442,7 @@ func TestReadImage_FileNotFound(t *testing.T) {
func TestOptionsMapCreation(t *testing.T) {
fOpt := createTestFlagOptions()
options := make(map[string]interface{})
options := make(map[string]any)
if *fOpt.maxTokens > 0 {
options["num_predict"] = *fOpt.maxTokens
}

View File

@ -11,6 +11,7 @@ import (
"fmt"
"io"
"log"
"maps"
"math"
"net"
"net/http"
@ -1204,9 +1205,7 @@ func (r runOptions) Copy() runOptions {
var opts map[string]any
if r.Options != nil {
opts = make(map[string]any, len(r.Options))
for k, v := range r.Options {
opts[k] = v
}
maps.Copy(opts, r.Options)
}
var think *api.ThinkValue
@ -1952,13 +1951,13 @@ func inferThinkingOption(caps *[]model.Capability, runOpts *runOptions, explicit
}
func renderToolCalls(toolCalls []api.ToolCall, plainText bool) string {
out := ""
var sb strings.Builder
formatExplanation := ""
formatValues := ""
if !plainText {
formatExplanation = readline.ColorGrey + readline.ColorBold
formatValues = readline.ColorDefault
out += formatExplanation
sb.WriteString(formatExplanation)
}
for i, toolCall := range toolCalls {
argsAsJSON, err := json.Marshal(toolCall.Function.Arguments)
@ -1966,13 +1965,13 @@ func renderToolCalls(toolCalls []api.ToolCall, plainText bool) string {
return ""
}
if i > 0 {
out += "\n"
sb.WriteString("\n")
}
// all tool calls are unexpected since we don't currently support registering any in the CLI
out += fmt.Sprintf(" Model called a non-existent function '%s()' with arguments: %s", formatValues+toolCall.Function.Name+formatExplanation, formatValues+string(argsAsJSON)+formatExplanation)
fmt.Fprintf(&sb, " Model called a non-existent function '%s()' with arguments: %s", formatValues+toolCall.Function.Name+formatExplanation, formatValues+string(argsAsJSON)+formatExplanation)
}
if !plainText {
out += readline.ColorDefault
sb.WriteString(readline.ColorDefault)
}
return out
return sb.String()
}

View File

@ -1322,8 +1322,8 @@ func TestRunOptions_Copy(t *testing.T) {
// Test 2: Verify all fields are copied correctly
tests := []struct {
name string
got interface{}
want interface{}
got any
want any
}{
{"Model", copied.Model, original.Model},
{"ParentModel", copied.ParentModel, original.ParentModel},

View File

@ -410,7 +410,7 @@ func generateInteractive(cmd *cobra.Command, opts runOptions) error {
if resp.Parameters == "" {
fmt.Println(" No additional parameters were specified for this model.")
} else {
for _, l := range strings.Split(resp.Parameters, "\n") {
for l := range strings.SplitSeq(resp.Parameters, "\n") {
fmt.Printf(" %s\n", l)
}
}

View File

@ -846,14 +846,7 @@ nextOperation:
func uniqueDeviceIDs(gpuLayers ml.GPULayersList) []ml.DeviceID {
devices := []ml.DeviceID{}
for _, layer := range gpuLayers {
new := true
for _, ID := range devices {
if layer.DeviceID == ID {
new = false
break
}
}
if new {
if !slices.Contains(devices, layer.DeviceID) {
devices = append(devices, layer.DeviceID)
}
}
@ -1721,12 +1714,12 @@ func (s *llamaServer) Detokenize(ctx context.Context, tokens []int) (string, err
return "", fmt.Errorf("no tokenizer configured")
}
var resp string
var sb strings.Builder
for _, token := range tokens {
resp += s.llamaModel.TokenToPiece(token)
sb.WriteString(s.llamaModel.TokenToPiece(token))
}
return resp, nil
return sb.String(), nil
}
func (s *ollamaServer) Detokenize(ctx context.Context, tokens []int) (string, error) {

View File

@ -68,7 +68,7 @@ func TestEmbeddingsMiddleware_EncodingFormats(t *testing.T) {
switch tc.expectType {
case "array":
if _, ok := result.Data[0].Embedding.([]interface{}); !ok {
if _, ok := result.Data[0].Embedding.([]any); !ok {
t.Errorf("expected array, got %T", result.Data[0].Embedding)
}
case "string":

View File

@ -414,14 +414,7 @@ func LibraryPaths(l []DeviceInfo) []string {
gpuLibs := []string{LibOllamaPath}
for _, gpu := range l {
for _, dir := range gpu.LibraryPath {
needed := true
for _, existing := range gpuLibs {
if dir == existing {
needed = false
break
}
}
if needed {
if !slices.Contains(gpuLibs, dir) {
gpuLibs = append(gpuLibs, dir)
}
}

View File

@ -175,9 +175,10 @@ func populateFields(base Base, v reflect.Value, tags ...Tag) reflect.Value {
tagsCopy = append(tagsCopy, parseTag(tag))
}
if tt == reflect.TypeOf((*Base)(nil)).Elem() {
switch {
case tt == reflect.TypeFor[Base]():
vv.Set(reflect.ValueOf(base))
} else if tt == reflect.TypeOf((*ml.Tensor)(nil)).Elem() {
case tt == reflect.TypeFor[ml.Tensor]():
var fn func([]Tag, string, string) [][]string
fn = func(tags []Tag, prefix, suffix string) (fullNames [][]string) {
if len(tags) > 0 {
@ -217,9 +218,9 @@ func populateFields(base Base, v reflect.Value, tags ...Tag) reflect.Value {
break
}
}
} else if tt.Kind() == reflect.Pointer || tt.Kind() == reflect.Interface {
case tt.Kind() == reflect.Pointer || tt.Kind() == reflect.Interface:
setPointer(base, vv, tagsCopy)
} else if tt.Kind() == reflect.Slice || tt.Kind() == reflect.Array {
case tt.Kind() == reflect.Slice || tt.Kind() == reflect.Array:
for i := range vv.Len() {
vvv := vv.Index(i)
if vvv.Kind() == reflect.Pointer || vvv.Kind() == reflect.Interface {

View File

@ -205,12 +205,12 @@ func (q queue) Less(i, j int) bool {
func (q queue) Swap(i, j int) { q[i], q[j] = q[j], q[i] }
func (q *queue) Push(x interface{}) {
func (q *queue) Push(x any) {
item := x.(*candidate)
*q = append(*q, item)
}
func (q *queue) Pop() interface{} {
func (q *queue) Pop() any {
old := *q
n := len(old)
item := old[n-1]

View File

@ -487,19 +487,14 @@ func FromChatRequest(r ChatCompletionRequest) (*api.ChatRequest, error) {
}
}
types := []string{"jpeg", "jpg", "png", "webp"}
valid := false
// support blank mime type to match api/chat taking just unadorned base64
if strings.HasPrefix(url, "data:;base64,") {
url = strings.TrimPrefix(url, "data:;base64,")
valid = true
}
for _, t := range types {
prefix := "data:image/" + t + ";base64,"
if strings.HasPrefix(url, prefix) {
url = strings.TrimPrefix(url, prefix)
valid = true
break
url, valid := strings.CutPrefix(url, "data:;base64,")
if !valid {
for _, t := range []string{"jpeg", "jpg", "png", "webp"} {
prefix := "data:image/" + t + ";base64,"
url, valid = strings.CutPrefix(url, prefix)
if valid {
break
}
}
}

View File

@ -7,6 +7,7 @@ import (
"errors"
"fmt"
"io"
"maps"
"net/http"
"os"
"os/user"
@ -78,9 +79,7 @@ func (f Modelfile) CreateRequest(relativeDir string) (*api.CreateRequest, error)
if req.Files == nil {
req.Files = digestMap
} else {
for k, v := range digestMap {
req.Files[k] = v
}
maps.Copy(req.Files, digestMap)
}
case "adapter":
path, err := expandPath(c.Args, relativeDir)

View File

@ -3,6 +3,7 @@ package readline
import (
"fmt"
"os"
"strings"
"github.com/emirpasic/gods/v2/lists/arraylist"
"github.com/mattn/go-runewidth"
@ -515,13 +516,13 @@ func (b *Buffer) StringN(n int) string {
}
func (b *Buffer) StringNM(n, m int) string {
var s string
var sb strings.Builder
if m == 0 {
m = b.Buf.Size()
}
for cnt := n; cnt < m; cnt++ {
c, _ := b.Buf.Get(cnt)
s += string(c)
sb.WriteRune(c)
}
return s
return sb.String()
}

View File

@ -5,6 +5,7 @@ import (
"fmt"
"io"
"os"
"strings"
)
type Prompt struct {
@ -124,18 +125,18 @@ func (i *Instance) Readline() (string, error) {
case KeyRight:
buf.MoveRight()
case CharBracketedPaste:
var code string
var code strings.Builder
for range 3 {
r, err = i.Terminal.Read()
if err != nil {
return "", io.EOF
}
code += string(r)
code.WriteRune(r)
}
if code == CharBracketedPasteStart {
if code.String() == CharBracketedPasteStart {
i.Pasting = true
} else if code == CharBracketedPasteEnd {
} else if code.String() == CharBracketedPasteEnd {
i.Pasting = false
}
case KeyDel:

View File

@ -459,10 +459,7 @@ func TestLogprobsWithStopSequences(t *testing.T) {
origLogprobsLen := len(logprobs)
numTokensRemoved := origLen - newLen
newLogprobsLen := origLogprobsLen - numTokensRemoved
if newLogprobsLen < 0 {
newLogprobsLen = 0
}
newLogprobsLen := max(origLogprobsLen-numTokensRemoved, 0)
logprobs = logprobs[:newLogprobsLen]
// Verify responses were truncated correctly

View File

@ -577,10 +577,7 @@ func (s *Server) processBatch(tokenBatch *llama.Batch, embedBatch *llama.Batch)
if seq.logprobs {
origLogprobsLen := len(seq.pendingLogprobs)
numTokensRemoved := origLen - newLen
newLogprobsLen := origLogprobsLen - numTokensRemoved
if newLogprobsLen < 0 {
newLogprobsLen = 0
}
newLogprobsLen := max(origLogprobsLen-numTokensRemoved, 0)
seq.pendingLogprobs = seq.pendingLogprobs[:newLogprobsLen]
}

View File

@ -801,10 +801,7 @@ func (s *Server) computeBatch(activeBatch batchState) {
if seq.logprobs {
origLogprobsLen := len(seq.pendingLogprobs)
numTokensRemoved := origLen - newLen
newLogprobsLen := origLogprobsLen - numTokensRemoved
if newLogprobsLen < 0 {
newLogprobsLen = 0
}
newLogprobsLen := max(origLogprobsLen-numTokensRemoved, 0)
seq.pendingLogprobs = seq.pendingLogprobs[:newLogprobsLen]
}

View File

@ -33,7 +33,7 @@ func (r registryChallenge) URL() (*url.URL, error) {
values := redirectURL.Query()
values.Add("service", r.Service)
for _, s := range strings.Split(r.Scope, " ") {
for s := range strings.SplitSeq(r.Scope, " ") {
values.Add("scope", s)
}
@ -57,7 +57,7 @@ func getAuthorizationToken(ctx context.Context, challenge registryChallenge) (st
}
sha256sum := sha256.Sum256(nil)
data := []byte(fmt.Sprintf("%s,%s,%s", http.MethodGet, redirectURL.String(), base64.StdEncoding.EncodeToString([]byte(hex.EncodeToString(sha256sum[:])))))
data := fmt.Appendf(nil, "%s,%s,%s", http.MethodGet, redirectURL.String(), base64.StdEncoding.EncodeToString([]byte(hex.EncodeToString(sha256sum[:]))))
headers := make(http.Header)
signature, err := auth.Sign(ctx, data)

View File

@ -84,8 +84,7 @@ func useCaseInsensitiveTempDir(t *testing.T) bool {
// TODO(bmizerany): Print platform-specific instructions or
// link to docs on that topic.
lines := strings.Split(volumeHint, "\n")
for _, line := range lines {
for line := range strings.SplitSeq(volumeHint, "\n") {
t.Skip(line)
}
}

View File

@ -142,7 +142,7 @@ var junkName Name
func BenchmarkParseName(b *testing.B) {
b.ReportAllocs()
for range b.N {
for b.Loop() {
junkName = Parse("h/n/m:t")
}
}

View File

@ -251,7 +251,7 @@ func (s *Local) handleDelete(_ http.ResponseWriter, r *http.Request) error {
type progressUpdateJSON struct {
Error string `json:"error,omitempty,omitzero"`
Status string `json:"status,omitempty,omitzero"`
Digest blob.Digest `json:"digest,omitempty,omitzero"`
Digest blob.Digest `json:"digest,omitzero"`
Total int64 `json:"total,omitempty,omitzero"`
Completed int64 `json:"completed,omitempty,omitzero"`
}

View File

@ -74,7 +74,7 @@ func chatPrompt(ctx context.Context, m *Model, tokenize tokenizeFunc, opts *api.
return "", nil, errors.New("this model only supports one image while more than one image requested")
}
var prefix string
var prefix strings.Builder
prompt := msg.Content
for _, i := range msg.Images {
@ -85,14 +85,14 @@ func chatPrompt(ctx context.Context, m *Model, tokenize tokenizeFunc, opts *api.
imgTag := fmt.Sprintf("[img-%d]", imgData.ID)
if !strings.Contains(prompt, "[img]") {
prefix += imgTag
prefix.WriteString(imgTag)
} else {
prompt = strings.Replace(prompt, "[img]", imgTag, 1)
}
images = append(images, imgData)
}
msgs[currMsgIdx+cnt].Content = prefix + prompt
msgs[currMsgIdx+cnt].Content = prefix.String() + prompt
}
// truncate any messages that do not fit into the context window

View File

@ -12,6 +12,7 @@ import (
"io"
"io/fs"
"log/slog"
"maps"
"math"
"math/rand"
"net"
@ -1139,9 +1140,7 @@ func GetModelInfo(req api.ShowRequest) (*api.ShowResponse, error) {
if m.Options == nil {
m.Options = make(map[string]any)
}
for k, v := range req.Options {
m.Options[k] = v
}
maps.Copy(m.Options, req.Options)
}
var sb strings.Builder

View File

@ -41,7 +41,7 @@ func (m *mockRunner) Completion(ctx context.Context, r llm.CompletionRequest, fn
}
func (mockRunner) Tokenize(_ context.Context, s string) (tokens []int, err error) {
for range strings.Fields(s) {
for range strings.FieldsSeq(s) {
tokens = append(tokens, len(tokens))
}

View File

@ -432,8 +432,7 @@ func TestRoutes(t *testing.T) {
}
var params []string
paramsSplit := strings.Split(showResp.Parameters, "\n")
for _, p := range paramsSplit {
for p := range strings.SplitSeq(showResp.Parameters, "\n") {
params = append(params, strings.Join(strings.Fields(p), " "))
}
sort.Strings(params)

View File

@ -274,7 +274,7 @@ func findArguments(tool *api.Tool, buffer []byte) (map[string]any, int) {
return args, true
}
if argsStr, ok := obj[name].(string); ok {
var argsData map[string]interface{}
var argsData map[string]any
if err := json.Unmarshal([]byte(argsStr), &argsData); err == nil {
return argsData, ok
}