Enha: stricter stop string

This commit is contained in:
Grail Finder
2026-02-04 12:47:54 +03:00
parent 79861e7c2b
commit 7187df509f
3 changed files with 9 additions and 26 deletions

20
bot.go
View File

@@ -861,18 +861,7 @@ out:
newMsg = processMessageTag(newMsg) newMsg = processMessageTag(newMsg)
chatBody.Messages = append(chatBody.Messages, newMsg) chatBody.Messages = append(chatBody.Messages, newMsg)
} }
logger.Debug("chatRound: before cleanChatBody", "messages_before_clean", len(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)
}
// // Clean null/empty messages to prevent API issues with endpoints like llama.cpp jinja template
cleanChatBody() cleanChatBody()
logger.Debug("chatRound: after cleanChatBody", "messages_after_clean", len(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)
}
refreshChatDisplay() refreshChatDisplay()
updateStatusLine() updateStatusLine()
// bot msg is done; // bot msg is done;
@@ -901,19 +890,10 @@ func cleanChatBody() {
if chatBody == nil || chatBody.Messages == nil { if chatBody == nil || chatBody.Messages == nil {
return return
} }
originalLen := len(chatBody.Messages)
logger.Debug("cleanChatBody: before cleaning", "message_count", originalLen)
for i, msg := range chatBody.Messages {
logger.Debug("cleanChatBody: before clean", "index", i, "role", msg.Role, "content_len", len(msg.Content), "has_content", msg.HasContent(), "tool_call_id", msg.ToolCallID)
}
// Tool request cleaning is now configurable via AutoCleanToolCallsFromCtx (default false) // Tool request cleaning is now configurable via AutoCleanToolCallsFromCtx (default false)
// /completion msg where part meant for user and other part tool call // /completion msg where part meant for user and other part tool call
chatBody.Messages = cleanToolCalls(chatBody.Messages) chatBody.Messages = cleanToolCalls(chatBody.Messages)
chatBody.Messages = consolidateAssistantMessages(chatBody.Messages) chatBody.Messages = consolidateAssistantMessages(chatBody.Messages)
logger.Debug("cleanChatBody: after cleaning", "original_len", originalLen, "new_len", len(chatBody.Messages))
for i, msg := range chatBody.Messages {
logger.Debug("cleanChatBody: after clean", "index", i, "role", msg.Role, "content_len", len(msg.Content), "has_content", msg.HasContent(), "tool_call_id", msg.ToolCallID)
}
} }
// convertJSONToMapStringString unmarshals JSON into map[string]interface{} and converts all values to strings. // convertJSONToMapStringString unmarshals JSON into map[string]interface{} and converts all values to strings.

6
llm.go
View File

@@ -207,7 +207,7 @@ func (lcp LCPCompletion) FormMsg(msg, role string, resume bool) (io.Reader, erro
logger.Debug("checking prompt for /completion", "tool_use", cfg.ToolUse, logger.Debug("checking prompt for /completion", "tool_use", cfg.ToolUse,
"msg", msg, "resume", resume, "prompt", prompt, "multimodal_data_count", len(multimodalData)) "msg", msg, "resume", resume, "prompt", prompt, "multimodal_data_count", len(multimodalData))
payload := models.NewLCPReq(prompt, chatBody.Model, multimodalData, payload := models.NewLCPReq(prompt, chatBody.Model, multimodalData,
defaultLCPProps, chatBody.MakeStopSliceExcluding(botPersona, listChatRoles())) defaultLCPProps, chatBody.MakeStopSliceExcluding("", listChatRoles()))
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)
@@ -444,7 +444,7 @@ func (ds DeepSeekerCompletion) FormMsg(msg, role string, resume bool) (io.Reader
"msg", msg, "resume", resume, "prompt", prompt) "msg", msg, "resume", resume, "prompt", prompt)
payload := models.NewDSCompletionReq(prompt, chatBody.Model, payload := models.NewDSCompletionReq(prompt, chatBody.Model,
defaultLCPProps["temp"], defaultLCPProps["temp"],
chatBody.MakeStopSliceExcluding(botPersona, listChatRoles())) chatBody.MakeStopSliceExcluding("", listChatRoles()))
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)
@@ -604,7 +604,7 @@ func (or OpenRouterCompletion) FormMsg(msg, role string, resume bool) (io.Reader
if cfg.ThinkUse && !cfg.ToolUse { if cfg.ThinkUse && !cfg.ToolUse {
prompt += "<think>" prompt += "<think>"
} }
stopSlice := chatBody.MakeStopSliceExcluding(botPersona, listChatRoles()) stopSlice := chatBody.MakeStopSliceExcluding("", listChatRoles())
logger.Debug("checking prompt for /completion", "tool_use", cfg.ToolUse, logger.Debug("checking prompt for /completion", "tool_use", cfg.ToolUse,
"msg", msg, "resume", resume, "prompt", prompt, "stop_strings", stopSlice) "msg", msg, "resume", resume, "prompt", prompt, "stop_strings", stopSlice)
payload := models.NewOpenRouterCompletionReq(chatBody.Model, prompt, payload := models.NewOpenRouterCompletionReq(chatBody.Model, prompt,

View File

@@ -384,7 +384,10 @@ func (cb *ChatBody) MakeStopSliceExcluding(
// Add multiple variations to catch different formatting // Add multiple variations to catch different formatting
ss = append(ss, role+":\n") // Most common: role with newline ss = append(ss, role+":\n") // Most common: role with newline
ss = append(ss, role+":") // Role with colon but no newline ss = append(ss, role+":") // Role with colon but no newline
ss = append(ss, role+": ") // Role with colon and space ss = append(ss, role+": ") // Role with colon and single space
ss = append(ss, role+": ") // Role with colon and double space (common tokenization)
ss = append(ss, role+": \n") // Role with colon and double space (common tokenization)
ss = append(ss, role+": ") // Role with colon and triple space
} }
return ss return ss
} }