@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.
- package/AiEmbeddingModel/package.json +6 -0
- package/AiLanguageModel/package.json +6 -0
- package/AiTool/package.json +6 -0
- package/dist/cjs/AiChat.js +65 -86
- package/dist/cjs/AiChat.js.map +1 -1
- package/dist/cjs/{Embeddings.js → AiEmbeddingModel.js} +12 -12
- package/dist/cjs/AiEmbeddingModel.js.map +1 -0
- package/dist/cjs/AiError.js +8 -1
- package/dist/cjs/AiError.js.map +1 -1
- package/dist/cjs/AiInput.js +335 -248
- package/dist/cjs/AiInput.js.map +1 -1
- package/dist/cjs/AiLanguageModel.js +311 -0
- package/dist/cjs/AiLanguageModel.js.map +1 -0
- package/dist/cjs/AiModel.js +11 -5
- package/dist/cjs/AiModel.js.map +1 -1
- package/dist/cjs/AiPlan.js +10 -3
- package/dist/cjs/AiPlan.js.map +1 -1
- package/dist/cjs/AiResponse.js +481 -165
- package/dist/cjs/AiResponse.js.map +1 -1
- package/dist/cjs/AiTelemetry.js +10 -3
- package/dist/cjs/AiTelemetry.js.map +1 -1
- package/dist/cjs/AiTool.js +93 -0
- package/dist/cjs/AiTool.js.map +1 -0
- package/dist/cjs/AiToolkit.js +121 -98
- package/dist/cjs/AiToolkit.js.map +1 -1
- package/dist/cjs/Tokenizer.js +14 -16
- package/dist/cjs/Tokenizer.js.map +1 -1
- package/dist/cjs/index.js +7 -9
- package/dist/cjs/internal/aiPlan.js +6 -9
- package/dist/cjs/internal/aiPlan.js.map +1 -1
- package/dist/cjs/internal/common.js +22 -0
- package/dist/cjs/internal/common.js.map +1 -0
- package/dist/dts/AiChat.d.ts +58 -44
- package/dist/dts/AiChat.d.ts.map +1 -1
- package/dist/dts/{Embeddings.d.ts → AiEmbeddingModel.d.ts} +13 -14
- package/dist/dts/AiEmbeddingModel.d.ts.map +1 -0
- package/dist/dts/AiError.d.ts +4 -3
- package/dist/dts/AiError.d.ts.map +1 -1
- package/dist/dts/AiInput.d.ts +441 -146
- package/dist/dts/AiInput.d.ts.map +1 -1
- package/dist/dts/AiLanguageModel.d.ts +263 -0
- package/dist/dts/AiLanguageModel.d.ts.map +1 -0
- package/dist/dts/AiModel.d.ts +21 -20
- package/dist/dts/AiModel.d.ts.map +1 -1
- package/dist/dts/AiPlan.d.ts +90 -26
- package/dist/dts/AiPlan.d.ts.map +1 -1
- package/dist/dts/AiResponse.d.ts +711 -100
- package/dist/dts/AiResponse.d.ts.map +1 -1
- package/dist/dts/AiTelemetry.d.ts +175 -157
- package/dist/dts/AiTelemetry.d.ts.map +1 -1
- package/dist/dts/AiTool.d.ts +288 -0
- package/dist/dts/AiTool.d.ts.map +1 -0
- package/dist/dts/AiToolkit.d.ts +50 -111
- package/dist/dts/AiToolkit.d.ts.map +1 -1
- package/dist/dts/Tokenizer.d.ts +8 -6
- package/dist/dts/Tokenizer.d.ts.map +1 -1
- package/dist/dts/index.d.ts +8 -12
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/common.d.ts +2 -0
- package/dist/dts/internal/common.d.ts.map +1 -0
- package/dist/esm/AiChat.js +62 -83
- package/dist/esm/AiChat.js.map +1 -1
- package/dist/esm/{Embeddings.js → AiEmbeddingModel.js} +10 -10
- package/dist/esm/AiEmbeddingModel.js.map +1 -0
- package/dist/esm/AiError.js +8 -1
- package/dist/esm/AiError.js.map +1 -1
- package/dist/esm/AiInput.js +316 -238
- package/dist/esm/AiInput.js.map +1 -1
- package/dist/esm/AiLanguageModel.js +300 -0
- package/dist/esm/AiLanguageModel.js.map +1 -0
- package/dist/esm/AiModel.js +11 -5
- package/dist/esm/AiModel.js.map +1 -1
- package/dist/esm/AiPlan.js +8 -2
- package/dist/esm/AiPlan.js.map +1 -1
- package/dist/esm/AiResponse.js +467 -162
- package/dist/esm/AiResponse.js.map +1 -1
- package/dist/esm/AiTelemetry.js +8 -2
- package/dist/esm/AiTelemetry.js.map +1 -1
- package/dist/esm/AiTool.js +82 -0
- package/dist/esm/AiTool.js.map +1 -0
- package/dist/esm/AiToolkit.js +118 -96
- package/dist/esm/AiToolkit.js.map +1 -1
- package/dist/esm/Tokenizer.js +14 -16
- package/dist/esm/Tokenizer.js.map +1 -1
- package/dist/esm/index.js +8 -12
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/aiPlan.js +4 -7
- package/dist/esm/internal/aiPlan.js.map +1 -1
- package/dist/esm/internal/common.js +14 -0
- package/dist/esm/internal/common.js.map +1 -0
- package/package.json +28 -36
- package/src/AiChat.ts +182 -207
- package/src/{Embeddings.ts → AiEmbeddingModel.ts} +19 -18
- package/src/AiError.ts +8 -1
- package/src/AiInput.ts +434 -313
- package/src/AiLanguageModel.ts +569 -0
- package/src/AiModel.ts +47 -29
- package/src/AiPlan.ts +102 -30
- package/src/AiResponse.ts +743 -187
- package/src/AiTelemetry.ts +214 -197
- package/src/AiTool.ts +496 -0
- package/src/AiToolkit.ts +200 -240
- package/src/Tokenizer.ts +18 -22
- package/src/index.ts +9 -14
- package/src/internal/aiPlan.ts +12 -14
- package/src/internal/common.ts +12 -0
- package/AiModels/package.json +0 -6
- package/AiRole/package.json +0 -6
- package/Completions/package.json +0 -6
- package/Embeddings/package.json +0 -6
- package/dist/cjs/AiModels.js +0 -54
- package/dist/cjs/AiModels.js.map +0 -1
- package/dist/cjs/AiRole.js +0 -106
- package/dist/cjs/AiRole.js.map +0 -1
- package/dist/cjs/Completions.js +0 -256
- package/dist/cjs/Completions.js.map +0 -1
- package/dist/cjs/Embeddings.js.map +0 -1
- package/dist/dts/AiModels.d.ts +0 -34
- package/dist/dts/AiModels.d.ts.map +0 -1
- package/dist/dts/AiRole.d.ts +0 -111
- package/dist/dts/AiRole.d.ts.map +0 -1
- package/dist/dts/Completions.d.ts +0 -128
- package/dist/dts/Completions.d.ts.map +0 -1
- package/dist/dts/Embeddings.d.ts.map +0 -1
- package/dist/esm/AiModels.js +0 -44
- package/dist/esm/AiModels.js.map +0 -1
- package/dist/esm/AiRole.js +0 -93
- package/dist/esm/AiRole.js.map +0 -1
- package/dist/esm/Completions.js +0 -245
- package/dist/esm/Completions.js.map +0 -1
- package/dist/esm/Embeddings.js.map +0 -1
- package/src/AiModels.ts +0 -77
- package/src/AiRole.ts +0 -122
- 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
|
|
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
|
|
15
|
-
import
|
|
16
|
-
import
|
|
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
|
|
19
|
+
* @category Context
|
|
21
20
|
*/
|
|
22
|
-
export class AiChat extends
|
|
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
|
|
28
|
+
* @category Models
|
|
30
29
|
*/
|
|
31
30
|
export declare namespace AiChat {
|
|
32
31
|
/**
|
|
33
32
|
* @since 1.0.0
|
|
34
|
-
* @category
|
|
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
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
AiLanguageModel.ExtractSuccess<Options>,
|
|
63
|
+
AiLanguageModel.ExtractError<Options>,
|
|
64
|
+
AiLanguageModel.ExtractContext<Options>
|
|
64
65
|
>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
|
102
|
+
* @category Constructors
|
|
83
103
|
*/
|
|
84
|
-
export const
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
),
|
|
127
|
-
(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
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
|
-
|
|
154
|
-
|
|
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
|
-
|
|
188
|
-
|
|
189
|
-
return
|
|
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
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
235
|
-
|
|
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
|
|
220
|
+
* @category Constructors
|
|
246
221
|
*/
|
|
247
|
-
export const empty: Effect.Effect<AiChat.Service, never,
|
|
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
|
|
228
|
+
* @category Constructors
|
|
252
229
|
*/
|
|
253
|
-
export const fromExport = (data: unknown): Effect.Effect<AiChat.Service, ParseError,
|
|
254
|
-
|
|
255
|
-
|
|
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
|
|
237
|
+
* @category Constructors
|
|
261
238
|
*/
|
|
262
|
-
export const fromJson = (data: string): Effect.Effect<AiChat.Service, ParseError,
|
|
263
|
-
|
|
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
|
|
17
|
+
* @category Context
|
|
18
18
|
*/
|
|
19
|
-
export class
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
27
|
+
export declare namespace AiEmbeddingModel {
|
|
29
28
|
/**
|
|
30
29
|
* @since 1.0.0
|
|
31
|
-
* @category
|
|
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
|
|
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>(
|
|
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<
|
|
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
|
|
78
|
+
* @category Constructors
|
|
78
79
|
*/
|
|
79
80
|
export const make = (options: {
|
|
80
|
-
readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<
|
|
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("
|
|
107
|
+
}).pipe(Effect.withSpan("AiEmbeddingModel.embed", { captureStackTrace: false }))
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
return
|
|
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
|
|
121
|
+
* @category Constructors
|
|
121
122
|
*/
|
|
122
123
|
export const makeDataLoader = (options: {
|
|
123
|
-
readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<
|
|
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("
|
|
137
|
+
Effect.withSpan("AiEmbeddingModel.embed", { captureStackTrace: false })
|
|
137
138
|
)
|
|
138
139
|
}
|
|
139
140
|
|
|
140
|
-
return
|
|
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
|
*/
|