From 86cd5caa8063645d0bdf6b57643f2f1efb6f124d Mon Sep 17 00:00:00 2001 From: Dinh Nguyen <127725498+ntqdinh-axonivy@users.noreply.github.com> Date: Wed, 20 Nov 2024 15:19:26 +0700 Subject: [PATCH] MARP-747 Improve the explanatory dialog and pimp the documentation. (#77) --------- Co-authored-by: linhpd-axonivy Co-authored-by: Dinh Nguyen --- openai-assistant-product/README.md | 3 + openai-assistant-product/README_DE.md | 3 + .../openai/assistant/ChatGptRequest.java | 12 +- .../openai/assistant/ui/ChatGptUiFlow.java | 24 +++- .../assistant/ui/CopyableInfoDialog.java | 105 +--------------- .../openai/assistant/ui/MarkdownDialog.java | 114 ++++++++++++++++++ .../openai/assistant/ui/QuestionDialog.java | 29 +++++ .../axonivy/connector/openai/mock/MockAI.java | 9 +- ...ist-ask-without-system-promt-response.json | 34 ++++++ .../json/assist-ask-without-system-promt.json | 14 +++ ...ist-insert-with-system-promt-response.json | 34 ++++++ .../json/assist-insert-with-system-promt.json | 18 +++ .../openai/mock/utils/AiAssistanceUtils.java | 36 ++++++ .../openai/test/AiAssistanceTest.java | 25 ++++ 14 files changed, 347 insertions(+), 113 deletions(-) create mode 100644 openai-assistant/src/com/axonivy/connector/openai/assistant/ui/MarkdownDialog.java create mode 100644 openai-assistant/src/com/axonivy/connector/openai/assistant/ui/QuestionDialog.java create mode 100644 openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-ask-without-system-promt-response.json create mode 100644 openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-ask-without-system-promt.json create mode 100644 openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-insert-with-system-promt-response.json create mode 100644 openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-insert-with-system-promt.json create mode 100644 openai-connector-test/src/com/axonivy/connector/openai/mock/utils/AiAssistanceUtils.java diff --git a/openai-assistant-product/README.md b/openai-assistant-product/README.md index 56fc169..31eae70 100644 --- a/openai-assistant-product/README.md +++ b/openai-assistant-product/README.md @@ -54,3 +54,6 @@ The following keys are valid and interpreted: ``` @variables.yaml@ ``` + +### Note +Make sure to enable the `Show Only Source Page` option under `Window` -> `Preferences` -> `Axon Ivy` -> `Html Dialog Editor` -> `Show Only Source Page` to prevent unexpected behavior. \ No newline at end of file diff --git a/openai-assistant-product/README_DE.md b/openai-assistant-product/README_DE.md index be6c688..b843879 100644 --- a/openai-assistant-product/README_DE.md +++ b/openai-assistant-product/README_DE.md @@ -56,3 +56,6 @@ The following keys are valid and interpreted: @variables.yaml@ ``` +### Note +Make sure to enable the `Show Only Source Page` option under `Window` -> `Preferences` -> `Axon Ivy` -> `Html Dialog Editor` -> `Show Only Source Page` to prevent unexpected behavior. + diff --git a/openai-assistant/src/com/axonivy/connector/openai/assistant/ChatGptRequest.java b/openai-assistant/src/com/axonivy/connector/openai/assistant/ChatGptRequest.java index 910a8b9..f78e67e 100644 --- a/openai-assistant/src/com/axonivy/connector/openai/assistant/ChatGptRequest.java +++ b/openai-assistant/src/com/axonivy/connector/openai/assistant/ChatGptRequest.java @@ -42,9 +42,19 @@ public String getModels() { } public String ask(String context, String question) { + return sendRequest(context, question, false); + } + + public String insert(String context, String question) { + return sendRequest(context, question, true); + } + + private String sendRequest(String context, String question, boolean includeSystemPrompt) { WebTarget chat = client.get().path("chat/completions"); ArrayNode arrayNode = JsonNodeFactory.instance.arrayNode(); - arrayNode.add(message("system", SYSTEM_PROMPT)); + if (includeSystemPrompt) { + arrayNode.add(message("system", SYSTEM_PROMPT)); + } arrayNode.add(message("user", String.format("%s \n\n %s", context, question))); ObjectNode request = completion().set("messages", arrayNode); var payload = Entity.entity(request, MediaType.APPLICATION_JSON); diff --git a/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/ChatGptUiFlow.java b/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/ChatGptUiFlow.java index bdfadec..7535ed6 100644 --- a/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/ChatGptUiFlow.java +++ b/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/ChatGptUiFlow.java @@ -67,7 +67,7 @@ public void run() { String insert = SwtCommonDialogs.openInputDialog(site.getShell(), "any wishes?", "what can Chat GPT do for you?", "insert a combobox to pick a brand out of: Mercedes, BMW or Tesla"); if (insert != null) { - var response = runWithProgress(()->chatGpt.ask(what, insert)); + var response = runWithProgress(() -> chatGpt.insert(what, insert)); diffResult(response); } return; @@ -99,11 +99,10 @@ public void run() { return; } } - - boolean assist = SwtCommonDialogs.openQuestionDialog(site.getShell(), "need assistance?", """ - ready for asking chat GPT on ? - """+quest+": \n"+abbrev(what)); - if (assist) { + var message = String.format("```\n%s\n```", centerAbbrev(what)); + var dialog = new QuestionDialog(site.getShell(), String.format("%s Code Snippet", capitalize(quest)), message); + dialog.open(); + if (dialog.isAgreed()) { var response = runWithProgress(()->chatGpt.ask(what, quest)); if (quest.equalsIgnoreCase(Quests.FIX)) { response = diffResult(response); @@ -113,6 +112,10 @@ public void run() { } } + private String capitalize(String text) { + return text.substring(0, 1).toUpperCase() + text.substring(1); + } + private String runWithProgress(Supplier gptAction) { var response = new AtomicReference(); run(pm -> { @@ -180,6 +183,15 @@ private static String abbrev(String what) { return what; } + private static String centerAbbrev(String what) { + int limit = 500; + if (what.length() > limit) { + int halfLimit = (limit - 3) / 2; + return what.substring(0, halfLimit) + "\n" + "..." + "\n" + what.substring(what.length() - halfLimit); + } + return what; + } + private Optional getSelectedText() { if (selected instanceof TextSelection text) { return Optional.of(text.getText()); diff --git a/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/CopyableInfoDialog.java b/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/CopyableInfoDialog.java index 40d9ce6..f0c7442 100644 --- a/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/CopyableInfoDialog.java +++ b/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/CopyableInfoDialog.java @@ -1,107 +1,17 @@ package com.axonivy.connector.openai.assistant.ui; -import org.commonmark.parser.Parser; -import org.commonmark.renderer.html.HtmlRenderer; -import org.eclipse.jface.dialogs.Dialog; -import org.eclipse.jface.preference.JFacePreferences; -import org.eclipse.jface.resource.JFaceResources; -import org.eclipse.swt.SWT; -import org.eclipse.swt.browser.Browser; -import org.eclipse.swt.browser.ProgressEvent; -import org.eclipse.swt.browser.ProgressListener; import org.eclipse.swt.dnd.Clipboard; import org.eclipse.swt.dnd.TextTransfer; import org.eclipse.swt.dnd.Transfer; -import org.eclipse.swt.graphics.Color; -import org.eclipse.swt.graphics.Point; -import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.graphics.Rectangle; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Shell; -public class CopyableInfoDialog extends Dialog { +public class CopyableInfoDialog extends MarkdownDialog { private static final int COPY_TO_CLIPBOARD_ID = 1; - private static final String HEX_COLOR_FORMAT = "#%02x%02x%02x"; - private String title; - private String message; - private Browser browser; public CopyableInfoDialog(Shell parentShell, String title, String message) { - super(parentShell); - this.title = title; - this.message = message; - } - - @Override - protected void configureShell(Shell newShell) { - super.configureShell(newShell); - newShell.setText(title); - newShell.setMinimumSize(750, 400); - } - - @Override - protected Point getInitialSize() { - return new Point(750, 400); - } - - @Override - protected Point getInitialLocation(Point initialSize) { - Rectangle screenSize = getShell().getDisplay().getPrimaryMonitor().getBounds(); - - // Calculate the center position - int x = (screenSize.width - initialSize.x) / 2; - int y = (screenSize.height - initialSize.y) / 2; - - return new Point(x, y); - } - - @Override - protected boolean isResizable() { - return true; - } - - @Override - protected Control createDialogArea(Composite parent) { - Composite container = (Composite) super.createDialogArea(parent); - container.setLayout(new GridLayout(1, false)); - - browser = new Browser(container, SWT.BORDER); - browser.setLayoutData(new GridData(GridData.FILL_BOTH)); - - Parser parser = Parser.builder().build(); - HtmlRenderer renderer = HtmlRenderer.builder().build(); - String htmlContent = renderer.render(parser.parse(this.message)); - - // Get Eclipse theme colors - Color bgColor = JFaceResources.getColorRegistry().get(JFacePreferences.CONTENT_ASSIST_BACKGROUND_COLOR); - Color fgColor = JFaceResources.getColorRegistry().get(JFacePreferences.CONTENT_ASSIST_FOREGROUND_COLOR); - - // Create CSS with Eclipse colors - String css = String.format("body { background-color: %s; color: %s; font-family: '%s'; }", toHex(bgColor.getRGB()), - toHex(fgColor.getRGB()), JFaceResources.getTextFont().getFontData()[0].getName()); - - // Wrap HTML content with custom CSS - String htmlWithCss = String.format("%s", css, htmlContent); - - browser.setText(htmlWithCss); - - browser.addProgressListener(new ProgressListener() { - @Override - public void completed(ProgressEvent event) { - getShell().getDisplay().asyncExec(() -> resizeDialog()); - } - - @Override - public void changed(ProgressEvent event) { - // Not needed for this implementation - } - }); - - return container; + super(parentShell, title, message); } @Override @@ -125,15 +35,4 @@ private void copyToClipboard() { clipboard.setContents(new Object[] { message }, new Transfer[] { textTransfer }); clipboard.dispose(); } - - private String toHex(RGB rgb) { - return String.format(HEX_COLOR_FORMAT, rgb.red, rgb.green, rgb.blue); - } - - private void resizeDialog() { - Shell shell = getShell(); - Point preferredSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT); - shell.setSize(preferredSize); - shell.layout(true, true); - } } diff --git a/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/MarkdownDialog.java b/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/MarkdownDialog.java new file mode 100644 index 0000000..1245a1f --- /dev/null +++ b/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/MarkdownDialog.java @@ -0,0 +1,114 @@ +package com.axonivy.connector.openai.assistant.ui; + +import org.commonmark.parser.Parser; +import org.commonmark.renderer.html.HtmlRenderer; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.preference.JFacePreferences; +import org.eclipse.jface.resource.JFaceResources; +import org.eclipse.swt.SWT; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.browser.ProgressEvent; +import org.eclipse.swt.browser.ProgressListener; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.RGB; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Shell; + +public abstract class MarkdownDialog extends Dialog { + + private static final String HEX_COLOR_FORMAT = "#%02x%02x%02x"; + protected String title; + protected String message; + protected Browser browser; + + public MarkdownDialog(Shell parentShell, String title, String message) { + super(parentShell); + this.title = title; + this.message = message; + } + + @Override + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText(title); + newShell.setMinimumSize(750, 400); + } + + @Override + protected Point getInitialSize() { + return new Point(750, 400); + } + + @Override + protected Point getInitialLocation(Point initialSize) { + Rectangle screenSize = getShell().getDisplay().getPrimaryMonitor().getBounds(); + + // Calculate the center position + int x = (screenSize.width - initialSize.x) / 2; + int y = (screenSize.height - initialSize.y) / 2; + + return new Point(x, y); + } + + @Override + protected boolean isResizable() { + return true; + } + + @Override + protected Control createDialogArea(Composite parent) { + Composite container = (Composite) super.createDialogArea(parent); + container.setLayout(new GridLayout(1, false)); + + browser = new Browser(container, SWT.BORDER); + browser.setLayoutData(new GridData(GridData.FILL_BOTH)); + + Parser parser = Parser.builder().build(); + HtmlRenderer renderer = HtmlRenderer.builder().build(); + String htmlContent = renderer.render(parser.parse(this.message)); + + // Wrap HTML content with custom CSS + String htmlWithCss = String.format("%s", getEclipseCss(), + htmlContent); + + browser.setText(htmlWithCss); + + browser.addProgressListener(new ProgressListener() { + @Override + public void completed(ProgressEvent event) { + getShell().getDisplay().asyncExec(() -> resizeDialog()); + } + + @Override + public void changed(ProgressEvent event) { + // Not needed for this implementation + } + }); + + return container; + } + + private String getEclipseCss() { + // Get Eclipse theme colors + Color fgColor = JFaceResources.getColorRegistry().get(JFacePreferences.CONTENT_ASSIST_FOREGROUND_COLOR); + Color bgColor = JFaceResources.getColorRegistry().get(JFacePreferences.CONTENT_ASSIST_BACKGROUND_COLOR); + return String.format("body { background-color: %s; color: %s; font-family: '%s'; }", toHex(bgColor.getRGB()), + toHex(fgColor.getRGB()), JFaceResources.getTextFont().getFontData()[0].getName()); + } + + private String toHex(RGB rgb) { + return String.format(HEX_COLOR_FORMAT, rgb.red, rgb.green, rgb.blue); + } + + private void resizeDialog() { + Shell shell = getShell(); + Point preferredSize = shell.computeSize(SWT.DEFAULT, SWT.DEFAULT); + shell.setSize(preferredSize); + shell.layout(true, true); + } +} diff --git a/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/QuestionDialog.java b/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/QuestionDialog.java new file mode 100644 index 0000000..25cb437 --- /dev/null +++ b/openai-assistant/src/com/axonivy/connector/openai/assistant/ui/QuestionDialog.java @@ -0,0 +1,29 @@ +package com.axonivy.connector.openai.assistant.ui; + +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Shell; + +public class QuestionDialog extends MarkdownDialog { + + private int buttonId; + + public QuestionDialog(Shell parentShell, String title, String message) { + super(parentShell, title, message); + } + @Override + protected void createButtonsForButtonBar(Composite parent) { + createButton(parent, IDialogConstants.YES_ID, IDialogConstants.YES_LABEL, true); + createButton(parent, IDialogConstants.NO_ID, IDialogConstants.NO_LABEL, false); + } + + @Override + protected void buttonPressed(int buttonId) { + this.buttonId = buttonId; + super.buttonPressed(OK); + } + + public boolean isAgreed() { + return buttonId == IDialogConstants.YES_ID; + } +} diff --git a/openai-connector-test/src/com/axonivy/connector/openai/mock/MockAI.java b/openai-connector-test/src/com/axonivy/connector/openai/mock/MockAI.java index c04c27f..bea7cbe 100644 --- a/openai-connector-test/src/com/axonivy/connector/openai/mock/MockAI.java +++ b/openai-connector-test/src/com/axonivy/connector/openai/mock/MockAI.java @@ -51,8 +51,11 @@ public class MockAI { "completions", json(load("completions.json")), "completions-response", json(load("completions-response.json")), "mail-generator", json(load("mail-generator.json")), - "mail-generator-response", json(load("mail-generator-response.json")) - ); + "mail-generator-response", json(load("mail-generator-response.json")), + "assist-ask-without-system-promt", json(load("assist-ask-without-system-promt.json")), + "assist-ask-without-system-promt-response", json(load("assist-ask-without-system-promt-response.json")), + "assist-insert-with-system-promt", json(load("assist-insert-with-system-promt.json")), + "assist-insert-with-system-promt-response", json(load("assist-insert-with-system-promt-response.json"))); @POST @Path("completions") @@ -89,7 +92,7 @@ private String input(JsonNode request, Map examples) { return null; } - @POST + @POST @Path("chat/completions") @Consumes(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON) diff --git a/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-ask-without-system-promt-response.json b/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-ask-without-system-promt-response.json new file mode 100644 index 0000000..010c94a --- /dev/null +++ b/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-ask-without-system-promt-response.json @@ -0,0 +1,34 @@ +{ + "id": "chatcmpl-AVHUYbcl2WKpRj0oaLrZm8yNXosBQ", + "object": "chat.completion", + "created": 1732018770, + "model": "gpt-3.5-turbo-0125", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "Sure, here is a combobox for you to pick a brand out of Mercedes, BMW, or Tesla:\n\n", + "refusal": null + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 28, + "completion_tokens": 64, + "total_tokens": 92, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "system_fingerprint": null +} \ No newline at end of file diff --git a/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-ask-without-system-promt.json b/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-ask-without-system-promt.json new file mode 100644 index 0000000..6111ce0 --- /dev/null +++ b/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-ask-without-system-promt.json @@ -0,0 +1,14 @@ +{ + "model": "gpt-3.5-turbo", + "max_tokens": 1024, + "temperature": 1, + "top_p": 1, + "frequency_penalty": 0, + "presence_penalty": 0, + "messages": [ + { + "role": "user", + "content": "insert a combobox to pick a brand out of: Mercedes, BMW or Tesla" + } + ] +} \ No newline at end of file diff --git a/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-insert-with-system-promt-response.json b/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-insert-with-system-promt-response.json new file mode 100644 index 0000000..49e5d74 --- /dev/null +++ b/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-insert-with-system-promt-response.json @@ -0,0 +1,34 @@ +{ + "id": "chatcmpl-AVHNuLIeqrGBUWPhDez363Gs5akFe", + "object": "chat.completion", + "created": 1732018358, + "model": "gpt-3.5-turbo-0125", + "choices": [ + { + "index": 0, + "message": { + "role": "assistant", + "content": "", + "refusal": null + }, + "logprobs": null, + "finish_reason": "stop" + } + ], + "usage": { + "prompt_tokens": 179, + "completion_tokens": 46, + "total_tokens": 225, + "prompt_tokens_details": { + "cached_tokens": 0, + "audio_tokens": 0 + }, + "completion_tokens_details": { + "reasoning_tokens": 0, + "audio_tokens": 0, + "accepted_prediction_tokens": 0, + "rejected_prediction_tokens": 0 + } + }, + "system_fingerprint": null +} \ No newline at end of file diff --git a/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-insert-with-system-promt.json b/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-insert-with-system-promt.json new file mode 100644 index 0000000..c14a84d --- /dev/null +++ b/openai-connector-test/src/com/axonivy/connector/openai/mock/json/assist-insert-with-system-promt.json @@ -0,0 +1,18 @@ +{ + "model": "gpt-3.5-turbo", + "max_tokens": 1024, + "temperature": 1, + "top_p": 1, + "frequency_penalty": 0, + "presence_penalty": 0, + "messages": [ + { + "role": "system", + "content": "SYSTEM_PROMT" + }, + { + "role": "user", + "content": "insert a combobox to pick a brand out of: Mercedes, BMW or Tesla" + } + ] +} \ No newline at end of file diff --git a/openai-connector-test/src/com/axonivy/connector/openai/mock/utils/AiAssistanceUtils.java b/openai-connector-test/src/com/axonivy/connector/openai/mock/utils/AiAssistanceUtils.java new file mode 100644 index 0000000..98e4e51 --- /dev/null +++ b/openai-connector-test/src/com/axonivy/connector/openai/mock/utils/AiAssistanceUtils.java @@ -0,0 +1,36 @@ +package com.axonivy.connector.openai.mock.utils; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ArrayNode; +import com.fasterxml.jackson.databind.node.JsonNodeFactory; +import com.fasterxml.jackson.databind.node.ObjectNode; + +public class AiAssistanceUtils { + private static ObjectNode completion() { + ObjectNode request = JsonNodeFactory.instance.objectNode(); + request.put("model", "gpt-3.5-turbo"); + request.put("temperature", 1); + request.put("top_p", 1); + request.put("frequency_penalty", 0); + request.put("presence_penalty", 0); + request.put("max_tokens", 1024); + return request; + } + + private static ObjectNode message(String role, String content) { + return JsonNodeFactory.instance.objectNode().put("role", role).put("content", content); + } + + public static Entity buildPayloadFromQuestion(String question, boolean includeSystemPrompt) { + ArrayNode arrayNode = JsonNodeFactory.instance.arrayNode(); + if (includeSystemPrompt) { + arrayNode.add(message("system", "SYSTEM_PROMT")); + } + arrayNode.add(message("user", question)); + ObjectNode request = completion().set("messages", arrayNode); + return Entity.entity(request, MediaType.APPLICATION_JSON); + } +} diff --git a/openai-connector-test/src_test/com/axonivy/connector/openai/test/AiAssistanceTest.java b/openai-connector-test/src_test/com/axonivy/connector/openai/test/AiAssistanceTest.java index 01c0e0f..800500c 100644 --- a/openai-connector-test/src_test/com/axonivy/connector/openai/test/AiAssistanceTest.java +++ b/openai-connector-test/src_test/com/axonivy/connector/openai/test/AiAssistanceTest.java @@ -14,6 +14,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import com.axonivy.connector.openai.mock.utils.AiAssistanceUtils; import com.fasterxml.jackson.databind.JsonNode; import ch.ivyteam.ivy.application.IApplication; @@ -85,6 +86,22 @@ void mailGenerator() { .isNotEmpty(); } + @Test + void askWithOutSystemPromt() { + JsonNode result = assistWithQuestion("insert a combobox to pick a brand out of: Mercedes, BMW or Tesla", false); + assertThat(result.toPrettyString()).isNotEmpty(); + assertThat(result.toPrettyString()).as("Provide combobox with generated message") + .contains("Sure, here is a combobox for you to pick a brand out of Mercedes, BMW, or Tesla"); + } + + @Test + void insertWithSystemPromt() { + JsonNode result = assistWithQuestion("insert a combobox to pick a brand out of: Mercedes, BMW or Tesla", true); + assertThat(result.toPrettyString()).isNotEmpty(); + assertThat(result.toPrettyString()).as("Provide combobox with system promt") + .contains("