@botpress/zai 1.0.0-beta.8 → 1.0.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/csj/adapters/adapter.js +2 -0
- package/dist/csj/adapters/botpress-table.js +173 -0
- package/dist/csj/adapters/memory.js +12 -0
- package/dist/csj/index.js +9 -0
- package/dist/csj/models.js +387 -0
- package/dist/csj/operations/check.js +143 -0
- package/dist/csj/operations/constants.js +2 -0
- package/dist/csj/operations/errors.js +15 -0
- package/dist/csj/operations/extract.js +214 -0
- package/dist/csj/operations/filter.js +182 -0
- package/dist/csj/operations/label.js +242 -0
- package/dist/csj/operations/rewrite.js +113 -0
- package/dist/csj/operations/summarize.js +134 -0
- package/dist/csj/operations/text.js +48 -0
- package/dist/csj/utils.js +44 -0
- package/dist/csj/zai.js +142 -0
- package/dist/esm/adapters/adapter.js +5 -0
- package/dist/esm/adapters/botpress-table.js +194 -0
- package/dist/esm/adapters/memory.js +15 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/models.js +390 -0
- package/dist/esm/operations/check.js +149 -0
- package/dist/esm/operations/constants.js +6 -0
- package/dist/esm/operations/errors.js +18 -0
- package/dist/esm/operations/extract.js +217 -0
- package/dist/esm/operations/filter.js +189 -0
- package/dist/esm/operations/label.js +246 -0
- package/dist/esm/operations/rewrite.js +113 -0
- package/dist/esm/operations/summarize.js +134 -0
- package/dist/esm/operations/text.js +48 -0
- package/dist/esm/utils.js +51 -0
- package/dist/esm/zai.js +161 -0
- package/package.json +17 -13
- package/scripts/update-models.mts +76 -0
- package/scripts/update-types.mts +59 -0
- package/src/adapters/adapter.ts +35 -0
- package/src/adapters/botpress-table.ts +214 -0
- package/src/adapters/memory.ts +13 -0
- package/src/index.ts +11 -0
- package/src/models.ts +394 -0
- package/src/operations/__tests/botpress_docs.txt +26040 -0
- package/src/operations/__tests/cache.jsonl +101 -0
- package/src/operations/__tests/index.ts +86 -0
- package/src/operations/check.ts +188 -0
- package/src/operations/constants.ts +2 -0
- package/src/operations/errors.ts +9 -0
- package/src/operations/extract.ts +292 -0
- package/src/operations/filter.ts +232 -0
- package/src/operations/label.ts +333 -0
- package/src/operations/rewrite.ts +149 -0
- package/src/operations/summarize.ts +194 -0
- package/src/operations/text.ts +64 -0
- package/src/sdk-interfaces/llm/generateContent.ts +127 -0
- package/src/sdk-interfaces/llm/listLanguageModels.ts +19 -0
- package/src/utils.ts +62 -0
- package/src/zai.ts +193 -0
- package/dist/index.cjs +0 -1903
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.cts +0 -916
- package/dist/index.d.ts +0 -916
- package/dist/index.js +0 -1873
- package/dist/index.js.map +0 -1
package/dist/csj/zai.js
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import sdk from "@botpress/sdk";
|
|
2
|
+
import { getWasmTokenizer } from "@botpress/wasm";
|
|
3
|
+
import { TableAdapter } from "./adapters/botpress-table";
|
|
4
|
+
import { MemoryAdapter } from "./adapters/memory";
|
|
5
|
+
import { Models } from "./models";
|
|
6
|
+
import { BotpressClient } from "./utils";
|
|
7
|
+
const { z } = sdk;
|
|
8
|
+
const ActiveLearning = z.object({
|
|
9
|
+
enable: z.boolean().describe("Whether to enable active learning").default(false),
|
|
10
|
+
tableName: z.string().regex(
|
|
11
|
+
/^[A-Za-z0-9_/-]{1,100}Table$/,
|
|
12
|
+
"Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes"
|
|
13
|
+
).describe("The name of the table to store active learning tasks").default("ActiveLearningTable"),
|
|
14
|
+
taskId: z.string().regex(
|
|
15
|
+
/^[A-Za-z0-9_/-]{1,100}$/,
|
|
16
|
+
"Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes"
|
|
17
|
+
).describe("The ID of the task").default("default")
|
|
18
|
+
});
|
|
19
|
+
const ZaiConfig = z.object({
|
|
20
|
+
client: BotpressClient,
|
|
21
|
+
userId: z.string().describe("The ID of the user consuming the API").optional(),
|
|
22
|
+
retry: z.object({ maxRetries: z.number().min(0).max(100) }).default({ maxRetries: 3 }),
|
|
23
|
+
modelId: z.custom(
|
|
24
|
+
(value) => {
|
|
25
|
+
if (typeof value !== "string" || !value.includes("__")) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
message: "Invalid model ID"
|
|
32
|
+
}
|
|
33
|
+
).describe("The ID of the model you want to use").default("openai__gpt-4o-mini-2024-07-18"),
|
|
34
|
+
activeLearning: ActiveLearning.default({ enable: false }),
|
|
35
|
+
namespace: z.string().regex(
|
|
36
|
+
/^[A-Za-z0-9_/-]{1,100}$/,
|
|
37
|
+
"Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes"
|
|
38
|
+
).default("zai")
|
|
39
|
+
});
|
|
40
|
+
export class Zai {
|
|
41
|
+
static tokenizer = null;
|
|
42
|
+
client;
|
|
43
|
+
originalConfig;
|
|
44
|
+
userId;
|
|
45
|
+
integration;
|
|
46
|
+
model;
|
|
47
|
+
retry;
|
|
48
|
+
Model;
|
|
49
|
+
namespace;
|
|
50
|
+
adapter;
|
|
51
|
+
activeLearning;
|
|
52
|
+
constructor(config) {
|
|
53
|
+
var _a;
|
|
54
|
+
this.originalConfig = config;
|
|
55
|
+
const parsed = ZaiConfig.parse(config);
|
|
56
|
+
this.client = parsed.client;
|
|
57
|
+
const [integration, modelId] = parsed.modelId.split("__");
|
|
58
|
+
if (!(integration == null ? void 0 : integration.length) || !(modelId == null ? void 0 : modelId.length)) {
|
|
59
|
+
throw new Error(`Invalid model ID: ${parsed.modelId}. Expected format: <integration>__<modelId>`);
|
|
60
|
+
}
|
|
61
|
+
this.integration = integration;
|
|
62
|
+
this.model = modelId;
|
|
63
|
+
this.namespace = parsed.namespace;
|
|
64
|
+
this.userId = parsed.userId;
|
|
65
|
+
this.retry = parsed.retry;
|
|
66
|
+
this.Model = Models.find((m) => m.id === parsed.modelId);
|
|
67
|
+
this.activeLearning = parsed.activeLearning;
|
|
68
|
+
this.adapter = ((_a = parsed.activeLearning) == null ? void 0 : _a.enable) ? new TableAdapter({ client: this.client, tableName: parsed.activeLearning.tableName }) : new MemoryAdapter([]);
|
|
69
|
+
}
|
|
70
|
+
/** @internal */
|
|
71
|
+
async callModel(props) {
|
|
72
|
+
let retries = this.retry.maxRetries;
|
|
73
|
+
while (retries-- >= 0) {
|
|
74
|
+
try {
|
|
75
|
+
return await this._callModel(props);
|
|
76
|
+
} catch (e) {
|
|
77
|
+
if (retries >= 0) {
|
|
78
|
+
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
79
|
+
} else {
|
|
80
|
+
throw new Error("Failed to call model after multiple retries");
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
throw new Error("Failed to call model after multiple retries");
|
|
85
|
+
}
|
|
86
|
+
/** @internal */
|
|
87
|
+
async _callModel(props) {
|
|
88
|
+
let retries = this.retry.maxRetries;
|
|
89
|
+
do {
|
|
90
|
+
const start = Date.now();
|
|
91
|
+
const input = {
|
|
92
|
+
messages: [],
|
|
93
|
+
temperature: 0,
|
|
94
|
+
topP: 1,
|
|
95
|
+
model: { id: this.model },
|
|
96
|
+
userId: this.userId,
|
|
97
|
+
...props
|
|
98
|
+
};
|
|
99
|
+
const { output } = await this.client.callAction({
|
|
100
|
+
type: `${this.integration}:generateContent`,
|
|
101
|
+
input
|
|
102
|
+
});
|
|
103
|
+
const latency = Date.now() - start;
|
|
104
|
+
return {
|
|
105
|
+
...output,
|
|
106
|
+
metadata: {
|
|
107
|
+
model: this.model,
|
|
108
|
+
latency,
|
|
109
|
+
cost: { input: output.usage.inputCost, output: output.usage.outputCost },
|
|
110
|
+
tokens: { input: output.usage.inputTokens, output: output.usage.outputTokens }
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
} while (--retries > 0);
|
|
114
|
+
}
|
|
115
|
+
async getTokenizer() {
|
|
116
|
+
Zai.tokenizer ??= await (async () => {
|
|
117
|
+
while (!getWasmTokenizer) {
|
|
118
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
119
|
+
}
|
|
120
|
+
return getWasmTokenizer();
|
|
121
|
+
})();
|
|
122
|
+
return Zai.tokenizer;
|
|
123
|
+
}
|
|
124
|
+
get taskId() {
|
|
125
|
+
if (!this.activeLearning.enable) {
|
|
126
|
+
return void 0;
|
|
127
|
+
}
|
|
128
|
+
return `${this.namespace}/${this.activeLearning.taskId}`.replace(/\/+/g, "/");
|
|
129
|
+
}
|
|
130
|
+
with(options) {
|
|
131
|
+
return new Zai({
|
|
132
|
+
...this.originalConfig,
|
|
133
|
+
...options
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
learn(taskId) {
|
|
137
|
+
return new Zai({
|
|
138
|
+
...this.originalConfig,
|
|
139
|
+
activeLearning: { ...this.activeLearning, taskId, enable: true }
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
5
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
6
|
+
var __spreadValues = (a, b) => {
|
|
7
|
+
for (var prop in b || (b = {}))
|
|
8
|
+
if (__hasOwnProp.call(b, prop))
|
|
9
|
+
__defNormalProp(a, prop, b[prop]);
|
|
10
|
+
if (__getOwnPropSymbols)
|
|
11
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
12
|
+
if (__propIsEnum.call(b, prop))
|
|
13
|
+
__defNormalProp(a, prop, b[prop]);
|
|
14
|
+
}
|
|
15
|
+
return a;
|
|
16
|
+
};
|
|
17
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
18
|
+
import sdk from "@botpress/sdk";
|
|
19
|
+
const { z } = sdk;
|
|
20
|
+
import { BotpressClient, GenerationMetadata } from "../utils";
|
|
21
|
+
import { Adapter } from "./adapter";
|
|
22
|
+
const CRITICAL_TAGS = {
|
|
23
|
+
system: "true",
|
|
24
|
+
"schema-purpose": "active-learning",
|
|
25
|
+
"schema-version": "Oct-2024"
|
|
26
|
+
};
|
|
27
|
+
const OPTIONAL_TAGS = {
|
|
28
|
+
"x-studio-title": "Active Learning",
|
|
29
|
+
"x-studio-description": "Table for storing active learning tasks and examples",
|
|
30
|
+
"x-studio-readonly": "true",
|
|
31
|
+
"x-studio-icon": "lucide://atom",
|
|
32
|
+
"x-studio-color": "green"
|
|
33
|
+
};
|
|
34
|
+
const FACTOR = 30;
|
|
35
|
+
const Props = z.object({
|
|
36
|
+
client: BotpressClient,
|
|
37
|
+
tableName: z.string().regex(
|
|
38
|
+
/^[a-zA-Z0-9_]{1,45}Table$/,
|
|
39
|
+
"Table name must be lowercase and contain only letters, numbers and underscores"
|
|
40
|
+
)
|
|
41
|
+
});
|
|
42
|
+
const TableSchema = z.object({
|
|
43
|
+
taskType: z.string().describe("The type of the task (filter, extract, etc.)"),
|
|
44
|
+
taskId: z.string(),
|
|
45
|
+
key: z.string().describe("A unique key for the task (e.g. a hash of the input, taskId, taskType and instructions)"),
|
|
46
|
+
instructions: z.string(),
|
|
47
|
+
input: z.object({}).passthrough().describe("The input to the task"),
|
|
48
|
+
output: z.object({}).passthrough().describe("The expected output"),
|
|
49
|
+
explanation: z.string().nullable(),
|
|
50
|
+
metadata: GenerationMetadata,
|
|
51
|
+
status: z.enum(["pending", "rejected", "approved"]),
|
|
52
|
+
feedback: z.object({
|
|
53
|
+
rating: z.enum(["very-bad", "bad", "good", "very-good"]),
|
|
54
|
+
comment: z.string().nullable()
|
|
55
|
+
}).nullable().default(null)
|
|
56
|
+
});
|
|
57
|
+
const searchableColumns = ["input"];
|
|
58
|
+
const TableJsonSchema = Object.entries(TableSchema.shape).reduce((acc, [key, value]) => {
|
|
59
|
+
var _a, _b;
|
|
60
|
+
acc[key] = value.toJsonSchema();
|
|
61
|
+
(_b = (_a = acc[key])["x-zui"]) != null ? _b : _a["x-zui"] = {};
|
|
62
|
+
acc[key]["x-zui"].searchable = searchableColumns.includes(key);
|
|
63
|
+
return acc;
|
|
64
|
+
}, {});
|
|
65
|
+
class TableAdapter extends Adapter {
|
|
66
|
+
constructor(props) {
|
|
67
|
+
super();
|
|
68
|
+
__publicField(this, "client");
|
|
69
|
+
__publicField(this, "tableName");
|
|
70
|
+
__publicField(this, "status");
|
|
71
|
+
__publicField(this, "errors", []);
|
|
72
|
+
props = Props.parse(props);
|
|
73
|
+
this.client = props.client;
|
|
74
|
+
this.tableName = props.tableName;
|
|
75
|
+
this.status = "ready";
|
|
76
|
+
}
|
|
77
|
+
async getExamples({ taskType, taskId, input }) {
|
|
78
|
+
await this.assertTableExists();
|
|
79
|
+
const { rows } = await this.client.findTableRows({
|
|
80
|
+
table: this.tableName,
|
|
81
|
+
search: JSON.stringify({ value: input }).substring(0, 1023),
|
|
82
|
+
// Search is limited to 1024 characters
|
|
83
|
+
limit: 10,
|
|
84
|
+
// TODO
|
|
85
|
+
filter: {
|
|
86
|
+
// Proximity match of approved examples
|
|
87
|
+
taskType,
|
|
88
|
+
taskId,
|
|
89
|
+
status: "approved"
|
|
90
|
+
}
|
|
91
|
+
}).catch((err) => {
|
|
92
|
+
console.error(`Error fetching examples: ${err.message}`);
|
|
93
|
+
return { rows: [] };
|
|
94
|
+
});
|
|
95
|
+
return rows.map((row) => {
|
|
96
|
+
var _a;
|
|
97
|
+
return {
|
|
98
|
+
key: row.key,
|
|
99
|
+
input: row.input.value,
|
|
100
|
+
output: row.output.value,
|
|
101
|
+
explanation: row.explanation,
|
|
102
|
+
similarity: (_a = row.similarity) != null ? _a : 0
|
|
103
|
+
};
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
async saveExample({
|
|
107
|
+
key,
|
|
108
|
+
taskType,
|
|
109
|
+
taskId,
|
|
110
|
+
instructions,
|
|
111
|
+
input,
|
|
112
|
+
output,
|
|
113
|
+
explanation,
|
|
114
|
+
metadata,
|
|
115
|
+
status = "pending"
|
|
116
|
+
}) {
|
|
117
|
+
await this.assertTableExists();
|
|
118
|
+
await this.client.upsertTableRows({
|
|
119
|
+
table: this.tableName,
|
|
120
|
+
keyColumn: "key",
|
|
121
|
+
rows: [
|
|
122
|
+
{
|
|
123
|
+
key,
|
|
124
|
+
taskType,
|
|
125
|
+
taskId,
|
|
126
|
+
instructions,
|
|
127
|
+
input: { value: input },
|
|
128
|
+
output: { value: output },
|
|
129
|
+
explanation: explanation != null ? explanation : null,
|
|
130
|
+
status,
|
|
131
|
+
metadata
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}).catch(() => {
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async assertTableExists() {
|
|
138
|
+
var _a, _b, _c;
|
|
139
|
+
if (this.status !== "ready") {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const { table, created } = await this.client.getOrCreateTable({
|
|
143
|
+
table: this.tableName,
|
|
144
|
+
factor: FACTOR,
|
|
145
|
+
frozen: true,
|
|
146
|
+
isComputeEnabled: false,
|
|
147
|
+
tags: __spreadValues(__spreadValues({}, CRITICAL_TAGS), OPTIONAL_TAGS),
|
|
148
|
+
schema: TableJsonSchema
|
|
149
|
+
}).catch((err) => {
|
|
150
|
+
this.status = "error";
|
|
151
|
+
this.errors = [err.message];
|
|
152
|
+
return { table: null, created: false };
|
|
153
|
+
});
|
|
154
|
+
if (!table) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (!created) {
|
|
158
|
+
const issues = [];
|
|
159
|
+
if (table.factor !== FACTOR) {
|
|
160
|
+
issues.push(`Factor is ${table.factor} instead of ${FACTOR}`);
|
|
161
|
+
}
|
|
162
|
+
if (table.frozen !== true) {
|
|
163
|
+
issues.push("Table is not frozen");
|
|
164
|
+
}
|
|
165
|
+
for (const [key, value] of Object.entries(CRITICAL_TAGS)) {
|
|
166
|
+
if (((_a = table.tags) == null ? void 0 : _a[key]) !== value) {
|
|
167
|
+
issues.push(`Tag ${key} is ${(_b = table.tags) == null ? void 0 : _b[key]} instead of ${value}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (const key of Object.keys(TableJsonSchema)) {
|
|
171
|
+
const column = (_c = table.schema) == null ? void 0 : _c.properties[key];
|
|
172
|
+
const expected = TableJsonSchema[key];
|
|
173
|
+
if (!column) {
|
|
174
|
+
issues.push(`Column ${key} is missing`);
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
if (column.type !== expected.type) {
|
|
178
|
+
issues.push(`Column ${key} has type ${column.type} instead of ${expected.type}`);
|
|
179
|
+
}
|
|
180
|
+
if (expected["x-zui"].searchable && !column["x-zui"].searchable) {
|
|
181
|
+
issues.push(`Column ${key} is not searchable but should be`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (issues.length) {
|
|
185
|
+
this.status = "error";
|
|
186
|
+
this.errors = issues;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
this.status = "initialized";
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
export {
|
|
193
|
+
TableAdapter
|
|
194
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Adapter } from "./adapter";
|
|
2
|
+
class MemoryAdapter extends Adapter {
|
|
3
|
+
constructor(examples) {
|
|
4
|
+
super();
|
|
5
|
+
this.examples = examples;
|
|
6
|
+
}
|
|
7
|
+
async getExamples() {
|
|
8
|
+
return this.examples;
|
|
9
|
+
}
|
|
10
|
+
async saveExample() {
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
MemoryAdapter
|
|
15
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
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 {
|
|
10
|
+
Zai
|
|
11
|
+
};
|