mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-21 02:11:29 +00:00
feat: support high context limits (CodeGPT)
This commit is contained in:
parent
d336b9ec8b
commit
30c255c5b5
20 changed files with 190 additions and 34 deletions
|
|
@ -63,7 +63,7 @@ public final class EncodingManager {
|
|||
public int countTokens(String text) {
|
||||
try {
|
||||
// #444: Cl100kParser.split() throws AssertionError "Input is not UTF-8: "
|
||||
return encoding.countTokens(text);
|
||||
return encoding.countTokens(text.replaceAll("<|", "").replaceAll("|>", ""));
|
||||
} catch (Exception | Error ex) {
|
||||
LOG.warn("Could not count tokens for: " + text, ex);
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
package ee.carlrobert.codegpt.completions;
|
||||
|
||||
import ee.carlrobert.codegpt.ReferencedFile;
|
||||
import ee.carlrobert.codegpt.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.conversations.message.Message;
|
||||
import java.util.List;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CallParameters {
|
||||
|
|
@ -11,8 +13,9 @@ public class CallParameters {
|
|||
private final Message message;
|
||||
private final boolean retry;
|
||||
private final String highlightedText;
|
||||
private @Nullable String imageMediaType;
|
||||
private String imageMediaType;
|
||||
private byte[] imageData;
|
||||
private List<ReferencedFile> referencedFiles;
|
||||
|
||||
public CallParameters(Conversation conversation, Message message) {
|
||||
this(conversation, ConversationType.DEFAULT, message, null, false);
|
||||
|
|
@ -66,4 +69,12 @@ public class CallParameters {
|
|||
public @Nullable String getHighlightedText() {
|
||||
return highlightedText;
|
||||
}
|
||||
|
||||
public @Nullable List<ReferencedFile> getReferencedFiles() {
|
||||
return referencedFiles;
|
||||
}
|
||||
|
||||
public void setReferencedFiles(List<ReferencedFile> referencedFiles) {
|
||||
this.referencedFiles = referencedFiles;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import ee.carlrobert.codegpt.ReferencedFile;
|
|||
import ee.carlrobert.codegpt.actions.ActionType;
|
||||
import ee.carlrobert.codegpt.completions.CallParameters;
|
||||
import ee.carlrobert.codegpt.completions.CompletionRequestService;
|
||||
import ee.carlrobert.codegpt.completions.CompletionRequestUtil;
|
||||
import ee.carlrobert.codegpt.completions.ConversationType;
|
||||
import ee.carlrobert.codegpt.completions.ToolwindowChatCompletionRequestHandler;
|
||||
import ee.carlrobert.codegpt.conversations.Conversation;
|
||||
|
|
@ -134,8 +133,6 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
.toList();
|
||||
message.setReferencedFilePaths(referencedFilePaths);
|
||||
message.setUserMessage(message.getPrompt());
|
||||
message.setPrompt(
|
||||
CompletionRequestUtil.getPromptWithContext(referencedFiles, message.getPrompt()));
|
||||
|
||||
totalTokensPanel.updateReferencedFilesTokens(referencedFiles);
|
||||
|
||||
|
|
@ -147,6 +144,7 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
var attachedFilePath = CodeGPTKeys.IMAGE_ATTACHMENT_FILE_PATH.get(project);
|
||||
var callParameters =
|
||||
getCallParameters(conversationType, message, highlightedText, attachedFilePath);
|
||||
callParameters.setReferencedFiles(referencedFiles);
|
||||
if (callParameters.getImageData() != null) {
|
||||
message.setImageFilePath(attachedFilePath);
|
||||
chatToolWindowPanel.ifPresent(panel -> panel.clearNotifications(project));
|
||||
|
|
@ -180,10 +178,23 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
return callParameters;
|
||||
}
|
||||
|
||||
private boolean hasReferencedFilePaths(Message message) {
|
||||
return message.getReferencedFilePaths() != null && !message.getReferencedFilePaths().isEmpty();
|
||||
}
|
||||
|
||||
private boolean hasReferencedFilePaths(Conversation conversation) {
|
||||
return conversation.getMessages().stream()
|
||||
.anyMatch(
|
||||
it -> it.getReferencedFilePaths() != null && !it.getReferencedFilePaths().isEmpty());
|
||||
}
|
||||
|
||||
private ResponsePanel createResponsePanel(
|
||||
CallParameters callParameters,
|
||||
ConversationType conversationType) {
|
||||
var message = callParameters.getMessage();
|
||||
var fileContextIncluded =
|
||||
hasReferencedFilePaths(message) || hasReferencedFilePaths(conversation);
|
||||
|
||||
return new ResponsePanel()
|
||||
.withReloadAction(() -> reloadMessage(message, conversation, conversationType))
|
||||
.withDeleteAction(() -> removeMessage(message.getId(), conversation))
|
||||
|
|
@ -194,7 +205,9 @@ public class ChatToolWindowTabPanel implements Disposable {
|
|||
true,
|
||||
false,
|
||||
message.isWebSearchIncluded(),
|
||||
message.getDocumentationDetails() != null, this));
|
||||
message.getDocumentationDetails() != null,
|
||||
fileContextIncluded,
|
||||
this));
|
||||
}
|
||||
|
||||
private void reloadMessage(
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import ee.carlrobert.codegpt.events.AnalysisCompletedEventDetails;
|
|||
import ee.carlrobert.codegpt.events.AnalysisFailedEventDetails;
|
||||
import ee.carlrobert.codegpt.events.CodeGPTEvent;
|
||||
import ee.carlrobert.codegpt.events.EventDetails;
|
||||
import ee.carlrobert.codegpt.events.ProcessContextEventDetails;
|
||||
import ee.carlrobert.codegpt.events.WebSearchEventDetails;
|
||||
import ee.carlrobert.codegpt.settings.GeneralSettingsConfigurable;
|
||||
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
|
||||
|
|
@ -44,10 +45,10 @@ import javax.swing.Box;
|
|||
import javax.swing.BoxLayout;
|
||||
import javax.swing.DefaultListModel;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextPane;
|
||||
import javax.swing.SwingConstants;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ChatMessageResponseBody extends JPanel {
|
||||
|
|
@ -59,7 +60,9 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
private final DefaultListModel<WebSearchEventDetails> webpageListModel = new DefaultListModel<>();
|
||||
private final WebpageList webpageList = new WebpageList(webpageListModel);
|
||||
private final JPanel webDocProgressContainer = new JPanel();
|
||||
private final AsyncProcessIcon spinner = new AsyncProcessIcon("sign_in_spinner");
|
||||
private final JPanel progressContainer = new JPanel();
|
||||
private final AsyncProcessIcon webDocsSpinner = new AsyncProcessIcon("web_docs_spinner");
|
||||
private final AsyncProcessIcon processSpinner = new AsyncProcessIcon("process_spinner");
|
||||
private final @Nullable String highlightedText;
|
||||
private ResponseEditorPanel currentlyProcessedEditorPanel;
|
||||
private JTextPane currentlyProcessedTextPane;
|
||||
|
|
@ -67,7 +70,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
private boolean responseReceived;
|
||||
|
||||
public ChatMessageResponseBody(Project project, Disposable parentDisposable) {
|
||||
this(project, null, false, false, false, false, parentDisposable);
|
||||
this(project, null, false, false, false, false, false, parentDisposable);
|
||||
}
|
||||
|
||||
public ChatMessageResponseBody(
|
||||
|
|
@ -77,8 +80,8 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
boolean readOnly,
|
||||
boolean webSearchIncluded,
|
||||
boolean webDocIncluded,
|
||||
boolean fileContextIncluded,
|
||||
Disposable parentDisposable) {
|
||||
super(new BorderLayout());
|
||||
this.project = project;
|
||||
this.highlightedText = highlightedText;
|
||||
this.parentDisposable = parentDisposable;
|
||||
|
|
@ -98,6 +101,12 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
add(webDocProgressContainer);
|
||||
}
|
||||
|
||||
if (fileContextIncluded) {
|
||||
progressContainer.setLayout(new BoxLayout(progressContainer, BoxLayout.Y_AXIS));
|
||||
progressContainer.setBorder(JBUI.Borders.emptyBottom(8));
|
||||
add(progressContainer);
|
||||
}
|
||||
|
||||
if (withGhostText) {
|
||||
prepareProcessingText(!readOnly);
|
||||
currentlyProcessedTextPane.setText(
|
||||
|
|
@ -209,6 +218,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
case ANALYZE_WEB_DOC_STARTED -> showWebDocsProgress();
|
||||
case ANALYZE_WEB_DOC_COMPLETED -> completeWebDocsProgress(event.getDetails());
|
||||
case ANALYZE_WEB_DOC_FAILED -> failWebDocsProgress(event.getDetails());
|
||||
case PROCESS_CONTEXT -> showProcessContextEvent(event.getDetails());
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
|
|
@ -305,7 +315,7 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
|
||||
private void showWebDocsProgress() {
|
||||
var wrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
wrapper.add(spinner);
|
||||
wrapper.add(webDocsSpinner);
|
||||
wrapper.add(Box.createHorizontalStrut(4));
|
||||
wrapper.add(new JBLabel(
|
||||
CodeGPTBundle.get("chatMessageResponseBody.webDocs.startProgress.label")).withFont(
|
||||
|
|
@ -325,10 +335,50 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
}
|
||||
}
|
||||
|
||||
private void showProcessContextEvent(EventDetails eventDetails) {
|
||||
if (eventDetails instanceof ProcessContextEventDetails details) {
|
||||
switch (details.getStatus()) {
|
||||
case "STARTED": {
|
||||
updateProgressContainer(details.getDescription(), null);
|
||||
break;
|
||||
}
|
||||
case "FAILED": {
|
||||
updateProgressContainer(details.getDescription(), General.Error);
|
||||
break;
|
||||
}
|
||||
case "COMPLETED": {
|
||||
updateProgressContainer(details.getDescription(), Icons.GreenCheckmark);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateWebDocsProgressLabel(String text, Icon icon) {
|
||||
updateWebDocsProgress(new JBLabel(text, icon, SwingConstants.LEADING).withFont(JBFont.small()));
|
||||
}
|
||||
|
||||
private void updateProgressContainer(String text, @Nullable Icon icon) {
|
||||
ApplicationManager.getApplication().invokeLater(() -> {
|
||||
progressContainer.removeAll();
|
||||
JComponent wrapper;
|
||||
if (icon != null) {
|
||||
wrapper = new JBLabel(text, icon, SwingConstants.LEADING);
|
||||
((JBLabel) wrapper).setHorizontalTextPosition(SwingConstants.LEADING);
|
||||
} else {
|
||||
wrapper = new JPanel(new FlowLayout(FlowLayout.LEADING, 0, 0));
|
||||
wrapper.add(new JBLabel(text));
|
||||
wrapper.add(Box.createHorizontalStrut(4));
|
||||
wrapper.add(processSpinner);
|
||||
}
|
||||
progressContainer.add(JBUI.Panels.simplePanel(wrapper));
|
||||
progressContainer.revalidate();
|
||||
progressContainer.repaint();
|
||||
});
|
||||
}
|
||||
|
||||
private void updateWebDocsProgress(Component content) {
|
||||
webDocProgressContainer.removeAll();
|
||||
webDocProgressContainer.add(JBUI.Panels.simplePanel(content));
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ public class ChatToolWindowScrollablePanel extends ScrollablePanel {
|
|||
It looks like you haven't configured your API key yet. Visit <a href="#OPEN_SETTINGS">CodeGPT settings</a> to do so.
|
||||
</p>
|
||||
<p style="margin-top: 4px; margin-bottom: 4px;">
|
||||
Don't have an account? <a href="https://codegpt.ee/signin">Sign up</a> for free access to all open-source models.
|
||||
Don't have an account? <a href="https://codegpt.ee">Sign up</a> for free access to all models.
|
||||
</p>
|
||||
</html>""",
|
||||
false,
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ public class UserMessagePanel extends JPanel {
|
|||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
parentDisposable)
|
||||
.withResponse(prompt);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ public class TotalTokensPanel extends JPanel {
|
|||
"Referenced Files Tokens", totalTokensDetails.getReferencedFilesTokens()))
|
||||
.entrySet().stream()
|
||||
.map(entry -> format(
|
||||
"<p style=\"margin: 0;\"><small>%s: <strong>%d</strong></small></p>",
|
||||
"<p style=\"margin: 0; padding: 0;\"><small>%s: <strong>%d</strong></small></p>",
|
||||
entry.getKey(),
|
||||
entry.getValue()))
|
||||
.collect(Collectors.joining());
|
||||
|
|
@ -165,14 +165,16 @@ public class TotalTokensPanel extends JPanel {
|
|||
private String getIconToolTipText(String html) {
|
||||
if (!GeneralSettings.isSelected(ServiceType.OPENAI)) {
|
||||
return """
|
||||
<html
|
||||
<p style="margin: 4px 0;">
|
||||
<html>
|
||||
<body style="margin: 0; padding: 0;">
|
||||
%s
|
||||
<p style="margin-top: 8px;">
|
||||
<small>
|
||||
<strong>ⓘ Keep in mind that the output values might vary across different
|
||||
large language models due to variations in their encoding methods.</strong>
|
||||
<strong>Note:</strong> Output values might vary across different large language models
|
||||
due to variations in their encoding methods.
|
||||
</small>
|
||||
</p>
|
||||
%s
|
||||
</body>
|
||||
</html>""".formatted(html);
|
||||
}
|
||||
return "<html" + html + "</html>";
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
package ee.carlrobert.codegpt.ui.checkbox;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.CheckedTreeNode;
|
||||
import com.intellij.util.PlatformIcons;
|
||||
import ee.carlrobert.codegpt.ReferencedFile;
|
||||
import ee.carlrobert.codegpt.ui.OverlayUtil;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
|
@ -19,12 +21,20 @@ public class VirtualFileCheckboxTree extends FileCheckboxTree {
|
|||
|
||||
public List<ReferencedFile> getReferencedFiles() {
|
||||
var checkedNodes = getCheckedNodes(VirtualFile.class, Objects::nonNull);
|
||||
if (checkedNodes.length > 1000) {
|
||||
if (checkedNodes.length > 1024) {
|
||||
OverlayUtil.showNotification("Too many files selected.", NotificationType.ERROR);
|
||||
throw new RuntimeException("Too many files selected");
|
||||
}
|
||||
|
||||
return Arrays.stream(checkedNodes)
|
||||
.map(item -> new ReferencedFile(new File(item.getPath())))
|
||||
.map(item -> {
|
||||
var file = new File(item.getPath());
|
||||
if (file.isFile()) {
|
||||
return new ReferencedFile(file);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue