mirror of
https://github.com/carlrobertoh/ProxyAI.git
synced 2026-05-12 22:31:24 +00:00
on quota exceeded suggest user switch to different LLM provider (#221)
* on quota exceeded suggest user switch to different LLM provider * Improve insufficient quota handling, add more telemetry actions --------- Co-authored-by: Carl-Robert Linnupuu <carlrobertoh@gmail.com>
This commit is contained in:
parent
a45646740e
commit
4c8b8d4e4f
6 changed files with 95 additions and 21 deletions
|
|
@ -13,5 +13,6 @@ public enum ActionType {
|
|||
CREATE_NEW_FILE,
|
||||
COPY_CODE,
|
||||
REPLACE_IN_MAIN_EDITOR,
|
||||
RELOAD_MESSAGE
|
||||
RELOAD_MESSAGE,
|
||||
CHANGE_PROVIDER
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
package ee.carlrobert.codegpt.completions;
|
||||
|
||||
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
|
||||
import ee.carlrobert.codegpt.conversations.Conversation;
|
||||
import ee.carlrobert.codegpt.conversations.message.Message;
|
||||
import ee.carlrobert.codegpt.settings.state.AzureSettingsState;
|
||||
import ee.carlrobert.codegpt.settings.state.OpenAISettingsState;
|
||||
import ee.carlrobert.codegpt.settings.state.SettingsState;
|
||||
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
|
||||
import ee.carlrobert.llm.client.openai.completion.ErrorDetails;
|
||||
import ee.carlrobert.llm.client.you.completion.YouCompletionEventListener;
|
||||
import ee.carlrobert.llm.client.you.completion.YouSerpResult;
|
||||
|
|
@ -230,11 +230,18 @@ public class CompletionRequestHandler {
|
|||
}
|
||||
|
||||
private void sendError(ErrorDetails error, Throwable ex) {
|
||||
TelemetryAction.COMPLETION_ERROR.createActionMessage()
|
||||
.property("conversationId", conversation.getId().toString())
|
||||
.property("model", conversation.getModel())
|
||||
.error(new RuntimeException(error.toString(), ex))
|
||||
.send();
|
||||
var telemetryMessage = TelemetryAction.COMPLETION_ERROR.createActionMessage();
|
||||
if ("insufficient_quota".equals(error.getCode())) {
|
||||
telemetryMessage
|
||||
.property("type", "USER")
|
||||
.property("code", "INSUFFICIENT_QUOTA");
|
||||
} else {
|
||||
telemetryMessage
|
||||
.property("conversationId", conversation.getId().toString())
|
||||
.property("model", conversation.getModel())
|
||||
.error(new RuntimeException(error.toString(), ex));
|
||||
}
|
||||
telemetryMessage.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import ee.carlrobert.codegpt.credentials.OpenAICredentialsManager;
|
|||
import ee.carlrobert.codegpt.settings.state.AzureSettingsState;
|
||||
import ee.carlrobert.codegpt.settings.state.OpenAISettingsState;
|
||||
import ee.carlrobert.codegpt.settings.state.SettingsState;
|
||||
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.standard.StandardChatToolWindowContentManager;
|
||||
import ee.carlrobert.codegpt.util.ApplicationUtils;
|
||||
import javax.swing.JComponent;
|
||||
|
|
@ -64,7 +65,8 @@ public class SettingsConfigurable implements Configurable, Disposable {
|
|||
|
||||
OpenAICredentialsManager.getInstance().setApiKey(serviceSelectionForm.getOpenAIApiKey());
|
||||
AzureCredentialsManager.getInstance().setApiKey(serviceSelectionForm.getAzureOpenAIApiKey());
|
||||
AzureCredentialsManager.getInstance().setAzureActiveDirectoryToken(serviceSelectionForm.getAzureActiveDirectoryToken());
|
||||
AzureCredentialsManager.getInstance()
|
||||
.setAzureActiveDirectoryToken(serviceSelectionForm.getAzureActiveDirectoryToken());
|
||||
|
||||
settings.setDisplayName(settingsComponent.getDisplayName());
|
||||
settings.setUseOpenAIService(serviceSelectionForm.isOpenAIServiceSelected());
|
||||
|
|
@ -77,6 +79,11 @@ public class SettingsConfigurable implements Configurable, Disposable {
|
|||
|
||||
if (serviceChanged || modelChanged) {
|
||||
resetActiveTab();
|
||||
if (serviceChanged) {
|
||||
TelemetryAction.SETTINGS_CHANGED.createActionMessage()
|
||||
.property("service", getServiceCode(serviceSelectionForm))
|
||||
.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +116,9 @@ public class SettingsConfigurable implements Configurable, Disposable {
|
|||
public void dispose() {
|
||||
}
|
||||
|
||||
private boolean isServiceChanged(ServiceSelectionForm serviceSelectionForm, SettingsState settings) {
|
||||
private boolean isServiceChanged(
|
||||
ServiceSelectionForm serviceSelectionForm,
|
||||
SettingsState settings) {
|
||||
return serviceSelectionForm.isOpenAIServiceSelected() != settings.isUseOpenAIService() ||
|
||||
serviceSelectionForm.isAzureServiceSelected() != settings.isUseAzureService() ||
|
||||
serviceSelectionForm.isYouServiceSelected() != settings.isUseYouService();
|
||||
|
|
@ -124,4 +133,17 @@ public class SettingsConfigurable implements Configurable, Disposable {
|
|||
|
||||
project.getService(StandardChatToolWindowContentManager.class).resetActiveTab();
|
||||
}
|
||||
|
||||
private String getServiceCode(ServiceSelectionForm serviceSelectionForm) {
|
||||
if (serviceSelectionForm.isOpenAIServiceSelected()) {
|
||||
return "openai";
|
||||
}
|
||||
if (serviceSelectionForm.isAzureServiceSelected()) {
|
||||
return "azure";
|
||||
}
|
||||
if (serviceSelectionForm.isYouServiceSelected()) {
|
||||
return "you";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -200,9 +200,16 @@ public abstract class BaseChatToolWindowTabPanel implements ChatToolWindowTabPan
|
|||
}
|
||||
}));
|
||||
requestHandler.addErrorListener((error, ex) -> {
|
||||
responsePanel.enableActions();
|
||||
responseContainer.displayError(error.getMessage());
|
||||
stopStreaming(responseContainer);
|
||||
try {
|
||||
if ("insufficient_quota".equals(error.getCode())) {
|
||||
responseContainer.displayQuotaExceeded();
|
||||
} else {
|
||||
responseContainer.displayError(error.getMessage());
|
||||
}
|
||||
} finally {
|
||||
responsePanel.enableActions();
|
||||
stopStreaming(responseContainer);
|
||||
}
|
||||
});
|
||||
requestHandler.addSerpResultsListener(
|
||||
serpResults -> serpResultsMapping.put(message.getId(), serpResults.stream()
|
||||
|
|
|
|||
|
|
@ -19,9 +19,11 @@ import com.vladsch.flexmark.ast.FencedCodeBlock;
|
|||
import com.vladsch.flexmark.html.HtmlRenderer;
|
||||
import com.vladsch.flexmark.parser.Parser;
|
||||
import com.vladsch.flexmark.util.data.MutableDataSet;
|
||||
import ee.carlrobert.codegpt.actions.ActionType;
|
||||
import ee.carlrobert.codegpt.completions.SerpResult;
|
||||
import ee.carlrobert.codegpt.settings.SettingsConfigurable;
|
||||
import ee.carlrobert.codegpt.settings.state.SettingsState;
|
||||
import ee.carlrobert.codegpt.telemetry.TelemetryAction;
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.editor.ChatToolWindowTabPanelEditor;
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.ResponseNodeRenderer;
|
||||
import ee.carlrobert.codegpt.toolwindow.chat.StreamParser;
|
||||
|
|
@ -52,11 +54,18 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
this(project, getPanelBackgroundColor(), false, parentDisposable);
|
||||
}
|
||||
|
||||
public ChatMessageResponseBody(Project project, boolean withGhostText, Disposable parentDisposable) {
|
||||
public ChatMessageResponseBody(
|
||||
Project project,
|
||||
boolean withGhostText,
|
||||
Disposable parentDisposable) {
|
||||
this(project, getPanelBackgroundColor(), withGhostText, parentDisposable);
|
||||
}
|
||||
|
||||
public ChatMessageResponseBody(Project project, Color backgroundColor, boolean withGhostText, Disposable parentDisposable) {
|
||||
public ChatMessageResponseBody(
|
||||
Project project,
|
||||
Color backgroundColor,
|
||||
boolean withGhostText,
|
||||
Disposable parentDisposable) {
|
||||
super(new BorderLayout());
|
||||
this.project = project;
|
||||
this.parentDisposable = parentDisposable;
|
||||
|
|
@ -66,7 +75,8 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
|
||||
if (withGhostText) {
|
||||
prepareProcessingTextResponse();
|
||||
currentlyProcessedTextPane.setText("<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">‍</p></html>");
|
||||
currentlyProcessedTextPane.setText(
|
||||
"<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">‍</p></html>");
|
||||
}
|
||||
|
||||
UIManager.addPropertyChangeListener(propertyChangeEvent -> setBackground(backgroundColor));
|
||||
|
|
@ -95,7 +105,8 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
var message = SettingsState.getInstance().isUseYouService() ?
|
||||
"Please <a href=\"#\">log in</a> to access the chat feature." :
|
||||
"API key not provided. Open <a href=\"#\">Settings</a> to set one.";
|
||||
currentlyProcessedTextPane.setText(String.format("<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">%s</p></html>", message));
|
||||
currentlyProcessedTextPane.setText(
|
||||
format("<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">%s</p></html>", message));
|
||||
currentlyProcessedTextPane.addHyperlinkListener(e -> {
|
||||
if (e.getEventType() == ACTIVATED) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(project, SettingsConfigurable.class);
|
||||
|
|
@ -104,6 +115,23 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
currentlyProcessedTextPane.getCaret().setVisible(false);
|
||||
}
|
||||
|
||||
public void displayQuotaExceeded() {
|
||||
currentlyProcessedTextPane.setText("<html>"
|
||||
+ "<p style=\"margin-top: 4px; margin-bottom: 8px;\">"
|
||||
+ "You exceeded your current quota, please check your plan and billing details, "
|
||||
+ "or <a href=\"#CHANGE_PROVIDER\">change</a> to a different LLM provider.</p>"
|
||||
+ "</html>");
|
||||
currentlyProcessedTextPane.addHyperlinkListener(e -> {
|
||||
if (e.getEventType() == ACTIVATED) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(project, SettingsConfigurable.class);
|
||||
TelemetryAction.IDE_ACTION.createActionMessage()
|
||||
.property("action", ActionType.CHANGE_PROVIDER.name())
|
||||
.send();
|
||||
}
|
||||
});
|
||||
currentlyProcessedTextPane.getCaret().setVisible(false);
|
||||
}
|
||||
|
||||
public void hideCarets() {
|
||||
if (currentlyProcessedEditor != null) {
|
||||
((EditorEx) currentlyProcessedEditor.getEditor()).setCaretVisible(false);
|
||||
|
|
@ -115,7 +143,9 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
}
|
||||
|
||||
public void displayError(String message) {
|
||||
var errorText = format("<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">%s</p></html>", message);
|
||||
var errorText = format(
|
||||
"<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">%s</p></html>",
|
||||
message);
|
||||
if (responseReceived) {
|
||||
var errorPane = createTextPane();
|
||||
errorPane.setText(errorText);
|
||||
|
|
@ -131,7 +161,8 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
|
||||
public void displaySerpResults(List<SerpResult> serpResults) {
|
||||
var titles = serpResults.stream()
|
||||
.map(result -> format("<li style=\"margin-bottom: 4px;\"><a href=\"%s\">%s</a></li>", result.getUrl(), result.getName()))
|
||||
.map(result -> format("<li style=\"margin-bottom: 4px;\"><a href=\"%s\">%s</a></li>",
|
||||
result.getUrl(), result.getName()))
|
||||
.collect(Collectors.joining());
|
||||
var html = format(
|
||||
"<html>" +
|
||||
|
|
@ -153,7 +184,8 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
streamParser.clear();
|
||||
// TODO: First message might be code block
|
||||
prepareProcessingTextResponse();
|
||||
currentlyProcessedTextPane.setText("<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">‍</p></html>");
|
||||
currentlyProcessedTextPane.setText(
|
||||
"<html><p style=\"margin-top: 4px; margin-bottom: 8px;\">‍</p></html>");
|
||||
|
||||
repaint();
|
||||
revalidate();
|
||||
|
|
@ -203,7 +235,11 @@ public class ChatMessageResponseBody extends JPanel {
|
|||
private void prepareProcessingCodeResponse(String code, String language) {
|
||||
hideCarets();
|
||||
currentlyProcessedTextPane = null;
|
||||
currentlyProcessedEditor = new ChatToolWindowTabPanelEditor(project, code, language, parentDisposable);
|
||||
currentlyProcessedEditor = new ChatToolWindowTabPanelEditor(
|
||||
project,
|
||||
code,
|
||||
language,
|
||||
parentDisposable);
|
||||
currentlyProcessedElement = new ResponseWrapper();
|
||||
|
||||
currentlyProcessedElement.add(currentlyProcessedEditor.getComponent());
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue