Skip to content

Commit fd23c90

Browse files
committed
Closes #3005 adds GPT-4 Turbo & latest Anthropic models
1 parent b58d654 commit fd23c90

File tree

5 files changed

+152
-92
lines changed

5 files changed

+152
-92
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p
66

77
## [Unreleased]
88

9+
### Added
10+
11+
- Adds support for OpenAI's GPT-4 Turbo and latest Anthropic models for GitLens' experimental AI features — closes [#3005](https://github.com/gitkraken/vscode-gitlens/issues/3005)
12+
13+
### Changed
14+
15+
- Refines AI prompts to provide better commit message generation and explanation results
16+
917
## [14.5.0] - 2023-11-13
1018

1119
### Added

package.json

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3175,7 +3175,7 @@
31753175
},
31763176
"gitlens.experimental.generateCommitMessagePrompt": {
31773177
"type": "string",
3178-
"default": "Commit messages must have a short description that is less than 50 chars followed by a newline and a more detailed description.\n- Write concisely using an informal tone and avoid specific names from the code",
3178+
"default": "Now, please generate a commit message. Ensure that it includes a precise and informative subject line that succinctly summarizes the crux of the changes in under 50 characters. If necessary, follow with an explanatory body providing insight into the nature of the changes, the reasoning behind them, and any significant consequences or considerations arising from them. Conclude with any relevant issue references at the end of the message.",
31793179
"markdownDescription": "Specifies the prompt to use to tell OpenAI how to structure or format the generated commit message",
31803180
"scope": "window",
31813181
"order": 2
@@ -3202,19 +3202,23 @@
32023202
"gpt-3.5-turbo",
32033203
"gpt-3.5-turbo-16k",
32043204
"gpt-3.5-turbo-0613",
3205+
"gpt-3.5-turbo-1106",
32053206
"gpt-4",
32063207
"gpt-4-0613",
32073208
"gpt-4-32k",
3208-
"gpt-4-32k-0613"
3209+
"gpt-4-32k-0613",
3210+
"gpt-4-1106-preview"
32093211
],
32103212
"enumDescriptions": [
3211-
"GPT 3.5 Turbo",
3212-
"GPT 3.5 Turbo 16k",
3213-
"GPT 3.5 Turbo (June 13)",
3214-
"GPT 4",
3215-
"GPT 4 (June 13)",
3216-
"GPT 4 32k",
3217-
"GPT 4 32k (June 13)"
3213+
"GPT-3.5 Turbo",
3214+
"GPT-3.5 Turbo 16k",
3215+
"GPT-3.5 Turbo (June 13)",
3216+
"GPT-3.5 Turbo (Nov 6)",
3217+
"GPT-4",
3218+
"GPT-4 (June 13)",
3219+
"GPT-4 32k",
3220+
"GPT-4 32k (June 13)",
3221+
"GPT-4 Turbo (Nov 6)"
32183222
],
32193223
"markdownDescription": "Specifies the OpenAI model to use for GitLens' experimental AI features",
32203224
"scope": "window",
@@ -3232,20 +3236,14 @@
32323236
},
32333237
"gitlens.ai.experimental.anthropic.model": {
32343238
"type": "string",
3235-
"default": "claude-v1",
3239+
"default": "claude-instant-1",
32363240
"enum": [
3237-
"claude-v1",
3238-
"claude-v1-100k",
3239-
"claude-instant-v1",
3240-
"claude-instant-v1-100k",
3241+
"claude-instant-1",
32413242
"claude-2"
32423243
],
32433244
"enumDescriptions": [
3244-
"Claude v1",
3245-
"Claude v1 100k",
3246-
"Claude Instant v1",
3247-
"Claude Instant v1 100k",
3248-
"Claude 2"
3245+
"Claude Instant",
3246+
"Claude"
32493247
],
32503248
"markdownDescription": "Specifies the Anthropic model to use for GitLens' experimental AI features",
32513249
"scope": "window",

src/ai/anthropicProvider.ts

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export class AnthropicProvider implements AIProvider {
1212
readonly name = 'Anthropic';
1313

1414
private get model(): AnthropicModels {
15-
return configuration.get('ai.experimental.anthropic.model') || 'claude-v1';
15+
return configuration.get('ai.experimental.anthropic.model') || 'claude-instant-1';
1616
}
1717

1818
constructor(private readonly container: Container) {}
@@ -24,7 +24,7 @@ export class AnthropicProvider implements AIProvider {
2424
if (apiKey == null) return undefined;
2525

2626
const model = this.model;
27-
const maxCodeCharacters = getMaxCharacters(model);
27+
const maxCodeCharacters = getMaxCharacters(model, 1600);
2828

2929
const code = diff.substring(0, maxCodeCharacters);
3030
if (diff.length > maxCodeCharacters) {
@@ -38,15 +38,29 @@ export class AnthropicProvider implements AIProvider {
3838
customPrompt += '.';
3939
}
4040

41-
let prompt =
42-
"\n\nHuman: You are an AI programming assistant tasked with writing a meaningful commit message by summarizing code changes.\n- Follow the user's instructions carefully & to the letter!\n- Don't repeat yourself or make anything up!\n- Minimize any other prose.";
43-
prompt += `\n${customPrompt}\n- Avoid phrases like "this commit", "this change", etc.`;
44-
prompt += '\n\nAssistant: OK';
45-
if (options?.context) {
46-
prompt += `\n\nHuman: Use "${options.context}" to help craft the commit message.\n\nAssistant: OK`;
47-
}
48-
prompt += `\n\nHuman: Write a meaningful commit message for the following code changes:\n\n${code}`;
49-
prompt += '\n\nAssistant:';
41+
const prompt = `\n\nHuman: You are an advanced AI programming assistant tasked with summarizing code changes into a concise and meaningful commit message. Compose a commit message that:
42+
- Strictly synthesizes meaningful information from the provided code diff
43+
- Utilizes any additional user-provided context to comprehend the rationale behind the code changes
44+
- Is clear and brief, with an informal yet professional tone, and without superfluous descriptions
45+
- Avoids unnecessary phrases such as "this commit", "this change", and the like
46+
- Avoids direct mention of specific code identifiers, names, or file names, unless they are crucial for understanding the purpose of the changes
47+
- Most importantly emphasizes the 'why' of the change, its benefits, or the problem it addresses rather than only the 'what' that changed
48+
49+
Follow the user's instructions carefully, don't repeat yourself, don't include the code in the output, or make anything up!
50+
51+
Human: Here is the code diff to use to generate the commit message:
52+
53+
${code}
54+
55+
${
56+
options?.context
57+
? `Human: Here is additional context which should be taken into account when generating the commit message:\n\n${options.context}`
58+
: ''
59+
}
60+
61+
Human: ${customPrompt}
62+
63+
Assistant:`;
5064

5165
const request: AnthropicCompletionRequest = {
5266
model: model,
@@ -80,7 +94,7 @@ export class AnthropicProvider implements AIProvider {
8094
if (apiKey == null) return undefined;
8195

8296
const model = this.model;
83-
const maxCodeCharacters = getMaxCharacters(model);
97+
const maxCodeCharacters = getMaxCharacters(model, 2400);
8498

8599
const code = diff.substring(0, maxCodeCharacters);
86100
if (diff.length > maxCodeCharacters) {
@@ -89,12 +103,24 @@ export class AnthropicProvider implements AIProvider {
89103
);
90104
}
91105

92-
let prompt =
93-
"\n\nHuman: You are an AI programming assistant tasked with providing an easy to understand but detailed explanation of a commit by summarizing the code changes while also using the commit message as additional context and framing.\nDon't make anything up!";
94-
prompt += `\nUse the following user-provided commit message, which should provide some explanation to why these changes where made, when attempting to generate the rich explanation:\n\n${message}`;
95-
prompt += '\n\nAssistant: OK';
96-
prompt += `\n\nHuman: Explain the following code changes:\n\n${code}`;
97-
prompt += '\n\nAssistant:';
106+
const prompt = `\n\nHuman: You are an advanced AI programming assistant tasked with summarizing code changes into an explanation that is both easy to understand and meaningful. Construct an explanation that:
107+
- Concisely synthesizes meaningful information from the provided code diff
108+
- Incorporates any additional context provided by the user to understand the rationale behind the code changes
109+
- Places the emphasis on the 'why' of the change, clarifying its benefits or addressing the problem that necessitated the change, beyond just detailing the 'what' has changed
110+
111+
Do not make any assumptions or invent details that are not supported by the code diff or the user-provided context.
112+
113+
Human: Here is additional context provided by the author of the changes, which should provide some explanation to why these changes where made. Please strongly consider this information when generating your explanation:
114+
115+
${message}
116+
117+
Human: Now, kindly explain the following code diff in a way that would be clear to someone reviewing or trying to understand these changes:
118+
119+
${code}
120+
121+
Human: Remember to frame your explanation in a way that is suitable for a reviewer to quickly grasp the essence of the changes, the issues they resolve, and their implications on the codebase.
122+
123+
Assistant:`;
98124

99125
const request: AnthropicCompletionRequest = {
100126
model: model,
@@ -200,18 +226,22 @@ async function getApiKey(storage: Storage): Promise<string | undefined> {
200226
return apiKey;
201227
}
202228

203-
function getMaxCharacters(model: AnthropicModels): number {
204-
if (model === 'claude-2' || model === 'claude-v1-100k' || model === 'claude-instant-v1-100k') {
205-
return 135000;
229+
function getMaxCharacters(model: AnthropicModels, outputLength: number): number {
230+
let tokens;
231+
switch (model) {
232+
case 'claude-2': // 100,000 tokens
233+
case 'claude-instant-1':
234+
tokens = 100000;
235+
break;
236+
default: // 4,096 tokens
237+
tokens = 4096;
238+
break;
206239
}
207-
return 12000;
240+
241+
return tokens * 4 - outputLength / 4;
208242
}
209-
export type AnthropicModels =
210-
| 'claude-v1'
211-
| 'claude-v1-100k'
212-
| 'claude-instant-v1'
213-
| 'claude-instant-v1-100k'
214-
| 'claude-2';
243+
244+
export type AnthropicModels = 'claude-instant-1' | 'claude-2';
215245

216246
interface AnthropicCompletionRequest {
217247
model: string;

src/ai/openaiProvider.ts

Lines changed: 62 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class OpenAIProvider implements AIProvider {
2828
if (apiKey == null) return undefined;
2929

3030
const model = this.model;
31-
const maxCodeCharacters = getMaxCharacters(model);
31+
const maxCodeCharacters = getMaxCharacters(model, 1600);
3232

3333
const code = diff.substring(0, maxCodeCharacters);
3434
if (diff.length > maxCodeCharacters) {
@@ -47,27 +47,35 @@ export class OpenAIProvider implements AIProvider {
4747
messages: [
4848
{
4949
role: 'system',
50-
content:
51-
"You are an AI programming assistant tasked with writing a meaningful commit message by summarizing code changes.\n\n- Follow the user's instructions carefully & to the letter!\n- Don't repeat yourself or make anything up!\n- Minimize any other prose.",
50+
content: `You are an advanced AI programming assistant tasked with summarizing code changes into a concise and meaningful commit message. Compose a commit message that:
51+
- Strictly synthesizes meaningful information from the provided code diff
52+
- Utilizes any additional user-provided context to comprehend the rationale behind the code changes
53+
- Is clear and brief, with an informal yet professional tone, and without superfluous descriptions
54+
- Avoids unnecessary phrases such as "this commit", "this change", and the like
55+
- Avoids direct mention of specific code identifiers, names, or file names, unless they are crucial for understanding the purpose of the changes
56+
- Most importantly emphasizes the 'why' of the change, its benefits, or the problem it addresses rather than only the 'what' that changed
57+
58+
Follow the user's instructions carefully, don't repeat yourself, don't include the code in the output, or make anything up!`,
59+
},
60+
{
61+
role: 'user',
62+
content: `Here is the code diff to use to generate the commit message:\n\n${code}`,
5263
},
64+
...(options?.context
65+
? [
66+
{
67+
role: 'user' as const,
68+
content: `Here is additional context which should be taken into account when generating the commit message:\n\n${options.context}`,
69+
},
70+
]
71+
: []),
5372
{
5473
role: 'user',
55-
content: `${customPrompt}\n- Avoid phrases like "this commit", "this change", etc.`,
74+
content: customPrompt,
5675
},
5776
],
5877
};
5978

60-
if (options?.context) {
61-
request.messages.push({
62-
role: 'user',
63-
content: `Use "${options.context}" to help craft the commit message.`,
64-
});
65-
}
66-
request.messages.push({
67-
role: 'user',
68-
content: `Write a meaningful commit message for the following code changes:\n\n${code}`,
69-
});
70-
7179
const rsp = await this.fetch(apiKey, request);
7280
if (!rsp.ok) {
7381
debugger;
@@ -89,7 +97,7 @@ export class OpenAIProvider implements AIProvider {
8997
if (apiKey == null) return undefined;
9098

9199
const model = this.model;
92-
const maxCodeCharacters = getMaxCharacters(model);
100+
const maxCodeCharacters = getMaxCharacters(model, 2400);
93101

94102
const code = diff.substring(0, maxCodeCharacters);
95103
if (diff.length > maxCodeCharacters) {
@@ -103,20 +111,25 @@ export class OpenAIProvider implements AIProvider {
103111
messages: [
104112
{
105113
role: 'system',
106-
content:
107-
"You are an AI programming assistant tasked with providing an easy to understand but detailed explanation of a commit by summarizing the code changes while also using the commit message as additional context and framing.\n\n- Don't make anything up!",
114+
content: `You are an advanced AI programming assistant tasked with summarizing code changes into an explanation that is both easy to understand and meaningful. Construct an explanation that:
115+
- Concisely synthesizes meaningful information from the provided code diff
116+
- Incorporates any additional context provided by the user to understand the rationale behind the code changes
117+
- Places the emphasis on the 'why' of the change, clarifying its benefits or addressing the problem that necessitated the change, beyond just detailing the 'what' has changed
118+
119+
Do not make any assumptions or invent details that are not supported by the code diff or the user-provided context.`,
108120
},
109121
{
110122
role: 'user',
111-
content: `Use the following user-provided commit message, which should provide some explanation to why these changes where made, when attempting to generate the rich explanation:\n\n${message}`,
123+
content: `Here is additional context provided by the author of the changes, which should provide some explanation to why these changes where made. Please strongly consider this information when generating your explanation:\n\n${message}`,
112124
},
113125
{
114-
role: 'assistant',
115-
content: 'OK',
126+
role: 'user',
127+
content: `Now, kindly explain the following code diff in a way that would be clear to someone reviewing or trying to understand these changes:\n\n${code}`,
116128
},
117129
{
118130
role: 'user',
119-
content: `Explain the following code changes:\n\n${code}`,
131+
content:
132+
'Remember to frame your explanation in a way that is suitable for a reviewer to quickly grasp the essence of the changes, the issues they resolve, and their implications on the codebase.',
120133
},
121134
],
122135
};
@@ -220,26 +233,45 @@ async function getApiKey(storage: Storage): Promise<string | undefined> {
220233
return openaiApiKey;
221234
}
222235

223-
function getMaxCharacters(model: OpenAIModels): number {
236+
function getMaxCharacters(model: OpenAIModels, outputLength: number): number {
237+
let tokens;
224238
switch (model) {
225-
case 'gpt-4-32k':
239+
case 'gpt-4-1106-preview': // 128,000 tokens (4,096 max output tokens)
240+
tokens = 128000;
241+
break;
242+
case 'gpt-4-32k': // 32,768 tokens
226243
case 'gpt-4-32k-0613':
227-
return 43000;
228-
case 'gpt-3.5-turbo-16k':
229-
return 21000;
230-
default:
231-
return 12000;
244+
tokens = 32768;
245+
break;
246+
case 'gpt-4': // 8,192 tokens
247+
case 'gpt-4-0613':
248+
tokens = 8192;
249+
break;
250+
case 'gpt-3.5-turbo-1106': // 16,385 tokens (4,096 max output tokens)
251+
tokens = 16385;
252+
break;
253+
case 'gpt-3.5-turbo-16k': // 16,385 tokens; Will point to gpt-3.5-turbo-1106 starting Dec 11, 2023
254+
tokens = 16385;
255+
break;
256+
case 'gpt-3.5-turbo': // Will point to gpt-3.5-turbo-1106 starting Dec 11, 2023
257+
default: // 4,096 tokens
258+
tokens = 4096;
259+
break;
232260
}
261+
262+
return tokens * 4 - outputLength / 4;
233263
}
234264

235265
export type OpenAIModels =
266+
| 'gpt-3.5-turbo-1106'
236267
| 'gpt-3.5-turbo'
237268
| 'gpt-3.5-turbo-16k'
238269
| 'gpt-3.5-turbo-0613'
239270
| 'gpt-4'
240271
| 'gpt-4-0613'
241272
| 'gpt-4-32k'
242-
| 'gpt-4-32k-0613';
273+
| 'gpt-4-32k-0613'
274+
| 'gpt-4-1106-preview';
243275

244276
interface OpenAIChatCompletionRequest {
245277
model: OpenAIModels;

0 commit comments

Comments
 (0)