@sinequa/assistant 3.7.0 → 3.7.1
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/chat/chat.component.d.ts +81 -1
- package/chat/types.d.ts +70 -9
- package/esm2020/chat/chat.component.mjs +102 -5
- package/esm2020/chat/instance-manager.service.mjs +2 -2
- package/esm2020/chat/types.mjs +12 -6
- package/fesm2015/sinequa-assistant-chat.mjs +114 -10
- package/fesm2015/sinequa-assistant-chat.mjs.map +1 -1
- package/fesm2020/sinequa-assistant-chat.mjs +113 -10
- package/fesm2020/sinequa-assistant-chat.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -66,7 +66,7 @@ class InstanceManagerService {
|
|
|
66
66
|
*/
|
|
67
67
|
getInstance(key) {
|
|
68
68
|
if (!this.checkInstance(key)) {
|
|
69
|
-
throw new Error(`No
|
|
69
|
+
throw new Error(`No assistant instance found for the given key : '${key}'`);
|
|
70
70
|
}
|
|
71
71
|
return this._serviceInstances.get(key);
|
|
72
72
|
}
|
|
@@ -225,10 +225,6 @@ const uiSettingsSchema = z.object({
|
|
|
225
225
|
displaySystemPrompt: z.boolean(),
|
|
226
226
|
displayUserPrompt: z.boolean()
|
|
227
227
|
});
|
|
228
|
-
// Define the Zod representation for the chatStarter object
|
|
229
|
-
const chatStarterSchema = z.object({
|
|
230
|
-
text: z.string()
|
|
231
|
-
});
|
|
232
228
|
// Define the Zod representation for the defaultValues object
|
|
233
229
|
const defaultValuesSchema = z.object({
|
|
234
230
|
service_id: z.string(),
|
|
@@ -244,6 +240,15 @@ const defaultValuesSchema = z.object({
|
|
|
244
240
|
systemPrompt: z.string(),
|
|
245
241
|
userPrompt: z.string()
|
|
246
242
|
});
|
|
243
|
+
// Define the Zod representation for the chatStarter object
|
|
244
|
+
const chatStarterSchema = z.object({
|
|
245
|
+
text: z.string()
|
|
246
|
+
});
|
|
247
|
+
// Define the Zod representation for the action object
|
|
248
|
+
const actionSchema = z.object({
|
|
249
|
+
forcedWorkflow: z.string(),
|
|
250
|
+
forcedWorkflowProperties: z.record(z.unknown()).optional() // forcedWorkflowProperties must be an object (Map equivalent)
|
|
251
|
+
});
|
|
247
252
|
// Define the Zod representation for the modeSettings object
|
|
248
253
|
const initializationSchema = z.object({
|
|
249
254
|
event: z.enum(['Query', 'Prompt']),
|
|
@@ -257,7 +262,8 @@ const modeSettingsSchema = z.object({
|
|
|
257
262
|
enabledUserInput: z.boolean(),
|
|
258
263
|
displayUserPrompt: z.boolean(),
|
|
259
264
|
sendUserPrompt: z.boolean(),
|
|
260
|
-
initialization: initializationSchema
|
|
265
|
+
initialization: initializationSchema,
|
|
266
|
+
actions: z.record(actionSchema).optional()
|
|
261
267
|
}).refine(data => !(data.initialization.chatStarters?.length && (data.sendUserPrompt || data.displayUserPrompt || data.initialization.event === 'Query')), {
|
|
262
268
|
message: "Incompatible configuration for using chatStarters ('sendUserPrompt' and 'displayUserPrompt' must be false, 'initialization.event' must not be 'Query')",
|
|
263
269
|
});
|
|
@@ -2108,7 +2114,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
2108
2114
|
this._actions = [];
|
|
2109
2115
|
this._resetChatAction = new Action({
|
|
2110
2116
|
icon: 'fas fa-sync',
|
|
2111
|
-
title: "Reset
|
|
2117
|
+
title: "Reset assistant",
|
|
2112
2118
|
action: () => this.newChat()
|
|
2113
2119
|
});
|
|
2114
2120
|
this._sub = new Subscription();
|
|
@@ -2177,6 +2183,9 @@ class ChatComponent extends AbstractFacet {
|
|
|
2177
2183
|
this._sub.unsubscribe();
|
|
2178
2184
|
this._dataSubscription?.unsubscribe();
|
|
2179
2185
|
this._reloadSubscription?.unsubscribe();
|
|
2186
|
+
if (this.chatService instanceof WebSocketChatService) {
|
|
2187
|
+
this.chatService.stopConnection();
|
|
2188
|
+
}
|
|
2180
2189
|
}
|
|
2181
2190
|
get isAdmin() {
|
|
2182
2191
|
return this.principalService.principal?.isAdministrator || false;
|
|
@@ -2203,6 +2212,17 @@ class ChatComponent extends AbstractFacet {
|
|
|
2203
2212
|
this.instanceManagerService.storeInstance(this.instanceId, this.chatService);
|
|
2204
2213
|
}
|
|
2205
2214
|
get actions() { return this._actions; }
|
|
2215
|
+
/**
|
|
2216
|
+
* Handles the changes in the chat component.
|
|
2217
|
+
* If the chat service is a WebSocketChatService, it handles the override of the message handlers if they exist.
|
|
2218
|
+
* Initializes the chat with the provided chat messages if they exist, otherwise loads the default chat.
|
|
2219
|
+
* If the chat is initialized, the initialization event is "Query", the query changes, and the queryChangeShouldTriggerReload function is provided,
|
|
2220
|
+
* then the chat should be reloaded if the function returns true. Otherwise, the chat should be reloaded by default.
|
|
2221
|
+
* It takes into account the ongoing streaming process and the ongoing stopping process to trigger that conditionally define the logic
|
|
2222
|
+
* of the reload :
|
|
2223
|
+
* - If the chat is streaming, then stop the generation and wait for the fetch to complete before reloading the chat.
|
|
2224
|
+
* - If the chat is stopping the generation, then wait for the fetch to complete before reloading the chat.
|
|
2225
|
+
*/
|
|
2206
2226
|
_handleChanges() {
|
|
2207
2227
|
const changes = this.changes$.value;
|
|
2208
2228
|
// If the chat service is a WebSocketChatService, handle the override of the message handlers if exists
|
|
@@ -2294,6 +2314,12 @@ class ChatComponent extends AbstractFacet {
|
|
|
2294
2314
|
}
|
|
2295
2315
|
}
|
|
2296
2316
|
}
|
|
2317
|
+
/**
|
|
2318
|
+
* Triggers a reload after the query change.
|
|
2319
|
+
* This method performs the necessary operations to reload the chat after a query change.
|
|
2320
|
+
* It sets the system and user messages, resets the savedChatId, generates a new chatId,
|
|
2321
|
+
* generates a new chat audit event, and handles the query mode.
|
|
2322
|
+
*/
|
|
2297
2323
|
_triggerReloadAfterQueryChange() {
|
|
2298
2324
|
const systemMsg = { role: 'system', content: this.config.defaultValues.systemPrompt, additionalProperties: { display: false } };
|
|
2299
2325
|
const userMsg = { role: 'user', content: ChatService.formatPrompt(this.config.defaultValues.userPrompt, { principal: this.principalService.principal }), additionalProperties: { display: this.config.modeSettings.displayUserPrompt } };
|
|
@@ -2302,18 +2328,37 @@ class ChatComponent extends AbstractFacet {
|
|
|
2302
2328
|
this.chatService.generateAuditEvent('new-chat', { 'configuration': JSON.stringify(this.chatService.chatConfig$.value) }); // Generate a new chat audit event
|
|
2303
2329
|
this._handleQueryMode(systemMsg, userMsg);
|
|
2304
2330
|
}
|
|
2331
|
+
/**
|
|
2332
|
+
* Adds a scroll listener to the message list element.
|
|
2333
|
+
* The listener is triggered when any of the following events occur:
|
|
2334
|
+
* - Loading state changes
|
|
2335
|
+
* - Messages change
|
|
2336
|
+
* - Streaming state changes
|
|
2337
|
+
* - Scroll event occurs on the message list element
|
|
2338
|
+
*
|
|
2339
|
+
* When the listener is triggered, it updates the `isAtBottom` property.
|
|
2340
|
+
*/
|
|
2305
2341
|
_addScrollListener() {
|
|
2306
2342
|
this._sub.add(merge(this.loading$, this.messages$, this.chatService.streaming$, fromEvent(this.messageList.nativeElement, 'scroll')).subscribe(() => {
|
|
2307
2343
|
this.isAtBottom = this._toggleScrollButtonVisibility();
|
|
2308
2344
|
this.cdr.detectChanges();
|
|
2309
2345
|
}));
|
|
2310
2346
|
}
|
|
2347
|
+
/**
|
|
2348
|
+
* Get the model description based on the defaultValues service_id and model_id
|
|
2349
|
+
*/
|
|
2311
2350
|
updateModelDescription() {
|
|
2312
2351
|
this.modelDescription = this.chatService.getModel(this.config.defaultValues.service_id, this.config.defaultValues.model_id);
|
|
2313
2352
|
this.cdr.detectChanges();
|
|
2314
2353
|
}
|
|
2354
|
+
/**
|
|
2355
|
+
* Submits a question from the user.
|
|
2356
|
+
* If the user is editing a previous message, removes all subsequent messages from the chat history.
|
|
2357
|
+
* Triggers the fetch of the answer for the submitted question by calling _fetchAnswer().
|
|
2358
|
+
* Clears the input value in the UI.
|
|
2359
|
+
*/
|
|
2315
2360
|
submitQuestion() {
|
|
2316
|
-
if (this.chatService.streaming$.value) {
|
|
2361
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
2317
2362
|
return;
|
|
2318
2363
|
}
|
|
2319
2364
|
if (this.question.trim() && this.messages$.value && this.chatService.chatHistory) {
|
|
@@ -2337,6 +2382,13 @@ class ChatComponent extends AbstractFacet {
|
|
|
2337
2382
|
this.questionInput.nativeElement.style.height = `auto`;
|
|
2338
2383
|
}
|
|
2339
2384
|
}
|
|
2385
|
+
/**
|
|
2386
|
+
* Triggers the fetch of the answer for the given question and updates the conversation.
|
|
2387
|
+
* Generates an audit event for the user input.
|
|
2388
|
+
*
|
|
2389
|
+
* @param question - The question asked by the user.
|
|
2390
|
+
* @param conversation - The current conversation messages.
|
|
2391
|
+
*/
|
|
2340
2392
|
_fetchAnswer(question, conversation) {
|
|
2341
2393
|
const userMsg = { role: 'user', content: question, additionalProperties: { display: true, isUserInput: true, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
|
|
2342
2394
|
const messages = [...conversation, userMsg];
|
|
@@ -2348,7 +2400,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
2348
2400
|
* Depending on the connection's state :
|
|
2349
2401
|
* - If connected => given a list of messages, the chat endpoint is invoked for a continuation and updates the list of messages accordingly.
|
|
2350
2402
|
* - If any other state => a connection error message is displayed in the chat.
|
|
2351
|
-
* @param messages
|
|
2403
|
+
* @param messages The list of messages to invoke the chat endpoint with
|
|
2352
2404
|
*/
|
|
2353
2405
|
fetch(messages) {
|
|
2354
2406
|
this._updateConnectionStatus();
|
|
@@ -2472,12 +2524,18 @@ class ChatComponent extends AbstractFacet {
|
|
|
2472
2524
|
this.scrollDown();
|
|
2473
2525
|
}
|
|
2474
2526
|
}
|
|
2527
|
+
/**
|
|
2528
|
+
* @returns true if the chat discussion is scrolled down to the bottom, false otherwise
|
|
2529
|
+
*/
|
|
2475
2530
|
_toggleScrollButtonVisibility() {
|
|
2476
2531
|
if (this.messageList?.nativeElement) {
|
|
2477
2532
|
return Math.round(this.messageList?.nativeElement.scrollHeight - this.messageList?.nativeElement.scrollTop - 1) <= this.messageList?.nativeElement.clientHeight;
|
|
2478
2533
|
}
|
|
2479
2534
|
return true;
|
|
2480
2535
|
}
|
|
2536
|
+
/**
|
|
2537
|
+
* Scroll down to the bottom of the chat discussion
|
|
2538
|
+
*/
|
|
2481
2539
|
scrollDown() {
|
|
2482
2540
|
setTimeout(() => {
|
|
2483
2541
|
if (this.messageList?.nativeElement) {
|
|
@@ -2501,6 +2559,30 @@ class ChatComponent extends AbstractFacet {
|
|
|
2501
2559
|
this.chatService.generateAuditEvent('new-chat', { 'configuration': JSON.stringify(this.chatService.chatConfig$.value) }); // Generate a new chat audit event
|
|
2502
2560
|
this.loadDefaultChat(); // Start a new chat
|
|
2503
2561
|
}
|
|
2562
|
+
/**
|
|
2563
|
+
* Attaches the specified document IDs to the assistant.
|
|
2564
|
+
* If the chat is streaming or stopping the generation, the operation is not allowed.
|
|
2565
|
+
* If no document IDs are provided, the operation is not allowed.
|
|
2566
|
+
* If the action for attaching a document is not defined at the application customization level, an error is logged.
|
|
2567
|
+
* @param ids - An array of document IDs to attach.
|
|
2568
|
+
*/
|
|
2569
|
+
attachToChat(ids) {
|
|
2570
|
+
if (!!this.chatService.streaming$.value || !!this.chatService.stoppingGeneration$.value) {
|
|
2571
|
+
return;
|
|
2572
|
+
}
|
|
2573
|
+
if (!ids || ids?.length < 1) {
|
|
2574
|
+
return;
|
|
2575
|
+
}
|
|
2576
|
+
const attachDocAction = this.config.modeSettings.actions?.["attachDocAction"];
|
|
2577
|
+
if (!attachDocAction) {
|
|
2578
|
+
console.error(`No action is defined for attaching a document to the assistant "${this.instanceId}"`);
|
|
2579
|
+
return;
|
|
2580
|
+
}
|
|
2581
|
+
const userMsg = { role: 'user', content: '', additionalProperties: { display: false, isUserInput: false, type: "Action", forcedWorkflow: attachDocAction.forcedWorkflow, forcedWorkflowProperties: { ...(attachDocAction.forcedWorkflowProperties || {}), ids }, additionalWorkflowProperties: this.config.additionalWorkflowProperties } };
|
|
2582
|
+
const messages = [...this.chatService.chatHistory, userMsg];
|
|
2583
|
+
this.messages$.next(messages);
|
|
2584
|
+
this.fetch(messages);
|
|
2585
|
+
}
|
|
2504
2586
|
/**
|
|
2505
2587
|
* Start the default chat with the defaultValues settings
|
|
2506
2588
|
* If the chat is meant to be initialized with event === "Query", the corresponding user query message will be added to the chat history
|
|
@@ -2560,7 +2642,7 @@ class ChatComponent extends AbstractFacet {
|
|
|
2560
2642
|
*/
|
|
2561
2643
|
openChat(messages, savedChatId) {
|
|
2562
2644
|
if (!messages || !Array.isArray(messages)) {
|
|
2563
|
-
console.error('Error occurs while trying to load the
|
|
2645
|
+
console.error('Error occurs while trying to load the discussion. Invalid messages received :', messages);
|
|
2564
2646
|
return;
|
|
2565
2647
|
}
|
|
2566
2648
|
if (savedChatId) {
|
|
@@ -2593,14 +2675,26 @@ class ChatComponent extends AbstractFacet {
|
|
|
2593
2675
|
this.question = '';
|
|
2594
2676
|
this.terminateFetch();
|
|
2595
2677
|
}
|
|
2678
|
+
/**
|
|
2679
|
+
* Fetch and Load the saved chat from the saved chat index.
|
|
2680
|
+
* If the saved chat is found, the chat discussion will be loaded with the provided messages and chatId
|
|
2681
|
+
*/
|
|
2596
2682
|
onLoadChat() {
|
|
2597
2683
|
this.loading$.next(true);
|
|
2598
2684
|
this._sub.add(this.chatService.loadSavedChat$
|
|
2599
2685
|
.pipe(filter(savedChat => !!savedChat), switchMap(savedChat => this.chatService.getSavedChat(savedChat.id)), filter(savedChatHistory => !!savedChatHistory), tap(savedChatHistory => this.openChat(savedChatHistory.history, savedChatHistory.id))).subscribe());
|
|
2600
2686
|
}
|
|
2687
|
+
/**
|
|
2688
|
+
* Stop the generation of the current assistant's answer.
|
|
2689
|
+
* The fetch subscription will be terminated.
|
|
2690
|
+
*/
|
|
2601
2691
|
stopGeneration() {
|
|
2602
2692
|
this.chatService.stopGeneration().subscribe(() => this.terminateFetch());
|
|
2603
2693
|
}
|
|
2694
|
+
/**
|
|
2695
|
+
* Terminate the fetch process by unsubscribing from the data subscription and updating the loading status to false.
|
|
2696
|
+
* Additionally, focus on the chat input if the focusAfterResponse flag is set to true.
|
|
2697
|
+
*/
|
|
2604
2698
|
terminateFetch() {
|
|
2605
2699
|
this._dataSubscription?.unsubscribe();
|
|
2606
2700
|
this._dataSubscription = undefined;
|
|
@@ -2680,6 +2774,10 @@ class ChatComponent extends AbstractFacet {
|
|
|
2680
2774
|
// return the index of the message in the filtered history
|
|
2681
2775
|
return filteredHistory[index - numberOfHiddenMessagesInMessages$BeforeIndex].additionalProperties.rank;
|
|
2682
2776
|
}
|
|
2777
|
+
/**
|
|
2778
|
+
* Handles the key up event for 'Backspace' and 'Enter' keys.
|
|
2779
|
+
* @param event - The keyboard event.
|
|
2780
|
+
*/
|
|
2683
2781
|
onKeyUp(event) {
|
|
2684
2782
|
switch (event.key) {
|
|
2685
2783
|
case 'Backspace':
|
|
@@ -2696,6 +2794,11 @@ class ChatComponent extends AbstractFacet {
|
|
|
2696
2794
|
break;
|
|
2697
2795
|
}
|
|
2698
2796
|
}
|
|
2797
|
+
/**
|
|
2798
|
+
* Calculates and adjusts the height of the question input element based on its content.
|
|
2799
|
+
* If the Enter key is pressed without the Shift key, it prevents the default behavior.
|
|
2800
|
+
* @param event The keyboard event
|
|
2801
|
+
*/
|
|
2699
2802
|
calculateHeight(event) {
|
|
2700
2803
|
if (event?.key === 'Enter' && !event.shiftKey) {
|
|
2701
2804
|
event?.preventDefault();
|