@botpress/zai 1.2.0 → 2.0.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/dist/index.d.ts +19 -10
- package/dist/operations/check.js +7 -3
- package/dist/operations/label.js +21 -3
- package/e2e/data/cache.jsonl +11 -0
- package/package.json +2 -2
- package/src/operations/check.ts +23 -4
- package/src/operations/label.ts +41 -6
package/dist/index.d.ts
CHANGED
|
@@ -33,22 +33,22 @@ declare const GenerationMetadata: _bpinternal_zui.ZodObject<{
|
|
|
33
33
|
input?: number;
|
|
34
34
|
output?: number;
|
|
35
35
|
};
|
|
36
|
+
latency?: number;
|
|
36
37
|
tokens?: {
|
|
37
38
|
input?: number;
|
|
38
39
|
output?: number;
|
|
39
40
|
};
|
|
40
|
-
latency?: number;
|
|
41
41
|
}, {
|
|
42
42
|
model?: string;
|
|
43
43
|
cost?: {
|
|
44
44
|
input?: number;
|
|
45
45
|
output?: number;
|
|
46
46
|
};
|
|
47
|
+
latency?: number;
|
|
47
48
|
tokens?: {
|
|
48
49
|
input?: number;
|
|
49
50
|
output?: number;
|
|
50
51
|
};
|
|
51
|
-
latency?: number;
|
|
52
52
|
}>;
|
|
53
53
|
|
|
54
54
|
type SaveExampleProps<TInput, TOutput> = {
|
|
@@ -113,8 +113,8 @@ declare const ZaiConfig: _bpinternal_zui.ZodObject<{
|
|
|
113
113
|
}>>;
|
|
114
114
|
namespace: _bpinternal_zui.ZodDefault<_bpinternal_zui.ZodString>;
|
|
115
115
|
}, "strip", _bpinternal_zui.ZodTypeAny, {
|
|
116
|
-
userId?: string;
|
|
117
116
|
client?: Cognitive | BotpressClientLike;
|
|
117
|
+
userId?: string;
|
|
118
118
|
modelId?: string;
|
|
119
119
|
activeLearning?: {
|
|
120
120
|
tableName?: string;
|
|
@@ -123,8 +123,8 @@ declare const ZaiConfig: _bpinternal_zui.ZodObject<{
|
|
|
123
123
|
};
|
|
124
124
|
namespace?: string;
|
|
125
125
|
}, {
|
|
126
|
-
userId?: string;
|
|
127
126
|
client?: Cognitive | BotpressClientLike;
|
|
127
|
+
userId?: string;
|
|
128
128
|
modelId?: string;
|
|
129
129
|
activeLearning?: {
|
|
130
130
|
tableName?: string;
|
|
@@ -277,7 +277,12 @@ declare const Options$3: _bpinternal_zui.ZodObject<{
|
|
|
277
277
|
declare module '@botpress/zai' {
|
|
278
278
|
interface Zai {
|
|
279
279
|
/** Checks wether a condition is true or not */
|
|
280
|
-
check(input: unknown, condition: string, options?: Options$3): Promise<
|
|
280
|
+
check(input: unknown, condition: string, options?: Options$3): Promise<{
|
|
281
|
+
/** Whether the condition is true or not */
|
|
282
|
+
value: boolean;
|
|
283
|
+
/** The explanation of the decision */
|
|
284
|
+
explanation: string;
|
|
285
|
+
}>;
|
|
281
286
|
}
|
|
282
287
|
}
|
|
283
288
|
|
|
@@ -289,25 +294,25 @@ declare const Options$2: _bpinternal_zui.ZodObject<{
|
|
|
289
294
|
filter: _bpinternal_zui.ZodBoolean;
|
|
290
295
|
reason: _bpinternal_zui.ZodOptional<_bpinternal_zui.ZodString>;
|
|
291
296
|
}, "strip", _bpinternal_zui.ZodTypeAny, {
|
|
292
|
-
filter?: boolean;
|
|
293
297
|
input?: any;
|
|
298
|
+
filter?: boolean;
|
|
294
299
|
reason?: string;
|
|
295
300
|
}, {
|
|
296
|
-
filter?: boolean;
|
|
297
301
|
input?: any;
|
|
302
|
+
filter?: boolean;
|
|
298
303
|
reason?: string;
|
|
299
304
|
}>, "many">>;
|
|
300
305
|
}, "strip", _bpinternal_zui.ZodTypeAny, {
|
|
301
306
|
examples?: {
|
|
302
|
-
filter?: boolean;
|
|
303
307
|
input?: any;
|
|
308
|
+
filter?: boolean;
|
|
304
309
|
reason?: string;
|
|
305
310
|
}[];
|
|
306
311
|
tokensPerItem?: number;
|
|
307
312
|
}, {
|
|
308
313
|
examples?: {
|
|
309
|
-
filter?: boolean;
|
|
310
314
|
input?: any;
|
|
315
|
+
filter?: boolean;
|
|
311
316
|
reason?: string;
|
|
312
317
|
}[];
|
|
313
318
|
tokensPerItem?: number;
|
|
@@ -410,7 +415,11 @@ declare module '@botpress/zai' {
|
|
|
410
415
|
interface Zai {
|
|
411
416
|
/** Tags the provided input with a list of predefined labels */
|
|
412
417
|
label<T extends string>(input: unknown, labels: Labels<T>, options?: Options<T>): Promise<{
|
|
413
|
-
[K in T]:
|
|
418
|
+
[K in T]: {
|
|
419
|
+
explanation: string;
|
|
420
|
+
value: boolean;
|
|
421
|
+
confidence: number;
|
|
422
|
+
};
|
|
414
423
|
}>;
|
|
415
424
|
}
|
|
416
425
|
}
|
package/dist/operations/check.js
CHANGED
|
@@ -42,7 +42,7 @@ Zai.prototype.check = async function(input, condition, _options) {
|
|
|
42
42
|
}) : [];
|
|
43
43
|
const exactMatch = examples.find((x) => x.key === Key);
|
|
44
44
|
if (exactMatch) {
|
|
45
|
-
return exactMatch.output;
|
|
45
|
+
return { explanation: exactMatch.explanation ?? "", value: exactMatch.output };
|
|
46
46
|
}
|
|
47
47
|
const defaultExamples = [
|
|
48
48
|
{ input: "50 Cent", check: true, reason: "50 Cent is widely recognized as a public personality." },
|
|
@@ -121,6 +121,7 @@ In your "Analysis", please refer to the Expert Examples # to justify your decisi
|
|
|
121
121
|
throw new Error(`The model did not return a valid answer. The response was: ${answer}`);
|
|
122
122
|
}
|
|
123
123
|
let finalAnswer;
|
|
124
|
+
const explanation = answer.replace(TRUE, "").replace(FALSE, "").replace(END, "").replace("Final Answer:", "").replace("Analysis:", "").trim();
|
|
124
125
|
if (hasTrue && hasFalse) {
|
|
125
126
|
finalAnswer = answer.lastIndexOf(TRUE) > answer.lastIndexOf(FALSE);
|
|
126
127
|
} else {
|
|
@@ -146,8 +147,11 @@ In your "Analysis", please refer to the Expert Examples # to justify your decisi
|
|
|
146
147
|
}
|
|
147
148
|
},
|
|
148
149
|
output: finalAnswer,
|
|
149
|
-
explanation
|
|
150
|
+
explanation
|
|
150
151
|
});
|
|
151
152
|
}
|
|
152
|
-
return
|
|
153
|
+
return {
|
|
154
|
+
value: finalAnswer,
|
|
155
|
+
explanation: explanation.trim()
|
|
156
|
+
};
|
|
153
157
|
};
|
package/dist/operations/label.js
CHANGED
|
@@ -55,6 +55,18 @@ const parseLabel = (label) => {
|
|
|
55
55
|
}
|
|
56
56
|
return LABELS.AMBIGUOUS;
|
|
57
57
|
};
|
|
58
|
+
const getConfidence = (label) => {
|
|
59
|
+
switch (label) {
|
|
60
|
+
case LABELS.ABSOLUTELY_NOT:
|
|
61
|
+
case LABELS.ABSOLUTELY_YES:
|
|
62
|
+
return 1;
|
|
63
|
+
case LABELS.PROBABLY_NOT:
|
|
64
|
+
case LABELS.PROBABLY_YES:
|
|
65
|
+
return 0.5;
|
|
66
|
+
default:
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
58
70
|
Zai.prototype.label = async function(input, _labels, _options) {
|
|
59
71
|
const options = Options.parse(_options ?? {});
|
|
60
72
|
const labels = Labels.parse(_labels);
|
|
@@ -76,8 +88,10 @@ Zai.prototype.label = async function(input, _labels, _options) {
|
|
|
76
88
|
const allLabels = await Promise.all(chunks.map((chunk2) => this.label(chunk2, _labels)));
|
|
77
89
|
return allLabels.reduce((acc, x) => {
|
|
78
90
|
Object.keys(x).forEach((key) => {
|
|
79
|
-
if (acc[key] === true) {
|
|
80
|
-
acc[key] =
|
|
91
|
+
if (acc[key]?.value === true) {
|
|
92
|
+
acc[key] = acc[key];
|
|
93
|
+
} else if (x[key]?.value === true) {
|
|
94
|
+
acc[key] = x[key];
|
|
81
95
|
} else {
|
|
82
96
|
acc[key] = acc[key] || x[key];
|
|
83
97
|
}
|
|
@@ -96,7 +110,11 @@ Zai.prototype.label = async function(input, _labels, _options) {
|
|
|
96
110
|
);
|
|
97
111
|
const convertToAnswer = (mapping) => {
|
|
98
112
|
return Object.keys(labels).reduce((acc, key) => {
|
|
99
|
-
acc[key] =
|
|
113
|
+
acc[key] = {
|
|
114
|
+
explanation: mapping[key]?.explanation ?? "",
|
|
115
|
+
value: mapping[key]?.label === LABELS.ABSOLUTELY_YES || mapping[key]?.label === LABELS.PROBABLY_YES,
|
|
116
|
+
confidence: getConfidence(mapping[key]?.label)
|
|
117
|
+
};
|
|
100
118
|
return acc;
|
|
101
119
|
}, {});
|
|
102
120
|
};
|
package/e2e/data/cache.jsonl
CHANGED
|
@@ -105,3 +105,14 @@
|
|
|
105
105
|
{"key":"d01b8e7","value":{"output":{"id":"chatcmpl-B65VO7tHpTROLR2PFoftMZaE5Jfyf","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"■json_start■\n{\n \"name\": \"JAMES BOND\",\n \"movie\": \"CASINO ROYALE\"\n}\n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":405,"inputCost":0.0010125000000000002,"outputTokens":28,"outputCost":0.00028000000000000003},"botpress":{"cost":0.0012925000000000002}},"meta":{"cached":true}}}
|
|
106
106
|
{"key":"138e86b7","value":{"output":{"id":"chatcmpl-B65hlbKAnvuGuGcAhuxPVKnN69Afl","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"■START■Botpress is absolutely fantastic!","index":0,"stopReason":"stop"}],"usage":{"inputTokens":95,"inputCost":0.00023750000000000003,"outputTokens":9,"outputCost":0.00009},"botpress":{"cost":0.00032750000000000005}},"meta":{"cached":false}}}
|
|
107
107
|
{"key":"42e66d0b","value":{"output":{"id":"chatcmpl-B65hq1endvtZB7KVSaoKfBwuS4nve","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"■START■Botpress is absolutely incredible!","index":0,"stopReason":"stop"}],"usage":{"inputTokens":94,"inputCost":0.00023500000000000002,"outputTokens":9,"outputCost":0.00009},"botpress":{"cost":0.00032500000000000004}},"meta":{"cached":false}}}
|
|
108
|
+
{"key":"b24750c2","value":{"output":{"id":"chatcmpl-BReZyP5RHIaBUTjo4gYV6XWN83ZIY","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"■0:false \n■1:true \n■2:false \n■3:true \n■4:false ","index":0,"stopReason":"stop"}],"usage":{"inputTokens":317,"inputCost":0.0007925,"outputTokens":21,"outputCost":0.00021},"botpress":{"cost":0.0010025}},"meta":{"cached":false}}}
|
|
109
|
+
{"key":"3fee982e","value":{"output":{"id":"chatcmpl-BReZz9kGBc2kkqHDppuC1jvef4OXG","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"■json_start■\n{\n \"name\": \"JAMES BOND\",\n \"movie\": \"CASINO ROYALE\"\n}\n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":284,"inputCost":0.00071,"outputTokens":28,"outputCost":0.00028000000000000003},"botpress":{"cost":0.00099}},"meta":{"cached":false}}}
|
|
110
|
+
{"key":"bca8c242","value":{"output":{"id":"chatcmpl-BReZzhBpjrqZc9i3xZQd72soEYjIU","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"Analysis: \"What's up\" is another common informal greeting in English, similar to \"hello!\" from Expert Example #1, as both serve as a way to initiate friendly communication. Since Expert Example #1 regards greetings positively (as shown by the answer being ■TRUE■), \"What's up\" should similarly be evaluated as ■TRUE■.\n\nFinal Answer: ■TRUE■ \n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":309,"inputCost":0.0007725000000000001,"outputTokens":75,"outputCost":0.00075},"botpress":{"cost":0.0015225}},"meta":{"cached":false}}}
|
|
111
|
+
{"key":"c0182ff2","value":{"output":{"id":"chatcmpl-BRea0OnzIAwF7NjYjfNsmF2iYFGBH","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"Based on the condition \"competes with us? (botpress)\", we determine whether each item is a competitor to Botpress (a conversational AI or chatbot-focused platform). Taking this into account:\n\n■0 = Nike → Not a chatbot platform; does not compete → **false** \n■1 = Ada.cx → Conversational AI platform; competes → **true** \n■2 = Adidas → Not a chatbot platform; does not compete → **false** \n■3 = Moveworks → Conversational AI platform; competes → **true** \n■4 = Lululemon → Not a chatbot platform; does not compete → **false**\n\nFinal Output:\n■0:false■1:true■2:false■3:true■4:false","index":0,"stopReason":"stop"}],"usage":{"inputTokens":239,"inputCost":0.0005975,"outputTokens":151,"outputCost":0.00151},"botpress":{"cost":0.0021075}},"meta":{"cached":false}}}
|
|
112
|
+
{"key":"4808af91","value":{"output":{"id":"chatcmpl-BRea4fxYZvzR6j42CL2sifEuppEuR","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"■0:false■1:true■2:false■3:true■4:false","index":0,"stopReason":"stop"}],"usage":{"inputTokens":302,"inputCost":0.000755,"outputTokens":16,"outputCost":0.00016},"botpress":{"cost":0.000915}},"meta":{"cached":false}}}
|
|
113
|
+
{"key":"216f51b3","value":{"output":{"id":"chatcmpl-BRfNoO17sUd83dAozRV4ULSNrL02h","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"Analysis: Referring to Expert Example #1, the phrase \"what is up\" was considered NOT an official greeting. The input \"What's up\" is essentially the same phrase but in contracted form, and therefore should be treated the same way. Based on this, \"What's up\" is also NOT considered an official greeting. \n\nFinal Answer: ■FALSE■ \n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":365,"inputCost":0.0009125000000000001,"outputTokens":73,"outputCost":0.0007300000000000001},"botpress":{"cost":0.0016425000000000003}},"meta":{"cached":false}}}
|
|
114
|
+
{"key":"d275ae64","value":{"output":{"id":"chatcmpl-BRfO9CunJK0edu6QzwK2XSOBqN3Oz","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"Analysis: The phrase \"What's up\" is a common informal greeting, similar in meaning to \"hello.\" Unlike Expert Example #1 (\"wassup\"), which is highly informal slang and not universally considered a proper greeting, \"What's up\" is widely recognized as a greeting, even if informal. Expert Example #2 demonstrates that common greetings such as \"hello\" are considered TRUE, and \"What's up\" functions in a similar way.\n\nFinal Answer: ■TRUE■ \n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":372,"inputCost":0.00093,"outputTokens":93,"outputCost":0.00093},"botpress":{"cost":0.00186}},"meta":{"cached":false}}}
|
|
115
|
+
{"key":"d9ea3351","value":{"output":{"id":"chatcmpl-BRfQe05pFZ6CDcvRz3FulZfaygVRa","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"Analysis: In Expert Example #2, \"what is up\" is explicitly considered NOT an official greeting in the business scenario. The input \"What's up\" is the contraction of \"what is up\" and carries the exact same meaning and usage. Since Expert Example #2 determined \"what is up\" does not qualify as a greeting, the same reasoning applies to \"What's up.\" \n\nFinal Answer: ■FALSE■ \n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":428,"inputCost":0.00107,"outputTokens":84,"outputCost":0.00084},"botpress":{"cost":0.00191}},"meta":{"cached":false}}}
|
|
116
|
+
{"key":"d17ac02e","value":{"output":{"id":"chatcmpl-BRfTPIN75pd3nYzGGyZ7HATPTpJvG","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"Analysis: In Expert Example #1, the phrase \"what is up\" was analyzed and determined to be not considered an official greeting in the given business scenario. Similarly, \"What's up\" is an informal variation of the same phrase and aligns with the analysis in Example #1. Therefore, this input should also be considered not an official greeting based on the provided examples.\n\nFinal Answer: ■FALSE■ \n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":365,"inputCost":0.0009125000000000001,"outputTokens":81,"outputCost":0.0008100000000000001},"botpress":{"cost":0.0017225}},"meta":{"cached":false}}}
|
|
117
|
+
{"key":"ef02ab44","value":{"output":{"id":"chatcmpl-BRfTSdx4wnjMxiOSK0VEXA2YlvT1D","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"Analysis: \"What's up\" is a phrase commonly used as a casual greeting. Referring to Expert Example #1, where \"wassup\" (a slang variant of \"What's up\") was considered not a formal greeting and the condition was deemed false, it would follow that \"What's up,\" while slightly more standard, falls under the same casual category and is not a formal greeting.\n\nFinal Answer: ■FALSE■ \n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":319,"inputCost":0.0007975,"outputTokens":84,"outputCost":0.00084},"botpress":{"cost":0.0016375}},"meta":{"cached":false}}}
|
|
118
|
+
{"key":"e52b868e","value":{"output":{"id":"chatcmpl-BRfYXsEiwHHpIfQOoVTu8r9NCnzWQ","provider":"OpenAI","model":"gpt-4o-2024-11-20","choices":[{"role":"assistant","type":"text","content":"```\n■is_human:【The input refers to a person named Sylvain Perron, who is likely a human being. There is no suggestion otherwise.】:ABSOLUTELY_YES■\n\n■good_person:【The input mentions Sylvain Perron has no criminal record, which may suggest he is a law-abiding person. However, being a \"good person\" encompasses more than not having a criminal record, so the information is insufficient to confirm this.】:AMBIGUOUS■\n\n■bad_person:【The absence of a criminal record might indicate that Sylvain Perron is not a bad person, though this alone is insufficient to make an absolute judgment.】:PROBABLY_NOT■\n\n■canadian:【No explicit information is given about Sylvain Perron's nationality. However, according to Expert Example #1, where all users are assumed to be Canadian given the context, we can lean towards the assumption that Sylvain Perron is Canadian.】:ABSOLUTELY_YES■\n\n■is_french:【Sylvain is a common French name, as noted in Expert Example #1. \"Perron\" is also a French surname, which might suggest a French background. However, no explicit evidence confirms this person is French rather than Canadian with a French name.】:AMBIGUOUS■\n","index":0,"stopReason":"stop"}],"usage":{"inputTokens":1085,"inputCost":0.0027125,"outputTokens":271,"outputCost":0.00271},"botpress":{"cost":0.0054225}},"meta":{"cached":false}}}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@botpress/zai",
|
|
3
3
|
"description": "Zui AI (zai) – An LLM utility library written on top of Zui and the Botpress API",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"author": "",
|
|
24
24
|
"license": "ISC",
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@botpress/cognitive": "
|
|
26
|
+
"@botpress/cognitive": "0.1.16",
|
|
27
27
|
"json5": "^2.2.3",
|
|
28
28
|
"jsonrepair": "^3.10.0",
|
|
29
29
|
"lodash-es": "^4.17.21"
|
package/src/operations/check.ts
CHANGED
|
@@ -19,7 +19,16 @@ const Options = z.object({
|
|
|
19
19
|
declare module '@botpress/zai' {
|
|
20
20
|
interface Zai {
|
|
21
21
|
/** Checks wether a condition is true or not */
|
|
22
|
-
check(
|
|
22
|
+
check(
|
|
23
|
+
input: unknown,
|
|
24
|
+
condition: string,
|
|
25
|
+
options?: Options
|
|
26
|
+
): Promise<{
|
|
27
|
+
/** Whether the condition is true or not */
|
|
28
|
+
value: boolean
|
|
29
|
+
/** The explanation of the decision */
|
|
30
|
+
explanation: string
|
|
31
|
+
}>
|
|
23
32
|
}
|
|
24
33
|
}
|
|
25
34
|
|
|
@@ -67,7 +76,7 @@ Zai.prototype.check = async function (this: Zai, input, condition, _options) {
|
|
|
67
76
|
|
|
68
77
|
const exactMatch = examples.find((x) => x.key === Key)
|
|
69
78
|
if (exactMatch) {
|
|
70
|
-
return exactMatch.output
|
|
79
|
+
return { explanation: exactMatch.explanation ?? '', value: exactMatch.output }
|
|
71
80
|
}
|
|
72
81
|
|
|
73
82
|
const defaultExamples = [
|
|
@@ -165,6 +174,13 @@ In your "Analysis", please refer to the Expert Examples # to justify your decisi
|
|
|
165
174
|
}
|
|
166
175
|
|
|
167
176
|
let finalAnswer: boolean
|
|
177
|
+
const explanation = answer
|
|
178
|
+
.replace(TRUE, '')
|
|
179
|
+
.replace(FALSE, '')
|
|
180
|
+
.replace(END, '')
|
|
181
|
+
.replace('Final Answer:', '')
|
|
182
|
+
.replace('Analysis:', '')
|
|
183
|
+
.trim()
|
|
168
184
|
|
|
169
185
|
if (hasTrue && hasFalse) {
|
|
170
186
|
// If both TRUE and FALSE are present, we need to check which one was answered last
|
|
@@ -193,9 +209,12 @@ In your "Analysis", please refer to the Expert Examples # to justify your decisi
|
|
|
193
209
|
},
|
|
194
210
|
},
|
|
195
211
|
output: finalAnswer,
|
|
196
|
-
explanation
|
|
212
|
+
explanation,
|
|
197
213
|
})
|
|
198
214
|
}
|
|
199
215
|
|
|
200
|
-
return
|
|
216
|
+
return {
|
|
217
|
+
value: finalAnswer,
|
|
218
|
+
explanation: explanation.trim(),
|
|
219
|
+
}
|
|
201
220
|
}
|
package/src/operations/label.ts
CHANGED
|
@@ -14,6 +14,7 @@ const LABELS = {
|
|
|
14
14
|
PROBABLY_YES: 'PROBABLY_YES',
|
|
15
15
|
ABSOLUTELY_YES: 'ABSOLUTELY_YES',
|
|
16
16
|
} as const
|
|
17
|
+
|
|
17
18
|
const ALL_LABELS = Object.values(LABELS).join(' | ')
|
|
18
19
|
|
|
19
20
|
type Example<T extends string> = {
|
|
@@ -78,7 +79,11 @@ declare module '@botpress/zai' {
|
|
|
78
79
|
labels: Labels<T>,
|
|
79
80
|
options?: Options<T>
|
|
80
81
|
): Promise<{
|
|
81
|
-
[K in T]:
|
|
82
|
+
[K in T]: {
|
|
83
|
+
explanation: string
|
|
84
|
+
value: boolean
|
|
85
|
+
confidence: number
|
|
86
|
+
}
|
|
82
87
|
}>
|
|
83
88
|
}
|
|
84
89
|
}
|
|
@@ -100,6 +105,20 @@ const parseLabel = (label: string): Label => {
|
|
|
100
105
|
return LABELS.AMBIGUOUS
|
|
101
106
|
}
|
|
102
107
|
|
|
108
|
+
const getConfidence = (label: Label) => {
|
|
109
|
+
switch (label) {
|
|
110
|
+
case LABELS.ABSOLUTELY_NOT:
|
|
111
|
+
case LABELS.ABSOLUTELY_YES:
|
|
112
|
+
return 1
|
|
113
|
+
|
|
114
|
+
case LABELS.PROBABLY_NOT:
|
|
115
|
+
case LABELS.PROBABLY_YES:
|
|
116
|
+
return 0.5
|
|
117
|
+
default:
|
|
118
|
+
return 0
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
103
122
|
Zai.prototype.label = async function <T extends string>(this: Zai, input, _labels, _options) {
|
|
104
123
|
const options = Options.parse(_options ?? {})
|
|
105
124
|
const labels = Labels.parse(_labels)
|
|
@@ -127,15 +146,21 @@ Zai.prototype.label = async function <T extends string>(this: Zai, input, _label
|
|
|
127
146
|
// Merge all the labels together (those who are true will remain true)
|
|
128
147
|
return allLabels.reduce((acc, x) => {
|
|
129
148
|
Object.keys(x).forEach((key) => {
|
|
130
|
-
if (acc[key] === true) {
|
|
131
|
-
acc[key] =
|
|
149
|
+
if (acc[key]?.value === true) {
|
|
150
|
+
acc[key] = acc[key]
|
|
151
|
+
} else if (x[key]?.value === true) {
|
|
152
|
+
acc[key] = x[key]
|
|
132
153
|
} else {
|
|
133
154
|
acc[key] = acc[key] || x[key]
|
|
134
155
|
}
|
|
135
156
|
})
|
|
136
157
|
return acc
|
|
137
158
|
}, {}) as {
|
|
138
|
-
[K in T]:
|
|
159
|
+
[K in T]: {
|
|
160
|
+
explanation: string
|
|
161
|
+
value: boolean
|
|
162
|
+
confidence: number
|
|
163
|
+
}
|
|
139
164
|
}
|
|
140
165
|
}
|
|
141
166
|
|
|
@@ -152,9 +177,19 @@ Zai.prototype.label = async function <T extends string>(this: Zai, input, _label
|
|
|
152
177
|
|
|
153
178
|
const convertToAnswer = (mapping: { [K in T]: { explanation: string; label: Label } }) => {
|
|
154
179
|
return Object.keys(labels).reduce((acc, key) => {
|
|
155
|
-
acc[key] =
|
|
180
|
+
acc[key] = {
|
|
181
|
+
explanation: mapping[key]?.explanation ?? '',
|
|
182
|
+
value: mapping[key]?.label === LABELS.ABSOLUTELY_YES || mapping[key]?.label === LABELS.PROBABLY_YES,
|
|
183
|
+
confidence: getConfidence(mapping[key]?.label),
|
|
184
|
+
}
|
|
156
185
|
return acc
|
|
157
|
-
}, {}) as {
|
|
186
|
+
}, {}) as {
|
|
187
|
+
[K in T]: {
|
|
188
|
+
explanation: string
|
|
189
|
+
value: boolean
|
|
190
|
+
confidence: number
|
|
191
|
+
}
|
|
192
|
+
}
|
|
158
193
|
}
|
|
159
194
|
|
|
160
195
|
const examples = taskId
|