Fix: thinking

This commit is contained in:
Grail Finder
2025-02-15 08:46:33 +03:00
parent 2b9c44eff9
commit 83babd0271
6 changed files with 40 additions and 11 deletions

8
bot.go
View File

@@ -39,7 +39,7 @@ var (
chunkParser ChunkParser chunkParser ChunkParser
defaultLCPProps = map[string]float32{ defaultLCPProps = map[string]float32{
"temperature": 0.8, "temperature": 0.8,
"dry_multiplier": 0.6, "dry_multiplier": 0.0,
"min_p": 0.05, "min_p": 0.05,
"n_predict": -1.0, "n_predict": -1.0,
} }
@@ -108,6 +108,7 @@ func sendMsgToLLM(body io.Reader) {
} }
// starts with -> data: // starts with -> data:
line = line[6:] line = line[6:]
logger.Info("debugging resp", "line", string(line))
content, stop, err := chunkParser.ParseChunk(line) content, stop, err := chunkParser.ParseChunk(line)
if err != nil { if err != nil {
logger.Error("error parsing response body", "error", err, "line", string(line), "url", cfg.CurrentAPI) logger.Error("error parsing response body", "error", err, "line", string(line), "url", cfg.CurrentAPI)
@@ -185,6 +186,10 @@ func chatRound(userMsg, role string, tv *tview.TextView, regen bool) {
fmt.Fprintf(tv, "(%d) ", len(chatBody.Messages)) fmt.Fprintf(tv, "(%d) ", len(chatBody.Messages))
fmt.Fprint(tv, roleToIcon(cfg.AssistantRole)) fmt.Fprint(tv, roleToIcon(cfg.AssistantRole))
fmt.Fprint(tv, "\n") fmt.Fprint(tv, "\n")
if cfg.ThinkUse && !strings.Contains(cfg.CurrentAPI, "v1") {
// fmt.Fprint(tv, "<think>")
chunkChan <- "<think>"
}
} }
respText := strings.Builder{} respText := strings.Builder{}
out: out:
@@ -201,6 +206,7 @@ out:
} }
} }
botRespMode = false botRespMode = false
// how can previous messages be affected?
chatBody.Messages = append(chatBody.Messages, models.RoleMsg{ chatBody.Messages = append(chatBody.Messages, models.RoleMsg{
Role: cfg.AssistantRole, Content: respText.String(), Role: cfg.AssistantRole, Content: respText.String(),
}) })

View File

@@ -17,6 +17,7 @@ type Config struct {
UserRole string `toml:"UserRole"` UserRole string `toml:"UserRole"`
ToolRole string `toml:"ToolRole"` ToolRole string `toml:"ToolRole"`
ToolUse bool `toml:"ToolUse"` ToolUse bool `toml:"ToolUse"`
ThinkUse bool `toml:"ThinkUse"`
AssistantRole string `toml:"AssistantRole"` AssistantRole string `toml:"AssistantRole"`
SysDir string `toml:"SysDir"` SysDir string `toml:"SysDir"`
ChunkLimit uint32 `toml:"ChunkLimit"` ChunkLimit uint32 `toml:"ChunkLimit"`

11
llm.go
View File

@@ -30,9 +30,6 @@ type OpenAIer struct {
func (lcp LlamaCPPeer) FormMsg(msg, role string) (io.Reader, error) { func (lcp LlamaCPPeer) FormMsg(msg, role string) (io.Reader, error) {
if msg != "" { // otherwise let the bot continue if msg != "" { // otherwise let the bot continue
// if role == cfg.UserRole {
// msg = msg + cfg.AssistantRole + ":"
// }
newMsg := models.RoleMsg{Role: role, Content: msg} newMsg := models.RoleMsg{Role: role, Content: msg}
chatBody.Messages = append(chatBody.Messages, newMsg) chatBody.Messages = append(chatBody.Messages, newMsg)
// if rag // if rag
@@ -51,11 +48,17 @@ func (lcp LlamaCPPeer) FormMsg(msg, role string) (io.Reader, error) {
messages[i] = m.ToPrompt() messages[i] = m.ToPrompt()
} }
prompt := strings.Join(messages, "\n") prompt := strings.Join(messages, "\n")
// strings builder?
if cfg.ToolUse && msg != "" { if cfg.ToolUse && msg != "" {
prompt += "\n" + cfg.ToolRole + ":\n" + toolSysMsg prompt += "\n" + cfg.ToolRole + ":\n" + toolSysMsg
} }
botMsgStart := "\n" + cfg.AssistantRole + ":\n" botMsgStart := "\n" + cfg.AssistantRole + ":\n"
payload := models.NewLCPReq(prompt+botMsgStart, cfg, defaultLCPProps) prompt += botMsgStart
// if cfg.ThinkUse && msg != "" && !cfg.ToolUse {
if cfg.ThinkUse && !cfg.ToolUse {
prompt += "<think>"
}
payload := models.NewLCPReq(prompt, cfg, defaultLCPProps)
data, err := json.Marshal(payload) data, err := json.Marshal(payload)
if err != nil { if err != nil {
logger.Error("failed to form a msg", "error", err) logger.Error("failed to form a msg", "error", err)

View File

@@ -12,7 +12,7 @@ var (
botRespMode = false botRespMode = false
editMode = false editMode = false
selectedIndex = int(-1) selectedIndex = int(-1)
indexLine = "F12 to show keys help | bot resp mode: %v (F6) | char: %s (ctrl+s) | chat: %s (F1) | RAGEnabled: %v (F11) | toolUseAdviced: %v (ctrl+k) | model: %s (ctrl+l)\nAPI_URL: %s (ctrl+v)" indexLine = "F12 to show keys help | bot resp mode: %v (F6) | char: %s (ctrl+s) | chat: %s (F1) | RAGEnabled: %v (F11) | toolUseAdviced: %v (ctrl+k) | model: %s (ctrl+l)\nAPI_URL: %s (ctrl+v) | ThinkUse: %v (ctrl+p)"
focusSwitcher = map[tview.Primitive]tview.Primitive{} focusSwitcher = map[tview.Primitive]tview.Primitive{}
) )

View File

@@ -12,7 +12,7 @@ var (
toolCallRE = regexp.MustCompile(`__tool_call__\s*([\s\S]*?)__tool_call__`) toolCallRE = regexp.MustCompile(`__tool_call__\s*([\s\S]*?)__tool_call__`)
quotesRE = regexp.MustCompile(`(".*?")`) quotesRE = regexp.MustCompile(`(".*?")`)
starRE = regexp.MustCompile(`(\*.*?\*)`) starRE = regexp.MustCompile(`(\*.*?\*)`)
thinkRE = regexp.MustCompile(`(<think>.*?</think>)`) thinkRE = regexp.MustCompile(`(<think>\s*([\s\S]*?)</think>)`)
codeBlockRE = regexp.MustCompile(`(?s)\x60{3}(?:.*?)\n(.*?)\n\s*\x60{3}\s*`) codeBlockRE = regexp.MustCompile(`(?s)\x60{3}(?:.*?)\n(.*?)\n\s*\x60{3}\s*`)
basicSysMsg = `Large Language Model that helps user with any of his requests.` basicSysMsg = `Large Language Model that helps user with any of his requests.`
toolSysMsg = `You can do functions call if needed. toolSysMsg = `You can do functions call if needed.

27
tui.go
View File

@@ -65,7 +65,7 @@ var (
[yellow]Ctrl+t[white]: remove thinking (<think>) and tool messages from context (delete from chat) [yellow]Ctrl+t[white]: remove thinking (<think>) and tool messages from context (delete from chat)
[yellow]Ctrl+l[white]: update connected model name (llamacpp) [yellow]Ctrl+l[white]: update connected model name (llamacpp)
[yellow]Ctrl+k[white]: switch tool use (recommend tool use to llm after user msg) [yellow]Ctrl+k[white]: switch tool use (recommend tool use to llm after user msg)
[yellow]Ctrl+i[white]: if chat agent is char.png will show the image; then any key to return [yellow]Ctrl+j[white]: if chat agent is char.png will show the image; then any key to return
Press Enter to go back Press Enter to go back
` `
@@ -97,6 +97,10 @@ func colorText() {
var codeBlocks []string var codeBlocks []string
placeholder := "__CODE_BLOCK_%d__" placeholder := "__CODE_BLOCK_%d__"
counter := 0 counter := 0
// thinking
var thinkBlocks []string
placeholderThink := "__THINK_BLOCK_%d__"
counterThink := 0
// Replace code blocks with placeholders and store their styled versions // Replace code blocks with placeholders and store their styled versions
text = codeBlockRE.ReplaceAllStringFunc(text, func(match string) string { text = codeBlockRE.ReplaceAllStringFunc(text, func(match string) string {
// Style the code block and store it // Style the code block and store it
@@ -107,19 +111,31 @@ func colorText() {
counter++ counter++
return id return id
}) })
text = thinkRE.ReplaceAllStringFunc(text, func(match string) string {
// Style the code block and store it
styled := fmt.Sprintf("[red::i]%s[-:-:-]", match)
thinkBlocks = append(codeBlocks, styled)
// Generate a unique placeholder (e.g., "__CODE_BLOCK_0__")
id := fmt.Sprintf(placeholderThink, counterThink)
counter++
return id
})
// Step 2: Apply other regex styles to the non-code parts // Step 2: Apply other regex styles to the non-code parts
text = quotesRE.ReplaceAllString(text, `[orange::-]$1[-:-:-]`) text = quotesRE.ReplaceAllString(text, `[orange::-]$1[-:-:-]`)
text = starRE.ReplaceAllString(text, `[turquoise::i]$1[-:-:-]`) text = starRE.ReplaceAllString(text, `[turquoise::i]$1[-:-:-]`)
text = thinkRE.ReplaceAllString(text, `[turquoise::i]$1[-:-:-]`) // text = thinkRE.ReplaceAllString(text, `[yellow::i]$1[-:-:-]`)
// Step 3: Restore the styled code blocks from placeholders // Step 3: Restore the styled code blocks from placeholders
for i, cb := range codeBlocks { for i, cb := range codeBlocks {
text = strings.Replace(text, fmt.Sprintf(placeholder, i), cb, 1) text = strings.Replace(text, fmt.Sprintf(placeholder, i), cb, 1)
} }
for i, tb := range thinkBlocks {
text = strings.Replace(text, fmt.Sprintf(placeholderThink, i), tb, 1)
}
textView.SetText(text) textView.SetText(text)
} }
func updateStatusLine() { func updateStatusLine() {
position.SetText(fmt.Sprintf(indexLine, botRespMode, cfg.AssistantRole, activeChatName, cfg.RAGEnabled, cfg.ToolUse, currentModel, cfg.CurrentAPI)) position.SetText(fmt.Sprintf(indexLine, botRespMode, cfg.AssistantRole, activeChatName, cfg.RAGEnabled, cfg.ToolUse, currentModel, cfg.CurrentAPI, cfg.ThinkUse))
} }
func initSysCards() ([]string, error) { func initSysCards() ([]string, error) {
@@ -167,6 +183,9 @@ func startNewChat() {
func makePropsForm(props map[string]float32) *tview.Form { func makePropsForm(props map[string]float32) *tview.Form {
form := tview.NewForm(). form := tview.NewForm().
AddTextView("Notes", "Props for llamacpp completion call", 40, 2, true, false). AddTextView("Notes", "Props for llamacpp completion call", 40, 2, true, false).
AddCheckbox("Insert <think> (/completion only)", cfg.ThinkUse, func(checked bool) {
cfg.ThinkUse = checked
}).
AddButton("Quit", func() { AddButton("Quit", func() {
pages.RemovePage(propsPage) pages.RemovePage(propsPage)
}) })
@@ -588,7 +607,7 @@ func init() {
updateStatusLine() updateStatusLine()
return nil return nil
} }
if event.Key() == tcell.KeyCtrlI { if event.Key() == tcell.KeyCtrlJ {
// show image // show image
loadImage() loadImage()
pages.AddPage(imgPage, imgView, true, true) pages.AddPage(imgPage, imgView, true, true)