@effect/ai 0.8.1 → 0.8.2
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/AiTelemetry/package.json +6 -0
- package/Embeddings/package.json +6 -0
- package/dist/cjs/AiChat.js +90 -103
- package/dist/cjs/AiChat.js.map +1 -1
- package/dist/cjs/AiTelemetry.js +52 -0
- package/dist/cjs/AiTelemetry.js.map +1 -0
- package/dist/cjs/Completions.js +50 -46
- package/dist/cjs/Completions.js.map +1 -1
- package/dist/cjs/Embeddings.js +92 -0
- package/dist/cjs/Embeddings.js.map +1 -0
- package/dist/cjs/index.js +5 -1
- package/dist/dts/AiChat.d.ts +12 -1
- package/dist/dts/AiChat.d.ts.map +1 -1
- package/dist/dts/AiTelemetry.d.ts +205 -0
- package/dist/dts/AiTelemetry.d.ts.map +1 -0
- package/dist/dts/Completions.d.ts +29 -8
- package/dist/dts/Completions.d.ts.map +1 -1
- package/dist/dts/Embeddings.d.ts +59 -0
- package/dist/dts/Embeddings.d.ts.map +1 -0
- package/dist/dts/index.d.ts +8 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/AiChat.js +90 -102
- package/dist/esm/AiChat.js.map +1 -1
- package/dist/esm/AiTelemetry.js +42 -0
- package/dist/esm/AiTelemetry.js.map +1 -0
- package/dist/esm/Completions.js +50 -46
- package/dist/esm/Completions.js.map +1 -1
- package/dist/esm/Embeddings.js +80 -0
- package/dist/esm/Embeddings.js.map +1 -0
- package/dist/esm/index.js +8 -0
- package/dist/esm/index.js.map +1 -1
- package/package.json +20 -3
- package/src/AiChat.ts +160 -169
- package/src/AiTelemetry.ts +297 -0
- package/src/Completions.ts +140 -107
- package/src/Embeddings.ts +143 -0
- package/src/index.ts +10 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import { dataLoader } from "@effect/experimental/RequestResolver"
|
|
5
|
+
import * as Context from "effect/Context"
|
|
6
|
+
import type * as Duration from "effect/Duration"
|
|
7
|
+
import * as Effect from "effect/Effect"
|
|
8
|
+
import { identity } from "effect/Function"
|
|
9
|
+
import * as Option from "effect/Option"
|
|
10
|
+
import * as Request from "effect/Request"
|
|
11
|
+
import * as RequestResolver from "effect/RequestResolver"
|
|
12
|
+
import * as Schema from "effect/Schema"
|
|
13
|
+
import { AiError } from "./AiError.js"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @since 1.0.0
|
|
17
|
+
* @category tags
|
|
18
|
+
*/
|
|
19
|
+
export class Embeddings extends Context.Tag("@effect/ai/Embeddings")<
|
|
20
|
+
Embeddings,
|
|
21
|
+
Embeddings.Service
|
|
22
|
+
>() {}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @since 1.0.0
|
|
26
|
+
* @category models
|
|
27
|
+
*/
|
|
28
|
+
export declare namespace Embeddings {
|
|
29
|
+
/**
|
|
30
|
+
* @since 1.0.0
|
|
31
|
+
* @category models
|
|
32
|
+
*/
|
|
33
|
+
export interface Service {
|
|
34
|
+
readonly embed: (input: string) => Effect.Effect<Array<number>, AiError>
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @since 1.0.0
|
|
39
|
+
* @category models
|
|
40
|
+
*/
|
|
41
|
+
export interface Result {
|
|
42
|
+
readonly index: number
|
|
43
|
+
readonly embeddings: Array<number>
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class EmbeddingRequest extends Schema.TaggedRequest<EmbeddingRequest>()("EmbeddingRequest", {
|
|
48
|
+
failure: AiError,
|
|
49
|
+
success: Schema.mutable(Schema.Array(Schema.Number)),
|
|
50
|
+
payload: { input: Schema.String }
|
|
51
|
+
}) {}
|
|
52
|
+
|
|
53
|
+
const makeBatchedResolver = (
|
|
54
|
+
embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<Embeddings.Result>, AiError>
|
|
55
|
+
) =>
|
|
56
|
+
RequestResolver.makeBatched(
|
|
57
|
+
(requests: ReadonlyArray<EmbeddingRequest>) =>
|
|
58
|
+
embedMany(requests.map((request) => request.input)).pipe(
|
|
59
|
+
Effect.flatMap(
|
|
60
|
+
Effect.forEach(
|
|
61
|
+
({ embeddings, index }) => Request.succeed(requests[index], embeddings),
|
|
62
|
+
{ discard: true }
|
|
63
|
+
)
|
|
64
|
+
),
|
|
65
|
+
Effect.catchAll((error) =>
|
|
66
|
+
Effect.forEach(
|
|
67
|
+
requests,
|
|
68
|
+
(request) => Request.fail(request, error),
|
|
69
|
+
{ discard: true }
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @since 1.0.0
|
|
77
|
+
* @category constructors
|
|
78
|
+
*/
|
|
79
|
+
export const make = (options: {
|
|
80
|
+
readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<Embeddings.Result>, AiError>
|
|
81
|
+
readonly maxBatchSize?: number
|
|
82
|
+
readonly cache?: {
|
|
83
|
+
readonly capacity: number
|
|
84
|
+
readonly timeToLive: Duration.DurationInput
|
|
85
|
+
}
|
|
86
|
+
}) =>
|
|
87
|
+
Effect.gen(function*() {
|
|
88
|
+
const cache = yield* Option.fromNullable(options.cache).pipe(
|
|
89
|
+
Effect.flatMap((config) => Request.makeCache(config)),
|
|
90
|
+
Effect.optionFromOptional
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
const resolver = makeBatchedResolver(options.embedMany).pipe(
|
|
94
|
+
options.maxBatchSize ? RequestResolver.batchN(options.maxBatchSize) : identity
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
function embed(input: string) {
|
|
98
|
+
const request = Effect.request(new EmbeddingRequest({ input }), resolver)
|
|
99
|
+
return Option.match(cache, {
|
|
100
|
+
onNone: () => request,
|
|
101
|
+
onSome: (cache) =>
|
|
102
|
+
request.pipe(
|
|
103
|
+
Effect.withRequestCaching(true),
|
|
104
|
+
Effect.withRequestCache(cache)
|
|
105
|
+
)
|
|
106
|
+
}).pipe(Effect.withSpan("Embeddings.embed", { captureStackTrace: false }))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return Embeddings.of({
|
|
110
|
+
embed
|
|
111
|
+
})
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Creates an `Embeddings` service which will aggregate all `embed` requests
|
|
116
|
+
* received during the specified `window` (up to a maximum of `maxBatchSize`
|
|
117
|
+
* requests, if specified) and execute them as a single batch.
|
|
118
|
+
*
|
|
119
|
+
* @since 1.0.0
|
|
120
|
+
* @category constructors
|
|
121
|
+
*/
|
|
122
|
+
export const makeDataLoader = (options: {
|
|
123
|
+
readonly embedMany: (input: ReadonlyArray<string>) => Effect.Effect<Array<Embeddings.Result>, AiError>
|
|
124
|
+
readonly window: Duration.DurationInput
|
|
125
|
+
readonly maxBatchSize?: number
|
|
126
|
+
}) =>
|
|
127
|
+
Effect.gen(function*() {
|
|
128
|
+
const resolver = makeBatchedResolver(options.embedMany)
|
|
129
|
+
const resolverDelayed = yield* dataLoader(resolver, {
|
|
130
|
+
window: options.window,
|
|
131
|
+
maxBatchSize: options.maxBatchSize
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
function embed(input: string) {
|
|
135
|
+
return Effect.request(new EmbeddingRequest({ input }), resolverDelayed).pipe(
|
|
136
|
+
Effect.withSpan("Embeddings.embed", { captureStackTrace: false })
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return Embeddings.of({
|
|
141
|
+
embed
|
|
142
|
+
})
|
|
143
|
+
})
|
package/src/index.ts
CHANGED
|
@@ -23,6 +23,11 @@ export * as AiResponse from "./AiResponse.js"
|
|
|
23
23
|
*/
|
|
24
24
|
export * as AiRole from "./AiRole.js"
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @since 1.0.0
|
|
28
|
+
*/
|
|
29
|
+
export * as AiTelemetry from "./AiTelemetry.js"
|
|
30
|
+
|
|
26
31
|
/**
|
|
27
32
|
* @since 1.0.0
|
|
28
33
|
*/
|
|
@@ -33,6 +38,11 @@ export * as AiToolkit from "./AiToolkit.js"
|
|
|
33
38
|
*/
|
|
34
39
|
export * as Completions from "./Completions.js"
|
|
35
40
|
|
|
41
|
+
/**
|
|
42
|
+
* @since 1.0.0
|
|
43
|
+
*/
|
|
44
|
+
export * as Embeddings from "./Embeddings.js"
|
|
45
|
+
|
|
36
46
|
/**
|
|
37
47
|
* @since 1.0.0
|
|
38
48
|
*/
|