chore: Add README.md files
This commit is contained in:
commit
4ceec902a3
155 changed files with 19124 additions and 0 deletions
22
demo-06/README.md
Normal file
22
demo-06/README.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
Demo 06 - RAG Part 2
|
||||
===============================================
|
||||
|
||||
Retrieval Augmented Generation (RAG) is a way to extend the knowledge of the LLM used in the AI service.
|
||||
|
||||
The RAG pattern is composed of two parts:
|
||||
* Ingestion: This is the part that stores data in the knowledge base.
|
||||
* Augmentation: This is the part that adds the retrieved information to the input of the LLM.
|
||||
|
||||
|
||||
# Embedding model
|
||||
One of the core components of the RAG pattern is the embedding model. The embedding model is used to transform the
|
||||
text into numerical vectors. These vectors are used to compare the text and find the most relevant segments.
|
||||
|
||||
# Vector store
|
||||
In the previous step, we used an in memory store. Now we will use a persistent store to keep the embeddings between restarts.
|
||||
|
||||
# Ingesting documents into the vector store
|
||||
While you are editing the `src/main/resources/application.properties` file, add the following configuration:
|
||||
```
|
||||
rag.location=src/main/resources/rag
|
||||
```
|
210
demo-06/pom.xml
Normal file
210
demo-06/pom.xml
Normal file
|
@ -0,0 +1,210 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>ch.phoenixtechnologies</groupId>
|
||||
<artifactId>ai-lc4j-workshop</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>demo-06</artifactId>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
|
||||
<!-- Plugin versions -->
|
||||
<compiler-plugin.version>3.14.0</compiler-plugin.version>
|
||||
<enforcer-plugin.version>3.5.0</enforcer-plugin.version>
|
||||
<surefire-plugin.version>3.5.2</surefire-plugin.version>
|
||||
<spotless-maven-plugin.version>2.44.3</spotless-maven-plugin.version>
|
||||
<palantir-java-format.version>2.50.0</palantir-java-format.version>
|
||||
<release-plugin.version>3.1.1</release-plugin.version>
|
||||
|
||||
<!-- Quarkus version -->
|
||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||
<quarkus.platform.version>3.19.2</quarkus.platform.version>
|
||||
|
||||
<!-- LangChain4j-->
|
||||
<quarkus-langchain4j.version>0.25.0</quarkus-langchain4j.version>
|
||||
|
||||
<!-- Test dependency versions -->
|
||||
<assertj.version>3.27.3</assertj.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>${quarkus.platform.artifact-id}</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkiverse.langchain4j</groupId>
|
||||
<artifactId>quarkus-langchain4j-bom</artifactId>
|
||||
<version>${quarkus-langchain4j.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-config-yaml</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- langchain4j -->
|
||||
<dependency>
|
||||
<groupId>io.quarkiverse.langchain4j</groupId>
|
||||
<artifactId>quarkus-langchain4j-openai</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkiverse.langchain4j</groupId>
|
||||
<artifactId>quarkus-langchain4j-pgvector</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.langchain4j</groupId>
|
||||
<artifactId>langchain4j-embeddings</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-rest</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-websockets-next</artifactId>
|
||||
</dependency>
|
||||
<!-- UI -->
|
||||
<dependency>
|
||||
<groupId>org.mvnpm</groupId>
|
||||
<artifactId>importmap</artifactId>
|
||||
<version>1.0.8</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mvnpm.at.mvnpm</groupId>
|
||||
<artifactId>vaadin-webcomponents</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mvnpm</groupId>
|
||||
<artifactId>es-module-shims</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mvnpm</groupId>
|
||||
<artifactId>wc-chatbot</artifactId>
|
||||
<version>0.2.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>${quarkus.platform.group-id}</groupId>
|
||||
<artifactId>quarkus-maven-plugin</artifactId>
|
||||
<version>${quarkus.platform.version}</version>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
<goal>generate-code</goal>
|
||||
<goal>generate-code-tests</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
<release>${java.version}</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${surefire-plugin.version}</version>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||
<maven.home>${maven.home}</maven.home>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-enforcer-plugin</artifactId>
|
||||
<version>${enforcer-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>ban-bad-log4j-versions</id>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>enforce</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<rules>
|
||||
<bannedDependencies>
|
||||
<excludes>
|
||||
<exclude>org.apache.logging.log4j:log4j-core:(,2.17.1)</exclude>
|
||||
</excludes>
|
||||
</bannedDependencies>
|
||||
</rules>
|
||||
<fail>true</fail>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.diffplug.spotless</groupId>
|
||||
<artifactId>spotless-maven-plugin</artifactId>
|
||||
<version>${spotless-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
<phase>compile</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<java>
|
||||
<removeUnusedImports />
|
||||
<palantirJavaFormat>
|
||||
<version>${palantir-java-format.version}</version>
|
||||
<style>PALANTIR</style>
|
||||
<formatJavadoc>false</formatJavadoc>
|
||||
</palantirJavaFormat>
|
||||
</java>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>${release-plugin.version}</version>
|
||||
<configuration>
|
||||
<tagNameFormat>@{project.version}</tagNameFormat>
|
||||
<checkModificationExcludes>mvnw</checkModificationExcludes>
|
||||
<scmReleaseCommitComment>chore: release @{releaseLabel}</scmReleaseCommitComment>
|
||||
<scmDevelopmentCommitComment>chore: prepare for next development iteration [skip ci]</scmDevelopmentCommitComment>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,18 @@
|
|||
package ch.phoenixtechnologies.lc4j.openai.runtime.config;
|
||||
|
||||
import io.smallrye.config.ConfigMapping;
|
||||
|
||||
@ConfigMapping(prefix = "l4j.custom-embedding-model")
|
||||
public interface CustomEmbeddingModelConfig {
|
||||
String baseUrl();
|
||||
|
||||
String apiKey();
|
||||
|
||||
String modelName();
|
||||
|
||||
boolean logRequests();
|
||||
|
||||
boolean logResponses();
|
||||
|
||||
// int dimensions();
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package ch.phoenixtechnologies.lc4j.openai.runtime.config;
|
||||
|
||||
import dev.langchain4j.model.embedding.EmbeddingModel;
|
||||
import dev.langchain4j.model.openai.OpenAiEmbeddingModel;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.inject.Produces;
|
||||
|
||||
@ApplicationScoped
|
||||
public class CustomEmbeddingModelProducer {
|
||||
private final CustomEmbeddingModelConfig config;
|
||||
|
||||
public CustomEmbeddingModelProducer(CustomEmbeddingModelConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@Produces
|
||||
public EmbeddingModel getModel() {
|
||||
return OpenAiEmbeddingModel.builder()
|
||||
.apiKey(config.apiKey())
|
||||
.baseUrl(config.baseUrl())
|
||||
.modelName(config.modelName())
|
||||
.logRequests(config.logRequests())
|
||||
.logResponses(config.logResponses())
|
||||
// .dimensions(config.dimensions())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package ch.phoenixtechnologies.lc4j.workshop;
|
||||
|
||||
import dev.langchain4j.service.SystemMessage;
|
||||
import io.quarkiverse.langchain4j.RegisterAiService;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
import jakarta.enterprise.context.SessionScoped;
|
||||
|
||||
@SessionScoped
|
||||
@RegisterAiService
|
||||
public interface CustomerSupportAgent {
|
||||
@SystemMessage(
|
||||
"""
|
||||
You are a customer support agent of a IT company 'Phoenix Technologies AG based in Switzerland.
|
||||
You are friendly, polite and concise.
|
||||
If the question is unrelated to IT services, you should politely redirect the customer to the right department.
|
||||
""")
|
||||
Multi<String> chat(String userMessage);
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package ch.phoenixtechnologies.lc4j.workshop;
|
||||
|
||||
import io.quarkus.websockets.next.OnOpen;
|
||||
import io.quarkus.websockets.next.OnTextMessage;
|
||||
import io.quarkus.websockets.next.WebSocket;
|
||||
import io.smallrye.mutiny.Multi;
|
||||
|
||||
@WebSocket(path = "/customer-support-agent")
|
||||
public class CustomerSupportAgentWebSocket {
|
||||
private final CustomerSupportAgent agent;
|
||||
|
||||
public CustomerSupportAgentWebSocket(CustomerSupportAgent agent) {
|
||||
this.agent = agent;
|
||||
}
|
||||
|
||||
@OnOpen
|
||||
public String onOpen() {
|
||||
return "Welcome to Phoenix Technologies AI!";
|
||||
}
|
||||
|
||||
@OnTextMessage
|
||||
public Multi<String> onTextMessage(String message) {
|
||||
return agent.chat(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package ch.phoenixtechnologies.lc4j.workshop;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import org.mvnpm.importmap.Aggregator;
|
||||
|
||||
@ApplicationScoped
|
||||
@Path("/_importmap")
|
||||
public class ImportmapResource {
|
||||
private static final String JAVASCRIPT_CODE =
|
||||
"""
|
||||
const im = document.createElement('script');
|
||||
im.type = 'importmap';
|
||||
im.textContent = JSON.stringify(%s);
|
||||
document.currentScript.after(im);
|
||||
""";
|
||||
private String importmap;
|
||||
|
||||
@PostConstruct
|
||||
void init() {
|
||||
Aggregator aggregator = new Aggregator();
|
||||
// Add our own mappings
|
||||
aggregator.addMapping("icons/", "/icons/");
|
||||
aggregator.addMapping("components/", "/components/");
|
||||
aggregator.addMapping("fonts/", "/fonts/");
|
||||
this.importmap = aggregator.aggregateAsJson();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/dynamic.importmap")
|
||||
@Produces("application/importmap+json")
|
||||
public String importMap() {
|
||||
return this.importmap;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/dynamic-importmap.js")
|
||||
@Produces("application/javascript")
|
||||
public String importMapJson() {
|
||||
return JAVASCRIPT_CODE.formatted(this.importmap);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package ch.phoenixtechnologies.lc4j.workshop;
|
||||
|
||||
import static dev.langchain4j.data.document.splitter.DocumentSplitters.recursive;
|
||||
|
||||
import dev.langchain4j.data.document.Document;
|
||||
import dev.langchain4j.data.document.loader.FileSystemDocumentLoader;
|
||||
import dev.langchain4j.model.embedding.EmbeddingModel;
|
||||
import dev.langchain4j.model.embedding.onnx.HuggingFaceTokenizer;
|
||||
import dev.langchain4j.store.embedding.EmbeddingStore;
|
||||
import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
|
||||
import io.quarkus.logging.Log;
|
||||
import io.quarkus.runtime.StartupEvent;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
@ApplicationScoped
|
||||
public class RagIngestion {
|
||||
|
||||
/**
|
||||
* Ingests the documents from the given location into the embedding store.
|
||||
*
|
||||
* @param ev the startup event to trigger the ingestion when the application starts
|
||||
* @param store the embedding store the embedding store (PostGreSQL in our case)
|
||||
* @param embeddingModel the embedding model to use for the embedding (BGE-Small-EN-Quantized in our case)
|
||||
* @param documents the location of the documents to ingest
|
||||
*/
|
||||
public void ingest(
|
||||
@Observes StartupEvent ev,
|
||||
EmbeddingStore store,
|
||||
EmbeddingModel embeddingModel,
|
||||
@ConfigProperty(name = "rag.location") Path documents) {
|
||||
store.removeAll(); // cleanup the store to start fresh (just for demo purposes)
|
||||
List<Document> list = FileSystemDocumentLoader.loadDocumentsRecursively(documents);
|
||||
EmbeddingStoreIngestor ingestor = EmbeddingStoreIngestor.builder()
|
||||
.embeddingStore(store)
|
||||
.embeddingModel(embeddingModel)
|
||||
.documentSplitter(recursive(100, 25, new HuggingFaceTokenizer()))
|
||||
.build();
|
||||
ingestor.ingest(list);
|
||||
Log.info("Documents ingested successfully");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package ch.phoenixtechnologies.lc4j.workshop;
|
||||
|
||||
import dev.langchain4j.data.message.UserMessage;
|
||||
import dev.langchain4j.model.embedding.EmbeddingModel;
|
||||
import dev.langchain4j.rag.DefaultRetrievalAugmentor;
|
||||
import dev.langchain4j.rag.RetrievalAugmentor;
|
||||
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
|
||||
import dev.langchain4j.store.embedding.EmbeddingStore;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.inject.Produces;
|
||||
|
||||
public class RagRetriever {
|
||||
@Produces
|
||||
@ApplicationScoped
|
||||
public RetrievalAugmentor create(EmbeddingStore store, EmbeddingModel model) {
|
||||
var contentRetriever = EmbeddingStoreContentRetriever.builder()
|
||||
.embeddingModel(model)
|
||||
.embeddingStore(store)
|
||||
.maxResults(3)
|
||||
.build();
|
||||
|
||||
return DefaultRetrievalAugmentor.builder()
|
||||
.contentRetriever(contentRetriever)
|
||||
.contentInjector((contents, userMessage) -> {
|
||||
StringBuffer prompt = new StringBuffer(userMessage.singleText());
|
||||
//prompt.append("\nPlease, only use the following information:\n");
|
||||
contents.forEach(content -> prompt.append("- ")
|
||||
.append(content.textSegment().text())
|
||||
.append("\n"));
|
||||
return new UserMessage(prompt.toString());
|
||||
})
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
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 chatBot = document.getElementsByTagName("chat-bot")[0];
|
||||
|
||||
const protocol = (window.location.protocol === 'https:') ? 'wss' : 'ws';
|
||||
const socket = new WebSocket(protocol + '://' + window.location.host + '/customer-support-agent');
|
||||
|
||||
const that = this;
|
||||
socket.onmessage = function (event) {
|
||||
chatBot.hideLastLoading();
|
||||
// LLM response
|
||||
let lastMessage;
|
||||
if (chatBot.messages.length > 0) {
|
||||
lastMessage = chatBot.messages[chatBot.messages.length - 1];
|
||||
}
|
||||
if (lastMessage && lastMessage.sender.name === "Bot" && ! lastMessage.loading) {
|
||||
if (! lastMessage.msg) {
|
||||
lastMessage.msg = "";
|
||||
}
|
||||
lastMessage.msg += event.data;
|
||||
let bubbles = chatBot.shadowRoot.querySelectorAll("chat-bubble");
|
||||
let bubble = bubbles.item(bubbles.length - 1);
|
||||
if (lastMessage.message) {
|
||||
bubble.innerHTML = that._stripHtml(lastMessage.message) + lastMessage.msg;
|
||||
} else {
|
||||
bubble.innerHTML = lastMessage.msg;
|
||||
}
|
||||
chatBot.body.scrollTo({ top: chatBot.body.scrollHeight, behavior: 'smooth' })
|
||||
} else {
|
||||
chatBot.sendMessage(event.data, {
|
||||
right: false,
|
||||
sender: {
|
||||
name: "Bot"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
|
@ -0,0 +1,63 @@
|
|||
import {LitElement, html, css} 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/grid';
|
||||
import '@vaadin/grid/vaadin-grid-sort-column.js';
|
||||
|
||||
export class DemoTitle extends LitElement {
|
||||
|
||||
static styles = css`
|
||||
h2 {
|
||||
font-family: "Red Hat Mono", monospace;
|
||||
font-size: 60px;
|
||||
font-style: normal;
|
||||
font-variant: normal;
|
||||
font-weight: 700;
|
||||
line-height: 26.4px;
|
||||
color: var(--main-highlight-text-color);
|
||||
}
|
||||
|
||||
.title {
|
||||
text-align: center;
|
||||
padding: 1em;
|
||||
background: var(--main-bg-color);
|
||||
}
|
||||
|
||||
.explanation {
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
width: 50%;
|
||||
text-align: justify;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.explanation img {
|
||||
max-width: 60%;
|
||||
display: block;
|
||||
float:left;
|
||||
margin-right: 2em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
`
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="title">
|
||||
<h2>Phoenix Technologies</h2>
|
||||
</div>
|
||||
<div class="explanation">
|
||||
<p>Welcome to Phoenix Technologies!</p>
|
||||
<p>Please click the button on the bottom right to start the conversation
|
||||
with an LLM-powered customer support agent.</p>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
customElements.define('demo-title', DemoTitle);
|
1
demo-06/src/main/resources/META-INF/resources/fonts/red-hat-font.min.css
vendored
Normal file
1
demo-06/src/main/resources/META-INF/resources/fonts/red-hat-font.min.css
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
@font-face{font-family:"Red Hat Display";font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/redhatdisplay/v7/8vIQ7wUr0m80wwYf0QCXZzYzUoTg8z6hR4jNCH5Z.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Red Hat Display";font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/redhatdisplay/v7/8vIQ7wUr0m80wwYf0QCXZzYzUoTg_T6hR4jNCA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Red Hat Display";font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/redhatdisplay/v7/8vIQ7wUr0m80wwYf0QCXZzYzUoTg8z6hR4jNCH5Z.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Red Hat Display";font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/redhatdisplay/v7/8vIQ7wUr0m80wwYf0QCXZzYzUoTg_T6hR4jNCA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Red Hat Display";font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/redhatdisplay/v7/8vIQ7wUr0m80wwYf0QCXZzYzUoTg8z6hR4jNCH5Z.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Red Hat Display";font-style:normal;font-weight:700;font-display:swap;src:url(https://fonts.gstatic.com/s/redhatdisplay/v7/8vIQ7wUr0m80wwYf0QCXZzYzUoTg_T6hR4jNCA.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Red Hat Text";font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/redhattext/v6/RrQXbohi_ic6B3yVSzGBrMxQZqctMc-JPWCN.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Red Hat Text";font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/redhattext/v6/RrQXbohi_ic6B3yVSzGBrMxQaKctMc-JPQ.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:"Red Hat Text";font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/redhattext/v6/RrQXbohi_ic6B3yVSzGBrMxQZqctMc-JPWCN.woff2) format("woff2");unicode-range:U+0100-024F,U+0259,U+1E00-1EFF,U+2020,U+20A0-20AB,U+20AD-20CF,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:"Red Hat Text";font-style:normal;font-weight:500;font-display:swap;src:url(https://fonts.gstatic.com/s/redhattext/v6/RrQXbohi_ic6B3yVSzGBrMxQaKctMc-JPQ.woff2) format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}/*# sourceMappingURL=red-hat-font.css.map */
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,7 @@
|
|||
// import './font-awesome-brands.js';
|
||||
// import './font-awesome-regular.js';
|
||||
import './font-awesome-solid.js';
|
||||
|
||||
// export * from './font-awesome-brands.js';
|
||||
// export * from './font-awesome-regular.js';
|
||||
export * from './font-awesome-solid.js';
|
82
demo-06/src/main/resources/META-INF/resources/index.html
Normal file
82
demo-06/src/main/resources/META-INF/resources/index.html
Normal file
|
@ -0,0 +1,82 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link rel="shortcut icon" type="image/png" href="favicon.ico">
|
||||
|
||||
<script src="/_importmap/dynamic-importmap.js"></script>
|
||||
|
||||
<script type="module">
|
||||
import 'icons/font-awesome.js';
|
||||
import 'components/demo-title.js';
|
||||
import 'components/demo-chat.js';
|
||||
import 'wc-chatbot';
|
||||
</script>
|
||||
|
||||
<link rel="stylesheet" href="fonts/red-hat-font.min.css">
|
||||
|
||||
<title>Miles of Smiles</title>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
--main-bg-color: rgb(246, 242, 242);
|
||||
--main-highlight-text-color: rgba(237, 98, 128);
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
font-family: 'Red Hat Text', sans-serif;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
color: var(--lumo-body-text-color);
|
||||
background: var(--main-bg-color);
|
||||
}
|
||||
|
||||
chat-bot {
|
||||
--chatbot-avatar-bg-color: rgba(237, 98, 128);
|
||||
--chatbot-avatar-margin: 10%;
|
||||
--chatbot-header-bg-color: rgba(237, 98, 128);
|
||||
--chatbot-header-title-color: #FFFFFF;
|
||||
--chatbot-body-bg-color: var(--main-bg-color);
|
||||
--chatbot-send-button-color: rgba(237, 98, 128);
|
||||
}
|
||||
|
||||
chat-bot::part(chat-bubble) {
|
||||
--chat-bubble-avatar-color: rgba(237, 98, 128);
|
||||
--chat-bubble-color: rgba(203, 232, 237, 0.71);
|
||||
--chat-bubble-right-color: rgb(157, 238, 244);
|
||||
--chat-bubble-font-color: #333;
|
||||
--chat-bubble-font-right-color: #333;
|
||||
--chat-bubble-delay: 0.2s;
|
||||
}
|
||||
|
||||
.middle {
|
||||
margin-top: 2em;
|
||||
overflow: hidden;
|
||||
width: 50%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<demo-title></demo-title>
|
||||
|
||||
<div class="middle">
|
||||
<demo-chat>
|
||||
<chat-bot></chat-bot>
|
||||
</demo-chat>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
35
demo-06/src/main/resources/application.yaml
Normal file
35
demo-06/src/main/resources/application.yaml
Normal file
|
@ -0,0 +1,35 @@
|
|||
quarkus:
|
||||
langchain4j:
|
||||
openai:
|
||||
api-key: #PUT_YOUR_TOKEN_HERE
|
||||
base-url: https://inference-llama33-70b-maas.apps.ai.kvant.cloud/v1/
|
||||
timeout: 60s
|
||||
#https://docs.langchain4j.dev/tutorials/model-parameters/
|
||||
chat-model:
|
||||
model-name: inference-llama33-70b
|
||||
temperature: 1.0
|
||||
#max-tokens: 1000
|
||||
#frequency-penalty: 2
|
||||
frequency-penalty: 0
|
||||
log-requests: true
|
||||
log-responses: true
|
||||
embedding-model:
|
||||
log-responses: true
|
||||
log-requests: true
|
||||
#embedding-model:
|
||||
# provider: dev.langchain4j.model.embedding.onnx.bgesmallenq.BgeSmallEnQuantizedEmbeddingModel
|
||||
pgvector:
|
||||
dimension: 1024
|
||||
#This configuration takes precedence over the embedding-model.provider one.
|
||||
l4j:
|
||||
custom-embedding-model:
|
||||
#This is 1024 dimension model. pgvector must be configured accordingly
|
||||
model-name: inference-multilingual-e5l
|
||||
base-url: https://inference-multilingual-e5l-maas.apps.ai.kvant.cloud/v1
|
||||
api-key: #PUT_YOUR_TOKEN_HERE
|
||||
log-requests: false
|
||||
log-responses: false
|
||||
#Not supported by current implementation
|
||||
#dimensions: ${quarkus.langchain4j.pgvector.dimension}
|
||||
rag:
|
||||
location: src/main/resources/rag
|
37
demo-06/src/main/resources/rag/terms-of-use.txt
Normal file
37
demo-06/src/main/resources/rag/terms-of-use.txt
Normal file
|
@ -0,0 +1,37 @@
|
|||
Phoenix Technologies IT Services Terms of Use
|
||||
|
||||
1. Introduction
|
||||
These Terms of Service (“Terms”) govern the access or use by you, an individual, from within any country in the world, of applications, websites, content, products, and services (“Services”) made available by Phoenix Technologies IT Services, a company registered in the United States of America.
|
||||
|
||||
2. The Services
|
||||
Phoenix Technologies provides IT Services to the end user. We reserve the right to temporarily or permanently discontinue the Services at any time and are not liable for any modification, suspension or discontinuation of the Services.
|
||||
|
||||
3. Bookings
|
||||
3.1 Users may make a booking through our website or mobile application.
|
||||
3.2 You must provide accurate, current and complete information during the reservation process. You are responsible for all charges incurred under your account.
|
||||
3.3 All bookings are subject to IT service availability.
|
||||
|
||||
4. Cancellation Policy
|
||||
4.1 Reservations can be cancelled up to 11 days prior to the start of the booking period.
|
||||
4.2 If the booking period is less than 4 days, cancellations are not permitted.
|
||||
|
||||
5. Use of Service
|
||||
5.1 All services rented from Phoenix Technologies must not be used:
|
||||
for any illegal purpose or in connection with any criminal offense.
|
||||
for using in profit organization.
|
||||
for selling it to a third party.
|
||||
outside of Switzerland or EU.
|
||||
|
||||
6. Liability
|
||||
6.1 Users will be held liable for any damage, loss, or theft that occurs during the rental period.
|
||||
6.2 We do not accept liability for any indirect or consequential loss, damage, or expense including but not limited to loss of profits.
|
||||
|
||||
7. Governing Law
|
||||
These terms will be governed by and construed in accordance with the laws of the Switzerland, and any disputes relating to these terms will be subject to the exclusive jurisdiction of the courts of Switzerland.
|
||||
|
||||
8. Changes to These Terms
|
||||
We may revise these terms of use at any time by amending this page. You are expected to check this page from time to time to take notice of any changes we made.
|
||||
|
||||
9. Acceptance of These Terms
|
||||
By using the Services, you acknowledge that you have read and understand these Terms and agree to be bound by them.
|
||||
If you do not agree to these Terms, please do not use or access our Services.
|
Loading…
Add table
Add a link
Reference in a new issue