feat: add another component that can render md

This commit is contained in:
Markus Hofstetter 2025-04-29 08:39:25 +02:00
parent af32f2d02f
commit 1033f49c8e
8 changed files with 266 additions and 28 deletions

84
.m2/settings.xml Normal file
View File

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" ?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0">
<interactiveMode>false</interactiveMode>
<servers>
<server>
<id>dvb</id>
<username>${env.NEXUS2_DEPLOYMENT_USER}</username>
<password>${env.NEXUS2_DEPLOYMENT_PASSWORD}</password>
</server>
<server>
<id>dvb.snapshots</id>
<username>${env.NEXUS2_DEPLOYMENT_USER}</username>
<password>${env.NEXUS2_DEPLOYMENT_PASSWORD}</password>
</server>
</servers>
<mirrors>
<mirror>
<id>dvbern.nexus</id>
<mirrorOf>*</mirrorOf>
<name>DV Bern NEXUS Repository Mirror</name>
<url>https://nexus.dvbern.ch/nexus/content/groups/allrepos/</url>
</mirror>
</mirrors>
<profiles>
<profile>
<id>dvbern.nexus</id>
<properties>
<maven.repo.releases.url>https://nexus.dvbern.ch/nexus/content/repositories/dvb/</maven.repo.releases.url>
<maven.repo.snapshots.url>https://nexus.dvbern.ch/nexus/content/repositories/dvb.snapshots/</maven.repo.snapshots.url>
</properties>
<repositories>
<repository>
<id>central</id>
<url>http://central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>central</id>
<url>http://central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
<profile>
<id>mvnpm-repo</id>
<repositories>
<repository>
<id>central</id>
<name>central</name>
<url>https://repo.maven.apache.org/maven2</url>
</repository>
<repository>
<snapshots>
<enabled>false</enabled>
</snapshots>
<id>mvnpm.org</id>
<name>mvnpm</name>
<url>https://repo.mvnpm.org/maven2</url>
</repository>
</repositories>
</profile>
</profiles>
<activeProfiles>
<activeProfile>mvnpm-repo</activeProfile>
<!-- <activeProfile>dvbern.nexus</activeProfile>-->
</activeProfiles>
</settings>

View File

@ -76,6 +76,12 @@
<version>0.2.1</version> <version>0.2.1</version>
<scope>runtime</scope> <scope>runtime</scope>
</dependency> </dependency>
<!-- <dependency>-->
<!-- <groupId>org.mvnpm</groupId>-->
<!-- <artifactId>deep-chat</artifactId>-->
<!-- <version>2.1.1</version>-->
<!-- <scope>runtime</scope>-->
<!-- </dependency>-->
<dependency> <dependency>
<groupId>io.quarkiverse.langchain4j</groupId> <groupId>io.quarkiverse.langchain4j</groupId>
<artifactId>quarkus-langchain4j-easy-rag</artifactId> <artifactId>quarkus-langchain4j-easy-rag</artifactId>

View File

@ -0,0 +1,18 @@
package dev.langchain4j.quarkus.workshop.deepchat;
import dev.langchain4j.service.SystemMessage;
import io.quarkiverse.langchain4j.RegisterAiService;
import io.smallrye.mutiny.Multi;
import jakarta.enterprise.context.SessionScoped;
@SessionScoped
@RegisterAiService
public interface DeepChatSupportAgent {
@SystemMessage("""
You are a customer support agent of the vaccination application 'vacme'.
You are friendly, polite and concise.
If the question is unrelated to the login process or the usage of the vacme page, you should politely redirect the customer to the support email.
""")
Multi<String> chat(String userMessage);
}

View File

@ -0,0 +1,28 @@
package dev.langchain4j.quarkus.workshop.deepchat;
import io.quarkus.websockets.next.OnOpen;
import io.quarkus.websockets.next.OnTextMessage;
import io.quarkus.websockets.next.WebSocket;
import io.smallrye.mutiny.Multi;
import jakarta.inject.Inject;
@WebSocket(path = "/deep-chat-support-agent")
public class DeepChatSupportAgentWebSocket {
private final DeepChatSupportAgent deepChatSupportAgent;
@Inject
public DeepChatSupportAgentWebSocket(DeepChatSupportAgent deepChatSupportAgent) {
this.deepChatSupportAgent = deepChatSupportAgent;
}
@OnOpen
public DeepChatTextResponse onOpen() {
return new DeepChatTextResponse("Willkommen beim Vacme Support! Wie kann ich Ihnen Heute helfen?", false);
}
@OnTextMessage
public Multi<DeepChatTextResponse> onTextMessage(String message) {
return deepChatSupportAgent.chat(message).map(text -> new DeepChatTextResponse(text, false));
}
}

View File

@ -0,0 +1,8 @@
package dev.langchain4j.quarkus.workshop.deepchat;
public record DeepChatTextResponse(String text, boolean overwrite) {
public DeepChatTextResponse(String text, boolean overwrite) {
this.text = text;
this.overwrite = overwrite;
}
}

View File

@ -26,6 +26,24 @@ export class DemoChat extends LitElement {
const that = this; const that = this;
socket.onmessage = function (event) { socket.onmessage = function (event) {
that.addToWsChat(chatBot, event, that);
// this.addToDeepchat()
}
chatBot.addEventListener("sent", function (e) {
if (e.detail.message.sender.name !== "Bot") {
// User message
const msg = that._stripHtml(e.detail.message.message);
socket.send(msg);
chatBot.sendMessage("", {
right: false,
loading: true
});
}
});
}
addToWsChat(chatBot, event, that) {
chatBot.hideLastLoading(); chatBot.hideLastLoading();
// LLM response // LLM response
let lastMessage; let lastMessage;
@ -54,21 +72,6 @@ export class DemoChat extends LitElement {
}); });
} }
} }
chatBot.addEventListener("sent", function (e) {
if (e.detail.message.sender.name !== "Bot") {
// User message
const msg = that._stripHtml(e.detail.message.message);
socket.send(msg);
chatBot.sendMessage("", {
right: false,
loading: true
});
}
});
}
} }
customElements.define('demo-chat', DemoChat); customElements.define('demo-chat', DemoChat);

View File

@ -0,0 +1,66 @@
import {css, LitElement} from 'lit';
import '@vaadin/icon';
import '@vaadin/button';
import '@vaadin/text-field';
import '@vaadin/text-area';
import '@vaadin/form-layout';
import '@vaadin/progress-bar';
import '@vaadin/checkbox';
import '@vaadin/horizontal-layout';
import '@vaadin/grid';
import '@vaadin/grid/vaadin-grid-sort-column.js';
export class DemoChat extends LitElement {
_stripHtml(html) {
const div = document.createElement("div");
div.innerHTML = html;
return div.textContent || div.innerText || "";
}
connectedCallback() {
const chatElementRef = document.getElementsByTagName("deep-chat")[0];
const protocol = (window.location.protocol === 'https:') ? 'wss' : 'ws';
const websocket = new WebSocket(protocol + '://' + window.location.host + '/customer-support-agent');
// this handler is invoked when the component is loaded
chatElementRef.onMessage = (body) => {
if (body.message && body.message.role === 'user') {
websocket.send(body.message.text);
}};
chatElementRef.connect = {
stream: true,
handler: (_, signals) => {
try {
signals.onOpen(); // enables the user to send messages
websocket.onmessage = (message) => {
signals.onResponse({text: message.data});
};
websocket.onclose = () => {
signals.onClose(); // stops the user from sending messages
};
websocket.onerror = () => {
// 'Connection error' is a special string that will also display in Deep Chat
signals.onResponse({error: 'Connection error'});
};
// triggered when the user sends a message
// signals.newUserMessage.listener = (body) => {
// websocket.send(JSON.stringify(body));
// };
} catch (e) {
signals.onResponse({error: 'error'}); // displays an error message
signals.onClose(); // stops the user from sending messages
}
},
};
}
}
customElements.define('demo-deep-chat', DemoChat);

View File

@ -6,11 +6,16 @@
<link rel="shortcut icon" type="image/png" href="favicon.ico"> <link rel="shortcut icon" type="image/png" href="favicon.ico">
<script src="/_importmap/dynamic-importmap.js"></script> <script src="/_importmap/dynamic-importmap.js"></script>
<script
type="module"
src="https://unpkg.com/deep-chat@2.1.1/dist/deepChat.bundle.js"
></script>
<script type="module"> <script type="module">
import 'icons/font-awesome.js'; import 'icons/font-awesome.js';
import 'components/demo-title.js'; import 'components/demo-title.js';
import 'components/demo-chat.js'; import 'components/demo-chat.js';
import 'components/demo-deep-chat.js';
import 'wc-chatbot'; import 'wc-chatbot';
</script> </script>
@ -71,12 +76,32 @@
<body> <body>
<!--<deep-chat stream="true" connect='{"url": "ws://localhost:8080/deep-chat-support-agent", "websocket": true}'></deep-chat>-->
<!--<deep-chat avatars="true"></deep-chat>-->
<!--<deep-chat connect='{"url": "http://localhost:8686/openai-chat-stream", "stream": true}'></deep-chat>-->
<!--<deep-chat connect='{"stream": {"simulation": 6}}'></deep-chat>-->
<!--<deep-chat-->
<!-- remarkable='{"html": true, "typographer": true}'-->
<!-- history='[-->
<!-- {"text": "Text containing <button>html</button>", "role": "user"},-->
<!-- {"text": "Typographic text: (c)", "role": "user"},-->
<!-- {"text": " # title \n- list1", "role": "user"}-->
<!--]'-->
<!-- style="border-radius: 8px"-->
<!-- demo="true"-->
<!--&gt;</deep-chat>-->
<demo-title></demo-title> <demo-title></demo-title>
<div class="middle"> <div class="middle">
<demo-chat> <demo-chat>
<chat-bot></chat-bot> <chat-bot></chat-bot>
</demo-chat> </demo-chat>
<demo-deep-chat>
<deep-chat></deep-chat>
</demo-deep-chat>
</div> </div>
</body> </body>