wingbot 3.71.5 → 3.72.0
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/.babelrc +0 -0
- package/.github/workflows/deploy.yml +2 -2
- package/.github/workflows/pullRequest.yml +2 -2
- package/LICENSE +0 -0
- package/README.md +0 -0
- package/index.js +0 -0
- package/jsconfig.json +0 -0
- package/package.json +1 -1
- package/plugins/ai.wingbot.clearMessageSequences/plugin.js +0 -0
- package/plugins/ai.wingbot.conditionIfGoBackPossible/plugin.js +0 -0
- package/plugins/ai.wingbot.disambiguation/plugin.js +0 -0
- package/plugins/ai.wingbot.goBack/plugin.js +0 -0
- package/plugins/ai.wingbot.goToLastBreadcrumb/plugin.js +0 -0
- package/plugins/ai.wingbot.ifImageDetected/plugin.js +0 -0
- package/plugins/ai.wingbot.ifStickerDetected/plugin.js +0 -0
- package/plugins/ai.wingbot.jumpBack/plugin.js +0 -0
- package/plugins/ai.wingbot.jumpTo/plugin.js +0 -0
- package/plugins/ai.wingbot.keepInInteraction/plugin.js +0 -0
- package/plugins/ai.wingbot.keepInInteractionJustOnce/plugin.js +0 -0
- package/plugins/ai.wingbot.keepPreviousHandlers/plugin.js +0 -0
- package/plugins/ai.wingbot.keepPreviousHandlersJustOnce/plugin.js +0 -0
- package/plugins/ai.wingbot.oneTimeNotificationRequest/plugin.js +0 -0
- package/plugins/ai.wingbot.openai/plugin.js +0 -0
- package/plugins/ai.wingbot.passThreadToBot/plugin.js +0 -0
- package/plugins/ai.wingbot.persona/plugin.js +0 -0
- package/plugins/ai.wingbot.putABreadcrumb/plugin.js +0 -0
- package/plugins/ai.wingbot.regexp/plugin.js +0 -0
- package/plugins/ai.wingbot.setState/plugin.js +0 -0
- package/plugins/ai.wingbot.setStateFromInput/plugin.js +0 -0
- package/plugins/ai.wingbot.slotsContinue/plugin.js +0 -0
- package/plugins/ai.wingbot.slotsRegister/plugin.js +0 -0
- package/plugins/ai.wingbot.stopResponding/plugin.js +0 -0
- package/plugins/ai.wingbot.trackingEvent/plugin.js +0 -0
- package/plugins/ai.wingbot.upload/plugin.js +0 -0
- package/plugins/ai.wingbot.waitASecond/plugin.js +0 -0
- package/plugins/index.js +0 -0
- package/plugins/plugins.json +0 -0
- package/src/Ai.js +44 -3
- package/src/AiMatching.js +66 -40
- package/src/BatchConversationTester.js +0 -0
- package/src/BotApp.js +0 -0
- package/src/BotAppSender.js +0 -0
- package/src/BuildRouter.js +2 -0
- package/src/CallbackAuditLog.js +0 -0
- package/src/ChatGpt.js +0 -0
- package/src/ConversationTester.js +0 -0
- package/src/LLM.js +184 -3
- package/src/LLMMockProvider.js +0 -0
- package/src/LLMSession.js +90 -3
- package/src/MockAiModel.js +0 -0
- package/src/OrchestratorClient.js +0 -0
- package/src/Plugins.js +0 -0
- package/src/Processor.js +1 -1
- package/src/ReducerWrapper.js +0 -0
- package/src/Request.js +0 -0
- package/src/Responder.js +142 -11
- package/src/ReturnSender.js +4 -4
- package/src/Router.js +0 -0
- package/src/RouterWrap.js +0 -0
- package/src/SecurityMiddleware.js +0 -0
- package/src/Tester.js +44 -2
- package/src/analytics/GA4.js +0 -0
- package/src/analytics/consts.js +0 -0
- package/src/analytics/onInteractionHandler.js +0 -0
- package/src/defaultResourceMap.js +0 -0
- package/src/features.js +0 -0
- package/src/flags.js +0 -0
- package/src/fuzzy/factoryFuzzySearch.js +0 -0
- package/src/fuzzy/fuzzyUtils.js +0 -0
- package/src/fuzzy/index.js +0 -0
- package/src/fuzzy/levenshtein.js +0 -0
- package/src/fuzzy/normalize.js +0 -0
- package/src/fuzzy/prepareFuzzyIndex.js +0 -0
- package/src/graphApi/GraphApi.js +0 -0
- package/src/graphApi/WingbotApiConnector.js +0 -0
- package/src/graphApi/apiAuthorizer.js +0 -0
- package/src/graphApi/conversationTestApi.js +0 -0
- package/src/graphApi/conversationsApi.js +0 -0
- package/src/graphApi/index.js +0 -0
- package/src/graphApi/postBackApi.js +0 -0
- package/src/graphApi/schema.gql +0 -0
- package/src/graphApi/validateBotApi.js +0 -0
- package/src/notifications/Notifications.js +0 -0
- package/src/notifications/NotificationsStorage.js +0 -0
- package/src/notifications/api/index.js +0 -0
- package/src/notifications/api/notificationsApiFactory.js +0 -0
- package/src/notifications/index.js +0 -0
- package/src/resolvers/bounce.js +0 -0
- package/src/resolvers/button.js +0 -0
- package/src/resolvers/carousel.js +0 -0
- package/src/resolvers/contextMessage.js +21 -4
- package/src/resolvers/expected.js +0 -0
- package/src/resolvers/expectedInput.js +0 -0
- package/src/resolvers/hbs.js +0 -0
- package/src/resolvers/include.js +0 -0
- package/src/resolvers/index.js +0 -0
- package/src/resolvers/media.js +0 -0
- package/src/resolvers/message.js +54 -4
- package/src/resolvers/passThread.js +0 -0
- package/src/resolvers/path.js +0 -0
- package/src/resolvers/plugin.js +0 -0
- package/src/resolvers/postback.js +0 -0
- package/src/resolvers/resolverTags.js +0 -0
- package/src/resolvers/setState.js +0 -0
- package/src/resolvers/skip.js +0 -0
- package/src/resolvers/subscribtions.js +0 -0
- package/src/resolvers/utils.js +14 -5
- package/src/systemEntities/email.js +0 -0
- package/src/systemEntities/index.js +0 -0
- package/src/systemEntities/phone.js +0 -0
- package/src/systemEntities/regexps.js +0 -0
- package/src/templates/BaseTemplate.js +0 -0
- package/src/templates/ButtonTemplate.js +0 -0
- package/src/templates/GenericTemplate.js +0 -0
- package/src/templates/ListTemplate.js +0 -0
- package/src/templates/ReceiptTemplate.js +0 -0
- package/src/testTools/AnyResponseAssert.js +0 -0
- package/src/testTools/PromptAssert.js +184 -0
- package/src/testTools/ResponseAssert.js +0 -0
- package/src/testTools/asserts.js +42 -4
- package/src/testTools/index.js +0 -0
- package/src/tools/MemoryBotConfigStorage.js +0 -0
- package/src/tools/MemoryChatLogStorage.js +0 -0
- package/src/tools/MemoryStateStorage.js +0 -0
- package/src/tools/bufferloader.js +0 -0
- package/src/tools/index.js +0 -0
- package/src/tools/routeToEvents.js +0 -0
- package/src/transcript/extractText.js +0 -0
- package/src/transcript/textBodyFromTranscript.js +0 -0
- package/src/transcript/transcriptFromHistory.js +0 -0
- package/src/utils/ai.js +0 -0
- package/src/utils/compileWithState.js +0 -0
- package/src/utils/customCondition.js +14 -1
- package/src/utils/customFn.js +0 -0
- package/src/utils/datetime.js +0 -0
- package/src/utils/deepMapTools.js +0 -0
- package/src/utils/generateToken.js +0 -0
- package/src/utils/getCondition.js +16 -4
- package/src/utils/getUpdate.js +4 -4
- package/src/utils/headersToAuditMeta.js +0 -0
- package/src/utils/index.js +0 -0
- package/src/utils/pathUtils.js +0 -0
- package/src/utils/quickReplies.js +0 -0
- package/src/utils/slots.js +0 -0
- package/src/utils/stateData.js +2 -0
- package/src/utils/stateVariables.js +0 -0
- package/src/utils/tokenizer.js +0 -0
- package/src/utils/wrapPluginFunction.js +0 -0
- package/src/wingbot/CachedModel.js +0 -0
- package/src/wingbot/CustomEntityDetectionModel.js +0 -0
- package/src/wingbot/WingbotModel.js +0 -0
- package/src/wingbot/index.js +0 -0
package/src/LLM.js
CHANGED
|
@@ -3,16 +3,72 @@
|
|
|
3
3
|
*/
|
|
4
4
|
'use strict';
|
|
5
5
|
|
|
6
|
+
const { getSetState } = require('./utils/getUpdate');
|
|
6
7
|
const { PHONE_REGEX, EMAIL_REGEX } = require('./systemEntities/regexps');
|
|
8
|
+
const getCondition = require('./utils/getCondition');
|
|
9
|
+
const stateData = require('./utils/stateData');
|
|
10
|
+
const Ai = require('./Ai');
|
|
11
|
+
// const getCondition = require('./utils/getCondition');
|
|
7
12
|
|
|
8
13
|
/** @typedef {import('./Responder')} Responder */
|
|
14
|
+
/** @typedef {import('./AiMatching').PreprocessorOutput} PreprocessorOutput */
|
|
15
|
+
/** @typedef {import('./Request')} Request */
|
|
9
16
|
/** @typedef {import('./Responder').Persona} Persona */
|
|
10
17
|
/** @typedef {import('./Router').BaseConfiguration} BaseConfiguration */
|
|
11
18
|
/** @typedef {import('./LLMSession').LLMMessage<any>} LLMMessage */
|
|
12
19
|
/** @typedef {import('./LLMSession').ToolCall} ToolCall */
|
|
13
20
|
/** @typedef {import('./LLMSession').LLMRole} LLMRole */
|
|
21
|
+
/** @typedef {import('./LLMSession').FilterScope} FilterScope */
|
|
14
22
|
/** @typedef {import('./LLMSession')} LLMSession */
|
|
15
23
|
/** @typedef {import('./transcript/transcriptFromHistory').Transcript} Transcript */
|
|
24
|
+
/** @typedef {import('./utils/getCondition').ConditionDefinition} ConditionDefinition */
|
|
25
|
+
/** @typedef {import('./utils/getCondition').ConditionContext} ConditionContext */
|
|
26
|
+
/** @typedef {import('./utils/stateData').IStateRequest} IStateRequest */
|
|
27
|
+
|
|
28
|
+
/** @typedef {string|'_DISCARD'} EvaluationRuleAction */
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @typedef {object} EvaluationRuleData
|
|
32
|
+
* @prop {EvaluationRuleAction} [action]
|
|
33
|
+
* @prop {object} [setState]
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @typedef {object} RuleDefinitionData
|
|
38
|
+
* @prop {string[]} aiTags
|
|
39
|
+
* @prop {EvaluationRuleAction} [targetRouteId]
|
|
40
|
+
*/
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @typedef {EvaluationRuleData & RuleDefinitionData & ConditionDefinition} EvaluationRule
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @typedef {object} PrepocessedRuleData
|
|
48
|
+
* @prop {Function} condition
|
|
49
|
+
* @prop {PreprocessorOutput} rule
|
|
50
|
+
*/
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @typedef {EvaluationRuleData & PrepocessedRuleData} PreprocessedRule
|
|
54
|
+
*/
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {object} RuleScore
|
|
58
|
+
* @prop {number} score
|
|
59
|
+
*/
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @typedef {RuleScore & PreprocessedRule} RuleWithScore
|
|
63
|
+
*/
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* @typedef {object} EvaluationResult
|
|
67
|
+
* @prop {string} action
|
|
68
|
+
* @prop {boolean} discard
|
|
69
|
+
* @prop {RuleWithScore[]} results
|
|
70
|
+
* @prop {object} setState
|
|
71
|
+
*/
|
|
16
72
|
|
|
17
73
|
/**
|
|
18
74
|
* @callback LLMChatProviderPrompt
|
|
@@ -82,6 +138,13 @@ class LLM {
|
|
|
82
138
|
|
|
83
139
|
static GPT_FLAG = 'gpt';
|
|
84
140
|
|
|
141
|
+
/** @type {FilterScope} */
|
|
142
|
+
static FILTER_SCOPE_CONVERSATION = 'conversation';
|
|
143
|
+
|
|
144
|
+
static EVALUATION_ACTIONS = {
|
|
145
|
+
DISCARD: '_DISCARD'
|
|
146
|
+
};
|
|
147
|
+
|
|
85
148
|
/** @type {AnonymizeRegexp[]} */
|
|
86
149
|
static anonymizeRegexps = [
|
|
87
150
|
{ replacement: '@PHONE', regex: new RegExp(PHONE_REGEX.source, 'g') },
|
|
@@ -91,12 +154,13 @@ class LLM {
|
|
|
91
154
|
/**
|
|
92
155
|
*
|
|
93
156
|
* @param {LLMConfiguration} configuration
|
|
157
|
+
* @param {Ai} ai
|
|
94
158
|
*/
|
|
95
|
-
constructor (configuration) {
|
|
159
|
+
constructor (configuration, ai) {
|
|
96
160
|
const { provider, ...rest } = configuration;
|
|
97
161
|
|
|
98
162
|
this._configuration = {
|
|
99
|
-
transcriptFlag:
|
|
163
|
+
transcriptFlag: null,
|
|
100
164
|
transcriptLength: 5,
|
|
101
165
|
provider: null,
|
|
102
166
|
logger: {
|
|
@@ -107,6 +171,25 @@ class LLM {
|
|
|
107
171
|
|
|
108
172
|
/** @type {LLMChatProvider} */
|
|
109
173
|
this._provider = provider;
|
|
174
|
+
|
|
175
|
+
this._ai = ai;
|
|
176
|
+
|
|
177
|
+
/** @type {LLMMessage} */
|
|
178
|
+
this._lastResult = null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @returns {Ai}
|
|
183
|
+
*/
|
|
184
|
+
get ai () {
|
|
185
|
+
return this._ai;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* @returns {LLMMessage}
|
|
190
|
+
*/
|
|
191
|
+
get lastResult () {
|
|
192
|
+
return this._lastResult;
|
|
110
193
|
}
|
|
111
194
|
|
|
112
195
|
/**
|
|
@@ -148,7 +231,7 @@ class LLM {
|
|
|
148
231
|
...options
|
|
149
232
|
};
|
|
150
233
|
|
|
151
|
-
const prompt = session.toArray();
|
|
234
|
+
const prompt = session.toArray(true);
|
|
152
235
|
const result = await this._provider.requestChat(prompt, opts);
|
|
153
236
|
this._logPrompt(prompt, result);
|
|
154
237
|
return result;
|
|
@@ -160,6 +243,7 @@ class LLM {
|
|
|
160
243
|
* @param {LLMMessage} result
|
|
161
244
|
*/
|
|
162
245
|
_logPrompt (prompt, result) {
|
|
246
|
+
this._lastResult = result;
|
|
163
247
|
this._configuration.logger.logPrompt({
|
|
164
248
|
prompt, result
|
|
165
249
|
});
|
|
@@ -188,6 +272,103 @@ class LLM {
|
|
|
188
272
|
}));
|
|
189
273
|
}
|
|
190
274
|
|
|
275
|
+
/**
|
|
276
|
+
*
|
|
277
|
+
* @param {EvaluationRule[]} rules
|
|
278
|
+
* @param {ConditionContext} [context]
|
|
279
|
+
* @returns {PreprocessedRule[]}
|
|
280
|
+
*/
|
|
281
|
+
static preprocessEvaluationRules (rules, context = {}) {
|
|
282
|
+
const {
|
|
283
|
+
linksMap = new Map(),
|
|
284
|
+
ai = Ai.ai
|
|
285
|
+
} = context;
|
|
286
|
+
|
|
287
|
+
return rules.map((evalRule) => {
|
|
288
|
+
const { aiTags, targetRouteId, ...rest } = evalRule;
|
|
289
|
+
|
|
290
|
+
const condition = getCondition(rest, context);
|
|
291
|
+
const rule = ai.matcher.preprocessRule(aiTags);
|
|
292
|
+
|
|
293
|
+
let { action = null } = evalRule;
|
|
294
|
+
|
|
295
|
+
if (!action && targetRouteId && linksMap.has(targetRouteId)) {
|
|
296
|
+
action = linksMap.get(targetRouteId);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
return {
|
|
300
|
+
...rest,
|
|
301
|
+
condition,
|
|
302
|
+
rule
|
|
303
|
+
};
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Returns all actions, which has been recognized
|
|
309
|
+
* with higher score than threshold, but
|
|
310
|
+
*
|
|
311
|
+
* - _DISCARD action discards any other rules (will return all relevant _DISCARD actions)
|
|
312
|
+
* - only the TOP ranked "interaction" action will be returned
|
|
313
|
+
* - actions will come in THE SAME order, so the "setState" will be applied in the same order
|
|
314
|
+
*
|
|
315
|
+
*
|
|
316
|
+
* @param {LLMMessage|string} result
|
|
317
|
+
* @param {PreprocessedRule[]} rules
|
|
318
|
+
* @param {IStateRequest} req
|
|
319
|
+
* @param {Responder} res
|
|
320
|
+
* @returns {Promise<EvaluationResult>}
|
|
321
|
+
*/
|
|
322
|
+
async evaluateResultWithRules (result, rules, req, res) {
|
|
323
|
+
const text = typeof result === 'string' ? result : result.content;
|
|
324
|
+
const nlpResult = await this._ai.queryModel(text, req);
|
|
325
|
+
const state = stateData(req, res);
|
|
326
|
+
|
|
327
|
+
let topRankedAction = null;
|
|
328
|
+
let topActionScore = 0;
|
|
329
|
+
let discard = false;
|
|
330
|
+
const setState = {};
|
|
331
|
+
|
|
332
|
+
const sAct = Object.values(LLM.EVALUATION_ACTIONS);
|
|
333
|
+
|
|
334
|
+
const results = rules
|
|
335
|
+
.filter((rule) => rule.condition(req, res))
|
|
336
|
+
.map((rule) => {
|
|
337
|
+
const matched = this._ai.matcher
|
|
338
|
+
.matchText(text, rule.rule, nlpResult, state);
|
|
339
|
+
|
|
340
|
+
if (!matched || matched.score < this._ai.threshold) {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (rule.action === LLM.EVALUATION_ACTIONS.DISCARD) {
|
|
345
|
+
discard = true;
|
|
346
|
+
} else if (rule.action && topActionScore < matched.score) {
|
|
347
|
+
topRankedAction = rule.action;
|
|
348
|
+
topActionScore = matched.score;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
return {
|
|
352
|
+
...rule,
|
|
353
|
+
score: matched.score
|
|
354
|
+
};
|
|
355
|
+
})
|
|
356
|
+
.filter((rule) => rule !== null
|
|
357
|
+
&& (!discard || rule.action === LLM.EVALUATION_ACTIONS.DISCARD)
|
|
358
|
+
&& (!rule.action || rule.action === topRankedAction || sAct.includes(rule.action)));
|
|
359
|
+
|
|
360
|
+
results.forEach((rule) => {
|
|
361
|
+
Object.assign(setState, getSetState(rule.setState, req, res, setState));
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
setState,
|
|
366
|
+
results,
|
|
367
|
+
discard,
|
|
368
|
+
action: discard ? null : topRankedAction
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
191
372
|
}
|
|
192
373
|
|
|
193
374
|
module.exports = LLM;
|
package/src/LLMMockProvider.js
CHANGED
|
File without changes
|
package/src/LLMSession.js
CHANGED
|
@@ -13,6 +13,8 @@ const LLM = require('./LLM');
|
|
|
13
13
|
/** @typedef {'tool'} LLMToolRole */
|
|
14
14
|
/** @typedef {LLMChatRole|LLMSystemRole|LLMToolRole|string} LLMRole */
|
|
15
15
|
|
|
16
|
+
/** @typedef {LLMRole|'conversation'} FilterScope */
|
|
17
|
+
|
|
16
18
|
/** @typedef {'stop'|'length'|'tool_calls'|'content_filter'} LLMFinishReason */
|
|
17
19
|
|
|
18
20
|
/**
|
|
@@ -38,6 +40,19 @@ const LLM = require('./LLM');
|
|
|
38
40
|
* @param {QuickReply[]} quickReplies
|
|
39
41
|
*/
|
|
40
42
|
|
|
43
|
+
/**
|
|
44
|
+
* @callback LLMFilterFn
|
|
45
|
+
* @param {string} text
|
|
46
|
+
* @param {LLMRole} role
|
|
47
|
+
* @returns {boolean|string}
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @typedef {object} LLMFilter
|
|
52
|
+
* @prop {LLMFilterFn} filter
|
|
53
|
+
* @prop {FilterScope} scope
|
|
54
|
+
*/
|
|
55
|
+
|
|
41
56
|
/**
|
|
42
57
|
* @class LLMSession
|
|
43
58
|
*/
|
|
@@ -48,8 +63,9 @@ class LLMSession {
|
|
|
48
63
|
* @param {LLM} llm
|
|
49
64
|
* @param {LLMMessage<any>[]} [chat]
|
|
50
65
|
* @param {SendCallback} [onSend]
|
|
66
|
+
* @param {LLMFilter[]} [filters=[]]
|
|
51
67
|
*/
|
|
52
|
-
constructor (llm, chat = [], onSend = () => {}) {
|
|
68
|
+
constructor (llm, chat = [], onSend = () => {}, filters = []) {
|
|
53
69
|
this._llm = llm;
|
|
54
70
|
|
|
55
71
|
this._onSend = onSend;
|
|
@@ -60,6 +76,13 @@ class LLMSession {
|
|
|
60
76
|
this._generatedIndex = null;
|
|
61
77
|
|
|
62
78
|
this._sort();
|
|
79
|
+
|
|
80
|
+
/** @type {LLMFilter[]} */
|
|
81
|
+
this._filters = filters;
|
|
82
|
+
|
|
83
|
+
this._SCOPE_CONVERSATION_ROLES = [
|
|
84
|
+
LLM.ROLE_ASSISTANT, LLM.ROLE_USER
|
|
85
|
+
];
|
|
63
86
|
}
|
|
64
87
|
|
|
65
88
|
_sort (what = this._chat) {
|
|
@@ -114,10 +137,43 @@ class LLMSession {
|
|
|
114
137
|
}
|
|
115
138
|
|
|
116
139
|
/**
|
|
140
|
+
*
|
|
141
|
+
* @param {boolean} [filtered=false]
|
|
117
142
|
* @returns {LLMMessage[]}
|
|
118
143
|
*/
|
|
119
|
-
toArray () {
|
|
120
|
-
|
|
144
|
+
toArray (filtered = false) {
|
|
145
|
+
const messages = this._mergeSystem();
|
|
146
|
+
if (!filtered || this._filters.length === 0) {
|
|
147
|
+
return messages;
|
|
148
|
+
}
|
|
149
|
+
return messages
|
|
150
|
+
.map((message) => {
|
|
151
|
+
if (!message.content) {
|
|
152
|
+
return message;
|
|
153
|
+
}
|
|
154
|
+
const content = this._filters.reduce((text, filter) => {
|
|
155
|
+
if (!text) {
|
|
156
|
+
return text;
|
|
157
|
+
}
|
|
158
|
+
if (filter.scope !== message.role
|
|
159
|
+
&& (filter.scope !== LLM.FILTER_SCOPE_CONVERSATION
|
|
160
|
+
|| !this._SCOPE_CONVERSATION_ROLES.includes(message.role))) {
|
|
161
|
+
return text;
|
|
162
|
+
}
|
|
163
|
+
const res = filter.filter(text, message.role);
|
|
164
|
+
return res === true ? text : res;
|
|
165
|
+
}, message.content);
|
|
166
|
+
|
|
167
|
+
if (!content) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
...message,
|
|
173
|
+
content
|
|
174
|
+
};
|
|
175
|
+
})
|
|
176
|
+
.filter((message) => message !== null);
|
|
121
177
|
}
|
|
122
178
|
|
|
123
179
|
/**
|
|
@@ -200,6 +256,20 @@ class LLMSession {
|
|
|
200
256
|
return this;
|
|
201
257
|
}
|
|
202
258
|
|
|
259
|
+
/**
|
|
260
|
+
*
|
|
261
|
+
* @param {LLMFilter|LLMFilter[]} filter
|
|
262
|
+
* @returns {this}
|
|
263
|
+
*/
|
|
264
|
+
addFilter (filter) {
|
|
265
|
+
if (Array.isArray(filter)) {
|
|
266
|
+
this._filters.push(...filter);
|
|
267
|
+
} else {
|
|
268
|
+
this._filters.push(filter);
|
|
269
|
+
}
|
|
270
|
+
return this;
|
|
271
|
+
}
|
|
272
|
+
|
|
203
273
|
/**
|
|
204
274
|
*
|
|
205
275
|
* @param {LLMProviderOptions} [options={}]
|
|
@@ -214,6 +284,23 @@ class LLMSession {
|
|
|
214
284
|
return result;
|
|
215
285
|
}
|
|
216
286
|
|
|
287
|
+
/**
|
|
288
|
+
*
|
|
289
|
+
* @returns {string}
|
|
290
|
+
*/
|
|
291
|
+
lastResponse () {
|
|
292
|
+
const messages = [];
|
|
293
|
+
for (let i = this._chat.length - 1; i >= 0; i--) {
|
|
294
|
+
const message = this._chat[i];
|
|
295
|
+
|
|
296
|
+
if (message.role !== LLM.ROLE_ASSISTANT || !message.content) {
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
messages.unshift(message.content);
|
|
300
|
+
}
|
|
301
|
+
return messages.join('\n\n');
|
|
302
|
+
}
|
|
303
|
+
|
|
217
304
|
/**
|
|
218
305
|
*
|
|
219
306
|
* @param {boolean} [dontMarkAsSent=false]
|
package/src/MockAiModel.js
CHANGED
|
File without changes
|
|
File without changes
|
package/src/Plugins.js
CHANGED
|
File without changes
|
package/src/Processor.js
CHANGED
|
@@ -416,7 +416,7 @@ class Processor extends EventEmitter {
|
|
|
416
416
|
});
|
|
417
417
|
}
|
|
418
418
|
|
|
419
|
-
const llm = new LLM(llmOptions);
|
|
419
|
+
const llm = new LLM(llmOptions, Ai.ai);
|
|
420
420
|
|
|
421
421
|
const result = await this
|
|
422
422
|
._dispatch(message, pageId, messageSender, responderData, preloadPromise, llm);
|
package/src/ReducerWrapper.js
CHANGED
|
File without changes
|
package/src/Request.js
CHANGED
|
File without changes
|
package/src/Responder.js
CHANGED
|
@@ -34,7 +34,14 @@ const EXCEPTION_HOPCOUNT_THRESHOLD = 5;
|
|
|
34
34
|
/** @typedef {import('./analytics/consts').TrackingType} TrackingType */
|
|
35
35
|
|
|
36
36
|
/** @typedef {import('./LLM').LLMConfiguration} LLMConfiguration */
|
|
37
|
+
/** @typedef {import('./LLM').PreprocessedRule} PreprocessedRule */
|
|
38
|
+
/** @typedef {import('./LLM').EvaluationRuleAction} EvaluationRuleAction */
|
|
39
|
+
/** @typedef {import('./LLM').EvaluationResult} EvaluationResult */
|
|
37
40
|
/** @typedef {import('./LLMSession').LLMMessage} LLMMessage */
|
|
41
|
+
/** @typedef {import('./LLMSession').LLMFilterFn} LLMFilterFn */
|
|
42
|
+
/** @typedef {import('./LLMSession').LLMFilter} LLMFilter */
|
|
43
|
+
/** @typedef {import('./LLMSession').FilterScope} FilterScope */
|
|
44
|
+
/** @typedef {import('./utils/stateData').IStateRequest} IStateRequest */
|
|
38
45
|
|
|
39
46
|
/**
|
|
40
47
|
* @enum {string} ExpectedInput
|
|
@@ -243,6 +250,28 @@ class Responder {
|
|
|
243
250
|
this._llmContext = new Map([
|
|
244
251
|
[this.LLM_CTX_DEFAULT, []]
|
|
245
252
|
]);
|
|
253
|
+
|
|
254
|
+
/** @type {Map<string,PreprocessedRule[]>} */
|
|
255
|
+
this._llmResultRules = new Map([
|
|
256
|
+
[this.LLM_CTX_DEFAULT, []]
|
|
257
|
+
]);
|
|
258
|
+
|
|
259
|
+
/** @type {Map<string,LLMFilter[]>} */
|
|
260
|
+
this._llmFilters = new Map([
|
|
261
|
+
[this.LLM_CTX_DEFAULT, []],
|
|
262
|
+
[null, []]
|
|
263
|
+
]);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
*
|
|
268
|
+
* @deprecated use llmAddInstructions() instead
|
|
269
|
+
* @param {PromptSource} systemPrompt
|
|
270
|
+
* @param {string} [contextType]
|
|
271
|
+
* @returns {this}
|
|
272
|
+
*/
|
|
273
|
+
llmAddSystemPrompt (systemPrompt, contextType) {
|
|
274
|
+
return this.llmAddInstructions(systemPrompt, contextType);
|
|
246
275
|
}
|
|
247
276
|
|
|
248
277
|
/**
|
|
@@ -251,7 +280,7 @@ class Responder {
|
|
|
251
280
|
* @param {string} contextType
|
|
252
281
|
* @returns {this}
|
|
253
282
|
*/
|
|
254
|
-
|
|
283
|
+
llmAddInstructions (systemPrompt, contextType = this.LLM_CTX_DEFAULT) {
|
|
255
284
|
if (!systemPrompt) {
|
|
256
285
|
return this;
|
|
257
286
|
}
|
|
@@ -264,12 +293,109 @@ class Responder {
|
|
|
264
293
|
return this;
|
|
265
294
|
}
|
|
266
295
|
|
|
296
|
+
/**
|
|
297
|
+
*
|
|
298
|
+
* @param {LLMFilter|LLMFilterFn} filter
|
|
299
|
+
* @param {FilterScope} [scope]
|
|
300
|
+
* @param {string} [contextType]
|
|
301
|
+
* @returns {this}
|
|
302
|
+
*/
|
|
303
|
+
llmAddFilter (
|
|
304
|
+
filter,
|
|
305
|
+
scope = LLM.FILTER_SCOPE_CONVERSATION,
|
|
306
|
+
contextType = null
|
|
307
|
+
) {
|
|
308
|
+
/** @type {LLMFilter} */
|
|
309
|
+
const addFilter = typeof filter === 'function'
|
|
310
|
+
? {
|
|
311
|
+
filter,
|
|
312
|
+
scope
|
|
313
|
+
}
|
|
314
|
+
: filter;
|
|
315
|
+
|
|
316
|
+
if (!this._llmFilters.has(contextType)) {
|
|
317
|
+
this._llmFilters.set(contextType, []);
|
|
318
|
+
}
|
|
319
|
+
this._llmFilters.get(contextType).push(addFilter);
|
|
320
|
+
return this;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
*
|
|
325
|
+
* @param {string[]|PreprocessedRule} rule
|
|
326
|
+
* @param {EvaluationRuleAction} [action]
|
|
327
|
+
* @param {object} [setState]
|
|
328
|
+
* @param {string} [contextType]
|
|
329
|
+
* @returns {this}
|
|
330
|
+
*/
|
|
331
|
+
llmAddResultRule (
|
|
332
|
+
rule,
|
|
333
|
+
action = null,
|
|
334
|
+
setState = null,
|
|
335
|
+
contextType = this.LLM_CTX_DEFAULT
|
|
336
|
+
) {
|
|
337
|
+
let addRule = rule;
|
|
338
|
+
|
|
339
|
+
if (Array.isArray(addRule)) {
|
|
340
|
+
[addRule] = LLM.preprocessEvaluationRules([{
|
|
341
|
+
// @ts-ignore
|
|
342
|
+
aiTags: rule,
|
|
343
|
+
action,
|
|
344
|
+
setState
|
|
345
|
+
}], {
|
|
346
|
+
ai: this.llm.ai
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (!this._llmResultRules.has(contextType)) {
|
|
351
|
+
this._llmResultRules.set(contextType, []);
|
|
352
|
+
}
|
|
353
|
+
this._llmResultRules.get(contextType).push(addRule);
|
|
354
|
+
return this;
|
|
355
|
+
}
|
|
356
|
+
|
|
267
357
|
async llmSession (contextType = this.LLM_CTX_DEFAULT) {
|
|
268
358
|
const system = await this._getSystemContentForType(contextType);
|
|
269
359
|
|
|
270
360
|
const chat = system.map((content) => ({ role: LLM.ROLE_SYSTEM, content }));
|
|
271
361
|
|
|
272
|
-
|
|
362
|
+
const filters = this._filtersForContext(contextType);
|
|
363
|
+
return new LLMSession(this.llm, chat, this._llmSend.bind(this), filters);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
*
|
|
368
|
+
* @param {LLMSession} session
|
|
369
|
+
* @param {string} [contextType]
|
|
370
|
+
* @returns {Promise<EvaluationResult>}
|
|
371
|
+
*/
|
|
372
|
+
async llmEvaluate (session, contextType = this.LLM_CTX_DEFAULT) {
|
|
373
|
+
const rules = this._llmResultRules.get(contextType) || [];
|
|
374
|
+
const text = session.lastResponse();
|
|
375
|
+
|
|
376
|
+
if (rules.length === 0 || !text) {
|
|
377
|
+
return {
|
|
378
|
+
action: null,
|
|
379
|
+
setState: {},
|
|
380
|
+
results: [],
|
|
381
|
+
discard: false
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/** @type {IStateRequest} */
|
|
386
|
+
const req = {
|
|
387
|
+
state: this.options.state,
|
|
388
|
+
text: () => text,
|
|
389
|
+
senderId: this._senderId,
|
|
390
|
+
pageId: this._pageId,
|
|
391
|
+
actionData: () => this._data,
|
|
392
|
+
isConfidentInput: () => false
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
const result = await this.llm.evaluateResultWithRules(text, rules, req, this);
|
|
396
|
+
this.setState(result.setState);
|
|
397
|
+
|
|
398
|
+
return result;
|
|
273
399
|
}
|
|
274
400
|
|
|
275
401
|
async _replaceAsync (str, regex, asyncFn) {
|
|
@@ -339,16 +465,20 @@ class Responder {
|
|
|
339
465
|
...LLM.anonymizeTranscript(transcript, transcriptAnonymize)
|
|
340
466
|
];
|
|
341
467
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
transcriptLength,
|
|
346
|
-
transcriptFlag,
|
|
347
|
-
transcriptAnonymize,
|
|
348
|
-
chat
|
|
349
|
-
});
|
|
468
|
+
const filters = this._filtersForContext(contextType);
|
|
469
|
+
return new LLMSession(this.llm, chat, this._llmSend.bind(this), filters);
|
|
470
|
+
}
|
|
350
471
|
|
|
351
|
-
|
|
472
|
+
/**
|
|
473
|
+
*
|
|
474
|
+
* @param {string|null} contextType
|
|
475
|
+
* @returns {LLMFilter[]}
|
|
476
|
+
*/
|
|
477
|
+
_filtersForContext (contextType) {
|
|
478
|
+
return [
|
|
479
|
+
...(this._llmFilters.get(contextType) || []),
|
|
480
|
+
...this._llmFilters.get(null)
|
|
481
|
+
];
|
|
352
482
|
}
|
|
353
483
|
|
|
354
484
|
/**
|
|
@@ -403,6 +533,7 @@ class Responder {
|
|
|
403
533
|
*/
|
|
404
534
|
setFlag (flag) {
|
|
405
535
|
this._senderMeta.flag = flag;
|
|
536
|
+
// @ts-ignore
|
|
406
537
|
return this;
|
|
407
538
|
}
|
|
408
539
|
|
package/src/ReturnSender.js
CHANGED
|
@@ -162,7 +162,7 @@ class ReturnSender {
|
|
|
162
162
|
};
|
|
163
163
|
|
|
164
164
|
/** @type {PromptInfo[]} */
|
|
165
|
-
this.
|
|
165
|
+
this.prompts = [];
|
|
166
166
|
|
|
167
167
|
this._responseTexts = [];
|
|
168
168
|
|
|
@@ -199,7 +199,7 @@ class ReturnSender {
|
|
|
199
199
|
* @param {PromptInfo} promptInfo
|
|
200
200
|
*/
|
|
201
201
|
logPrompt (promptInfo) {
|
|
202
|
-
this.
|
|
202
|
+
this.prompts.push(promptInfo);
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
/**
|
|
@@ -669,7 +669,7 @@ class ReturnSender {
|
|
|
669
669
|
const payload = {};
|
|
670
670
|
const meta = {
|
|
671
671
|
actions: this._visitedInteractions.slice(),
|
|
672
|
-
prompts: this.
|
|
672
|
+
prompts: this.prompts
|
|
673
673
|
};
|
|
674
674
|
|
|
675
675
|
if (req) {
|
|
@@ -697,7 +697,7 @@ class ReturnSender {
|
|
|
697
697
|
_createMeta (req = null, res = null) { // eslint-disable-line no-unused-vars
|
|
698
698
|
const meta = {
|
|
699
699
|
visitedInteractions: this._visitedInteractions.slice(),
|
|
700
|
-
prompts: this.
|
|
700
|
+
prompts: this.prompts
|
|
701
701
|
};
|
|
702
702
|
|
|
703
703
|
if (req) {
|
package/src/Router.js
CHANGED
|
File without changes
|
package/src/RouterWrap.js
CHANGED
|
File without changes
|
|
File without changes
|