mirror of
https://github.com/coalaura/whiskr.git
synced 2025-12-02 20:22:52 +00:00
auto-update model list and show creation date
This commit is contained in:
4
chat.go
4
chat.go
@@ -101,8 +101,8 @@ func (r *Request) Parse() (*openrouter.ChatCompletionRequest, int, error) {
|
||||
toolIndex int
|
||||
)
|
||||
|
||||
model, ok := ModelMap[r.Model]
|
||||
if !ok {
|
||||
model := GetModel(r.Model)
|
||||
if model == nil {
|
||||
return nil, 0, fmt.Errorf("unknown model: %q", r.Model)
|
||||
}
|
||||
|
||||
|
||||
7
main.go
7
main.go
@@ -19,7 +19,7 @@ func main() {
|
||||
icons, err := LoadIcons()
|
||||
log.MustFail(err)
|
||||
|
||||
models, err := LoadModels()
|
||||
err = StartModelUpdateLoop()
|
||||
log.MustFail(err)
|
||||
|
||||
tokenizer, err := LoadTokenizer(TikTokenSource)
|
||||
@@ -35,6 +35,9 @@ func main() {
|
||||
r.Handle("/*", cache(http.StripPrefix("/", fs)))
|
||||
|
||||
r.Get("/-/data", func(w http.ResponseWriter, r *http.Request) {
|
||||
modelMx.RLock()
|
||||
defer modelMx.RUnlock()
|
||||
|
||||
RespondJson(w, http.StatusOK, map[string]any{
|
||||
"authenticated": IsAuthenticated(r),
|
||||
"config": map[string]any{
|
||||
@@ -43,7 +46,7 @@ func main() {
|
||||
"motion": env.UI.ReducedMotion,
|
||||
},
|
||||
"icons": icons,
|
||||
"models": models,
|
||||
"models": ModelList,
|
||||
"prompts": Prompts,
|
||||
"version": Version,
|
||||
})
|
||||
|
||||
71
models.go
71
models.go
@@ -4,12 +4,15 @@ import (
|
||||
"context"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/revrost/go-openrouter"
|
||||
)
|
||||
|
||||
type Model struct {
|
||||
ID string `json:"id"`
|
||||
Created int64 `json:"created"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
@@ -21,23 +24,64 @@ type Model struct {
|
||||
Images bool `json:"-"`
|
||||
}
|
||||
|
||||
var ModelMap = make(map[string]*Model)
|
||||
var (
|
||||
modelMx sync.RWMutex
|
||||
|
||||
func LoadModels() ([]*Model, error) {
|
||||
log.Println("Loading models...")
|
||||
ModelMap map[string]*Model
|
||||
ModelList []*Model
|
||||
)
|
||||
|
||||
func GetModel(name string) *Model {
|
||||
modelMx.RLock()
|
||||
defer modelMx.RUnlock()
|
||||
|
||||
return ModelMap[name]
|
||||
}
|
||||
|
||||
func StartModelUpdateLoop() error {
|
||||
err := LoadModels(true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
ticker := time.NewTicker(2 * time.Hour)
|
||||
|
||||
for range ticker.C {
|
||||
err := LoadModels(false)
|
||||
if err != nil {
|
||||
log.Warnln(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func LoadModels(initial bool) error {
|
||||
log.Println("Refreshing model list...")
|
||||
|
||||
client := OpenRouterClient()
|
||||
|
||||
list, err := client.ListUserModels(context.Background())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
if !initial && len(list) == len(ModelList) {
|
||||
log.Println("No new models, skipping update")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
return list[i].Created > list[j].Created
|
||||
})
|
||||
|
||||
models := make([]*Model, len(list))
|
||||
var (
|
||||
newList = make([]*Model, len(list))
|
||||
newMap = make(map[string]*Model, len(list))
|
||||
)
|
||||
|
||||
for index, model := range list {
|
||||
name := model.Name
|
||||
@@ -48,20 +92,27 @@ func LoadModels() ([]*Model, error) {
|
||||
|
||||
m := &Model{
|
||||
ID: model.ID,
|
||||
Created: model.Created,
|
||||
Name: name,
|
||||
Description: model.Description,
|
||||
}
|
||||
|
||||
GetModelTags(model, m)
|
||||
|
||||
models[index] = m
|
||||
|
||||
ModelMap[model.ID] = m
|
||||
newList[index] = m
|
||||
newMap[model.ID] = m
|
||||
}
|
||||
|
||||
log.Printf("Loaded %d models\n", len(models))
|
||||
log.Printf("Loaded %d models\n", len(newList))
|
||||
|
||||
return models, nil
|
||||
modelMx.Lock()
|
||||
|
||||
ModelList = newList
|
||||
ModelMap = newMap
|
||||
|
||||
modelMx.Unlock()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetModelTags(model openrouter.Model, m *Model) {
|
||||
|
||||
@@ -1451,7 +1451,7 @@
|
||||
// render models
|
||||
fillSelect($model, data.models, (el, model) => {
|
||||
el.value = model.id;
|
||||
el.title = model.description;
|
||||
el.title = `${model.name} (${formatTimestamp(model.created)})\n---\n${model.description}`;
|
||||
el.textContent = model.name;
|
||||
|
||||
el.dataset.tags = (model.tags || []).join(",");
|
||||
|
||||
@@ -97,7 +97,6 @@
|
||||
// option label
|
||||
const _label = make("div", "label");
|
||||
|
||||
_label.title = option.label;
|
||||
_label.textContent = option.label;
|
||||
|
||||
_opt.appendChild(_label);
|
||||
|
||||
@@ -56,6 +56,10 @@ function formatMilliseconds(ms) {
|
||||
return `${Math.round(ms / 1000)}s`;
|
||||
}
|
||||
|
||||
function formatTimestamp(ts) {
|
||||
return new Date(ts * 1000).toLocaleDateString();
|
||||
}
|
||||
|
||||
function dataBlob(dataUrl) {
|
||||
const [header, data] = dataUrl.split(","),
|
||||
mime = header.match(/data:(.*?)(;|$)/)[1];
|
||||
|
||||
Reference in New Issue
Block a user