@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.
- package/package.json +9 -2
- package/dist/src/operations/check.test.js +0 -129
- package/dist/src/operations/extract.test.js +0 -163
- package/dist/src/operations/filter.test.js +0 -151
- package/dist/src/operations/label.test.js +0 -213
- package/dist/src/operations/rewrite.test.js +0 -96
- package/dist/src/operations/summarize.test.js +0 -22
- package/dist/src/operations/text.test.js +0 -51
- package/dist/src/operations/zai-learn.test.js +0 -71
- package/dist/src/operations/zai-retry.test.js +0 -50
- package/src/adapters/adapter.ts +0 -35
- package/src/adapters/botpress-table.ts +0 -213
- package/src/adapters/memory.ts +0 -13
- package/src/env.ts +0 -54
- package/src/index.ts +0 -11
- package/src/models.ts +0 -347
- package/src/operations/__tests/botpress_docs.txt +0 -26040
- package/src/operations/__tests/index.ts +0 -30
- package/src/operations/check.test.ts +0 -155
- package/src/operations/check.ts +0 -187
- package/src/operations/constants.ts +0 -2
- package/src/operations/errors.ts +0 -9
- package/src/operations/extract.test.ts +0 -209
- package/src/operations/extract.ts +0 -291
- package/src/operations/filter.test.ts +0 -182
- package/src/operations/filter.ts +0 -231
- package/src/operations/label.test.ts +0 -239
- package/src/operations/label.ts +0 -332
- package/src/operations/rewrite.test.ts +0 -114
- package/src/operations/rewrite.ts +0 -148
- package/src/operations/summarize.test.ts +0 -25
- package/src/operations/summarize.ts +0 -193
- package/src/operations/text.test.ts +0 -60
- package/src/operations/text.ts +0 -63
- package/src/operations/zai-learn.test.ts +0 -85
- package/src/operations/zai-retry.test.ts +0 -64
- package/src/scripts/update-models.ts +0 -74
- package/src/utils.ts +0 -61
- 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
|
-
}
|