chatbot enhancements

This commit is contained in:
Bane Stojkovic
2025-04-05 17:08:38 +02:00
parent a5cc9c1374
commit 52b4f487b5
5 changed files with 121 additions and 30 deletions
+11
View File
@@ -20,4 +20,15 @@
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
</natures>
<filteredResources>
<filter>
<id>1743865242662</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>
@@ -23,6 +23,7 @@ package org.diylc.plugins.chatbot.model;
import com.diyfever.httpproxy.ParamName;
import java.io.File;
import java.util.List;
public interface IChatbotAPI {
@@ -40,7 +41,7 @@ public interface IChatbotAPI {
*/
String promptChatbot(@ParamName("username") String username, @ParamName("token") String token,
@ParamName("machineId") String machineId, @ParamName("project") String project,
@ParamName("netlist") String netlist, @ParamName("prompt") String prompt);
@ParamName("netlist") File netlist, @ParamName("prompt") String prompt);
SubscriptionEntity getSubscriptionInfo(@ParamName("username") String username, @ParamName("token") String token,
@ParamName("machineId") String machineId);
@@ -30,6 +30,7 @@ import org.diylc.common.ComponentType;
import org.diylc.common.IPlugInPort;
import org.diylc.common.PropertyWrapper;
import org.diylc.core.IDIYComponent;
import org.diylc.core.ISwitch;
import org.diylc.netlist.Group;
import org.diylc.netlist.Netlist;
import org.diylc.netlist.NetlistException;
@@ -43,6 +44,9 @@ import org.diylc.presenter.ComponentProcessor;
import org.diylc.utils.FileUtils;
import java.awt.*;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
@@ -89,17 +93,36 @@ public class ChatbotService {
String fileName = extractFileName(currentFile);
String netlist;
File netlistFile = null;
try {
netlist = extractNetlists();
} catch (NetlistException e) {
LOG.error("Error extracting netlist", e);
if (netlist != null) {
netlistFile = File.createTempFile("diylc_netlist_", ".txt");
try (FileWriter writer = new FileWriter(netlistFile)) {
writer.write(netlist);
}
// Make sure the temp file is deleted when the JVM exits
netlistFile.deleteOnExit();
}
} catch (NetlistException | IOException e) {
LOG.error("Error extracting or saving netlist", e);
netlist = null;
}
return getService().promptChatbot(
plugInPort.getCloudService().getCurrentUsername(),
plugInPort.getCloudService().getCurrentToken(),
plugInPort.getCloudService().getMachineId(), fileName, netlist, prompt);
try {
return getService().promptChatbot(
plugInPort.getCloudService().getCurrentUsername(),
plugInPort.getCloudService().getCurrentToken(),
plugInPort.getCloudService().getMachineId(),
fileName,
netlistFile,
prompt);
} finally {
// Clean up the temp file immediately after use
if (netlistFile != null && netlistFile.exists()) {
netlistFile.delete();
}
}
}
private static final Set<Class<?>> PROPERTY_TYPES_TO_SKIP = Set.of(Font.class, Color.class);
@@ -108,12 +131,11 @@ public class ChatbotService {
private String extractNetlists() throws NetlistException {
List<Netlist> netlists = plugInPort.extractNetlists(true);
if (netlists == null) {
if (netlists == null || netlists.isEmpty()) {
return null;
}
StringBuilder sb = new StringBuilder();
sb.append("Components: ");
Set<? extends IDIYComponent<?>> components = netlists.stream()
.flatMap(n -> n.getGroups().stream()
@@ -121,8 +143,45 @@ public class ChatbotService {
map(Node::getComponent)))
.collect(Collectors.toSet());
if (!components.isEmpty()) {
sb.append(
"Components (each element of the JSON array represents one component with all the relevant properties): ");
outputComponents(components, sb);
}
Set<? extends IDIYComponent<?>> switches = plugInPort.getCurrentProject().getComponents()
.stream().filter(x -> x instanceof ISwitch)
.collect(Collectors.toSet());;
if (!switches.isEmpty()) {
sb.append(
"Switches (each element of the JSON array represents one switch with all the relevant properties): ");
outputComponents(switches, sb);
}
for (Netlist netlist : netlists) {
sb.append("\n");
if (!netlist.getSwitchSetup().isEmpty()) {
sb.append("Switch configuration: ").append(netlist.getSwitchSetup()).append(". ");
}
sb.append("Each line below represents one JSON array that lists all the nodes that are connected together. Nodes are labeled as (component name).(node name):\n\n");
for (Group v : netlist.getSortedGroups()) {
// sb.append(v.getSortedNodes()).append("\n");
List<String> nodeList = v.getSortedNodes().stream().map(x -> x.getComponent().getName() + "." + x.getDisplayName()).toList();
try {
String json = MAPPER.writeValueAsString(nodeList);
sb.append(json).append("\n");
} catch (Exception e) {
LOG.error("Failed to serialize component descriptors to JSON", e);
}
}
}
return sb.toString();
}
private static void outputComponents(Set<? extends IDIYComponent<?>> components, StringBuilder sb) {
List<Map<String, Object>> componentDescriptors = new ArrayList<>();
components.forEach(c -> {
ComponentType componentType = ComponentProcessor.getInstance()
.extractComponentTypeFrom((Class<? extends IDIYComponent<?>>) c.getClass());
@@ -148,7 +207,7 @@ public class ChatbotService {
LOG.warn("Error extracting properties", e);
}
});
componentDescriptors.add(componentDescriptorMap);
});
@@ -158,15 +217,6 @@ public class ChatbotService {
} catch (Exception e) {
LOG.error("Failed to serialize component descriptors to JSON", e);
}
for (Netlist netlist : netlists) {
sb.append("Switch configuration: ").append(netlist.getSwitchSetup()).append("\n\n")
.append("Connected node groups:\n\n");
for (Group v : netlist.getSortedGroups()) {
sb.append(v.getSortedNodes()).append("\n");
}
}
return sb.toString();
}
public SubscriptionEntity getSubscriptionInfo() throws NotLoggedInException {
@@ -21,7 +21,9 @@ public class ChatbotPane extends JPanel {
private static final long serialVersionUID = 1L;
private static final Logger LOG = Logger.getLogger(ChatbotPane.class);
public static final String ME = "Me: ";
public static final String AI_ASSISTANT = "AI Assistant: ";
public static Font DEFAULT_FONT = new Font("Square721 BT", Font.PLAIN, 12);
private static final Font MONOSPACED_FONT = new Font("Monospaced", Font.PLAIN, 12);
private static final Color TERMINAL_BG = new Color(40, 40, 40);
@@ -45,7 +47,7 @@ public class ChatbotPane extends JPanel {
private JButton clearButton;
private boolean loggedIn = false;
private String projectFileName = "initial";
private String projectFileName = null;
public ChatbotPane(ISwingUI swingUI, IPlugInPort plugInPort) {
super();
@@ -221,8 +223,8 @@ public class ChatbotPane extends JPanel {
try {
SubscriptionEntity subscriptionInfo = plugInPort.getChatbotService().getSubscriptionInfo();
appendSection(ChatbotService.SYSTEM,
"Your current subscription tier is " + subscriptionInfo.getTier() +
" expiring on " + subscriptionInfo.getEndDate() + " with " +
"Your are currently subscribed to the '" + subscriptionInfo.getTier() +
"' tier, expiring on " + subscriptionInfo.getEndDate() + ", with " +
subscriptionInfo.getRemainingCredits() + " credits remaining.");
} catch (NotLoggedInException e) {
LOG.error("Error getting subscription info", e);
@@ -238,8 +240,8 @@ public class ChatbotPane extends JPanel {
try {
List<ChatMessageEntity> chatHistory = plugInPort.getChatbotService().getChatHistory();
chatHistory.forEach(message -> {
appendSection(ChatbotService.USER, message.getPrompt());
appendSection(ChatbotService.ASSISTANT, message.getResponse());
appendSection(ChatbotService.USER, ME + message.getPrompt());
appendSection(ChatbotService.ASSISTANT, AI_ASSISTANT + message.getResponse());
});
} catch (NotLoggedInException e) {
appendSection(ChatbotService.SYSTEM, "Failed to retrieve chat history.");
@@ -257,6 +259,8 @@ public class ChatbotPane extends JPanel {
chatEditorPane.setContentType("text/html");
chatEditorPane.setText(HTML_STYLE + "<body></body>");
refreshChat();
}
return chatEditorPane;
}
@@ -296,7 +300,7 @@ public class ChatbotPane extends JPanel {
askButton.setBorderPainted(true);
askButton.addActionListener(e -> {
final String prompt = getPromptArea().getText();
appendSection(ChatbotService.USER, prompt);
appendSection(ChatbotService.USER, ME + prompt);
appendSection(ChatbotService.TEMPORARY, "Waiting for the response...");
getPromptArea().setText(null);
@@ -319,7 +323,7 @@ public class ChatbotPane extends JPanel {
@Override
public void complete(String result) {
appendSection(ChatbotService.ASSISTANT, result);
appendSection(ChatbotService.ASSISTANT, AI_ASSISTANT + result);
getClearButton().setEnabled(true);
}
}, false);
@@ -328,7 +332,7 @@ public class ChatbotPane extends JPanel {
return askButton;
}
void appendSection(String style, String insertText) {
private void appendSection(String style, String insertText) {
String text = getChatEditorPane().getText();
// remove any temporary divs
String regex = "(?s)<div\\s+class=[\"']temporary[\"'][^>]*>.*?</div>\\s*<br>\\s*";