ai-experiments 0.1.0 → 2.0.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.
- package/.turbo/turbo-build.log +5 -0
- package/CHANGELOG.md +8 -0
- package/README.md +306 -91
- package/dist/cartesian.d.ts +140 -0
- package/dist/cartesian.d.ts.map +1 -0
- package/dist/cartesian.js +216 -0
- package/dist/cartesian.js.map +1 -0
- package/dist/decide.d.ts +152 -0
- package/dist/decide.d.ts.map +1 -0
- package/dist/decide.js +329 -0
- package/dist/decide.js.map +1 -0
- package/dist/experiment.d.ts +53 -0
- package/dist/experiment.d.ts.map +1 -0
- package/dist/experiment.js +292 -0
- package/dist/experiment.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/tracking.d.ts +159 -0
- package/dist/tracking.d.ts.map +1 -0
- package/dist/tracking.js +310 -0
- package/dist/tracking.js.map +1 -0
- package/dist/types.d.ts +198 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/examples.ts +261 -0
- package/package.json +21 -39
- package/src/cartesian.ts +259 -0
- package/src/decide.ts +398 -0
- package/src/experiment.ts +358 -0
- package/src/index.ts +44 -0
- package/src/tracking.ts +339 -0
- package/src/types.ts +215 -0
- package/tsconfig.json +9 -0
package/CHANGELOG.md
ADDED
package/README.md
CHANGED
|
@@ -1,146 +1,361 @@
|
|
|
1
1
|
# ai-experiments
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
AI-powered experimentation primitives for testing and evaluating models.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`ai-experiments` provides a comprehensive toolkit for A/B testing, parameter exploration, decision making, and tracking in AI applications. It follows the same patterns and conventions as `ai-functions` from the primitives monorepo.
|
|
4
8
|
|
|
5
9
|
## Installation
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
|
-
npm install ai-experiments
|
|
9
|
-
# or
|
|
10
|
-
yarn add ai-experiments
|
|
11
|
-
# or
|
|
12
12
|
pnpm add ai-experiments
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Core APIs
|
|
16
16
|
|
|
17
|
-
###
|
|
17
|
+
### `Experiment()` - A/B Testing and Variant Evaluation
|
|
18
|
+
|
|
19
|
+
Run experiments with multiple variants to find the best configuration.
|
|
18
20
|
|
|
19
21
|
```typescript
|
|
20
|
-
import { Experiment } from 'ai-experiments'
|
|
22
|
+
import { Experiment } from 'ai-experiments'
|
|
23
|
+
|
|
24
|
+
const results = await Experiment({
|
|
25
|
+
id: 'prompt-comparison',
|
|
26
|
+
name: 'Prompt Engineering Test',
|
|
27
|
+
variants: [
|
|
28
|
+
{
|
|
29
|
+
id: 'baseline',
|
|
30
|
+
name: 'Baseline Prompt',
|
|
31
|
+
config: { prompt: 'Summarize this text.' },
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
id: 'detailed',
|
|
35
|
+
name: 'Detailed Prompt',
|
|
36
|
+
config: { prompt: 'Provide a comprehensive summary...' },
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
execute: async (config) => {
|
|
40
|
+
return await ai.generate({ prompt: config.prompt })
|
|
41
|
+
},
|
|
42
|
+
metric: (result) => result.quality_score,
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
console.log('Best variant:', results.bestVariant)
|
|
46
|
+
```
|
|
21
47
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
48
|
+
**Options:**
|
|
49
|
+
- `parallel: true` - Run variants in parallel (default)
|
|
50
|
+
- `maxConcurrency: 5` - Limit concurrent executions
|
|
51
|
+
- `stopOnError: false` - Stop on first error
|
|
52
|
+
- Event callbacks: `onVariantStart`, `onVariantComplete`, `onVariantError`
|
|
27
53
|
|
|
28
|
-
|
|
29
|
-
```
|
|
54
|
+
### `cartesian()` - Parameter Grid Exploration
|
|
30
55
|
|
|
31
|
-
|
|
56
|
+
Generate all combinations of parameters for exhaustive testing.
|
|
32
57
|
|
|
33
58
|
```typescript
|
|
34
|
-
import {
|
|
35
|
-
|
|
36
|
-
const result = await Experiment('temperature-comparison', {
|
|
37
|
-
models: ['gpt-4o', 'gpt-4o-mini'],
|
|
38
|
-
temperature: [0, 0.3, 0.7, 1.0],
|
|
39
|
-
prompt: 'Generate a creative story about a robot.',
|
|
40
|
-
});
|
|
59
|
+
import { cartesian } from 'ai-experiments'
|
|
41
60
|
|
|
42
|
-
|
|
43
|
-
|
|
61
|
+
const combinations = cartesian({
|
|
62
|
+
model: ['sonnet', 'opus', 'gpt-4o'],
|
|
63
|
+
temperature: [0.3, 0.7, 1.0],
|
|
64
|
+
maxTokens: [100, 500, 1000],
|
|
65
|
+
})
|
|
66
|
+
// Returns 27 combinations (3 × 3 × 3)
|
|
67
|
+
|
|
68
|
+
// Use with experiments:
|
|
69
|
+
const variants = combinations.map((config, i) => ({
|
|
70
|
+
id: `variant-${i}`,
|
|
71
|
+
name: `${config.model} T=${config.temperature}`,
|
|
72
|
+
config,
|
|
73
|
+
}))
|
|
44
74
|
```
|
|
45
75
|
|
|
46
|
-
|
|
76
|
+
**Related functions:**
|
|
77
|
+
- `cartesianFilter()` - Filter invalid combinations
|
|
78
|
+
- `cartesianSample()` - Random sample when full product is too large
|
|
79
|
+
- `cartesianCount()` - Count combinations without generating them
|
|
80
|
+
- `cartesianWithLabels()` - Include dimension indices
|
|
47
81
|
|
|
48
|
-
|
|
49
|
-
import { cartesian } from 'ai-experiments';
|
|
82
|
+
### `decide()` - Intelligent Decision Making
|
|
50
83
|
|
|
51
|
-
|
|
52
|
-
model: ['gpt-4o', 'gpt-4o-mini'],
|
|
53
|
-
temperature: [0, 0.7],
|
|
54
|
-
maxTokens: [100, 500]
|
|
55
|
-
});
|
|
84
|
+
Make decisions by scoring and comparing options.
|
|
56
85
|
|
|
57
|
-
|
|
86
|
+
```typescript
|
|
87
|
+
import { decide } from 'ai-experiments'
|
|
88
|
+
|
|
89
|
+
// Simple decision
|
|
90
|
+
const result = await decide({
|
|
91
|
+
options: ['fast', 'accurate', 'balanced'],
|
|
92
|
+
score: (approach) => evaluateApproach(approach),
|
|
93
|
+
context: 'Choosing summarization approach',
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
console.log(result.selected) // 'balanced'
|
|
97
|
+
console.log(result.score) // 0.9
|
|
98
|
+
|
|
99
|
+
// Return all options sorted by score
|
|
100
|
+
const result = await decide({
|
|
101
|
+
options: ['option-a', 'option-b', 'option-c'],
|
|
102
|
+
score: async (opt) => await scoreOption(opt),
|
|
103
|
+
returnAll: true,
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
console.log(result.allOptions)
|
|
58
107
|
// [
|
|
59
|
-
// {
|
|
60
|
-
// {
|
|
61
|
-
// {
|
|
62
|
-
// { model: 'gpt-4o', temperature: 0.7, maxTokens: 500 },
|
|
63
|
-
// { model: 'gpt-4o-mini', temperature: 0, maxTokens: 100 },
|
|
64
|
-
// { model: 'gpt-4o-mini', temperature: 0, maxTokens: 500 },
|
|
65
|
-
// { model: 'gpt-4o-mini', temperature: 0.7, maxTokens: 100 },
|
|
66
|
-
// { model: 'gpt-4o-mini', temperature: 0.7, maxTokens: 500 }
|
|
108
|
+
// { option: 'option-b', score: 0.95 },
|
|
109
|
+
// { option: 'option-a', score: 0.82 },
|
|
110
|
+
// { option: 'option-c', score: 0.71 },
|
|
67
111
|
// ]
|
|
68
112
|
```
|
|
69
113
|
|
|
70
|
-
|
|
114
|
+
**Advanced decision strategies:**
|
|
115
|
+
- `decideWeighted()` - Weighted random selection
|
|
116
|
+
- `decideEpsilonGreedy()` - Exploration vs exploitation
|
|
117
|
+
- `decideThompsonSampling()` - Bayesian bandit algorithm
|
|
118
|
+
- `decideUCB()` - Upper Confidence Bound
|
|
119
|
+
|
|
120
|
+
### `track()` - Event Tracking
|
|
121
|
+
|
|
122
|
+
Track experiment events and metrics.
|
|
71
123
|
|
|
72
124
|
```typescript
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
125
|
+
import { track, configureTracking, createFileBackend } from 'ai-experiments'
|
|
126
|
+
|
|
127
|
+
// Configure tracking backend
|
|
128
|
+
configureTracking({
|
|
129
|
+
backend: createFileBackend({ path: './experiments.jsonl' }),
|
|
130
|
+
metadata: { projectId: 'my-project' },
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
// Events are automatically tracked by Experiment()
|
|
134
|
+
// You can also track custom events:
|
|
135
|
+
track({
|
|
136
|
+
type: 'experiment.start',
|
|
137
|
+
timestamp: new Date(),
|
|
138
|
+
data: {
|
|
139
|
+
experimentId: 'my-experiment',
|
|
140
|
+
variantCount: 3,
|
|
141
|
+
},
|
|
142
|
+
})
|
|
82
143
|
```
|
|
83
144
|
|
|
84
|
-
|
|
145
|
+
**Built-in backends:**
|
|
146
|
+
- `createConsoleBackend()` - Log to console (default)
|
|
147
|
+
- `createMemoryBackend()` - Store events in memory
|
|
148
|
+
- `createBatchBackend()` - Batch events before sending
|
|
149
|
+
- `createFileBackend()` - Write to JSONL file
|
|
150
|
+
|
|
151
|
+
## Usage Patterns
|
|
152
|
+
|
|
153
|
+
### Pattern 1: Parameter Sweep
|
|
85
154
|
|
|
86
|
-
|
|
155
|
+
Test all combinations of hyperparameters:
|
|
87
156
|
|
|
88
157
|
```typescript
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
158
|
+
import { cartesian, Experiment } from 'ai-experiments'
|
|
159
|
+
|
|
160
|
+
const paramGrid = cartesian({
|
|
161
|
+
temperature: [0.3, 0.5, 0.7, 0.9],
|
|
162
|
+
topP: [0.9, 0.95, 1.0],
|
|
163
|
+
maxTokens: [100, 500, 1000],
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
const variants = paramGrid.map((params, i) => ({
|
|
167
|
+
id: `config-${i}`,
|
|
168
|
+
name: `T=${params.temperature} P=${params.topP} max=${params.maxTokens}`,
|
|
169
|
+
config: params,
|
|
170
|
+
}))
|
|
171
|
+
|
|
172
|
+
const results = await Experiment({
|
|
173
|
+
id: 'param-sweep',
|
|
174
|
+
name: 'Hyperparameter Optimization',
|
|
175
|
+
variants,
|
|
176
|
+
execute: async (config) => {
|
|
177
|
+
return await ai.generate({ ...config, prompt: 'Test prompt' })
|
|
178
|
+
},
|
|
179
|
+
metric: (result) => evaluateQuality(result),
|
|
180
|
+
})
|
|
181
|
+
|
|
182
|
+
console.log('Best config:', results.bestVariant)
|
|
93
183
|
```
|
|
94
184
|
|
|
95
|
-
|
|
185
|
+
### Pattern 2: Progressive Testing
|
|
96
186
|
|
|
97
|
-
|
|
98
|
-
- `config`: Configuration object with the following properties:
|
|
99
|
-
- `models`: Array of model names to use
|
|
100
|
-
- `temperature`: Number or array of temperature values
|
|
101
|
-
- `seed` (optional): Number or array of seed values
|
|
102
|
-
- `prompt` (optional): String or function that generates prompts
|
|
103
|
-
- `inputs` (optional): Array or function that returns input values
|
|
104
|
-
- `expected` (optional): Expected output for validation
|
|
105
|
-
- `schema` (optional): Schema for structured output
|
|
187
|
+
Start with a sample, then test more if needed:
|
|
106
188
|
|
|
107
|
-
|
|
189
|
+
```typescript
|
|
190
|
+
import { cartesianSample, Experiment } from 'ai-experiments'
|
|
191
|
+
|
|
192
|
+
// Sample 20 random combinations from a large space
|
|
193
|
+
const sample = cartesianSample(
|
|
194
|
+
{
|
|
195
|
+
param1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
|
196
|
+
param2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
|
197
|
+
param3: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
|
198
|
+
},
|
|
199
|
+
20
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
const results = await Experiment({
|
|
203
|
+
id: 'initial-sample',
|
|
204
|
+
name: 'Initial Random Sample',
|
|
205
|
+
variants: sample.map((config, i) => ({
|
|
206
|
+
id: `sample-${i}`,
|
|
207
|
+
name: `Sample ${i}`,
|
|
208
|
+
config,
|
|
209
|
+
})),
|
|
210
|
+
execute: async (config) => runTest(config),
|
|
211
|
+
metric: (result) => result.score,
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
// If results are promising, expand the search
|
|
215
|
+
if (results.bestVariant && results.bestVariant.metricValue > 0.8) {
|
|
216
|
+
console.log('Found promising region, expanding search...')
|
|
217
|
+
// Test more combinations near the best one
|
|
218
|
+
}
|
|
219
|
+
```
|
|
108
220
|
|
|
109
|
-
|
|
110
|
-
- `name`: Name of the experiment
|
|
111
|
-
- `results`: Array of results for each parameter combination
|
|
112
|
-
- `totalTime`: Total time taken for the experiment
|
|
113
|
-
- `timestamp`: ISO string of when the experiment was run
|
|
221
|
+
### Pattern 3: Multi-Armed Bandit
|
|
114
222
|
|
|
115
|
-
|
|
223
|
+
Adaptively choose variants based on performance:
|
|
116
224
|
|
|
117
225
|
```typescript
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
226
|
+
import { decideThompsonSampling, track } from 'ai-experiments'
|
|
227
|
+
|
|
228
|
+
// Track success/failure for each variant
|
|
229
|
+
const stats = {
|
|
230
|
+
'variant-a': { alpha: 10, beta: 5 }, // 10 successes, 5 failures
|
|
231
|
+
'variant-b': { alpha: 8, beta: 3 }, // 8 successes, 3 failures
|
|
232
|
+
'variant-c': { alpha: 2, beta: 2 }, // 2 successes, 2 failures (uncertain)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Thompson sampling balances exploration and exploitation
|
|
236
|
+
const selected = decideThompsonSampling(
|
|
237
|
+
['variant-a', 'variant-b', 'variant-c'],
|
|
238
|
+
stats
|
|
239
|
+
)
|
|
240
|
+
|
|
241
|
+
// Update stats based on result
|
|
242
|
+
const result = await runVariant(selected)
|
|
243
|
+
if (result.success) {
|
|
244
|
+
stats[selected].alpha += 1
|
|
245
|
+
} else {
|
|
246
|
+
stats[selected].beta += 1
|
|
247
|
+
}
|
|
121
248
|
```
|
|
122
249
|
|
|
123
|
-
|
|
250
|
+
### Pattern 4: Sequential Testing with Early Stopping
|
|
124
251
|
|
|
125
|
-
|
|
252
|
+
Stop testing once a clear winner emerges:
|
|
126
253
|
|
|
127
|
-
|
|
254
|
+
```typescript
|
|
255
|
+
import { Experiment } from 'ai-experiments'
|
|
256
|
+
|
|
257
|
+
let bestScore = 0
|
|
258
|
+
let testCount = 0
|
|
259
|
+
const maxTests = 100
|
|
260
|
+
|
|
261
|
+
const results = await Experiment(
|
|
262
|
+
{
|
|
263
|
+
id: 'sequential-test',
|
|
264
|
+
name: 'Sequential Testing',
|
|
265
|
+
variants: [...],
|
|
266
|
+
execute: async (config) => runTest(config),
|
|
267
|
+
metric: (result) => result.score,
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
parallel: false, // Sequential execution
|
|
271
|
+
onVariantComplete: (result) => {
|
|
272
|
+
testCount++
|
|
273
|
+
if (result.metricValue && result.metricValue > bestScore) {
|
|
274
|
+
bestScore = result.metricValue
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Stop if we found a really good result
|
|
278
|
+
if (bestScore > 0.95) {
|
|
279
|
+
console.log('Found excellent result, stopping early')
|
|
280
|
+
// In a real implementation, you'd need to handle early stopping
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
```
|
|
128
286
|
|
|
129
|
-
|
|
287
|
+
## TypeScript Types
|
|
130
288
|
|
|
131
|
-
|
|
289
|
+
The package is fully typed with comprehensive TypeScript definitions:
|
|
132
290
|
|
|
133
291
|
```typescript
|
|
134
|
-
|
|
292
|
+
import type {
|
|
293
|
+
ExperimentConfig,
|
|
294
|
+
ExperimentResult,
|
|
295
|
+
ExperimentSummary,
|
|
296
|
+
ExperimentVariant,
|
|
297
|
+
DecisionResult,
|
|
298
|
+
TrackingEvent,
|
|
299
|
+
TrackingBackend,
|
|
300
|
+
} from 'ai-experiments'
|
|
135
301
|
```
|
|
136
302
|
|
|
137
|
-
|
|
303
|
+
## Integration with ai-functions
|
|
138
304
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
305
|
+
Works seamlessly with `ai-functions` for AI-powered experiments:
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import { generateObject } from 'ai-functions'
|
|
309
|
+
import { Experiment, cartesian } from 'ai-experiments'
|
|
310
|
+
|
|
311
|
+
const prompts = [
|
|
312
|
+
'Summarize briefly',
|
|
313
|
+
'Provide a detailed summary',
|
|
314
|
+
'Extract key points',
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
const models = ['sonnet', 'opus', 'gpt-4o']
|
|
318
|
+
|
|
319
|
+
// Test all combinations of prompts and models
|
|
320
|
+
const combinations = cartesian({ prompt: prompts, model: models })
|
|
321
|
+
|
|
322
|
+
const results = await Experiment({
|
|
323
|
+
id: 'prompt-model-test',
|
|
324
|
+
name: 'Prompt and Model Comparison',
|
|
325
|
+
variants: combinations.map((config, i) => ({
|
|
326
|
+
id: `combo-${i}`,
|
|
327
|
+
name: `${config.model}: "${config.prompt.slice(0, 20)}..."`,
|
|
328
|
+
config,
|
|
329
|
+
})),
|
|
330
|
+
execute: async (config) => {
|
|
331
|
+
return await generateObject({
|
|
332
|
+
model: config.model,
|
|
333
|
+
schema: { summary: 'The summary text' },
|
|
334
|
+
prompt: config.prompt,
|
|
335
|
+
})
|
|
336
|
+
},
|
|
337
|
+
metric: (result) => evaluateSummary(result.object.summary),
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
console.log('Best combination:', results.bestVariant)
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Examples
|
|
344
|
+
|
|
345
|
+
See [examples.ts](./examples.ts) for complete working examples demonstrating:
|
|
346
|
+
- Simple A/B experiments
|
|
347
|
+
- Parameter grid exploration
|
|
348
|
+
- Decision making strategies
|
|
349
|
+
- Event tracking
|
|
350
|
+
- Sequential vs parallel execution
|
|
351
|
+
|
|
352
|
+
Run the examples:
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
pnpm build
|
|
356
|
+
node --import tsx examples.ts
|
|
357
|
+
```
|
|
143
358
|
|
|
144
|
-
|
|
359
|
+
## License
|
|
145
360
|
|
|
146
|
-
|
|
361
|
+
MIT
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cartesian product utilities for parameter exploration
|
|
3
|
+
*/
|
|
4
|
+
import type { CartesianParams, CartesianResult } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Generate cartesian product of parameter sets
|
|
7
|
+
*
|
|
8
|
+
* Takes an object where each key maps to an array of possible values,
|
|
9
|
+
* and returns all possible combinations as an array of objects.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { cartesian } from 'ai-experiments'
|
|
14
|
+
*
|
|
15
|
+
* const combinations = cartesian({
|
|
16
|
+
* model: ['sonnet', 'opus', 'gpt-4o'],
|
|
17
|
+
* temperature: [0.3, 0.7, 1.0],
|
|
18
|
+
* maxTokens: [100, 500, 1000],
|
|
19
|
+
* })
|
|
20
|
+
*
|
|
21
|
+
* // Returns 27 combinations (3 * 3 * 3):
|
|
22
|
+
* // [
|
|
23
|
+
* // { model: 'sonnet', temperature: 0.3, maxTokens: 100 },
|
|
24
|
+
* // { model: 'sonnet', temperature: 0.3, maxTokens: 500 },
|
|
25
|
+
* // { model: 'sonnet', temperature: 0.3, maxTokens: 1000 },
|
|
26
|
+
* // { model: 'sonnet', temperature: 0.7, maxTokens: 100 },
|
|
27
|
+
* // ...
|
|
28
|
+
* // ]
|
|
29
|
+
*
|
|
30
|
+
* // Use with experiments:
|
|
31
|
+
* const variants = combinations.map((config, i) => ({
|
|
32
|
+
* id: `variant-${i}`,
|
|
33
|
+
* name: `${config.model} T=${config.temperature} max=${config.maxTokens}`,
|
|
34
|
+
* config,
|
|
35
|
+
* }))
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export declare function cartesian<T extends CartesianParams>(params: T): CartesianResult<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Generate a grid of parameter combinations with filtering
|
|
41
|
+
*
|
|
42
|
+
* Similar to cartesian(), but allows filtering out invalid combinations.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* ```ts
|
|
46
|
+
* import { cartesianFilter } from 'ai-experiments'
|
|
47
|
+
*
|
|
48
|
+
* const combinations = cartesianFilter(
|
|
49
|
+
* {
|
|
50
|
+
* model: ['sonnet', 'opus'],
|
|
51
|
+
* temperature: [0.3, 0.7, 1.0],
|
|
52
|
+
* maxTokens: [100, 500],
|
|
53
|
+
* },
|
|
54
|
+
* // Filter out combinations where opus uses high temperature
|
|
55
|
+
* (combo) => !(combo.model === 'opus' && combo.temperature > 0.7)
|
|
56
|
+
* )
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare function cartesianFilter<T extends CartesianParams>(params: T, filter: (combo: {
|
|
60
|
+
[K in keyof T]: T[K][number];
|
|
61
|
+
}) => boolean): CartesianResult<T>;
|
|
62
|
+
/**
|
|
63
|
+
* Generate a random sample from the cartesian product
|
|
64
|
+
*
|
|
65
|
+
* Useful when the full cartesian product is too large to test all combinations.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* import { cartesianSample } from 'ai-experiments'
|
|
70
|
+
*
|
|
71
|
+
* // Full product would be 1000 combinations (10 * 10 * 10)
|
|
72
|
+
* // Sample just 20 random combinations
|
|
73
|
+
* const sample = cartesianSample(
|
|
74
|
+
* {
|
|
75
|
+
* param1: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
|
76
|
+
* param2: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
|
77
|
+
* param3: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
|
|
78
|
+
* },
|
|
79
|
+
* 20
|
|
80
|
+
* )
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function cartesianSample<T extends CartesianParams>(params: T, sampleSize: number, options?: {
|
|
84
|
+
/** Random seed for reproducibility */
|
|
85
|
+
seed?: number;
|
|
86
|
+
/** Whether to sample without replacement (default: true) */
|
|
87
|
+
unique?: boolean;
|
|
88
|
+
}): CartesianResult<T>;
|
|
89
|
+
/**
|
|
90
|
+
* Count the total number of combinations without generating them
|
|
91
|
+
*
|
|
92
|
+
* Useful for checking if cartesian product is feasible before generating.
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* import { cartesianCount } from 'ai-experiments'
|
|
97
|
+
*
|
|
98
|
+
* const count = cartesianCount({
|
|
99
|
+
* model: ['sonnet', 'opus', 'gpt-4o'],
|
|
100
|
+
* temperature: [0.3, 0.5, 0.7, 0.9],
|
|
101
|
+
* maxTokens: [100, 500, 1000, 2000],
|
|
102
|
+
* })
|
|
103
|
+
* // Returns 48 (3 * 4 * 4)
|
|
104
|
+
*
|
|
105
|
+
* if (count > 100) {
|
|
106
|
+
* console.log('Too many combinations, use cartesianSample instead')
|
|
107
|
+
* }
|
|
108
|
+
* ```
|
|
109
|
+
*/
|
|
110
|
+
export declare function cartesianCount<T extends CartesianParams>(params: T): number;
|
|
111
|
+
/**
|
|
112
|
+
* Generate cartesian product with labels for each dimension
|
|
113
|
+
*
|
|
114
|
+
* Returns combinations with additional metadata about which dimension each value came from.
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```ts
|
|
118
|
+
* import { cartesianWithLabels } from 'ai-experiments'
|
|
119
|
+
*
|
|
120
|
+
* const labeled = cartesianWithLabels({
|
|
121
|
+
* model: ['sonnet', 'opus'],
|
|
122
|
+
* temperature: [0.3, 0.7],
|
|
123
|
+
* })
|
|
124
|
+
* // [
|
|
125
|
+
* // { values: { model: 'sonnet', temperature: 0.3 }, labels: { model: 0, temperature: 0 } },
|
|
126
|
+
* // { values: { model: 'sonnet', temperature: 0.7 }, labels: { model: 0, temperature: 1 } },
|
|
127
|
+
* // { values: { model: 'opus', temperature: 0.3 }, labels: { model: 1, temperature: 0 } },
|
|
128
|
+
* // { values: { model: 'opus', temperature: 0.7 }, labels: { model: 1, temperature: 1 } },
|
|
129
|
+
* // ]
|
|
130
|
+
* ```
|
|
131
|
+
*/
|
|
132
|
+
export declare function cartesianWithLabels<T extends CartesianParams>(params: T): Array<{
|
|
133
|
+
values: {
|
|
134
|
+
[K in keyof T]: T[K][number];
|
|
135
|
+
};
|
|
136
|
+
labels: {
|
|
137
|
+
[K in keyof T]: number;
|
|
138
|
+
};
|
|
139
|
+
}>;
|
|
140
|
+
//# sourceMappingURL=cartesian.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cartesian.d.ts","sourceRoot":"","sources":["../src/cartesian.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,SAAS,CAAC,CAAC,SAAS,eAAe,EAAE,MAAM,EAAE,CAAC,GAAG,eAAe,CAAC,CAAC,CAAC,CA0BlF;AA4BD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,eAAe,EACvD,MAAM,EAAE,CAAC,EACT,MAAM,EAAE,CAAC,KAAK,EAAE;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;CAAE,KAAK,OAAO,GAC3D,eAAe,CAAC,CAAC,CAAC,CAGpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,eAAe,EACvD,MAAM,EAAE,CAAC,EACT,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE;IACP,sCAAsC;IACtC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,MAAM,CAAC,EAAE,OAAO,CAAA;CACZ,GACL,eAAe,CAAC,CAAC,CAAC,CAqBpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,eAAe,EAAE,MAAM,EAAE,CAAC,GAAG,MAAM,CAS3E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,eAAe,EAC3D,MAAM,EAAE,CAAC,GACR,KAAK,CAAC;IACP,MAAM,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;KAAE,CAAA;IACxC,MAAM,EAAE;SAAG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM;KAAE,CAAA;CACnC,CAAC,CA0BD"}
|