-
Notifications
You must be signed in to change notification settings - Fork 38
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #409 from samkerr4coding/fix/issue-243
fix(issue-243): Fix UI chatresponsemodel
- Loading branch information
Showing
7 changed files
with
176 additions
and
163 deletions.
There are no files selected for viewing
42 changes: 13 additions & 29 deletions
42
src/main/java/com/devoxx/genie/ui/panel/ChatResponsePanel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,30 @@ | ||
package com.devoxx.genie.ui.panel; | ||
|
||
import com.devoxx.genie.model.request.ChatMessageContext; | ||
import com.devoxx.genie.service.FileListManager; | ||
import com.devoxx.genie.ui.panel.chatresponse.*; | ||
import com.devoxx.genie.ui.settings.DevoxxGenieStateService; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import javax.swing.*; | ||
import java.awt.*; | ||
|
||
public class ChatResponsePanel extends BackgroundPanel { | ||
|
||
private final transient ChatMessageContext chatMessageContext; | ||
|
||
public ChatResponsePanel(@NotNull ChatMessageContext chatMessageContext) { | ||
super(chatMessageContext.getId()); | ||
this.chatMessageContext = chatMessageContext; | ||
setLayout(new GridBagLayout()); | ||
buildResponsePanel(); | ||
} | ||
|
||
private void buildResponsePanel() { | ||
GridBagConstraints gbc = new GridBagConstraints(); | ||
gbc.gridx = 0; | ||
gbc.gridy = 0; | ||
gbc.weightx = 1; // full width components | ||
gbc.fill = GridBagConstraints.HORIZONTAL; // Fill horizontally | ||
gbc.anchor = GridBagConstraints.WEST; // Anchor to the west (left) | ||
|
||
add(new ResponseHeaderPanel(chatMessageContext), gbc); | ||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); | ||
|
||
gbc.gridy++; | ||
add(new ResponseContentPanel(chatMessageContext), gbc); | ||
add(new ResponseHeaderPanel(chatMessageContext)); | ||
add(new ResponseDocumentPanel(chatMessageContext)); | ||
|
||
gbc.gridy++; | ||
add(new FileListPanel(chatMessageContext, FileListManager.getInstance().getFiles()), gbc); | ||
if (chatMessageContext.hasFiles()) { | ||
add(new FileListPanel(chatMessageContext)); | ||
} | ||
|
||
gbc.gridy++; | ||
add(new SemanticSearchReferencesPanel(chatMessageContext, chatMessageContext.getSemanticReferences()), gbc); | ||
if (chatMessageContext.getSemanticReferences() != null && !chatMessageContext.getSemanticReferences().isEmpty()) { | ||
add(new SemanticSearchReferencesPanel(chatMessageContext)); | ||
} | ||
|
||
gbc.gridy++; | ||
JPanel metricPanelWrapper = new JPanel(new FlowLayout(FlowLayout.LEFT)); | ||
metricPanelWrapper.add(new MetricExecutionInfoPanel(chatMessageContext)); | ||
add(metricPanelWrapper, gbc); | ||
if (Boolean.TRUE.equals(DevoxxGenieStateService.getInstance().getShowExecutionTime())) { | ||
add(new MetricExecutionInfoPanel(chatMessageContext)); | ||
} | ||
} | ||
} |
15 changes: 4 additions & 11 deletions
15
src/main/java/com/devoxx/genie/ui/panel/chatresponse/FileListPanel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,12 @@ | ||
package com.devoxx.genie.ui.panel.chatresponse; | ||
|
||
import com.devoxx.genie.model.request.ChatMessageContext; | ||
import com.devoxx.genie.service.FileListManager; | ||
import com.devoxx.genie.ui.component.ExpandablePanel; | ||
import com.intellij.openapi.vfs.VirtualFile; | ||
|
||
import javax.swing.*; | ||
import java.util.List; | ||
public class FileListPanel extends ExpandablePanel { | ||
|
||
// FileListPanel.java | ||
public class FileListPanel extends JPanel { | ||
public FileListPanel(ChatMessageContext chatMessageContext, List<VirtualFile> files) { | ||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); | ||
setOpaque(false); | ||
if (chatMessageContext.hasFiles()) { | ||
add(new ExpandablePanel(chatMessageContext, files)); | ||
} | ||
public FileListPanel(ChatMessageContext chatMessageContext) { | ||
super(chatMessageContext, FileListManager.getInstance().getFiles()); | ||
} | ||
} |
67 changes: 30 additions & 37 deletions
67
src/main/java/com/devoxx/genie/ui/panel/chatresponse/MetricExecutionInfoPanel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,65 +1,58 @@ | ||
package com.devoxx.genie.ui.panel.chatresponse; | ||
|
||
import com.devoxx.genie.model.enumarations.ModelProvider; | ||
import com.devoxx.genie.model.request.ChatMessageContext; | ||
import com.devoxx.genie.ui.settings.DevoxxGenieStateService; | ||
import com.devoxx.genie.service.ProjectContentService; | ||
import com.devoxx.genie.util.DefaultLLMSettingsUtil; | ||
import com.intellij.ui.JBColor; | ||
import com.knuddels.jtokkit.api.Encoding; | ||
import dev.langchain4j.model.output.TokenUsage; | ||
|
||
import javax.swing.*; | ||
import java.awt.*; | ||
import java.text.NumberFormat; | ||
import java.util.Locale; | ||
|
||
// MetricExecutionInfoPanel.java | ||
public class MetricExecutionInfoPanel extends JPanel { | ||
|
||
private static final float METRIC_FONT_SIZE = 12f; | ||
private static final double MS_TO_SECONDS = 1000.0; | ||
|
||
public MetricExecutionInfoPanel(ChatMessageContext chatMessageContext) { | ||
setLayout(new FlowLayout(FlowLayout.LEFT)); | ||
setOpaque(false); | ||
|
||
if (shouldShowExecutionTime(chatMessageContext)) { | ||
add(createMetricLabel(chatMessageContext)); | ||
} | ||
} | ||
String metricInfoLabel = String.format("ϟ %.2fs", chatMessageContext.getExecutionTimeMs() / 1000.0); | ||
TokenUsage tokenUsage = chatMessageContext.getTokenUsage(); | ||
|
||
private boolean shouldShowExecutionTime(ChatMessageContext chatMessageContext) { | ||
return Boolean.TRUE.equals(DevoxxGenieStateService.getInstance().getShowExecutionTime()); | ||
} | ||
if (tokenUsage != null) { | ||
String cost = ""; | ||
if (DefaultLLMSettingsUtil.isApiKeyBasedProvider(chatMessageContext.getLanguageModel().getProvider())) { | ||
cost = String.format("- %.5f $", chatMessageContext.getCost()); | ||
} | ||
|
||
private JLabel createMetricLabel(ChatMessageContext chatMessageContext) { | ||
String metricInfo = buildMetricInfo(chatMessageContext); | ||
JLabel label = new JLabel(metricInfo); | ||
label.setForeground(JBColor.GRAY); | ||
label.setFont(label.getFont().deriveFont(METRIC_FONT_SIZE)); | ||
return label; | ||
} | ||
tokenUsage = calcOllamaInputTokenCount(chatMessageContext, tokenUsage); | ||
|
||
private String buildMetricInfo(ChatMessageContext chatMessageContext) { | ||
String metricInfoLabel = String.format("ϟ %.2fs", chatMessageContext.getExecutionTimeMs() / MS_TO_SECONDS); | ||
TokenUsage tokenUsage = chatMessageContext.getTokenUsage(); | ||
if (tokenUsage != null) { | ||
metricInfoLabel = buildTokenUsageLabel(tokenUsage, metricInfoLabel, chatMessageContext); | ||
} | ||
return metricInfoLabel; | ||
} | ||
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.getDefault()); | ||
String formattedInputTokens = numberFormat.format(tokenUsage.inputTokenCount()); | ||
String formattedOutputTokens = numberFormat.format(tokenUsage.outputTokenCount()); | ||
|
||
private String buildTokenUsageLabel(TokenUsage tokenUsage, String metricInfoLabel, ChatMessageContext chatMessageContext) { | ||
String cost = ""; | ||
if (DefaultLLMSettingsUtil.isApiKeyBasedProvider(chatMessageContext.getLanguageModel().getProvider())) { | ||
cost = String.format("- %.5f $", chatMessageContext.getCost()); | ||
metricInfoLabel += String.format(" - Tokens ↑ %s ↓️ %s %s", formattedInputTokens, formattedOutputTokens, cost); | ||
} | ||
|
||
// ... (Implementation for calculating token usage, you can move the relevant code here) | ||
|
||
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.getDefault()); | ||
String formattedInputTokens = numberFormat.format(tokenUsage.inputTokenCount()); | ||
String formattedOutputTokens = numberFormat.format(tokenUsage.outputTokenCount()); | ||
JLabel tokenLabel = new JLabel(metricInfoLabel); | ||
tokenLabel.setForeground(JBColor.GRAY); | ||
tokenLabel.setFont(tokenLabel.getFont().deriveFont(12f)); | ||
add(tokenLabel); | ||
} | ||
|
||
metricInfoLabel += String.format(" - Tokens ↑ %s ↓️ %s %s", formattedInputTokens, formattedOutputTokens, cost); | ||
return metricInfoLabel; | ||
private static TokenUsage calcOllamaInputTokenCount(ChatMessageContext chatMessageContext, TokenUsage tokenUsage) { | ||
if (chatMessageContext.getLanguageModel().getProvider().equals(ModelProvider.Ollama)) { | ||
int inputContextTokens = 0; | ||
if (chatMessageContext.getContext() != null) { | ||
Encoding encodingForProvider = ProjectContentService.getEncodingForProvider(chatMessageContext.getLanguageModel().getProvider()); | ||
inputContextTokens = encodingForProvider.encode(chatMessageContext.getContext()).size(); | ||
} | ||
tokenUsage = new TokenUsage(tokenUsage.inputTokenCount() + inputContextTokens, tokenUsage.outputTokenCount()); | ||
} | ||
return tokenUsage; | ||
} | ||
} |
71 changes: 0 additions & 71 deletions
71
src/main/java/com/devoxx/genie/ui/panel/chatresponse/ResponseContentPanel.java
This file was deleted.
Oops, something went wrong.
124 changes: 124 additions & 0 deletions
124
src/main/java/com/devoxx/genie/ui/panel/chatresponse/ResponseDocumentPanel.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package com.devoxx.genie.ui.panel.chatresponse; | ||
|
||
import com.devoxx.genie.model.request.ChatMessageContext; | ||
import com.devoxx.genie.model.request.EditorInfo; | ||
import com.devoxx.genie.service.gitdiff.GitMergeService; | ||
import com.devoxx.genie.ui.processor.NodeProcessorFactory; | ||
import com.devoxx.genie.ui.settings.DevoxxGenieStateService; | ||
import com.intellij.openapi.vfs.VirtualFile; | ||
import org.commonmark.node.Block; | ||
import org.commonmark.node.FencedCodeBlock; | ||
import org.commonmark.node.IndentedCodeBlock; | ||
import org.commonmark.node.Node; | ||
import org.commonmark.parser.Parser; | ||
import org.jetbrains.annotations.NotNull; | ||
|
||
import javax.swing.*; | ||
import java.awt.*; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class ResponseDocumentPanel extends JPanel { | ||
|
||
|
||
private final transient ChatMessageContext chatMessageContext; | ||
|
||
public ResponseDocumentPanel(@NotNull ChatMessageContext chatMessageContext) { | ||
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); | ||
|
||
this.chatMessageContext = chatMessageContext; | ||
|
||
String markDownResponse = chatMessageContext.getAiMessage().text(); | ||
|
||
System.out.println(markDownResponse); | ||
|
||
Node document = Parser.builder().build().parse(markDownResponse); | ||
|
||
DevoxxGenieStateService stateService = DevoxxGenieStateService.getInstance(); | ||
|
||
if (Boolean.TRUE.equals(stateService.getGitDiffActivated())) { | ||
processGitDiff(chatMessageContext, document); | ||
} | ||
|
||
addDocumentNodesToPanel(document); | ||
} | ||
|
||
private void processGitDiff(@NotNull ChatMessageContext chatMessageContext, @NotNull Node document) { | ||
// Get original file info | ||
EditorInfo editorInfo = chatMessageContext.getEditorInfo(); | ||
if (editorInfo == null) { | ||
return; | ||
} | ||
|
||
if (editorInfo.getSelectedFiles() != null && !editorInfo.getSelectedFiles().isEmpty()) { | ||
List<VirtualFile> files = editorInfo.getSelectedFiles(); | ||
List<String> modifiedContents = new ArrayList<>(); | ||
|
||
// Collect modified contents from code blocks | ||
Node node = document.getFirstChild(); | ||
while (node != null) { | ||
if (node instanceof FencedCodeBlock codeBlock) { | ||
modifiedContents.add(codeBlock.getLiteral()); | ||
} | ||
node = node.getNext(); | ||
} | ||
|
||
GitMergeService.getInstance().showDiffView( | ||
chatMessageContext.getProject(), | ||
files.get(0), | ||
modifiedContents.isEmpty() ? "" : modifiedContents.get(0)); | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Add document nodes to the panel. | ||
* | ||
* @param document the document | ||
*/ | ||
private void addDocumentNodesToPanel(@NotNull Node document) { | ||
JPanel jPanel = createPanel(); | ||
|
||
Node node = document.getFirstChild(); | ||
|
||
while (node != null) { | ||
JPanel panel; | ||
if (node instanceof FencedCodeBlock fencedCodeBlock) { | ||
panel = processBlock(fencedCodeBlock); | ||
} else if (node instanceof IndentedCodeBlock indentedCodeBlock) { | ||
panel = processBlock(indentedCodeBlock); | ||
} else { | ||
panel = processBlock((Block) node); | ||
} | ||
|
||
setFullWidth(panel); | ||
jPanel.add(panel); | ||
node = node.getNext(); | ||
} | ||
|
||
add(jPanel); | ||
} | ||
|
||
private void setFullWidth(@NotNull JPanel panel) { | ||
Dimension maximumSize = new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE); | ||
panel.setMaximumSize(maximumSize); | ||
panel.setMinimumSize(new Dimension(panel.getPreferredSize().width, panel.getPreferredSize().height)); | ||
} | ||
|
||
private @NotNull JPanel createPanel() { | ||
JPanel jPanel = new JPanel(); | ||
jPanel.setLayout(new BoxLayout(jPanel, BoxLayout.Y_AXIS)); | ||
jPanel.setOpaque(false); | ||
return jPanel; | ||
} | ||
|
||
/** | ||
* Process a block and return a panel. | ||
* | ||
* @param theBlock the block | ||
* @return the panel | ||
*/ | ||
private JPanel processBlock(Block theBlock) { | ||
return NodeProcessorFactory.createProcessor(chatMessageContext, theBlock).processNode(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.