@botpress/zai 2.1.2 β 2.1.3
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/README.md +225 -29
- package/dist/response.js +3 -2
- package/package.json +2 -2
- package/src/response.ts +3 -2
package/README.md
CHANGED
|
@@ -1,57 +1,253 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Zai - AI Operations Made Simple
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Zai is a powerful LLM utility library that provides a clean, type-safe API for common AI operations. Built on Zod schemas and the Botpress API, it makes AI operations simple, intuitive, and production-ready.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## β¨ Key Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **π― Simple API** - One-liner operations for common AI tasks
|
|
8
|
+
- **π Type Safety** - Full TypeScript support with Zod schema validation
|
|
9
|
+
- **π§ Active Learning** - Learn from examples and improve over time
|
|
10
|
+
- **β‘ Performance** - Built-in retries, caching, and error handling
|
|
11
|
+
- **βΎοΈ Infinite Documents** - Handle any document size with automatic chunking
|
|
12
|
+
- **π Usage Tracking** - Monitor tokens, costs, and performance
|
|
13
|
+
|
|
14
|
+
## π¦ Installation
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @botpress/zai @botpress/client @bpinternal/zui
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## π Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { Client } from '@botpress/client'
|
|
24
|
+
import { Zai } from '@botpress/zai'
|
|
25
|
+
import { z } from '@bpinternal/zui'
|
|
26
|
+
|
|
27
|
+
// Initialize
|
|
28
|
+
const client = new Client({ botId: 'YOUR_BOT_ID', token: 'YOUR_TOKEN' })
|
|
29
|
+
const zai = new Zai({ client })
|
|
30
|
+
|
|
31
|
+
// Extract structured data
|
|
32
|
+
const person = await zai.extract(
|
|
33
|
+
'John Doe is 30 years old and lives in New York',
|
|
34
|
+
z.object({
|
|
35
|
+
name: z.string(),
|
|
36
|
+
age: z.number(),
|
|
37
|
+
location: z.string(),
|
|
38
|
+
})
|
|
39
|
+
)
|
|
40
|
+
// Result: { name: 'John Doe', age: 30, location: 'New York' }
|
|
41
|
+
|
|
42
|
+
// Check content
|
|
43
|
+
const isPositive = await zai.check('This product is amazing!', 'expresses positive sentiment')
|
|
44
|
+
// Result: true
|
|
45
|
+
|
|
46
|
+
// Generate text
|
|
47
|
+
const story = await zai.text('Write a short story about AI', { length: 200 })
|
|
48
|
+
|
|
49
|
+
// Summarize documents
|
|
50
|
+
const summary = await zai.summarize(longDocument, { length: 500 })
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## π Core Operations
|
|
54
|
+
|
|
55
|
+
### 1. Extract - Get structured data from text
|
|
8
56
|
|
|
9
57
|
```typescript
|
|
10
|
-
|
|
58
|
+
// Extract single object
|
|
59
|
+
const product = await zai.extract(
|
|
60
|
+
text,
|
|
61
|
+
z.object({
|
|
62
|
+
name: z.string(),
|
|
63
|
+
price: z.number(),
|
|
64
|
+
inStock: z.boolean(),
|
|
65
|
+
})
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
// Extract array of items
|
|
69
|
+
const products = await zai.extract(text, z.array(productSchema))
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 2. Check - Verify boolean conditions
|
|
73
|
+
|
|
74
|
+
```typescript
|
|
75
|
+
const result = await zai.check(email, 'is spam')
|
|
76
|
+
const { value, explanation } = await result.full()
|
|
77
|
+
```
|
|
11
78
|
|
|
79
|
+
### 3. Label - Apply multiple labels
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
const labels = await zai.label(review, {
|
|
83
|
+
positive: 'expresses positive sentiment',
|
|
84
|
+
technical: 'mentions technical details',
|
|
85
|
+
verified: 'from verified purchaser',
|
|
86
|
+
})
|
|
87
|
+
// Result: { positive: true, technical: false, verified: true }
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### 4. Rewrite - Transform text
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
// Translate
|
|
94
|
+
const french = await zai.rewrite(text, 'translate to French')
|
|
95
|
+
|
|
96
|
+
// Change tone
|
|
97
|
+
const formal = await zai.rewrite('Hey! What's up?', 'make it professional')
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### 5. Filter - Filter arrays with natural language
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
const techCompanies = await zai.filter(companies, 'are technology companies')
|
|
104
|
+
const recentPosts = await zai.filter(posts, 'were published this week')
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### 6. Text - Generate content
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
const blogPost = await zai.text('Write about the future of AI', {
|
|
111
|
+
length: 1000,
|
|
112
|
+
temperature: 0.7,
|
|
113
|
+
})
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### 7. Summarize - Create summaries
|
|
117
|
+
|
|
118
|
+
```typescript
|
|
119
|
+
// Simple summary
|
|
120
|
+
const summary = await zai.summarize(article)
|
|
121
|
+
|
|
122
|
+
// With custom prompt
|
|
123
|
+
const technicalSummary = await zai.summarize(paper, {
|
|
124
|
+
length: 500,
|
|
125
|
+
prompt: 'Focus on technical implementation details',
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## π§ Active Learning
|
|
130
|
+
|
|
131
|
+
Enable active learning to improve accuracy over time:
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
12
134
|
const zai = new Zai({
|
|
13
|
-
client
|
|
135
|
+
client,
|
|
136
|
+
activeLearning: {
|
|
137
|
+
enable: true,
|
|
138
|
+
tableName: 'ai_learning_data',
|
|
139
|
+
taskId: 'sentiment-analysis',
|
|
140
|
+
},
|
|
14
141
|
})
|
|
142
|
+
|
|
143
|
+
// Use with task ID for learning
|
|
144
|
+
const result = await zai.learn('sentiment-analysis').check(text, 'is positive')
|
|
15
145
|
```
|
|
16
146
|
|
|
17
|
-
##
|
|
147
|
+
## βοΈ Configuration
|
|
148
|
+
|
|
149
|
+
### Model Selection
|
|
18
150
|
|
|
19
151
|
```typescript
|
|
20
|
-
|
|
152
|
+
// Use the best model (default)
|
|
153
|
+
const zai = new Zai({ client, model: 'best' })
|
|
154
|
+
|
|
155
|
+
// Use fast model for speed
|
|
156
|
+
const fastZai = new Zai({ client, model: 'fast' })
|
|
157
|
+
|
|
158
|
+
// Use specific model
|
|
159
|
+
const customZai = new Zai({ client, model: 'gpt-4-turbo' })
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Progress Tracking
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
const response = zai.summarize(veryLongDocument)
|
|
166
|
+
|
|
167
|
+
// Track progress
|
|
168
|
+
response.on('progress', (progress) => {
|
|
169
|
+
console.log(`${progress.percent}% complete`)
|
|
170
|
+
})
|
|
21
171
|
|
|
22
|
-
|
|
23
|
-
// await zai.map(filtered, z.object({ animal: z.string(), name: z.string() }))
|
|
24
|
-
// await zai.sort(named, 'from most dangerous to least dangerous')
|
|
25
|
-
// await zai.cluster(named, 'based on color')
|
|
26
|
-
// await zai.append(named, 'another one')
|
|
172
|
+
const summary = await response
|
|
27
173
|
```
|
|
28
174
|
|
|
29
|
-
|
|
175
|
+
### Usage Monitoring
|
|
30
176
|
|
|
31
177
|
```typescript
|
|
32
|
-
await zai.text
|
|
33
|
-
await
|
|
34
|
-
await zai.rewrite('Hello, I am ...', 'make it longer')
|
|
178
|
+
const result = await zai.extract(text, schema)
|
|
179
|
+
const usage = await result.usage()
|
|
35
180
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
181
|
+
console.log({
|
|
182
|
+
tokens: usage.totalTokens,
|
|
183
|
+
cost: usage.totalCost,
|
|
184
|
+
latency: usage.totalLatency,
|
|
185
|
+
})
|
|
40
186
|
```
|
|
41
187
|
|
|
42
|
-
##
|
|
188
|
+
## π― Benefits
|
|
189
|
+
|
|
190
|
+
1. **Production Ready** - Built-in error handling, retries, and rate limiting
|
|
191
|
+
2. **Type Safe** - Full TypeScript support with runtime validation
|
|
192
|
+
3. **Scalable** - Handle documents of any size with automatic chunking
|
|
193
|
+
4. **Cost Effective** - Track usage and optimize with active learning
|
|
194
|
+
5. **Developer Friendly** - Clean API with method chaining and events
|
|
195
|
+
|
|
196
|
+
## π Advanced Usage
|
|
197
|
+
|
|
198
|
+
### Chaining Operations
|
|
43
199
|
|
|
44
200
|
```typescript
|
|
45
|
-
await zai.
|
|
201
|
+
const processedData = await zai.with({ temperature: 0.3 }).learn('data-extraction').extract(document, complexSchema)
|
|
46
202
|
```
|
|
47
203
|
|
|
48
|
-
|
|
204
|
+
### Handling Large Documents
|
|
49
205
|
|
|
50
206
|
```typescript
|
|
51
|
-
|
|
207
|
+
// Automatically chunks and processes in parallel
|
|
208
|
+
const extractedData = await zai.extract(
|
|
209
|
+
hugeDocument, // 100k+ tokens
|
|
210
|
+
z.array(recordSchema),
|
|
211
|
+
{ chunkSize: 4000 }
|
|
212
|
+
)
|
|
213
|
+
```
|
|
52
214
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
215
|
+
### Custom Abort Signals
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
const controller = new AbortController()
|
|
219
|
+
const response = zai.summarize(document, { signal: controller.signal })
|
|
220
|
+
|
|
221
|
+
// Cancel if needed
|
|
222
|
+
setTimeout(() => controller.abort(), 5000)
|
|
57
223
|
```
|
|
224
|
+
|
|
225
|
+
## π οΈ API Reference
|
|
226
|
+
|
|
227
|
+
### Zai Class
|
|
228
|
+
|
|
229
|
+
- `new Zai(options)` - Create instance with client and configuration
|
|
230
|
+
- `.with(config)` - Create new instance with merged configuration
|
|
231
|
+
- `.learn(taskId)` - Enable active learning for specific task
|
|
232
|
+
|
|
233
|
+
### Operations
|
|
234
|
+
|
|
235
|
+
- `.extract(content, schema, options?)` - Extract structured data
|
|
236
|
+
- `.check(content, condition, options?)` - Verify boolean condition
|
|
237
|
+
- `.label(content, criteria, options?)` - Apply multiple labels
|
|
238
|
+
- `.rewrite(content, instruction, options?)` - Transform text
|
|
239
|
+
- `.filter(items, condition, options?)` - Filter array items
|
|
240
|
+
- `.text(prompt, options?)` - Generate text
|
|
241
|
+
- `.summarize(content, options?)` - Create summary
|
|
242
|
+
|
|
243
|
+
### Response Methods
|
|
244
|
+
|
|
245
|
+
- `await response` - Get simple result
|
|
246
|
+
- `await response.full()` - Get detailed result with metadata
|
|
247
|
+
- `await response.usage()` - Get usage statistics
|
|
248
|
+
- `response.on('progress', handler)` - Track progress
|
|
249
|
+
- `response.abort()` - Cancel operation
|
|
250
|
+
|
|
251
|
+
## π License
|
|
252
|
+
|
|
253
|
+
MIT - See LICENSE file for details
|
package/dist/response.js
CHANGED
|
@@ -50,13 +50,14 @@ export class Response {
|
|
|
50
50
|
this.abort(signal.reason);
|
|
51
51
|
};
|
|
52
52
|
signal.addEventListener("abort", () => signalAbort());
|
|
53
|
-
this.once("complete", () => signal.removeEventListener("abort", signalAbort));
|
|
54
|
-
this.once("error", () => signal.removeEventListener("abort", signalAbort));
|
|
53
|
+
void this.once("complete", () => signal.removeEventListener("abort", signalAbort));
|
|
54
|
+
void this.once("error", () => signal.removeEventListener("abort", signalAbort));
|
|
55
55
|
return this;
|
|
56
56
|
}
|
|
57
57
|
abort(reason) {
|
|
58
58
|
this._context.controller.abort(reason);
|
|
59
59
|
}
|
|
60
|
+
// oxlint-disable-next-line no-thenable
|
|
60
61
|
then(onfulfilled, onrejected) {
|
|
61
62
|
return this._promise.then(
|
|
62
63
|
(value) => {
|
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": "2.1.
|
|
4
|
+
"version": "2.1.3",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"author": "",
|
|
30
30
|
"license": "ISC",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@botpress/cognitive": "0.1.
|
|
32
|
+
"@botpress/cognitive": "0.1.32",
|
|
33
33
|
"json5": "^2.2.3",
|
|
34
34
|
"jsonrepair": "^3.10.0",
|
|
35
35
|
"lodash-es": "^4.17.21"
|
package/src/response.ts
CHANGED
|
@@ -68,8 +68,8 @@ export class Response<T = any, S = T> implements PromiseLike<S> {
|
|
|
68
68
|
|
|
69
69
|
signal.addEventListener('abort', () => signalAbort())
|
|
70
70
|
|
|
71
|
-
this.once('complete', () => signal.removeEventListener('abort', signalAbort))
|
|
72
|
-
this.once('error', () => signal.removeEventListener('abort', signalAbort))
|
|
71
|
+
void this.once('complete', () => signal.removeEventListener('abort', signalAbort))
|
|
72
|
+
void this.once('error', () => signal.removeEventListener('abort', signalAbort))
|
|
73
73
|
|
|
74
74
|
return this
|
|
75
75
|
}
|
|
@@ -78,6 +78,7 @@ export class Response<T = any, S = T> implements PromiseLike<S> {
|
|
|
78
78
|
this._context.controller.abort(reason)
|
|
79
79
|
}
|
|
80
80
|
|
|
81
|
+
// oxlint-disable-next-line no-thenable
|
|
81
82
|
public then<TResult1 = S, TResult2 = never>(
|
|
82
83
|
onfulfilled?: ((value: S) => TResult1 | PromiseLike<TResult1>) | null,
|
|
83
84
|
onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null
|