Skip to content

Commit

Permalink
Closes #3005 adds GPT-4 Turbo & latest Anthropic models
Browse files Browse the repository at this point in the history
  • Loading branch information
eamodio committed Nov 15, 2023
1 parent b58d654 commit fd23c90
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 92 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/) and this p

## [Unreleased]

### Added

- 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)

### Changed

- Refines AI prompts to provide better commit message generation and explanation results

## [14.5.0] - 2023-11-13

### Added
Expand Down
36 changes: 17 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3175,7 +3175,7 @@
},
"gitlens.experimental.generateCommitMessagePrompt": {
"type": "string",
"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",
"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.",
"markdownDescription": "Specifies the prompt to use to tell OpenAI how to structure or format the generated commit message",
"scope": "window",
"order": 2
Expand All @@ -3202,19 +3202,23 @@
"gpt-3.5-turbo",
"gpt-3.5-turbo-16k",
"gpt-3.5-turbo-0613",
"gpt-3.5-turbo-1106",
"gpt-4",
"gpt-4-0613",
"gpt-4-32k",
"gpt-4-32k-0613"
"gpt-4-32k-0613",
"gpt-4-1106-preview"
],
"enumDescriptions": [
"GPT 3.5 Turbo",
"GPT 3.5 Turbo 16k",
"GPT 3.5 Turbo (June 13)",
"GPT 4",
"GPT 4 (June 13)",
"GPT 4 32k",
"GPT 4 32k (June 13)"
"GPT-3.5 Turbo",
"GPT-3.5 Turbo 16k",
"GPT-3.5 Turbo (June 13)",
"GPT-3.5 Turbo (Nov 6)",
"GPT-4",
"GPT-4 (June 13)",
"GPT-4 32k",
"GPT-4 32k (June 13)",
"GPT-4 Turbo (Nov 6)"
],
"markdownDescription": "Specifies the OpenAI model to use for GitLens' experimental AI features",
"scope": "window",
Expand All @@ -3232,20 +3236,14 @@
},
"gitlens.ai.experimental.anthropic.model": {
"type": "string",
"default": "claude-v1",
"default": "claude-instant-1",
"enum": [
"claude-v1",
"claude-v1-100k",
"claude-instant-v1",
"claude-instant-v1-100k",
"claude-instant-1",
"claude-2"
],
"enumDescriptions": [
"Claude v1",
"Claude v1 100k",
"Claude Instant v1",
"Claude Instant v1 100k",
"Claude 2"
"Claude Instant",
"Claude"
],
"markdownDescription": "Specifies the Anthropic model to use for GitLens' experimental AI features",
"scope": "window",
Expand Down
86 changes: 58 additions & 28 deletions src/ai/anthropicProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export class AnthropicProvider implements AIProvider {
readonly name = 'Anthropic';

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

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

const model = this.model;
const maxCodeCharacters = getMaxCharacters(model);
const maxCodeCharacters = getMaxCharacters(model, 1600);

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

let prompt =
"\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.";
prompt += `\n${customPrompt}\n- Avoid phrases like "this commit", "this change", etc.`;
prompt += '\n\nAssistant: OK';
if (options?.context) {
prompt += `\n\nHuman: Use "${options.context}" to help craft the commit message.\n\nAssistant: OK`;
}
prompt += `\n\nHuman: Write a meaningful commit message for the following code changes:\n\n${code}`;
prompt += '\n\nAssistant:';
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:
- Strictly synthesizes meaningful information from the provided code diff
- Utilizes any additional user-provided context to comprehend the rationale behind the code changes
- Is clear and brief, with an informal yet professional tone, and without superfluous descriptions
- Avoids unnecessary phrases such as "this commit", "this change", and the like
- Avoids direct mention of specific code identifiers, names, or file names, unless they are crucial for understanding the purpose of the changes
- Most importantly emphasizes the 'why' of the change, its benefits, or the problem it addresses rather than only the 'what' that changed
Follow the user's instructions carefully, don't repeat yourself, don't include the code in the output, or make anything up!
Human: Here is the code diff to use to generate the commit message:
${code}
${
options?.context
? `Human: Here is additional context which should be taken into account when generating the commit message:\n\n${options.context}`
: ''
}
Human: ${customPrompt}
Assistant:`;

const request: AnthropicCompletionRequest = {
model: model,
Expand Down Expand Up @@ -80,7 +94,7 @@ export class AnthropicProvider implements AIProvider {
if (apiKey == null) return undefined;

const model = this.model;
const maxCodeCharacters = getMaxCharacters(model);
const maxCodeCharacters = getMaxCharacters(model, 2400);

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

let prompt =
"\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!";
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}`;
prompt += '\n\nAssistant: OK';
prompt += `\n\nHuman: Explain the following code changes:\n\n${code}`;
prompt += '\n\nAssistant:';
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:
- Concisely synthesizes meaningful information from the provided code diff
- Incorporates any additional context provided by the user to understand the rationale behind the code changes
- 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
Do not make any assumptions or invent details that are not supported by the code diff or the user-provided context.
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:
${message}
Human: Now, kindly explain the following code diff in a way that would be clear to someone reviewing or trying to understand these changes:
${code}
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.
Assistant:`;

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

function getMaxCharacters(model: AnthropicModels): number {
if (model === 'claude-2' || model === 'claude-v1-100k' || model === 'claude-instant-v1-100k') {
return 135000;
function getMaxCharacters(model: AnthropicModels, outputLength: number): number {
let tokens;
switch (model) {
case 'claude-2': // 100,000 tokens
case 'claude-instant-1':
tokens = 100000;
break;
default: // 4,096 tokens
tokens = 4096;
break;
}
return 12000;

return tokens * 4 - outputLength / 4;
}
export type AnthropicModels =
| 'claude-v1'
| 'claude-v1-100k'
| 'claude-instant-v1'
| 'claude-instant-v1-100k'
| 'claude-2';

export type AnthropicModels = 'claude-instant-1' | 'claude-2';

interface AnthropicCompletionRequest {
model: string;
Expand Down
92 changes: 62 additions & 30 deletions src/ai/openaiProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class OpenAIProvider implements AIProvider {
if (apiKey == null) return undefined;

const model = this.model;
const maxCodeCharacters = getMaxCharacters(model);
const maxCodeCharacters = getMaxCharacters(model, 1600);

const code = diff.substring(0, maxCodeCharacters);
if (diff.length > maxCodeCharacters) {
Expand All @@ -47,27 +47,35 @@ export class OpenAIProvider implements AIProvider {
messages: [
{
role: 'system',
content:
"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.",
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:
- Strictly synthesizes meaningful information from the provided code diff
- Utilizes any additional user-provided context to comprehend the rationale behind the code changes
- Is clear and brief, with an informal yet professional tone, and without superfluous descriptions
- Avoids unnecessary phrases such as "this commit", "this change", and the like
- Avoids direct mention of specific code identifiers, names, or file names, unless they are crucial for understanding the purpose of the changes
- Most importantly emphasizes the 'why' of the change, its benefits, or the problem it addresses rather than only the 'what' that changed
Follow the user's instructions carefully, don't repeat yourself, don't include the code in the output, or make anything up!`,
},
{
role: 'user',
content: `Here is the code diff to use to generate the commit message:\n\n${code}`,
},
...(options?.context
? [
{
role: 'user' as const,
content: `Here is additional context which should be taken into account when generating the commit message:\n\n${options.context}`,
},
]
: []),
{
role: 'user',
content: `${customPrompt}\n- Avoid phrases like "this commit", "this change", etc.`,
content: customPrompt,
},
],
};

if (options?.context) {
request.messages.push({
role: 'user',
content: `Use "${options.context}" to help craft the commit message.`,
});
}
request.messages.push({
role: 'user',
content: `Write a meaningful commit message for the following code changes:\n\n${code}`,
});

const rsp = await this.fetch(apiKey, request);
if (!rsp.ok) {
debugger;
Expand All @@ -89,7 +97,7 @@ export class OpenAIProvider implements AIProvider {
if (apiKey == null) return undefined;

const model = this.model;
const maxCodeCharacters = getMaxCharacters(model);
const maxCodeCharacters = getMaxCharacters(model, 2400);

const code = diff.substring(0, maxCodeCharacters);
if (diff.length > maxCodeCharacters) {
Expand All @@ -103,20 +111,25 @@ export class OpenAIProvider implements AIProvider {
messages: [
{
role: 'system',
content:
"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!",
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:
- Concisely synthesizes meaningful information from the provided code diff
- Incorporates any additional context provided by the user to understand the rationale behind the code changes
- 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
Do not make any assumptions or invent details that are not supported by the code diff or the user-provided context.`,
},
{
role: 'user',
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}`,
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}`,
},
{
role: 'assistant',
content: 'OK',
role: 'user',
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}`,
},
{
role: 'user',
content: `Explain the following code changes:\n\n${code}`,
content:
'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.',
},
],
};
Expand Down Expand Up @@ -220,26 +233,45 @@ async function getApiKey(storage: Storage): Promise<string | undefined> {
return openaiApiKey;
}

function getMaxCharacters(model: OpenAIModels): number {
function getMaxCharacters(model: OpenAIModels, outputLength: number): number {
let tokens;
switch (model) {
case 'gpt-4-32k':
case 'gpt-4-1106-preview': // 128,000 tokens (4,096 max output tokens)
tokens = 128000;
break;
case 'gpt-4-32k': // 32,768 tokens
case 'gpt-4-32k-0613':
return 43000;
case 'gpt-3.5-turbo-16k':
return 21000;
default:
return 12000;
tokens = 32768;
break;
case 'gpt-4': // 8,192 tokens
case 'gpt-4-0613':
tokens = 8192;
break;
case 'gpt-3.5-turbo-1106': // 16,385 tokens (4,096 max output tokens)
tokens = 16385;
break;
case 'gpt-3.5-turbo-16k': // 16,385 tokens; Will point to gpt-3.5-turbo-1106 starting Dec 11, 2023
tokens = 16385;
break;
case 'gpt-3.5-turbo': // Will point to gpt-3.5-turbo-1106 starting Dec 11, 2023
default: // 4,096 tokens
tokens = 4096;
break;
}

return tokens * 4 - outputLength / 4;
}

export type OpenAIModels =
| 'gpt-3.5-turbo-1106'
| 'gpt-3.5-turbo'
| 'gpt-3.5-turbo-16k'
| 'gpt-3.5-turbo-0613'
| 'gpt-4'
| 'gpt-4-0613'
| 'gpt-4-32k'
| 'gpt-4-32k-0613';
| 'gpt-4-32k-0613'
| 'gpt-4-1106-preview';

interface OpenAIChatCompletionRequest {
model: OpenAIModels;
Expand Down
Loading

0 comments on commit fd23c90

Please sign in to comment.