ai-functions 2.1.1 → 2.3.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.
Files changed (286) hide show
  1. package/.turbo/turbo-build.log +1 -4
  2. package/CHANGELOG.md +68 -1
  3. package/README.md +397 -157
  4. package/dist/ai-promise.d.ts +50 -3
  5. package/dist/ai-promise.d.ts.map +1 -1
  6. package/dist/ai-promise.js +410 -51
  7. package/dist/ai-promise.js.map +1 -1
  8. package/dist/ai-schemas.d.ts +56 -0
  9. package/dist/ai-schemas.d.ts.map +1 -0
  10. package/dist/ai-schemas.js +53 -0
  11. package/dist/ai-schemas.js.map +1 -0
  12. package/dist/ai.d.ts +16 -242
  13. package/dist/ai.d.ts.map +1 -1
  14. package/dist/ai.js +54 -837
  15. package/dist/ai.js.map +1 -1
  16. package/dist/batch/anthropic.d.ts +6 -4
  17. package/dist/batch/anthropic.d.ts.map +1 -1
  18. package/dist/batch/anthropic.js +83 -145
  19. package/dist/batch/anthropic.js.map +1 -1
  20. package/dist/batch/bedrock.d.ts +8 -30
  21. package/dist/batch/bedrock.d.ts.map +1 -1
  22. package/dist/batch/bedrock.js +155 -338
  23. package/dist/batch/bedrock.js.map +1 -1
  24. package/dist/batch/cloudflare.d.ts +8 -20
  25. package/dist/batch/cloudflare.d.ts.map +1 -1
  26. package/dist/batch/cloudflare.js +68 -189
  27. package/dist/batch/cloudflare.js.map +1 -1
  28. package/dist/batch/google.d.ts +6 -20
  29. package/dist/batch/google.d.ts.map +1 -1
  30. package/dist/batch/google.js +70 -238
  31. package/dist/batch/google.js.map +1 -1
  32. package/dist/batch/index.d.ts +4 -1
  33. package/dist/batch/index.d.ts.map +1 -1
  34. package/dist/batch/index.js +4 -1
  35. package/dist/batch/index.js.map +1 -1
  36. package/dist/batch/memory.d.ts +1 -1
  37. package/dist/batch/memory.d.ts.map +1 -1
  38. package/dist/batch/memory.js +14 -10
  39. package/dist/batch/memory.js.map +1 -1
  40. package/dist/batch/openai.d.ts +11 -14
  41. package/dist/batch/openai.d.ts.map +1 -1
  42. package/dist/batch/openai.js +52 -156
  43. package/dist/batch/openai.js.map +1 -1
  44. package/dist/batch/provider.d.ts +111 -0
  45. package/dist/batch/provider.d.ts.map +1 -0
  46. package/dist/batch/provider.js +233 -0
  47. package/dist/batch/provider.js.map +1 -0
  48. package/dist/batch-map.d.ts.map +1 -1
  49. package/dist/batch-map.js +23 -17
  50. package/dist/batch-map.js.map +1 -1
  51. package/dist/batch-queue.d.ts +65 -0
  52. package/dist/batch-queue.d.ts.map +1 -1
  53. package/dist/batch-queue.js +169 -14
  54. package/dist/batch-queue.js.map +1 -1
  55. package/dist/budget.d.ts +272 -0
  56. package/dist/budget.d.ts.map +1 -0
  57. package/dist/budget.js +513 -0
  58. package/dist/budget.js.map +1 -0
  59. package/dist/cache.d.ts +295 -0
  60. package/dist/cache.d.ts.map +1 -0
  61. package/dist/cache.js +433 -0
  62. package/dist/cache.js.map +1 -0
  63. package/dist/context.d.ts +42 -8
  64. package/dist/context.d.ts.map +1 -1
  65. package/dist/context.js +64 -62
  66. package/dist/context.js.map +1 -1
  67. package/dist/digital-objects-registry.d.ts +229 -0
  68. package/dist/digital-objects-registry.d.ts.map +1 -0
  69. package/dist/digital-objects-registry.js +617 -0
  70. package/dist/digital-objects-registry.js.map +1 -0
  71. package/dist/embeddings.d.ts +2 -2
  72. package/dist/embeddings.d.ts.map +1 -1
  73. package/dist/errors.d.ts +22 -0
  74. package/dist/errors.d.ts.map +1 -0
  75. package/dist/errors.js +35 -0
  76. package/dist/errors.js.map +1 -0
  77. package/dist/eval/runner.d.ts +10 -1
  78. package/dist/eval/runner.d.ts.map +1 -1
  79. package/dist/eval/runner.js +41 -35
  80. package/dist/eval/runner.js.map +1 -1
  81. package/dist/eval-log/in-memory.d.ts +34 -0
  82. package/dist/eval-log/in-memory.d.ts.map +1 -0
  83. package/dist/eval-log/in-memory.js +84 -0
  84. package/dist/eval-log/in-memory.js.map +1 -0
  85. package/dist/eval-log/index.d.ts +29 -0
  86. package/dist/eval-log/index.d.ts.map +1 -0
  87. package/dist/eval-log/index.js +39 -0
  88. package/dist/eval-log/index.js.map +1 -0
  89. package/dist/eval-log/types.d.ts +101 -0
  90. package/dist/eval-log/types.d.ts.map +1 -0
  91. package/dist/eval-log/types.js +16 -0
  92. package/dist/eval-log/types.js.map +1 -0
  93. package/dist/function-registry.d.ts +116 -0
  94. package/dist/function-registry.d.ts.map +1 -0
  95. package/dist/function-registry.js +546 -0
  96. package/dist/function-registry.js.map +1 -0
  97. package/dist/generate.d.ts +9 -3
  98. package/dist/generate.d.ts.map +1 -1
  99. package/dist/generate.js +18 -22
  100. package/dist/generate.js.map +1 -1
  101. package/dist/index.d.ts +35 -20
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +89 -42
  104. package/dist/index.js.map +1 -1
  105. package/dist/logger.d.ts +118 -0
  106. package/dist/logger.d.ts.map +1 -0
  107. package/dist/logger.js +187 -0
  108. package/dist/logger.js.map +1 -0
  109. package/dist/middleware/budget.d.ts +84 -0
  110. package/dist/middleware/budget.d.ts.map +1 -0
  111. package/dist/middleware/budget.js +110 -0
  112. package/dist/middleware/budget.js.map +1 -0
  113. package/dist/middleware/cache.d.ts +103 -0
  114. package/dist/middleware/cache.d.ts.map +1 -0
  115. package/dist/middleware/cache.js +228 -0
  116. package/dist/middleware/cache.js.map +1 -0
  117. package/dist/middleware/embed-cache.d.ts +99 -0
  118. package/dist/middleware/embed-cache.d.ts.map +1 -0
  119. package/dist/middleware/embed-cache.js +128 -0
  120. package/dist/middleware/embed-cache.js.map +1 -0
  121. package/dist/middleware/index.d.ts +11 -0
  122. package/dist/middleware/index.d.ts.map +1 -0
  123. package/dist/middleware/index.js +11 -0
  124. package/dist/middleware/index.js.map +1 -0
  125. package/dist/middleware/trace.d.ts +103 -0
  126. package/dist/middleware/trace.d.ts.map +1 -0
  127. package/dist/middleware/trace.js +176 -0
  128. package/dist/middleware/trace.js.map +1 -0
  129. package/dist/primitives.d.ts +120 -1
  130. package/dist/primitives.d.ts.map +1 -1
  131. package/dist/primitives.js +398 -26
  132. package/dist/primitives.js.map +1 -1
  133. package/dist/retry.d.ts +368 -0
  134. package/dist/retry.d.ts.map +1 -0
  135. package/dist/retry.js +646 -0
  136. package/dist/retry.js.map +1 -0
  137. package/dist/schema.d.ts.map +1 -1
  138. package/dist/schema.js +2 -10
  139. package/dist/schema.js.map +1 -1
  140. package/dist/telemetry.d.ts +128 -0
  141. package/dist/telemetry.d.ts.map +1 -0
  142. package/dist/telemetry.js +285 -0
  143. package/dist/telemetry.js.map +1 -0
  144. package/dist/template.d.ts.map +1 -1
  145. package/dist/template.js +6 -1
  146. package/dist/template.js.map +1 -1
  147. package/dist/tool-orchestration.d.ts +453 -0
  148. package/dist/tool-orchestration.d.ts.map +1 -0
  149. package/dist/tool-orchestration.js +763 -0
  150. package/dist/tool-orchestration.js.map +1 -0
  151. package/dist/type-guards.d.ts +28 -0
  152. package/dist/type-guards.d.ts.map +1 -0
  153. package/dist/type-guards.js +29 -0
  154. package/dist/type-guards.js.map +1 -0
  155. package/dist/types.d.ts +135 -17
  156. package/dist/types.d.ts.map +1 -1
  157. package/dist/types.js +36 -1
  158. package/dist/types.js.map +1 -1
  159. package/dist/wrap-for-v3.d.ts +80 -0
  160. package/dist/wrap-for-v3.d.ts.map +1 -0
  161. package/dist/wrap-for-v3.js +89 -0
  162. package/dist/wrap-for-v3.js.map +1 -0
  163. package/examples/00-quickstart.ts +232 -0
  164. package/examples/01-rag-chatbot.ts +212 -0
  165. package/examples/02-multi-agent-research.ts +290 -0
  166. package/examples/03-email-classification.ts +379 -0
  167. package/examples/04-content-moderation.ts +400 -0
  168. package/examples/05-document-extraction.ts +455 -0
  169. package/examples/06-streaming-chat-nextjs.ts +437 -0
  170. package/examples/07-cloudflare-worker.ts +483 -0
  171. package/examples/08-batch-processing.ts +491 -0
  172. package/examples/09-budget-constrained.ts +527 -0
  173. package/examples/10-tool-orchestration.ts +565 -0
  174. package/examples/11-retry-resilience.ts +403 -0
  175. package/examples/12-caching-strategies.ts +422 -0
  176. package/examples/README.md +145 -0
  177. package/package.json +10 -6
  178. package/src/ai-promise.ts +528 -99
  179. package/src/ai-schemas.ts +122 -0
  180. package/src/ai.ts +69 -1153
  181. package/src/batch/anthropic.ts +96 -161
  182. package/src/batch/bedrock.ts +203 -454
  183. package/src/batch/cloudflare.ts +99 -282
  184. package/src/batch/google.ts +91 -297
  185. package/src/batch/index.ts +4 -1
  186. package/src/batch/memory.ts +15 -10
  187. package/src/batch/openai.ts +65 -193
  188. package/src/batch/provider.ts +336 -0
  189. package/src/batch-map.ts +29 -24
  190. package/src/batch-queue.ts +200 -11
  191. package/src/budget.ts +740 -0
  192. package/src/cache.ts +681 -0
  193. package/src/context.ts +122 -76
  194. package/src/digital-objects-registry.ts +750 -0
  195. package/src/errors.ts +37 -0
  196. package/src/eval/runner.ts +63 -38
  197. package/src/eval-log/in-memory.ts +90 -0
  198. package/src/eval-log/index.ts +46 -0
  199. package/src/eval-log/types.ts +110 -0
  200. package/src/function-registry.ts +671 -0
  201. package/src/generate.ts +33 -33
  202. package/src/index.ts +325 -49
  203. package/src/logger.ts +232 -0
  204. package/src/middleware/budget.ts +171 -0
  205. package/src/middleware/cache.ts +299 -0
  206. package/src/middleware/embed-cache.ts +195 -0
  207. package/src/middleware/index.ts +23 -0
  208. package/src/middleware/trace.ts +248 -0
  209. package/src/primitives.ts +589 -62
  210. package/src/retry.ts +902 -0
  211. package/src/schema.ts +8 -17
  212. package/src/telemetry.ts +403 -0
  213. package/src/template.ts +8 -4
  214. package/src/tool-orchestration.ts +1173 -0
  215. package/src/type-guards.ts +31 -0
  216. package/src/types.ts +164 -25
  217. package/src/wrap-for-v3.ts +105 -0
  218. package/test/ai-promise.test.ts +1080 -0
  219. package/test/ai-proxy.test.ts +1 -1
  220. package/test/backward-compat.test.ts +147 -0
  221. package/test/batch-autosubmit-errors.test.ts +610 -0
  222. package/test/batch-blog-posts.test.ts +87 -129
  223. package/test/budget-tracking.test.ts +800 -0
  224. package/test/cache.test.ts +712 -0
  225. package/test/context-isolation.test.ts +687 -0
  226. package/test/core-functions.test.ts +183 -579
  227. package/test/decide.test.ts +154 -322
  228. package/test/define.test.ts +211 -8
  229. package/test/digital-objects-registry.test.ts +760 -0
  230. package/test/embedding-cache-middleware.test.ts +140 -0
  231. package/test/evals/deterministic.eval.test.ts +376 -0
  232. package/test/generate-core.test.ts +140 -229
  233. package/test/implicit-batch.test.ts +22 -65
  234. package/test/json-parse-error-handling.test.ts +463 -0
  235. package/test/retry-policy-integration.test.ts +117 -0
  236. package/test/retry.test.ts +1016 -0
  237. package/test/schema.test.ts +55 -19
  238. package/test/streaming.test.ts +316 -0
  239. package/test/template.test.ts +1164 -0
  240. package/test/tool-orchestration.test.ts +1040 -0
  241. package/test/wrap-for-v3.test.ts +612 -0
  242. package/vitest.config.js +6 -0
  243. package/vitest.config.ts +20 -0
  244. package/dist/rpc/auth.d.ts +0 -69
  245. package/dist/rpc/auth.d.ts.map +0 -1
  246. package/dist/rpc/auth.js +0 -136
  247. package/dist/rpc/auth.js.map +0 -1
  248. package/dist/rpc/client.d.ts +0 -62
  249. package/dist/rpc/client.d.ts.map +0 -1
  250. package/dist/rpc/client.js +0 -103
  251. package/dist/rpc/client.js.map +0 -1
  252. package/dist/rpc/deferred.d.ts +0 -60
  253. package/dist/rpc/deferred.d.ts.map +0 -1
  254. package/dist/rpc/deferred.js +0 -96
  255. package/dist/rpc/deferred.js.map +0 -1
  256. package/dist/rpc/index.d.ts +0 -22
  257. package/dist/rpc/index.d.ts.map +0 -1
  258. package/dist/rpc/index.js +0 -38
  259. package/dist/rpc/index.js.map +0 -1
  260. package/dist/rpc/local.d.ts +0 -42
  261. package/dist/rpc/local.d.ts.map +0 -1
  262. package/dist/rpc/local.js +0 -50
  263. package/dist/rpc/local.js.map +0 -1
  264. package/dist/rpc/server.d.ts +0 -165
  265. package/dist/rpc/server.d.ts.map +0 -1
  266. package/dist/rpc/server.js +0 -405
  267. package/dist/rpc/server.js.map +0 -1
  268. package/dist/rpc/session.d.ts +0 -32
  269. package/dist/rpc/session.d.ts.map +0 -1
  270. package/dist/rpc/session.js +0 -43
  271. package/dist/rpc/session.js.map +0 -1
  272. package/dist/rpc/transport.d.ts +0 -306
  273. package/dist/rpc/transport.d.ts.map +0 -1
  274. package/dist/rpc/transport.js +0 -731
  275. package/dist/rpc/transport.js.map +0 -1
  276. package/src/batch/anthropic.js +0 -256
  277. package/src/batch/bedrock.js +0 -584
  278. package/src/batch/cloudflare.js +0 -287
  279. package/src/batch/google.js +0 -359
  280. package/src/batch/index.js +0 -30
  281. package/src/batch/memory.js +0 -187
  282. package/src/batch/openai.js +0 -402
  283. package/src/eval/index.js +0 -7
  284. package/src/eval/models.js +0 -119
  285. package/src/eval/runner.js +0 -147
  286. package/test/schema.test.js +0 -96
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Quickstart Example
3
+ *
4
+ * This example demonstrates the core primitives of ai-functions in a simple,
5
+ * easy-to-follow format. It covers:
6
+ * - Basic text generation with `write`
7
+ * - List generation with `list`
8
+ * - Boolean checks with `is`
9
+ * - Structured output with `ai`
10
+ * - Configuration options
11
+ *
12
+ * @example
13
+ * ```bash
14
+ * ANTHROPIC_API_KEY=sk-... npx tsx examples/00-quickstart.ts
15
+ * ```
16
+ */
17
+
18
+ import { ai, write, list, is, extract, configure, withContext } from '../src/index.js'
19
+
20
+ // ============================================================================
21
+ // Setup
22
+ // ============================================================================
23
+
24
+ // Configure the AI provider (optional - will use env vars by default)
25
+ configure({
26
+ model: 'sonnet', // or 'gpt-4o', 'claude-3-5-haiku-latest', etc.
27
+ provider: 'anthropic', // or 'openai'
28
+ })
29
+
30
+ // ============================================================================
31
+ // Text Generation
32
+ // ============================================================================
33
+
34
+ async function textGenerationExamples() {
35
+ console.log('\n=== Text Generation ===\n')
36
+
37
+ // Simple text generation
38
+ const haiku = await write`a haiku about TypeScript`
39
+ console.log('Haiku:', haiku)
40
+
41
+ // With more context
42
+ const email = await write`a professional email declining a meeting invitation.
43
+ Keep it brief and polite.`
44
+ console.log('\nEmail:', email)
45
+ }
46
+
47
+ // ============================================================================
48
+ // List Generation
49
+ // ============================================================================
50
+
51
+ async function listGenerationExamples() {
52
+ console.log('\n=== List Generation ===\n')
53
+
54
+ // Generate a simple list
55
+ const ideas = await list`5 startup ideas in the AI space`
56
+ console.log('Startup Ideas:')
57
+ ideas.forEach((idea, i) => console.log(` ${i + 1}. ${idea}`))
58
+
59
+ // Using map for processing (batched automatically)
60
+ console.log('\nProcessing ideas with map...')
61
+ const evaluated = await Promise.all(
62
+ ideas.slice(0, 3).map(async (idea) => ({
63
+ idea,
64
+ feasible: await is`"${idea}" is technically feasible with current technology`,
65
+ }))
66
+ )
67
+
68
+ console.log('\nFeasibility Check:')
69
+ evaluated.forEach((e) => {
70
+ console.log(` ${e.feasible ? '✓' : '✗'} ${e.idea}`)
71
+ })
72
+ }
73
+
74
+ // ============================================================================
75
+ // Boolean Checks
76
+ // ============================================================================
77
+
78
+ async function booleanCheckExamples() {
79
+ console.log('\n=== Boolean Checks ===\n')
80
+
81
+ // Simple true/false questions
82
+ const checks = [
83
+ await is`"TypeScript" is a programming language`,
84
+ await is`42 is a prime number`,
85
+ await is`Paris is the capital of France`,
86
+ await is`HTML is a programming language`,
87
+ ]
88
+
89
+ console.log('Boolean Checks:')
90
+ console.log(` TypeScript is a programming language: ${checks[0]}`)
91
+ console.log(` 42 is a prime number: ${checks[1]}`)
92
+ console.log(` Paris is capital of France: ${checks[2]}`)
93
+ console.log(` HTML is a programming language: ${checks[3]}`)
94
+
95
+ // Content validation example
96
+ const userInput = 'Buy our amazing product at discount.com!!!'
97
+ const isSpam = await is`This text is spam or promotional: "${userInput}"`
98
+ console.log(`\n "${userInput}" is spam: ${isSpam}`)
99
+ }
100
+
101
+ // ============================================================================
102
+ // Structured Output
103
+ // ============================================================================
104
+
105
+ async function structuredOutputExamples() {
106
+ console.log('\n=== Structured Output ===\n')
107
+
108
+ // Extract structured data from text
109
+ const article = `
110
+ Apple Inc. announced today that CEO Tim Cook will be presenting
111
+ the new iPhone 16 at the September 2024 event in Cupertino, California.
112
+ The device is expected to feature AI capabilities and cost around $999.
113
+ `
114
+
115
+ // Using destructuring to define the schema
116
+ const { company, product, person, location, price, date } = await ai`
117
+ Extract key information from this article:
118
+ ${article}
119
+
120
+ Provide:
121
+ - company: company name
122
+ - product: product mentioned
123
+ - person: person mentioned
124
+ - location: location mentioned
125
+ - price: price if mentioned
126
+ - date: date or time mentioned
127
+ `
128
+
129
+ console.log('Extracted Information:')
130
+ console.log(` Company: ${company}`)
131
+ console.log(` Product: ${product}`)
132
+ console.log(` Person: ${person}`)
133
+ console.log(` Location: ${location}`)
134
+ console.log(` Price: ${price}`)
135
+ console.log(` Date: ${date}`)
136
+
137
+ // Generate structured content
138
+ const { title, description, tags } = await ai`
139
+ Create a blog post metadata for a post about "Getting Started with AI Functions":
140
+ - title: engaging blog post title
141
+ - description: SEO description (under 160 chars)
142
+ - tags: array of 5 relevant tags
143
+ `
144
+
145
+ console.log('\nGenerated Blog Metadata:')
146
+ console.log(` Title: ${title}`)
147
+ console.log(` Description: ${description}`)
148
+ console.log(` Tags: ${(tags as string[]).join(', ')}`)
149
+ }
150
+
151
+ // ============================================================================
152
+ // Data Extraction
153
+ // ============================================================================
154
+
155
+ async function extractionExamples() {
156
+ console.log('\n=== Data Extraction ===\n')
157
+
158
+ const text = `
159
+ Contact us at support@example.com or sales@company.io.
160
+ Call John at 555-123-4567 or reach Sarah at 555-987-6543.
161
+ Meeting scheduled for March 15, 2024 and follow-up on April 1st.
162
+ `
163
+
164
+ const emails = await extract`all email addresses from: ${text}`
165
+ console.log('Emails:', emails)
166
+
167
+ const phones = await extract`all phone numbers from: ${text}`
168
+ console.log('Phone Numbers:', phones)
169
+
170
+ const dates = await extract`all dates from: ${text}`
171
+ console.log('Dates:', dates)
172
+ }
173
+
174
+ // ============================================================================
175
+ // Scoped Configuration
176
+ // ============================================================================
177
+
178
+ async function scopedConfigExamples() {
179
+ console.log('\n=== Scoped Configuration ===\n')
180
+
181
+ // Use different settings for specific operations
182
+ const result = await withContext(
183
+ {
184
+ model: 'claude-3-5-haiku-latest', // Use faster model
185
+ temperature: 0.1, // More deterministic
186
+ },
187
+ async () => {
188
+ console.log(' Using Haiku model with low temperature...')
189
+ return write`What is 2+2? Answer with just the number.`
190
+ }
191
+ )
192
+
193
+ console.log(` Result: ${result}`)
194
+
195
+ // Back to default configuration
196
+ const creative = await write`Give a creative name for a cat`
197
+ console.log(` Creative cat name: ${creative}`)
198
+ }
199
+
200
+ // ============================================================================
201
+ // Main
202
+ // ============================================================================
203
+
204
+ async function main() {
205
+ console.log('\n========================================')
206
+ console.log(' ai-functions Quickstart')
207
+ console.log('========================================')
208
+
209
+ await textGenerationExamples()
210
+ await listGenerationExamples()
211
+ await booleanCheckExamples()
212
+ await structuredOutputExamples()
213
+ await extractionExamples()
214
+ await scopedConfigExamples()
215
+
216
+ console.log('\n========================================')
217
+ console.log(' Quickstart Complete!')
218
+ console.log('========================================')
219
+ console.log(`
220
+ Next steps:
221
+ - Try the other examples in this directory
222
+ - Read the README.md for the full API reference
223
+ - Check out test/ for more usage patterns
224
+ `)
225
+ }
226
+
227
+ main()
228
+ .then(() => process.exit(0))
229
+ .catch((error) => {
230
+ console.error('\nError:', error.message)
231
+ process.exit(1)
232
+ })
@@ -0,0 +1,212 @@
1
+ /**
2
+ * RAG Chatbot Example
3
+ *
4
+ * This example demonstrates building a Retrieval-Augmented Generation (RAG) chatbot
5
+ * using ai-functions. It shows how to:
6
+ * - Generate embeddings for documents
7
+ * - Perform semantic search
8
+ * - Generate context-aware responses
9
+ *
10
+ * @example
11
+ * ```bash
12
+ * ANTHROPIC_API_KEY=sk-... npx tsx examples/01-rag-chatbot.ts
13
+ * ```
14
+ */
15
+
16
+ import {
17
+ write,
18
+ list,
19
+ configure,
20
+ EmbeddingCache,
21
+ MemoryCache,
22
+ GenerationCache,
23
+ withRetry,
24
+ } from '../src/index.js'
25
+
26
+ // ============================================================================
27
+ // Document Store (In-memory for this example)
28
+ // ============================================================================
29
+
30
+ interface Document {
31
+ id: string
32
+ content: string
33
+ embedding?: number[]
34
+ }
35
+
36
+ const documents: Document[] = [
37
+ {
38
+ id: 'doc-1',
39
+ content:
40
+ 'ai-functions is a TypeScript library that simplifies AI integration. It provides template literals for natural AI calls like `const poem = await write`a haiku about TypeScript``.',
41
+ },
42
+ {
43
+ id: 'doc-2',
44
+ content:
45
+ 'The library supports batch processing with 50% cost savings through provider batch APIs. Use createBatch() to process large workloads efficiently.',
46
+ },
47
+ {
48
+ id: 'doc-3',
49
+ content:
50
+ 'Built-in retry logic with exponential backoff handles rate limits automatically. Use withRetry() or RetryPolicy for custom retry behavior.',
51
+ },
52
+ {
53
+ id: 'doc-4',
54
+ content:
55
+ 'Budget tracking monitors token usage and costs. BudgetTracker supports alerts at configurable thresholds and enforces spending limits.',
56
+ },
57
+ {
58
+ id: 'doc-5',
59
+ content:
60
+ 'The list primitive generates arrays with automatic batching. Use list`5 ideas`.map() to process each item in parallel.',
61
+ },
62
+ ]
63
+
64
+ // ============================================================================
65
+ // Simple Embedding Simulation (replace with real embeddings in production)
66
+ // ============================================================================
67
+
68
+ function simulateEmbedding(text: string): number[] {
69
+ // Simple word-based embedding simulation
70
+ // In production, use a real embedding model
71
+ const words = text.toLowerCase().split(/\s+/)
72
+ const embedding = new Array(128).fill(0)
73
+
74
+ for (const word of words) {
75
+ const hash = word.split('').reduce((acc, char) => acc + char.charCodeAt(0), 0)
76
+ embedding[hash % 128] += 1
77
+ }
78
+
79
+ // Normalize
80
+ const magnitude = Math.sqrt(embedding.reduce((acc, val) => acc + val * val, 0))
81
+ return embedding.map((val) => (magnitude > 0 ? val / magnitude : 0))
82
+ }
83
+
84
+ function cosineSimilarity(a: number[], b: number[]): number {
85
+ let dotProduct = 0
86
+ for (let i = 0; i < a.length; i++) {
87
+ dotProduct += a[i] * b[i]
88
+ }
89
+ return dotProduct
90
+ }
91
+
92
+ // ============================================================================
93
+ // RAG Chatbot Implementation
94
+ // ============================================================================
95
+
96
+ class RAGChatbot {
97
+ private documents: Document[]
98
+ private responseCache: GenerationCache
99
+
100
+ constructor(documents: Document[]) {
101
+ this.documents = documents
102
+ this.responseCache = new GenerationCache({
103
+ defaultTTL: 3600000, // 1 hour cache
104
+ })
105
+
106
+ // Generate embeddings for all documents
107
+ for (const doc of this.documents) {
108
+ doc.embedding = simulateEmbedding(doc.content)
109
+ }
110
+ }
111
+
112
+ /**
113
+ * Find the most relevant documents for a query
114
+ */
115
+ private findRelevantDocs(query: string, topK: number = 3): Document[] {
116
+ const queryEmbedding = simulateEmbedding(query)
117
+
118
+ const scored = this.documents.map((doc) => ({
119
+ doc,
120
+ score: cosineSimilarity(queryEmbedding, doc.embedding!),
121
+ }))
122
+
123
+ return scored
124
+ .sort((a, b) => b.score - a.score)
125
+ .slice(0, topK)
126
+ .map(({ doc }) => doc)
127
+ }
128
+
129
+ /**
130
+ * Generate a response using RAG
131
+ */
132
+ async chat(userMessage: string): Promise<string> {
133
+ console.log(`\nUser: ${userMessage}`)
134
+ console.log('---')
135
+
136
+ // Step 1: Retrieve relevant documents
137
+ const relevantDocs = this.findRelevantDocs(userMessage)
138
+ console.log(`Found ${relevantDocs.length} relevant documents`)
139
+
140
+ // Step 2: Build context from retrieved documents
141
+ const context = relevantDocs.map((doc, i) => `[Source ${i + 1}]: ${doc.content}`).join('\n\n')
142
+
143
+ // Step 3: Generate response with context
144
+ const response =
145
+ await write`You are a helpful assistant that answers questions about ai-functions library.
146
+
147
+ Context from documentation:
148
+ ${context}
149
+
150
+ User Question: ${userMessage}
151
+
152
+ Please provide a helpful, accurate response based on the context above. If the context doesn't contain enough information, say so.`
153
+
154
+ console.log(`Assistant: ${response}`)
155
+ return response
156
+ }
157
+
158
+ /**
159
+ * Generate follow-up questions
160
+ */
161
+ async suggestFollowUps(topic: string): Promise<string[]> {
162
+ const suggestions =
163
+ await list`3 follow-up questions someone might ask about ${topic} related to ai-functions library`
164
+ return suggestions
165
+ }
166
+ }
167
+
168
+ // ============================================================================
169
+ // Main Example
170
+ // ============================================================================
171
+
172
+ async function main() {
173
+ console.log('\n=== RAG Chatbot Example ===\n')
174
+
175
+ // Configure the AI provider
176
+ configure({
177
+ model: 'sonnet',
178
+ provider: 'anthropic',
179
+ })
180
+
181
+ // Initialize the chatbot with our documents
182
+ const chatbot = new RAGChatbot(documents)
183
+
184
+ // Example conversation
185
+ const questions = [
186
+ 'How do I generate a list of items?',
187
+ 'What are the cost savings for batch processing?',
188
+ 'How does retry handling work?',
189
+ ]
190
+
191
+ for (const question of questions) {
192
+ await chatbot.chat(question)
193
+ console.log('')
194
+ }
195
+
196
+ // Generate follow-up suggestions
197
+ console.log('\n--- Suggested follow-up questions ---')
198
+ const followUps = await chatbot.suggestFollowUps('batch processing')
199
+ for (const suggestion of followUps) {
200
+ console.log(`- ${suggestion}`)
201
+ }
202
+ }
203
+
204
+ main()
205
+ .then(() => {
206
+ console.log('\n=== Example Complete ===\n')
207
+ process.exit(0)
208
+ })
209
+ .catch((error) => {
210
+ console.error('\nError:', error.message)
211
+ process.exit(1)
212
+ })