@effect/ai 0.14.1 → 0.16.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 (134) hide show
  1. package/AiEmbeddingModel/package.json +6 -0
  2. package/AiLanguageModel/package.json +6 -0
  3. package/AiTool/package.json +6 -0
  4. package/dist/cjs/AiChat.js +65 -86
  5. package/dist/cjs/AiChat.js.map +1 -1
  6. package/dist/cjs/{Embeddings.js → AiEmbeddingModel.js} +12 -12
  7. package/dist/cjs/AiEmbeddingModel.js.map +1 -0
  8. package/dist/cjs/AiError.js +8 -1
  9. package/dist/cjs/AiError.js.map +1 -1
  10. package/dist/cjs/AiInput.js +335 -248
  11. package/dist/cjs/AiInput.js.map +1 -1
  12. package/dist/cjs/AiLanguageModel.js +311 -0
  13. package/dist/cjs/AiLanguageModel.js.map +1 -0
  14. package/dist/cjs/AiModel.js +11 -5
  15. package/dist/cjs/AiModel.js.map +1 -1
  16. package/dist/cjs/AiPlan.js +10 -3
  17. package/dist/cjs/AiPlan.js.map +1 -1
  18. package/dist/cjs/AiResponse.js +481 -165
  19. package/dist/cjs/AiResponse.js.map +1 -1
  20. package/dist/cjs/AiTelemetry.js +10 -3
  21. package/dist/cjs/AiTelemetry.js.map +1 -1
  22. package/dist/cjs/AiTool.js +93 -0
  23. package/dist/cjs/AiTool.js.map +1 -0
  24. package/dist/cjs/AiToolkit.js +121 -98
  25. package/dist/cjs/AiToolkit.js.map +1 -1
  26. package/dist/cjs/Tokenizer.js +14 -16
  27. package/dist/cjs/Tokenizer.js.map +1 -1
  28. package/dist/cjs/index.js +7 -9
  29. package/dist/cjs/internal/aiPlan.js +6 -9
  30. package/dist/cjs/internal/aiPlan.js.map +1 -1
  31. package/dist/cjs/internal/common.js +22 -0
  32. package/dist/cjs/internal/common.js.map +1 -0
  33. package/dist/dts/AiChat.d.ts +58 -44
  34. package/dist/dts/AiChat.d.ts.map +1 -1
  35. package/dist/dts/{Embeddings.d.ts → AiEmbeddingModel.d.ts} +13 -14
  36. package/dist/dts/AiEmbeddingModel.d.ts.map +1 -0
  37. package/dist/dts/AiError.d.ts +4 -3
  38. package/dist/dts/AiError.d.ts.map +1 -1
  39. package/dist/dts/AiInput.d.ts +441 -146
  40. package/dist/dts/AiInput.d.ts.map +1 -1
  41. package/dist/dts/AiLanguageModel.d.ts +263 -0
  42. package/dist/dts/AiLanguageModel.d.ts.map +1 -0
  43. package/dist/dts/AiModel.d.ts +21 -20
  44. package/dist/dts/AiModel.d.ts.map +1 -1
  45. package/dist/dts/AiPlan.d.ts +90 -26
  46. package/dist/dts/AiPlan.d.ts.map +1 -1
  47. package/dist/dts/AiResponse.d.ts +711 -100
  48. package/dist/dts/AiResponse.d.ts.map +1 -1
  49. package/dist/dts/AiTelemetry.d.ts +175 -157
  50. package/dist/dts/AiTelemetry.d.ts.map +1 -1
  51. package/dist/dts/AiTool.d.ts +288 -0
  52. package/dist/dts/AiTool.d.ts.map +1 -0
  53. package/dist/dts/AiToolkit.d.ts +50 -111
  54. package/dist/dts/AiToolkit.d.ts.map +1 -1
  55. package/dist/dts/Tokenizer.d.ts +8 -6
  56. package/dist/dts/Tokenizer.d.ts.map +1 -1
  57. package/dist/dts/index.d.ts +8 -12
  58. package/dist/dts/index.d.ts.map +1 -1
  59. package/dist/dts/internal/common.d.ts +2 -0
  60. package/dist/dts/internal/common.d.ts.map +1 -0
  61. package/dist/esm/AiChat.js +62 -83
  62. package/dist/esm/AiChat.js.map +1 -1
  63. package/dist/esm/{Embeddings.js → AiEmbeddingModel.js} +10 -10
  64. package/dist/esm/AiEmbeddingModel.js.map +1 -0
  65. package/dist/esm/AiError.js +8 -1
  66. package/dist/esm/AiError.js.map +1 -1
  67. package/dist/esm/AiInput.js +316 -238
  68. package/dist/esm/AiInput.js.map +1 -1
  69. package/dist/esm/AiLanguageModel.js +300 -0
  70. package/dist/esm/AiLanguageModel.js.map +1 -0
  71. package/dist/esm/AiModel.js +11 -5
  72. package/dist/esm/AiModel.js.map +1 -1
  73. package/dist/esm/AiPlan.js +8 -2
  74. package/dist/esm/AiPlan.js.map +1 -1
  75. package/dist/esm/AiResponse.js +467 -162
  76. package/dist/esm/AiResponse.js.map +1 -1
  77. package/dist/esm/AiTelemetry.js +8 -2
  78. package/dist/esm/AiTelemetry.js.map +1 -1
  79. package/dist/esm/AiTool.js +82 -0
  80. package/dist/esm/AiTool.js.map +1 -0
  81. package/dist/esm/AiToolkit.js +118 -96
  82. package/dist/esm/AiToolkit.js.map +1 -1
  83. package/dist/esm/Tokenizer.js +14 -16
  84. package/dist/esm/Tokenizer.js.map +1 -1
  85. package/dist/esm/index.js +8 -12
  86. package/dist/esm/index.js.map +1 -1
  87. package/dist/esm/internal/aiPlan.js +4 -7
  88. package/dist/esm/internal/aiPlan.js.map +1 -1
  89. package/dist/esm/internal/common.js +14 -0
  90. package/dist/esm/internal/common.js.map +1 -0
  91. package/package.json +28 -36
  92. package/src/AiChat.ts +182 -207
  93. package/src/{Embeddings.ts → AiEmbeddingModel.ts} +19 -18
  94. package/src/AiError.ts +8 -1
  95. package/src/AiInput.ts +434 -313
  96. package/src/AiLanguageModel.ts +569 -0
  97. package/src/AiModel.ts +47 -29
  98. package/src/AiPlan.ts +102 -30
  99. package/src/AiResponse.ts +743 -187
  100. package/src/AiTelemetry.ts +214 -197
  101. package/src/AiTool.ts +496 -0
  102. package/src/AiToolkit.ts +200 -240
  103. package/src/Tokenizer.ts +18 -22
  104. package/src/index.ts +9 -14
  105. package/src/internal/aiPlan.ts +12 -14
  106. package/src/internal/common.ts +12 -0
  107. package/AiModels/package.json +0 -6
  108. package/AiRole/package.json +0 -6
  109. package/Completions/package.json +0 -6
  110. package/Embeddings/package.json +0 -6
  111. package/dist/cjs/AiModels.js +0 -54
  112. package/dist/cjs/AiModels.js.map +0 -1
  113. package/dist/cjs/AiRole.js +0 -106
  114. package/dist/cjs/AiRole.js.map +0 -1
  115. package/dist/cjs/Completions.js +0 -256
  116. package/dist/cjs/Completions.js.map +0 -1
  117. package/dist/cjs/Embeddings.js.map +0 -1
  118. package/dist/dts/AiModels.d.ts +0 -34
  119. package/dist/dts/AiModels.d.ts.map +0 -1
  120. package/dist/dts/AiRole.d.ts +0 -111
  121. package/dist/dts/AiRole.d.ts.map +0 -1
  122. package/dist/dts/Completions.d.ts +0 -128
  123. package/dist/dts/Completions.d.ts.map +0 -1
  124. package/dist/dts/Embeddings.d.ts.map +0 -1
  125. package/dist/esm/AiModels.js +0 -44
  126. package/dist/esm/AiModels.js.map +0 -1
  127. package/dist/esm/AiRole.js +0 -93
  128. package/dist/esm/AiRole.js.map +0 -1
  129. package/dist/esm/Completions.js +0 -245
  130. package/dist/esm/Completions.js.map +0 -1
  131. package/dist/esm/Embeddings.js.map +0 -1
  132. package/src/AiModels.ts +0 -77
  133. package/src/AiRole.ts +0 -122
  134. package/src/Completions.ts +0 -434
package/src/AiChat.ts CHANGED
@@ -2,264 +2,239 @@
2
2
  * @since 1.0.0
3
3
  */
4
4
  import * as Channel from "effect/Channel"
5
- import * as Chunk from "effect/Chunk"
5
+ import * as Context from "effect/Context"
6
6
  import * as Effect from "effect/Effect"
7
7
  import type { ParseError } from "effect/ParseResult"
8
8
  import * as Ref from "effect/Ref"
9
9
  import * as Schema from "effect/Schema"
10
10
  import * as Stream from "effect/Stream"
11
- import type { Concurrency } from "effect/Types"
12
11
  import type { AiError } from "./AiError.js"
13
12
  import * as AiInput from "./AiInput.js"
14
- import { AiResponse, WithResolved } from "./AiResponse.js"
15
- import type * as AiToolkit from "./AiToolkit.js"
16
- import { Completions } from "./Completions.js"
13
+ import * as AiLanguageModel from "./AiLanguageModel.js"
14
+ import * as AiResponse from "./AiResponse.js"
15
+ import type * as AiTool from "./AiTool.js"
17
16
 
18
17
  /**
19
18
  * @since 1.0.0
20
- * @category tags
19
+ * @category Context
21
20
  */
22
- export class AiChat extends Effect.Tag("@effect/ai/AiChat")<
21
+ export class AiChat extends Context.Tag("@effect/ai/AiChat")<
23
22
  AiChat,
24
23
  AiChat.Service
25
24
  >() {}
26
25
 
27
26
  /**
28
27
  * @since 1.0.0
29
- * @category models
28
+ * @category Models
30
29
  */
31
30
  export declare namespace AiChat {
32
31
  /**
33
32
  * @since 1.0.0
34
- * @category models
33
+ * @category Models
35
34
  */
36
35
  export interface Service {
36
+ /**
37
+ * The chat history.
38
+ */
37
39
  readonly history: Effect.Effect<AiInput.AiInput>
40
+
41
+ /**
42
+ * Exports the chat into a structured format.
43
+ */
38
44
  readonly export: Effect.Effect<unknown>
45
+
46
+ /**
47
+ * Exports the chat as a JSON string.
48
+ */
39
49
  readonly exportJson: Effect.Effect<string>
40
- readonly send: (input: AiInput.Input) => Effect.Effect<AiResponse, AiError>
41
- readonly stream: (input: AiInput.Input) => Stream.Stream<AiResponse, AiError>
42
- readonly structured: {
43
- <A, I, R>(options: {
44
- readonly input: AiInput.Input
45
- readonly schema: Completions.StructuredSchema<A, I, R>
46
- }): Effect.Effect<A, AiError, R>
47
- <A, I, R>(options: {
48
- readonly input: AiInput.Input
49
- readonly schema: Schema.Schema<A, I, R>
50
- readonly toolCallId: string
51
- }): Effect.Effect<A, AiError, R>
52
- }
53
- readonly toolkit: <Tools extends AiToolkit.Tool.AnySchema>(
54
- options: {
55
- readonly input: AiInput.Input
56
- readonly tools: AiToolkit.Handlers<Tools>
57
- readonly required?: Tools["_tag"] | boolean | undefined
58
- readonly concurrency?: Concurrency | undefined
59
- }
50
+
51
+ /**
52
+ * Generate text using a large language model for the specified `prompt`.
53
+ *
54
+ * If a `toolkit` is specified, the large language model will additionally
55
+ * be able to perform tool calls to augment its response.
56
+ *
57
+ * Both input and output messages will be added to the chat history.
58
+ */
59
+ readonly generateText: <Tools extends AiTool.Any, Options>(
60
+ options: Options & Omit<AiLanguageModel.GenerateTextOptions<Tools>, "system">
60
61
  ) => Effect.Effect<
61
- WithResolved<AiToolkit.Tool.Success<Tools>>,
62
- AiError | AiToolkit.Tool.Failure<Tools>,
63
- AiToolkit.Tool.Context<Tools>
62
+ AiLanguageModel.ExtractSuccess<Options>,
63
+ AiLanguageModel.ExtractError<Options>,
64
+ AiLanguageModel.ExtractContext<Options>
64
65
  >
65
- readonly toolkitStream: <Tools extends AiToolkit.Tool.AnySchema>(
66
- options: {
67
- readonly input: AiInput.Input
68
- readonly tools: AiToolkit.Handlers<Tools>
69
- readonly required?: Tools["_tag"] | boolean | undefined
70
- readonly concurrency?: Concurrency | undefined
71
- }
66
+
67
+ /**
68
+ * Generate text using a large language model for the specified `prompt`,
69
+ * streaming output from the model as soon as it is available.
70
+ *
71
+ * If a `toolkit` is specified, the large language model will additionally
72
+ * be able to perform tool calls to augment its response.
73
+ *
74
+ * Both input and output messages will be added to the chat history.
75
+ */
76
+ readonly streamText: <Tools extends AiTool.Any, Options>(
77
+ options: Options & Omit<AiLanguageModel.GenerateTextOptions<Tools>, "system">
72
78
  ) => Stream.Stream<
73
- WithResolved<AiToolkit.Tool.Success<Tools>>,
74
- AiError | AiToolkit.Tool.Failure<Tools>,
75
- AiToolkit.Tool.Context<Tools>
79
+ AiLanguageModel.ExtractSuccess<Options>,
80
+ AiLanguageModel.ExtractError<Options>,
81
+ AiLanguageModel.ExtractContext<Options>
76
82
  >
83
+
84
+ /**
85
+ * Generate a structured object for the specified prompt and schema using a
86
+ * large language model.
87
+ *
88
+ * When using a `Schema` that does not have an `identifier` or `_tag`
89
+ * property, you must specify a `toolCallId` to properly associate the
90
+ * output of the model.
91
+ *
92
+ * Both input and output messages will be added to the chat history.
93
+ */
94
+ readonly generateObject: <A, I, R>(
95
+ options: Omit<AiLanguageModel.GenerateObjectOptions<A, I, R>, "system">
96
+ ) => Effect.Effect<AiResponse.WithStructuredOutput<A>, AiError, R>
77
97
  }
78
98
  }
79
99
 
80
100
  /**
81
101
  * @since 1.0.0
82
- * @category constructors
102
+ * @category Constructors
83
103
  */
84
- export const fromInput = Effect.fnUntraced(
85
- function*(input: AiInput.Input) {
86
- const completions = yield* Completions
87
- const history = yield* Ref.make(AiInput.make(input))
88
- const semaphore = yield* Effect.makeSemaphore(1)
104
+ export const fromPrompt = Effect.fnUntraced(function*(options: {
105
+ readonly prompt: AiInput.Raw
106
+ readonly system?: string
107
+ }) {
108
+ const languageModel = yield* AiLanguageModel.AiLanguageModel
109
+ const context = yield* Effect.context<never>()
110
+ const provideContext = <A, E, R>(effect: Effect.Effect<A, E, R>): Effect.Effect<A, E, R> =>
111
+ Effect.mapInputContext(effect, (input) => Context.merge(context, input))
112
+ const provideContextStream = <A, E, R>(stream: Stream.Stream<A, E, R>): Stream.Stream<A, E, R> =>
113
+ Stream.mapInputContext(stream, (input) => Context.merge(context, input))
114
+ const history = yield* Ref.make<AiInput.AiInput>(AiInput.make(options.prompt))
115
+ const semaphore = yield* Effect.makeSemaphore(1)
116
+ const system = options.system
89
117
 
90
- return AiChat.of({
91
- history: Ref.get(history),
92
- export: Ref.get(history).pipe(
93
- Effect.flatMap(Schema.encode(AiInput.Schema)),
94
- Effect.orDie
95
- ),
96
- exportJson: Ref.get(history).pipe(
97
- Effect.flatMap(Schema.encode(AiInput.SchemaJson)),
98
- Effect.orDie
99
- ),
100
- send(input) {
101
- const newParts = AiInput.make(input)
102
- return Ref.get(history).pipe(
103
- Effect.flatMap((parts) => {
104
- const allParts = Chunk.appendAll(parts, newParts)
105
- return completions.create(allParts).pipe(
106
- Effect.tap((response) => {
107
- const responseParts = AiInput.make(response)
108
- return Ref.set(history, Chunk.appendAll(allParts, responseParts))
109
- })
110
- )
111
- }),
112
- semaphore.withPermits(1),
113
- Effect.withSpan("AiChat.send", {
114
- attributes: { input },
115
- captureStackTrace: false
116
- })
117
- )
118
- },
119
- stream(input) {
120
- return Stream.suspend(() => {
121
- let combined = AiResponse.empty
122
- return Stream.fromChannel(Channel.acquireUseRelease(
123
- semaphore.take(1).pipe(
124
- Effect.zipRight(Ref.get(history)),
125
- Effect.map(Chunk.appendAll(AiInput.make(input)))
126
- ),
127
- (parts) =>
128
- completions.stream(parts).pipe(
129
- Stream.map((chunk) => {
130
- combined = combined.concat(chunk)
131
- return chunk
132
- }),
133
- Stream.toChannel
134
- ),
135
- (parts) =>
136
- Effect.zipRight(
137
- Ref.set(history, Chunk.appendAll(parts, AiInput.make(combined))),
138
- semaphore.release(1)
139
- )
140
- ))
141
- }).pipe(Stream.withSpan("AiChat.stream", {
142
- attributes: { input },
143
- captureStackTrace: false
144
- }))
145
- },
146
- structured(options) {
147
- const newParts = AiInput.make(options.input)
148
- return Ref.get(history).pipe(
149
- Effect.flatMap((parts) => {
150
- const allParts = Chunk.appendAll(parts, newParts)
151
- return completions.structured({
118
+ return AiChat.of({
119
+ history: Ref.get(history),
120
+ export: Ref.get(history).pipe(
121
+ Effect.flatMap(Schema.encode(AiInput.AiInput)),
122
+ Effect.orDie
123
+ ),
124
+ exportJson: Ref.get(history).pipe(
125
+ Effect.flatMap(Schema.encode(AiInput.FromJson)),
126
+ Effect.orDie
127
+ ),
128
+ generateText(options) {
129
+ const newInput = AiInput.make(options.prompt)
130
+ return Ref.get(history).pipe(
131
+ Effect.flatMap((oldInput) => {
132
+ const input = AiInput.concat(oldInput, newInput)
133
+ return languageModel.generateText({
134
+ ...options,
135
+ system,
136
+ prompt: input
137
+ }).pipe(
138
+ Effect.tap((response) => {
139
+ const modelInput = AiInput.make(response)
140
+ return Ref.set(history, AiInput.concat(input, modelInput))
141
+ }),
142
+ provideContext
143
+ )
144
+ }),
145
+ semaphore.withPermits(1),
146
+ Effect.withSpan("AiChat.generateText", { captureStackTrace: false })
147
+ )
148
+ },
149
+ streamText(options) {
150
+ return Stream.suspend(() => {
151
+ let combined = AiResponse.empty
152
+ return Stream.fromChannel(Channel.acquireUseRelease(
153
+ semaphore.take(1).pipe(
154
+ Effect.zipRight(Ref.get(history)),
155
+ Effect.map((history) => AiInput.concat(history, AiInput.make(options.prompt)))
156
+ ),
157
+ (parts) =>
158
+ languageModel.streamText({
152
159
  ...options,
153
- input: allParts
154
- } as any).pipe(
155
- Effect.flatMap((response) => {
156
- const responseParts = AiInput.make(response)
157
- return Effect.as(
158
- Ref.set(history, Chunk.appendAll(allParts, responseParts)),
159
- response.unsafeValue
160
- )
161
- })
162
- )
163
- }),
164
- semaphore.withPermits(1),
165
- Effect.withSpan("AiChat.structured", {
166
- attributes: {
167
- input: options.input,
168
- schema: "toolCallId" in options
169
- ? options.toolCallId
170
- : "_tag" in options.schema
171
- ? options.schema._tag
172
- : options.schema.identifier
173
- },
174
- captureStackTrace: false
175
- })
176
- )
177
- },
178
- toolkit(options) {
179
- const newParts = AiInput.make(options.input)
180
- return Ref.get(history).pipe(
181
- Effect.flatMap((parts) => {
182
- const allParts = Chunk.appendAll(parts, newParts)
183
- return completions.toolkit({
184
- ...options,
185
- input: allParts
160
+ system,
161
+ prompt: parts
186
162
  }).pipe(
187
- Effect.tap((response) => {
188
- const responseParts = AiInput.make(response)
189
- return Ref.set(history, Chunk.appendAll(allParts, responseParts))
190
- })
191
- )
192
- }),
193
- semaphore.withPermits(1),
194
- Effect.withSpan("AiChat.toolkit", {
195
- attributes: { input: options.input },
196
- captureStackTrace: false
197
- })
198
- )
199
- },
200
- toolkitStream<Tools extends AiToolkit.Tool.AnySchema>(options: {
201
- readonly input: AiInput.Input
202
- readonly tools: AiToolkit.Handlers<Tools>
203
- readonly required?: Tools["_tag"] | boolean | undefined
204
- readonly concurrency?: Concurrency | undefined
205
- }): Stream.Stream<
206
- WithResolved<AiToolkit.Tool.Success<Tools>>,
207
- AiError | AiToolkit.Tool.Failure<Tools>,
208
- AiToolkit.Tool.Context<Tools>
209
- > {
210
- return Stream.suspend(() => {
211
- let combined = WithResolved.empty as WithResolved<AiToolkit.Tool.Success<Tools>>
212
- return Stream.fromChannel(Channel.acquireUseRelease(
213
- semaphore.take(1).pipe(
214
- Effect.zipRight(Ref.get(history)),
215
- Effect.map(Chunk.appendAll(AiInput.make(options.input)))
163
+ Stream.map((chunk) => {
164
+ combined = AiResponse.merge(combined, chunk)
165
+ return chunk
166
+ }),
167
+ Stream.toChannel
216
168
  ),
217
- (parts) =>
218
- completions.toolkitStream({
219
- ...options,
220
- input: parts
221
- }).pipe(
222
- Stream.map((chunk) => {
223
- combined = combined.concat(chunk)
224
- return chunk
225
- }),
226
- Stream.toChannel
227
- ),
228
- (parts) =>
229
- Effect.zipRight(
230
- Ref.set(history, Chunk.appendAll(parts, AiInput.make(combined))),
231
- semaphore.release(1)
169
+ (parts) =>
170
+ Effect.zipRight(
171
+ Ref.set(history, AiInput.concat(parts, AiInput.make(combined))),
172
+ semaphore.release(1)
173
+ )
174
+ ))
175
+ }).pipe(
176
+ provideContextStream,
177
+ Stream.withSpan("AiChat.streamText", {
178
+ captureStackTrace: false
179
+ })
180
+ ) as any
181
+ },
182
+ generateObject(options) {
183
+ const newInput = AiInput.make(options.prompt)
184
+ return Ref.get(history).pipe(
185
+ Effect.flatMap((oldInput) => {
186
+ const input = AiInput.concat(oldInput, newInput)
187
+ return languageModel.generateObject({
188
+ ...options,
189
+ system,
190
+ prompt: input
191
+ } as any).pipe(
192
+ Effect.flatMap((response) => {
193
+ const modelInput = AiInput.make(response)
194
+ return Effect.as(
195
+ Ref.set(history, AiInput.concat(input, modelInput)),
196
+ response
232
197
  )
233
- ))
234
- }).pipe(Stream.withSpan("AiChat.toolkitStream", {
235
- attributes: { input: options.input },
198
+ })
199
+ )
200
+ }),
201
+ provideContext,
202
+ semaphore.withPermits(1),
203
+ Effect.withSpan("AiChat.generateObject", {
204
+ attributes: {
205
+ toolCallId: "toolCallId" in options
206
+ ? options.toolCallId
207
+ : "_tag" in options.schema
208
+ ? options.schema._tag
209
+ : (options.schema as any).identifier ?? "generateObject"
210
+ },
236
211
  captureStackTrace: false
237
- }))
238
- }
239
- })
240
- }
241
- )
212
+ })
213
+ ) as any
214
+ }
215
+ })
216
+ })
242
217
 
243
218
  /**
244
219
  * @since 1.0.0
245
- * @category constructors
220
+ * @category Constructors
246
221
  */
247
- export const empty: Effect.Effect<AiChat.Service, never, Completions> = fromInput(AiInput.empty)
222
+ export const empty: Effect.Effect<AiChat.Service, never, AiLanguageModel.AiLanguageModel> = fromPrompt({ prompt: [] })
223
+
224
+ const decodeUnknown = Schema.decodeUnknown(AiInput.AiInput)
248
225
 
249
226
  /**
250
227
  * @since 1.0.0
251
- * @category constructors
228
+ * @category Constructors
252
229
  */
253
- export const fromExport = (data: unknown): Effect.Effect<AiChat.Service, ParseError, Completions> =>
254
- Schema.decodeUnknown(AiInput.Schema)(data).pipe(
255
- Effect.flatMap(fromInput)
256
- )
230
+ export const fromExport = (data: unknown): Effect.Effect<AiChat.Service, ParseError, AiLanguageModel.AiLanguageModel> =>
231
+ Effect.flatMap(decodeUnknown(data), (prompt) => fromPrompt({ prompt }))
232
+
233
+ const decodeJson = Schema.decode(AiInput.FromJson)
257
234
 
258
235
  /**
259
236
  * @since 1.0.0
260
- * @category constructors
237
+ * @category Constructors
261
238
  */
262
- export const fromJson = (data: string): Effect.Effect<AiChat.Service, ParseError, Completions> =>
263
- Schema.decode(AiInput.SchemaJson)(data).pipe(
264
- Effect.flatMap(fromInput)
265
- )
239
+ export const fromJson = (data: string): Effect.Effect<AiChat.Service, ParseError, AiLanguageModel.AiLanguageModel> =>
240
+ Effect.flatMap(decodeJson(data), (prompt) => fromPrompt({ prompt }))
@@ -14,21 +14,20 @@ import { AiError } from "./AiError.js"
14
14
 
15
15
  /**
16
16
  * @since 1.0.0
17
- * @category tags
17
+ * @category Context
18
18
  */
19
- export class Embeddings extends Context.Tag("@effect/ai/Embeddings")<
20
- Embeddings,
21
- Embeddings.Service
19
+ export class AiEmbeddingModel extends Context.Tag("@effect/ai/AiEmbeddingModel")<
20
+ AiEmbeddingModel,
21
+ AiEmbeddingModel.Service
22
22
  >() {}
23
23
 
24
24
  /**
25
25
  * @since 1.0.0
26
- * @category models
27
26
  */
28
- export declare namespace Embeddings {
27
+ export declare namespace AiEmbeddingModel {
29
28
  /**
30
29
  * @since 1.0.0
31
- * @category models
30
+ * @category Models
32
31
  */
33
32
  export interface Service {
34
33
  readonly embed: (input: string) => Effect.Effect<Array<number>, AiError>
@@ -36,7 +35,7 @@ export declare namespace Embeddings {
36
35
 
37
36
  /**
38
37
  * @since 1.0.0
39
- * @category models
38
+ * @category Models
40
39
  */
41
40
  export interface Result {
42
41
  readonly index: number
@@ -44,14 +43,16 @@ export declare namespace Embeddings {
44
43
  }
45
44
  }
46
45
 
47
- class EmbeddingRequest extends Schema.TaggedRequest<EmbeddingRequest>()("EmbeddingRequest", {
46
+ class EmbeddingRequest extends Schema.TaggedRequest<EmbeddingRequest>(
47
+ "@effect/ai/AiEmbeddingModel/Request"
48
+ )("EmbeddingRequest", {
48
49
  failure: AiError,
49
50
  success: Schema.mutable(Schema.Array(Schema.Number)),
50
51
  payload: { input: Schema.String }
51
52
  }) {}
52
53
 
53
54
  const makeBatchedResolver = (
54
- embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<Embeddings.Result>, AiError>
55
+ embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<AiEmbeddingModel.Result>, AiError>
55
56
  ) =>
56
57
  RequestResolver.makeBatched(
57
58
  (requests: ReadonlyArray<EmbeddingRequest>) =>
@@ -74,10 +75,10 @@ const makeBatchedResolver = (
74
75
 
75
76
  /**
76
77
  * @since 1.0.0
77
- * @category constructors
78
+ * @category Constructors
78
79
  */
79
80
  export const make = (options: {
80
- readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<Embeddings.Result>, AiError>
81
+ readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<AiEmbeddingModel.Result>, AiError>
81
82
  readonly maxBatchSize?: number
82
83
  readonly cache?: {
83
84
  readonly capacity: number
@@ -103,10 +104,10 @@ export const make = (options: {
103
104
  Effect.withRequestCaching(true),
104
105
  Effect.withRequestCache(cache)
105
106
  )
106
- }).pipe(Effect.withSpan("Embeddings.embed", { captureStackTrace: false }))
107
+ }).pipe(Effect.withSpan("AiEmbeddingModel.embed", { captureStackTrace: false }))
107
108
  }
108
109
 
109
- return Embeddings.of({
110
+ return AiEmbeddingModel.of({
110
111
  embed
111
112
  })
112
113
  })
@@ -117,10 +118,10 @@ export const make = (options: {
117
118
  * requests, if specified) and execute them as a single batch.
118
119
  *
119
120
  * @since 1.0.0
120
- * @category constructors
121
+ * @category Constructors
121
122
  */
122
123
  export const makeDataLoader = (options: {
123
- readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<Embeddings.Result>, AiError>
124
+ readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<AiEmbeddingModel.Result>, AiError>
124
125
  readonly window: Duration.DurationInput
125
126
  readonly maxBatchSize?: number
126
127
  }) =>
@@ -133,11 +134,11 @@ export const makeDataLoader = (options: {
133
134
 
134
135
  function embed(input: string) {
135
136
  return Effect.request(new EmbeddingRequest({ input }), resolverDelayed).pipe(
136
- Effect.withSpan("Embeddings.embed", { captureStackTrace: false })
137
+ Effect.withSpan("AiEmbeddingModel.embed", { captureStackTrace: false })
137
138
  )
138
139
  }
139
140
 
140
- return Embeddings.of({
141
+ return AiEmbeddingModel.of({
141
142
  embed
142
143
  })
143
144
  })
package/src/AiError.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  /**
2
2
  * @since 1.0.0
3
3
  */
4
+ import * as Predicate from "effect/Predicate"
4
5
  import * as Schema from "effect/Schema"
5
6
 
6
7
  /**
7
8
  * @since 1.0.0
8
9
  * @category type ids
9
10
  */
10
- export const TypeId: unique symbol = Symbol("@effect/ai/AiError")
11
+ export const TypeId: unique symbol = Symbol.for("@effect/ai/AiError")
11
12
 
12
13
  /**
13
14
  * @since 1.0.0
@@ -25,6 +26,12 @@ export class AiError extends Schema.TaggedError<AiError>("@effect/ai/AiError")("
25
26
  description: Schema.String,
26
27
  cause: Schema.optional(Schema.Defect)
27
28
  }) {
29
+ /**
30
+ * @since 1.0.0
31
+ */
32
+ static is(u: unknown): u is AiError {
33
+ return Predicate.hasProperty(u, TypeId)
34
+ }
28
35
  /**
29
36
  * @since 1.0.0
30
37
  */