@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.
Files changed (62) hide show
  1. package/dist/csj/adapters/adapter.js +2 -0
  2. package/dist/csj/adapters/botpress-table.js +173 -0
  3. package/dist/csj/adapters/memory.js +12 -0
  4. package/dist/csj/index.js +9 -0
  5. package/dist/csj/models.js +387 -0
  6. package/dist/csj/operations/check.js +143 -0
  7. package/dist/csj/operations/constants.js +2 -0
  8. package/dist/csj/operations/errors.js +15 -0
  9. package/dist/csj/operations/extract.js +214 -0
  10. package/dist/csj/operations/filter.js +182 -0
  11. package/dist/csj/operations/label.js +242 -0
  12. package/dist/csj/operations/rewrite.js +113 -0
  13. package/dist/csj/operations/summarize.js +134 -0
  14. package/dist/csj/operations/text.js +48 -0
  15. package/dist/csj/utils.js +44 -0
  16. package/dist/csj/zai.js +142 -0
  17. package/dist/esm/adapters/adapter.js +5 -0
  18. package/dist/esm/adapters/botpress-table.js +194 -0
  19. package/dist/esm/adapters/memory.js +15 -0
  20. package/dist/esm/index.js +11 -0
  21. package/dist/esm/models.js +390 -0
  22. package/dist/esm/operations/check.js +149 -0
  23. package/dist/esm/operations/constants.js +6 -0
  24. package/dist/esm/operations/errors.js +18 -0
  25. package/dist/esm/operations/extract.js +217 -0
  26. package/dist/esm/operations/filter.js +189 -0
  27. package/dist/esm/operations/label.js +246 -0
  28. package/dist/esm/operations/rewrite.js +113 -0
  29. package/dist/esm/operations/summarize.js +134 -0
  30. package/dist/esm/operations/text.js +48 -0
  31. package/dist/esm/utils.js +51 -0
  32. package/dist/esm/zai.js +161 -0
  33. package/package.json +17 -13
  34. package/scripts/update-models.mts +76 -0
  35. package/scripts/update-types.mts +59 -0
  36. package/src/adapters/adapter.ts +35 -0
  37. package/src/adapters/botpress-table.ts +214 -0
  38. package/src/adapters/memory.ts +13 -0
  39. package/src/index.ts +11 -0
  40. package/src/models.ts +394 -0
  41. package/src/operations/__tests/botpress_docs.txt +26040 -0
  42. package/src/operations/__tests/cache.jsonl +101 -0
  43. package/src/operations/__tests/index.ts +86 -0
  44. package/src/operations/check.ts +188 -0
  45. package/src/operations/constants.ts +2 -0
  46. package/src/operations/errors.ts +9 -0
  47. package/src/operations/extract.ts +292 -0
  48. package/src/operations/filter.ts +232 -0
  49. package/src/operations/label.ts +333 -0
  50. package/src/operations/rewrite.ts +149 -0
  51. package/src/operations/summarize.ts +194 -0
  52. package/src/operations/text.ts +64 -0
  53. package/src/sdk-interfaces/llm/generateContent.ts +127 -0
  54. package/src/sdk-interfaces/llm/listLanguageModels.ts +19 -0
  55. package/src/utils.ts +62 -0
  56. package/src/zai.ts +193 -0
  57. package/dist/index.cjs +0 -1903
  58. package/dist/index.cjs.map +0 -1
  59. package/dist/index.d.cts +0 -916
  60. package/dist/index.d.ts +0 -916
  61. package/dist/index.js +0 -1873
  62. package/dist/index.js.map +0 -1
@@ -0,0 +1,59 @@
1
+ import { Client } from '@botpress/client'
2
+ import sdk from '@botpress/sdk'
3
+
4
+ import _ from 'lodash'
5
+ import fs from 'node:fs'
6
+ import path from 'node:path'
7
+
8
+ const { z } = sdk
9
+
10
+ const Interfaces = ['llm'] as const
11
+
12
+ const client = new Client({
13
+ apiUrl: process.env.CLOUD_API_ENDPOINT,
14
+ botId: process.env.CLOUD_BOT_ID,
15
+ token: process.env.CLOUD_PAT
16
+ })
17
+
18
+ for (const name of Interfaces) {
19
+ const { interfaces } = await client.listInterfaces({
20
+ name
21
+ })
22
+
23
+ const { interface: latest } = await client.getInterface({
24
+ id: _.maxBy(interfaces, 'version')!.id
25
+ })
26
+
27
+ for (const action of Object.keys(latest.actions)) {
28
+ const references = Object.keys(latest.entities).reduce((acc, key) => {
29
+ return { ...acc, [key]: z.fromJsonSchema(latest.entities?.[key]?.schema!) }
30
+ }, {})
31
+ const input = latest.actions[action]?.input.schema!
32
+ const output = latest.actions[action]?.output.schema!
33
+
34
+ const types = `
35
+ // This file is generated. Do not edit it manually.
36
+ // See 'scripts/update-models.ts'
37
+
38
+ /* eslint-disable */
39
+ /* tslint:disable */
40
+
41
+ export namespace ${name} {
42
+ export namespace ${action} {
43
+ export ${sdk.z
44
+ .fromJsonSchema(input)
45
+ .title('Input')
46
+ .dereference(references)
47
+ .toTypescript({ declaration: 'type' })};
48
+ export ${sdk.z
49
+ .fromJsonSchema(output)
50
+ .title('Output')
51
+ .dereference(references)
52
+ .toTypescript({ declaration: 'type' })};
53
+ }
54
+ }`
55
+
56
+ fs.mkdirSync(path.resolve(`./src/sdk-interfaces/${name}`), { recursive: true })
57
+ fs.writeFileSync(path.resolve(`./src/sdk-interfaces/${name}/${action}.ts`), types)
58
+ }
59
+ }
@@ -0,0 +1,35 @@
1
+ import { GenerationMetadata } from '../utils'
2
+
3
+ export type SaveExampleProps<TInput, TOutput> = {
4
+ key: string
5
+ taskType: string
6
+ taskId: string
7
+ instructions: string
8
+ input: TInput
9
+ output: TOutput
10
+ explanation?: string
11
+ metadata: GenerationMetadata
12
+ status?: 'pending' | 'approved'
13
+ }
14
+
15
+ export type GetExamplesProps<TInput> = {
16
+ taskType: string
17
+ taskId: string
18
+ input: TInput
19
+ }
20
+
21
+ export abstract class Adapter {
22
+ abstract getExamples<TInput, TOutput>(
23
+ props: GetExamplesProps<TInput>
24
+ ): Promise<
25
+ Array<{
26
+ key: string
27
+ input: TInput
28
+ output: TOutput
29
+ explanation?: string
30
+ similarity: number
31
+ }>
32
+ >
33
+
34
+ abstract saveExample<TInput, TOutput>(props: SaveExampleProps<TInput, TOutput>): Promise<void>
35
+ }
@@ -0,0 +1,214 @@
1
+ import { type Client } from '@botpress/client'
2
+ import sdk from '@botpress/sdk'
3
+ const { z } = sdk
4
+
5
+ import { BotpressClient, GenerationMetadata } from '../utils'
6
+ import { Adapter, GetExamplesProps, SaveExampleProps } from './adapter'
7
+
8
+ const CRITICAL_TAGS = {
9
+ system: 'true',
10
+ 'schema-purpose': 'active-learning',
11
+ 'schema-version': 'Oct-2024'
12
+ } as const
13
+
14
+ const OPTIONAL_TAGS = {
15
+ 'x-studio-title': 'Active Learning',
16
+ 'x-studio-description': 'Table for storing active learning tasks and examples',
17
+ 'x-studio-readonly': 'true',
18
+ 'x-studio-icon': 'lucide://atom',
19
+ 'x-studio-color': 'green'
20
+ } as const
21
+
22
+ const FACTOR = 30
23
+
24
+ const Props = z.object({
25
+ client: BotpressClient,
26
+ tableName: z
27
+ .string()
28
+ .regex(
29
+ /^[a-zA-Z0-9_]{1,45}Table$/,
30
+ 'Table name must be lowercase and contain only letters, numbers and underscores'
31
+ )
32
+ })
33
+
34
+ export type TableSchema = sdk.z.input<typeof TableSchema>
35
+ const TableSchema = z.object({
36
+ taskType: z.string().describe('The type of the task (filter, extract, etc.)'),
37
+ taskId: z.string(),
38
+ key: z.string().describe('A unique key for the task (e.g. a hash of the input, taskId, taskType and instructions)'),
39
+ instructions: z.string(),
40
+ input: z.object({}).passthrough().describe('The input to the task'),
41
+ output: z.object({}).passthrough().describe('The expected output'),
42
+ explanation: z.string().nullable(),
43
+ metadata: GenerationMetadata,
44
+ status: z.enum(['pending', 'rejected', 'approved']),
45
+ feedback: z
46
+ .object({
47
+ rating: z.enum(['very-bad', 'bad', 'good', 'very-good']),
48
+ comment: z.string().nullable()
49
+ })
50
+ .nullable()
51
+ .default(null)
52
+ })
53
+
54
+ const searchableColumns = ['input'] as const satisfies Array<keyof typeof TableSchema.shape> as string[]
55
+
56
+ const TableJsonSchema = Object.entries(TableSchema.shape).reduce((acc, [key, value]) => {
57
+ acc[key] = value.toJsonSchema()
58
+ acc[key]['x-zui'] ??= {}
59
+ acc[key]['x-zui'].searchable = searchableColumns.includes(key)
60
+ return acc
61
+ }, {})
62
+
63
+ export class TableAdapter extends Adapter {
64
+ private client: Client
65
+ private tableName: string
66
+
67
+ private status: 'initialized' | 'ready' | 'error'
68
+ private errors = [] as string[]
69
+
70
+ constructor(props: sdk.z.input<typeof Props>) {
71
+ super()
72
+ props = Props.parse(props)
73
+ this.client = props.client
74
+ this.tableName = props.tableName
75
+ this.status = 'ready'
76
+ }
77
+
78
+ public async getExamples<TInput, TOutput>({ taskType, taskId, input }: GetExamplesProps<TInput>) {
79
+ await this.assertTableExists()
80
+
81
+ const { rows } = await this.client
82
+ .findTableRows({
83
+ table: this.tableName,
84
+ search: JSON.stringify({ value: input }).substring(0, 1023), // Search is limited to 1024 characters
85
+ limit: 10, // TODO
86
+ filter: {
87
+ // Proximity match of approved examples
88
+ taskType,
89
+ taskId,
90
+ status: 'approved'
91
+ } satisfies Partial<TableSchema>
92
+ })
93
+ .catch((err) => {
94
+ // TODO: handle error
95
+ console.error(`Error fetching examples: ${err.message}`)
96
+ return { rows: [] }
97
+ })
98
+
99
+ return rows.map((row) => ({
100
+ key: row.key,
101
+ input: row.input.value as TInput,
102
+ output: row.output.value as TOutput,
103
+ explanation: row.explanation,
104
+ similarity: row.similarity ?? 0
105
+ }))
106
+ }
107
+
108
+ public async saveExample<TInput, TOutput>({
109
+ key,
110
+ taskType,
111
+ taskId,
112
+ instructions,
113
+ input,
114
+ output,
115
+ explanation,
116
+ metadata,
117
+ status = 'pending'
118
+ }: SaveExampleProps<TInput, TOutput>) {
119
+ await this.assertTableExists()
120
+
121
+ await this.client
122
+ .upsertTableRows({
123
+ table: this.tableName,
124
+ keyColumn: 'key',
125
+ rows: [
126
+ {
127
+ key,
128
+ taskType,
129
+ taskId,
130
+ instructions,
131
+ input: { value: input },
132
+ output: { value: output },
133
+ explanation: explanation ?? null,
134
+ status,
135
+ metadata
136
+ } satisfies TableSchema
137
+ ]
138
+ })
139
+ .catch(() => {
140
+ // TODO: handle error
141
+ })
142
+ }
143
+
144
+ private async assertTableExists() {
145
+ if (this.status !== 'ready') {
146
+ return
147
+ }
148
+
149
+ const { table, created } = await this.client
150
+ .getOrCreateTable({
151
+ table: this.tableName,
152
+ factor: FACTOR,
153
+ frozen: true,
154
+ isComputeEnabled: false,
155
+ tags: {
156
+ ...CRITICAL_TAGS,
157
+ ...OPTIONAL_TAGS
158
+ },
159
+ schema: TableJsonSchema
160
+ })
161
+ .catch((err) => {
162
+ this.status = 'error'
163
+ this.errors = [err.message]
164
+ return { table: null, created: false }
165
+ })
166
+
167
+ if (!table) {
168
+ return
169
+ }
170
+
171
+ if (!created) {
172
+ const issues: string[] = []
173
+
174
+ if (table.factor !== FACTOR) {
175
+ issues.push(`Factor is ${table.factor} instead of ${FACTOR}`)
176
+ }
177
+
178
+ if (table.frozen !== true) {
179
+ issues.push('Table is not frozen')
180
+ }
181
+
182
+ for (const [key, value] of Object.entries(CRITICAL_TAGS)) {
183
+ if (table.tags?.[key] !== value) {
184
+ issues.push(`Tag ${key} is ${table.tags?.[key]} instead of ${value}`)
185
+ }
186
+ }
187
+
188
+ for (const key of Object.keys(TableJsonSchema)) {
189
+ const column = table.schema?.properties[key]
190
+ const expected = TableJsonSchema[key] as { type: string }
191
+
192
+ if (!column) {
193
+ issues.push(`Column ${key} is missing`)
194
+ continue
195
+ }
196
+
197
+ if (column.type !== expected.type) {
198
+ issues.push(`Column ${key} has type ${column.type} instead of ${expected.type}`)
199
+ }
200
+
201
+ if (expected['x-zui'].searchable && !column['x-zui'].searchable) {
202
+ issues.push(`Column ${key} is not searchable but should be`)
203
+ }
204
+ }
205
+
206
+ if (issues.length) {
207
+ this.status = 'error'
208
+ this.errors = issues
209
+ }
210
+ }
211
+
212
+ this.status = 'initialized'
213
+ }
214
+ }
@@ -0,0 +1,13 @@
1
+ import { Adapter } from './adapter'
2
+
3
+ export class MemoryAdapter extends Adapter {
4
+ constructor(public examples: any[]) {
5
+ super()
6
+ }
7
+
8
+ async getExamples() {
9
+ return this.examples
10
+ }
11
+
12
+ async saveExample() {}
13
+ }
package/src/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import { Zai } from './zai'
2
+
3
+ import './operations/text'
4
+ import './operations/rewrite'
5
+ import './operations/summarize'
6
+ import './operations/check'
7
+ import './operations/filter'
8
+ import './operations/extract'
9
+ import './operations/label'
10
+
11
+ export { Zai }