@botpress/zai 1.0.0-beta.2 → 1.0.0-beta.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.
Files changed (39) hide show
  1. package/package.json +9 -2
  2. package/dist/src/operations/check.test.js +0 -129
  3. package/dist/src/operations/extract.test.js +0 -163
  4. package/dist/src/operations/filter.test.js +0 -151
  5. package/dist/src/operations/label.test.js +0 -213
  6. package/dist/src/operations/rewrite.test.js +0 -96
  7. package/dist/src/operations/summarize.test.js +0 -22
  8. package/dist/src/operations/text.test.js +0 -51
  9. package/dist/src/operations/zai-learn.test.js +0 -71
  10. package/dist/src/operations/zai-retry.test.js +0 -50
  11. package/src/adapters/adapter.ts +0 -35
  12. package/src/adapters/botpress-table.ts +0 -213
  13. package/src/adapters/memory.ts +0 -13
  14. package/src/env.ts +0 -54
  15. package/src/index.ts +0 -11
  16. package/src/models.ts +0 -347
  17. package/src/operations/__tests/botpress_docs.txt +0 -26040
  18. package/src/operations/__tests/index.ts +0 -30
  19. package/src/operations/check.test.ts +0 -155
  20. package/src/operations/check.ts +0 -187
  21. package/src/operations/constants.ts +0 -2
  22. package/src/operations/errors.ts +0 -9
  23. package/src/operations/extract.test.ts +0 -209
  24. package/src/operations/extract.ts +0 -291
  25. package/src/operations/filter.test.ts +0 -182
  26. package/src/operations/filter.ts +0 -231
  27. package/src/operations/label.test.ts +0 -239
  28. package/src/operations/label.ts +0 -332
  29. package/src/operations/rewrite.test.ts +0 -114
  30. package/src/operations/rewrite.ts +0 -148
  31. package/src/operations/summarize.test.ts +0 -25
  32. package/src/operations/summarize.ts +0 -193
  33. package/src/operations/text.test.ts +0 -60
  34. package/src/operations/text.ts +0 -63
  35. package/src/operations/zai-learn.test.ts +0 -85
  36. package/src/operations/zai-retry.test.ts +0 -64
  37. package/src/scripts/update-models.ts +0 -74
  38. package/src/utils.ts +0 -61
  39. package/src/zai.ts +0 -185
@@ -1,74 +0,0 @@
1
- import '../env.ts'
2
-
3
- import { Client } from '@botpress/client'
4
- import { llm } from '@botpress/shared/interfaces'
5
- import dotenv from 'dotenv'
6
- import _ from 'lodash'
7
- import fs from 'node:fs'
8
- import path from 'node:path'
9
-
10
- const envLocal = [
11
- path.resolve('.', '.env.local'),
12
- path.resolve('../', '.env.local'),
13
- path.resolve('../..', '.env.local'),
14
- path.resolve('../../..', '.env.local')
15
- ].find(fs.existsSync)
16
-
17
- if (envLocal) {
18
- dotenv.config({ path: envLocal })
19
- }
20
-
21
- const LLM_LIST_MODELS = 'listLanguageModels' satisfies keyof typeof llm.definition.actions
22
-
23
- const client = new Client({
24
- apiUrl: process.env.VITE_CLOUD_API_ENDPOINT,
25
- botId: process.env.VITE_BOT_ID,
26
- token: process.env.VITE_CLOUD_PAT
27
- })
28
-
29
- const { bot } = await client.getBot({
30
- id: process.env.VITE_BOT_ID!
31
- })
32
-
33
- type Model = llm.Model & {
34
- integration: string
35
- }
36
-
37
- const models: Model[] = []
38
-
39
- for (const integrationId in bot.integrations) {
40
- const botIntegration = bot.integrations[integrationId]
41
- if (botIntegration.public && botIntegration.enabled && botIntegration.status === 'registered') {
42
- try {
43
- const { integration } = await client.getPublicIntegrationById({
44
- id: botIntegration.id
45
- })
46
-
47
- const canListModels = Object.keys(integration.actions).includes(LLM_LIST_MODELS)
48
- if (!canListModels) {
49
- continue
50
- }
51
-
52
- const { output } = await client.callAction({
53
- type: `${integration.name}:${LLM_LIST_MODELS}`,
54
- input: {}
55
- })
56
-
57
- if (_.isArray(output?.models)) {
58
- for (const model of output.models) {
59
- models.push({
60
- ...model,
61
- id: `${integration.name}__${model.id}`,
62
- integration: integration.name
63
- })
64
- }
65
- }
66
- } catch (err) {
67
- console.error('Error fetching integration:', err.message)
68
- }
69
- }
70
- }
71
-
72
- const content = JSON.stringify(_.orderBy(models, ['integration', 'name']), null, 2)
73
-
74
- fs.writeFileSync('./src/models.ts', `export const Models = ${content} as const`, 'utf-8')
package/src/utils.ts DELETED
@@ -1,61 +0,0 @@
1
- import { Client } from '@botpress/client'
2
- import { z } from '@bpinternal/zui'
3
-
4
- export const stringify = (input: unknown, beautify = true) => {
5
- return typeof input === 'string' && !!input.length
6
- ? input
7
- : input
8
- ? JSON.stringify(input, beautify ? null : undefined, beautify ? 2 : undefined)
9
- : '<input is null, false, undefined or empty>'
10
- }
11
-
12
- export const BotpressClient = z.custom<Client>(
13
- (value) =>
14
- typeof value === 'object' && value !== null && 'callAction' in value && typeof value.callAction === 'function',
15
- {
16
- message: 'Invalid Botpress Client. Make sure to pass an instance of @botpress/client'
17
- }
18
- )
19
-
20
- export function fastHash(str: string): string {
21
- let hash = 0
22
- for (let i = 0; i < str.length; i++) {
23
- hash = (hash << 5) - hash + str.charCodeAt(i)
24
- hash |= 0 // Convert to 32bit integer
25
- }
26
- return (hash >>> 0).toString(16) // Convert to unsigned and then to hex
27
- }
28
-
29
- export const takeUntilTokens = <T>(arr: T[], tokens: number, count: (el: T) => number) => {
30
- const result: T[] = []
31
- let total = 0
32
-
33
- for (const value of arr) {
34
- const valueTokens = count(value)
35
- if (total + valueTokens > tokens) {
36
- break
37
- }
38
- total += valueTokens
39
- result.push(value)
40
- }
41
-
42
- return result
43
- }
44
-
45
- export type GenerationMetadata = z.input<typeof GenerationMetadata>
46
- export const GenerationMetadata = z.object({
47
- model: z.string(),
48
- cost: z
49
- .object({
50
- input: z.number(),
51
- output: z.number()
52
- })
53
- .describe('Cost in $USD'),
54
- latency: z.number().describe('Latency in milliseconds'),
55
- tokens: z
56
- .object({
57
- input: z.number(),
58
- output: z.number()
59
- })
60
- .describe('Number of tokens used')
61
- })
package/src/zai.ts DELETED
@@ -1,185 +0,0 @@
1
- import { Client } from '@botpress/client'
2
- /**
3
- * Only for typing purposes
4
- * @internal
5
- */
6
- import { type llm } from '@botpress/shared/interfaces'
7
- import { type TextTokenizer, getWasmTokenizer } from '@botpress/wasm'
8
- import { z } from '@bpinternal/zui'
9
-
10
- import { Adapter } from './adapters/adapter'
11
- import { TableAdapter } from './adapters/botpress-table'
12
- import { MemoryAdapter } from './adapters/memory'
13
- import { Models } from './models'
14
- import { BotpressClient, GenerationMetadata } from './utils'
15
-
16
- type ModelId = (typeof Models)[number]['id']
17
-
18
- type ActiveLearning = z.input<typeof ActiveLearning>
19
- const ActiveLearning = z.object({
20
- enable: z.boolean().describe('Whether to enable active learning').default(false),
21
- tableName: z
22
- .string()
23
- .regex(
24
- /^[A-Za-z0-9_/-]{1,100}Table$/,
25
- 'Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes'
26
- )
27
- .describe('The name of the table to store active learning tasks')
28
- .default('ActiveLearningTable'),
29
- taskId: z
30
- .string()
31
- .regex(
32
- /^[A-Za-z0-9_/-]{1,100}$/,
33
- 'Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes'
34
- )
35
- .describe('The ID of the task')
36
- .default('default')
37
- })
38
-
39
- type ZaiConfig = z.input<typeof ZaiConfig>
40
- const ZaiConfig = z.object({
41
- client: BotpressClient,
42
- userId: z.string().describe('The ID of the user consuming the API').optional(),
43
- retry: z.object({ maxRetries: z.number().min(0).max(100) }).default({ maxRetries: 3 }),
44
- modelId: z
45
- .custom<ModelId>(
46
- (value) => {
47
- if (typeof value !== 'string' || !value.includes('__')) {
48
- return false
49
- }
50
-
51
- return true
52
- },
53
- {
54
- message: 'Invalid model ID'
55
- }
56
- )
57
- .describe('The ID of the model you want to use')
58
- .default('openai__gpt-4o-mini-2024-07-18' satisfies ModelId),
59
- activeLearning: ActiveLearning.default({ enable: false }),
60
- namespace: z
61
- .string()
62
- .regex(
63
- /^[A-Za-z0-9_/-]{1,100}$/,
64
- 'Namespace must be alphanumeric and contain only letters, numbers, underscores, hyphens and slashes'
65
- )
66
- .default('zai')
67
- })
68
-
69
- export class Zai {
70
- protected static tokenizer: TextTokenizer = null!
71
- protected client: Client
72
-
73
- private originalConfig: ZaiConfig
74
-
75
- private userId: string | undefined
76
- private integration: string
77
- private model: string
78
- private retry: { maxRetries: number }
79
-
80
- protected Model: (typeof Models)[number]
81
- protected namespace: string
82
- protected adapter: Adapter
83
- protected activeLearning: ActiveLearning
84
-
85
- constructor(config: ZaiConfig) {
86
- this.originalConfig = config
87
- const parsed = ZaiConfig.parse(config)
88
-
89
- this.client = parsed.client
90
- const [integration, modelId] = parsed.modelId.split('__')
91
- this.integration = integration
92
- this.model = modelId
93
- this.namespace = parsed.namespace
94
- this.userId = parsed.userId
95
- this.retry = parsed.retry as typeof this.retry
96
- this.Model = Models.find((m) => m.id === parsed.modelId)!
97
- this.activeLearning = parsed.activeLearning
98
-
99
- this.adapter = parsed.activeLearning?.enable
100
- ? new TableAdapter({ client: this.client, tableName: parsed.activeLearning.tableName })
101
- : new MemoryAdapter([])
102
- }
103
-
104
- /** @internal */
105
- protected async callModel(
106
- props: Partial<llm.GenerateContentInput>
107
- ): Promise<llm.GenerateContentOutput & { metadata: GenerationMetadata }> {
108
- let retries = this.retry.maxRetries
109
- while (retries-- >= 0) {
110
- try {
111
- return await this._callModel(props)
112
- } catch (e) {
113
- if (retries >= 0) {
114
- await new Promise((resolve) => setTimeout(resolve, 1000))
115
- } else {
116
- throw new Error('Failed to call model after multiple retries', e)
117
- }
118
- }
119
- }
120
-
121
- throw new Error('Failed to call model after multiple retries')
122
- }
123
-
124
- /** @internal */
125
- private async _callModel(
126
- props: Partial<llm.GenerateContentInput>
127
- ): Promise<llm.GenerateContentOutput & { metadata: GenerationMetadata }> {
128
- let retries = this.retry.maxRetries
129
- do {
130
- const start = Date.now()
131
- const input: llm.GenerateContentInput = {
132
- messages: [],
133
- temperature: 0.0,
134
- topP: 1,
135
- model: { id: this.model },
136
- userId: this.userId,
137
- ...props
138
- }
139
-
140
- const { output } = (await this.client.callAction({
141
- type: `${this.integration}:generateContent`,
142
- input
143
- })) as unknown as { output: llm.GenerateContentOutput }
144
-
145
- const latency = Date.now() - start
146
-
147
- return {
148
- ...output,
149
- metadata: {
150
- model: this.model,
151
- latency,
152
- cost: { input: output.usage.inputCost, output: output.usage.outputCost },
153
- tokens: { input: output.usage.inputTokens, output: output.usage.outputTokens }
154
- }
155
- }
156
- } while (--retries > 0)
157
- }
158
-
159
- protected async getTokenizer() {
160
- Zai.tokenizer ??= await getWasmTokenizer()
161
- return Zai.tokenizer
162
- }
163
-
164
- protected get taskId() {
165
- if (!this.activeLearning.enable) {
166
- return undefined
167
- }
168
-
169
- return `${this.namespace}/${this.activeLearning.taskId}`.replace(/\/+/g, '/')
170
- }
171
-
172
- public with(options: Partial<ZaiConfig>): Zai {
173
- return new Zai({
174
- ...this.originalConfig,
175
- ...options
176
- })
177
- }
178
-
179
- public learn(taskId: string) {
180
- return new Zai({
181
- ...this.originalConfig,
182
- activeLearning: { ...this.activeLearning, taskId, enable: true }
183
- })
184
- }
185
- }