Add the [batch] config block (Batch type + File.Batch) and ParseSize (binary KiB/MiB/GiB byte counts) in internal/config. serve now opens the dcache store when batch is on, marks the queued/running jobs a restart killed as failed (never resumed) and observes them, builds the runner from the config with the runner's defaults filling zeros, and closes the runner on both shutdown paths. Batch is on by default; disabled = true leaves srv.Batch nil so the endpoints answer 503. Co-Authored-By: ornith-1.5-35b-a3b <ornith-1.5-35b-a3b@llama.cpp.invalid>
153 lines
3.7 KiB
Go
153 lines
3.7 KiB
Go
package config
|
|
|
|
import (
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/pelletier/go-toml/v2"
|
|
)
|
|
|
|
// File is the on-disk /etc/sift/config.toml.
|
|
type File struct {
|
|
Listen string `toml:"listen"`
|
|
UserAgent string `toml:"user_agent"`
|
|
DenyPrefixes []string `toml:"deny_prefixes"`
|
|
SelfIP SelfIP `toml:"self_ip"`
|
|
Dixie Dixie `toml:"dixie"`
|
|
Digest Digest `toml:"digest"`
|
|
Context Context `toml:"context"`
|
|
Search Search `toml:"search"`
|
|
Batch Batch `toml:"batch"`
|
|
}
|
|
|
|
// Batch is the [batch] block. Batch is on by default: no block means the runner runs with its own
|
|
// defaults. disabled = true turns it off and the endpoints answer 503.
|
|
type Batch struct {
|
|
Disabled bool `toml:"disabled"`
|
|
TargetsPerJob int `toml:"targets_per_job"`
|
|
JobsPerCaller int `toml:"jobs_per_caller"`
|
|
JobsTotal int `toml:"jobs_total"`
|
|
Workers int `toml:"workers"`
|
|
TTL string `toml:"ttl"`
|
|
MaxBytes string `toml:"max_bytes"`
|
|
}
|
|
|
|
type Dixie struct {
|
|
Chat string `toml:"chat"`
|
|
Embed string `toml:"embed"`
|
|
EmbedModel string `toml:"embed_model"`
|
|
MaxInflight int `toml:"max_inflight"`
|
|
QueueDepth int `toml:"queue_depth"`
|
|
QueueWait string `toml:"queue_wait"`
|
|
}
|
|
|
|
type Digest struct {
|
|
Model string `toml:"model"`
|
|
Thinking bool `toml:"thinking"`
|
|
Cache string `toml:"cache"`
|
|
}
|
|
|
|
type Context struct {
|
|
Honcho string `toml:"honcho"`
|
|
Workspaces []string `toml:"workspaces"`
|
|
PermitRestricted []string `toml:"permit_restricted"`
|
|
}
|
|
|
|
// Search is the [search] block. Sources default off; bake-off picks defaults.
|
|
type Search struct {
|
|
K int `toml:"k"`
|
|
Timeout string `toml:"timeout"`
|
|
Rerank *bool `toml:"rerank"`
|
|
Digest bool `toml:"digest"`
|
|
CacheTTL string `toml:"cache_ttl"`
|
|
SearxNG SearchSource `toml:"searxng"`
|
|
BraveLLM SearchSource `toml:"brave_llm"`
|
|
Tavily TavilySource `toml:"tavily"`
|
|
}
|
|
|
|
type SearchSource struct {
|
|
Enabled bool `toml:"enabled"`
|
|
URL string `toml:"url"`
|
|
NoRerank bool `toml:"no_rerank"`
|
|
}
|
|
|
|
type TavilySource struct {
|
|
Enabled bool `toml:"enabled"`
|
|
URL string `toml:"url"`
|
|
DailyCreditCap int `toml:"daily_credit_cap"`
|
|
NoRerank bool `toml:"no_rerank"`
|
|
}
|
|
|
|
func (s Search) RerankOn() bool {
|
|
if s.Rerank == nil {
|
|
return true
|
|
}
|
|
return *s.Rerank
|
|
}
|
|
|
|
func (s Search) AnyEnabled() bool {
|
|
return s.SearxNG.Enabled || s.BraveLLM.Enabled || s.Tavily.Enabled
|
|
}
|
|
|
|
// SelfIP is the [self_ip] block.
|
|
type SelfIP struct {
|
|
Sources []string `toml:"sources"`
|
|
Interval string `toml:"interval"`
|
|
KeepPrevious string `toml:"keep_previous"`
|
|
Path string `toml:"path"`
|
|
}
|
|
|
|
// Load reads path. A missing file returns a zero File and a nil error.
|
|
func Load(path string) (File, error) {
|
|
var f File
|
|
b, err := os.ReadFile(path)
|
|
if err != nil {
|
|
if os.IsNotExist(err) {
|
|
return f, nil
|
|
}
|
|
return f, err
|
|
}
|
|
if err := toml.Unmarshal(b, &f); err != nil {
|
|
return File{}, err
|
|
}
|
|
return f, nil
|
|
}
|
|
|
|
func ParseDuration(s string, def time.Duration) time.Duration {
|
|
if s == "" {
|
|
return def
|
|
}
|
|
d, err := time.ParseDuration(s)
|
|
if err != nil {
|
|
return def
|
|
}
|
|
return d
|
|
}
|
|
|
|
// ParseSize parses a positive byte count: a plain integer, or one with a binary suffix KiB, MiB or
|
|
// GiB. Anything else, zero or negative returns def.
|
|
func ParseSize(s string, def int64) int64 {
|
|
s = strings.TrimSpace(s)
|
|
if s == "" {
|
|
return def
|
|
}
|
|
var mult int64
|
|
switch {
|
|
case strings.HasSuffix(s, "KiB"):
|
|
mult, s = 1<<10, s[:len(s)-3]
|
|
case strings.HasSuffix(s, "MiB"):
|
|
mult, s = 1<<20, s[:len(s)-3]
|
|
case strings.HasSuffix(s, "GiB"):
|
|
mult, s = 1<<30, s[:len(s)-3]
|
|
default:
|
|
mult = 1
|
|
}
|
|
n, err := strconv.ParseInt(s, 10, 64)
|
|
if err != nil || n <= 0 {
|
|
return def
|
|
}
|
|
return n * mult
|
|
}
|