Skip to content

Commit

Permalink
Merge pull request openpilot-hub#26 from PerryZhao/task/generate-git-…
Browse files Browse the repository at this point in the history
…commit-message

Generate commit message
  • Loading branch information
myoss authored Jan 18, 2024
2 parents 85478a2 + dc1d9ff commit 8998bac
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package com.zhongan.devpilot.actions.changesview;

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.changes.ui.ChangesBrowserBase;
import com.intellij.openapi.vcs.changes.ui.CommitDialogChangesBrowser;
import com.intellij.openapi.vcs.ui.CommitMessage;
import com.zhongan.devpilot.DevPilotIcons;
import com.zhongan.devpilot.actions.notifications.DevPilotNotification;
import com.zhongan.devpilot.constant.DefaultConst;
import com.zhongan.devpilot.constant.PromptConst;
import com.zhongan.devpilot.integrations.llms.LlmProviderFactory;
import com.zhongan.devpilot.integrations.llms.entity.DevPilotChatCompletionRequest;
import com.zhongan.devpilot.integrations.llms.entity.DevPilotMessage;
import com.zhongan.devpilot.util.DevPilotMessageBundle;
import com.zhongan.devpilot.util.DocumentUtil;
import com.zhongan.devpilot.util.MessageUtil;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.jetbrains.annotations.NotNull;

import static com.intellij.util.ObjectUtils.tryCast;
import static java.util.stream.Collectors.joining;
import static java.util.stream.Collectors.toList;

public class GenerateGitCommitMessageAction extends AnAction {

public GenerateGitCommitMessageAction() {
super(DevPilotMessageBundle.get("devpilot.action.changesview.generateCommit"), DevPilotMessageBundle.get("devpilot.action.changesview.generateCommit"), DevPilotIcons.SYSTEM_ICON);
}

@Override
public void actionPerformed(@NotNull AnActionEvent e) {
var project = e.getProject();
if (project == null || project.getBasePath() == null) {
return;
}

try {
String gitDiff = getGitDiff(project, getReferencedFilePaths(e));

if (DocumentUtil.experienceEstimatedTokens(gitDiff) + DocumentUtil.experienceEstimatedTokens(PromptConst.GENERATE_COMMIT) > DefaultConst.TOKEN_MAX_LENGTH) {
DevPilotNotification.warn(DevPilotMessageBundle.get("devpilot.changesview.tokens.estimation.overflow"));
}

var commitMessage = tryCast(e.getData(VcsDataKeys.COMMIT_MESSAGE_CONTROL), CommitMessage.class);
var editor = commitMessage != null ? commitMessage.getEditorField().getEditor() : null;
if (editor != null) {
((EditorEx) editor).setCaretVisible(false);

DevPilotMessage userMessage = MessageUtil.createUserMessage(gitDiff);
DevPilotChatCompletionRequest devPilotChatCompletionRequest = new DevPilotChatCompletionRequest();
devPilotChatCompletionRequest.getMessages().add(MessageUtil.createSystemMessage(PromptConst.GENERATE_COMMIT));
devPilotChatCompletionRequest.getMessages().add(userMessage);
devPilotChatCompletionRequest.setStream(Boolean.FALSE);

var llmProvider = new LlmProviderFactory().getLlmProvider(project);
String result = llmProvider.chatCompletion(devPilotChatCompletionRequest);

var application = ApplicationManager.getApplication();
application.invokeLater(() ->
application.runWriteAction(() ->
WriteCommandAction.runWriteCommandAction(project, () ->
editor.getDocument().setText(result))));
}
} catch (Exception ex) {
DevPilotNotification.warn("Exception occurred while generating commit message");
}
}

private @NotNull List<String> getReferencedFilePaths(AnActionEvent event) {
var changesBrowserBase = event.getData(ChangesBrowserBase.DATA_KEY);
if (changesBrowserBase == null) {
return List.of();
}

var includedChanges = ((CommitDialogChangesBrowser) changesBrowserBase).getIncludedChanges();
return includedChanges.stream()
.filter(item -> item.getVirtualFile() != null)
.map(item -> item.getVirtualFile().getPath())
.collect(toList());
}

private Process createGitDiffProcess(String projectPath, List<String> filePaths) throws IOException {
var command = new ArrayList<String>();
command.add("git");
command.add("diff");
command.addAll(filePaths);

var processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(projectPath));
return processBuilder.start();
}

private String getGitDiff(Project project, List<String> filePaths) throws IOException {
var process = createGitDiffProcess(project.getBasePath(), filePaths);
var reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
return reader.lines().collect(joining("\n"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ private static boolean isInputExceedLimit(String content, String prompt) {
return true;
}
// valid chinese and english character length
return DocumentUtil.getChineseCharCount(content + prompt) / 2 + DocumentUtil.getEnglishCharCount(content + prompt) / 4 > DefaultConst.TOKEN_MAX_LENGTH;
return DocumentUtil.experienceEstimatedTokens(content + prompt) > DefaultConst.TOKEN_MAX_LENGTH;
}

}
13 changes: 8 additions & 5 deletions src/main/java/com/zhongan/devpilot/constant/DefaultConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@

public class DefaultConst {

public final static String MAX_TOKEN_EXCEPTION_MSG = DevPilotMessageBundle.get("devpilot.chatWindow.context.overflow");
private DefaultConst() {
}

public final static int TOKEN_MAX_LENGTH = 4096;
public static final String MAX_TOKEN_EXCEPTION_MSG = DevPilotMessageBundle.get("devpilot.chatWindow.context.overflow");

public final static int ENGLISH_CONTENT_MAX_LENGTH = 12288;
public static final int TOKEN_MAX_LENGTH = 4096;

public final static int CHINESE_CONTENT_MAX_LENGTH = 1638;
public static final int ENGLISH_CONTENT_MAX_LENGTH = 12288;

public final static String DEFAULT_CODE_LANGUAGE = "java";
public static final int CHINESE_CONTENT_MAX_LENGTH = 1638;

public static final String DEFAULT_CODE_LANGUAGE = "java";

}
9 changes: 7 additions & 2 deletions src/main/java/com/zhongan/devpilot/constant/PromptConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@

public class PromptConst {

public final static String RESPONSE_FORMAT = "You are a coding expert.\n" +
private PromptConst() {
}

public static final String RESPONSE_FORMAT = "You are a coding expert.\n" +
"You must obey ALL of the following rules:\n\n" +
"- quote variable name with single backtick such as `name`.\n" +
"- quote code block with triple backticks such as ```...```";

public final static String ANSWER_IN_CHINESE = "\nPlease answer in Chinese.";
public static final String ANSWER_IN_CHINESE = "\nPlease answer in Chinese.";

public static final String GENERATE_COMMIT = "Summarize the git diff with a concise and descriptive commit message. Adopt the imperative mood, present tense, active voice, and include relevant verbs. Remember that your entire response will be directly used as the git commit message.";

}
4 changes: 4 additions & 0 deletions src/main/java/com/zhongan/devpilot/util/DocumentUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,4 +104,8 @@ public static int getEnglishCharCount(String text) {
return englishCount;
}

public static int experienceEstimatedTokens(String text) {
return getChineseCharCount(text) / 2 + getEnglishCharCount(text) / 4;
}

}
6 changes: 6 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@
</action>
<add-to-group group-id="EditorPopupMenu" anchor="first"/>
</group>
<group id="DevPilot.GenerateGitCommitMessageGroup">
<add-to-group group-id="Vcs.MessageActionGroup" anchor="first"/>
<action
id="DevPilot.GenerateGitCommitMessage"
class="com.zhongan.devpilot.actions.changesview.GenerateGitCommitMessageAction" />
</group>
</actions>

<applicationListeners>
Expand Down
5 changes: 4 additions & 1 deletion src/main/resources/messages/devpilot_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ devpilot.action.fix=Fix This
devpilot.action.review=Review Code
devpilot.action.explain=Explain This
devpilot.action.performance.check=Performance Check
devpilot.action.changesview.generateCommit=Generate Commit Message

devpilot.chatWindow.context.overflow=This model's maximum context length is 4096 tokens.
Expand All @@ -33,4 +34,6 @@ devpilot.welcome.assist=Hello @<span style=\"font-weight: bold;\">%s</span>, how
<br><br>\
As an AI-powered assistant, I strive to provide the best possible assistance. \
However, please keep in mind that there might be occasional surprises or mistakes.\
It's always a good idea to double-check any generated code or suggestions.
It's always a good idea to double-check any generated code or suggestions.

devpilot.changesview.tokens.estimation.overflow=The estimated number of tokens exceeds the maximum limit, and unexpected results may occur.
2 changes: 2 additions & 0 deletions src/main/resources/messages/devpilot_zh.properties
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ devpilot.action.fix=\u4ee3\u7801\u4FEE\u590D
devpilot.action.review=\u4EE3\u7801\u5BA1\u67E5
devpilot.action.explain=\u89E3\u91CA\u4ee3\u7801
devpilot.action.performance.check=\u6027\u80FD\u68C0\u67E5
devpilot.action.changesview.generateCommit=\u751f\u6210\u63d0\u4ea4\u65e5\u5fd7

devpilot.chatWindow.context.overflow=\u6a21\u578b\u4e0a\u4e0b\u6587\u6700\u5927\u4e3a4096 tokens.

Expand All @@ -35,3 +36,4 @@ devpilot.welcome.assist=\u60A8\u597D @<span style=\"font-weight: bold;\">%s</spa
\u4F46\u662F\u8BF7\u8BB0\u4F4F\uFF0C\u5076\u5C14\u6211\u4E5F\u4F1A\u51FA\u73B0\u610F\u5916\u6216\u9519\u8BEF\uFF0C\
\u4ED4\u7EC6\u68C0\u67E5\u4EFB\u4F55\u751F\u6210\u7684\u4EE3\u7801\u6216\u5EFA\u8BAE\u603B\u662F\u4E00\u4E2A\u597D\u4E3B\u610F\u3002

devpilot.changesview.tokens.estimation.overflow=\u9884\u4f30\u7684\u0074\u006f\u006b\u0065\u006e\u6570\u8d85\u8fc7\u6700\u5927\u9650\u5236\uff0c\u53ef\u80fd\u4f1a\u6709\u672a\u9884\u671f\u7ed3\u679c

0 comments on commit 8998bac

Please sign in to comment.