@liip/liipgpt 0.0.15 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -0
- package/chat/index.html +85 -14
- package/chat/liipgpt-chat.iife.js +31 -31
- package/lib/liipgpt-client.d.ts +3 -3
- package/lib/liipgpt-client.js +116 -96
- package/lib/liipgpt-client.umd.cjs +8 -8
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# LiipGPT Chat & Library
|
|
2
|
+
|
|
3
|
+
This package provides two main features:
|
|
4
|
+
|
|
5
|
+
1. A web component for embedding the LiipGPT chat UI
|
|
6
|
+
2. A client library for interacting with the LiipGPT API
|
|
7
|
+
|
|
8
|
+
# Chat UI
|
|
9
|
+
|
|
10
|
+
## Setup
|
|
11
|
+
|
|
12
|
+
### With NPM
|
|
13
|
+
|
|
14
|
+
```html
|
|
15
|
+
<liipgpt-chat org="..." api-url="..." api-key="..."></liipgpt-chat>
|
|
16
|
+
|
|
17
|
+
<script type="module">
|
|
18
|
+
import '@liip/liipgpt/chat';
|
|
19
|
+
</script>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### With CDN
|
|
23
|
+
|
|
24
|
+
```html
|
|
25
|
+
<!DOCTYPE html>
|
|
26
|
+
<html>
|
|
27
|
+
<head>
|
|
28
|
+
<script type="module" src="https://unpkg.com/@liip/liipgpt/chat/liipgpt-chat.iife.js"></script>
|
|
29
|
+
</head>
|
|
30
|
+
<body>
|
|
31
|
+
<liipgpt-chat org="..." api-url="..." api-key="..."></liipgpt-chat>
|
|
32
|
+
</body>
|
|
33
|
+
</html>
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Web Component Attributes
|
|
37
|
+
|
|
38
|
+
- `org`: Is used to select theme and translation based on the organization. All available orgs are previewed here: [Preview](https://liipgpt.pages.liip.ch/liipgpt-chat/?org=liipgpt)
|
|
39
|
+
- `api-url`: URL to the chat backend
|
|
40
|
+
- `api-key`: API key that can be configured in the admin ui
|
|
41
|
+
- `lang` (optional): this can be used to control the chat ui language by the parent
|
|
42
|
+
|
|
43
|
+
## Flyout Configuration
|
|
44
|
+
|
|
45
|
+
The chat ui is responsive based on the parent container. If you want embed the chat ui (e.g. in a flyout) make sure the parent has a predefined width and height.
|
|
46
|
+
|
|
47
|
+
## Language Support
|
|
48
|
+
|
|
49
|
+
The component supports multiple languages with the following priority:
|
|
50
|
+
|
|
51
|
+
1. Language was set via the `lang` attribute
|
|
52
|
+
2. User selected language in the chat UI
|
|
53
|
+
3. Browser language
|
|
54
|
+
4. Fallback to "en"
|
|
55
|
+
|
|
56
|
+
Supported UI languages: 'en', 'de', 'fr', 'it'
|
|
57
|
+
|
|
58
|
+
# Library Usage
|
|
59
|
+
|
|
60
|
+
For custom AI integrations, you can use the LiipGPT client:
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
import { LiipGPTClient } from '@liip/liipgpt';
|
|
64
|
+
|
|
65
|
+
const client = new LiipGPTClient({
|
|
66
|
+
apiUrl: 'YOUR_API_URL',
|
|
67
|
+
apiKey: 'YOUR_API_KEY',
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Start a chat conversation
|
|
71
|
+
const response = client.chat('What can you tell me about Generative AI?');
|
|
72
|
+
|
|
73
|
+
// Subscribe to streaming responses
|
|
74
|
+
response.subscribe((message) => {
|
|
75
|
+
if (message.state === 'streaming') {
|
|
76
|
+
console.log(message.payload.message.markdown);
|
|
77
|
+
}
|
|
78
|
+
if (message.state === 'done') {
|
|
79
|
+
console.log('Chat complete');
|
|
80
|
+
}
|
|
81
|
+
if (message.state === 'error') {
|
|
82
|
+
console.error(message.errorMessage);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
# Loader settings
|
|
88
|
+
|
|
89
|
+
A simple loader is provided by default, you can override colors to fit your brand by using the `loaderBackground` and `loaderColor` attributes:
|
|
90
|
+
|
|
91
|
+
```html
|
|
92
|
+
<liipgpt-chat ... loaderBackground="green" loaderColor="white"></liipgpt-chat>
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Remarks:
|
|
96
|
+
|
|
97
|
+
- it's recommended to set the same background color (as `loaderBackground`) on the parent container, to avoid a potential flickering.
|
|
98
|
+
- you can pass CSS gradients on the `loaderBackground` attribute.
|
|
99
|
+
|
|
100
|
+
## Custom loader
|
|
101
|
+
|
|
102
|
+
You can also provide your own loader by using the `slot="loader"` attribute on a `div`, within the `liipgpt-chat` element:
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<liipgpt-chat org="..." api-url="..." api-key="...">
|
|
106
|
+
<div slot="loader" style="...">
|
|
107
|
+
<svg>your animated svg here</svg>
|
|
108
|
+
<div>or a simple message</div>
|
|
109
|
+
</div>
|
|
110
|
+
</liipgpt-chat>
|
|
111
|
+
```
|
package/chat/index.html
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<script>
|
|
7
|
+
const params = new URLSearchParams(window.location.search);
|
|
8
|
+
|
|
9
|
+
if (params.get('org') === 'liipgpt') {
|
|
10
|
+
document.documentElement.style.background = 'linear-gradient(0deg, #1B181E 0%, #2A2440 90%)';
|
|
11
|
+
}
|
|
12
|
+
</script>
|
|
6
13
|
<title>LiipGPT Preview</title>
|
|
7
14
|
</head>
|
|
8
15
|
<body>
|
|
@@ -29,16 +36,33 @@
|
|
|
29
36
|
sidebarTop.appendChild(button);
|
|
30
37
|
});
|
|
31
38
|
|
|
32
|
-
// Add layout toggle
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
// Add layout toggle button
|
|
40
|
+
const toggleLayoutBtn = document.createElement('button');
|
|
41
|
+
toggleLayoutBtn.textContent = `Box layout${params.get('boxLayout') === 'true' ? ' ✓' : ''}`;
|
|
42
|
+
toggleLayoutBtn.onclick = () => {
|
|
43
|
+
const chatWrapper = document.getElementById('chat-wrapper');
|
|
44
|
+
const url = new URL(window.location.href);
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
if (chatWrapper.classList.contains('box-layout')) {
|
|
47
|
+
chatWrapper.classList.remove('box-layout');
|
|
48
|
+
url.searchParams.delete('boxLayout');
|
|
49
|
+
} else {
|
|
50
|
+
chatWrapper.classList.add('box-layout');
|
|
51
|
+
url.searchParams.set('boxLayout', 'true');
|
|
52
|
+
}
|
|
53
|
+
window.history.pushState({}, '', url.toString());
|
|
54
|
+
toggleLayoutBtn.textContent = `Box layout${window.location.search.includes('boxLayout=true') ? ' ✓' : ''}`;
|
|
55
|
+
};
|
|
56
|
+
sidebarBottom.appendChild(toggleLayoutBtn);
|
|
57
|
+
|
|
58
|
+
// Add loader toggle button
|
|
59
|
+
const toggleLoaderBtn = document.createElement('button');
|
|
60
|
+
toggleLoaderBtn.textContent = `Custom loader${params.get('customLoader') === 'true' ? ' ✓' : ''}`;
|
|
61
|
+
toggleLoaderBtn.onclick = () => {
|
|
62
|
+
toggleCustomLoader();
|
|
63
|
+
toggleLoaderBtn.textContent = `Custom loader${window.location.search.includes('customLoader=true') ? ' ✓' : ''}`;
|
|
64
|
+
};
|
|
65
|
+
sidebarBottom.appendChild(toggleLoaderBtn);
|
|
42
66
|
|
|
43
67
|
// Add language toggle buttons
|
|
44
68
|
const langContainer = document.createElement('div');
|
|
@@ -69,7 +93,6 @@
|
|
|
69
93
|
function setOrg(org) {
|
|
70
94
|
chat?.remove();
|
|
71
95
|
|
|
72
|
-
const params = new URLSearchParams(window.location.search);
|
|
73
96
|
const forceLang = params.get('lang');
|
|
74
97
|
|
|
75
98
|
chat = document.createElement('liipgpt-chat');
|
|
@@ -78,6 +101,11 @@
|
|
|
78
101
|
chat.setAttribute('apiUrl', 'https://liipgpt.api.dev.genai.liip.ch/liipgpt');
|
|
79
102
|
chat.setAttribute('apiKey', 'X9hL4Gp5W2D7eRtF');
|
|
80
103
|
chat.setAttribute('lang', forceLang);
|
|
104
|
+
if (org === 'liipgpt') {
|
|
105
|
+
chat.setAttribute('loaderBackground', 'linear-gradient(0deg, #1B181E 0%, #2A2440 90%)');
|
|
106
|
+
chat.setAttribute('loaderColor', '#9C92EE');
|
|
107
|
+
}
|
|
108
|
+
|
|
81
109
|
document.getElementById('chat-wrapper').appendChild(chat);
|
|
82
110
|
|
|
83
111
|
const url = new URL(window.location.href);
|
|
@@ -85,8 +113,51 @@
|
|
|
85
113
|
window.history.pushState({}, '', url.toString());
|
|
86
114
|
}
|
|
87
115
|
|
|
88
|
-
|
|
116
|
+
function toggleCustomLoader() {
|
|
117
|
+
const chat = document.getElementById('chat');
|
|
118
|
+
const existingLoader = chat.querySelector('[slot="loader"]');
|
|
119
|
+
const url = new URL(window.location.href);
|
|
120
|
+
|
|
121
|
+
if (existingLoader) {
|
|
122
|
+
existingLoader.remove();
|
|
123
|
+
url.searchParams.delete('customLoader');
|
|
124
|
+
} else {
|
|
125
|
+
const loader = document.createElement('div');
|
|
126
|
+
loader.setAttribute('slot', 'loader');
|
|
127
|
+
loader.style.cssText =
|
|
128
|
+
'display: flex; flex-direction: column; gap:8px; justify-content: center; align-items: center; width: 100%; height: 100%; background: linear-gradient(0deg, #1B181E 0%, #2A2440 90%);';
|
|
129
|
+
loader.innerHTML = `
|
|
130
|
+
<svg width="48" height="48" stroke="rgba(127, 127, 127, 0.4)" viewBox="0 0 24 24">
|
|
131
|
+
<g>
|
|
132
|
+
<circle cx="12" cy="12" r="9.5" fill="none" stroke-width="1" stroke-linecap="round">
|
|
133
|
+
<animate attributeName="stroke-dasharray" dur="1.3s" calcMode="spline" values="0 150;42 150;42 150;42 150" keyTimes="0;0.475;0.7;1" keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1" repeatCount="indefinite"/>
|
|
134
|
+
<animate attributeName="stroke-dashoffset" dur="1.3s" calcMode="spline" values="0;-2;-59;-59" keyTimes="0;0.475;0.98;1" keySplines="0.42,0,0.58,1;0.42,0,0.58,1;0.42,0,0.58,1" repeatCount="indefinite"/>
|
|
135
|
+
</circle>
|
|
136
|
+
<animateTransform attributeName="transform" type="rotate" dur="1.6s" values="0 12 12;360 12 12" repeatCount="indefinite"/>
|
|
137
|
+
</g>
|
|
138
|
+
</svg>
|
|
139
|
+
`;
|
|
140
|
+
chat.appendChild(loader);
|
|
141
|
+
url.searchParams.set('customLoader', 'true');
|
|
142
|
+
}
|
|
143
|
+
window.history.pushState({}, '', url.toString());
|
|
144
|
+
}
|
|
145
|
+
|
|
89
146
|
setOrg(params.get('org') || 'liipgpt');
|
|
147
|
+
|
|
148
|
+
// Add this to initialize loader based on URL param
|
|
149
|
+
if (params.get('customLoader') === 'true') {
|
|
150
|
+
toggleCustomLoader();
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Initialize layout based on URL param
|
|
154
|
+
if (params.get('boxLayout') === 'true') {
|
|
155
|
+
document.getElementById('chat-wrapper').classList.add('box-layout');
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (params.get('org') === 'liipgpt') {
|
|
159
|
+
document.documentElement.style.background = 'linear-gradient(0deg, #1B181E 0%, #2A2440 90%)';
|
|
160
|
+
}
|
|
90
161
|
</script>
|
|
91
162
|
|
|
92
163
|
<style>
|
|
@@ -116,7 +187,7 @@
|
|
|
116
187
|
padding: 16px;
|
|
117
188
|
background-color: #f5f5f5;
|
|
118
189
|
border-right: 1px solid #ddd;
|
|
119
|
-
min-width:
|
|
190
|
+
min-width: 180px;
|
|
120
191
|
height: 100vh;
|
|
121
192
|
box-sizing: border-box;
|
|
122
193
|
font-size: 0.8rem;
|
|
@@ -136,7 +207,7 @@
|
|
|
136
207
|
|
|
137
208
|
#sidebar button,
|
|
138
209
|
#sidebar .button {
|
|
139
|
-
padding: 8px
|
|
210
|
+
padding: 8px 12px;
|
|
140
211
|
border: 1px solid #ddd;
|
|
141
212
|
border-radius: 4px;
|
|
142
213
|
background-color: white;
|
|
@@ -165,7 +236,7 @@
|
|
|
165
236
|
right: 40px;
|
|
166
237
|
|
|
167
238
|
border-radius: 10px;
|
|
168
|
-
box-shadow: 0 10px 20px 2px rgba(0, 0, 0, 0.
|
|
239
|
+
box-shadow: 0 10px 20px 2px rgba(0, 0, 0, 0.2);
|
|
169
240
|
}
|
|
170
241
|
</style>
|
|
171
242
|
</body>
|