ai-functions 0.2.19 → 0.4.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/.turbo/turbo-build.log +5 -0
- package/.turbo/turbo-test.log +105 -0
- package/README.md +232 -37
- package/TODO.md +138 -0
- package/dist/ai-promise.d.ts +219 -0
- package/dist/ai-promise.d.ts.map +1 -0
- package/dist/ai-promise.js +610 -0
- package/dist/ai-promise.js.map +1 -0
- package/dist/ai.d.ts +285 -0
- package/dist/ai.d.ts.map +1 -0
- package/dist/ai.js +842 -0
- package/dist/ai.js.map +1 -0
- package/dist/batch/anthropic.d.ts +23 -0
- package/dist/batch/anthropic.d.ts.map +1 -0
- package/dist/batch/anthropic.js +257 -0
- package/dist/batch/anthropic.js.map +1 -0
- package/dist/batch/bedrock.d.ts +64 -0
- package/dist/batch/bedrock.d.ts.map +1 -0
- package/dist/batch/bedrock.js +586 -0
- package/dist/batch/bedrock.js.map +1 -0
- package/dist/batch/cloudflare.d.ts +37 -0
- package/dist/batch/cloudflare.d.ts.map +1 -0
- package/dist/batch/cloudflare.js +289 -0
- package/dist/batch/cloudflare.js.map +1 -0
- package/dist/batch/google.d.ts +41 -0
- package/dist/batch/google.d.ts.map +1 -0
- package/dist/batch/google.js +360 -0
- package/dist/batch/google.js.map +1 -0
- package/dist/batch/index.d.ts +31 -0
- package/dist/batch/index.d.ts.map +1 -0
- package/dist/batch/index.js +31 -0
- package/dist/batch/index.js.map +1 -0
- package/dist/batch/memory.d.ts +44 -0
- package/dist/batch/memory.d.ts.map +1 -0
- package/dist/batch/memory.js +188 -0
- package/dist/batch/memory.js.map +1 -0
- package/dist/batch/openai.d.ts +37 -0
- package/dist/batch/openai.d.ts.map +1 -0
- package/dist/batch/openai.js +403 -0
- package/dist/batch/openai.js.map +1 -0
- package/dist/batch-map.d.ts +125 -0
- package/dist/batch-map.d.ts.map +1 -0
- package/dist/batch-map.js +406 -0
- package/dist/batch-map.js.map +1 -0
- package/dist/batch-queue.d.ts +273 -0
- package/dist/batch-queue.d.ts.map +1 -0
- package/dist/batch-queue.js +271 -0
- package/dist/batch-queue.js.map +1 -0
- package/dist/context.d.ts +133 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +267 -0
- package/dist/context.js.map +1 -0
- package/dist/embeddings.d.ts +123 -0
- package/dist/embeddings.d.ts.map +1 -0
- package/dist/embeddings.js +170 -0
- package/dist/embeddings.js.map +1 -0
- package/dist/eval/index.d.ts +8 -0
- package/dist/eval/index.d.ts.map +1 -0
- package/dist/eval/index.js +8 -0
- package/dist/eval/index.js.map +1 -0
- package/dist/eval/models.d.ts +66 -0
- package/dist/eval/models.d.ts.map +1 -0
- package/dist/eval/models.js +120 -0
- package/dist/eval/models.js.map +1 -0
- package/dist/eval/runner.d.ts +64 -0
- package/dist/eval/runner.d.ts.map +1 -0
- package/dist/eval/runner.js +148 -0
- package/dist/eval/runner.js.map +1 -0
- package/dist/generate.d.ts +168 -0
- package/dist/generate.d.ts.map +1 -0
- package/dist/generate.js +174 -0
- package/dist/generate.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/primitives.d.ts +292 -0
- package/dist/primitives.d.ts.map +1 -0
- package/dist/primitives.js +471 -0
- package/dist/primitives.js.map +1 -0
- package/dist/providers/cloudflare.d.ts +9 -0
- package/dist/providers/cloudflare.d.ts.map +1 -0
- package/dist/providers/cloudflare.js +9 -0
- package/dist/providers/cloudflare.js.map +1 -0
- package/dist/providers/index.d.ts +9 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +9 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/schema.d.ts +54 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +109 -0
- package/dist/schema.js.map +1 -0
- package/dist/template.d.ts +73 -0
- package/dist/template.d.ts.map +1 -0
- package/dist/template.js +129 -0
- package/dist/template.js.map +1 -0
- package/dist/types.d.ts +481 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/evalite.config.ts +19 -0
- package/evals/README.md +212 -0
- package/evals/classification.eval.ts +108 -0
- package/evals/marketing.eval.ts +370 -0
- package/evals/math.eval.ts +94 -0
- package/evals/run-evals.ts +166 -0
- package/evals/structured-output.eval.ts +143 -0
- package/evals/writing.eval.ts +117 -0
- package/examples/batch-blog-posts.ts +160 -0
- package/package.json +59 -43
- package/src/ai-promise.ts +784 -0
- package/src/ai.ts +1183 -0
- package/src/batch/anthropic.ts +375 -0
- package/src/batch/bedrock.ts +801 -0
- package/src/batch/cloudflare.ts +421 -0
- package/src/batch/google.ts +491 -0
- package/src/batch/index.ts +31 -0
- package/src/batch/memory.ts +253 -0
- package/src/batch/openai.ts +557 -0
- package/src/batch-map.ts +534 -0
- package/src/batch-queue.ts +493 -0
- package/src/context.ts +332 -0
- package/src/embeddings.ts +244 -0
- package/src/eval/index.ts +8 -0
- package/src/eval/models.ts +158 -0
- package/src/eval/runner.ts +217 -0
- package/src/generate.ts +245 -0
- package/src/index.ts +154 -0
- package/src/primitives.ts +612 -0
- package/src/providers/cloudflare.ts +15 -0
- package/src/providers/index.ts +14 -0
- package/src/schema.ts +147 -0
- package/src/template.ts +209 -0
- package/src/types.ts +540 -0
- package/test/README.md +105 -0
- package/test/ai-proxy.test.ts +192 -0
- package/test/async-iterators.test.ts +327 -0
- package/test/batch-background.test.ts +482 -0
- package/test/batch-blog-posts.test.ts +387 -0
- package/test/blog-generation.test.ts +510 -0
- package/test/browse-read.test.ts +611 -0
- package/test/core-functions.test.ts +694 -0
- package/test/decide.test.ts +393 -0
- package/test/define.test.ts +274 -0
- package/test/e2e-bedrock-manual.ts +163 -0
- package/test/e2e-bedrock.test.ts +191 -0
- package/test/e2e-flex-gateway.ts +157 -0
- package/test/e2e-flex-manual.ts +183 -0
- package/test/e2e-flex.test.ts +209 -0
- package/test/e2e-google-manual.ts +178 -0
- package/test/e2e-google.test.ts +216 -0
- package/test/embeddings.test.ts +284 -0
- package/test/evals/define-function.eval.test.ts +379 -0
- package/test/evals/primitives.eval.test.ts +384 -0
- package/test/function-types.test.ts +492 -0
- package/test/generate-core.test.ts +319 -0
- package/test/generate.test.ts +163 -0
- package/test/implicit-batch.test.ts +422 -0
- package/test/schema.test.ts +109 -0
- package/test/tagged-templates.test.ts +302 -0
- package/tsconfig.json +8 -6
- package/vitest.config.ts +42 -0
- package/LICENSE +0 -21
- package/db/cache.ts +0 -6
- package/db/mongo.ts +0 -75
- package/dist/mjs/db/cache.d.ts +0 -1
- package/dist/mjs/db/cache.js +0 -5
- package/dist/mjs/db/mongo.d.ts +0 -31
- package/dist/mjs/db/mongo.js +0 -48
- package/dist/mjs/examples/data.d.ts +0 -1105
- package/dist/mjs/examples/data.js +0 -1105
- package/dist/mjs/functions/ai.d.ts +0 -20
- package/dist/mjs/functions/ai.js +0 -83
- package/dist/mjs/functions/ai.test.d.ts +0 -1
- package/dist/mjs/functions/ai.test.js +0 -29
- package/dist/mjs/functions/gpt.d.ts +0 -4
- package/dist/mjs/functions/gpt.js +0 -10
- package/dist/mjs/functions/list.d.ts +0 -7
- package/dist/mjs/functions/list.js +0 -72
- package/dist/mjs/index.d.ts +0 -3
- package/dist/mjs/index.js +0 -3
- package/dist/mjs/queue/kafka.d.ts +0 -0
- package/dist/mjs/queue/kafka.js +0 -1
- package/dist/mjs/queue/memory.d.ts +0 -0
- package/dist/mjs/queue/memory.js +0 -1
- package/dist/mjs/queue/mongo.d.ts +0 -30
- package/dist/mjs/queue/mongo.js +0 -42
- package/dist/mjs/streams/kafka.d.ts +0 -0
- package/dist/mjs/streams/kafka.js +0 -1
- package/dist/mjs/streams/memory.d.ts +0 -0
- package/dist/mjs/streams/memory.js +0 -1
- package/dist/mjs/streams/mongo.d.ts +0 -0
- package/dist/mjs/streams/mongo.js +0 -1
- package/dist/mjs/streams/types.d.ts +0 -0
- package/dist/mjs/streams/types.js +0 -1
- package/dist/mjs/types.d.ts +0 -11
- package/dist/mjs/types.js +0 -1
- package/dist/mjs/utils/completion.d.ts +0 -9
- package/dist/mjs/utils/completion.js +0 -20
- package/dist/mjs/utils/schema.d.ts +0 -10
- package/dist/mjs/utils/schema.js +0 -72
- package/dist/mjs/utils/schema.test.d.ts +0 -1
- package/dist/mjs/utils/schema.test.js +0 -60
- package/dist/mjs/utils/state.d.ts +0 -1
- package/dist/mjs/utils/state.js +0 -19
- package/examples/data.ts +0 -1105
- package/fixup +0 -11
- package/functions/ai.test.ts +0 -41
- package/functions/ai.ts +0 -115
- package/functions/gpt.ts +0 -12
- package/functions/list.ts +0 -84
- package/index.ts +0 -3
- package/queue/kafka.ts +0 -0
- package/queue/memory.ts +0 -0
- package/queue/mongo.ts +0 -88
- package/streams/kafka.ts +0 -0
- package/streams/memory.ts +0 -0
- package/streams/mongo.ts +0 -0
- package/streams/types.ts +0 -0
- package/tsconfig-backup.json +0 -105
- package/tsconfig-base.json +0 -26
- package/tsconfig-cjs.json +0 -8
- package/types.ts +0 -12
- package/utils/completion.ts +0 -28
- package/utils/schema.test.ts +0 -69
- package/utils/schema.ts +0 -74
- package/utils/state.ts +0 -23
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
|
|
2
|
+
> ai-functions@0.0.1 test /Users/nathanclevenger/projects/mdx.org.ai/primitives/packages/ai-functions
|
|
3
|
+
> vitest
|
|
4
|
+
|
|
5
|
+
[dotenv@17.2.3] injecting env (2) from ../../../.env -- tip: 📡 add observability to secrets: https://dotenvx.com/ops
|
|
6
|
+
|
|
7
|
+
DEV v2.1.9 /Users/nathanclevenger/projects/mdx.org.ai/primitives/packages/ai-functions
|
|
8
|
+
|
|
9
|
+
✓ test/core-functions.test.ts (38 tests) 11ms
|
|
10
|
+
✓ test/function-types.test.ts (35 tests) 4ms
|
|
11
|
+
✓ test/browse-read.test.ts (31 tests) 5ms
|
|
12
|
+
✓ test/batch-background.test.ts (20 tests) 2ms
|
|
13
|
+
✓ test/decide.test.ts (15 tests) 2ms
|
|
14
|
+
✓ test/async-iterators.test.ts (13 tests) 336ms
|
|
15
|
+
✓ test/generate-core.test.ts (18 tests) 2ms
|
|
16
|
+
✓ test/tagged-templates.test.ts (19 tests) 3ms
|
|
17
|
+
✓ test/define.test.ts (18 tests) 955ms
|
|
18
|
+
✓ generative function execution > executes a generative string function 456ms
|
|
19
|
+
✓ test/embeddings.test.ts (24 tests | 2 skipped) 36ms
|
|
20
|
+
✓ test/ai-proxy.test.ts (14 tests) 1585ms
|
|
21
|
+
✓ ai proxy auto-define > uses cached definition on second call 524ms
|
|
22
|
+
✓ AI() schema functions > generates nested objects 339ms
|
|
23
|
+
✓ test/generate.test.ts (9 tests) 1702ms
|
|
24
|
+
✓ generateText > generates simple text response 323ms
|
|
25
|
+
✓ test/schema.test.ts (12 tests) 2ms
|
|
26
|
+
|
|
27
|
+
Test Files 13 passed (13)
|
|
28
|
+
Tests 264 passed | 2 skipped (266)
|
|
29
|
+
Start at 14:14:37
|
|
30
|
+
Duration 5.46s (transform 171ms, setup 0ms, collect 351ms, tests 4.65s, environment 0ms, prepare 84ms)
|
|
31
|
+
|
|
32
|
+
PASS Waiting for file changes...
|
|
33
|
+
press h to show help, press q to quit
|
|
34
|
+
c[3J RERUN ../language-models/dist/aliases.js
|
|
35
|
+
|
|
36
|
+
✓ test/generate.test.ts (9 tests) 1916ms
|
|
37
|
+
✓ generateObject > generates a simple object with string fields 622ms
|
|
38
|
+
✓ test/ai-proxy.test.ts (14 tests) 1361ms
|
|
39
|
+
✓ ai proxy auto-define > uses cached definition on second call 540ms
|
|
40
|
+
✓ test/define.test.ts (18 tests) 349ms
|
|
41
|
+
✓ test/embeddings.test.ts (24 tests | 2 skipped) 32ms
|
|
42
|
+
✓ test/schema.test.ts (12 tests) 1ms
|
|
43
|
+
|
|
44
|
+
Test Files 5 passed (5)
|
|
45
|
+
Tests 75 passed | 2 skipped (77)
|
|
46
|
+
Start at 14:22:55
|
|
47
|
+
Duration 3.99s
|
|
48
|
+
|
|
49
|
+
PASS Waiting for file changes...
|
|
50
|
+
press h to show help, press q to quit
|
|
51
|
+
c[3J RERUN ../language-models/dist/aliases.js
|
|
52
|
+
|
|
53
|
+
✓ test/generate.test.ts (9 tests) 948ms
|
|
54
|
+
✓ test/ai-proxy.test.ts (14 tests) 610ms
|
|
55
|
+
✓ test/define.test.ts (18 tests) 289ms
|
|
56
|
+
✓ test/embeddings.test.ts (24 tests | 2 skipped) 30ms
|
|
57
|
+
✓ test/schema.test.ts (12 tests) 1ms
|
|
58
|
+
|
|
59
|
+
Test Files 5 passed (5)
|
|
60
|
+
Tests 75 passed | 2 skipped (77)
|
|
61
|
+
Start at 14:31:30
|
|
62
|
+
Duration 2.00s
|
|
63
|
+
|
|
64
|
+
PASS Waiting for file changes...
|
|
65
|
+
press h to show help, press q to quit
|
|
66
|
+
c[3J RERUN src/index.ts
|
|
67
|
+
|
|
68
|
+
✓ test/generate.test.ts (9 tests) 2001ms
|
|
69
|
+
✓ generateObject > generates a simple object with string fields 481ms
|
|
70
|
+
✓ test/ai-proxy.test.ts (14 tests) 1395ms
|
|
71
|
+
✓ ai proxy auto-define > auto-defines a function on first call 320ms
|
|
72
|
+
✓ ai proxy auto-define > uses cached definition on second call 541ms
|
|
73
|
+
✓ test/define.test.ts (18 tests) 844ms
|
|
74
|
+
✓ test/embeddings.test.ts (24 tests | 2 skipped) 47ms
|
|
75
|
+
✓ test/schema.test.ts (12 tests) 1ms
|
|
76
|
+
|
|
77
|
+
Test Files 5 passed (5)
|
|
78
|
+
Tests 75 passed | 2 skipped (77)
|
|
79
|
+
Start at 01:20:37
|
|
80
|
+
Duration 4.50s
|
|
81
|
+
|
|
82
|
+
PASS Waiting for file changes...
|
|
83
|
+
press h to show help, press q to quit
|
|
84
|
+
c[3J RERUN test/implicit-batch.test.ts
|
|
85
|
+
|
|
86
|
+
✓ test/batch-blog-posts.test.ts (15 tests) 411ms
|
|
87
|
+
✓ test/implicit-batch.test.ts (26 tests) 4ms
|
|
88
|
+
✓ test/generate.test.ts (9 tests) 1676ms
|
|
89
|
+
✓ generateObject > generates a simple object with string fields 498ms
|
|
90
|
+
✓ test/ai-proxy.test.ts (14 tests) 1328ms
|
|
91
|
+
✓ ai proxy auto-define > auto-defines a function on first call 380ms
|
|
92
|
+
✓ ai proxy auto-define > uses cached definition on second call 525ms
|
|
93
|
+
✓ test/define.test.ts (18 tests) 869ms
|
|
94
|
+
✓ generative function execution > executes a generative string function 315ms
|
|
95
|
+
✓ test/embeddings.test.ts (24 tests | 2 skipped) 36ms
|
|
96
|
+
✓ test/schema.test.ts (12 tests) 1ms
|
|
97
|
+
|
|
98
|
+
Test Files 7 passed (7)
|
|
99
|
+
Tests 116 passed | 2 skipped (118)
|
|
100
|
+
Start at 03:35:28
|
|
101
|
+
Duration 4.48s
|
|
102
|
+
|
|
103
|
+
PASS Waiting for file changes...
|
|
104
|
+
press h to show help, press q to quit
|
|
105
|
+
ELIFECYCLE Test failed. See above for more details.
|
package/README.md
CHANGED
|
@@ -1,59 +1,254 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ai-functions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Call AI like you'd talk to a colleague. No prompts. No configuration. Just say what you need.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
```typescript
|
|
6
|
+
import { ai, list, is } from 'ai-functions'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
// Ask for anything - it reads like English
|
|
9
|
+
const qualified = is`${lead} a good fit for our enterprise plan?`
|
|
10
|
+
const ideas = list`blog posts that would resonate with ${persona}`
|
|
11
|
+
const { summary, nextSteps } = ai`analyze this sales call: ${transcript}`
|
|
12
|
+
```
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
import { AI } from 'ai-functions'
|
|
14
|
+
## Installation
|
|
11
15
|
|
|
12
|
-
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add ai-functions
|
|
13
18
|
```
|
|
14
19
|
|
|
15
|
-
|
|
20
|
+
## The Magic: Promise Pipelining
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
const categorizeProduct = ai.categorizeProduct({
|
|
19
|
-
productType: 'App | API | Marketplace | Platform | Packaged Service | Professional Service | Website',
|
|
20
|
-
customer: 'ideal customer profile in 3-5 words',
|
|
21
|
-
solution: 'describe the offer in 4-10 words',
|
|
22
|
-
description: 'website meta description',
|
|
23
|
-
})
|
|
22
|
+
Chain operations naturally—no `await` needed until you actually need the result:
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
```typescript
|
|
25
|
+
// Destructure to get exactly what you need
|
|
26
|
+
const { qualified, score, reason } = ai`qualify this lead: ${lead}`
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
// Chain functions together—dependencies resolve automatically
|
|
29
|
+
const followUp = ai`write follow-up email based on: ${reason}`
|
|
30
|
+
const subject = ai`subject line for: ${followUp}`
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
// Only await when you need the actual value
|
|
33
|
+
if (await qualified) {
|
|
34
|
+
await sendEmail({ to: lead.email, subject: await subject, body: await followUp })
|
|
35
|
+
}
|
|
33
36
|
```
|
|
34
37
|
|
|
35
|
-
|
|
38
|
+
## Real-World Examples
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
+
### Lead Qualification
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
const { score, qualified, reasoning } = ai`
|
|
44
|
+
qualify ${lead} for our product
|
|
45
|
+
considering: ${idealCustomerProfile}
|
|
46
|
+
`
|
|
47
|
+
|
|
48
|
+
if (await qualified) {
|
|
49
|
+
await assignToSales(lead)
|
|
40
50
|
}
|
|
41
51
|
```
|
|
42
52
|
|
|
43
|
-
|
|
53
|
+
### Content Marketing
|
|
44
54
|
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
const
|
|
55
|
+
```typescript
|
|
56
|
+
// Generate topic ideas for your audience
|
|
57
|
+
const topics = list`content ideas for ${persona} in ${industry}`
|
|
48
58
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
}
|
|
59
|
+
// Evaluate each in parallel—single LLM call!
|
|
60
|
+
const evaluated = await topics.map(topic => ({
|
|
61
|
+
topic,
|
|
62
|
+
potential: is`${topic} would drive signups?`,
|
|
63
|
+
difficulty: ai`content difficulty for: ${topic}`,
|
|
64
|
+
}))
|
|
65
|
+
|
|
66
|
+
// Pick the best
|
|
67
|
+
const winner = evaluated.find(t => t.potential && t.difficulty === 'easy')
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Sales Intelligence
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
const { pros, cons, objections } = lists`
|
|
74
|
+
competitive analysis: ${ourProduct} vs ${competitor}
|
|
75
|
+
`
|
|
76
|
+
|
|
77
|
+
const battleCard = ai`
|
|
78
|
+
sales battlecard addressing: ${objections}
|
|
79
|
+
highlighting: ${pros}
|
|
80
|
+
`
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Customer Success
|
|
55
84
|
|
|
56
|
-
|
|
57
|
-
|
|
85
|
+
```typescript
|
|
86
|
+
// Analyze customer health
|
|
87
|
+
const { healthy, churnRisk, opportunities } = ai`
|
|
88
|
+
analyze customer health for ${customer}
|
|
89
|
+
based on: ${usageData}
|
|
90
|
+
`
|
|
91
|
+
|
|
92
|
+
if (await churnRisk) {
|
|
93
|
+
const outreach = ai`retention outreach for ${customer} addressing ${churnRisk}`
|
|
94
|
+
await scheduleCall(customer, await outreach)
|
|
58
95
|
}
|
|
59
96
|
```
|
|
97
|
+
|
|
98
|
+
### Recruiting
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const candidates = list`source ${role} candidates from ${jobBoards}`
|
|
102
|
+
|
|
103
|
+
const evaluated = await candidates.map(candidate => ({
|
|
104
|
+
candidate,
|
|
105
|
+
fit: is`${candidate} matches ${requirements}?`,
|
|
106
|
+
summary: ai`one-line summary of ${candidate}`,
|
|
107
|
+
}))
|
|
108
|
+
|
|
109
|
+
const shortlist = evaluated.filter(c => c.fit)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## API Reference
|
|
113
|
+
|
|
114
|
+
### Generation
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
ai`anything you need` // flexible object/text
|
|
118
|
+
write`blog post about ${topic}` // long-form content
|
|
119
|
+
summarize`${document}` // condense to key points
|
|
120
|
+
list`ideas for ${topic}` // array of items
|
|
121
|
+
lists`pros and cons of ${topic}` // named lists
|
|
122
|
+
extract`emails from ${text}` // structured extraction
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Classification
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
is`${email} spam?` // boolean
|
|
129
|
+
decide`which converts better?`(optionA, optionB) // pick best
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Code & Visuals
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
code`email validation function` // generate code
|
|
136
|
+
diagram`user flow for ${feature}` // mermaid diagrams
|
|
137
|
+
slides`pitch deck for ${startup}` // presentations
|
|
138
|
+
image`hero image for ${brand}` // image generation
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Research & Web
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
research`${competitor} market position` // web research
|
|
145
|
+
read`${url}` // url to markdown
|
|
146
|
+
browse`${url}` // browser automation
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Human-in-the-Loop
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
ask`what's the priority for ${feature}?` // free-form input
|
|
153
|
+
approve`deploy ${version} to production?` // yes/no approval
|
|
154
|
+
review`${document}` // detailed feedback
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## The `lists` Function
|
|
158
|
+
|
|
159
|
+
Get exactly what you ask for through destructuring:
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
// Just name what you want—the schema is inferred!
|
|
163
|
+
const { pros, cons } = lists`pros and cons of ${decision}`
|
|
164
|
+
const { strengths, weaknesses, opportunities, threats } = lists`SWOT for ${company}`
|
|
165
|
+
const { mustHave, niceToHave, outOfScope } = lists`requirements for ${feature}`
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Batch Processing with `.map()`
|
|
169
|
+
|
|
170
|
+
Process arrays in a single LLM call:
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
const leads = await list`leads from ${campaign}`
|
|
174
|
+
|
|
175
|
+
// Each field evaluated for each lead—all in ONE call
|
|
176
|
+
const qualified = await leads.map(lead => ({
|
|
177
|
+
lead,
|
|
178
|
+
score: ai`score 1-100: ${lead}`,
|
|
179
|
+
qualified: is`${lead} matches ${icp}?`,
|
|
180
|
+
nextStep: ai`recommended action for ${lead}`,
|
|
181
|
+
}))
|
|
182
|
+
|
|
183
|
+
// Filter and act
|
|
184
|
+
qualified
|
|
185
|
+
.filter(l => l.qualified)
|
|
186
|
+
.forEach(l => createTask(l.nextStep))
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Typed Schemas with `AI()`
|
|
190
|
+
|
|
191
|
+
For reusable, typed functions:
|
|
192
|
+
|
|
193
|
+
```typescript
|
|
194
|
+
const ai = AI({
|
|
195
|
+
qualifyLead: {
|
|
196
|
+
score: 'Lead score 1-100 (number)',
|
|
197
|
+
qualified: 'Whether to pursue (boolean)',
|
|
198
|
+
reasoning: 'Explanation of score',
|
|
199
|
+
nextSteps: ['Recommended actions'],
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
analyzeCompetitor: {
|
|
203
|
+
positioning: 'How they position themselves',
|
|
204
|
+
strengths: ['Their advantages'],
|
|
205
|
+
weaknesses: ['Their disadvantages'],
|
|
206
|
+
battleCard: 'Key talking points for sales',
|
|
207
|
+
},
|
|
208
|
+
})
|
|
209
|
+
|
|
210
|
+
// Fully typed!
|
|
211
|
+
const result = await ai.qualifyLead('Enterprise CTO interested in AI automation')
|
|
212
|
+
result.score // number
|
|
213
|
+
result.qualified // boolean
|
|
214
|
+
result.nextSteps // string[]
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## Schema Syntax
|
|
218
|
+
|
|
219
|
+
| Syntax | Type | Example |
|
|
220
|
+
|--------|------|---------|
|
|
221
|
+
| `'description'` | string | `name: 'Company name'` |
|
|
222
|
+
| `'desc (number)'` | number | `score: 'Score 1-100 (number)'` |
|
|
223
|
+
| `'desc (boolean)'` | boolean | `qualified: 'Pursue? (boolean)'` |
|
|
224
|
+
| `'opt1 \| opt2'` | enum | `priority: 'high \| medium \| low'` |
|
|
225
|
+
| `['description']` | array | `steps: ['Action items']` |
|
|
226
|
+
| `{ nested }` | object | `contact: { name, email }` |
|
|
227
|
+
|
|
228
|
+
## Philosophy
|
|
229
|
+
|
|
230
|
+
**Code should read like conversation.**
|
|
231
|
+
|
|
232
|
+
Compare:
|
|
233
|
+
```typescript
|
|
234
|
+
// Traditional AI code
|
|
235
|
+
const response = await openai.chat.completions.create({
|
|
236
|
+
model: "gpt-4",
|
|
237
|
+
messages: [{ role: "user", content: `Analyze this lead: ${JSON.stringify(lead)}` }],
|
|
238
|
+
response_format: { type: "json_object" },
|
|
239
|
+
})
|
|
240
|
+
const result = JSON.parse(response.choices[0].message.content)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
// ai-functions
|
|
245
|
+
const { qualified, score, nextStep } = ai`analyze lead: ${lead}`
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
The second version is what you'd say to a colleague. That's the goal.
|
|
249
|
+
|
|
250
|
+
## Related Packages
|
|
251
|
+
|
|
252
|
+
- [`ai-database`](../ai-database) — AI-powered database operations
|
|
253
|
+
- [`ai-providers`](../ai-providers) — Model provider abstraction
|
|
254
|
+
- [`language-models`](../language-models) — Model definitions
|
package/TODO.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# ai-functions TODO
|
|
2
|
+
|
|
3
|
+
Changes from README that need implementation in tests/code.
|
|
4
|
+
|
|
5
|
+
## Function Types System
|
|
6
|
+
|
|
7
|
+
- [ ] Implement 4 function types: `Generative`, `Code`, `Agentic`, `Human`
|
|
8
|
+
- [ ] Type inference from function name + argument names + argument values
|
|
9
|
+
- [ ] Subjective judgment (e.g., `processRefund({ amount: 12.99 })` vs `amount: 50000`)
|
|
10
|
+
|
|
11
|
+
## Core Architecture
|
|
12
|
+
|
|
13
|
+
- [ ] `generate(type, prompt, opts?)` as the core primitive
|
|
14
|
+
- [ ] Types: `json`, `text`, `code`, `list`, `extract`, `summary`, `diagram`, `slides`, `markdown`, `yaml`, `xml`
|
|
15
|
+
- [ ] Schema support for `json` type
|
|
16
|
+
- [ ] All other functions call `generate` under the hood
|
|
17
|
+
- [ ] `define(name, schema)` - foundation function
|
|
18
|
+
- [ ] Infers function type from name + args
|
|
19
|
+
- [ ] Creates appropriate function (Generative, Code, Agentic, Human)
|
|
20
|
+
- [ ] Caches definition for subsequent calls
|
|
21
|
+
- [ ] `AI({ schemas })` factory for typed instances
|
|
22
|
+
|
|
23
|
+
## Tagged Template Support
|
|
24
|
+
|
|
25
|
+
- [ ] Every function supports tagged template syntax
|
|
26
|
+
- [ ] Objects/arrays in templates auto-stringify to YAML
|
|
27
|
+
- [ ] Template + options chaining: ``fn`prompt`({ model: '...' })``
|
|
28
|
+
|
|
29
|
+
## Standalone Exports
|
|
30
|
+
|
|
31
|
+
All functions exported directly (not just on `ai` object):
|
|
32
|
+
|
|
33
|
+
- [ ] `ai` - text generation
|
|
34
|
+
- [ ] `summarize` - condense text
|
|
35
|
+
- [ ] `do` - single-pass task executor with tools (not agentic loop)
|
|
36
|
+
- [ ] `is` - boolean classification
|
|
37
|
+
- [ ] `list` - generate list
|
|
38
|
+
- [ ] `lists` - multiple named lists
|
|
39
|
+
- [ ] `extract` - extract from text
|
|
40
|
+
- [ ] `write` - generate content
|
|
41
|
+
- [ ] `generate` - core primitive
|
|
42
|
+
- [ ] `decide` - LLM as judge, picks from options
|
|
43
|
+
- [ ] `code` - generate code
|
|
44
|
+
- [ ] `diagram` - generate diagrams (mermaid, etc.)
|
|
45
|
+
- [ ] `slides` - generate presentations (slidev, marp, reveal.js)
|
|
46
|
+
- [ ] `image` - generate images
|
|
47
|
+
- [ ] `video` - generate videos
|
|
48
|
+
- [ ] `research` - agentic research
|
|
49
|
+
- [ ] `read` - URL to markdown (Firecrawl)
|
|
50
|
+
- [ ] `browse` - browser automation (Stagehand/Browserbase)
|
|
51
|
+
- [ ] `page.extract` - extract data from page
|
|
52
|
+
- [ ] `page.do` - perform action on page
|
|
53
|
+
|
|
54
|
+
## Magic Proxy (`ai.*`)
|
|
55
|
+
|
|
56
|
+
- [ ] `ai.anyFunctionName(args)` auto-defines on first call
|
|
57
|
+
- [ ] Infers function type from name + args
|
|
58
|
+
- [ ] Examples:
|
|
59
|
+
- [ ] `ai.fizzBuzz()` → CodeFunction
|
|
60
|
+
- [ ] `ai.storyBrand()` → GenerativeFunction with schema
|
|
61
|
+
- [ ] `ai.launchProductHunt()` → AgenticFunction
|
|
62
|
+
- [ ] `ai.approveExpense()` → HumanFunction
|
|
63
|
+
|
|
64
|
+
## Human Functions
|
|
65
|
+
|
|
66
|
+
- [ ] `ask` - ask human a question
|
|
67
|
+
- [ ] `approve` - request human approval
|
|
68
|
+
- [ ] `review` - request human review
|
|
69
|
+
- [ ] Integration with `human-in-the-loop`, `digital-workers`, `autonomous-agents` packages
|
|
70
|
+
|
|
71
|
+
## Async Iterators
|
|
72
|
+
|
|
73
|
+
- [ ] `list` returns `AsyncIterable` for streaming
|
|
74
|
+
- [ ] `extract` returns `AsyncIterable` for streaming
|
|
75
|
+
- [ ] `for await (const item of list`...`)` pattern
|
|
76
|
+
- [ ] Early termination with `break`
|
|
77
|
+
|
|
78
|
+
## `decide` - LLM as Judge
|
|
79
|
+
|
|
80
|
+
- [ ] Syntax: ``decide`criteria`(optionA, optionB, ...)``
|
|
81
|
+
- [ ] Returns the winning option (same type as inputs)
|
|
82
|
+
- [ ] Type-safe: passing `Product` objects returns `Product`
|
|
83
|
+
|
|
84
|
+
## Options Parameter
|
|
85
|
+
|
|
86
|
+
Every function accepts options as last parameter:
|
|
87
|
+
|
|
88
|
+
- [ ] `model` - model selection
|
|
89
|
+
- [ ] `thinking` - `'low' | 'medium' | 'high' | number` (token budget)
|
|
90
|
+
- [ ] `temperature`
|
|
91
|
+
- [ ] `maxTokens`
|
|
92
|
+
|
|
93
|
+
## Batch & Background Processing
|
|
94
|
+
|
|
95
|
+
- [ ] Background mode: `{ mode: 'background' }` returns job immediately
|
|
96
|
+
- [ ] `job.result()` to get result later
|
|
97
|
+
- [ ] `job.status` for status
|
|
98
|
+
- [ ] Batch mode: `fn.batch([contexts])`
|
|
99
|
+
- [ ] Better pricing (50% off on OpenAI)
|
|
100
|
+
- [ ] Processes all at once
|
|
101
|
+
- [ ] Batch streaming: `fn.batch.stream([contexts])`
|
|
102
|
+
- [ ] `for await` as results complete
|
|
103
|
+
|
|
104
|
+
## Integration with Other Packages
|
|
105
|
+
|
|
106
|
+
- [ ] `ai-sandbox` - `evaluate({ code, tests, module, script })` for CodeFunctions
|
|
107
|
+
- [ ] `ai-database` - `embed` moved there, used by `db.search()`
|
|
108
|
+
- [ ] `ai-providers` / `language-models` - model resolution
|
|
109
|
+
- [ ] `human-in-the-loop` - Human function implementation
|
|
110
|
+
- [ ] `autonomous-agents` - Agent loop (vs single-pass `do`)
|
|
111
|
+
|
|
112
|
+
## Type System
|
|
113
|
+
|
|
114
|
+
- [ ] `AIFunction<TArgs, TReturn>` - callable + tagged template
|
|
115
|
+
- [ ] Schema syntax parsing:
|
|
116
|
+
- [ ] `'description'` → string
|
|
117
|
+
- [ ] `'desc (number)'` → number
|
|
118
|
+
- [ ] `'desc (boolean)'` → boolean
|
|
119
|
+
- [ ] `'opt1 | opt2'` → enum
|
|
120
|
+
- [ ] `['description']` → array
|
|
121
|
+
- [ ] `{ nested }` → object
|
|
122
|
+
- [ ] Type inference for `AI()` factory schemas
|
|
123
|
+
|
|
124
|
+
## Tests to Write
|
|
125
|
+
|
|
126
|
+
- [ ] Tagged template parsing and YAML conversion
|
|
127
|
+
- [ ] Each function type (Generative, Code, Agentic, Human)
|
|
128
|
+
- [ ] Function type inference from name + args
|
|
129
|
+
- [ ] `generate` with all type options
|
|
130
|
+
- [ ] `define` creating correct function types
|
|
131
|
+
- [ ] Magic proxy auto-definition
|
|
132
|
+
- [ ] Async iterators on `list` and `extract`
|
|
133
|
+
- [ ] `decide` returning correct option
|
|
134
|
+
- [ ] Batch and background modes
|
|
135
|
+
- [ ] Options parameter (model, thinking, etc.)
|
|
136
|
+
- [ ] `browse` with `page.extract` and `page.do`
|
|
137
|
+
- [ ] `read` URL fetching
|
|
138
|
+
- [ ] `research` agentic flow
|