@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 CHANGED
@@ -1,57 +1,253 @@
1
- # Zui AI
1
+ # Zai - AI Operations Made Simple
2
2
 
3
- **Zai** (stands for _Zui + AI_) is a lightweight utility library that uses AI to manipulate and generate Zui schemas and objects.
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
- It's built on top of Zui and the Botpress client to interface with the different LLMs.
5
+ ## ✨ Key Features
6
6
 
7
- ## Usage
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
- import Zai from '@botpress/zai'
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: new Client({}), // your botpress client here
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
- ## Array
147
+ ## βš™οΈ Configuration
148
+
149
+ ### Model Selection
18
150
 
19
151
  ```typescript
20
- await zai.filter(['cat', 'dog', 'carrot'], 'is an animal')
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
- // Not implemented yet
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
- ## String
175
+ ### Usage Monitoring
30
176
 
31
177
  ```typescript
32
- await zai.text('a story about ....')
33
- await zai.summarize(book)
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
- // Not implemented yet
37
- // await zai.rate(novel, ['is the novel good?', 'how creative is it?', 'quality of writing', 'is the ending good?'])
38
- // await zai.label(tweet, [{ label: '' }])
39
- // await zai.classify(tweet, [])
181
+ console.log({
182
+ tokens: usage.totalTokens,
183
+ cost: usage.totalCost,
184
+ latency: usage.totalLatency,
185
+ })
40
186
  ```
41
187
 
42
- ## Boolean
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.check({ name: 'hey', bio: '...' }, 'contains insults')
201
+ const processedData = await zai.with({ temperature: 0.3 }).learn('data-extraction').extract(document, complexSchema)
46
202
  ```
47
203
 
48
- ## Object
204
+ ### Handling Large Documents
49
205
 
50
206
  ```typescript
51
- await zai.extract('My name is Sly and I am from Canada !', z.object({ name: z.string(), country: z.string() }))
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
- // Not implemented yet
54
- // await zai.extend({ name: 'Sylvain' }, z.object({ country: z.string() }))
55
- // await zai.diff(before, after)
56
- // await zai.edit(object, '')
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.2",
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.31",
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