Skip to content

Commit f85c62b

Browse files
authored
provideChatSummary() uses advanced summarizer (#1189)
1 parent 9318e2a commit f85c62b

File tree

2 files changed

+45
-84
lines changed

2 files changed

+45
-84
lines changed

src/extension/prompt/node/summarizer.ts

Lines changed: 37 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -9,55 +9,13 @@ import { ChatFetchResponseType, ChatLocation } from '../../../platform/chat/comm
99
import { IEndpointProvider } from '../../../platform/endpoint/common/endpointProvider';
1010
import { ILogService } from '../../../platform/log/common/logService';
1111
import { IInstantiationService } from '../../../util/vs/platform/instantiation/common/instantiation';
12+
import { ConversationHistorySummarizationPrompt } from '../../prompts/node/agent/summarizedConversationHistory';
13+
import { renderPromptElement } from '../../prompts/node/base/promptRenderer';
14+
import { ChatVariablesCollection } from '../common/chatVariablesCollection';
1215
import { TurnStatus } from '../common/conversation';
16+
import { IBuildPromptContext } from '../common/intents';
1317
import { addHistoryToConversation } from './chatParticipantRequestHandler';
1418

15-
// Simple prompt template for summarization
16-
// Consider adopting the more sophisticated summarizedConversationHistory.tsx
17-
class SummaryPrompt {
18-
render() {
19-
return {
20-
messages: [
21-
{
22-
role: 'system' as const,
23-
content: `You are an expert at summarizing chat conversations.
24-
25-
You will be provided:
26-
27-
- A series of user/assistant message pairs in chronological order
28-
- A final user message indicating the user's intent.
29-
30-
Your task is to:
31-
32-
- Create a detailed summary of the conversation that captures the user's intent and key information.
33-
34-
Keep in mind:
35-
36-
- The user is iterating on a feature specification, bug fix, or other common programming task.
37-
- There may be relevant code snippets or files referenced in the conversation.
38-
- The user is collaborating with the assistant to refine their ideas and solutions, course-correcting the assistant as needed.
39-
- The user will provide feedback on the assistant's suggestions and may request changes or improvements.
40-
- Disregard messages that the user has indicated are incorrect, irrelevant, or unhelpful.
41-
- Preserve relevant and actionable context and key information.
42-
- If the conversation is long or discusses several tasks, keep the summary focused on the task indicated by the user's intent.
43-
- Always prefer decisions in later messages over earlier ones.
44-
45-
Structure your summary using the following format:
46-
47-
TITLE: A brief title for the summary
48-
USER INTENT: The user's goal or intent for the conversation
49-
TASK DESCRIPTION: Main technical goals and user requirements
50-
EXISTING: What has already been accomplished. Include file paths and other direct references.
51-
PENDING: What still needs to be done. Include file paths and other direct references.
52-
CODE STATE: A list of all files discussed or modified. Provide code snippets or diffs that illustrate important context.
53-
RELEVANT CODE/DOCUMENTATION SNIPPETS: Key code or documentation snippets from referenced files or discussions.
54-
OTHER NOTES: Any additional context or information that may be relevant.`
55-
}
56-
]
57-
};
58-
}
59-
}
60-
6119
export class ChatSummarizerProvider implements vscode.ChatSummarizer {
6220

6321
constructor(
@@ -77,43 +35,40 @@ export class ChatSummarizerProvider implements vscode.ChatSummarizer {
7735
}
7836

7937
const endpoint = await this.endpointProvider.getChatEndpoint('gpt-4o-mini');
80-
const summaryPrompt = new SummaryPrompt();
81-
const { messages: systemMessages } = summaryPrompt.render();
82-
83-
// Condense each turn into a single user message containing both request and response
84-
const conversationContent = turns
85-
.filter(turn => turn.request?.message)
86-
.map(turn => {
87-
const userMsg = turn.request?.message || '';
88-
const assistantMsg = turn.responseMessage?.message || '';
89-
if (assistantMsg) {
90-
return `User: ${userMsg}\n\nAssistant: ${assistantMsg}`;
91-
} else {
92-
return `User: ${userMsg}`;
93-
}
94-
})
95-
.join('\n\n---\n\n');
96-
97-
const conversationMessages: Raw.ChatMessage[] = [
98-
{
99-
role: Raw.ChatRole.User,
100-
content: [{
101-
type: Raw.ChatCompletionContentPartKind.Text,
102-
text: `Here is the conversation to summarize:\n\n${conversationContent}`
103-
}]
104-
}
105-
];
38+
const promptContext: IBuildPromptContext = {
39+
requestId: 'chat-summary',
40+
query: '',
41+
history: turns,
42+
chatVariables: new ChatVariablesCollection(),
43+
isContinuation: false,
44+
toolCallRounds: undefined,
45+
toolCallResults: undefined,
46+
};
10647

107-
const allMessages: Raw.ChatMessage[] = [
108-
{
109-
role: Raw.ChatRole.System,
110-
content: [{
111-
type: Raw.ChatCompletionContentPartKind.Text,
112-
text: systemMessages[0].content as string
113-
}]
114-
},
115-
...conversationMessages
116-
];
48+
let allMessages: Raw.ChatMessage[];
49+
try {
50+
const rendered = await renderPromptElement(
51+
this.instantiationService,
52+
endpoint,
53+
ConversationHistorySummarizationPrompt,
54+
{
55+
priority: 0,
56+
endpoint,
57+
location: ChatLocation.Panel,
58+
promptContext,
59+
maxToolResultLength: 2000,
60+
triggerSummarize: false,
61+
simpleMode: false,
62+
maxSummaryTokens: 7_000,
63+
},
64+
undefined,
65+
token
66+
);
67+
allMessages = rendered.messages;
68+
} catch (err) {
69+
this.logService.error(`Failed to render conversation summarization prompt: ${err instanceof Error ? err.message : String(err)}`);
70+
return '';
71+
}
11772

11873
const response = await endpoint.makeChatRequest(
11974
'summarize',

src/extension/prompts/node/agent/summarizedConversationHistory.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,8 @@ export interface SummarizedAgentHistoryProps extends BasePromptElementProps {
320320
readonly enableCacheBreakpoints?: boolean;
321321
readonly workingNotebook?: NotebookDocument;
322322
readonly maxToolResultLength: number;
323+
/** Optional hard cap on summary tokens; effective budget = min(prompt sizing tokenBudget, this value) */
324+
readonly maxSummaryTokens?: number;
323325
}
324326

325327
/**
@@ -524,9 +526,13 @@ class ConversationHistorySummarizer {
524526
}
525527

526528
const summarySize = await this.sizing.countTokens(response.value);
527-
if (summarySize > this.sizing.tokenBudget) {
529+
const effectiveBudget =
530+
!!this.props.maxSummaryTokens
531+
? Math.min(this.sizing.tokenBudget, this.props.maxSummaryTokens)
532+
: this.sizing.tokenBudget;
533+
if (summarySize > effectiveBudget) {
528534
this.sendSummarizationTelemetry('too_large', response.requestId, this.props.endpoint.model, mode, elapsedTime, response.usage);
529-
this.logInfo(`Summary too large: ${summarySize} tokens`, mode);
535+
this.logInfo(`Summary too large: ${summarySize} tokens (effective budget ${effectiveBudget})`, mode);
530536
throw new Error('Summary too large');
531537
}
532538

0 commit comments

Comments
 (0)