fix: 修复间隔对话后首条回复为上一次对话内容的问题
根因:用户消息在回复完成后才缓存到 ConversationStore,而 assistant 回复在 orchestrator 中先缓存,导致存储顺序为 assistant → user 颠倒。 下次请求时 LLM 看到连续两条 assistant 再连续两条 user,对两条 user 消息都生成回复。 修复:将用户消息缓存移到 orchestrator 调用之前,确保 user → assistant 正确顺序;synthesizer 中对 DialogHistory 末尾与当前消息相同的 user 消息去重。 同时包含之前的 action 消息类型检测修复(isActionLike 启发式 + injector XML 标签格式改进)。 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -41,9 +41,59 @@ func autoDetectType(text string) model.ReviewMessageType {
|
||||
if hasMarkdownSyntax(text) {
|
||||
return model.ReviewMessageMarkdown
|
||||
}
|
||||
if isActionLike(text) {
|
||||
return model.ReviewMessageAction
|
||||
}
|
||||
return model.ReviewMessageChat
|
||||
}
|
||||
|
||||
// isActionLike checks whether text looks like an action/expression description
|
||||
// (e.g. "忍不住轻声笑出来", "俏皮地眨眨眼") rather than dialogue. Used as a
|
||||
// fallback when the model doesn't use <action> tags or brackets.
|
||||
func isActionLike(text string) bool {
|
||||
runes := []rune(strings.TrimSpace(text))
|
||||
if len(runes) == 0 || len(runes) > 50 {
|
||||
return false
|
||||
}
|
||||
// Dialogue markers disqualify action
|
||||
if strings.ContainsAny(text, "??!!") {
|
||||
return false
|
||||
}
|
||||
// Common dialogue starters
|
||||
dialoguePrefixes := []string{"你", "您", "我", "他", "她", "这", "那", "怎么", "什么", "为什"}
|
||||
for _, p := range dialoguePrefixes {
|
||||
if strings.HasPrefix(string(runes), p) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
// Soft dialogue indicators: text that looks like addressing someone
|
||||
softDialogue := []string{"吗", "吧", "哦", "呢", "啦", "呀", "喔"}
|
||||
dialogueScore := 0
|
||||
for _, s := range softDialogue {
|
||||
if strings.HasSuffix(string(runes), s) {
|
||||
dialogueScore++
|
||||
}
|
||||
}
|
||||
if dialogueScore >= 1 && strings.Contains(text, "你") {
|
||||
return false
|
||||
}
|
||||
// Action-indicating patterns
|
||||
actionPatterns := []string{
|
||||
"笑出来", "眨眨眼", "歪头", "点头", "摇头", "挥手", "伸手",
|
||||
"松口气", "叹口气", "叹气", "拍拍", "摸摸", "抱抱",
|
||||
"轻轻", "俏皮", "微微", "默默", "悄悄", "偷偷",
|
||||
"忍不住", "不由得", "不禁",
|
||||
"站起来", "坐下", "走", "跑", "跳", "躺",
|
||||
"眼睛", "目光", "嘴角", "眉头", "脸上",
|
||||
}
|
||||
for _, p := range actionPatterns {
|
||||
if strings.Contains(text, p) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// parseReviewMessages splits the assistant's full response into typed messages.
|
||||
//
|
||||
// Phases:
|
||||
|
||||
@@ -259,9 +259,16 @@ func (s *Synthesizer) buildSynthesizeMessages(params SynthesizeParams) []model.L
|
||||
})
|
||||
}
|
||||
|
||||
// 注入对话历史
|
||||
if len(params.DialogHistory) > 0 {
|
||||
messages = append(messages, params.DialogHistory...)
|
||||
// 注入对话历史(去掉末尾的当前用户消息,因为后面会单独追加)
|
||||
history := params.DialogHistory
|
||||
if len(history) > 0 {
|
||||
last := history[len(history)-1]
|
||||
if last.Role == model.RoleUser && last.Content == params.UserMessage {
|
||||
history = history[:len(history)-1]
|
||||
}
|
||||
}
|
||||
if len(history) > 0 {
|
||||
messages = append(messages, history...)
|
||||
}
|
||||
|
||||
// 当前用户消息 (支持多模态图片)
|
||||
|
||||
Reference in New Issue
Block a user