@botpress/zai 1.0.1 → 1.2.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.
Files changed (45) hide show
  1. package/README.md +1 -1
  2. package/build.ts +9 -0
  3. package/dist/adapters/adapter.js +2 -0
  4. package/dist/adapters/botpress-table.js +168 -0
  5. package/dist/adapters/memory.js +12 -0
  6. package/dist/index.d.ts +111 -609
  7. package/dist/index.js +9 -1873
  8. package/dist/operations/check.js +153 -0
  9. package/dist/operations/constants.js +2 -0
  10. package/dist/operations/errors.js +15 -0
  11. package/dist/operations/extract.js +232 -0
  12. package/dist/operations/filter.js +191 -0
  13. package/dist/operations/label.js +249 -0
  14. package/dist/operations/rewrite.js +123 -0
  15. package/dist/operations/summarize.js +133 -0
  16. package/dist/operations/text.js +47 -0
  17. package/dist/utils.js +37 -0
  18. package/dist/zai.js +100 -0
  19. package/e2e/data/botpress_docs.txt +26040 -0
  20. package/e2e/data/cache.jsonl +107 -0
  21. package/e2e/utils.ts +89 -0
  22. package/package.json +33 -29
  23. package/src/adapters/adapter.ts +35 -0
  24. package/src/adapters/botpress-table.ts +210 -0
  25. package/src/adapters/memory.ts +13 -0
  26. package/src/index.ts +11 -0
  27. package/src/operations/check.ts +201 -0
  28. package/src/operations/constants.ts +2 -0
  29. package/src/operations/errors.ts +9 -0
  30. package/src/operations/extract.ts +309 -0
  31. package/src/operations/filter.ts +244 -0
  32. package/src/operations/label.ts +345 -0
  33. package/src/operations/rewrite.ts +161 -0
  34. package/src/operations/summarize.ts +195 -0
  35. package/src/operations/text.ts +65 -0
  36. package/src/utils.ts +52 -0
  37. package/src/zai.ts +147 -0
  38. package/tsconfig.json +3 -23
  39. package/dist/index.cjs +0 -1903
  40. package/dist/index.cjs.map +0 -1
  41. package/dist/index.d.cts +0 -916
  42. package/dist/index.js.map +0 -1
  43. package/tsup.config.ts +0 -16
  44. package/vitest.config.ts +0 -9
  45. package/vitest.setup.ts +0 -24
package/dist/index.js CHANGED
@@ -1,1873 +1,9 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
-
4
- // src/zai.ts
5
- import sdk3 from "@botpress/sdk";
6
- import { getWasmTokenizer } from "@botpress/wasm";
7
-
8
- // src/adapters/botpress-table.ts
9
- import sdk2 from "@botpress/sdk";
10
-
11
- // src/utils.ts
12
- import sdk from "@botpress/sdk";
13
- var { z } = sdk;
14
- var stringify = /* @__PURE__ */ __name((input, beautify = true) => {
15
- return typeof input === "string" && !!input.length ? input : input ? JSON.stringify(input, beautify ? null : void 0, beautify ? 2 : void 0) : "<input is null, false, undefined or empty>";
16
- }, "stringify");
17
- var BotpressClient = z.custom(
18
- (value) => typeof value === "object" && value !== null && "callAction" in value && typeof value.callAction === "function",
19
- {
20
- message: "Invalid Botpress Client. Make sure to pass an instance of @botpress/client"
21
- }
22
- );
23
- function fastHash(str) {
24
- let hash = 0;
25
- for (let i = 0; i < str.length; i++) {
26
- hash = (hash << 5) - hash + str.charCodeAt(i);
27
- hash |= 0;
28
- }
29
- return (hash >>> 0).toString(16);
30
- }
31
- __name(fastHash, "fastHash");
32
- var takeUntilTokens = /* @__PURE__ */ __name((arr, tokens, count) => {
33
- const result = [];
34
- let total = 0;
35
- for (const value of arr) {
36
- const valueTokens = count(value);
37
- if (total + valueTokens > tokens) {
38
- break;
39
- }
40
- total += valueTokens;
41
- result.push(value);
42
- }
43
- return result;
44
- }, "takeUntilTokens");
45
- var GenerationMetadata = z.object({
46
- model: z.string(),
47
- cost: z.object({
48
- input: z.number(),
49
- output: z.number()
50
- }).describe("Cost in $USD"),
51
- latency: z.number().describe("Latency in milliseconds"),
52
- tokens: z.object({
53
- input: z.number(),
54
- output: z.number()
55
- }).describe("Number of tokens used")
56
- });
57
-
58
- // src/adapters/adapter.ts
59
- var Adapter = class {
60
- static {
61
- __name(this, "Adapter");
62
- }
63
- };
64
-
65
- // src/adapters/botpress-table.ts
66
- var { z: z2 } = sdk2;
67
- var CRITICAL_TAGS = {
68
- system: "true",
69
- "schema-purpose": "active-learning",
70
- "schema-version": "Oct-2024"
71
- };
72
- var OPTIONAL_TAGS = {
73
- "x-studio-title": "Active Learning",
74
- "x-studio-description": "Table for storing active learning tasks and examples",
75
- "x-studio-readonly": "true",
76
- "x-studio-icon": "lucide://atom",
77
- "x-studio-color": "green"
78
- };
79
- var FACTOR = 30;
80
- var Props = z2.object({
81
- client: BotpressClient,
82
- tableName: z2.string().regex(
83
- /^[a-zA-Z0-9_]{1,45}Table$/,
84
- "Table name must be lowercase and contain only letters, numbers and underscores"
85
- )
86
- });
87
- var TableSchema = z2.object({
88
- taskType: z2.string().describe("The type of the task (filter, extract, etc.)"),
89
- taskId: z2.string(),
90
- key: z2.string().describe("A unique key for the task (e.g. a hash of the input, taskId, taskType and instructions)"),
91
- instructions: z2.string(),
92
- input: z2.object({}).passthrough().describe("The input to the task"),
93
- output: z2.object({}).passthrough().describe("The expected output"),
94
- explanation: z2.string().nullable(),
95
- metadata: GenerationMetadata,
96
- status: z2.enum(["pending", "rejected", "approved"]),
97
- feedback: z2.object({
98
- rating: z2.enum(["very-bad", "bad", "good", "very-good"]),
99
- comment: z2.string().nullable()
100
- }).nullable().default(null)
101
- });
102
- var searchableColumns = ["input"];
103
- var TableJsonSchema = Object.entries(TableSchema.shape).reduce((acc, [key, value]) => {
104
- acc[key] = value.toJsonSchema();
105
- acc[key]["x-zui"] ??= {};
106
- acc[key]["x-zui"].searchable = searchableColumns.includes(key);
107
- return acc;
108
- }, {});
109
- var TableAdapter = class extends Adapter {
110
- static {
111
- __name(this, "TableAdapter");
112
- }
113
- client;
114
- tableName;
115
- status;
116
- errors = [];
117
- constructor(props) {
118
- super();
119
- props = Props.parse(props);
120
- this.client = props.client;
121
- this.tableName = props.tableName;
122
- this.status = "ready";
123
- }
124
- async getExamples({ taskType, taskId, input }) {
125
- await this.assertTableExists();
126
- const { rows } = await this.client.findTableRows({
127
- table: this.tableName,
128
- search: JSON.stringify({ value: input }).substring(0, 1023),
129
- // Search is limited to 1024 characters
130
- limit: 10,
131
- // TODO
132
- filter: {
133
- // Proximity match of approved examples
134
- taskType,
135
- taskId,
136
- status: "approved"
137
- }
138
- }).catch((err) => {
139
- console.error(`Error fetching examples: ${err.message}`);
140
- return { rows: [] };
141
- });
142
- return rows.map((row) => ({
143
- key: row.key,
144
- input: row.input.value,
145
- output: row.output.value,
146
- explanation: row.explanation,
147
- similarity: row.similarity ?? 0
148
- }));
149
- }
150
- async saveExample({
151
- key,
152
- taskType,
153
- taskId,
154
- instructions,
155
- input,
156
- output,
157
- explanation,
158
- metadata,
159
- status = "pending"
160
- }) {
161
- await this.assertTableExists();
162
- await this.client.upsertTableRows({
163
- table: this.tableName,
164
- keyColumn: "key",
165
- rows: [
166
- {
167
- key,
168
- taskType,
169
- taskId,
170
- instructions,
171
- input: { value: input },
172
- output: { value: output },
173
- explanation: explanation ?? null,
174
- status,
175
- metadata
176
- }
177
- ]
178
- }).catch(() => {
179
- });
180
- }
181
- async assertTableExists() {
182
- if (this.status !== "ready") {
183
- return;
184
- }
185
- const { table, created } = await this.client.getOrCreateTable({
186
- table: this.tableName,
187
- factor: FACTOR,
188
- frozen: true,
189
- isComputeEnabled: false,
190
- tags: {
191
- ...CRITICAL_TAGS,
192
- ...OPTIONAL_TAGS
193
- },
194
- schema: TableJsonSchema
195
- }).catch((err) => {
196
- this.status = "error";
197
- this.errors = [err.message];
198
- return { table: null, created: false };
199
- });
200
- if (!table) {
201
- return;
202
- }
203
- if (!created) {
204
- const issues = [];
205
- if (table.factor !== FACTOR) {
206
- issues.push(`Factor is ${table.factor} instead of ${FACTOR}`);
207
- }
208
- if (table.frozen !== true) {
209
- issues.push("Table is not frozen");
210
- }
211
- for (const [key, value] of Object.entries(CRITICAL_TAGS)) {
212
- if (table.tags?.[key] !== value) {
213
- issues.push(`Tag ${key} is ${table.tags?.[key]} instead of ${value}`);
214
- }
215
- }
216
- for (const key of Object.keys(TableJsonSchema)) {
217
- const column = table.schema?.properties[key];
218
- const expected = TableJsonSchema[key];
219
- if (!column) {
220
- issues.push(`Column ${key} is missing`);
221
- continue;
222
- }
223
- if (column.type !== expected.type) {
224
- issues.push(`Column ${key} has type ${column.type} instead of ${expected.type}`);
225
- }
226
- if (expected["x-zui"].searchable && !column["x-zui"].searchable) {
227
- issues.push(`Column ${key} is not searchable but should be`);
228
- }
229
- }
230
- if (issues.length) {
231
- this.status = "error";
232
- this.errors = issues;
233
- }
234
- }
235
- this.status = "initialized";
236
- }
237
- };
238
-
239
- // src/adapters/memory.ts
240
- var MemoryAdapter = class extends Adapter {
241
- constructor(examples) {
242
- super();
243
- this.examples = examples;
244
- }
245
- static {
246
- __name(this, "MemoryAdapter");
247
- }
248
- async getExamples() {
249
- return this.examples;
250
- }
251
- async saveExample() {
252
- }
253
- };
254
-
255
- // src/models.ts
256
- var Models = [
257
- {
258
- "id": "anthropic__claude-3-haiku-20240307",
259
- "name": "Claude 3 Haiku",
260
- "integration": "anthropic",
261
- "input": {
262
- "maxTokens": 2e5
263
- },
264
- "output": {
265
- "maxTokens": 4096
266
- }
267
- },
268
- {
269
- "id": "anthropic__claude-3-5-sonnet-20240620",
270
- "name": "Claude 3.5 Sonnet",
271
- "integration": "anthropic",
272
- "input": {
273
- "maxTokens": 2e5
274
- },
275
- "output": {
276
- "maxTokens": 4096
277
- }
278
- },
279
- {
280
- "id": "cerebras__llama3.1-70b",
281
- "name": "Llama 3.1 70B",
282
- "integration": "cerebras",
283
- "input": {
284
- "maxTokens": 8192
285
- },
286
- "output": {
287
- "maxTokens": 8192
288
- }
289
- },
290
- {
291
- "id": "cerebras__llama3.1-8b",
292
- "name": "Llama 3.1 8B",
293
- "integration": "cerebras",
294
- "input": {
295
- "maxTokens": 8192
296
- },
297
- "output": {
298
- "maxTokens": 8192
299
- }
300
- },
301
- {
302
- "id": "fireworks-ai__accounts/fireworks/models/deepseek-coder-v2-instruct",
303
- "name": "DeepSeek Coder V2 Instruct",
304
- "integration": "fireworks-ai",
305
- "input": {
306
- "maxTokens": 131072
307
- },
308
- "output": {
309
- "maxTokens": 131072
310
- }
311
- },
312
- {
313
- "id": "fireworks-ai__accounts/fireworks/models/deepseek-coder-v2-lite-instruct",
314
- "name": "DeepSeek Coder V2 Lite",
315
- "integration": "fireworks-ai",
316
- "input": {
317
- "maxTokens": 163840
318
- },
319
- "output": {
320
- "maxTokens": 163840
321
- }
322
- },
323
- {
324
- "id": "fireworks-ai__accounts/fireworks/models/firellava-13b",
325
- "name": "FireLLaVA-13B",
326
- "integration": "fireworks-ai",
327
- "input": {
328
- "maxTokens": 4096
329
- },
330
- "output": {
331
- "maxTokens": 4096
332
- }
333
- },
334
- {
335
- "id": "fireworks-ai__accounts/fireworks/models/firefunction-v2",
336
- "name": "Firefunction V2",
337
- "integration": "fireworks-ai",
338
- "input": {
339
- "maxTokens": 8192
340
- },
341
- "output": {
342
- "maxTokens": 8192
343
- }
344
- },
345
- {
346
- "id": "fireworks-ai__accounts/fireworks/models/gemma2-9b-it",
347
- "name": "Gemma 2 9B Instruct",
348
- "integration": "fireworks-ai",
349
- "input": {
350
- "maxTokens": 8192
351
- },
352
- "output": {
353
- "maxTokens": 8192
354
- }
355
- },
356
- {
357
- "id": "fireworks-ai__accounts/fireworks/models/llama-v3p1-405b-instruct",
358
- "name": "Llama 3.1 405B Instruct",
359
- "integration": "fireworks-ai",
360
- "input": {
361
- "maxTokens": 131072
362
- },
363
- "output": {
364
- "maxTokens": 131072
365
- }
366
- },
367
- {
368
- "id": "fireworks-ai__accounts/fireworks/models/llama-v3p1-70b-instruct",
369
- "name": "Llama 3.1 70B Instruct",
370
- "integration": "fireworks-ai",
371
- "input": {
372
- "maxTokens": 131072
373
- },
374
- "output": {
375
- "maxTokens": 131072
376
- }
377
- },
378
- {
379
- "id": "fireworks-ai__accounts/fireworks/models/llama-v3p1-8b-instruct",
380
- "name": "Llama 3.1 8B Instruct",
381
- "integration": "fireworks-ai",
382
- "input": {
383
- "maxTokens": 131072
384
- },
385
- "output": {
386
- "maxTokens": 131072
387
- }
388
- },
389
- {
390
- "id": "fireworks-ai__accounts/fireworks/models/mixtral-8x22b-instruct",
391
- "name": "Mixtral MoE 8x22B Instruct",
392
- "integration": "fireworks-ai",
393
- "input": {
394
- "maxTokens": 65536
395
- },
396
- "output": {
397
- "maxTokens": 65536
398
- }
399
- },
400
- {
401
- "id": "fireworks-ai__accounts/fireworks/models/mixtral-8x7b-instruct",
402
- "name": "Mixtral MoE 8x7B Instruct",
403
- "integration": "fireworks-ai",
404
- "input": {
405
- "maxTokens": 32768
406
- },
407
- "output": {
408
- "maxTokens": 32768
409
- }
410
- },
411
- {
412
- "id": "fireworks-ai__accounts/fireworks/models/mythomax-l2-13b",
413
- "name": "MythoMax L2 13b",
414
- "integration": "fireworks-ai",
415
- "input": {
416
- "maxTokens": 4096
417
- },
418
- "output": {
419
- "maxTokens": 4096
420
- }
421
- },
422
- {
423
- "id": "fireworks-ai__accounts/fireworks/models/qwen2-72b-instruct",
424
- "name": "Qwen2 72b Instruct",
425
- "integration": "fireworks-ai",
426
- "input": {
427
- "maxTokens": 32768
428
- },
429
- "output": {
430
- "maxTokens": 32768
431
- }
432
- },
433
- {
434
- "id": "groq__gemma2-9b-it",
435
- "name": "Gemma2 9B",
436
- "integration": "groq",
437
- "input": {
438
- "maxTokens": 8192
439
- },
440
- "output": {
441
- "maxTokens": 8192
442
- }
443
- },
444
- {
445
- "id": "groq__llama3-70b-8192",
446
- "name": "LLaMA 3 70B",
447
- "integration": "groq",
448
- "input": {
449
- "maxTokens": 8192
450
- },
451
- "output": {
452
- "maxTokens": 8192
453
- }
454
- },
455
- {
456
- "id": "groq__llama3-8b-8192",
457
- "name": "LLaMA 3 8B",
458
- "integration": "groq",
459
- "input": {
460
- "maxTokens": 8192
461
- },
462
- "output": {
463
- "maxTokens": 8192
464
- }
465
- },
466
- {
467
- "id": "groq__llama-3.1-70b-versatile",
468
- "name": "LLaMA 3.1 70B",
469
- "integration": "groq",
470
- "input": {
471
- "maxTokens": 128e3
472
- },
473
- "output": {
474
- "maxTokens": 8192
475
- }
476
- },
477
- {
478
- "id": "groq__llama-3.1-8b-instant",
479
- "name": "LLaMA 3.1 8B",
480
- "integration": "groq",
481
- "input": {
482
- "maxTokens": 128e3
483
- },
484
- "output": {
485
- "maxTokens": 8192
486
- }
487
- },
488
- {
489
- "id": "groq__llama-3.2-11b-vision-preview",
490
- "name": "LLaMA 3.2 11B Vision",
491
- "integration": "groq",
492
- "input": {
493
- "maxTokens": 128e3
494
- },
495
- "output": {
496
- "maxTokens": 8192
497
- }
498
- },
499
- {
500
- "id": "groq__llama-3.2-1b-preview",
501
- "name": "LLaMA 3.2 1B",
502
- "integration": "groq",
503
- "input": {
504
- "maxTokens": 128e3
505
- },
506
- "output": {
507
- "maxTokens": 8192
508
- }
509
- },
510
- {
511
- "id": "groq__llama-3.2-3b-preview",
512
- "name": "LLaMA 3.2 3B",
513
- "integration": "groq",
514
- "input": {
515
- "maxTokens": 128e3
516
- },
517
- "output": {
518
- "maxTokens": 8192
519
- }
520
- },
521
- {
522
- "id": "groq__llama-3.2-90b-vision-preview",
523
- "name": "LLaMA 3.2 90B Vision",
524
- "integration": "groq",
525
- "input": {
526
- "maxTokens": 128e3
527
- },
528
- "output": {
529
- "maxTokens": 8192
530
- }
531
- },
532
- {
533
- "id": "groq__llama-3.3-70b-versatile",
534
- "name": "LLaMA 3.3 70B",
535
- "integration": "groq",
536
- "input": {
537
- "maxTokens": 128e3
538
- },
539
- "output": {
540
- "maxTokens": 32768
541
- }
542
- },
543
- {
544
- "id": "groq__mixtral-8x7b-32768",
545
- "name": "Mixtral 8x7B",
546
- "integration": "groq",
547
- "input": {
548
- "maxTokens": 32768
549
- },
550
- "output": {
551
- "maxTokens": 32768
552
- }
553
- },
554
- {
555
- "id": "openai__o1-2024-12-17",
556
- "name": "GPT o1",
557
- "integration": "openai",
558
- "input": {
559
- "maxTokens": 2e5
560
- },
561
- "output": {
562
- "maxTokens": 1e5
563
- }
564
- },
565
- {
566
- "id": "openai__o1-mini-2024-09-12",
567
- "name": "GPT o1-mini",
568
- "integration": "openai",
569
- "input": {
570
- "maxTokens": 128e3
571
- },
572
- "output": {
573
- "maxTokens": 65536
574
- }
575
- },
576
- {
577
- "id": "openai__gpt-3.5-turbo-0125",
578
- "name": "GPT-3.5 Turbo",
579
- "integration": "openai",
580
- "input": {
581
- "maxTokens": 128e3
582
- },
583
- "output": {
584
- "maxTokens": 4096
585
- }
586
- },
587
- {
588
- "id": "openai__gpt-4-turbo-2024-04-09",
589
- "name": "GPT-4 Turbo",
590
- "integration": "openai",
591
- "input": {
592
- "maxTokens": 128e3
593
- },
594
- "output": {
595
- "maxTokens": 4096
596
- }
597
- },
598
- {
599
- "id": "openai__gpt-4o-2024-08-06",
600
- "name": "GPT-4o (August 2024)",
601
- "integration": "openai",
602
- "input": {
603
- "maxTokens": 128e3
604
- },
605
- "output": {
606
- "maxTokens": 16384
607
- }
608
- },
609
- {
610
- "id": "openai__gpt-4o-2024-05-13",
611
- "name": "GPT-4o (May 2024)",
612
- "integration": "openai",
613
- "input": {
614
- "maxTokens": 128e3
615
- },
616
- "output": {
617
- "maxTokens": 4096
618
- }
619
- },
620
- {
621
- "id": "openai__gpt-4o-2024-11-20",
622
- "name": "GPT-4o (November 2024)",
623
- "integration": "openai",
624
- "input": {
625
- "maxTokens": 128e3
626
- },
627
- "output": {
628
- "maxTokens": 16384
629
- }
630
- },
631
- {
632
- "id": "openai__gpt-4o-mini-2024-07-18",
633
- "name": "GPT-4o Mini",
634
- "integration": "openai",
635
- "input": {
636
- "maxTokens": 128e3
637
- },
638
- "output": {
639
- "maxTokens": 16384
640
- }
641
- }
642
- ];
643
-
644
- // src/zai.ts
645
- var { z: z3 } = sdk3;
646
- var ActiveLearning = z3.object({
647
- enable: z3.boolean().describe("Whether to enable active learning").default(false),
648
- tableName: z3.string().regex(
649
- /^[A-Za-z0-9_/-]{1,100}Table$/,
650
- "Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes"
651
- ).describe("The name of the table to store active learning tasks").default("ActiveLearningTable"),
652
- taskId: z3.string().regex(
653
- /^[A-Za-z0-9_/-]{1,100}$/,
654
- "Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes"
655
- ).describe("The ID of the task").default("default")
656
- });
657
- var ZaiConfig = z3.object({
658
- client: BotpressClient,
659
- userId: z3.string().describe("The ID of the user consuming the API").optional(),
660
- retry: z3.object({ maxRetries: z3.number().min(0).max(100) }).default({ maxRetries: 3 }),
661
- modelId: z3.custom(
662
- (value) => {
663
- if (typeof value !== "string" || !value.includes("__")) {
664
- return false;
665
- }
666
- return true;
667
- },
668
- {
669
- message: "Invalid model ID"
670
- }
671
- ).describe("The ID of the model you want to use").default("openai__gpt-4o-mini-2024-07-18"),
672
- activeLearning: ActiveLearning.default({ enable: false }),
673
- namespace: z3.string().regex(
674
- /^[A-Za-z0-9_/-]{1,100}$/,
675
- "Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes"
676
- ).default("zai")
677
- });
678
- var Zai = class _Zai {
679
- static {
680
- __name(this, "Zai");
681
- }
682
- static tokenizer = null;
683
- client;
684
- originalConfig;
685
- userId;
686
- integration;
687
- model;
688
- retry;
689
- Model;
690
- namespace;
691
- adapter;
692
- activeLearning;
693
- constructor(config) {
694
- this.originalConfig = config;
695
- const parsed = ZaiConfig.parse(config);
696
- this.client = parsed.client;
697
- const [integration, modelId] = parsed.modelId.split("__");
698
- if (!integration?.length || !modelId?.length) {
699
- throw new Error(`Invalid model ID: ${parsed.modelId}. Expected format: <integration>__<modelId>`);
700
- }
701
- this.integration = integration;
702
- this.model = modelId;
703
- this.namespace = parsed.namespace;
704
- this.userId = parsed.userId;
705
- this.retry = parsed.retry;
706
- this.Model = Models.find((m) => m.id === parsed.modelId);
707
- this.activeLearning = parsed.activeLearning;
708
- this.adapter = parsed.activeLearning?.enable ? new TableAdapter({ client: this.client, tableName: parsed.activeLearning.tableName }) : new MemoryAdapter([]);
709
- }
710
- /** @internal */
711
- async callModel(props) {
712
- let retries = this.retry.maxRetries;
713
- while (retries-- >= 0) {
714
- try {
715
- return await this._callModel(props);
716
- } catch (e) {
717
- if (retries >= 0) {
718
- await new Promise((resolve) => setTimeout(resolve, 1e3));
719
- } else {
720
- throw new Error("Failed to call model after multiple retries");
721
- }
722
- }
723
- }
724
- throw new Error("Failed to call model after multiple retries");
725
- }
726
- /** @internal */
727
- async _callModel(props) {
728
- let retries = this.retry.maxRetries;
729
- do {
730
- const start = Date.now();
731
- const input = {
732
- messages: [],
733
- temperature: 0,
734
- topP: 1,
735
- model: { id: this.model },
736
- userId: this.userId,
737
- ...props
738
- };
739
- const { output } = await this.client.callAction({
740
- type: `${this.integration}:generateContent`,
741
- input
742
- });
743
- const latency = Date.now() - start;
744
- return {
745
- ...output,
746
- metadata: {
747
- model: this.model,
748
- latency,
749
- cost: { input: output.usage.inputCost, output: output.usage.outputCost },
750
- tokens: { input: output.usage.inputTokens, output: output.usage.outputTokens }
751
- }
752
- };
753
- } while (--retries > 0);
754
- }
755
- async getTokenizer() {
756
- _Zai.tokenizer ??= await (async () => {
757
- while (!getWasmTokenizer) {
758
- await new Promise((resolve) => setTimeout(resolve, 25));
759
- }
760
- return getWasmTokenizer();
761
- })();
762
- return _Zai.tokenizer;
763
- }
764
- get taskId() {
765
- if (!this.activeLearning.enable) {
766
- return void 0;
767
- }
768
- return `${this.namespace}/${this.activeLearning.taskId}`.replace(/\/+/g, "/");
769
- }
770
- with(options) {
771
- return new _Zai({
772
- ...this.originalConfig,
773
- ...options
774
- });
775
- }
776
- learn(taskId) {
777
- return new _Zai({
778
- ...this.originalConfig,
779
- activeLearning: { ...this.activeLearning, taskId, enable: true }
780
- });
781
- }
782
- };
783
-
784
- // src/operations/text.ts
785
- import sdk4 from "@botpress/sdk";
786
- import _ from "lodash";
787
-
788
- // src/operations/constants.ts
789
- var PROMPT_INPUT_BUFFER = 1048;
790
- var PROMPT_OUTPUT_BUFFER = 512;
791
-
792
- // src/operations/text.ts
793
- var { z: z4 } = sdk4;
794
- var Options = z4.object({
795
- length: z4.number().min(1).max(1e5).optional().describe("The maximum number of tokens to generate")
796
- });
797
- Zai.prototype.text = async function(prompt, _options) {
798
- const options = Options.parse(_options ?? {});
799
- const tokenizer = await this.getTokenizer();
800
- prompt = tokenizer.truncate(prompt, Math.max(this.Model.input.maxTokens - PROMPT_INPUT_BUFFER, 100));
801
- if (options.length) {
802
- options.length = Math.min(this.Model.output.maxTokens - PROMPT_OUTPUT_BUFFER, options.length);
803
- }
804
- const instructions = [];
805
- let chart = "";
806
- if (options.length) {
807
- const length = _.clamp(options.length * 0.75, 5, options.length);
808
- instructions.push(`IMPORTANT: Length constraint: ${length} tokens/words`);
809
- instructions.push(`The text must be standalone and complete in less than ${length} tokens/words`);
810
- }
811
- if (options.length && options.length <= 500) {
812
- chart = `
813
- | Tokens | Text Length (approximate) |
814
- |-------------|--------------------------------------|
815
- | < 5 tokens | 1-3 words |
816
- | 5-10 tokens | 3-6 words |
817
- | 10-20 tokens| 6-15 words |
818
- | 20-50 tokens| A short sentence (15-30 words) |
819
- | 50-100 tokens| A medium sentence (30-70 words) |
820
- | 100-200 tokens| A short paragraph (70-150 words) |
821
- | 200-300 tokens| A medium paragraph (150-200 words) |
822
- | 300-500 tokens| A long paragraph (200-300 words) |`.trim();
823
- }
824
- const output = await this.callModel({
825
- systemPrompt: `
826
- Generate a text that fulfills the user prompt below. Answer directly to the prompt, without any acknowledgements or fluff. Also, make sure the text is standalone and complete.
827
- ${instructions.map((x) => `- ${x}`).join("\n")}
828
- ${chart}
829
- `.trim(),
830
- temperature: 0.7,
831
- messages: [{ type: "text", content: prompt, role: "user" }],
832
- maxTokens: options.length
833
- });
834
- return output?.choices?.[0]?.content;
835
- };
836
-
837
- // src/operations/rewrite.ts
838
- import sdk5 from "@botpress/sdk";
839
- var { z: z5 } = sdk5;
840
- var Example = z5.object({
841
- input: z5.string(),
842
- output: z5.string()
843
- });
844
- var Options2 = z5.object({
845
- examples: z5.array(Example).default([]),
846
- length: z5.number().min(10).max(16e3).optional().describe("The maximum number of tokens to generate")
847
- });
848
- var START = "\u25A0START\u25A0";
849
- var END = "\u25A0END\u25A0";
850
- Zai.prototype.rewrite = async function(original, prompt, _options) {
851
- const options = Options2.parse(_options ?? {});
852
- const tokenizer = await this.getTokenizer();
853
- const taskId = this.taskId;
854
- const taskType = "zai.rewrite";
855
- const INPUT_COMPONENT_SIZE = Math.max(100, (this.Model.input.maxTokens - PROMPT_INPUT_BUFFER) / 2);
856
- prompt = tokenizer.truncate(prompt, INPUT_COMPONENT_SIZE);
857
- const inputSize = tokenizer.count(original) + tokenizer.count(prompt);
858
- const maxInputSize = this.Model.input.maxTokens - tokenizer.count(prompt) - PROMPT_INPUT_BUFFER;
859
- if (inputSize > maxInputSize) {
860
- throw new Error(
861
- `The input size is ${inputSize} tokens long, which is more than the maximum of ${maxInputSize} tokens for this model (${this.Model.name} = ${this.Model.input.maxTokens} tokens)`
862
- );
863
- }
864
- const instructions = [];
865
- const originalSize = tokenizer.count(original);
866
- if (options.length && originalSize > options.length) {
867
- instructions.push(`The original text is ${originalSize} tokens long \u2013 it should be less than ${options.length}`);
868
- instructions.push(
869
- `The text must be standalone and complete in less than ${options.length} tokens, so it has to be shortened to fit the length as well`
870
- );
871
- }
872
- const format = /* @__PURE__ */ __name((before, prompt2) => {
873
- return `
874
- Prompt: ${prompt2}
875
-
876
- ${START}
877
- ${before}
878
- ${END}
879
- `.trim();
880
- }, "format");
881
- const Key = fastHash(
882
- stringify({
883
- taskId,
884
- taskType,
885
- input: original,
886
- prompt
887
- })
888
- );
889
- const formatExample = /* @__PURE__ */ __name(({ input, output: output2, instructions: instructions2 }) => {
890
- return [
891
- { type: "text", role: "user", content: format(input, instructions2 || prompt) },
892
- { type: "text", role: "assistant", content: `${START}${output2}${END}` }
893
- ];
894
- }, "formatExample");
895
- const defaultExamples = [
896
- { input: "Hello, how are you?", output: "Bonjour, comment \xE7a va?", instructions: "translate to French" },
897
- { input: "1\n2\n3", output: "3\n2\n1", instructions: "reverse the order" }
898
- ];
899
- const tableExamples = taskId ? await this.adapter.getExamples({
900
- input: original,
901
- taskId,
902
- taskType
903
- }) : [];
904
- const exactMatch = tableExamples.find((x) => x.key === Key);
905
- if (exactMatch) {
906
- return exactMatch.output;
907
- }
908
- const savedExamples = [
909
- ...tableExamples.map((x) => ({ input: x.input, output: x.output })),
910
- ...options.examples
911
- ];
912
- const REMAINING_TOKENS = this.Model.input.maxTokens - tokenizer.count(prompt) - PROMPT_INPUT_BUFFER;
913
- const examples = takeUntilTokens(
914
- savedExamples.length ? savedExamples : defaultExamples,
915
- REMAINING_TOKENS,
916
- (el) => tokenizer.count(stringify(el.input)) + tokenizer.count(stringify(el.output))
917
- ).map(formatExample).flat();
918
- const output = await this.callModel({
919
- systemPrompt: `
920
- Rewrite the text between the ${START} and ${END} tags to match the user prompt.
921
- ${instructions.map((x) => `\u2022 ${x}`).join("\n")}
922
- `.trim(),
923
- messages: [...examples, { type: "text", content: format(original, prompt), role: "user" }],
924
- maxTokens: options.length,
925
- stopSequences: [END]
926
- });
927
- let result = output.choices[0]?.content;
928
- if (result.includes(START)) {
929
- result = result.slice(result.indexOf(START) + START.length);
930
- }
931
- if (result.includes(END)) {
932
- result = result.slice(0, result.indexOf(END));
933
- }
934
- if (taskId) {
935
- await this.adapter.saveExample({
936
- key: Key,
937
- metadata: output.metadata,
938
- instructions: prompt,
939
- input: original,
940
- output: result,
941
- taskType,
942
- taskId
943
- });
944
- }
945
- return result;
946
- };
947
-
948
- // src/operations/summarize.ts
949
- import sdk6 from "@botpress/sdk";
950
- import _2 from "lodash";
951
- var { z: z6 } = sdk6;
952
- var Options3 = z6.object({
953
- prompt: z6.string().describe("What should the text be summarized to?").default("New information, concepts and ideas that are deemed important"),
954
- format: z6.string().describe("How to format the example text").default(
955
- "A normal text with multiple sentences and paragraphs. Use markdown to format the text into sections. Use headings, lists, and other markdown features to make the text more readable. Do not include links, images, or other non-text elements."
956
- ),
957
- length: z6.number().min(10).max(1e5).describe("The length of the summary in tokens").default(250),
958
- intermediateFactor: z6.number().min(1).max(10).describe("How many times longer (than final length) are the intermediate summaries generated").default(4),
959
- maxIterations: z6.number().min(1).default(100),
960
- sliding: z6.object({
961
- window: z6.number().min(10).max(1e5),
962
- overlap: z6.number().min(0).max(1e5)
963
- }).describe("Sliding window options").default({ window: 5e4, overlap: 250 })
964
- });
965
- var START2 = "\u25A0START\u25A0";
966
- var END2 = "\u25A0END\u25A0";
967
- Zai.prototype.summarize = async function(original, _options) {
968
- const options = Options3.parse(_options ?? {});
969
- const tokenizer = await this.getTokenizer();
970
- const INPUT_COMPONENT_SIZE = Math.max(100, (this.Model.input.maxTokens - PROMPT_INPUT_BUFFER) / 4);
971
- options.prompt = tokenizer.truncate(options.prompt, INPUT_COMPONENT_SIZE);
972
- options.format = tokenizer.truncate(options.format, INPUT_COMPONENT_SIZE);
973
- const maxOutputSize = this.Model.output.maxTokens - PROMPT_OUTPUT_BUFFER;
974
- if (options.length > maxOutputSize) {
975
- throw new Error(
976
- `The desired output length is ${maxOutputSize} tokens long, which is more than the maximum of ${this.Model.output.maxTokens} tokens for this model (${this.Model.name})`
977
- );
978
- }
979
- options.sliding.window = Math.min(options.sliding.window, this.Model.input.maxTokens - PROMPT_INPUT_BUFFER);
980
- options.sliding.overlap = Math.min(options.sliding.overlap, options.sliding.window - 3 * options.sliding.overlap);
981
- const format = /* @__PURE__ */ __name((summary, newText) => {
982
- return `
983
- ${START2}
984
- ${summary.length ? summary : "<summary still empty>"}
985
- ${END2}
986
-
987
- Please amend the summary between the ${START2} and ${END2} tags to accurately reflect the prompt and the additional text below.
988
-
989
- <|start_new_information|>
990
- ${newText}
991
- <|new_information|>`.trim();
992
- }, "format");
993
- const tokens = tokenizer.split(original);
994
- const parts = Math.ceil(tokens.length / (options.sliding.window - options.sliding.overlap));
995
- let iteration = 0;
996
- const N = 2;
997
- const useMergeSort = parts >= Math.pow(2, N);
998
- const chunkSize = Math.ceil(tokens.length / (parts * N));
999
- if (useMergeSort) {
1000
- const chunks = _2.chunk(tokens, chunkSize).map((x) => x.join(""));
1001
- const allSummaries = await Promise.all(chunks.map((chunk) => this.summarize(chunk, options)));
1002
- return this.summarize(allSummaries.join("\n\n============\n\n"), options);
1003
- }
1004
- const summaries = [];
1005
- let currentSummary = "";
1006
- for (let i = 0; i < tokens.length; i += options.sliding.window) {
1007
- const from = Math.max(0, i - options.sliding.overlap);
1008
- const to = Math.min(tokens.length, i + options.sliding.window + options.sliding.overlap);
1009
- const isFirst = i === 0;
1010
- const isLast = to >= tokens.length;
1011
- const slice = tokens.slice(from, to).join("");
1012
- if (iteration++ >= options.maxIterations) {
1013
- break;
1014
- }
1015
- const instructions = [
1016
- `At each step, you will receive a part of the text to summarize. Make sure to reply with the new summary in the tags ${START2} and ${END2}.`,
1017
- "Summarize the text and make sure that the main points are included.",
1018
- "Ignore any unnecessary details and focus on the main points.",
1019
- "Use short and concise sentences to increase readability and information density.",
1020
- "When looking at the new information, focus on: " + options.prompt
1021
- ];
1022
- if (isFirst) {
1023
- instructions.push(
1024
- "The current summary is empty. You need to generate a summary that covers the main points of the text."
1025
- );
1026
- }
1027
- let generationLength = options.length;
1028
- if (!isLast) {
1029
- generationLength = Math.min(
1030
- tokenizer.count(currentSummary) + options.length * options.intermediateFactor,
1031
- maxOutputSize
1032
- );
1033
- instructions.push(
1034
- "You need to amend the summary to include the new information. Make sure the summary is complete and covers all the main points."
1035
- );
1036
- instructions.push(`The current summary is ${currentSummary.length} tokens long.`);
1037
- instructions.push(`You can amend the summary to be up to ${generationLength} tokens long.`);
1038
- }
1039
- if (isLast) {
1040
- instructions.push(
1041
- "This is the last part you will have to summarize. Make sure the summary is complete and covers all the main points."
1042
- );
1043
- instructions.push(
1044
- `The current summary is ${currentSummary.length} tokens long. You need to make sure it is ${options.length} tokens or less.`
1045
- );
1046
- if (currentSummary.length > options.length) {
1047
- instructions.push(
1048
- `The current summary is already too long, so you need to shorten it to ${options.length} tokens while also including the new information.`
1049
- );
1050
- }
1051
- }
1052
- const output = await this.callModel({
1053
- systemPrompt: `
1054
- You are summarizing a text. The text is split into ${parts} parts, and you are currently working on part ${iteration}.
1055
- At every step, you will receive the current summary and a new part of the text. You need to amend the summary to include the new information (if needed).
1056
- The summary needs to cover the main points of the text and must be concise.
1057
-
1058
- IMPORTANT INSTRUCTIONS:
1059
- ${instructions.map((x) => `- ${x.trim()}`).join("\n")}
1060
-
1061
- FORMAT OF THE SUMMARY:
1062
- ${options.format}
1063
- `.trim(),
1064
- messages: [{ type: "text", content: format(currentSummary, slice), role: "user" }],
1065
- maxTokens: generationLength,
1066
- stopSequences: [END2]
1067
- });
1068
- let result = output?.choices[0]?.content;
1069
- if (result.includes(START2)) {
1070
- result = result.slice(result.indexOf(START2) + START2.length);
1071
- }
1072
- if (result.includes("\u25A0")) {
1073
- result = result.slice(0, result.indexOf("\u25A0"));
1074
- }
1075
- summaries.push(result);
1076
- currentSummary = result;
1077
- }
1078
- return currentSummary.trim();
1079
- };
1080
-
1081
- // src/operations/check.ts
1082
- import sdk7 from "@botpress/sdk";
1083
- var { z: z7 } = sdk7;
1084
- var Example2 = z7.object({
1085
- input: z7.any(),
1086
- check: z7.boolean(),
1087
- reason: z7.string().optional()
1088
- });
1089
- var Options4 = z7.object({
1090
- examples: z7.array(Example2).describe("Examples to check the condition against").default([])
1091
- });
1092
- var TRUE = "\u25A0TRUE\u25A0";
1093
- var FALSE = "\u25A0FALSE\u25A0";
1094
- var END3 = "\u25A0END\u25A0";
1095
- Zai.prototype.check = async function(input, condition, _options) {
1096
- const options = Options4.parse(_options ?? {});
1097
- const tokenizer = await this.getTokenizer();
1098
- const PROMPT_COMPONENT = Math.max(this.Model.input.maxTokens - PROMPT_INPUT_BUFFER, 100);
1099
- const taskId = this.taskId;
1100
- const taskType = "zai.check";
1101
- const PROMPT_TOKENS = {
1102
- INPUT: Math.floor(0.5 * PROMPT_COMPONENT),
1103
- CONDITION: Math.floor(0.2 * PROMPT_COMPONENT)
1104
- };
1105
- const inputAsString = tokenizer.truncate(stringify(input), PROMPT_TOKENS.INPUT);
1106
- condition = tokenizer.truncate(condition, PROMPT_TOKENS.CONDITION);
1107
- const EXAMPLES_TOKENS = PROMPT_COMPONENT - tokenizer.count(inputAsString) - tokenizer.count(condition);
1108
- const Key = fastHash(
1109
- JSON.stringify({
1110
- taskType,
1111
- taskId,
1112
- input: inputAsString,
1113
- condition
1114
- })
1115
- );
1116
- const examples = taskId ? await this.adapter.getExamples({
1117
- input: inputAsString,
1118
- taskType,
1119
- taskId
1120
- }) : [];
1121
- const exactMatch = examples.find((x) => x.key === Key);
1122
- if (exactMatch) {
1123
- return exactMatch.output;
1124
- }
1125
- const defaultExamples = [
1126
- { input: "50 Cent", check: true, reason: "50 Cent is widely recognized as a public personality." },
1127
- {
1128
- input: ["apple", "banana", "carrot", "house"],
1129
- check: false,
1130
- reason: "The list contains a house, which is not a fruit. Also, the list contains a carrot, which is a vegetable."
1131
- }
1132
- ];
1133
- const userExamples = [
1134
- ...examples.map((e) => ({ input: e.input, check: e.output, reason: e.explanation })),
1135
- ...options.examples
1136
- ];
1137
- let exampleId = 1;
1138
- const formatInput = /* @__PURE__ */ __name((input2, condition2) => {
1139
- const header = userExamples.length ? `Expert Example #${exampleId++}` : `Example of condition: "${condition2}"`;
1140
- return `
1141
- ${header}
1142
- <|start_input|>
1143
- ${input2.trim()}
1144
- <|end_input|>
1145
- `.trim();
1146
- }, "formatInput");
1147
- const formatOutput = /* @__PURE__ */ __name((answer2, justification) => {
1148
- return `
1149
- Analysis: ${justification}
1150
- Final Answer: ${answer2 ? TRUE : FALSE}
1151
- ${END3}
1152
- `.trim();
1153
- }, "formatOutput");
1154
- const formatExample = /* @__PURE__ */ __name((example) => [
1155
- { type: "text", content: formatInput(stringify(example.input ?? null), condition), role: "user" },
1156
- {
1157
- type: "text",
1158
- content: formatOutput(example.check, example.reason ?? ""),
1159
- role: "assistant"
1160
- }
1161
- ], "formatExample");
1162
- const allExamples = takeUntilTokens(
1163
- userExamples.length ? userExamples : defaultExamples,
1164
- EXAMPLES_TOKENS,
1165
- (el) => tokenizer.count(stringify(el.input)) + tokenizer.count(el.reason ?? "")
1166
- ).map(formatExample).flat();
1167
- const specialInstructions = userExamples.length ? `
1168
- - You have been provided with examples from previous experts. Make sure to read them carefully before making your decision.
1169
- - Make sure to refer to the examples provided by the experts to justify your decision (when applicable).
1170
- - When in doubt, ground your decision on the examples provided by the experts instead of your own intuition.
1171
- - When no example is similar to the input, make sure to provide a clear justification for your decision while inferring the decision-making process from the examples provided by the experts.
1172
- `.trim() : "";
1173
- const output = await this.callModel({
1174
- systemPrompt: `
1175
- Check if the following condition is true or false for the given input. Before answering, make sure to read the input and the condition carefully.
1176
- Justify your answer, then answer with either ${TRUE} or ${FALSE} at the very end, then add ${END3} to finish the response.
1177
- IMPORTANT: Make sure to answer with either ${TRUE} or ${FALSE} at the end of your response, but NOT both.
1178
- ---
1179
- Expert Examples (#1 to #${exampleId - 1}):
1180
- ${specialInstructions}
1181
- `.trim(),
1182
- stopSequences: [END3],
1183
- messages: [
1184
- ...allExamples,
1185
- {
1186
- type: "text",
1187
- content: `
1188
- Considering the below input and above examples, is the following condition true or false?
1189
- ${formatInput(inputAsString, condition)}
1190
- In your "Analysis", please refer to the Expert Examples # to justify your decision.`.trim(),
1191
- role: "user"
1192
- }
1193
- ]
1194
- });
1195
- const answer = output.choices[0]?.content;
1196
- const hasTrue = answer.includes(TRUE);
1197
- const hasFalse = answer.includes(FALSE);
1198
- if (!hasTrue && !hasFalse) {
1199
- throw new Error(`The model did not return a valid answer. The response was: ${answer}`);
1200
- }
1201
- let finalAnswer;
1202
- if (hasTrue && hasFalse) {
1203
- finalAnswer = answer.lastIndexOf(TRUE) > answer.lastIndexOf(FALSE);
1204
- } else {
1205
- finalAnswer = hasTrue;
1206
- }
1207
- if (taskId) {
1208
- await this.adapter.saveExample({
1209
- key: Key,
1210
- taskType,
1211
- taskId,
1212
- input: inputAsString,
1213
- instructions: condition,
1214
- metadata: output.metadata,
1215
- output: finalAnswer,
1216
- explanation: answer.replace(TRUE, "").replace(FALSE, "").replace(END3, "").replace("Final Answer:", "").trim()
1217
- });
1218
- }
1219
- return finalAnswer;
1220
- };
1221
-
1222
- // src/operations/filter.ts
1223
- import sdk8 from "@botpress/sdk";
1224
- import _3 from "lodash";
1225
- var { z: z8 } = sdk8;
1226
- var Example3 = z8.object({
1227
- input: z8.any(),
1228
- filter: z8.boolean(),
1229
- reason: z8.string().optional()
1230
- });
1231
- var Options5 = z8.object({
1232
- tokensPerItem: z8.number().min(1).max(1e5).optional().describe("The maximum number of tokens per item").default(250),
1233
- examples: z8.array(Example3).describe("Examples to filter the condition against").default([])
1234
- });
1235
- var END4 = "\u25A0END\u25A0";
1236
- Zai.prototype.filter = async function(input, condition, _options) {
1237
- const options = Options5.parse(_options ?? {});
1238
- const tokenizer = await this.getTokenizer();
1239
- const taskId = this.taskId;
1240
- const taskType = "zai.filter";
1241
- const MAX_ITEMS_PER_CHUNK = 50;
1242
- const TOKENS_TOTAL_MAX = this.Model.input.maxTokens - PROMPT_INPUT_BUFFER - PROMPT_OUTPUT_BUFFER;
1243
- const TOKENS_EXAMPLES_MAX = Math.floor(Math.max(250, TOKENS_TOTAL_MAX * 0.5));
1244
- const TOKENS_CONDITION_MAX = _3.clamp(TOKENS_TOTAL_MAX * 0.25, 250, tokenizer.count(condition));
1245
- const TOKENS_INPUT_ARRAY_MAX = TOKENS_TOTAL_MAX - TOKENS_EXAMPLES_MAX - TOKENS_CONDITION_MAX;
1246
- condition = tokenizer.truncate(condition, TOKENS_CONDITION_MAX);
1247
- let chunks = [];
1248
- let currentChunk = [];
1249
- let currentChunkTokens = 0;
1250
- for (const element of input) {
1251
- const elementAsString = tokenizer.truncate(stringify(element, false), options.tokensPerItem);
1252
- const elementTokens = tokenizer.count(elementAsString);
1253
- if (currentChunkTokens + elementTokens > TOKENS_INPUT_ARRAY_MAX || currentChunk.length >= MAX_ITEMS_PER_CHUNK) {
1254
- chunks.push(currentChunk);
1255
- currentChunk = [];
1256
- currentChunkTokens = 0;
1257
- }
1258
- currentChunk.push(element);
1259
- currentChunkTokens += elementTokens;
1260
- }
1261
- if (currentChunk.length > 0) {
1262
- chunks.push(currentChunk);
1263
- }
1264
- chunks = chunks.filter((x) => x.length > 0);
1265
- const formatInput = /* @__PURE__ */ __name((input2, condition2) => {
1266
- return `
1267
- Condition to check:
1268
- ${condition2}
1269
-
1270
- Items (from \u25A00 to \u25A0${input2.length - 1})
1271
- ==============================
1272
- ${input2.map((x, idx) => `\u25A0${idx} = ${stringify(x.input ?? null, false)}`).join("\n")}
1273
- `.trim();
1274
- }, "formatInput");
1275
- const formatExamples = /* @__PURE__ */ __name((examples) => {
1276
- return `
1277
- ${examples.map((x, idx) => `\u25A0${idx}:${!!x.filter ? "true" : "false"}`).join("")}
1278
- ${END4}
1279
- ====
1280
- Here's the reasoning behind each example:
1281
- ${examples.map((x, idx) => `\u25A0${idx}:${!!x.filter ? "true" : "false"}:${x.reason ?? "No reason provided"}`).join("\n")}
1282
- `.trim();
1283
- }, "formatExamples");
1284
- const genericExamples = [
1285
- {
1286
- input: "apple",
1287
- filter: true,
1288
- reason: "Apples are fruits"
1289
- },
1290
- {
1291
- input: "Apple Inc.",
1292
- filter: false,
1293
- reason: "Apple Inc. is a company, not a fruit"
1294
- },
1295
- {
1296
- input: "banana",
1297
- filter: true,
1298
- reason: "Bananas are fruits"
1299
- },
1300
- {
1301
- input: "potato",
1302
- filter: false,
1303
- reason: "Potatoes are vegetables"
1304
- }
1305
- ];
1306
- const genericExamplesMessages = [
1307
- {
1308
- type: "text",
1309
- content: formatInput(genericExamples, "is a fruit"),
1310
- role: "user"
1311
- },
1312
- {
1313
- type: "text",
1314
- content: formatExamples(genericExamples),
1315
- role: "assistant"
1316
- }
1317
- ];
1318
- const filterChunk = /* @__PURE__ */ __name(async (chunk) => {
1319
- const examples = taskId ? await this.adapter.getExamples({
1320
- // The Table API can't search for a huge input string
1321
- input: JSON.stringify(chunk).slice(0, 1e3),
1322
- taskType,
1323
- taskId
1324
- }).then(
1325
- (x) => x.map((y) => ({ filter: y.output, input: y.input, reason: y.explanation }))
1326
- ) : [];
1327
- const allExamples = takeUntilTokens(
1328
- [...examples, ...options.examples ?? []],
1329
- TOKENS_EXAMPLES_MAX,
1330
- (el) => tokenizer.count(stringify(el.input))
1331
- );
1332
- const exampleMessages = [
1333
- {
1334
- type: "text",
1335
- content: formatInput(allExamples, condition),
1336
- role: "user"
1337
- },
1338
- {
1339
- type: "text",
1340
- content: formatExamples(allExamples),
1341
- role: "assistant"
1342
- }
1343
- ];
1344
- const output = await this.callModel({
1345
- systemPrompt: `
1346
- You are given a list of items. Your task is to filter out the items that meet the condition below.
1347
- You need to return the full list of items with the format:
1348
- \u25A0x:true\u25A0y:false\u25A0z:true (where x, y, z are the indices of the items in the list)
1349
- You need to start with "\u25A00" and go up to the last index "\u25A0${chunk.length - 1}".
1350
- If an item meets the condition, you should return ":true", otherwise ":false".
1351
-
1352
- IMPORTANT: Make sure to read the condition and the examples carefully before making your decision.
1353
- The condition is: "${condition}"
1354
- `.trim(),
1355
- stopSequences: [END4],
1356
- messages: [
1357
- ...exampleMessages.length ? exampleMessages : genericExamplesMessages,
1358
- {
1359
- type: "text",
1360
- content: formatInput(
1361
- chunk.map((x) => ({ input: x })),
1362
- condition
1363
- ),
1364
- role: "user"
1365
- }
1366
- ]
1367
- });
1368
- const answer = output.choices[0]?.content;
1369
- const indices = answer.trim().split("\u25A0").filter((x) => x.length > 0).map((x) => {
1370
- const [idx, filter] = x.split(":");
1371
- return { idx: parseInt(idx?.trim() ?? ""), filter: filter?.toLowerCase().trim() === "true" };
1372
- });
1373
- const partial = chunk.filter((_6, idx) => {
1374
- return indices.find((x) => x.idx === idx)?.filter ?? false;
1375
- });
1376
- if (taskId) {
1377
- const key = fastHash(
1378
- stringify({
1379
- taskId,
1380
- taskType,
1381
- input: JSON.stringify(chunk),
1382
- condition
1383
- })
1384
- );
1385
- await this.adapter.saveExample({
1386
- key,
1387
- taskType,
1388
- taskId,
1389
- input: JSON.stringify(chunk),
1390
- output: partial,
1391
- instructions: condition,
1392
- metadata: output.metadata
1393
- });
1394
- }
1395
- return partial;
1396
- }, "filterChunk");
1397
- const filteredChunks = await Promise.all(chunks.map(filterChunk));
1398
- return filteredChunks.flat();
1399
- };
1400
-
1401
- // src/operations/extract.ts
1402
- import sdk9 from "@botpress/sdk";
1403
- import JSON5 from "json5";
1404
- import { jsonrepair } from "jsonrepair";
1405
- import _4 from "lodash";
1406
-
1407
- // src/operations/errors.ts
1408
- var JsonParsingError = class extends Error {
1409
- constructor(json, error) {
1410
- const message = `Error parsing JSON:
1411
-
1412
- ---JSON---
1413
- ${json}
1414
-
1415
- ---Error---
1416
-
1417
- ${error}`;
1418
- super(message);
1419
- this.json = json;
1420
- this.error = error;
1421
- }
1422
- static {
1423
- __name(this, "JsonParsingError");
1424
- }
1425
- };
1426
-
1427
- // src/operations/extract.ts
1428
- var { z: z9 } = sdk9;
1429
- var Options6 = z9.object({
1430
- instructions: z9.string().optional().describe("Instructions to guide the user on how to extract the data"),
1431
- chunkLength: z9.number().min(100).max(1e5).optional().describe("The maximum number of tokens per chunk").default(16e3)
1432
- });
1433
- var START3 = "\u25A0json_start\u25A0";
1434
- var END5 = "\u25A0json_end\u25A0";
1435
- var NO_MORE = "\u25A0NO_MORE_ELEMENT\u25A0";
1436
- Zai.prototype.extract = async function(input, schema, _options) {
1437
- const options = Options6.parse(_options ?? {});
1438
- const tokenizer = await this.getTokenizer();
1439
- const taskId = this.taskId;
1440
- const taskType = "zai.extract";
1441
- const PROMPT_COMPONENT = Math.max(this.Model.input.maxTokens - PROMPT_INPUT_BUFFER, 100);
1442
- let isArrayOfObjects = false;
1443
- const originalSchema = schema;
1444
- if (schema instanceof sdk9.ZodObject) {
1445
- } else if (schema instanceof sdk9.ZodArray) {
1446
- if (schema._def.type instanceof sdk9.ZodObject) {
1447
- isArrayOfObjects = true;
1448
- schema = schema._def.type;
1449
- } else {
1450
- throw new Error("Schema must be a ZodObject or a ZodArray<ZodObject>");
1451
- }
1452
- } else {
1453
- throw new Error("Schema must be either a ZuiObject or a ZuiArray<ZuiObject>");
1454
- }
1455
- const schemaTypescript = schema.toTypescript({ declaration: false });
1456
- const schemaLength = tokenizer.count(schemaTypescript);
1457
- options.chunkLength = Math.min(options.chunkLength, this.Model.input.maxTokens - PROMPT_INPUT_BUFFER - schemaLength);
1458
- const keys = Object.keys(schema.shape);
1459
- let inputAsString = stringify(input);
1460
- if (tokenizer.count(inputAsString) > options.chunkLength) {
1461
- if (isArrayOfObjects) {
1462
- const tokens = tokenizer.split(inputAsString);
1463
- const chunks = _4.chunk(tokens, options.chunkLength).map((x) => x.join(""));
1464
- const all = await Promise.all(chunks.map((chunk) => this.extract(chunk, originalSchema)));
1465
- return all.flat();
1466
- } else {
1467
- inputAsString = tokenizer.truncate(stringify(input), options.chunkLength);
1468
- }
1469
- }
1470
- const instructions = [];
1471
- if (options.instructions) {
1472
- instructions.push(options.instructions);
1473
- }
1474
- const shape = `{ ${keys.map((key) => `"${key}": ...`).join(", ")} }`;
1475
- const abbv = "{ ... }";
1476
- if (isArrayOfObjects) {
1477
- instructions.push("You may have multiple elements, or zero elements in the input.");
1478
- instructions.push("You must extract each element separately.");
1479
- instructions.push(`Each element must be a JSON object with exactly the format: ${START3}${shape}${END5}`);
1480
- instructions.push(`When you are done extracting all elements, type "${NO_MORE}" to finish.`);
1481
- instructions.push(`For example, if you have zero elements, the output should look like this: ${NO_MORE}`);
1482
- instructions.push(
1483
- `For example, if you have two elements, the output should look like this: ${START3}${abbv}${END5}${START3}${abbv}${END5}${NO_MORE}`
1484
- );
1485
- } else {
1486
- instructions.push("You may have exactly one element in the input.");
1487
- instructions.push(`The element must be a JSON object with exactly the format: ${START3}${shape}${END5}`);
1488
- }
1489
- const EXAMPLES_TOKENS = PROMPT_COMPONENT - tokenizer.count(inputAsString) - tokenizer.count(instructions.join("\n"));
1490
- const Key = fastHash(
1491
- JSON.stringify({
1492
- taskType,
1493
- taskId,
1494
- input: inputAsString,
1495
- instructions: options.instructions
1496
- })
1497
- );
1498
- const examples = taskId ? await this.adapter.getExamples({
1499
- input: inputAsString,
1500
- taskType,
1501
- taskId
1502
- }) : [];
1503
- const exactMatch = examples.find((x) => x.key === Key);
1504
- if (exactMatch) {
1505
- return exactMatch.output;
1506
- }
1507
- const defaultExample = isArrayOfObjects ? {
1508
- input: `The story goes as follow.
1509
- Once upon a time, there was a person named Alice who was 30 years old.
1510
- Then, there was a person named Bob who was 25 years old.
1511
- The end.`,
1512
- schema: "Array<{ name: string, age: number }>",
1513
- instructions: "Extract all people",
1514
- extracted: [
1515
- {
1516
- name: "Alice",
1517
- age: 30
1518
- },
1519
- {
1520
- name: "Bob",
1521
- age: 25
1522
- }
1523
- ]
1524
- } : {
1525
- input: `The story goes as follow.
1526
- Once upon a time, there was a person named Alice who was 30 years old.
1527
- The end.`,
1528
- schema: "{ name: string, age: number }",
1529
- instructions: "Extract the person",
1530
- extracted: { name: "Alice", age: 30 }
1531
- };
1532
- const userExamples = examples.map((e) => ({
1533
- input: e.input,
1534
- extracted: e.output,
1535
- schema: schemaTypescript,
1536
- instructions: options.instructions
1537
- }));
1538
- let exampleId = 1;
1539
- const formatInput = /* @__PURE__ */ __name((input2, schema2, instructions2) => {
1540
- const header = userExamples.length ? `Expert Example #${exampleId++}` : "Here's an example to help you understand the format:";
1541
- return `
1542
- ${header}
1543
-
1544
- <|start_schema|>
1545
- ${schema2}
1546
- <|end_schema|>
1547
-
1548
- <|start_instructions|>
1549
- ${instructions2 ?? "No specific instructions, just follow the schema above."}
1550
- <|end_instructions|>
1551
-
1552
- <|start_input|>
1553
- ${input2.trim()}
1554
- <|end_input|>
1555
- `.trim();
1556
- }, "formatInput");
1557
- const formatOutput = /* @__PURE__ */ __name((extracted) => {
1558
- extracted = _4.isArray(extracted) ? extracted : [extracted];
1559
- return extracted.map(
1560
- (x) => `
1561
- ${START3}
1562
- ${JSON.stringify(x, null, 2)}
1563
- ${END5}`.trim()
1564
- ).join("\n") + NO_MORE;
1565
- }, "formatOutput");
1566
- const formatExample = /* @__PURE__ */ __name((example) => [
1567
- {
1568
- type: "text",
1569
- content: formatInput(stringify(example.input ?? null), example.schema, example.instructions),
1570
- role: "user"
1571
- },
1572
- {
1573
- type: "text",
1574
- content: formatOutput(example.extracted),
1575
- role: "assistant"
1576
- }
1577
- ], "formatExample");
1578
- const allExamples = takeUntilTokens(
1579
- userExamples.length ? userExamples : [defaultExample],
1580
- EXAMPLES_TOKENS,
1581
- (el) => tokenizer.count(stringify(el.input)) + tokenizer.count(stringify(el.extracted))
1582
- ).map(formatExample).flat();
1583
- const output = await this.callModel({
1584
- systemPrompt: `
1585
- Extract the following information from the input:
1586
- ${schemaTypescript}
1587
- ====
1588
-
1589
- ${instructions.map((x) => `\u2022 ${x}`).join("\n")}
1590
- `.trim(),
1591
- stopSequences: [isArrayOfObjects ? NO_MORE : END5],
1592
- messages: [
1593
- ...allExamples,
1594
- {
1595
- role: "user",
1596
- type: "text",
1597
- content: formatInput(inputAsString, schemaTypescript, options.instructions ?? "")
1598
- }
1599
- ]
1600
- });
1601
- const answer = output.choices[0]?.content;
1602
- const elements = answer.split(START3).filter((x) => x.trim().length > 0).map((x) => {
1603
- try {
1604
- const json = x.slice(0, x.indexOf(END5)).trim();
1605
- const repairedJson = jsonrepair(json);
1606
- const parsedJson = JSON5.parse(repairedJson);
1607
- return schema.parse(parsedJson);
1608
- } catch (error) {
1609
- throw new JsonParsingError(x, error instanceof Error ? error : new Error("Unknown error"));
1610
- }
1611
- }).filter((x) => x !== null);
1612
- let final;
1613
- if (isArrayOfObjects) {
1614
- final = elements;
1615
- } else if (elements.length === 0) {
1616
- final = schema.parse({});
1617
- } else {
1618
- final = elements[0];
1619
- }
1620
- if (taskId) {
1621
- await this.adapter.saveExample({
1622
- key: Key,
1623
- taskId: `zai/${taskId}`,
1624
- taskType,
1625
- instructions: options.instructions ?? "No specific instructions",
1626
- input: inputAsString,
1627
- output: final,
1628
- metadata: output.metadata
1629
- });
1630
- }
1631
- return final;
1632
- };
1633
-
1634
- // src/operations/label.ts
1635
- import sdk10 from "@botpress/sdk";
1636
- import _5 from "lodash";
1637
- var { z: z10 } = sdk10;
1638
- var LABELS = {
1639
- ABSOLUTELY_NOT: "ABSOLUTELY_NOT",
1640
- PROBABLY_NOT: "PROBABLY_NOT",
1641
- AMBIGUOUS: "AMBIGUOUS",
1642
- PROBABLY_YES: "PROBABLY_YES",
1643
- ABSOLUTELY_YES: "ABSOLUTELY_YES"
1644
- };
1645
- var ALL_LABELS = Object.values(LABELS).join(" | ");
1646
- var Options7 = z10.object({
1647
- examples: z10.array(
1648
- z10.object({
1649
- input: z10.any(),
1650
- labels: z10.record(z10.object({ label: z10.enum(ALL_LABELS), explanation: z10.string().optional() }))
1651
- })
1652
- ).default([]).describe("Examples to help the user make a decision"),
1653
- instructions: z10.string().optional().describe("Instructions to guide the user on how to extract the data"),
1654
- chunkLength: z10.number().min(100).max(1e5).optional().describe("The maximum number of tokens per chunk").default(16e3)
1655
- });
1656
- var Labels = z10.record(z10.string().min(1).max(250), z10.string()).superRefine((labels, ctx) => {
1657
- const keys = Object.keys(labels);
1658
- for (const key of keys) {
1659
- if (key.length < 1 || key.length > 250) {
1660
- ctx.addIssue({ message: `The label key "${key}" must be between 1 and 250 characters long`, code: "custom" });
1661
- }
1662
- if (keys.lastIndexOf(key) !== keys.indexOf(key)) {
1663
- ctx.addIssue({ message: `Duplicate label: ${labels[key]}`, code: "custom" });
1664
- }
1665
- if (/[^a-zA-Z0-9_]/.test(key)) {
1666
- ctx.addIssue({
1667
- message: `The label key "${key}" must only contain alphanumeric characters and underscores`,
1668
- code: "custom"
1669
- });
1670
- }
1671
- }
1672
- return true;
1673
- });
1674
- var parseLabel = /* @__PURE__ */ __name((label) => {
1675
- label = label.toUpperCase().replace(/\s+/g, "_").replace(/_{2,}/g, "_").trim();
1676
- if (label.includes("ABSOLUTELY") && label.includes("NOT")) {
1677
- return LABELS.ABSOLUTELY_NOT;
1678
- } else if (label.includes("NOT")) {
1679
- return LABELS.PROBABLY_NOT;
1680
- } else if (label.includes("AMBIGUOUS")) {
1681
- return LABELS.AMBIGUOUS;
1682
- }
1683
- if (label.includes("YES")) {
1684
- return LABELS.PROBABLY_YES;
1685
- } else if (label.includes("ABSOLUTELY") && label.includes("YES")) {
1686
- return LABELS.ABSOLUTELY_YES;
1687
- }
1688
- return LABELS.AMBIGUOUS;
1689
- }, "parseLabel");
1690
- Zai.prototype.label = async function(input, _labels, _options) {
1691
- const options = Options7.parse(_options ?? {});
1692
- const labels = Labels.parse(_labels);
1693
- const tokenizer = await this.getTokenizer();
1694
- const taskId = this.taskId;
1695
- const taskType = "zai.label";
1696
- const TOTAL_MAX_TOKENS = _5.clamp(options.chunkLength, 1e3, this.Model.input.maxTokens - PROMPT_INPUT_BUFFER);
1697
- const CHUNK_EXAMPLES_MAX_TOKENS = _5.clamp(Math.floor(TOTAL_MAX_TOKENS * 0.5), 250, 1e4);
1698
- const CHUNK_INPUT_MAX_TOKENS = _5.clamp(
1699
- TOTAL_MAX_TOKENS - CHUNK_EXAMPLES_MAX_TOKENS,
1700
- TOTAL_MAX_TOKENS * 0.5,
1701
- TOTAL_MAX_TOKENS
1702
- );
1703
- const inputAsString = stringify(input);
1704
- if (tokenizer.count(inputAsString) > CHUNK_INPUT_MAX_TOKENS) {
1705
- const tokens = tokenizer.split(inputAsString);
1706
- const chunks = _5.chunk(tokens, CHUNK_INPUT_MAX_TOKENS).map((x) => x.join(""));
1707
- const allLabels = await Promise.all(chunks.map((chunk) => this.label(chunk, _labels)));
1708
- return allLabels.reduce((acc, x) => {
1709
- Object.keys(x).forEach((key) => {
1710
- if (acc[key] === true) {
1711
- acc[key] = true;
1712
- } else {
1713
- acc[key] = acc[key] || x[key];
1714
- }
1715
- });
1716
- return acc;
1717
- }, {});
1718
- }
1719
- const END6 = "\u25A0END\u25A0";
1720
- const Key = fastHash(
1721
- JSON.stringify({
1722
- taskType,
1723
- taskId,
1724
- input: inputAsString,
1725
- instructions: options.instructions ?? ""
1726
- })
1727
- );
1728
- const convertToAnswer = /* @__PURE__ */ __name((mapping) => {
1729
- return Object.keys(labels).reduce((acc, key) => {
1730
- acc[key] = mapping[key]?.label === "ABSOLUTELY_YES" || mapping[key]?.label === "PROBABLY_YES";
1731
- return acc;
1732
- }, {});
1733
- }, "convertToAnswer");
1734
- const examples = taskId ? await this.adapter.getExamples({
1735
- input: inputAsString,
1736
- taskType,
1737
- taskId
1738
- }) : [];
1739
- options.examples.forEach((example) => {
1740
- examples.push({
1741
- key: fastHash(JSON.stringify(example)),
1742
- input: example.input,
1743
- similarity: 1,
1744
- explanation: "",
1745
- output: example.labels
1746
- });
1747
- });
1748
- const exactMatch = examples.find((x) => x.key === Key);
1749
- if (exactMatch) {
1750
- return convertToAnswer(exactMatch.output);
1751
- }
1752
- const allExamples = takeUntilTokens(
1753
- examples,
1754
- CHUNK_EXAMPLES_MAX_TOKENS,
1755
- (el) => tokenizer.count(stringify(el.input)) + tokenizer.count(stringify(el.output)) + tokenizer.count(el.explanation ?? "") + 100
1756
- ).map((example, idx) => [
1757
- {
1758
- type: "text",
1759
- role: "user",
1760
- content: `
1761
- Expert Example #${idx + 1}
1762
-
1763
- <|start_input|>
1764
- ${stringify(example.input)}
1765
- <|end_input|>`.trim()
1766
- },
1767
- {
1768
- type: "text",
1769
- role: "assistant",
1770
- content: `
1771
- Expert Example #${idx + 1}
1772
- ============
1773
- ${Object.keys(example.output).map(
1774
- (key) => `
1775
- \u25A0${key}:\u3010${example.output[key]?.explanation}\u3011:${example.output[key]?.label}\u25A0
1776
- `.trim()
1777
- ).join("\n")}
1778
- ${END6}
1779
- `.trim()
1780
- }
1781
- ]).flat();
1782
- const format = Object.keys(labels).map((key) => {
1783
- return `
1784
- \u25A0${key}:\u3010explanation (where "explanation" is answering the question "${labels[key]}")\u3011:x\u25A0 (where x is ${ALL_LABELS})
1785
- `.trim();
1786
- }).join("\n\n");
1787
- const output = await this.callModel({
1788
- stopSequences: [END6],
1789
- systemPrompt: `
1790
- You need to tag the input with the following labels based on the question asked:
1791
- ${LABELS.ABSOLUTELY_NOT}: You are absolutely sure that the answer is "NO" to the question.
1792
- ${LABELS.PROBABLY_NOT}: You are leaning towards "NO" to the question.
1793
- ${LABELS.AMBIGUOUS}: You are unsure about the answer to the question.
1794
- ${LABELS.PROBABLY_YES}: You are leaning towards "YES" to the question.
1795
- ${LABELS.ABSOLUTELY_YES}: You are absolutely sure that the answer is "YES" to the question.
1796
-
1797
- You need to return a mapping of the labels, an explanation and the answer for each label following the format below:
1798
- \`\`\`
1799
- ${format}
1800
- ${END6}
1801
- \`\`\`
1802
-
1803
- ${options.instructions}
1804
-
1805
- ===
1806
- You should consider the Expert Examples below to help you make your decision.
1807
- In your "Analysis", please refer to the Expert Examples # to justify your decision.
1808
- `.trim(),
1809
- messages: [
1810
- ...allExamples,
1811
- {
1812
- type: "text",
1813
- role: "user",
1814
- content: `
1815
- Input to tag:
1816
- <|start_input|>
1817
- ${inputAsString}
1818
- <|end_input|>
1819
-
1820
- Answer with this following format:
1821
- \`\`\`
1822
- ${format}
1823
- ${END6}
1824
- \`\`\`
1825
-
1826
- Format cheatsheet:
1827
- \`\`\`
1828
- \u25A0label:\u3010explanation\u3011:x\u25A0
1829
- \`\`\`
1830
-
1831
- Where \`x\` is one of the following: ${ALL_LABELS}
1832
-
1833
- Remember: In your \`explanation\`, please refer to the Expert Examples # (and quote them) that are relevant to ground your decision-making process.
1834
- The Expert Examples are there to help you make your decision. They have been provided by experts in the field and their answers (and reasoning) are considered the ground truth and should be used as a reference to make your decision when applicable.
1835
- For example, you can say: "According to Expert Example #1, ..."`.trim()
1836
- }
1837
- ]
1838
- });
1839
- const answer = output.choices[0].content;
1840
- const final = Object.keys(labels).reduce((acc, key) => {
1841
- const match = answer.match(new RegExp(`\u25A0${key}:\u3010(.+)\u3011:(\\w{2,})\u25A0`, "i"));
1842
- if (match) {
1843
- const explanation = match[1].trim();
1844
- const label = parseLabel(match[2]);
1845
- acc[key] = {
1846
- explanation,
1847
- label
1848
- };
1849
- } else {
1850
- acc[key] = {
1851
- explanation: "",
1852
- label: LABELS.AMBIGUOUS
1853
- };
1854
- }
1855
- return acc;
1856
- }, {});
1857
- if (taskId) {
1858
- await this.adapter.saveExample({
1859
- key: Key,
1860
- taskType,
1861
- taskId,
1862
- instructions: options.instructions ?? "",
1863
- metadata: output.metadata,
1864
- input: inputAsString,
1865
- output: final
1866
- });
1867
- }
1868
- return convertToAnswer(final);
1869
- };
1870
- export {
1871
- Zai
1872
- };
1873
- //# sourceMappingURL=index.js.map
1
+ import { Zai } from "./zai";
2
+ import "./operations/text";
3
+ import "./operations/rewrite";
4
+ import "./operations/summarize";
5
+ import "./operations/check";
6
+ import "./operations/filter";
7
+ import "./operations/extract";
8
+ import "./operations/label";
9
+ export { Zai };