Enha: summary agent
This commit is contained in:
51
bot.go
51
bot.go
@@ -69,7 +69,6 @@ var (
|
|||||||
"meta-llama/llama-3.3-70b-instruct:free",
|
"meta-llama/llama-3.3-70b-instruct:free",
|
||||||
}
|
}
|
||||||
LocalModels = []string{}
|
LocalModels = []string{}
|
||||||
lastSummary string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// cleanNullMessages removes messages with null or empty content to prevent API issues
|
// cleanNullMessages removes messages with null or empty content to prevent API issues
|
||||||
@@ -627,22 +626,8 @@ func checkGame(role string, tv *tview.TextView) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func chatRound(userMsg, role string, tv *tview.TextView, regen, resume, summaryMode bool) {
|
func chatRound(userMsg, role string, tv *tview.TextView, regen, resume bool) {
|
||||||
botRespMode = true
|
botRespMode = true
|
||||||
if summaryMode {
|
|
||||||
// Save original messages
|
|
||||||
originalMessages := chatBody.Messages
|
|
||||||
defer func() { chatBody.Messages = originalMessages }()
|
|
||||||
// Build summary prompt messages
|
|
||||||
summaryMessages := []models.RoleMsg{}
|
|
||||||
// Add system instruction
|
|
||||||
summaryMessages = append(summaryMessages, models.RoleMsg{Role: "system", Content: "Please provide a concise summary of the following conversation. Focus on key points, decisions, and actions. Provide only the summary, no additional commentary."})
|
|
||||||
// Append all original messages (excluding system? keep them)
|
|
||||||
summaryMessages = append(summaryMessages, originalMessages...)
|
|
||||||
// Add a user message to trigger summary
|
|
||||||
summaryMessages = append(summaryMessages, models.RoleMsg{Role: cfg.UserRole, Content: "Summarize the conversation."})
|
|
||||||
chatBody.Messages = summaryMessages
|
|
||||||
}
|
|
||||||
botPersona := cfg.AssistantRole
|
botPersona := cfg.AssistantRole
|
||||||
if cfg.WriteNextMsgAsCompletionAgent != "" {
|
if cfg.WriteNextMsgAsCompletionAgent != "" {
|
||||||
botPersona = cfg.WriteNextMsgAsCompletionAgent
|
botPersona = cfg.WriteNextMsgAsCompletionAgent
|
||||||
@@ -672,7 +657,7 @@ func chatRound(userMsg, role string, tv *tview.TextView, regen, resume, summaryM
|
|||||||
}
|
}
|
||||||
go sendMsgToLLM(reader)
|
go sendMsgToLLM(reader)
|
||||||
logger.Debug("looking at vars in chatRound", "msg", userMsg, "regen", regen, "resume", resume)
|
logger.Debug("looking at vars in chatRound", "msg", userMsg, "regen", regen, "resume", resume)
|
||||||
if !summaryMode && !resume {
|
if !resume {
|
||||||
fmt.Fprintf(tv, "\n[-:-:b](%d) ", len(chatBody.Messages))
|
fmt.Fprintf(tv, "\n[-:-:b](%d) ", len(chatBody.Messages))
|
||||||
fmt.Fprint(tv, roleToIcon(botPersona))
|
fmt.Fprint(tv, roleToIcon(botPersona))
|
||||||
fmt.Fprint(tv, "[-:-:-]\n")
|
fmt.Fprint(tv, "[-:-:-]\n")
|
||||||
@@ -719,9 +704,6 @@ out:
|
|||||||
Role: botPersona, Content: respText.String(),
|
Role: botPersona, Content: respText.String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if summaryMode {
|
|
||||||
lastSummary = respText.String()
|
|
||||||
}
|
|
||||||
logger.Debug("chatRound: before cleanChatBody", "messages_before_clean", len(chatBody.Messages))
|
logger.Debug("chatRound: before cleanChatBody", "messages_before_clean", len(chatBody.Messages))
|
||||||
for i, msg := range chatBody.Messages {
|
for i, msg := range chatBody.Messages {
|
||||||
logger.Debug("chatRound: before cleaning", "index", i, "role", msg.Role, "content_len", len(msg.Content), "has_content", msg.HasContent(), "tool_call_id", msg.ToolCallID)
|
logger.Debug("chatRound: before cleaning", "index", i, "role", msg.Role, "content_len", len(msg.Content), "has_content", msg.HasContent(), "tool_call_id", msg.ToolCallID)
|
||||||
@@ -732,19 +714,15 @@ out:
|
|||||||
for i, msg := range chatBody.Messages {
|
for i, msg := range chatBody.Messages {
|
||||||
logger.Debug("chatRound: after cleaning", "index", i, "role", msg.Role, "content_len", len(msg.Content), "has_content", msg.HasContent(), "tool_call_id", msg.ToolCallID)
|
logger.Debug("chatRound: after cleaning", "index", i, "role", msg.Role, "content_len", len(msg.Content), "has_content", msg.HasContent(), "tool_call_id", msg.ToolCallID)
|
||||||
}
|
}
|
||||||
if !summaryMode {
|
|
||||||
colorText()
|
colorText()
|
||||||
updateStatusLine()
|
updateStatusLine()
|
||||||
}
|
|
||||||
// bot msg is done;
|
// bot msg is done;
|
||||||
// now check it for func call
|
// now check it for func call
|
||||||
// logChat(activeChatName, chatBody.Messages)
|
// logChat(activeChatName, chatBody.Messages)
|
||||||
if !summaryMode {
|
|
||||||
if err := updateStorageChat(activeChatName, chatBody.Messages); err != nil {
|
if err := updateStorageChat(activeChatName, chatBody.Messages); err != nil {
|
||||||
logger.Warn("failed to update storage", "error", err, "name", activeChatName)
|
logger.Warn("failed to update storage", "error", err, "name", activeChatName)
|
||||||
}
|
}
|
||||||
findCall(respText.String(), toolResp.String(), tv)
|
findCall(respText.String(), toolResp.String(), tv)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanChatBody removes messages with null or empty content to prevent API issues
|
// cleanChatBody removes messages with null or empty content to prevent API issues
|
||||||
@@ -847,7 +825,7 @@ func findCall(msg, toolCall string, tv *tview.TextView) {
|
|||||||
chatBody.Messages = append(chatBody.Messages, toolResponseMsg)
|
chatBody.Messages = append(chatBody.Messages, toolResponseMsg)
|
||||||
// Clear the stored tool call ID after using it (no longer needed)
|
// Clear the stored tool call ID after using it (no longer needed)
|
||||||
// Trigger the assistant to continue processing with the error message
|
// Trigger the assistant to continue processing with the error message
|
||||||
chatRound("", cfg.AssistantRole, tv, false, false, false)
|
chatRound("", cfg.AssistantRole, tv, false, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
lastToolCall.Args = openAIToolMap
|
lastToolCall.Args = openAIToolMap
|
||||||
@@ -880,7 +858,7 @@ func findCall(msg, toolCall string, tv *tview.TextView) {
|
|||||||
chatBody.Messages = append(chatBody.Messages, toolResponseMsg)
|
chatBody.Messages = append(chatBody.Messages, toolResponseMsg)
|
||||||
logger.Debug("findCall: added tool error response", "role", toolResponseMsg.Role, "content_len", len(toolResponseMsg.Content), "message_count_after_add", len(chatBody.Messages))
|
logger.Debug("findCall: added tool error response", "role", toolResponseMsg.Role, "content_len", len(toolResponseMsg.Content), "message_count_after_add", len(chatBody.Messages))
|
||||||
// Trigger the assistant to continue processing with the error message
|
// Trigger the assistant to continue processing with the error message
|
||||||
chatRound("", cfg.AssistantRole, tv, false, false, false)
|
chatRound("", cfg.AssistantRole, tv, false, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Update lastToolCall with parsed function call
|
// Update lastToolCall with parsed function call
|
||||||
@@ -913,7 +891,7 @@ func findCall(msg, toolCall string, tv *tview.TextView) {
|
|||||||
lastToolCall.ID = ""
|
lastToolCall.ID = ""
|
||||||
// Trigger the assistant to continue processing with the new tool response
|
// Trigger the assistant to continue processing with the new tool response
|
||||||
// by calling chatRound with empty content to continue the assistant's response
|
// by calling chatRound with empty content to continue the assistant's response
|
||||||
chatRound("", cfg.AssistantRole, tv, false, false, false)
|
chatRound("", cfg.AssistantRole, tv, false, false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
resp := callToolWithAgent(fc.Name, fc.Args)
|
resp := callToolWithAgent(fc.Name, fc.Args)
|
||||||
@@ -933,7 +911,7 @@ func findCall(msg, toolCall string, tv *tview.TextView) {
|
|||||||
lastToolCall.ID = ""
|
lastToolCall.ID = ""
|
||||||
// Trigger the assistant to continue processing with the new tool response
|
// Trigger the assistant to continue processing with the new tool response
|
||||||
// by calling chatRound with empty content to continue the assistant's response
|
// by calling chatRound with empty content to continue the assistant's response
|
||||||
chatRound("", cfg.AssistantRole, tv, false, false, false)
|
chatRound("", cfg.AssistantRole, tv, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func chatToTextSlice(showSys bool) []string {
|
func chatToTextSlice(showSys bool) []string {
|
||||||
@@ -1057,18 +1035,15 @@ func refreshLocalModelsIfEmpty() {
|
|||||||
|
|
||||||
func summarizeAndStartNewChat() {
|
func summarizeAndStartNewChat() {
|
||||||
if len(chatBody.Messages) == 0 {
|
if len(chatBody.Messages) == 0 {
|
||||||
notifyUser("info", "No chat history to summarize")
|
_ = notifyUser("info", "No chat history to summarize")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Create a dummy TextView for the summary request (won't be displayed)
|
_ = notifyUser("info", "Summarizing chat history...")
|
||||||
dummyTV := tview.NewTextView()
|
// Call the summarize_chat tool via agent
|
||||||
// Call chatRound with summaryMode true to generate summary
|
summaryBytes := callToolWithAgent("summarize_chat", map[string]string{})
|
||||||
notifyUser("info", "Summarizing chat history...")
|
summary := string(summaryBytes)
|
||||||
lastSummary = ""
|
|
||||||
chatRound("", cfg.UserRole, dummyTV, false, false, true)
|
|
||||||
summary := lastSummary
|
|
||||||
if summary == "" {
|
if summary == "" {
|
||||||
notifyUser("error", "Failed to generate summary")
|
_ = notifyUser("error", "Failed to generate summary")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Start a new chat
|
// Start a new chat
|
||||||
@@ -1087,7 +1062,7 @@ func summarizeAndStartNewChat() {
|
|||||||
if err := updateStorageChat(activeChatName, chatBody.Messages); err != nil {
|
if err := updateStorageChat(activeChatName, chatBody.Messages); err != nil {
|
||||||
logger.Warn("failed to update storage after injecting summary", "error", err)
|
logger.Warn("failed to update storage after injecting summary", "error", err)
|
||||||
}
|
}
|
||||||
notifyUser("info", "Chat summarized and new chat started with summary as tool response")
|
_ = notifyUser("info", "Chat summarized and new chat started with summary as tool response")
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|||||||
13
tools.go
13
tools.go
@@ -129,6 +129,7 @@ After that you are free to respond to the user.
|
|||||||
`
|
`
|
||||||
webSearchSysPrompt = `Summarize the web search results, extracting key information and presenting a concise answer. Provide sources and URLs where relevant.`
|
webSearchSysPrompt = `Summarize the web search results, extracting key information and presenting a concise answer. Provide sources and URLs where relevant.`
|
||||||
readURLSysPrompt = `Extract and summarize the content from the webpage. Provide key information, main points, and any relevant details.`
|
readURLSysPrompt = `Extract and summarize the content from the webpage. Provide key information, main points, and any relevant details.`
|
||||||
|
summarySysPrompt = `Please provide a concise summary of the following conversation. Focus on key points, decisions, and actions. Provide only the summary, no additional commentary.`
|
||||||
basicCard = &models.CharCard{
|
basicCard = &models.CharCard{
|
||||||
SysPrompt: basicSysMsg,
|
SysPrompt: basicSysMsg,
|
||||||
FirstMsg: defaultFirstMsg,
|
FirstMsg: defaultFirstMsg,
|
||||||
@@ -178,6 +179,8 @@ func registerWebAgents() {
|
|||||||
agent.Register("websearch", agent.NewWebAgentB(client, webSearchSysPrompt))
|
agent.Register("websearch", agent.NewWebAgentB(client, webSearchSysPrompt))
|
||||||
// Register read_url agent
|
// Register read_url agent
|
||||||
agent.Register("read_url", agent.NewWebAgentB(client, readURLSysPrompt))
|
agent.Register("read_url", agent.NewWebAgentB(client, readURLSysPrompt))
|
||||||
|
// Register summarize_chat agent
|
||||||
|
agent.Register("summarize_chat", agent.NewWebAgentB(client, summarySysPrompt))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -864,6 +867,15 @@ func isCommandAllowed(command string) bool {
|
|||||||
return allowedCommands[command]
|
return allowedCommands[command]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func summarizeChat(args map[string]string) []byte {
|
||||||
|
if len(chatBody.Messages) == 0 {
|
||||||
|
return []byte("No chat history to summarize.")
|
||||||
|
}
|
||||||
|
// Format chat history for the agent
|
||||||
|
chatText := chatToText(true) // include system and tool messages
|
||||||
|
return []byte(chatText)
|
||||||
|
}
|
||||||
|
|
||||||
type fnSig func(map[string]string) []byte
|
type fnSig func(map[string]string) []byte
|
||||||
|
|
||||||
var fnMap = map[string]fnSig{
|
var fnMap = map[string]fnSig{
|
||||||
@@ -884,6 +896,7 @@ var fnMap = map[string]fnSig{
|
|||||||
"todo_read": todoRead,
|
"todo_read": todoRead,
|
||||||
"todo_update": todoUpdate,
|
"todo_update": todoUpdate,
|
||||||
"todo_delete": todoDelete,
|
"todo_delete": todoDelete,
|
||||||
|
"summarize_chat": summarizeChat,
|
||||||
}
|
}
|
||||||
|
|
||||||
// callToolWithAgent calls the tool and applies any registered agent.
|
// callToolWithAgent calls the tool and applies any registered agent.
|
||||||
|
|||||||
6
tui.go
6
tui.go
@@ -831,7 +831,7 @@ func init() {
|
|||||||
// there is no case where user msg is regenerated
|
// there is no case where user msg is regenerated
|
||||||
// lastRole := chatBody.Messages[len(chatBody.Messages)-1].Role
|
// lastRole := chatBody.Messages[len(chatBody.Messages)-1].Role
|
||||||
textView.SetText(chatToText(cfg.ShowSys))
|
textView.SetText(chatToText(cfg.ShowSys))
|
||||||
go chatRound("", cfg.UserRole, textView, true, false, false)
|
go chatRound("", cfg.UserRole, textView, true, false)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if event.Key() == tcell.KeyF3 && !botRespMode {
|
if event.Key() == tcell.KeyF3 && !botRespMode {
|
||||||
@@ -1134,7 +1134,7 @@ func init() {
|
|||||||
// INFO: continue bot/text message
|
// INFO: continue bot/text message
|
||||||
// without new role
|
// without new role
|
||||||
lastRole := chatBody.Messages[len(chatBody.Messages)-1].Role
|
lastRole := chatBody.Messages[len(chatBody.Messages)-1].Role
|
||||||
go chatRound("", lastRole, textView, false, true, false)
|
go chatRound("", lastRole, textView, false, true)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if event.Key() == tcell.KeyCtrlQ {
|
if event.Key() == tcell.KeyCtrlQ {
|
||||||
@@ -1294,7 +1294,7 @@ func init() {
|
|||||||
textView.ScrollToEnd()
|
textView.ScrollToEnd()
|
||||||
colorText()
|
colorText()
|
||||||
}
|
}
|
||||||
go chatRound(msgText, persona, textView, false, false, false)
|
go chatRound(msgText, persona, textView, false, false)
|
||||||
// Also clear any image attachment after sending the message
|
// Also clear any image attachment after sending the message
|
||||||
go func() {
|
go func() {
|
||||||
// Wait a short moment for the message to be processed, then clear the image attachment
|
// Wait a short moment for the message to be processed, then clear the image attachment
|
||||||
|
|||||||
Reference in New Issue
Block a user