@botpress/zai 2.4.0 → 2.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1534 -22
- package/dist/operations/answer.js +6 -4
- package/dist/operations/extract.js +5 -1
- package/dist/response.js +166 -1
- package/dist/zai.js +106 -0
- package/e2e/data/cache.jsonl +2 -0
- package/package.json +1 -1
- package/src/context.ts +32 -0
- package/src/operations/answer.ts +105 -9
- package/src/operations/check.ts +75 -1
- package/src/operations/extract.ts +74 -3
- package/src/operations/filter.ts +86 -1
- package/src/operations/group.ts +150 -0
- package/src/operations/label.ts +119 -1
- package/src/operations/rate.ts +112 -2
- package/src/operations/rewrite.ts +84 -1
- package/src/operations/sort.ts +111 -9
- package/src/operations/summarize.ts +74 -1
- package/src/operations/text.ts +50 -1
- package/src/response.ts +264 -2
- package/src/zai.ts +214 -0
package/src/operations/check.ts
CHANGED
|
@@ -33,7 +33,81 @@ const _Options = z.object({
|
|
|
33
33
|
|
|
34
34
|
declare module '@botpress/zai' {
|
|
35
35
|
interface Zai {
|
|
36
|
-
/**
|
|
36
|
+
/**
|
|
37
|
+
* Checks whether a condition is true for the given input, with an explanation.
|
|
38
|
+
*
|
|
39
|
+
* This operation evaluates natural language conditions against your input data,
|
|
40
|
+
* returning both a boolean result and a detailed explanation. Perfect for
|
|
41
|
+
* content moderation, sentiment analysis, quality checks, and business rule validation.
|
|
42
|
+
*
|
|
43
|
+
* @param input - The data to evaluate (text, object, or any value)
|
|
44
|
+
* @param condition - Natural language description of the condition to check
|
|
45
|
+
* @param options - Optional examples to guide the evaluation
|
|
46
|
+
* @returns Response with { value: boolean, explanation: string }, simplified to boolean when awaited
|
|
47
|
+
*
|
|
48
|
+
* @example Basic sentiment check
|
|
49
|
+
* ```typescript
|
|
50
|
+
* const review = "This product exceeded my expectations!"
|
|
51
|
+
* const isPositive = await zai.check(review, 'Is the sentiment positive?')
|
|
52
|
+
* // Result: true
|
|
53
|
+
*
|
|
54
|
+
* // Get full details
|
|
55
|
+
* const { value, explanation } = await zai.check(review, 'Is the sentiment positive?').result()
|
|
56
|
+
* // value: true
|
|
57
|
+
* // explanation: "The review expresses satisfaction and exceeded expectations..."
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* @example Content moderation
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const comment = "Great article! Very informative."
|
|
63
|
+
* const isSpam = await zai.check(comment, 'Is this spam or promotional content?')
|
|
64
|
+
* // Result: false
|
|
65
|
+
*
|
|
66
|
+
* const hasProfanity = await zai.check(comment, 'Does this contain profanity or offensive language?')
|
|
67
|
+
* // Result: false
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @example Business rules validation
|
|
71
|
+
* ```typescript
|
|
72
|
+
* const invoice = {
|
|
73
|
+
* total: 1500,
|
|
74
|
+
* items: ['laptop', 'mouse'],
|
|
75
|
+
* customer: 'Enterprise Corp'
|
|
76
|
+
* }
|
|
77
|
+
*
|
|
78
|
+
* const needsApproval = await zai.check(
|
|
79
|
+
* invoice,
|
|
80
|
+
* 'Does this invoice require manager approval? (over $1000 or enterprise customer)'
|
|
81
|
+
* )
|
|
82
|
+
* // Result: true
|
|
83
|
+
* ```
|
|
84
|
+
*
|
|
85
|
+
* @example With examples for consistency
|
|
86
|
+
* ```typescript
|
|
87
|
+
* const result = await zai.check(text, 'Is this a technical question?', {
|
|
88
|
+
* examples: [
|
|
89
|
+
* {
|
|
90
|
+
* input: 'How do I deploy to production?',
|
|
91
|
+
* check: true,
|
|
92
|
+
* reason: 'Question about deployment process'
|
|
93
|
+
* },
|
|
94
|
+
* {
|
|
95
|
+
* input: 'What time is the meeting?',
|
|
96
|
+
* check: false,
|
|
97
|
+
* reason: 'Not a technical question'
|
|
98
|
+
* }
|
|
99
|
+
* ]
|
|
100
|
+
* })
|
|
101
|
+
* ```
|
|
102
|
+
*
|
|
103
|
+
* @example Quality assurance
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const code = "function add(a, b) { return a + b }"
|
|
106
|
+
* const hasDocumentation = await zai.check(code, 'Is this code properly documented?')
|
|
107
|
+
* const hasTests = await zai.check(code, 'Does this include unit tests?')
|
|
108
|
+
* const followsConventions = await zai.check(code, 'Does this follow naming conventions?')
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
37
111
|
check(
|
|
38
112
|
input: unknown,
|
|
39
113
|
condition: string,
|
|
@@ -41,11 +41,77 @@ type AnyObjectOrArray = Record<string, unknown> | Array<unknown>
|
|
|
41
41
|
|
|
42
42
|
declare module '@botpress/zai' {
|
|
43
43
|
interface Zai {
|
|
44
|
-
/**
|
|
44
|
+
/**
|
|
45
|
+
* Extracts structured data from unstructured text using a Zod schema.
|
|
46
|
+
*
|
|
47
|
+
* This operation uses LLMs to intelligently parse text and extract information
|
|
48
|
+
* according to your schema. It handles large inputs automatically by chunking
|
|
49
|
+
* and supports both objects and arrays.
|
|
50
|
+
*
|
|
51
|
+
* @param input - The text or data to extract information from
|
|
52
|
+
* @param schema - Zod schema defining the structure to extract
|
|
53
|
+
* @param options - Optional configuration for extraction behavior
|
|
54
|
+
* @returns A Response promise that resolves to data matching your schema
|
|
55
|
+
*
|
|
56
|
+
* @example Extract a single object
|
|
57
|
+
* ```typescript
|
|
58
|
+
* import { z } from '@bpinternal/zui'
|
|
59
|
+
*
|
|
60
|
+
* const personSchema = z.object({
|
|
61
|
+
* name: z.string(),
|
|
62
|
+
* age: z.number(),
|
|
63
|
+
* email: z.string().email()
|
|
64
|
+
* })
|
|
65
|
+
*
|
|
66
|
+
* const text = "Contact John Doe (35) at john@example.com"
|
|
67
|
+
* const person = await zai.extract(text, personSchema)
|
|
68
|
+
* // Result: { name: 'John Doe', age: 35, email: 'john@example.com' }
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* @example Extract an array of items
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const productSchema = z.array(z.object({
|
|
74
|
+
* name: z.string(),
|
|
75
|
+
* price: z.number()
|
|
76
|
+
* }))
|
|
77
|
+
*
|
|
78
|
+
* const text = "We have Apple ($1.50), Banana ($0.80), and Orange ($1.20)"
|
|
79
|
+
* const products = await zai.extract(text, productSchema)
|
|
80
|
+
* // Result: [
|
|
81
|
+
* // { name: 'Apple', price: 1.50 },
|
|
82
|
+
* // { name: 'Banana', price: 0.80 },
|
|
83
|
+
* // { name: 'Orange', price: 1.20 }
|
|
84
|
+
* // ]
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @example With custom instructions
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const result = await zai.extract(document, schema, {
|
|
90
|
+
* instructions: 'Only extract confirmed information, skip uncertain data',
|
|
91
|
+
* chunkLength: 10000, // Smaller chunks for better accuracy
|
|
92
|
+
* strict: true // Enforce strict schema validation
|
|
93
|
+
* })
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* @example Track usage and cost
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const response = zai.extract(text, schema)
|
|
99
|
+
*
|
|
100
|
+
* // Monitor progress
|
|
101
|
+
* response.on('progress', (usage) => {
|
|
102
|
+
* console.log(`Tokens used: ${usage.tokens.total}`)
|
|
103
|
+
* console.log(`Cost so far: $${usage.cost.total}`)
|
|
104
|
+
* })
|
|
105
|
+
*
|
|
106
|
+
* // Get full results
|
|
107
|
+
* const { output, usage, elapsed } = await response.result()
|
|
108
|
+
* console.log(`Extraction took ${elapsed}ms and cost $${usage.cost.total}`)
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
45
111
|
extract<S extends OfType<any>>(input: unknown, schema: S, options?: Options): Response<S['_output']>
|
|
46
112
|
}
|
|
47
113
|
}
|
|
48
|
-
|
|
114
|
+
const SPECIAL_CHAR = '■'
|
|
49
115
|
const START = '■json_start■'
|
|
50
116
|
const END = '■json_end■'
|
|
51
117
|
const NO_MORE = '■NO_MORE_ELEMENT■'
|
|
@@ -330,7 +396,12 @@ ${instructions.map((x) => `• ${x}`).join('\n')}
|
|
|
330
396
|
.filter((x) => x.trim().length > 0 && x.includes('}'))
|
|
331
397
|
.map((x) => {
|
|
332
398
|
try {
|
|
333
|
-
|
|
399
|
+
let json = x.slice(0, x.indexOf(END)).trim()
|
|
400
|
+
|
|
401
|
+
if (json.includes(SPECIAL_CHAR)) {
|
|
402
|
+
json = json.slice(0, json.indexOf(SPECIAL_CHAR)).trim()
|
|
403
|
+
}
|
|
404
|
+
|
|
334
405
|
const repairedJson = jsonrepair(json)
|
|
335
406
|
const parsedJson = JSON5.parse(repairedJson)
|
|
336
407
|
const safe = schema.safeParse(parsedJson)
|
package/src/operations/filter.ts
CHANGED
|
@@ -42,7 +42,92 @@ const _Options = z.object({
|
|
|
42
42
|
|
|
43
43
|
declare module '@botpress/zai' {
|
|
44
44
|
interface Zai {
|
|
45
|
-
/**
|
|
45
|
+
/**
|
|
46
|
+
* Filters array elements based on a natural language condition.
|
|
47
|
+
*
|
|
48
|
+
* This operation evaluates each element against a condition using LLMs,
|
|
49
|
+
* returning only elements that match. Handles large arrays automatically
|
|
50
|
+
* by processing in parallel chunks.
|
|
51
|
+
*
|
|
52
|
+
* @param input - Array of elements to filter
|
|
53
|
+
* @param condition - Natural language description of what to keep
|
|
54
|
+
* @param options - Configuration for token limits per item and examples
|
|
55
|
+
* @returns Response promise resolving to filtered array
|
|
56
|
+
*
|
|
57
|
+
* @example Filter positive reviews
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const reviews = [
|
|
60
|
+
* "Great product, love it!",
|
|
61
|
+
* "Terrible quality, broke immediately",
|
|
62
|
+
* "Amazing! Exceeded expectations",
|
|
63
|
+
* "Worst purchase ever"
|
|
64
|
+
* ]
|
|
65
|
+
*
|
|
66
|
+
* const positive = await zai.filter(reviews, 'Keep only positive reviews')
|
|
67
|
+
* // Result: ["Great product, love it!", "Amazing! Exceeded expectations"]
|
|
68
|
+
* ```
|
|
69
|
+
*
|
|
70
|
+
* @example Filter technical questions
|
|
71
|
+
* ```typescript
|
|
72
|
+
* const questions = [
|
|
73
|
+
* "How do I deploy to production?",
|
|
74
|
+
* "What time is lunch?",
|
|
75
|
+
* "Why is the API returning 500 errors?",
|
|
76
|
+
* "Can you book the conference room?"
|
|
77
|
+
* ]
|
|
78
|
+
*
|
|
79
|
+
* const technical = await zai.filter(
|
|
80
|
+
* questions,
|
|
81
|
+
* 'Keep only technical or engineering questions'
|
|
82
|
+
* )
|
|
83
|
+
* // Result: ["How do I deploy to production?", "Why is the API returning 500 errors?"]
|
|
84
|
+
* ```
|
|
85
|
+
*
|
|
86
|
+
* @example Filter with object array
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const products = [
|
|
89
|
+
* { name: 'Laptop', category: 'Electronics', inStock: true },
|
|
90
|
+
* { name: 'Desk', category: 'Furniture', inStock: false },
|
|
91
|
+
* { name: 'Mouse', category: 'Electronics', inStock: true },
|
|
92
|
+
* { name: 'Chair', category: 'Furniture', inStock: true }
|
|
93
|
+
* ]
|
|
94
|
+
*
|
|
95
|
+
* const available = await zai.filter(
|
|
96
|
+
* products,
|
|
97
|
+
* 'Keep only products that are in stock'
|
|
98
|
+
* )
|
|
99
|
+
* // Returns products where inStock === true
|
|
100
|
+
* ```
|
|
101
|
+
*
|
|
102
|
+
* @example Complex filtering logic
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const emails = [...] // Array of email objects
|
|
105
|
+
*
|
|
106
|
+
* const urgent = await zai.filter(
|
|
107
|
+
* emails,
|
|
108
|
+
* 'Keep emails that are urgent, from the CEO, or mention "critical bug"'
|
|
109
|
+
* )
|
|
110
|
+
* ```
|
|
111
|
+
*
|
|
112
|
+
* @example With examples for consistency
|
|
113
|
+
* ```typescript
|
|
114
|
+
* const filtered = await zai.filter(items, 'Keep valid entries', {
|
|
115
|
+
* examples: [
|
|
116
|
+
* {
|
|
117
|
+
* input: { status: 'active', verified: true },
|
|
118
|
+
* filter: true,
|
|
119
|
+
* reason: 'Active and verified'
|
|
120
|
+
* },
|
|
121
|
+
* {
|
|
122
|
+
* input: { status: 'pending', verified: false },
|
|
123
|
+
* filter: false,
|
|
124
|
+
* reason: 'Not yet verified'
|
|
125
|
+
* }
|
|
126
|
+
* ],
|
|
127
|
+
* tokensPerItem: 100 // Limit tokens per item for performance
|
|
128
|
+
* })
|
|
129
|
+
* ```
|
|
130
|
+
*/
|
|
46
131
|
filter<T>(input: Array<T>, condition: string, options?: Options): Response<Array<T>>
|
|
47
132
|
}
|
|
48
133
|
}
|
package/src/operations/group.ts
CHANGED
|
@@ -43,6 +43,156 @@ const _Options = z.object({
|
|
|
43
43
|
|
|
44
44
|
declare module '@botpress/zai' {
|
|
45
45
|
interface Zai {
|
|
46
|
+
/**
|
|
47
|
+
* Groups array items into categories based on semantic similarity or criteria.
|
|
48
|
+
*
|
|
49
|
+
* This operation intelligently categorizes items by analyzing their content and
|
|
50
|
+
* creating meaningful groups. It can discover natural groupings automatically or
|
|
51
|
+
* use predefined categories. Perfect for clustering, classification, and organization.
|
|
52
|
+
*
|
|
53
|
+
* @param input - Array of items to group
|
|
54
|
+
* @param options - Configuration for grouping behavior, instructions, and initial categories
|
|
55
|
+
* @returns Response with groups array (simplified to Record<groupLabel, items[]>)
|
|
56
|
+
*
|
|
57
|
+
* @example Automatic grouping
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const messages = [
|
|
60
|
+
* "I can't log in to my account",
|
|
61
|
+
* "How do I reset my password?",
|
|
62
|
+
* "When will my order arrive?",
|
|
63
|
+
* "The app keeps crashing",
|
|
64
|
+
* "I haven't received my package",
|
|
65
|
+
* "Error 500 on checkout"
|
|
66
|
+
* ]
|
|
67
|
+
*
|
|
68
|
+
* const groups = await zai.group(messages, {
|
|
69
|
+
* instructions: 'Group by type of customer issue'
|
|
70
|
+
* })
|
|
71
|
+
* // Result (simplified):
|
|
72
|
+
* // {
|
|
73
|
+
* // "Login Issues": ["I can't log in...", "How do I reset..."],
|
|
74
|
+
* // "Shipping Questions": ["When will my order...", "I haven't received..."],
|
|
75
|
+
* // "Technical Errors": ["The app keeps crashing", "Error 500..."]
|
|
76
|
+
* // }
|
|
77
|
+
*
|
|
78
|
+
* // Full result:
|
|
79
|
+
* const { output } = await zai.group(messages, { instructions: '...' }).result()
|
|
80
|
+
* // output: [
|
|
81
|
+
* // { id: 'login_issues', label: 'Login Issues', elements: [...] },
|
|
82
|
+
* // { id: 'shipping', label: 'Shipping Questions', elements: [...] },
|
|
83
|
+
* // { id: 'errors', label: 'Technical Errors', elements: [...] }
|
|
84
|
+
* // ]
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* @example With predefined categories
|
|
88
|
+
* ```typescript
|
|
89
|
+
* const articles = [
|
|
90
|
+
* "How to build a React app",
|
|
91
|
+
* "Python machine learning tutorial",
|
|
92
|
+
* "Understanding Docker containers",
|
|
93
|
+
* "Vue.js best practices",
|
|
94
|
+
* "Deep learning with TensorFlow"
|
|
95
|
+
* ]
|
|
96
|
+
*
|
|
97
|
+
* const groups = await zai.group(articles, {
|
|
98
|
+
* instructions: 'Categorize by technology',
|
|
99
|
+
* initialGroups: [
|
|
100
|
+
* { id: 'frontend', label: 'Frontend Development' },
|
|
101
|
+
* { id: 'backend', label: 'Backend Development' },
|
|
102
|
+
* { id: 'ml', label: 'Machine Learning' },
|
|
103
|
+
* { id: 'devops', label: 'DevOps & Infrastructure' }
|
|
104
|
+
* ]
|
|
105
|
+
* })
|
|
106
|
+
* // Groups articles into predefined categories
|
|
107
|
+
* ```
|
|
108
|
+
*
|
|
109
|
+
* @example Grouping products
|
|
110
|
+
* ```typescript
|
|
111
|
+
* const products = [
|
|
112
|
+
* { name: 'Laptop', price: 999, category: 'Electronics' },
|
|
113
|
+
* { name: 'Desk', price: 299, category: 'Furniture' },
|
|
114
|
+
* { name: 'Mouse', price: 29, category: 'Electronics' },
|
|
115
|
+
* { name: 'Chair', price: 199, category: 'Furniture' }
|
|
116
|
+
* ]
|
|
117
|
+
*
|
|
118
|
+
* const grouped = await zai.group(products, {
|
|
119
|
+
* instructions: 'Group by price range: budget (< $100), mid-range ($100-$500), premium (> $500)'
|
|
120
|
+
* })
|
|
121
|
+
* // Result:
|
|
122
|
+
* // {
|
|
123
|
+
* // "Budget": [Mouse],
|
|
124
|
+
* // "Mid-range": [Chair, Desk],
|
|
125
|
+
* // "Premium": [Laptop]
|
|
126
|
+
* // }
|
|
127
|
+
* ```
|
|
128
|
+
*
|
|
129
|
+
* @example Content categorization
|
|
130
|
+
* ```typescript
|
|
131
|
+
* const emails = [
|
|
132
|
+
* { subject: 'Meeting tomorrow', body: '...', from: 'boss@company.com' },
|
|
133
|
+
* { subject: 'Invoice #1234', body: '...', from: 'billing@vendor.com' },
|
|
134
|
+
* { subject: 'Weekly report', body: '...', from: 'team@company.com' },
|
|
135
|
+
* { subject: 'Payment received', body: '...', from: 'accounting@company.com' }
|
|
136
|
+
* ]
|
|
137
|
+
*
|
|
138
|
+
* const categorized = await zai.group(emails, {
|
|
139
|
+
* instructions: 'Categorize by email type: work communication, financial, reports',
|
|
140
|
+
* tokensPerElement: 300 // Allow more context per email
|
|
141
|
+
* })
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @example Customer feedback grouping
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const feedback = [
|
|
147
|
+
* "Love the new UI!",
|
|
148
|
+
* "App is too slow",
|
|
149
|
+
* "Great customer service",
|
|
150
|
+
* "Confusing navigation",
|
|
151
|
+
* "Fast shipping!",
|
|
152
|
+
* "Hard to find features"
|
|
153
|
+
* ]
|
|
154
|
+
*
|
|
155
|
+
* const grouped = await zai.group(feedback, {
|
|
156
|
+
* instructions: 'Group by aspect: UI/UX, Performance, Customer Service, Shipping'
|
|
157
|
+
* })
|
|
158
|
+
* ```
|
|
159
|
+
*
|
|
160
|
+
* @example Topic clustering for research
|
|
161
|
+
* ```typescript
|
|
162
|
+
* const papers = [
|
|
163
|
+
* { title: 'Transformer Networks for NLP', abstract: '...' },
|
|
164
|
+
* { title: 'CNN Image Classification', abstract: '...' },
|
|
165
|
+
* { title: 'BERT Language Understanding', abstract: '...' },
|
|
166
|
+
* { title: 'Object Detection with YOLO', abstract: '...' }
|
|
167
|
+
* ]
|
|
168
|
+
*
|
|
169
|
+
* const clusters = await zai.group(papers, {
|
|
170
|
+
* instructions: 'Group by research area',
|
|
171
|
+
* chunkLength: 10000 // Allow more tokens for detailed abstracts
|
|
172
|
+
* })
|
|
173
|
+
* // Result: Groups papers by topic (NLP, Computer Vision, etc.)
|
|
174
|
+
* ```
|
|
175
|
+
*
|
|
176
|
+
* @example With initial seed groups
|
|
177
|
+
* ```typescript
|
|
178
|
+
* const tasks = [
|
|
179
|
+
* "Fix login bug",
|
|
180
|
+
* "Update documentation",
|
|
181
|
+
* "Add dark mode",
|
|
182
|
+
* "Optimize database queries"
|
|
183
|
+
* ]
|
|
184
|
+
*
|
|
185
|
+
* const grouped = await zai.group(tasks, {
|
|
186
|
+
* instructions: 'Categorize development tasks',
|
|
187
|
+
* initialGroups: [
|
|
188
|
+
* { id: 'bugs', label: 'Bug Fixes', elements: [] },
|
|
189
|
+
* { id: 'features', label: 'New Features', elements: [] },
|
|
190
|
+
* { id: 'docs', label: 'Documentation', elements: [] },
|
|
191
|
+
* { id: 'performance', label: 'Performance', elements: [] }
|
|
192
|
+
* ]
|
|
193
|
+
* })
|
|
194
|
+
* ```
|
|
195
|
+
*/
|
|
46
196
|
group<T>(input: Array<T>, options?: Options): Response<Array<Group<T>>, Record<string, T[]>>
|
|
47
197
|
}
|
|
48
198
|
}
|
package/src/operations/label.ts
CHANGED
|
@@ -82,7 +82,125 @@ const _Labels = z.record(z.string().min(1).max(250), z.string()).superRefine((la
|
|
|
82
82
|
|
|
83
83
|
declare module '@botpress/zai' {
|
|
84
84
|
interface Zai {
|
|
85
|
-
/**
|
|
85
|
+
/**
|
|
86
|
+
* Tags input with multiple labels, each with explanation, value, and confidence level.
|
|
87
|
+
*
|
|
88
|
+
* This operation evaluates input against multiple categories simultaneously, providing
|
|
89
|
+
* nuanced confidence levels (ABSOLUTELY_YES, PROBABLY_YES, AMBIGUOUS, PROBABLY_NOT, ABSOLUTELY_NOT).
|
|
90
|
+
* Perfect for content classification, intent detection, and multi-criteria evaluation.
|
|
91
|
+
*
|
|
92
|
+
* @param input - The data to label (text, object, or any value)
|
|
93
|
+
* @param labels - Object mapping label keys to their descriptions
|
|
94
|
+
* @param options - Configuration for examples, instructions, and chunking
|
|
95
|
+
* @returns Response with detailed results per label (explanation, value, confidence), simplified to booleans
|
|
96
|
+
*
|
|
97
|
+
* @example Content moderation
|
|
98
|
+
* ```typescript
|
|
99
|
+
* const comment = "This is a great article! Click here for cheap products!"
|
|
100
|
+
*
|
|
101
|
+
* const result = await zai.label(comment, {
|
|
102
|
+
* spam: 'Is this spam or promotional content?',
|
|
103
|
+
* helpful: 'Is this comment helpful and constructive?',
|
|
104
|
+
* profanity: 'Does this contain profanity or offensive language?'
|
|
105
|
+
* }).result()
|
|
106
|
+
*
|
|
107
|
+
* // result.output:
|
|
108
|
+
* // {
|
|
109
|
+
* // spam: { value: true, confidence: 0.5, explanation: 'Contains promotional link...' },
|
|
110
|
+
* // helpful: { value: true, confidence: 1, explanation: 'Positive feedback...' },
|
|
111
|
+
* // profanity: { value: false, confidence: 1, explanation: 'No offensive language' }
|
|
112
|
+
* // }
|
|
113
|
+
*
|
|
114
|
+
* // Simplified (when awaited directly):
|
|
115
|
+
* const simple = await zai.label(comment, { spam: 'Is this spam?' })
|
|
116
|
+
* // simple: { spam: true }
|
|
117
|
+
* ```
|
|
118
|
+
*
|
|
119
|
+
* @example Intent classification
|
|
120
|
+
* ```typescript
|
|
121
|
+
* const message = "I can't log in to my account"
|
|
122
|
+
*
|
|
123
|
+
* const intents = await zai.label(message, {
|
|
124
|
+
* technical_issue: 'Is this a technical problem?',
|
|
125
|
+
* urgent: 'Does this require immediate attention?',
|
|
126
|
+
* needs_human: 'Should this be escalated to a human agent?',
|
|
127
|
+
* billing_related: 'Is this about billing or payments?'
|
|
128
|
+
* })
|
|
129
|
+
* // Returns boolean for each intent
|
|
130
|
+
* ```
|
|
131
|
+
*
|
|
132
|
+
* @example Sentiment analysis with nuance
|
|
133
|
+
* ```typescript
|
|
134
|
+
* const review = "The product is okay, but shipping was slow"
|
|
135
|
+
*
|
|
136
|
+
* const { output } = await zai.label(review, {
|
|
137
|
+
* positive: 'Is the overall sentiment positive?',
|
|
138
|
+
* negative: 'Is the overall sentiment negative?',
|
|
139
|
+
* mixed: 'Does this express mixed feelings?'
|
|
140
|
+
* }).result()
|
|
141
|
+
*
|
|
142
|
+
* // Check confidence levels
|
|
143
|
+
* if (output.mixed.confidence > 0.5) {
|
|
144
|
+
* console.log('Mixed sentiment detected:', output.mixed.explanation)
|
|
145
|
+
* }
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* @example Product categorization
|
|
149
|
+
* ```typescript
|
|
150
|
+
* const product = {
|
|
151
|
+
* name: 'Wireless Headphones',
|
|
152
|
+
* description: 'Noise-canceling Bluetooth headphones for music lovers',
|
|
153
|
+
* price: 199
|
|
154
|
+
* }
|
|
155
|
+
*
|
|
156
|
+
* const categories = await zai.label(product, {
|
|
157
|
+
* electronics: 'Is this an electronic device?',
|
|
158
|
+
* audio: 'Is this audio equipment?',
|
|
159
|
+
* premium: 'Is this a premium/luxury product?',
|
|
160
|
+
* portable: 'Is this portable/mobile?'
|
|
161
|
+
* })
|
|
162
|
+
* // Returns: { electronics: true, audio: true, premium: true, portable: true }
|
|
163
|
+
* ```
|
|
164
|
+
*
|
|
165
|
+
* @example With examples for consistency
|
|
166
|
+
* ```typescript
|
|
167
|
+
* const result = await zai.label(email, {
|
|
168
|
+
* urgent: 'Requires immediate response',
|
|
169
|
+
* complaint: 'Customer is dissatisfied'
|
|
170
|
+
* }, {
|
|
171
|
+
* examples: [
|
|
172
|
+
* {
|
|
173
|
+
* input: 'ASAP! System is down!',
|
|
174
|
+
* labels: {
|
|
175
|
+
* urgent: { label: 'ABSOLUTELY_YES', explanation: 'Critical issue' },
|
|
176
|
+
* complaint: { label: 'PROBABLY_YES', explanation: 'Implicit complaint' }
|
|
177
|
+
* }
|
|
178
|
+
* }
|
|
179
|
+
* ],
|
|
180
|
+
* instructions: 'Consider tone, urgency keywords, and context'
|
|
181
|
+
* })
|
|
182
|
+
* ```
|
|
183
|
+
*
|
|
184
|
+
* @example Understanding confidence levels
|
|
185
|
+
* ```typescript
|
|
186
|
+
* const { output } = await zai.label(text, labels).result()
|
|
187
|
+
*
|
|
188
|
+
* // Confidence values:
|
|
189
|
+
* // ABSOLUTELY_YES: confidence = 1.0, value = true
|
|
190
|
+
* // PROBABLY_YES: confidence = 0.5, value = true
|
|
191
|
+
* // AMBIGUOUS: confidence = 0, value = false
|
|
192
|
+
* // PROBABLY_NOT: confidence = 0.5, value = false
|
|
193
|
+
* // ABSOLUTELY_NOT: confidence = 1.0, value = false
|
|
194
|
+
*
|
|
195
|
+
* Object.entries(output).forEach(([key, result]) => {
|
|
196
|
+
* if (result.value && result.confidence === 1) {
|
|
197
|
+
* console.log(`Definitely ${key}:`, result.explanation)
|
|
198
|
+
* } else if (result.value && result.confidence === 0.5) {
|
|
199
|
+
* console.log(`Probably ${key}:`, result.explanation)
|
|
200
|
+
* }
|
|
201
|
+
* })
|
|
202
|
+
* ```
|
|
203
|
+
*/
|
|
86
204
|
label<T extends string>(
|
|
87
205
|
input: unknown,
|
|
88
206
|
labels: Labels<T>,
|
package/src/operations/rate.ts
CHANGED
|
@@ -76,8 +76,118 @@ export type SimplifiedRatingResult<T extends RatingInstructions> = T extends str
|
|
|
76
76
|
declare module '@botpress/zai' {
|
|
77
77
|
interface Zai {
|
|
78
78
|
/**
|
|
79
|
-
* Rates
|
|
80
|
-
*
|
|
79
|
+
* Rates array items on a 1-5 scale based on single or multiple criteria.
|
|
80
|
+
*
|
|
81
|
+
* This operation evaluates each item and assigns numeric ratings (1-5) where:
|
|
82
|
+
* - 1 = Very Bad, 2 = Bad, 3 = Average, 4 = Good, 5 = Very Good
|
|
83
|
+
*
|
|
84
|
+
* Supports both simple single-criterion rating (string instructions) and
|
|
85
|
+
* multi-criteria rating (object with criterion → description mapping).
|
|
86
|
+
*
|
|
87
|
+
* @param input - Array of items to rate
|
|
88
|
+
* @param instructions - Single criterion (string) or multiple criteria (object)
|
|
89
|
+
* @param options - Configuration for chunking and tokens per item
|
|
90
|
+
* @returns Response with ratings array (simplified to numbers for single criterion)
|
|
91
|
+
*
|
|
92
|
+
* @example Single criterion rating
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const reviews = [
|
|
95
|
+
* "Amazing product! Best purchase ever!",
|
|
96
|
+
* "It's okay, nothing special",
|
|
97
|
+
* "Terrible quality, broke immediately"
|
|
98
|
+
* ]
|
|
99
|
+
*
|
|
100
|
+
* const ratings = await zai.rate(reviews, 'Rate the sentiment')
|
|
101
|
+
* // Result: [5, 3, 1] (simplified to numbers)
|
|
102
|
+
*
|
|
103
|
+
* // Get full details
|
|
104
|
+
* const { output } = await zai.rate(reviews, 'Rate the sentiment').result()
|
|
105
|
+
* // output[0]: { sentiment: 5, total: 5 }
|
|
106
|
+
* ```
|
|
107
|
+
*
|
|
108
|
+
* @example Multi-criteria rating
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const essays = [
|
|
111
|
+
* "... student essay text ...",
|
|
112
|
+
* "... another essay ...",
|
|
113
|
+
* ]
|
|
114
|
+
*
|
|
115
|
+
* const ratings = await zai.rate(essays, {
|
|
116
|
+
* grammar: 'Rate the grammar and spelling',
|
|
117
|
+
* clarity: 'Rate how clear and well-organized the writing is',
|
|
118
|
+
* argumentation: 'Rate the strength of arguments and evidence'
|
|
119
|
+
* })
|
|
120
|
+
*
|
|
121
|
+
* // Result: [
|
|
122
|
+
* // { grammar: 4, clarity: 5, argumentation: 3, total: 12 },
|
|
123
|
+
* // { grammar: 3, clarity: 4, argumentation: 4, total: 11 }
|
|
124
|
+
* // ]
|
|
125
|
+
* ```
|
|
126
|
+
*
|
|
127
|
+
* @example Rating customer support conversations
|
|
128
|
+
* ```typescript
|
|
129
|
+
* const conversations = [
|
|
130
|
+
* { agent: 'John', messages: [...], duration: 300 },
|
|
131
|
+
* { agent: 'Jane', messages: [...], duration: 180 }
|
|
132
|
+
* ]
|
|
133
|
+
*
|
|
134
|
+
* const ratings = await zai.rate(conversations, {
|
|
135
|
+
* professionalism: 'How professional was the agent?',
|
|
136
|
+
* helpfulness: 'How helpful was the agent in solving the issue?',
|
|
137
|
+
* efficiency: 'How efficiently was the conversation handled?'
|
|
138
|
+
* })
|
|
139
|
+
*
|
|
140
|
+
* // Calculate average scores
|
|
141
|
+
* const avgProfessionalism = ratings.reduce((sum, r) => sum + r.professionalism, 0) / ratings.length
|
|
142
|
+
* ```
|
|
143
|
+
*
|
|
144
|
+
* @example Rating code quality
|
|
145
|
+
* ```typescript
|
|
146
|
+
* const codeSamples = [
|
|
147
|
+
* "function foo() { return x + y }",
|
|
148
|
+
* "const calculateTotal = (items) => items.reduce((sum, item) => sum + item.price, 0)",
|
|
149
|
+
* ]
|
|
150
|
+
*
|
|
151
|
+
* const quality = await zai.rate(codeSamples, {
|
|
152
|
+
* readability: 'How readable and clear is the code?',
|
|
153
|
+
* best_practices: 'Does it follow coding best practices?',
|
|
154
|
+
* documentation: 'Is the code well-documented?'
|
|
155
|
+
* })
|
|
156
|
+
* ```
|
|
157
|
+
*
|
|
158
|
+
* @example Product review rating
|
|
159
|
+
* ```typescript
|
|
160
|
+
* const products = [
|
|
161
|
+
* { name: 'Laptop', reviews: [...], avgStars: 4.2 },
|
|
162
|
+
* { name: 'Mouse', reviews: [...], avgStars: 3.8 }
|
|
163
|
+
* ]
|
|
164
|
+
*
|
|
165
|
+
* const ratings = await zai.rate(
|
|
166
|
+
* products,
|
|
167
|
+
* 'Rate overall product quality based on reviews and rating',
|
|
168
|
+
* {
|
|
169
|
+
* tokensPerItem: 500, // Allow more tokens for detailed reviews
|
|
170
|
+
* maxItemsPerChunk: 20 // Process 20 products per chunk
|
|
171
|
+
* }
|
|
172
|
+
* )
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* @example Finding highest-rated items
|
|
176
|
+
* ```typescript
|
|
177
|
+
* const ratings = await zai.rate(items, {
|
|
178
|
+
* quality: 'Product quality',
|
|
179
|
+
* value: 'Value for money',
|
|
180
|
+
* design: 'Design and aesthetics'
|
|
181
|
+
* })
|
|
182
|
+
*
|
|
183
|
+
* // Sort by total score
|
|
184
|
+
* const sorted = items
|
|
185
|
+
* .map((item, idx) => ({ item, rating: ratings[idx] }))
|
|
186
|
+
* .sort((a, b) => b.rating.total - a.rating.total)
|
|
187
|
+
*
|
|
188
|
+
* console.log('Top rated:', sorted[0].item)
|
|
189
|
+
* console.log('Score breakdown:', sorted[0].rating)
|
|
190
|
+
* ```
|
|
81
191
|
*/
|
|
82
192
|
rate<T, I extends RatingInstructions>(
|
|
83
193
|
input: Array<T>,
|