Enha: add agent to chat history; gen-regen diff

This commit is contained in:
Grail Finder
2024-12-05 18:36:05 +03:00
parent b9a5c681a6
commit 990e0695c5
6 changed files with 25 additions and 13 deletions

View File

@@ -43,3 +43,6 @@
- if option to show sys msg enabled: it show display new tool responses; - if option to show sys msg enabled: it show display new tool responses;
- when bot generation ended with err: need a way to switch back to the bot_resp_false mode; - when bot generation ended with err: need a way to switch back to the bot_resp_false mode;
- no selection focus on modal sys buttons after opening it a second time; - no selection focus on modal sys buttons after opening it a second time;
- chat should contain char in it (one to many: char: []chats);
- char card is the sys message, but how about giving tools to char that does not have it?
- it is a bit clumsy to mix chats in db and chars from the external files, maybe load external files in db on startup?

8
bot.go
View File

@@ -102,7 +102,7 @@ func sendMsgToLLM(body io.Reader) {
} }
} }
func chatRound(userMsg, role string, tv *tview.TextView) { func chatRound(userMsg, role string, tv *tview.TextView, regen bool) {
botRespMode = true botRespMode = true
reader := formMsg(chatBody, userMsg, role) reader := formMsg(chatBody, userMsg, role)
if reader == nil { if reader == nil {
@@ -110,7 +110,7 @@ func chatRound(userMsg, role string, tv *tview.TextView) {
return return
} }
go sendMsgToLLM(reader) go sendMsgToLLM(reader)
if userMsg != "" { // no need to write assistant icon since we continue old message if userMsg != "" && !regen { // no need to write assistant icon since we continue old message
fmt.Fprintf(tv, "(%d) ", len(chatBody.Messages)) fmt.Fprintf(tv, "(%d) ", len(chatBody.Messages))
fmt.Fprint(tv, cfg.AssistantIcon) fmt.Fprint(tv, cfg.AssistantIcon)
} }
@@ -158,12 +158,12 @@ func findCall(msg string, tv *tview.TextView) {
f, ok := fnMap[fc.Name] f, ok := fnMap[fc.Name]
if !ok { if !ok {
m := fc.Name + "%s is not implemented" m := fc.Name + "%s is not implemented"
chatRound(m, cfg.ToolRole, tv) chatRound(m, cfg.ToolRole, tv, false)
return return
} }
resp := f(fc.Args...) resp := f(fc.Args...)
toolMsg := fmt.Sprintf("tool response: %+v", string(resp)) toolMsg := fmt.Sprintf("tool response: %+v", string(resp))
chatRound(toolMsg, cfg.ToolRole, tv) chatRound(toolMsg, cfg.ToolRole, tv, false)
} }
func chatToTextSlice(showSys bool) []string { func chatToTextSlice(showSys bool) []string {

View File

@@ -10,7 +10,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; current chat: %s" indexLine = "F12 to show keys help; bot resp mode: %v; char: %s; chat: %s"
focusSwitcher = map[tview.Primitive]tview.Primitive{} focusSwitcher = map[tview.Primitive]tview.Primitive{}
) )

View File

@@ -9,6 +9,7 @@ type Chat struct {
ID uint32 `db:"id" json:"id"` ID uint32 `db:"id" json:"id"`
Name string `db:"name" json:"name"` Name string `db:"name" json:"name"`
Msgs string `db:"msgs" json:"msgs"` // []RoleMsg to string json Msgs string `db:"msgs" json:"msgs"` // []RoleMsg to string json
Agent string `db:"agent" json:"agent"`
CreatedAt time.Time `db:"created_at" json:"created_at"` CreatedAt time.Time `db:"created_at" json:"created_at"`
UpdatedAt time.Time `db:"updated_at" json:"updated_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"`
} }

View File

@@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS chats (
id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL, name TEXT NOT NULL,
msgs TEXT NOT NULL, msgs TEXT NOT NULL,
agent TEXT NOT NULL DEFAULT 'assistant',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
); );

23
tui.go
View File

@@ -33,7 +33,8 @@ var (
[yellow]F4[white]: edit msg [yellow]F4[white]: edit msg
[yellow]F5[white]: toggle system [yellow]F5[white]: toggle system
[yellow]F6[white]: interrupt bot resp [yellow]F6[white]: interrupt bot resp
[yellow]F7[white]: copy msg to clipboard (linux xclip) [yellow]F7[white]: copy last msg to clipboard (linux xclip)
[yellow]F8[white]: copy n msg to clipboard (linux xclip)
[yellow]Ctrl+s[white]: choose/replace system prompt [yellow]Ctrl+s[white]: choose/replace system prompt
Press Enter to go back Press Enter to go back
@@ -77,7 +78,7 @@ func init() {
AddItem(textArea, 0, 10, true). AddItem(textArea, 0, 10, true).
AddItem(position, 0, 1, false) AddItem(position, 0, 1, false)
updateStatusLine := func() { updateStatusLine := func() {
position.SetText(fmt.Sprintf(indexLine, botRespMode, activeChatName)) position.SetText(fmt.Sprintf(indexLine, botRespMode, cfg.AssistantRole, activeChatName))
// INFO: way too ineffective; it should be optional or removed // INFO: way too ineffective; it should be optional or removed
// tv := textView.GetText(false) // tv := textView.GetText(false)
// cq := quotesRE.ReplaceAllString(tv, `[orange]$1[white]`) // cq := quotesRE.ReplaceAllString(tv, `[orange]$1[white]`)
@@ -103,9 +104,10 @@ func init() {
chatBody.Messages = defaultStarter chatBody.Messages = defaultStarter
textView.SetText(chatToText(cfg.ShowSys)) textView.SetText(chatToText(cfg.ShowSys))
newChat := &models.Chat{ newChat := &models.Chat{
ID: id + 1, ID: id + 1,
Name: fmt.Sprintf("%v_%v", "new", time.Now().Unix()), Name: fmt.Sprintf("%v_%v", "new", time.Now().Unix()),
Msgs: string(defaultStarterBytes), Msgs: string(defaultStarterBytes),
Agent: cfg.AssistantRole,
} }
// activeChatName = path.Join(historyDir, fmt.Sprintf("%d_chat.json", time.Now().Unix())) // activeChatName = path.Join(historyDir, fmt.Sprintf("%d_chat.json", time.Now().Unix()))
activeChatName = newChat.Name activeChatName = newChat.Name
@@ -282,7 +284,7 @@ func init() {
// regen last msg // regen last msg
chatBody.Messages = chatBody.Messages[:len(chatBody.Messages)-1] chatBody.Messages = chatBody.Messages[:len(chatBody.Messages)-1]
textView.SetText(chatToText(cfg.ShowSys)) textView.SetText(chatToText(cfg.ShowSys))
go chatRound("", cfg.UserRole, textView) go chatRound("", cfg.UserRole, textView, true)
return nil return nil
} }
if event.Key() == tcell.KeyF3 && !botRespMode { if event.Key() == tcell.KeyF3 && !botRespMode {
@@ -335,6 +337,11 @@ func init() {
textArea.SetText("pressed ctrl+e", true) textArea.SetText("pressed ctrl+e", true)
return nil return nil
} }
if event.Key() == tcell.KeyCtrlA {
textArea.SetText("pressed ctrl+a", true)
// list all agents
return nil
}
if event.Key() == tcell.KeyCtrlS { if event.Key() == tcell.KeyCtrlS {
// switch sys prompt // switch sys prompt
cards, err := pngmeta.ReadDirCards(cfg.SysDir, cfg.UserRole) cards, err := pngmeta.ReadDirCards(cfg.SysDir, cfg.UserRole)
@@ -358,7 +365,7 @@ func init() {
} }
// cannot send msg in editMode or botRespMode // cannot send msg in editMode or botRespMode
if event.Key() == tcell.KeyEscape && !editMode && !botRespMode { if event.Key() == tcell.KeyEscape && !editMode && !botRespMode {
position.SetText(fmt.Sprintf(indexLine, botRespMode, activeChatName)) position.SetText(fmt.Sprintf(indexLine, botRespMode, cfg.AssistantRole, activeChatName))
// read all text into buffer // read all text into buffer
msgText := textArea.GetText() msgText := textArea.GetText()
if msgText != "" { if msgText != "" {
@@ -367,7 +374,7 @@ func init() {
textView.ScrollToEnd() textView.ScrollToEnd()
} }
// update statue line // update statue line
go chatRound(msgText, cfg.UserRole, textView) go chatRound(msgText, cfg.UserRole, textView, false)
return nil return nil
} }
if event.Key() == tcell.KeyPgUp || event.Key() == tcell.KeyPgDn { if event.Key() == tcell.KeyPgUp || event.Key() == tcell.KeyPgDn {