Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions adk/middlewares/summarization/prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,27 @@
package summarization

import (
"regexp"

"github.com/cloudwego/eino/adk/internal"
)

var (
pendingTasksRegex = regexp.MustCompile(`(?m)^\d+\.\s*Pending Tasks:\s*$`)
pendingTasksRegexZh = regexp.MustCompile(`(?m)^\d+\.\s*待处理任务[::]\s*$`)
)

func getPendingTasksRegex() *regexp.Regexp {
s, _ := internal.SelectPrompt(internal.I18nPrompts{
English: "en",
Chinese: "zh",
})
if s == "zh" {
return pendingTasksRegexZh
}
return pendingTasksRegex
}

func getSystemPrompt() string {
s, _ := internal.SelectPrompt(internal.I18nPrompts{
English: systemPrompt,
Expand Down Expand Up @@ -126,7 +144,7 @@ Your summary should include the following sections:
3. Files and Code Sections: Enumerate specific files and code sections examined, modified, or created. Pay special attention to the most recent messages and include full code snippets where applicable and include a summary of why this file read or edit is important.
4. Errors and fixes: List all errors that you ran into, and how you fixed them. Pay special attention to specific user feedback that you received, especially if the user told you to do something differently.
5. Problem Solving: Document problems solved and any ongoing troubleshooting efforts.
6. All user messages: List ALL user messages that are not tool results in the <all_user_messages>...</all_user_messages> block. These are critical for understanding the users' feedback and changing intent.
6. All user messages: List ALL user messages that are not tool results. These are critical for understanding the users' feedback and changing intent.
6. Pending Tasks: Outline any pending tasks that you have explicitly been asked to work on.
7. Current Work: Describe in detail precisely what was being worked on immediately before this summary request, paying special attention to the most recent messages from both user and assistant. Include file names and code snippets where applicable.
8. Optional Next Step: List the next step that you will take that is related to the most recent work you were doing. IMPORTANT: ensure that this step is DIRECTLY in line with the user's most recent explicit requests, and the task you were working on immediately before this summary request. If your last task was concluded, then only list next steps if they are explicitly in line with the users request. Do not start on tangential requests or really old requests that were already completed without confirming with the user first.
Expand Down Expand Up @@ -167,10 +185,8 @@ Here's an example of how your output should be structured:
[Description of solved problems and ongoing troubleshooting]

6. All user messages:
<all_user_messages>
- [Detailed non tool use user message]
- [...]
</all_user_messages>

7. Pending Tasks:
- [Task 1]
Expand Down Expand Up @@ -228,7 +244,7 @@ const summaryInstructionZh = `你的任务是对目前为止的对话创建一
3. 文件和代码部分:列举检查、修改或创建的具体文件和代码部分。特别注意最近的消息,在适用的地方包含完整的代码片段,并总结为什么这个文件的读取或编辑很重要
4. 错误和修复:列出你遇到的所有错误以及如何修复它们。特别注意你收到的具体用户反馈,尤其是用户要求你以不同方式处理的情况
5. 问题解决:记录已解决的问题和任何正在进行的故障排除工作
6. 所有用户消息:在 <all_user_messages>...</all_user_messages> 块中列出所有非工具结果的用户消息。这些对于理解用户的反馈和变化的意图至关重要
6. 所有用户消息:列出所有非工具结果的用户消息。这些对于理解用户的反馈和变化的意图至关重要
7. 待处理任务:列出明确要求你处理的任何待处理任务
8. 当前工作:详细描述在此总结请求之前正在进行的工作,特别注意用户和助手的最近消息。在适用的地方包含文件名和代码片段
9. 可选的下一步:列出与你最近工作相关的下一步操作。重要提示:确保这一步与用户最近的明确请求以及你在此总结请求之前正在处理的任务直接相关。如果你的上一个任务已经完成,则只有在与用户请求明确相关时才列出下一步。不要在未与用户确认的情况下开始处理无关的请求或已经完成的旧请求。
Expand Down Expand Up @@ -269,10 +285,8 @@ const summaryInstructionZh = `你的任务是对目前为止的对话创建一
[已解决问题和正在进行的故障排除的描述]

6. 所有用户消息:
<all_user_messages>
- [详细的非工具使用用户消息]
- [...]
</all_user_messages>

7. 待处理任务:
- [任务 1]
Expand Down
13 changes: 2 additions & 11 deletions adk/middlewares/summarization/summarization.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,11 +273,6 @@ func (m *middleware) summarize(ctx context.Context, msgs []adk.Message) (adk.Mes
return summary, nil
}

var (
allUserMessagesCloseTagRegex = regexp.MustCompile(`</?all_user_messages>`)
pendingTasksRegex = regexp.MustCompile(`(?m)^(\d+\.\s*)?Pending Tasks:`)
)

func (m *middleware) postProcessSummary(ctx context.Context, messages []adk.Message, summary adk.Message) (adk.Message, error) {
maxUserMsgTokens := m.getMaxUserMessageTokens()
content, err := m.insertUserMessagesIntoSummary(ctx, messages, summary.Content, maxUserMsgTokens)
Expand Down Expand Up @@ -363,12 +358,8 @@ func (m *middleware) insertUserMessagesIntoSummary(ctx context.Context, messages
return summary, nil
}

if loc := findLastMatch(allUserMessagesCloseTagRegex, summary); loc != nil {
return summary[:loc[0]] + userMsgsText + "\n" + summary[loc[0]:], nil
}

if loc := findLastMatch(pendingTasksRegex, summary); loc != nil {
return summary[:loc[0]] + userMsgsText + "\n\n" + summary[loc[0]:], nil
if loc := findLastMatch(getPendingTasksRegex(), summary); loc != nil {
return strings.TrimRight(summary[:loc[0]], "\n") + "\n" + userMsgsText + "\n\n" + summary[loc[0]:], nil
}

return appendSection(summary, fmt.Sprintf(getFallbackUserMessagesInstruction(), userMsgsText)), nil
Expand Down
25 changes: 19 additions & 6 deletions adk/middlewares/summarization/summarization_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,17 +437,30 @@ func TestAppendSection(t *testing.T) {
}
}

func TestFindLastMatch(t *testing.T) {
func TestPendingTasksRegex(t *testing.T) {
t.Run("no match returns nil", func(t *testing.T) {
result := findLastMatch(allUserMessagesCloseTagRegex, "no tags here")
result := findLastMatch(getPendingTasksRegex(), "no tasks here")
assert.Nil(t, result)
})

t.Run("finds last match", func(t *testing.T) {
text := "<all_user_messages>first</all_user_messages> middle <all_user_messages>second</all_user_messages>"
result := findLastMatch(allUserMessagesCloseTagRegex, text)
t.Run("does not match inline content", func(t *testing.T) {
text := "6. Pending Tasks: Outline any pending tasks"
result := findLastMatch(getPendingTasksRegex(), text)
assert.Nil(t, result)
})

t.Run("finds last match english", func(t *testing.T) {
text := "7. Pending Tasks:\n- task1\n\n8. Pending Tasks:\n- task2"
result := findLastMatch(pendingTasksRegex, text)
assert.NotNil(t, result)
assert.Equal(t, "8. Pending Tasks:", text[result[0]:result[1]])
})

t.Run("finds last match chinese", func(t *testing.T) {
text := "7. 待处理任务:\n- 任务1\n\n8. 待处理任务:\n- 任务2"
result := findLastMatch(pendingTasksRegexZh, text)
assert.NotNil(t, result)
assert.Equal(t, "</all_user_messages>", text[result[0]:result[1]])
assert.Equal(t, "8. 待处理任务:", text[result[0]:result[1]])
})
}

Expand Down