Enha: extract first valid recipient from knownto
This commit is contained in:
55
bot.go
55
bot.go
@@ -1305,15 +1305,17 @@ func init() {
|
|||||||
go chatWatcher(ctx)
|
go chatWatcher(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// triggerPrivateMessageResponses checks if a message was sent privately to specific characters
|
func getValidKnowToRecipient(msg *models.RoleMsg) (string, bool) {
|
||||||
// and triggers those non-user characters to respond
|
|
||||||
func triggerPrivateMessageResponses(msg *models.RoleMsg) {
|
|
||||||
if cfg == nil || !cfg.CharSpecificContextEnabled {
|
if cfg == nil || !cfg.CharSpecificContextEnabled {
|
||||||
return
|
return "", false
|
||||||
}
|
}
|
||||||
userCharacter := cfg.UserRole
|
// case where all roles are in the tag => public message
|
||||||
if cfg.WriteNextMsgAs != "" {
|
cr := listChatRoles()
|
||||||
userCharacter = cfg.WriteNextMsgAs
|
slices.Sort(cr)
|
||||||
|
slices.Sort(msg.KnownTo)
|
||||||
|
if slices.Equal(cr, msg.KnownTo) {
|
||||||
|
logger.Info("got msg with tag mentioning every role")
|
||||||
|
return "", false
|
||||||
}
|
}
|
||||||
// Check each character in the KnownTo list
|
// Check each character in the KnownTo list
|
||||||
for _, recipient := range msg.KnownTo {
|
for _, recipient := range msg.KnownTo {
|
||||||
@@ -1323,20 +1325,31 @@ func triggerPrivateMessageResponses(msg *models.RoleMsg) {
|
|||||||
}
|
}
|
||||||
// Skip if this is the user character (user handles their own turn)
|
// Skip if this is the user character (user handles their own turn)
|
||||||
// If user is in KnownTo, stop processing - it's the user's turn
|
// If user is in KnownTo, stop processing - it's the user's turn
|
||||||
if recipient == cfg.UserRole || recipient == userCharacter {
|
if recipient == cfg.UserRole || recipient == cfg.WriteNextMsgAs {
|
||||||
return // user in known_to => user's turn
|
return "", false
|
||||||
}
|
}
|
||||||
// Trigger the recipient character to respond
|
return recipient, true
|
||||||
triggerMsg := recipient + ":\n"
|
|
||||||
// Send empty message so LLM continues naturally from the conversation
|
|
||||||
crr := &models.ChatRoundReq{
|
|
||||||
UserMsg: triggerMsg,
|
|
||||||
Role: recipient,
|
|
||||||
Resume: true,
|
|
||||||
}
|
|
||||||
fmt.Fprintf(textView, "\n[-:-:b](%d) ", len(chatBody.Messages))
|
|
||||||
fmt.Fprint(textView, roleToIcon(recipient))
|
|
||||||
fmt.Fprint(textView, "[-:-:-]\n")
|
|
||||||
chatRoundChan <- crr
|
|
||||||
}
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
// triggerPrivateMessageResponses checks if a message was sent privately to specific characters
|
||||||
|
// and triggers those non-user characters to respond
|
||||||
|
func triggerPrivateMessageResponses(msg *models.RoleMsg) {
|
||||||
|
recipient, ok := getValidKnowToRecipient(msg)
|
||||||
|
if !ok || recipient == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Trigger the recipient character to respond
|
||||||
|
triggerMsg := recipient + ":\n"
|
||||||
|
// Send empty message so LLM continues naturally from the conversation
|
||||||
|
crr := &models.ChatRoundReq{
|
||||||
|
UserMsg: triggerMsg,
|
||||||
|
Role: recipient,
|
||||||
|
Resume: true,
|
||||||
|
}
|
||||||
|
fmt.Fprintf(textView, "\n[-:-:b](%d) ", len(chatBody.Messages))
|
||||||
|
fmt.Fprint(textView, roleToIcon(recipient))
|
||||||
|
fmt.Fprint(textView, "[-:-:-]\n")
|
||||||
|
chatRoundChan <- crr
|
||||||
}
|
}
|
||||||
|
|||||||
199
llm.go
199
llm.go
@@ -59,17 +59,19 @@ func ClearImageAttachment() {
|
|||||||
// filterMessagesForCurrentCharacter filters messages based on char-specific context.
|
// filterMessagesForCurrentCharacter filters messages based on char-specific context.
|
||||||
// Returns filtered messages and the bot persona role (target character).
|
// Returns filtered messages and the bot persona role (target character).
|
||||||
func filterMessagesForCurrentCharacter(messages []models.RoleMsg) ([]models.RoleMsg, string) {
|
func filterMessagesForCurrentCharacter(messages []models.RoleMsg) ([]models.RoleMsg, string) {
|
||||||
if cfg == nil || !cfg.CharSpecificContextEnabled {
|
|
||||||
botPersona := cfg.AssistantRole
|
|
||||||
if cfg.WriteNextMsgAsCompletionAgent != "" {
|
|
||||||
botPersona = cfg.WriteNextMsgAsCompletionAgent
|
|
||||||
}
|
|
||||||
return messages, botPersona
|
|
||||||
}
|
|
||||||
botPersona := cfg.AssistantRole
|
botPersona := cfg.AssistantRole
|
||||||
if cfg.WriteNextMsgAsCompletionAgent != "" {
|
if cfg.WriteNextMsgAsCompletionAgent != "" {
|
||||||
botPersona = cfg.WriteNextMsgAsCompletionAgent
|
botPersona = cfg.WriteNextMsgAsCompletionAgent
|
||||||
}
|
}
|
||||||
|
if cfg == nil || !cfg.CharSpecificContextEnabled {
|
||||||
|
return messages, botPersona
|
||||||
|
}
|
||||||
|
// get last message (written by user) and checck if it has a tag
|
||||||
|
lm := messages[len(messages)-1]
|
||||||
|
recipient, ok := getValidKnowToRecipient(&lm)
|
||||||
|
if ok && recipient != "" {
|
||||||
|
botPersona = recipient
|
||||||
|
}
|
||||||
filtered := filterMessagesForCharacter(messages, botPersona)
|
filtered := filterMessagesForCharacter(messages, botPersona)
|
||||||
return filtered, botPersona
|
return filtered, botPersona
|
||||||
}
|
}
|
||||||
@@ -162,23 +164,21 @@ func (lcp LCPCompletion) FormMsg(msg, role string, resume bool) (io.Reader, erro
|
|||||||
newMsg = *processMessageTag(&newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
// if rag - add as system message to avoid conflicts with tool usage
|
||||||
// if rag - add as system message to avoid conflicts with tool usage
|
if !resume && cfg.RAGEnabled {
|
||||||
if cfg.RAGEnabled {
|
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
||||||
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
|
||||||
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
|
ragResp, err := chatRagUse(um)
|
||||||
ragResp, err := chatRagUse(um)
|
if err != nil {
|
||||||
if err != nil {
|
logger.Error("failed to form a rag msg", "error", err)
|
||||||
logger.Error("failed to form a rag msg", "error", err)
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logger.Debug("RAG response received", "response_len", len(ragResp),
|
|
||||||
"response_preview", ragResp[:min(len(ragResp), 100)])
|
|
||||||
// Use system role for RAG context to avoid conflicts with tool usage
|
|
||||||
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
|
||||||
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
|
||||||
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
|
|
||||||
}
|
}
|
||||||
|
logger.Debug("RAG response received", "response_len", len(ragResp),
|
||||||
|
"response_preview", ragResp[:min(len(ragResp), 100)])
|
||||||
|
// Use system role for RAG context to avoid conflicts with tool usage
|
||||||
|
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
||||||
|
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
||||||
|
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
|
||||||
}
|
}
|
||||||
// sending description of the tools and how to use them
|
// sending description of the tools and how to use them
|
||||||
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
|
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
|
||||||
@@ -324,24 +324,22 @@ func (op LCPChat) FormMsg(msg, role string, resume bool) (io.Reader, error) {
|
|||||||
logger.Debug("LCPChat FormMsg: added message to chatBody", "role", newMsg.Role,
|
logger.Debug("LCPChat FormMsg: added message to chatBody", "role", newMsg.Role,
|
||||||
"content_len", len(newMsg.Content), "message_count_after_add", len(chatBody.Messages))
|
"content_len", len(newMsg.Content), "message_count_after_add", len(chatBody.Messages))
|
||||||
}
|
}
|
||||||
if !resume {
|
// if rag - add as system message to avoid conflicts with tool usage
|
||||||
// if rag - add as system message to avoid conflicts with tool usage
|
if !resume && cfg.RAGEnabled {
|
||||||
if cfg.RAGEnabled {
|
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
||||||
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
logger.Debug("LCPChat: RAG is enabled, preparing RAG context", "user_message", um)
|
||||||
logger.Debug("LCPChat: RAG is enabled, preparing RAG context", "user_message", um)
|
ragResp, err := chatRagUse(um)
|
||||||
ragResp, err := chatRagUse(um)
|
if err != nil {
|
||||||
if err != nil {
|
logger.Error("LCPChat: failed to form a rag msg", "error", err)
|
||||||
logger.Error("LCPChat: failed to form a rag msg", "error", err)
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logger.Debug("LCPChat: RAG response received",
|
|
||||||
"response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)])
|
|
||||||
// Use system role for RAG context to avoid conflicts with tool usage
|
|
||||||
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
|
||||||
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
|
||||||
logger.Debug("LCPChat: RAG message added to chat body", "role", ragMsg.Role,
|
|
||||||
"rag_content_len", len(ragMsg.Content), "message_count_after_rag", len(chatBody.Messages))
|
|
||||||
}
|
}
|
||||||
|
logger.Debug("LCPChat: RAG response received",
|
||||||
|
"response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)])
|
||||||
|
// Use system role for RAG context to avoid conflicts with tool usage
|
||||||
|
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
||||||
|
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
||||||
|
logger.Debug("LCPChat: RAG message added to chat body", "role", ragMsg.Role,
|
||||||
|
"rag_content_len", len(ragMsg.Content), "message_count_after_rag", len(chatBody.Messages))
|
||||||
}
|
}
|
||||||
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
|
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
|
||||||
// openai /v1/chat does not support custom roles; needs to be user, assistant, system
|
// openai /v1/chat does not support custom roles; needs to be user, assistant, system
|
||||||
@@ -416,24 +414,21 @@ func (ds DeepSeekerCompletion) FormMsg(msg, role string, resume bool) (io.Reader
|
|||||||
newMsg = *processMessageTag(&newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
// if rag - add as system message to avoid conflicts with tool usage
|
||||||
// if rag - add as system message to avoid conflicts with tool usage
|
if !resume && cfg.RAGEnabled {
|
||||||
// TODO: perhaps RAG should be a func/tool call instead?
|
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
||||||
if cfg.RAGEnabled {
|
logger.Debug("DeepSeekerCompletion: RAG is enabled, preparing RAG context", "user_message", um)
|
||||||
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
ragResp, err := chatRagUse(um)
|
||||||
logger.Debug("DeepSeekerCompletion: RAG is enabled, preparing RAG context", "user_message", um)
|
if err != nil {
|
||||||
ragResp, err := chatRagUse(um)
|
logger.Error("DeepSeekerCompletion: failed to form a rag msg", "error", err)
|
||||||
if err != nil {
|
return nil, err
|
||||||
logger.Error("DeepSeekerCompletion: failed to form a rag msg", "error", err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logger.Debug("DeepSeekerCompletion: RAG response received",
|
|
||||||
"response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)])
|
|
||||||
// Use system role for RAG context to avoid conflicts with tool usage
|
|
||||||
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
|
||||||
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
|
||||||
logger.Debug("DeepSeekerCompletion: RAG message added to chat body", "message_count", len(chatBody.Messages))
|
|
||||||
}
|
}
|
||||||
|
logger.Debug("DeepSeekerCompletion: RAG response received",
|
||||||
|
"response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)])
|
||||||
|
// Use system role for RAG context to avoid conflicts with tool usage
|
||||||
|
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
||||||
|
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
||||||
|
logger.Debug("DeepSeekerCompletion: RAG message added to chat body", "message_count", len(chatBody.Messages))
|
||||||
}
|
}
|
||||||
// sending description of the tools and how to use them
|
// sending description of the tools and how to use them
|
||||||
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
|
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
|
||||||
@@ -507,23 +502,21 @@ func (ds DeepSeekerChat) FormMsg(msg, role string, resume bool) (io.Reader, erro
|
|||||||
newMsg = *processMessageTag(&newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
// if rag - add as system message to avoid conflicts with tool usage
|
||||||
// if rag - add as system message to avoid conflicts with tool usage
|
if !resume && cfg.RAGEnabled {
|
||||||
if cfg.RAGEnabled {
|
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
||||||
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
|
||||||
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
|
ragResp, err := chatRagUse(um)
|
||||||
ragResp, err := chatRagUse(um)
|
if err != nil {
|
||||||
if err != nil {
|
logger.Error("failed to form a rag msg", "error", err)
|
||||||
logger.Error("failed to form a rag msg", "error", err)
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logger.Debug("RAG response received", "response_len", len(ragResp),
|
|
||||||
"response_preview", ragResp[:min(len(ragResp), 100)])
|
|
||||||
// Use system role for RAG context to avoid conflicts with tool usage
|
|
||||||
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
|
||||||
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
|
||||||
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
|
|
||||||
}
|
}
|
||||||
|
logger.Debug("RAG response received", "response_len", len(ragResp),
|
||||||
|
"response_preview", ragResp[:min(len(ragResp), 100)])
|
||||||
|
// Use system role for RAG context to avoid conflicts with tool usage
|
||||||
|
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
||||||
|
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
||||||
|
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
|
||||||
}
|
}
|
||||||
// Create copy of chat body with standardized user role
|
// Create copy of chat body with standardized user role
|
||||||
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
|
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
|
||||||
@@ -589,23 +582,21 @@ func (or OpenRouterCompletion) FormMsg(msg, role string, resume bool) (io.Reader
|
|||||||
newMsg = *processMessageTag(&newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
// if rag - add as system message to avoid conflicts with tool usage
|
||||||
// if rag - add as system message to avoid conflicts with tool usage
|
if !resume && cfg.RAGEnabled {
|
||||||
if cfg.RAGEnabled {
|
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
||||||
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
|
||||||
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
|
ragResp, err := chatRagUse(um)
|
||||||
ragResp, err := chatRagUse(um)
|
if err != nil {
|
||||||
if err != nil {
|
logger.Error("failed to form a rag msg", "error", err)
|
||||||
logger.Error("failed to form a rag msg", "error", err)
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logger.Debug("RAG response received", "response_len",
|
|
||||||
len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)])
|
|
||||||
// Use system role for RAG context to avoid conflicts with tool usage
|
|
||||||
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
|
||||||
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
|
||||||
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
|
|
||||||
}
|
}
|
||||||
|
logger.Debug("RAG response received", "response_len",
|
||||||
|
len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)])
|
||||||
|
// Use system role for RAG context to avoid conflicts with tool usage
|
||||||
|
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
||||||
|
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
||||||
|
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
|
||||||
}
|
}
|
||||||
// sending description of the tools and how to use them
|
// sending description of the tools and how to use them
|
||||||
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
|
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
|
||||||
@@ -710,23 +701,21 @@ func (or OpenRouterChat) FormMsg(msg, role string, resume bool) (io.Reader, erro
|
|||||||
newMsg = *processMessageTag(&newMsg)
|
newMsg = *processMessageTag(&newMsg)
|
||||||
chatBody.Messages = append(chatBody.Messages, newMsg)
|
chatBody.Messages = append(chatBody.Messages, newMsg)
|
||||||
}
|
}
|
||||||
if !resume {
|
// if rag - add as system message to avoid conflicts with tool usage
|
||||||
// if rag - add as system message to avoid conflicts with tool usage
|
if !resume && cfg.RAGEnabled {
|
||||||
if cfg.RAGEnabled {
|
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
||||||
um := chatBody.Messages[len(chatBody.Messages)-1].Content
|
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
|
||||||
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
|
ragResp, err := chatRagUse(um)
|
||||||
ragResp, err := chatRagUse(um)
|
if err != nil {
|
||||||
if err != nil {
|
logger.Error("failed to form a rag msg", "error", err)
|
||||||
logger.Error("failed to form a rag msg", "error", err)
|
return nil, err
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logger.Debug("RAG response received", "response_len", len(ragResp),
|
|
||||||
"response_preview", ragResp[:min(len(ragResp), 100)])
|
|
||||||
// Use system role for RAG context to avoid conflicts with tool usage
|
|
||||||
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
|
||||||
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
|
||||||
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
|
|
||||||
}
|
}
|
||||||
|
logger.Debug("RAG response received", "response_len", len(ragResp),
|
||||||
|
"response_preview", ragResp[:min(len(ragResp), 100)])
|
||||||
|
// Use system role for RAG context to avoid conflicts with tool usage
|
||||||
|
ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp}
|
||||||
|
chatBody.Messages = append(chatBody.Messages, ragMsg)
|
||||||
|
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
|
||||||
}
|
}
|
||||||
// Create copy of chat body with standardized user role
|
// Create copy of chat body with standardized user role
|
||||||
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
|
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
|
||||||
|
|||||||
Reference in New Issue
Block a user