mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-10 09:12:09 +10:00
chatbot enhancements
This commit is contained in:
@@ -5,9 +5,18 @@ import static org.mockito.Mockito.*;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import org.diylc.common.ComponentType;
|
||||
import org.diylc.common.IComponentTransformer;
|
||||
import org.diylc.common.PropertyWrapper;
|
||||
|
||||
@@ -112,6 +112,12 @@
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
<version>1.7.36</version>
|
||||
</dependency>
|
||||
<!-- Jackson for JSON processing -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.16.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.oracle</groupId>
|
||||
<artifactId>appbundler</artifactId>
|
||||
|
||||
@@ -3,18 +3,13 @@ package org.diylc.swing.plugins.chatbot;
|
||||
import org.apache.log4j.Logger;
|
||||
import org.diylc.common.IPlugInPort;
|
||||
import org.diylc.common.ITask;
|
||||
import org.diylc.core.IView;
|
||||
import org.diylc.plugins.chatbot.presenter.ChatbotPresenter;
|
||||
import org.diylc.plugins.cloud.presenter.CloudPresenter;
|
||||
import org.diylc.plugins.cloud.presenter.NotLoggedInException;
|
||||
import org.diylc.swing.ISwingUI;
|
||||
import org.diylc.swing.plugins.config.ConfigPlugin;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.Random;
|
||||
|
||||
public class ChatbotPane extends JPanel {
|
||||
|
||||
@@ -22,6 +17,93 @@ public class ChatbotPane extends JPanel {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(ChatbotPane.class);
|
||||
|
||||
public static final String ASSISTANT = "assistant";
|
||||
public static final String SYSTEM = "system";
|
||||
public static final String USER = "user";
|
||||
public static final String TEMPORARY = "temporary";
|
||||
|
||||
String[] electronicsQuestions = {
|
||||
"What is Ohm's Law, and how do voltage, current, and resistance relate to each other?",
|
||||
"Why are resistors important in circuits, and what happens if the resistor value is incorrect?",
|
||||
"What is a capacitor, and how does it behave differently from a resistor?",
|
||||
"How does an inductor work, and where might you find one in common DIY projects?",
|
||||
"What's the difference between AC (Alternating Current) and DC (Direct Current), and where is each used?",
|
||||
"How do diodes work, and why are they essential in electronics?",
|
||||
"What's the difference between series and parallel circuits, and why does it matter?",
|
||||
"How does a transistor function, and what role does it typically play in a circuit?",
|
||||
"Why is grounding important in electronic circuits, and what exactly does it do?",
|
||||
"What is impedance, and why is it important when connecting speakers or audio equipment?",
|
||||
"What exactly is an operational amplifier (op amp), and what are its common uses in audio circuits?",
|
||||
"How does a relay work, and when would you choose a relay over a transistor or MOSFET?",
|
||||
"What's the purpose of using a fuse or circuit breaker in a DIY electronics project?",
|
||||
"Why do certain electronic components need specific voltage ratings?",
|
||||
"What is electromagnetic interference (EMI), and how can you minimize it in your projects?",
|
||||
"What does polarity mean for components like electrolytic capacitors and diodes, and why is it important?",
|
||||
"How does filtering work to remove unwanted noise from audio signals or power supplies?",
|
||||
"What is signal clipping in audio circuits, and how can you prevent it?",
|
||||
"Why do some circuits require a heatsink, and how do heatsinks help protect components?",
|
||||
"What is frequency response, and why is it crucial for audio circuits like guitar pedals and amplifiers?",
|
||||
"How do you calculate the correct resistor value for limiting current to an LED?",
|
||||
"What is the role of a voltage regulator, and how does it keep voltage stable?",
|
||||
"How can you measure and verify voltage and current safely using a multimeter?",
|
||||
"What does it mean when a circuit is described as having a 'high input impedance' or 'low output impedance,' and why does it matter?",
|
||||
"How can you determine if components in your circuit are properly rated for the voltage and current they're experiencing?"
|
||||
};
|
||||
|
||||
String[] diylcQuestions = {
|
||||
"How do I add a component to my layout in DIYLC?",
|
||||
"How can I quickly find a specific component in DIYLC?s component toolbox?",
|
||||
"How do I move or reposition components on the canvas in DIYLC?",
|
||||
"How do I edit or change a component?s properties (e.g. value or color) in DIYLC?",
|
||||
"Is there a shortcut to duplicate or repeat the last component I placed in DIYLC?",
|
||||
"How can I group multiple components so I can move or edit them together in DIYLC?",
|
||||
"What are ?building blocks? in DIYLC and how do I create or use them?",
|
||||
"How do I save my DIYLC project and reopen it later on?",
|
||||
"How do I export my DIYLC layout as an image or PDF file?",
|
||||
"Can DIYLC generate a bill of materials (BOM) for my project, and how would I do that?",
|
||||
"How can I change or hide different layers in a DIYLC project to manage overlapping components?",
|
||||
"Is it possible to view the underside of a board in DIYLC, and how can I enable that?",
|
||||
"What does the ?Highlight Connected Areas? feature do in DIYLC and how do I use it for debugging?",
|
||||
"How can I analyze a guitar wiring diagram using DIYLC?s built-in tools?",
|
||||
"How do I assign a custom keyboard shortcut to a component in DIYLC for quick access?",
|
||||
"What are component variants in DIYLC and how can I create and apply them?",
|
||||
"What is the continuous creation mode in DIYLC and how does it help when adding many components?",
|
||||
"How can I create a custom component to add to DIYLC?s component library?",
|
||||
"Does DIYLC support plug-ins, and how can I add new functionality to the app with them?",
|
||||
"What is the DIYLC cloud feature and how can I share or download projects using it?"
|
||||
};
|
||||
|
||||
String[] circuitQuestions = {
|
||||
"What's the purpose of this specific resistor in my circuit?",
|
||||
"How do I correctly determine capacitor values for my power supply?",
|
||||
"How should I route wiring to reduce interference and noise?",
|
||||
"Which component should I choose for this switching application, a MOSFET or BJT?",
|
||||
"How do I verify if my ground connections are optimal?",
|
||||
"Why might this transistor get hot during operation?",
|
||||
"What's the best approach to simplify this section of my circuit?",
|
||||
"How can I ensure my circuit is safe against short circuits?",
|
||||
"What could be causing voltage instability in this circuit?",
|
||||
"How do I properly size resistors to protect LEDs?",
|
||||
"What are the steps to debug unexpected oscillations in my circuit?",
|
||||
"Should I add a bypass capacitor here, and what value should I use?",
|
||||
"How can I check if my components are operating within their rated specifications?",
|
||||
"Is this the right way to connect multiple power rails in my design?",
|
||||
"How can I test my circuit before physically assembling it?",
|
||||
"What are good layout practices to minimize electromagnetic interference?",
|
||||
"How do I identify if my circuit has any redundant or unnecessary components?",
|
||||
"Why might the voltage regulator not output the expected voltage?",
|
||||
"What's the recommended method for isolating digital and analog grounds?",
|
||||
"How do I safely integrate high-voltage components into my DIY circuit?",
|
||||
"Why isn't my LED lighting up when powered?",
|
||||
"How do I troubleshoot a circuit that's drawing more current than expected?",
|
||||
"Why does my amplifier circuit produce a humming or buzzing sound?",
|
||||
"How can I detect and fix intermittent connections in my circuit?",
|
||||
"What should I check if my circuit isn't responding to input signals as expected?",
|
||||
"How do I determine if my soldering joints are causing reliability issues?",
|
||||
"What steps can I take if my microcontroller circuit isn't functioning as intended?",
|
||||
"How do I troubleshoot a noisy or unstable sensor reading?"
|
||||
};
|
||||
|
||||
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);
|
||||
@@ -129,6 +211,19 @@ public class ChatbotPane extends JPanel {
|
||||
promptArea.setForeground(TERMINAL_FG);
|
||||
promptArea.setCaretColor(TERMINAL_FG);
|
||||
|
||||
// Add Enter key handling
|
||||
promptArea.addKeyListener(new java.awt.event.KeyAdapter() {
|
||||
@Override
|
||||
public void keyPressed(java.awt.event.KeyEvent e) {
|
||||
if (e.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER && !e.isShiftDown()) {
|
||||
e.consume(); // Prevent the newline from being added
|
||||
if (getAskButton().isEnabled()) {
|
||||
getAskButton().doClick();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Calculate height based on font metrics
|
||||
int lineHeight = promptArea.getFontMetrics(promptArea.getFont()).getHeight();
|
||||
int desiredHeight = lineHeight * 3 + 10; // 3 lines + padding
|
||||
@@ -207,33 +302,36 @@ public class ChatbotPane extends JPanel {
|
||||
".user { color: #98C379; }" + // Softer green that's easier on the eyes
|
||||
".assistant { color: #61AFEF; }" + // Lighter, more vibrant blue
|
||||
".system { color: #E5C07B; }" + // Warmer, muted yellow
|
||||
".temporary { color: #555555; }" +
|
||||
"</style>",
|
||||
MONOSPACED_FONT.getFamily(),
|
||||
MONOSPACED_FONT.getSize(),
|
||||
TERMINAL_FG.getRed(), TERMINAL_FG.getGreen(), TERMINAL_FG.getBlue(),
|
||||
TERMINAL_BG.getRed(), TERMINAL_BG.getGreen(), TERMINAL_BG.getBlue());
|
||||
|
||||
// Sample chat history
|
||||
String sampleChat =
|
||||
"<div class='system'>Welcome to DIYLC AI Assistant! How can I help you today?</div>\n\n" +
|
||||
"<div class='user'>How do I create a simple circuit?</div>\n\n" +
|
||||
"<div class='assistant'>To create a simple circuit:\n" +
|
||||
"1. Drag components from the component panel\n" +
|
||||
"2. Connect them by dragging from one terminal to another\n" +
|
||||
"3. Use the grid to align components neatly</div>\n\n" +
|
||||
"<div class='user'>What's the best way to organize components?</div>\n\n" +
|
||||
"<div class='assistant'>For best organization:\n" +
|
||||
"- Group related components together\n" +
|
||||
"- Use consistent spacing\n" +
|
||||
"- Label important connections\n" +
|
||||
"- Consider signal flow direction</div>";
|
||||
|
||||
|
||||
String sampleChat = getSampleChat();
|
||||
|
||||
chatEditorPane.setContentType("text/html");
|
||||
chatEditorPane.setText(htmlStyle + "<body><pre>" + sampleChat + "</pre></body>");
|
||||
}
|
||||
return chatEditorPane;
|
||||
}
|
||||
|
||||
private String getSampleChat() {
|
||||
Random r = new Random();
|
||||
|
||||
return
|
||||
"<div class='system'>Welcome to the DIYLC AI Assistant!</div><br><br>\n" +
|
||||
"<div class='assistant'>I'm here to help you design, build, and troubleshoot your electronics projects using DIY Layout Creator (DIYLC). You can ask me questions about:</div><br>\n" +
|
||||
"<ul>\n" +
|
||||
" <li><b>Electronics theory or concepts:</b> <i>e.g.,</i> '<span class='user'>" + electronicsQuestions[r.nextInt(
|
||||
electronicsQuestions.length)] + "</span>'</li>\n" +
|
||||
" <li><b>DIYLC features and usage:</b> <i>e.g.,</i> '<span class='user'>" + diylcQuestions[r.nextInt(diylcQuestions.length)] + "</span>'</li>\n" +
|
||||
" <li><b>Your current circuit project:</b> <i>e.g.,</i> '<span class='user'>" + circuitQuestions[r.nextInt(circuitQuestions.length)] + "</span>'</li>\n" +
|
||||
"</ul><br>\n" +
|
||||
"<div class='assistant'>Feel free to ask your own question or use one of these examples to get started!</div><br>";
|
||||
}
|
||||
|
||||
public JButton getAskButton() {
|
||||
if (askButton == null) {
|
||||
askButton = new JButton("Ask");
|
||||
@@ -243,7 +341,8 @@ public class ChatbotPane extends JPanel {
|
||||
askButton.setBorderPainted(true);
|
||||
askButton.addActionListener(e -> {
|
||||
final String prompt = getPromptArea().getText();
|
||||
appendSection("user", prompt);
|
||||
appendSection(USER, prompt);
|
||||
appendSection(TEMPORARY, "Waiting for the response...");
|
||||
getPromptArea().setText(null);
|
||||
String currentFile = plugInPort.getCurrentFileName();
|
||||
String fileName = extractFileName(currentFile);
|
||||
@@ -259,14 +358,14 @@ public class ChatbotPane extends JPanel {
|
||||
|
||||
@Override
|
||||
public void failed(Exception e) {
|
||||
appendSection("system", "Failed to retrieve the response from the server. Error: " + e.getMessage());
|
||||
appendSection(SYSTEM, "Failed to retrieve the response from the server. Error: " + e.getMessage());
|
||||
LOG.error("Failed to retrieve the response from the server", e);
|
||||
getClearButton().setEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void complete(String result) {
|
||||
appendSection("assistant", result);
|
||||
appendSection(ASSISTANT, result);
|
||||
getClearButton().setEnabled(true);
|
||||
}
|
||||
}, true);
|
||||
@@ -277,9 +376,13 @@ public class ChatbotPane extends JPanel {
|
||||
|
||||
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*";
|
||||
text = text.replaceAll(regex, "");
|
||||
// add a new div
|
||||
int bodyCloseIndex = text.indexOf("</body>");
|
||||
text = text.substring(0, bodyCloseIndex) +
|
||||
"\n<div class='" + style + "'>" + insertText + "</div>\n" +
|
||||
"\n<div class='" + style + "'>" + insertText + "</div><br>" +
|
||||
text.substring(bodyCloseIndex);
|
||||
getChatEditorPane().setText(text);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package org.diylc;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import org.diylc.common.ComponentType;
|
||||
import org.diylc.presenter.ComponentProcessor;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ComponentTypeDumpTest {
|
||||
|
||||
// @Test
|
||||
public void dumpComponentTypesToKnowledgeBaseSQLFile() {
|
||||
Map<String, List<ComponentType>> componentTypes =
|
||||
ComponentProcessor.getInstance().getComponentTypes();
|
||||
|
||||
List<DIYLCComponentType> components = componentTypes.values().stream()
|
||||
.flatMap(x -> x.stream())
|
||||
.map(x -> new DIYLCComponentType(x.getName(), x.getDescription(), x.getCategory(),
|
||||
ComponentProcessor.getInstance().extractProperties(x.getInstanceClass()).stream()
|
||||
.map(y -> new DIYLCProperty(y.getName(), formatType(y.getType())))
|
||||
.toList()))
|
||||
.toList();
|
||||
|
||||
try (PrintWriter writer = new PrintWriter(new File("/users/branislavstojkovic/downloads/test.sql"))) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.enable(SerializationFeature.INDENT_OUTPUT);
|
||||
|
||||
for (DIYLCComponentType component : components) {
|
||||
String section = "Component Type: " + component.getName();
|
||||
String escapedSection = section.replace("'", "''");
|
||||
|
||||
// First delete any existing record for this component type
|
||||
String deleteSql = String.format(
|
||||
"DELETE FROM diylc_knowledge_base WHERE section = '%s';\n",
|
||||
escapedSection
|
||||
);
|
||||
writer.write(deleteSql);
|
||||
|
||||
// Then insert the new record
|
||||
String content = mapper.writeValueAsString(component);
|
||||
content = content.replace("'", "''");
|
||||
|
||||
String insertSql = String.format(
|
||||
"INSERT INTO diylc_knowledge_base (section, content) VALUES ('%s', '%s');\n",
|
||||
escapedSection,
|
||||
content
|
||||
);
|
||||
|
||||
writer.write(insertSql);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Failed to write SQL file", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String formatType(Class<?> type) {
|
||||
if (type.isEnum()) {
|
||||
String enumValues = Arrays.stream(type.getEnumConstants())
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.joining(","));
|
||||
return type.getName() + "(" + enumValues + ")";
|
||||
}
|
||||
return type.getName();
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
static class DIYLCProperty {
|
||||
private String name;
|
||||
private String type;
|
||||
|
||||
public DIYLCProperty(String name, String type) {
|
||||
this.name = name;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getType() { return type; }
|
||||
public void setType(String type) { this.type = type; }
|
||||
}
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private static class DIYLCComponentType {
|
||||
private String name;
|
||||
private String description;
|
||||
private String category;
|
||||
private List<DIYLCProperty> properties;
|
||||
|
||||
public DIYLCComponentType(String name, String description, String category,
|
||||
List<DIYLCProperty> properties) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.category = category;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public String getName() { return name; }
|
||||
public void setName(String name) { this.name = name; }
|
||||
public String getDescription() { return description; }
|
||||
public void setDescription(String description) { this.description = description; }
|
||||
public String getCategory() { return category; }
|
||||
public void setCategory(String category) { this.category = category; }
|
||||
public List<DIYLCProperty> getProperties() { return properties; }
|
||||
public void setProperties(List<DIYLCProperty> properties) { this.properties = properties; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user