@botpress/zai 1.1.0 → 2.0.0
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 +1 -1
- package/build.ts +9 -0
- package/dist/adapters/botpress-table.js +21 -21
- package/dist/index.d.ts +27 -517
- package/dist/operations/check.js +22 -6
- package/dist/operations/extract.js +28 -8
- package/dist/operations/filter.js +15 -3
- package/dist/operations/label.js +36 -6
- package/dist/operations/rewrite.js +18 -6
- package/dist/operations/summarize.js +6 -5
- package/dist/operations/text.js +4 -3
- package/dist/utils.js +0 -6
- package/dist/zai.js +28 -68
- package/e2e/data/cache.jsonl +118 -0
- package/{src/operations/__tests/index.ts → e2e/utils.ts} +18 -16
- package/package.json +23 -21
- package/src/adapters/adapter.ts +2 -2
- package/src/adapters/botpress-table.ts +36 -36
- package/src/adapters/memory.ts +3 -3
- package/src/operations/check.ts +53 -20
- package/src/operations/errors.ts +1 -1
- package/src/operations/extract.ts +49 -31
- package/src/operations/filter.ts +36 -23
- package/src/operations/label.ts +73 -25
- package/src/operations/rewrite.ts +28 -15
- package/src/operations/summarize.ts +11 -9
- package/src/operations/text.ts +7 -5
- package/src/utils.ts +5 -14
- package/src/zai.ts +45 -91
- package/tsconfig.json +2 -22
- package/dist/models.js +0 -387
- package/src/models.ts +0 -394
- package/src/operations/__tests/cache.jsonl +0 -101
- package/src/sdk-interfaces/llm/generateContent.ts +0 -127
- package/src/sdk-interfaces/llm/listLanguageModels.ts +0 -19
- /package/{src/operations/__tests → e2e/data}/botpress_docs.txt +0 -0
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { Client } from '@botpress/client'
|
|
2
|
-
import { type TextTokenizer, getWasmTokenizer } from '@
|
|
3
|
-
|
|
2
|
+
import { type TextTokenizer, getWasmTokenizer } from '@bpinternal/thicktoken'
|
|
4
3
|
import fs from 'node:fs'
|
|
5
4
|
import path from 'node:path'
|
|
6
5
|
import { beforeAll } from 'vitest'
|
|
6
|
+
import { Zai } from '../src'
|
|
7
|
+
import { fastHash } from '../src/utils'
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
const DATA_PATH = path.join(__dirname, 'data')
|
|
10
|
+
const CACHE_PATH = path.join(DATA_PATH, 'cache.jsonl')
|
|
11
|
+
const DOC_PATH = path.join(DATA_PATH, 'botpress_docs.txt')
|
|
11
12
|
|
|
12
13
|
export const getClient = () => {
|
|
13
14
|
return new Client({
|
|
14
15
|
apiUrl: process.env.CLOUD_API_ENDPOINT ?? 'https://api.botpress.dev',
|
|
15
16
|
botId: process.env.CLOUD_BOT_ID,
|
|
16
|
-
token: process.env.CLOUD_PAT
|
|
17
|
+
token: process.env.CLOUD_PAT,
|
|
17
18
|
})
|
|
18
19
|
}
|
|
19
20
|
|
|
@@ -31,10 +32,7 @@ function readJSONL<T>(filePath: string, keyProperty: keyof T): Map<string, T> {
|
|
|
31
32
|
return map
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
const cache: Map<string, { key: string; value: any }> = readJSONL(
|
|
35
|
-
path.resolve(import.meta.dirname, './cache.jsonl'),
|
|
36
|
-
'key'
|
|
37
|
-
)
|
|
35
|
+
const cache: Map<string, { key: string; value: any }> = readJSONL(CACHE_PATH, 'key')
|
|
38
36
|
|
|
39
37
|
export const getCachedClient = () => {
|
|
40
38
|
const client = getClient()
|
|
@@ -54,10 +52,10 @@ export const getCachedClient = () => {
|
|
|
54
52
|
cache.set(key, { key, value: response })
|
|
55
53
|
|
|
56
54
|
fs.appendFileSync(
|
|
57
|
-
|
|
55
|
+
CACHE_PATH,
|
|
58
56
|
JSON.stringify({
|
|
59
57
|
key,
|
|
60
|
-
value: response
|
|
58
|
+
value: response,
|
|
61
59
|
}) + '\n'
|
|
62
60
|
)
|
|
63
61
|
|
|
@@ -65,23 +63,27 @@ export const getCachedClient = () => {
|
|
|
65
63
|
}
|
|
66
64
|
}
|
|
67
65
|
return Reflect.get(target, prop)
|
|
68
|
-
}
|
|
66
|
+
},
|
|
69
67
|
})
|
|
70
68
|
|
|
69
|
+
;(proxy as any).clone = () => {
|
|
70
|
+
return getCachedClient()
|
|
71
|
+
}
|
|
72
|
+
|
|
71
73
|
return proxy
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
export const getZai = () => {
|
|
75
77
|
const client = getCachedClient()
|
|
76
|
-
return new Zai({ client
|
|
78
|
+
return new Zai({ client })
|
|
77
79
|
}
|
|
78
80
|
|
|
79
81
|
export let tokenizer: TextTokenizer = null!
|
|
80
82
|
|
|
81
83
|
beforeAll(async () => {
|
|
82
|
-
tokenizer = await getWasmTokenizer()
|
|
84
|
+
tokenizer = (await getWasmTokenizer()) as TextTokenizer
|
|
83
85
|
})
|
|
84
86
|
|
|
85
|
-
export const BotpressDocumentation = fs.readFileSync(
|
|
87
|
+
export const BotpressDocumentation = fs.readFileSync(DOC_PATH, 'utf-8').trim()
|
|
86
88
|
|
|
87
89
|
export const metadata = { cost: { input: 1, output: 1 }, latency: 0, model: '', tokens: { input: 1, output: 1 } }
|
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": "
|
|
4
|
+
"version": "2.0.0",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -10,39 +10,41 @@
|
|
|
10
10
|
"import": "./dist/index.js"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"
|
|
14
|
-
"build
|
|
13
|
+
"check:type": "tsc --noEmit",
|
|
14
|
+
"build": "bp add -y && pnpm run build:types && pnpm run build:neutral",
|
|
15
|
+
"build:neutral": "ts-node -T ./build.ts",
|
|
15
16
|
"build:types": "tsup",
|
|
16
17
|
"watch": "tsup --watch",
|
|
17
|
-
"test": "vitest run --config vitest.config.ts",
|
|
18
|
-
"test:update": "vitest -u run --config vitest.config.ts",
|
|
19
|
-
"test:watch": "vitest --config vitest.config.ts"
|
|
20
|
-
"build-with-latest-models": "pnpm run update-types && pnpm run update-models && pnpm run build",
|
|
21
|
-
"update-models": "ts-node ./scripts/update-models.mts",
|
|
22
|
-
"update-types": "ts-node ./scripts/update-types.mts"
|
|
18
|
+
"test:e2e": "vitest run --config vitest.config.ts",
|
|
19
|
+
"test:e2e:update": "vitest -u run --config vitest.config.ts",
|
|
20
|
+
"test:e2e:watch": "vitest --config vitest.config.ts"
|
|
23
21
|
},
|
|
24
22
|
"keywords": [],
|
|
25
23
|
"author": "",
|
|
26
24
|
"license": "ISC",
|
|
27
25
|
"dependencies": {
|
|
26
|
+
"@botpress/cognitive": "0.1.16",
|
|
28
27
|
"json5": "^2.2.3",
|
|
29
|
-
"jsonrepair": "^3.
|
|
28
|
+
"jsonrepair": "^3.10.0",
|
|
30
29
|
"lodash-es": "^4.17.21"
|
|
31
30
|
},
|
|
32
31
|
"devDependencies": {
|
|
33
|
-
"@botpress/
|
|
32
|
+
"@botpress/client": "workspace:^",
|
|
33
|
+
"@botpress/common": "workspace:*",
|
|
34
|
+
"@botpress/vai": "workspace:*",
|
|
34
35
|
"@types/lodash-es": "^4.17.12",
|
|
35
|
-
"dotenv": "^16.4.
|
|
36
|
-
"esbuild": "^0.
|
|
36
|
+
"dotenv": "^16.4.4",
|
|
37
|
+
"esbuild": "^0.16.12",
|
|
38
|
+
"glob": "^9.3.4",
|
|
37
39
|
"lodash": "^4.17.21",
|
|
38
|
-
"
|
|
39
|
-
"tsup": "^8.3.5",
|
|
40
|
-
"typescript": "^5.7.2",
|
|
41
|
-
"vitest": "^2.1.8"
|
|
40
|
+
"tsup": "^8.0.2"
|
|
42
41
|
},
|
|
43
42
|
"peerDependencies": {
|
|
44
|
-
"@
|
|
45
|
-
"@
|
|
46
|
-
|
|
47
|
-
|
|
43
|
+
"@bpinternal/thicktoken": "^1.0.0",
|
|
44
|
+
"@bpinternal/zui": "^0.17.1"
|
|
45
|
+
},
|
|
46
|
+
"engines": {
|
|
47
|
+
"node": ">=18.0.0"
|
|
48
|
+
},
|
|
49
|
+
"packageManager": "pnpm@8.6.2"
|
|
48
50
|
}
|
package/src/adapters/adapter.ts
CHANGED
|
@@ -19,7 +19,7 @@ export type GetExamplesProps<TInput> = {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
export abstract class Adapter {
|
|
22
|
-
abstract getExamples<TInput, TOutput>(
|
|
22
|
+
public abstract getExamples<TInput, TOutput>(
|
|
23
23
|
props: GetExamplesProps<TInput>
|
|
24
24
|
): Promise<
|
|
25
25
|
Array<{
|
|
@@ -31,5 +31,5 @@ export abstract class Adapter {
|
|
|
31
31
|
}>
|
|
32
32
|
>
|
|
33
33
|
|
|
34
|
-
abstract saveExample<TInput, TOutput>(props: SaveExampleProps<TInput, TOutput>): Promise<void>
|
|
34
|
+
public abstract saveExample<TInput, TOutput>(props: SaveExampleProps<TInput, TOutput>): Promise<void>
|
|
35
35
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { type Client } from '@botpress/client'
|
|
2
2
|
import { z } from '@bpinternal/zui'
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import { GenerationMetadata } from '../utils'
|
|
5
5
|
import { Adapter, GetExamplesProps, SaveExampleProps } from './adapter'
|
|
6
6
|
|
|
7
7
|
const CRITICAL_TAGS = {
|
|
8
8
|
system: 'true',
|
|
9
9
|
'schema-purpose': 'active-learning',
|
|
10
|
-
'schema-version': 'Oct-2024'
|
|
10
|
+
'schema-version': 'Oct-2024',
|
|
11
11
|
} as const
|
|
12
12
|
|
|
13
13
|
const OPTIONAL_TAGS = {
|
|
@@ -15,19 +15,19 @@ const OPTIONAL_TAGS = {
|
|
|
15
15
|
'x-studio-description': 'Table for storing active learning tasks and examples',
|
|
16
16
|
'x-studio-readonly': 'true',
|
|
17
17
|
'x-studio-icon': 'lucide://atom',
|
|
18
|
-
'x-studio-color': 'green'
|
|
18
|
+
'x-studio-color': 'green',
|
|
19
19
|
} as const
|
|
20
20
|
|
|
21
21
|
const FACTOR = 30
|
|
22
22
|
|
|
23
23
|
const Props = z.object({
|
|
24
|
-
client:
|
|
24
|
+
client: z.custom(() => true),
|
|
25
25
|
tableName: z
|
|
26
26
|
.string()
|
|
27
27
|
.regex(
|
|
28
28
|
/^[a-zA-Z0-9_]{1,45}Table$/,
|
|
29
29
|
'Table name must be lowercase and contain only letters, numbers and underscores'
|
|
30
|
-
)
|
|
30
|
+
),
|
|
31
31
|
})
|
|
32
32
|
|
|
33
33
|
export type TableSchema = z.input<typeof TableSchema>
|
|
@@ -44,10 +44,10 @@ const TableSchema = z.object({
|
|
|
44
44
|
feedback: z
|
|
45
45
|
.object({
|
|
46
46
|
rating: z.enum(['very-bad', 'bad', 'good', 'very-good']),
|
|
47
|
-
comment: z.string().nullable()
|
|
47
|
+
comment: z.string().nullable(),
|
|
48
48
|
})
|
|
49
49
|
.nullable()
|
|
50
|
-
.default(null)
|
|
50
|
+
.default(null),
|
|
51
51
|
})
|
|
52
52
|
|
|
53
53
|
const searchableColumns = ['input'] as const satisfies Array<keyof typeof TableSchema.shape> as string[]
|
|
@@ -60,33 +60,33 @@ const TableJsonSchema = Object.entries(TableSchema.shape).reduce((acc, [key, val
|
|
|
60
60
|
}, {})
|
|
61
61
|
|
|
62
62
|
export class TableAdapter extends Adapter {
|
|
63
|
-
private
|
|
64
|
-
private
|
|
63
|
+
private _client: Client
|
|
64
|
+
private _tableName: string
|
|
65
65
|
|
|
66
|
-
private
|
|
66
|
+
private _status: 'initialized' | 'ready' | 'error'
|
|
67
67
|
|
|
68
|
-
constructor(props: z.input<typeof Props>) {
|
|
68
|
+
public constructor(props: z.input<typeof Props>) {
|
|
69
69
|
super()
|
|
70
70
|
props = Props.parse(props)
|
|
71
|
-
this.
|
|
72
|
-
this.
|
|
73
|
-
this.
|
|
71
|
+
this._client = props.client
|
|
72
|
+
this._tableName = props.tableName
|
|
73
|
+
this._status = 'ready'
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
public async getExamples<TInput, TOutput>({ taskType, taskId, input }: GetExamplesProps<TInput>) {
|
|
77
|
-
await this.
|
|
77
|
+
await this._assertTableExists()
|
|
78
78
|
|
|
79
|
-
const { rows } = await this.
|
|
79
|
+
const { rows } = await this._client
|
|
80
80
|
.findTableRows({
|
|
81
|
-
table: this.
|
|
81
|
+
table: this._tableName,
|
|
82
82
|
search: JSON.stringify({ value: input }).substring(0, 1023), // Search is limited to 1024 characters
|
|
83
83
|
limit: 10, // TODO
|
|
84
84
|
filter: {
|
|
85
85
|
// Proximity match of approved examples
|
|
86
86
|
taskType,
|
|
87
87
|
taskId,
|
|
88
|
-
status: 'approved'
|
|
89
|
-
} satisfies Partial<TableSchema
|
|
88
|
+
status: 'approved',
|
|
89
|
+
} satisfies Partial<TableSchema>,
|
|
90
90
|
})
|
|
91
91
|
.catch((err) => {
|
|
92
92
|
// TODO: handle error
|
|
@@ -99,7 +99,7 @@ export class TableAdapter extends Adapter {
|
|
|
99
99
|
input: row.input.value as TInput,
|
|
100
100
|
output: row.output.value as TOutput,
|
|
101
101
|
explanation: row.explanation,
|
|
102
|
-
similarity: row.similarity ?? 0
|
|
102
|
+
similarity: row.similarity ?? 0,
|
|
103
103
|
}))
|
|
104
104
|
}
|
|
105
105
|
|
|
@@ -112,13 +112,13 @@ export class TableAdapter extends Adapter {
|
|
|
112
112
|
output,
|
|
113
113
|
explanation,
|
|
114
114
|
metadata,
|
|
115
|
-
status = 'pending'
|
|
115
|
+
status = 'pending',
|
|
116
116
|
}: SaveExampleProps<TInput, TOutput>) {
|
|
117
|
-
await this.
|
|
117
|
+
await this._assertTableExists()
|
|
118
118
|
|
|
119
|
-
await this.
|
|
119
|
+
await this._client
|
|
120
120
|
.upsertTableRows({
|
|
121
|
-
table: this.
|
|
121
|
+
table: this._tableName,
|
|
122
122
|
keyColumn: 'key',
|
|
123
123
|
rows: [
|
|
124
124
|
{
|
|
@@ -130,34 +130,34 @@ export class TableAdapter extends Adapter {
|
|
|
130
130
|
output: { value: output },
|
|
131
131
|
explanation: explanation ?? null,
|
|
132
132
|
status,
|
|
133
|
-
metadata
|
|
134
|
-
} satisfies TableSchema
|
|
135
|
-
]
|
|
133
|
+
metadata,
|
|
134
|
+
} satisfies TableSchema,
|
|
135
|
+
],
|
|
136
136
|
})
|
|
137
137
|
.catch(() => {
|
|
138
138
|
// TODO: handle error
|
|
139
139
|
})
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
-
private async
|
|
143
|
-
if (this.
|
|
142
|
+
private async _assertTableExists() {
|
|
143
|
+
if (this._status !== 'ready') {
|
|
144
144
|
return
|
|
145
145
|
}
|
|
146
146
|
|
|
147
|
-
const { table, created } = await this.
|
|
147
|
+
const { table, created } = await this._client
|
|
148
148
|
.getOrCreateTable({
|
|
149
|
-
table: this.
|
|
149
|
+
table: this._tableName,
|
|
150
150
|
factor: FACTOR,
|
|
151
151
|
frozen: true,
|
|
152
152
|
isComputeEnabled: false,
|
|
153
153
|
tags: {
|
|
154
154
|
...CRITICAL_TAGS,
|
|
155
|
-
...OPTIONAL_TAGS
|
|
155
|
+
...OPTIONAL_TAGS,
|
|
156
156
|
},
|
|
157
|
-
schema: TableJsonSchema
|
|
157
|
+
schema: TableJsonSchema,
|
|
158
158
|
})
|
|
159
159
|
.catch(() => {
|
|
160
|
-
this.
|
|
160
|
+
this._status = 'error'
|
|
161
161
|
return { table: null, created: false }
|
|
162
162
|
})
|
|
163
163
|
|
|
@@ -201,10 +201,10 @@ export class TableAdapter extends Adapter {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
if (issues.length) {
|
|
204
|
-
this.
|
|
204
|
+
this._status = 'error'
|
|
205
205
|
}
|
|
206
206
|
}
|
|
207
207
|
|
|
208
|
-
this.
|
|
208
|
+
this._status = 'initialized'
|
|
209
209
|
}
|
|
210
210
|
}
|
package/src/adapters/memory.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { Adapter } from './adapter'
|
|
2
2
|
|
|
3
3
|
export class MemoryAdapter extends Adapter {
|
|
4
|
-
constructor(public examples: any[]) {
|
|
4
|
+
public constructor(public examples: any[]) {
|
|
5
5
|
super()
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
async getExamples() {
|
|
8
|
+
public async getExamples() {
|
|
9
9
|
return this.examples
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
async saveExample() {}
|
|
12
|
+
public async saveExample() {}
|
|
13
13
|
}
|
package/src/operations/check.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// eslint-disable consistent-type-definitions
|
|
1
2
|
import { z } from '@bpinternal/zui'
|
|
2
3
|
|
|
3
4
|
import { fastHash, stringify, takeUntilTokens } from '../utils'
|
|
@@ -7,18 +8,27 @@ import { PROMPT_INPUT_BUFFER } from './constants'
|
|
|
7
8
|
const Example = z.object({
|
|
8
9
|
input: z.any(),
|
|
9
10
|
check: z.boolean(),
|
|
10
|
-
reason: z.string().optional()
|
|
11
|
+
reason: z.string().optional(),
|
|
11
12
|
})
|
|
12
13
|
|
|
13
14
|
export type Options = z.input<typeof Options>
|
|
14
15
|
const Options = z.object({
|
|
15
|
-
examples: z.array(Example).describe('Examples to check the condition against').default([])
|
|
16
|
+
examples: z.array(Example).describe('Examples to check the condition against').default([]),
|
|
16
17
|
})
|
|
17
18
|
|
|
18
19
|
declare module '@botpress/zai' {
|
|
19
20
|
interface Zai {
|
|
20
21
|
/** Checks wether a condition is true or not */
|
|
21
|
-
check(
|
|
22
|
+
check(
|
|
23
|
+
input: unknown,
|
|
24
|
+
condition: string,
|
|
25
|
+
options?: Options
|
|
26
|
+
): Promise<{
|
|
27
|
+
/** Whether the condition is true or not */
|
|
28
|
+
value: boolean
|
|
29
|
+
/** The explanation of the decision */
|
|
30
|
+
explanation: string
|
|
31
|
+
}>
|
|
22
32
|
}
|
|
23
33
|
}
|
|
24
34
|
|
|
@@ -29,14 +39,15 @@ const END = '■END■'
|
|
|
29
39
|
Zai.prototype.check = async function (this: Zai, input, condition, _options) {
|
|
30
40
|
const options = Options.parse(_options ?? {})
|
|
31
41
|
const tokenizer = await this.getTokenizer()
|
|
32
|
-
|
|
42
|
+
await this.fetchModelDetails()
|
|
43
|
+
const PROMPT_COMPONENT = Math.max(this.ModelDetails.input.maxTokens - PROMPT_INPUT_BUFFER, 100)
|
|
33
44
|
|
|
34
45
|
const taskId = this.taskId
|
|
35
46
|
const taskType = 'zai.check'
|
|
36
47
|
|
|
37
48
|
const PROMPT_TOKENS = {
|
|
38
49
|
INPUT: Math.floor(0.5 * PROMPT_COMPONENT),
|
|
39
|
-
CONDITION: Math.floor(0.2 * PROMPT_COMPONENT)
|
|
50
|
+
CONDITION: Math.floor(0.2 * PROMPT_COMPONENT),
|
|
40
51
|
}
|
|
41
52
|
|
|
42
53
|
// Truncate the input to fit the model's input size
|
|
@@ -51,7 +62,7 @@ Zai.prototype.check = async function (this: Zai, input, condition, _options) {
|
|
|
51
62
|
taskType,
|
|
52
63
|
taskId,
|
|
53
64
|
input: inputAsString,
|
|
54
|
-
condition
|
|
65
|
+
condition,
|
|
55
66
|
})
|
|
56
67
|
)
|
|
57
68
|
|
|
@@ -59,13 +70,13 @@ Zai.prototype.check = async function (this: Zai, input, condition, _options) {
|
|
|
59
70
|
? await this.adapter.getExamples<string, boolean>({
|
|
60
71
|
input: inputAsString,
|
|
61
72
|
taskType,
|
|
62
|
-
taskId
|
|
73
|
+
taskId,
|
|
63
74
|
})
|
|
64
75
|
: []
|
|
65
76
|
|
|
66
77
|
const exactMatch = examples.find((x) => x.key === Key)
|
|
67
78
|
if (exactMatch) {
|
|
68
|
-
return exactMatch.output
|
|
79
|
+
return { explanation: exactMatch.explanation ?? '', value: exactMatch.output }
|
|
69
80
|
}
|
|
70
81
|
|
|
71
82
|
const defaultExamples = [
|
|
@@ -73,13 +84,14 @@ Zai.prototype.check = async function (this: Zai, input, condition, _options) {
|
|
|
73
84
|
{
|
|
74
85
|
input: ['apple', 'banana', 'carrot', 'house'],
|
|
75
86
|
check: false,
|
|
76
|
-
reason:
|
|
77
|
-
|
|
87
|
+
reason:
|
|
88
|
+
'The list contains a house, which is not a fruit. Also, the list contains a carrot, which is a vegetable.',
|
|
89
|
+
},
|
|
78
90
|
]
|
|
79
91
|
|
|
80
92
|
const userExamples = [
|
|
81
93
|
...examples.map((e) => ({ input: e.input, check: e.output, reason: e.explanation })),
|
|
82
|
-
...options.examples
|
|
94
|
+
...options.examples,
|
|
83
95
|
]
|
|
84
96
|
|
|
85
97
|
let exampleId = 1
|
|
@@ -108,8 +120,8 @@ ${END}
|
|
|
108
120
|
{
|
|
109
121
|
type: 'text' as const,
|
|
110
122
|
content: formatOutput(example.check, example.reason ?? ''),
|
|
111
|
-
role: 'assistant' as const
|
|
112
|
-
}
|
|
123
|
+
role: 'assistant' as const,
|
|
124
|
+
},
|
|
113
125
|
]
|
|
114
126
|
|
|
115
127
|
const allExamples = takeUntilTokens(
|
|
@@ -129,7 +141,7 @@ ${END}
|
|
|
129
141
|
`.trim()
|
|
130
142
|
: ''
|
|
131
143
|
|
|
132
|
-
const output = await this.callModel({
|
|
144
|
+
const { output, meta } = await this.callModel({
|
|
133
145
|
systemPrompt: `
|
|
134
146
|
Check if the following condition is true or false for the given input. Before answering, make sure to read the input and the condition carefully.
|
|
135
147
|
Justify your answer, then answer with either ${TRUE} or ${FALSE} at the very end, then add ${END} to finish the response.
|
|
@@ -147,9 +159,9 @@ ${specialInstructions}
|
|
|
147
159
|
Considering the below input and above examples, is the following condition true or false?
|
|
148
160
|
${formatInput(inputAsString, condition)}
|
|
149
161
|
In your "Analysis", please refer to the Expert Examples # to justify your decision.`.trim(),
|
|
150
|
-
role: 'user'
|
|
151
|
-
}
|
|
152
|
-
]
|
|
162
|
+
role: 'user',
|
|
163
|
+
},
|
|
164
|
+
],
|
|
153
165
|
})
|
|
154
166
|
|
|
155
167
|
const answer = output.choices[0]?.content as string
|
|
@@ -162,6 +174,13 @@ In your "Analysis", please refer to the Expert Examples # to justify your decisi
|
|
|
162
174
|
}
|
|
163
175
|
|
|
164
176
|
let finalAnswer: boolean
|
|
177
|
+
const explanation = answer
|
|
178
|
+
.replace(TRUE, '')
|
|
179
|
+
.replace(FALSE, '')
|
|
180
|
+
.replace(END, '')
|
|
181
|
+
.replace('Final Answer:', '')
|
|
182
|
+
.replace('Analysis:', '')
|
|
183
|
+
.trim()
|
|
165
184
|
|
|
166
185
|
if (hasTrue && hasFalse) {
|
|
167
186
|
// If both TRUE and FALSE are present, we need to check which one was answered last
|
|
@@ -177,11 +196,25 @@ In your "Analysis", please refer to the Expert Examples # to justify your decisi
|
|
|
177
196
|
taskId,
|
|
178
197
|
input: inputAsString,
|
|
179
198
|
instructions: condition,
|
|
180
|
-
metadata:
|
|
199
|
+
metadata: {
|
|
200
|
+
cost: {
|
|
201
|
+
input: meta.cost.input,
|
|
202
|
+
output: meta.cost.output,
|
|
203
|
+
},
|
|
204
|
+
latency: meta.latency,
|
|
205
|
+
model: this.Model,
|
|
206
|
+
tokens: {
|
|
207
|
+
input: meta.tokens.input,
|
|
208
|
+
output: meta.tokens.output,
|
|
209
|
+
},
|
|
210
|
+
},
|
|
181
211
|
output: finalAnswer,
|
|
182
|
-
explanation
|
|
212
|
+
explanation,
|
|
183
213
|
})
|
|
184
214
|
}
|
|
185
215
|
|
|
186
|
-
return
|
|
216
|
+
return {
|
|
217
|
+
value: finalAnswer,
|
|
218
|
+
explanation: explanation.trim(),
|
|
219
|
+
}
|
|
187
220
|
}
|
package/src/operations/errors.ts
CHANGED