ronantakizawa/codereview-bench huggingface dataset:
Repository: ollama/ollama
File: server/images.go (Go)

Code before:
		First:  true,
		System: m.System,
	}

	prompts := []PromptVars{}
	var images []llm.ImageData

	for _, msg := range msgs {
		switch strings.ToLower(msg.Role) {
		case "system":
			// if this is the first message it overrides the system prompt in the modelfile
			if !currentVars.First && currentVars.System != "" {
				prompts = append(prompts, currentVars)
				currentVars = PromptVars{}
			}
			currentVars.System = msg.Content
			lastSystem = msg.Content
		case "user":
			if currentVars.Prompt != "" {
				prompts = append(prompts, currentVars)
				currentVars = PromptVars{}
			}

			currentVars.Prompt = msg.Content
			for i := range msg.Images {
				id := len(images) + i
				currentVars.Prompt += fmt.Sprintf(" [img-%d]", id)
				currentVars.Images = append(currentVars.Images, llm.ImageData{
					ID:   id,
					Data: msg.Images[i],
				})
			}

			images = append(images, currentVars.Images...)
		case "assistant":
			currentVars.Response = msg.Content
			prompts = append(prompts, currentVars)
			currentVars = PromptVars{}
		default:
			return nil, fmt.Errorf("invalid role: %s, role must be one of [system, user, assistant]", msg.Role)
		}
	}

	// Append the last set of vars if they are non-empty
	if currentVars.Prompt != "" || currentVars.System != "" {
		prompts = append(prompts, currentVars)
	}

	return &ChatHistory{
		Prompts:    prompts,
		LastSystem: lastSystem,

Review comment (bug):
Should we just reject the request at this point if there is no projector to analyze the image? It could prevent the "random response when passed image" bug we see from time to time.

Code after:
		First:  true,
		System: m.System,
	}

	prompts := []PromptVars{}
	var images []llm.ImageData

	for _, msg := range msgs {
		switch strings.ToLower(msg.Role) {
		case "system":
			// if this is the first message it overrides the system prompt in the modelfile
			if !currentVars.First && currentVars.System != "" {
				prompts = append(prompts, currentVars)
				currentVars = PromptVars{}
			}
			currentVars.System = msg.Content
			lastSystem = msg.Content
		case "user":
			if currentVars.Prompt != "" {
				prompts = append(prompts, currentVars)
				currentVars = PromptVars{}
			}

			currentVars.Prompt = msg.Content

			if len(m.ProjectorPaths) > 0 {
				for i := range msg.Images {
					id := len(images) + i
					currentVars.Prompt += fmt.Sprintf(" [img-%d]", id)
					currentVars.Images = append(currentVars.Images, llm.ImageData{
						ID:   id,
						Data: msg.Images[i],
					})
				}

				images = append(images, currentVars.Images...)
			}
		case "assistant":
			currentVars.Response = msg.Content
			prompts = append(prompts, currentVars)
			currentVars = PromptVars{}
		default:
			return nil, fmt.Errorf("invalid role: %s, role must be one of [system, user, assistant]", msg.Role)
		}
	}

	// Append the last set of vars if they are non-empty
	if currentVars.Prompt != "" || currentVars.System != "" {
		prompts = append(prompts, currentVars)
	}
Repository: ollama/ollama
File: server/prompt.go (Go)

Code before:
	}

	tokens, err := encode(rendered)
	if err != nil {
		slog.Error("failed to encode prompt", "err", err)
		return 0, err
	}

	return len(tokens), err
}

// ChatPrompt builds up a prompt from a series of messages, truncating based on context window size
func ChatPrompt(tmpl string, system string, messages []api.Message, window int, encode func(string) ([]int, error)) (string, error) {
	type prompt struct {
		System   string
		Prompt   string
		Response string

		first  bool
		images []int
		tokens int
	}

	p := prompt{first: true}

	// Set the first system prompt to the model's system prompt
	if system != "" {
		p.System = system
	}

	// iterate through messages to build up {system,user,response} prompts
	var imgId int
	var prompts []prompt
	for _, msg := range messages {
		switch strings.ToLower(msg.Role) {
		case "system":
			if !p.first && (p.System != "" || p.Prompt != "" || p.Response != "") {
				prompts = append(prompts, p)
				p = prompt{}
			}

			p.System = msg.Content
		case "user":
			if p.Prompt != "" || p.Response != "" {
				prompts = append(prompts, p)
				p = prompt{}
			}

			p.Prompt = msg.Content

			for range msg.Images {

Review comment (suggestion):
An alternative to below is to prepend a system message, which might make things a bit easier to reason about here. This could actually happen out of `ChatPrompt` and instead happen in `ChatHandler`

```
if len(messages) == 0 {
  return "", nil
}

// prepend the model system message if required
if messages[0].Role != "system" {
  messages = append({Role: "system", "Content": system}, messages...)
}

var p prompt
```

Code after:
	}

	tokens, err := encode(rendered)
	if err != nil {
		slog.Error("failed to encode prompt", "err", err)
		return 0, err
	}

	return len(tokens), err
}

// ChatPrompt builds up a prompt from a series of messages, truncating based on context window size
func ChatPrompt(tmpl string, messages []api.Message, window int, encode func(string) ([]int, error)) (string, error) {
	type prompt struct {
		System   string
		Prompt   string
		Response string

		images []int
		tokens int
	}

	var p prompt

	// iterate through messages to build up {system,user,response} prompts
	var imgId int
	var prompts []prompt
	for _, msg := range messages {
		switch strings.ToLower(msg.Role) {
		case "system":
			if p.System != "" || p.Prompt != "" || p.Response != "" {
				prompts = append(prompts, p)
				p = prompt{}
			}

			p.System = msg.Content
		case "user":
			if p.Prompt != "" || p.Response != "" {
				prompts = append(prompts, p)
				p = prompt{}
			}

			p.Prompt = msg.Content

			for range msg.Images {
				p.Prompt += fmt.Sprintf(" [img-%d]", imgId)
				p.images = append(p.images, imgId)
				imgId += 1
			}
		case "assistant":
			if p.Response != "" {
Repository: ollama/ollama
File: llm/llm.go (Go)

Code before:
	}

	f, err := os.Open(model)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	ggml, err := DecodeGGML(f)
	if err != nil {
		return nil, err
	}

	if opts.NumCtx > int(ggml.KV().ContextLength()) {
		slog.Warn("requested context length is greater than model max context length", "requested", opts.NumCtx, "model", ggml.KV().ContextLength())
		opts.NumCtx = int(ggml.KV().ContextLength())
	}

	if opts.NumCtx < 4 {
		opts.NumCtx = 4
	}

	vram, _ := gpu.CheckVRAM()
	size := ggml.Size

	// fp16 k,v matrices require = n_ctx * n_layer * n_embd / n_head * n_head_kv * 2 bytes each * 2 key and value
	kv := 2 * 2 * int64(opts.NumCtx) * int64(ggml.KV().BlockCount()) * int64(ggml.KV().EmbeddingLength()) * int64(ggml.KV().HeadCountKV()) / int64(ggml.KV().HeadCount())

	// this amount is the overhead + tensors in memory
	// TODO: get this from the llama.cpp's graph calculations instead of
	// estimating it's 1/6 * kv_cache_size * num_gqa
	graph := int64(ggml.KV().GQA()) * kv / 6

	if slices.Contains(cpuOnlyFamilies, ggml.KV().Architecture()) {
		opts.NumGPU = 0
	}

	info := gpu.GetGPUInfo()
	switch runtime.GOOS {
	case "darwin":
		if opts.NumGPU == 0 {
			break
		}

		if size+kv+graph > vram {
			slog.Info("not enough vram available, setting num_gpu=0")
			opts.NumGPU = 0
			break
		}

		// TODO: implement layer splitting on macOS

Review comment (bug):
there is a potential divide by 0 error here that didnt used to be here, although it shouldnt be possible

Code after:
	}

	f, err := os.Open(model)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	ggml, size, err := DecodeGGML(f)
	if err != nil {
		return nil, err
	}

	if opts.NumCtx > int(ggml.KV().ContextLength()) {
		slog.Warn("requested context length is greater than model max context length", "requested", opts.NumCtx, "model", ggml.KV().ContextLength())
		opts.NumCtx = int(ggml.KV().ContextLength())
	}

	if opts.NumCtx < 4 {
		opts.NumCtx = 4
	}

	vram, _ := gpu.CheckVRAM()

	// fp16 k,v matrices require = n_ctx * n_layer * n_embd / n_head * n_head_kv * 2 bytes each * 2 key and value
	kv := 2 * 2 * int64(opts.NumCtx) * int64(ggml.KV().BlockCount()) * int64(ggml.KV().EmbeddingLength()) * int64(ggml.KV().HeadCountKV()) / int64(ggml.KV().HeadCount())

	// this amount is the overhead + tensors in memory
	// TODO: get this from the llama.cpp's graph calculations instead of
	// estimating it's 1/6 * kv_cache_size * num_gqa
	graph := int64(ggml.KV().GQA()) * kv / 6

	if slices.Contains(cpuOnlyFamilies, ggml.KV().Architecture()) {
		opts.NumGPU = 0
	}

	info := gpu.GetGPUInfo()
	switch runtime.GOOS {
	case "darwin":
		if opts.NumGPU == 0 {
			break
		}

		if size+kv+graph > vram {
			slog.Info("not enough vram available, setting num_gpu=0")
			opts.NumGPU = 0
			break
		}

		// TODO: implement layer splitting on macOS
		opts.NumGPU = 999
Repository: ollama/ollama
File: cmd/cmd.go (Go)

Code before:
		Short:   "Run a model",
		Args:    cobra.MinimumNArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    RunHandler,
	}

	runCmd.Flags().Bool("verbose", false, "Show timings for response")
	runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
	runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
	runCmd.Flags().String("format", "", "Response format (e.g. json)")

	serveCmd := &cobra.Command{
		Use:     "serve",
		Aliases: []string{"start"},
		Short:   "Start ollama",
		Args:    cobra.ExactArgs(0),
		RunE:    RunServer,
	}
	serveCmd.SetUsageTemplate(serveCmd.UsageTemplate() + `
Environment Variables:

	OLLAMA_HOST
		The host:port to bind to (default "localhost:11434")

		Examples:
			"localhost:11434"
	OLLAMA_ORIGINS
		A comma separated list of allowed origins. If unset, the
		default behavior is to allow same origin requests, only.

		Examples:
			"localhost:11434"
			"example.com,api.example.com"
	OLLAMA_MODELS
		The path to the models directory (default is "~/.ollama/models")
`)

	pullCmd := &cobra.Command{
		Use:     "pull MODEL",
		Short:   "Pull a model from a registry",
		Args:    cobra.ExactArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    PullHandler,
	}

	pullCmd.Flags().Bool("insecure", false, "Use an insecure registry")

	pushCmd := &cobra.Command{
		Use:     "push MODEL",
		Short:   "Push a model to a registry",
		Args:    cobra.ExactArgs(1),

Review comment (suggestion):
```suggestion
		The host:port to bind to (default "127.0.0.1:11434")

		Examples:
			"127.0.0.1:11434"
```

Code after:
		Short:   "Run a model",
		Args:    cobra.MinimumNArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    RunHandler,
	}

	runCmd.Flags().Bool("verbose", false, "Show timings for response")
	runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
	runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
	runCmd.Flags().String("format", "", "Response format (e.g. json)")

	serveCmd := &cobra.Command{
		Use:     "serve",
		Aliases: []string{"start"},
		Short:   "Start ollama",
		Args:    cobra.ExactArgs(0),
		RunE:    RunServer,
	}
	serveCmd.SetUsageTemplate(serveCmd.UsageTemplate() + `
Environment Variables:

	OLLAMA_HOST
		The host:port to bind to (default "127.0.0.1:11434")

		Examples:
			"127.0.0.1:11434"
	OLLAMA_ORIGINS
		A comma separated list of allowed origins. If unset, the
		default behavior is to allow same origin requests, only.

		Examples:
			"localhost:11434"
			"example.com,api.example.com"
	OLLAMA_MODELS
		The path to the models directory (default is "~/.ollama/models")
`)

	pullCmd := &cobra.Command{
		Use:     "pull MODEL",
		Short:   "Pull a model from a registry",
		Args:    cobra.ExactArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    PullHandler,
	}

	pullCmd.Flags().Bool("insecure", false, "Use an insecure registry")

	pushCmd := &cobra.Command{
		Use:     "push MODEL",
		Short:   "Push a model to a registry",
		Args:    cobra.ExactArgs(1),
Repository: ollama/ollama
File: cmd/cmd.go (Go)

Code before:
		Short:   "Run a model",
		Args:    cobra.MinimumNArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    RunHandler,
	}

	runCmd.Flags().Bool("verbose", false, "Show timings for response")
	runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
	runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
	runCmd.Flags().String("format", "", "Response format (e.g. json)")

	serveCmd := &cobra.Command{
		Use:     "serve",
		Aliases: []string{"start"},
		Short:   "Start ollama",
		Args:    cobra.ExactArgs(0),
		RunE:    RunServer,
	}

	pullCmd := &cobra.Command{
		Use:     "pull MODEL",
		Short:   "Pull a model from a registry",
		Args:    cobra.ExactArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    PullHandler,
	}

	pullCmd.Flags().Bool("insecure", false, "Use an insecure registry")

	pushCmd := &cobra.Command{
		Use:     "push MODEL",
		Short:   "Push a model to a registry",
		Args:    cobra.ExactArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    PushHandler,
	}

	pushCmd.Flags().Bool("insecure", false, "Use an insecure registry")

	listCmd := &cobra.Command{
		Use:     "list",
		Aliases: []string{"ls"},
		Short:   "List models",
		PreRunE: checkServerHeartbeat,
		RunE:    ListHandler,
	}

	copyCmd := &cobra.Command{
		Use:     "cp SOURCE TARGET",
		Short:   "Copy a model",
		Args:    cobra.ExactArgs(2),

Review comment (suggestion):
not sure if we need more examples but other possible values are just the host `127.0.0.1` (default to port 11434), just the port `:11434` (default to host 127.0.0.1)

Code after:
		Short:   "Run a model",
		Args:    cobra.MinimumNArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    RunHandler,
	}

	runCmd.Flags().Bool("verbose", false, "Show timings for response")
	runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
	runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
	runCmd.Flags().String("format", "", "Response format (e.g. json)")

	serveCmd := &cobra.Command{
		Use:     "serve",
		Aliases: []string{"start"},
		Short:   "Start ollama",
		Args:    cobra.ExactArgs(0),
		RunE:    RunServer,
	}
	serveCmd.SetUsageTemplate(serveCmd.UsageTemplate() + `
Environment Variables:

	OLLAMA_HOST
		The host:port to bind to (default "127.0.0.1:11434")

		Examples:
			"127.0.0.1:11434"
	OLLAMA_ORIGINS
		A comma separated list of allowed origins. If unset, the
		default behavior is to allow same origin requests, only.

		Examples:
			"localhost:11434"
			"example.com,api.example.com"
	OLLAMA_MODELS
		The path to the models directory (default is "~/.ollama/models")
`)

	pullCmd := &cobra.Command{
		Use:     "pull MODEL",
		Short:   "Pull a model from a registry",
		Args:    cobra.ExactArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    PullHandler,
	}

	pullCmd.Flags().Bool("insecure", false, "Use an insecure registry")

	pushCmd := &cobra.Command{
		Use:     "push MODEL",
		Short:   "Push a model to a registry",
		Args:    cobra.ExactArgs(1),
Repository: ollama/ollama
File: cmd/cmd.go (Go)

Code before:
		Use:     "show MODEL",
		Short:   "Show information for a model",
		Args:    cobra.ExactArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    ShowHandler,
	}

	showCmd.Flags().Bool("license", false, "Show license of a model")
	showCmd.Flags().Bool("modelfile", false, "Show Modelfile of a model")
	showCmd.Flags().Bool("parameters", false, "Show parameters of a model")
	showCmd.Flags().Bool("template", false, "Show template of a model")
	showCmd.Flags().Bool("system", false, "Show system message of a model")

	runCmd := &cobra.Command{
		Use:     "run MODEL [PROMPT]",
		Short:   "Run a model",
		Args:    cobra.MinimumNArgs(1),
		PreRunE: checkServerHeartbeat,
		RunE:    RunHandler,
	}

	runCmd.Flags().Bool("verbose", false, "Show timings for response")
	runCmd.Flags().Bool("insecure", false, "Use an insecure registry")
	runCmd.Flags().Bool("nowordwrap", false, "Don't wrap words to the next line automatically")
	runCmd.Flags().String("format", "", "Response format (e.g. json)")
	runCmd.SetUsageTemplate(runCmd.UsageTemplate() + `
Environment Variables:

    OLLAMA_HOST
        The host:port or base URL of the ollama server (default "http://localhost:11434")

        Examples:
            "127.0.0.1:11434"
            "http://localhost:11434"
            "https://api.example.com"
`)

	serveCmd := &cobra.Command{
		Use:     "serve",
		Aliases: []string{"start"},
		Short:   "Start ollama",
		Args:    cobra.ExactArgs(0),
		RunE:    RunServer,
	}
	serveCmd.SetUsageTemplate(serveCmd.UsageTemplate() + `
Environment Variables:

    OLLAMA_HOST
        The host:port to bind to (default "127.0.0.1:11434")

        Examples:

Review comment (suggestion):
It's not just run. `list`, `pull`, `push`, `create`, `cp`, any command that calls the API takes `OLLAMA_HOST`

Code after:
		}
	}

}

func checkServerHeartbeat(cmd *cobra.Command, _ []string) error {
	client, err := api.ClientFromEnvironment()
	if err != nil {
		return err
	}
	if err := client.Heartbeat(cmd.Context()); err != nil {
		if !strings.Contains(err.Error(), " refused") {
			return err
		}
		if err := startApp(cmd.Context(), client); err != nil {
			return fmt.Errorf("could not connect to ollama app, is it running?")
		}
	}
	return nil
}

func versionHandler(cmd *cobra.Command, _ []string) {
	client, err := api.ClientFromEnvironment()
	if err != nil {
		return
	}

	serverVersion, err := client.Version(cmd.Context())
	if err != nil {
		fmt.Println("Warning: could not connect to a running Ollama instance")
	}

	if serverVersion != "" {
		fmt.Printf("ollama version is %s\n", serverVersion)
	}

	if serverVersion != version.Version {
		fmt.Printf("Warning: client version is %s\n", version.Version)
	}
}

func appendHostEnvDocs(cmd *cobra.Command) {
	const hostEnvDocs = `
Environment Variables:
      OLLAMA_HOST        The host:port or base URL of the Ollama server (e.g. http://localhost:11434)
`
	cmd.SetUsageTemplate(cmd.UsageTemplate() + hostEnvDocs)
}

func NewCLI() *cobra.Command {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
Repository: ollama/ollama
File: scripts/install.sh (Shell)

Code before:

    echo $MISSING
}

[ "$(uname -s)" = "Linux" ] || error 'This script is intended to run on Linux only.'

ARCH=$(uname -m)
case "$ARCH" in
    x86_64) ARCH="amd64" ;;
    aarch64|arm64) ARCH="arm64" ;;
    *) error "Unsupported architecture: $ARCH" ;;
esac

KERN=$(uname -r)
case "$KERN" in
    *icrosoft*WSL2 | *icrosoft*wsl2) ;;
    *icrosoft) error "Microsoft WSL1 is not currently supported. Please upgrade to WSL2 with 'wsl --set-version <distro> 2'" ;;
    *) ;;
esac

OLLAMA_VERSION=${OLLAMA_VERSION:-""}
if [ -z "${OLLAMA_VERSION}" ]; then
    VER_PARAM=""
else
    VER_PARAM="?version=${OLLAMA_VERSION}"
fi


SUDO=
if [ "$(id -u)" -ne 0 ]; then
    # Running as root, no need for sudo
    if ! available sudo; then
        error "This script requires superuser permissions. Please re-run as root."
    fi

    SUDO="sudo"
fi

NEEDS=$(require curl awk grep sed tee xargs)
if [ -n "$NEEDS" ]; then
    status "ERROR: The following tools are required but missing:"
    for NEED in $NEEDS; do
        echo "  - $NEED"
    done
    exit 1
fi

status "Downloading ollama..."
curl --fail --show-error --location --progress-bar -o $TEMP_DIR/ollama "https://ollama.com/download/ollama-linux-${ARCH}${VER_PARAM}"

for BINDIR in /usr/local/bin /usr/bin /bin; do

Review comment (suggestion):
This produces the same thing
```suggestion
VER_PARAM="${OLLAMA_VERSION:+?version=$OLLAMA_VERSION}"
```

Code after:

    echo $MISSING
}

[ "$(uname -s)" = "Linux" ] || error 'This script is intended to run on Linux only.'

ARCH=$(uname -m)
case "$ARCH" in
    x86_64) ARCH="amd64" ;;
    aarch64|arm64) ARCH="arm64" ;;
    *) error "Unsupported architecture: $ARCH" ;;
esac

KERN=$(uname -r)
case "$KERN" in
    *icrosoft*WSL2 | *icrosoft*wsl2) ;;
    *icrosoft) error "Microsoft WSL1 is not currently supported. Please upgrade to WSL2 with 'wsl --set-version <distro> 2'" ;;
    *) ;;
esac

VER_PARAM="${OLLAMA_VERSION:+?version=$OLLAMA_VERSION}"

SUDO=
if [ "$(id -u)" -ne 0 ]; then
    # Running as root, no need for sudo
    if ! available sudo; then
        error "This script requires superuser permissions. Please re-run as root."
    fi

    SUDO="sudo"
fi

NEEDS=$(require curl awk grep sed tee xargs)
if [ -n "$NEEDS" ]; then
    status "ERROR: The following tools are required but missing:"
    for NEED in $NEEDS; do
        echo "  - $NEED"
    done
    exit 1
fi

status "Downloading ollama..."
curl --fail --show-error --location --progress-bar -o $TEMP_DIR/ollama "https://ollama.com/download/ollama-linux-${ARCH}${VER_PARAM}"

for BINDIR in /usr/local/bin /usr/bin /bin; do
    echo $PATH | grep -q $BINDIR && break || continue
done

status "Installing ollama to $BINDIR..."
$SUDO install -o0 -g0 -m755 -d $BINDIR
$SUDO install -o0 -g0 -m755 $TEMP_DIR/ollama $BINDIR/ollama
Repository: ollama/ollama
File: api/types.go (Go)

Code before:

type Duration struct {
	time.Duration
}

func (d *Duration) UnmarshalJSON(b []byte) (err error) {
	var v any
	if err := json.Unmarshal(b, &v); err != nil {
		return err
	}

	d.Duration = 5 * time.Minute

	switch t := v.(type) {
	case float64:
		if t < 0 {
			d.Duration = time.Duration(math.MaxInt64)
		} else {
			d.Duration = time.Duration(t * float64(time.Second))
		}
	case string:
		d.Duration, err = time.ParseDuration(t)
		if err != nil {
			return err
		}
		if d.Duration < 0 {
			d.Duration = time.Duration(math.MaxInt64)
		}
	}

	return nil
}

// FormatParams converts specified parameter options to their correct types
func FormatParams(params map[string][]string) (map[string]interface{}, 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

	// build map of json struct tags to their types
	jsonOpts := make(map[string]reflect.StructField)
	for _, field := range reflect.VisibleFields(typeOpts) {
		jsonTag := strings.Split(field.Tag.Get("json"), ",")[0]
		if jsonTag != "" {
			jsonOpts[jsonTag] = field
		}
	}

	out := make(map[string]interface{})
	// iterate params and set values based on json struct tags
	for key, vals := range params {

Review comment (suggestion):
I switched this to just handle everything as an int. I don't think we need anything more granular than that.

Code after:

type Duration struct {
	time.Duration
}

func (d Duration) MarshalJSON() ([]byte, error) {
	if d.Duration < 0 {
		return []byte("-1"), nil
	}
	return []byte("\"" + d.Duration.String() + "\""), nil
}

func (d *Duration) UnmarshalJSON(b []byte) (err error) {
	var v any
	if err := json.Unmarshal(b, &v); err != nil {
		return err
	}

	d.Duration = 5 * time.Minute

	switch t := v.(type) {
	case float64:
		if t < 0 {
			d.Duration = time.Duration(math.MaxInt64)
		} else {
			d.Duration = time.Duration(int(t) * int(time.Second))
		}
	case string:
		d.Duration, err = time.ParseDuration(t)
		if err != nil {
			return err
		}
		if d.Duration < 0 {
			d.Duration = time.Duration(math.MaxInt64)
		}
	default:
		return fmt.Errorf("Unsupported type: '%s'", reflect.TypeOf(v))
	}

	return nil
}

// FormatParams converts specified parameter options to their correct types
func FormatParams(params map[string][]string) (map[string]interface{}, 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

	// build map of json struct tags to their types
	jsonOpts := make(map[string]reflect.StructField)
	for _, field := range reflect.VisibleFields(typeOpts) {