1 Commits

Author SHA1 Message Date
Grail Finder
cdfccf9a24 Enha (llama.cpp): show loaded model on startup 2026-03-01 08:22:02 +03:00
6 changed files with 37 additions and 43 deletions

28
bot.go
View File

@@ -379,22 +379,22 @@ func fetchLCPModels() ([]string, error) {
// fetchLCPModelsWithLoadStatus returns models with "(loaded)" indicator for loaded models // fetchLCPModelsWithLoadStatus returns models with "(loaded)" indicator for loaded models
func fetchLCPModelsWithLoadStatus() ([]string, error) { func fetchLCPModelsWithLoadStatus() ([]string, error) {
models, err := fetchLCPModelsWithStatus() modelList, err := fetchLCPModelsWithStatus()
if err != nil { if err != nil {
return nil, err return nil, err
} }
result := make([]string, 0, len(models.Data)) result := make([]string, 0, len(modelList.Data))
li := 0 // loaded index li := 0 // loaded index
for i, m := range models.Data { for i, m := range modelList.Data {
modelName := m.ID modelName := m.ID
if m.Status.Value == "loaded" { if m.Status.Value == "loaded" {
modelName = "(loaded) " + modelName modelName = models.LoadedMark + modelName
li = i li = i
} }
result = append(result, modelName) result = append(result, modelName)
} }
if li == 0 { if li == 0 {
return result, nil // no loaded models return result, nil // no loaded modelList
} }
loadedModel := result[li] loadedModel := result[li]
result = append(result[:li], result[li+1:]...) result = append(result[:li], result[li+1:]...)
@@ -1323,11 +1323,27 @@ func updateModelLists() {
} }
// if llama.cpp started after gf-lt? // if llama.cpp started after gf-lt?
localModelsMu.Lock() localModelsMu.Lock()
LocalModels, err = fetchLCPModels() LocalModels, err = fetchLCPModelsWithLoadStatus()
localModelsMu.Unlock() localModelsMu.Unlock()
if err != nil { if err != nil {
logger.Warn("failed to fetch llama.cpp models", "error", err) logger.Warn("failed to fetch llama.cpp models", "error", err)
} }
// set already loaded model in llama.cpp
if strings.Contains(cfg.CurrentAPI, "localhost") || strings.Contains(cfg.CurrentAPI, "127.0.0.1") {
localModelsMu.Lock()
defer localModelsMu.Unlock()
for i := range LocalModels {
if strings.Contains(LocalModels[i], models.LoadedMark) {
m := strings.TrimPrefix(LocalModels[i], models.LoadedMark)
cfg.CurrentModel = m
chatBody.Model = m
cachedModelColor = "green"
updateStatusLine()
app.Draw()
return
}
}
}
} }
func refreshLocalModelsIfEmpty() { func refreshLocalModelsIfEmpty() {

View File

@@ -27,7 +27,6 @@ func startModelColorUpdater() {
go func() { go func() {
ticker := time.NewTicker(5 * time.Second) ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop() defer ticker.Stop()
// Initial check // Initial check
updateCachedModelColor() updateCachedModelColor()
for range ticker.C { for range ticker.C {
@@ -42,7 +41,6 @@ func updateCachedModelColor() {
cachedModelColor = "orange" cachedModelColor = "orange"
return return
} }
// Check if model is loaded // Check if model is loaded
loaded, err := isModelLoaded(chatBody.Model) loaded, err := isModelLoaded(chatBody.Model)
if err != nil { if err != nil {

12
models/consts.go Normal file
View File

@@ -0,0 +1,12 @@
package models
const (
LoadedMark = "(loaded) "
)
type APIType int
const (
APITypeChat APIType = iota
APITypeCompletion
)

View File

@@ -519,24 +519,6 @@ type OpenAIReq struct {
// === // ===
// type LLMModels struct {
// Object string `json:"object"`
// Data []struct {
// ID string `json:"id"`
// Object string `json:"object"`
// Created int `json:"created"`
// OwnedBy string `json:"owned_by"`
// Meta struct {
// VocabType int `json:"vocab_type"`
// NVocab int `json:"n_vocab"`
// NCtxTrain int `json:"n_ctx_train"`
// NEmbd int `json:"n_embd"`
// NParams int64 `json:"n_params"`
// Size int64 `json:"size"`
// } `json:"meta"`
// } `json:"data"`
// }
type LlamaCPPReq struct { type LlamaCPPReq struct {
Model string `json:"model"` Model string `json:"model"`
Stream bool `json:"stream"` Stream bool `json:"stream"`
@@ -641,10 +623,3 @@ type ChatRoundReq struct {
Regen bool Regen bool
Resume bool Resume bool
} }
type APIType int
const (
APITypeChat APIType = iota
APITypeCompletion
)

View File

@@ -1,6 +1,7 @@
package main package main
import ( import (
"gf-lt/models"
"slices" "slices"
"strings" "strings"
@@ -51,7 +52,7 @@ func showModelSelectionPopup() {
// Find the current model index to set as selected // Find the current model index to set as selected
currentModelIndex := -1 currentModelIndex := -1
for i, model := range modelList { for i, model := range modelList {
if strings.TrimPrefix(model, "(loaded) ") == chatBody.Model { if strings.TrimPrefix(model, models.LoadedMark) == chatBody.Model {
currentModelIndex = i currentModelIndex = i
} }
modelListWidget.AddItem(model, "", 0, nil) modelListWidget.AddItem(model, "", 0, nil)
@@ -61,7 +62,7 @@ func showModelSelectionPopup() {
modelListWidget.SetCurrentItem(currentModelIndex) modelListWidget.SetCurrentItem(currentModelIndex)
} }
modelListWidget.SetSelectedFunc(func(index int, mainText string, secondaryText string, shortcut rune) { modelListWidget.SetSelectedFunc(func(index int, mainText string, secondaryText string, shortcut rune) {
modelName := strings.TrimPrefix(mainText, "(loaded) ") modelName := strings.TrimPrefix(mainText, models.LoadedMark)
chatBody.Model = modelName chatBody.Model = modelName
cfg.CurrentModel = chatBody.Model cfg.CurrentModel = chatBody.Model
pages.RemovePage("modelSelectionPopup") pages.RemovePage("modelSelectionPopup")

View File

@@ -519,21 +519,17 @@ func fileEdit(args map[string]string) []byte {
return []byte(msg) return []byte(msg)
} }
path = resolvePath(path) path = resolvePath(path)
oldString, ok := args["oldString"] oldString, ok := args["oldString"]
if !ok || oldString == "" { if !ok || oldString == "" {
msg := "oldString not provided to file_edit tool" msg := "oldString not provided to file_edit tool"
logger.Error(msg) logger.Error(msg)
return []byte(msg) return []byte(msg)
} }
newString, ok := args["newString"] newString, ok := args["newString"]
if !ok { if !ok {
newString = "" newString = ""
} }
lineNumberStr, hasLineNumber := args["lineNumber"] lineNumberStr, hasLineNumber := args["lineNumber"]
// Read file content // Read file content
content, err := os.ReadFile(path) content, err := os.ReadFile(path)
if err != nil { if err != nil {
@@ -541,10 +537,8 @@ func fileEdit(args map[string]string) []byte {
logger.Error(msg) logger.Error(msg)
return []byte(msg) return []byte(msg)
} }
fileContent := string(content) fileContent := string(content)
var replacementCount int var replacementCount int
if hasLineNumber && lineNumberStr != "" { if hasLineNumber && lineNumberStr != "" {
// Line-number based edit // Line-number based edit
lineNum, err := strconv.Atoi(lineNumberStr) lineNum, err := strconv.Atoi(lineNumberStr)
@@ -579,13 +573,11 @@ func fileEdit(args map[string]string) []byte {
fileContent = strings.ReplaceAll(fileContent, oldString, newString) fileContent = strings.ReplaceAll(fileContent, oldString, newString)
replacementCount = strings.Count(fileContent, newString) replacementCount = strings.Count(fileContent, newString)
} }
if err := os.WriteFile(path, []byte(fileContent), 0644); err != nil { if err := os.WriteFile(path, []byte(fileContent), 0644); err != nil {
msg := "failed to write file: " + err.Error() msg := "failed to write file: " + err.Error()
logger.Error(msg) logger.Error(msg)
return []byte(msg) return []byte(msg)
} }
msg := fmt.Sprintf("file edited successfully at %s (%d replacement(s))", path, replacementCount) msg := fmt.Sprintf("file edited successfully at %s (%d replacement(s))", path, replacementCount)
return []byte(msg) return []byte(msg)
} }