@effect/ai-openai 4.0.0-beta.7 → 4.0.0-beta.70
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/dist/Generated.d.ts +66734 -37723
- package/dist/Generated.d.ts.map +1 -1
- package/dist/Generated.js +1 -1
- package/dist/Generated.js.map +1 -1
- package/dist/OpenAiClient.d.ts +81 -25
- package/dist/OpenAiClient.d.ts.map +1 -1
- package/dist/OpenAiClient.js +220 -39
- package/dist/OpenAiClient.js.map +1 -1
- package/dist/OpenAiClientGenerated.d.ts +91 -0
- package/dist/OpenAiClientGenerated.d.ts.map +1 -0
- package/dist/OpenAiClientGenerated.js +84 -0
- package/dist/OpenAiClientGenerated.js.map +1 -0
- package/dist/OpenAiConfig.d.ts +45 -10
- package/dist/OpenAiConfig.d.ts.map +1 -1
- package/dist/OpenAiConfig.js +31 -7
- package/dist/OpenAiConfig.js.map +1 -1
- package/dist/OpenAiEmbeddingModel.d.ts +89 -0
- package/dist/OpenAiEmbeddingModel.d.ts.map +1 -0
- package/dist/OpenAiEmbeddingModel.js +121 -0
- package/dist/OpenAiEmbeddingModel.js.map +1 -0
- package/dist/OpenAiError.d.ts +168 -35
- package/dist/OpenAiError.d.ts.map +1 -1
- package/dist/OpenAiError.js +1 -1
- package/dist/OpenAiLanguageModel.d.ts +250 -57
- package/dist/OpenAiLanguageModel.d.ts.map +1 -1
- package/dist/OpenAiLanguageModel.js +311 -160
- package/dist/OpenAiLanguageModel.js.map +1 -1
- package/dist/OpenAiSchema.d.ts +2029 -0
- package/dist/OpenAiSchema.d.ts.map +1 -0
- package/dist/OpenAiSchema.js +591 -0
- package/dist/OpenAiSchema.js.map +1 -0
- package/dist/OpenAiTelemetry.d.ts +31 -18
- package/dist/OpenAiTelemetry.d.ts.map +1 -1
- package/dist/OpenAiTelemetry.js +6 -4
- package/dist/OpenAiTelemetry.js.map +1 -1
- package/dist/OpenAiTool.d.ts +56 -67
- package/dist/OpenAiTool.d.ts.map +1 -1
- package/dist/OpenAiTool.js +33 -44
- package/dist/OpenAiTool.js.map +1 -1
- package/dist/index.d.ts +42 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -8
- package/dist/index.js.map +1 -1
- package/dist/internal/errors.js +4 -4
- package/dist/internal/errors.js.map +1 -1
- package/package.json +3 -3
- package/src/Generated.ts +9858 -5044
- package/src/OpenAiClient.ts +396 -90
- package/src/OpenAiClientGenerated.ts +202 -0
- package/src/OpenAiConfig.ts +46 -11
- package/src/OpenAiEmbeddingModel.ts +207 -0
- package/src/OpenAiError.ts +170 -35
- package/src/OpenAiLanguageModel.ts +633 -157
- package/src/OpenAiSchema.ts +984 -0
- package/src/OpenAiTelemetry.ts +32 -19
- package/src/OpenAiTool.ts +34 -45
- package/src/index.ts +45 -8
- package/src/internal/errors.ts +6 -4
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 4.0.0
|
|
3
|
+
*/
|
|
4
|
+
import * as Array from "effect/Array"
|
|
5
|
+
import type * as Config from "effect/Config"
|
|
6
|
+
import * as Context from "effect/Context"
|
|
7
|
+
import * as Effect from "effect/Effect"
|
|
8
|
+
import { identity } from "effect/Function"
|
|
9
|
+
import * as Function from "effect/Function"
|
|
10
|
+
import * as Layer from "effect/Layer"
|
|
11
|
+
import * as Predicate from "effect/Predicate"
|
|
12
|
+
import * as Redacted from "effect/Redacted"
|
|
13
|
+
import * as Headers from "effect/unstable/http/Headers"
|
|
14
|
+
import * as HttpClient from "effect/unstable/http/HttpClient"
|
|
15
|
+
import * as HttpClientRequest from "effect/unstable/http/HttpClientRequest"
|
|
16
|
+
import * as Generated from "./Generated.ts"
|
|
17
|
+
import { OpenAiConfig } from "./OpenAiConfig.ts"
|
|
18
|
+
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Service Identifier
|
|
21
|
+
// =============================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Service identifier for the generated OpenAI client.
|
|
25
|
+
*
|
|
26
|
+
* @since 4.0.0
|
|
27
|
+
* @category service
|
|
28
|
+
*/
|
|
29
|
+
export class OpenAiClientGenerated extends Context.Service<OpenAiClientGenerated, Generated.OpenAiClient>()(
|
|
30
|
+
"@effect/ai-openai/OpenAiClientGenerated"
|
|
31
|
+
) {}
|
|
32
|
+
|
|
33
|
+
// =============================================================================
|
|
34
|
+
// Options
|
|
35
|
+
// =============================================================================
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Options for configuring the generated OpenAI client.
|
|
39
|
+
*
|
|
40
|
+
* @since 4.0.0
|
|
41
|
+
* @category models
|
|
42
|
+
*/
|
|
43
|
+
export type Options = {
|
|
44
|
+
/**
|
|
45
|
+
* The OpenAI API key.
|
|
46
|
+
*/
|
|
47
|
+
readonly apiKey?: Redacted.Redacted<string> | undefined
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* The base URL for the OpenAI API.
|
|
51
|
+
*
|
|
52
|
+
* @default "https://api.openai.com/v1"
|
|
53
|
+
*/
|
|
54
|
+
readonly apiUrl?: string | undefined
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Optional organization ID for multi-org accounts.
|
|
58
|
+
*/
|
|
59
|
+
readonly organizationId?: Redacted.Redacted<string> | undefined
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Optional project ID for project-scoped requests.
|
|
63
|
+
*/
|
|
64
|
+
readonly projectId?: Redacted.Redacted<string> | undefined
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Optional transformer for the HTTP client.
|
|
68
|
+
*/
|
|
69
|
+
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const RedactedOpenAiHeaders = {
|
|
73
|
+
OpenAiOrganization: "OpenAI-Organization",
|
|
74
|
+
OpenAiProject: "OpenAI-Project"
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// =============================================================================
|
|
78
|
+
// Constructor
|
|
79
|
+
// =============================================================================
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Creates a generated OpenAI client service with the given options.
|
|
83
|
+
*
|
|
84
|
+
* @since 4.0.0
|
|
85
|
+
* @category constructors
|
|
86
|
+
*/
|
|
87
|
+
export const make = Effect.fnUntraced(
|
|
88
|
+
function*(options: Options): Effect.fn.Return<Generated.OpenAiClient, never, HttpClient.HttpClient> {
|
|
89
|
+
const baseClient = yield* HttpClient.HttpClient
|
|
90
|
+
const apiUrl = options.apiUrl ?? "https://api.openai.com/v1"
|
|
91
|
+
|
|
92
|
+
const httpClient = baseClient.pipe(
|
|
93
|
+
HttpClient.mapRequest(Function.flow(
|
|
94
|
+
HttpClientRequest.prependUrl(apiUrl),
|
|
95
|
+
options.apiKey
|
|
96
|
+
? HttpClientRequest.bearerToken(Redacted.value(options.apiKey))
|
|
97
|
+
: identity,
|
|
98
|
+
options.organizationId
|
|
99
|
+
? HttpClientRequest.setHeader(
|
|
100
|
+
RedactedOpenAiHeaders.OpenAiOrganization,
|
|
101
|
+
Redacted.value(options.organizationId)
|
|
102
|
+
)
|
|
103
|
+
: identity,
|
|
104
|
+
options.projectId
|
|
105
|
+
? HttpClientRequest.setHeader(
|
|
106
|
+
RedactedOpenAiHeaders.OpenAiProject,
|
|
107
|
+
Redacted.value(options.projectId)
|
|
108
|
+
)
|
|
109
|
+
: identity,
|
|
110
|
+
HttpClientRequest.acceptJson
|
|
111
|
+
)),
|
|
112
|
+
options.transformClient
|
|
113
|
+
? options.transformClient
|
|
114
|
+
: identity
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
return Generated.make(httpClient, {
|
|
118
|
+
transformClient: Effect.fnUntraced(function*(client) {
|
|
119
|
+
const config = yield* OpenAiConfig.getOrUndefined
|
|
120
|
+
if (Predicate.isNotUndefined(config?.transformClient)) {
|
|
121
|
+
return config.transformClient(client)
|
|
122
|
+
}
|
|
123
|
+
return client
|
|
124
|
+
})
|
|
125
|
+
})
|
|
126
|
+
},
|
|
127
|
+
Effect.updateService(
|
|
128
|
+
Headers.CurrentRedactedNames,
|
|
129
|
+
Array.appendAll(Object.values(RedactedOpenAiHeaders))
|
|
130
|
+
)
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
// =============================================================================
|
|
134
|
+
// Layers
|
|
135
|
+
// =============================================================================
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Creates a layer for the generated OpenAI client with the given options.
|
|
139
|
+
*
|
|
140
|
+
* @since 4.0.0
|
|
141
|
+
* @category layers
|
|
142
|
+
*/
|
|
143
|
+
export const layer = (options: Options): Layer.Layer<OpenAiClientGenerated, never, HttpClient.HttpClient> =>
|
|
144
|
+
Layer.effect(OpenAiClientGenerated, make(options))
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Creates a layer for the generated OpenAI client, loading the requisite
|
|
148
|
+
* configuration via Effect's `Config` module.
|
|
149
|
+
*
|
|
150
|
+
* @since 4.0.0
|
|
151
|
+
* @category layers
|
|
152
|
+
*/
|
|
153
|
+
export const layerConfig = (options?: {
|
|
154
|
+
/**
|
|
155
|
+
* The config value to load for the API key.
|
|
156
|
+
*/
|
|
157
|
+
readonly apiKey?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* The config value to load for the API URL.
|
|
161
|
+
*/
|
|
162
|
+
readonly apiUrl?: Config.Config<string> | undefined
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The config value to load for the organization ID.
|
|
166
|
+
*/
|
|
167
|
+
readonly organizationId?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* The config value to load for the project ID.
|
|
171
|
+
*/
|
|
172
|
+
readonly projectId?: Config.Config<Redacted.Redacted<string> | undefined> | undefined
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Optional transformer for the HTTP client.
|
|
176
|
+
*/
|
|
177
|
+
readonly transformClient?: ((client: HttpClient.HttpClient) => HttpClient.HttpClient) | undefined
|
|
178
|
+
}): Layer.Layer<OpenAiClientGenerated, Config.ConfigError, HttpClient.HttpClient> =>
|
|
179
|
+
Layer.effect(
|
|
180
|
+
OpenAiClientGenerated,
|
|
181
|
+
Effect.gen(function*() {
|
|
182
|
+
const apiKey = Predicate.isNotUndefined(options?.apiKey)
|
|
183
|
+
? yield* options.apiKey :
|
|
184
|
+
undefined
|
|
185
|
+
const apiUrl = Predicate.isNotUndefined(options?.apiUrl)
|
|
186
|
+
? yield* options.apiUrl :
|
|
187
|
+
undefined
|
|
188
|
+
const organizationId = Predicate.isNotUndefined(options?.organizationId)
|
|
189
|
+
? yield* options.organizationId
|
|
190
|
+
: undefined
|
|
191
|
+
const projectId = Predicate.isNotUndefined(options?.projectId)
|
|
192
|
+
? yield* options.projectId :
|
|
193
|
+
undefined
|
|
194
|
+
return yield* make({
|
|
195
|
+
apiKey,
|
|
196
|
+
apiUrl,
|
|
197
|
+
organizationId,
|
|
198
|
+
projectId,
|
|
199
|
+
transformClient: options?.transformClient
|
|
200
|
+
})
|
|
201
|
+
})
|
|
202
|
+
)
|
package/src/OpenAiConfig.ts
CHANGED
|
@@ -1,35 +1,61 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The `OpenAiConfig` module provides contextual configuration for the
|
|
3
|
+
* `@effect/ai-openai` integration. It is used to customize how OpenAI clients
|
|
4
|
+
* are built and interpreted without threading configuration through every API
|
|
5
|
+
* call manually.
|
|
6
|
+
*
|
|
7
|
+
* The primary use case is installing an HTTP client transform with
|
|
8
|
+
* {@link withClientTransform}. This lets applications adapt the underlying
|
|
9
|
+
* OpenAI HTTP client for cross-cutting concerns such as custom middleware,
|
|
10
|
+
* instrumentation, proxying, or request policy changes while keeping the
|
|
11
|
+
* OpenAI service APIs unchanged.
|
|
12
|
+
*
|
|
13
|
+
* Configuration is scoped through Effect's context, so transforms only apply to
|
|
14
|
+
* the effect they are provided to and anything evaluated inside that scope.
|
|
15
|
+
* When multiple transforms are needed, compose them into a single
|
|
16
|
+
* `HttpClient => HttpClient` function before providing the configuration.
|
|
17
|
+
*
|
|
18
|
+
* @since 4.0.0
|
|
3
19
|
*/
|
|
20
|
+
import * as Context from "effect/Context"
|
|
4
21
|
import * as Effect from "effect/Effect"
|
|
5
22
|
import { dual } from "effect/Function"
|
|
6
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
7
23
|
import type { HttpClient } from "effect/unstable/http/HttpClient"
|
|
8
24
|
|
|
9
25
|
/**
|
|
10
|
-
*
|
|
26
|
+
* Context service carrying scoped OpenAI configuration for provider
|
|
27
|
+
* operations.
|
|
28
|
+
*
|
|
11
29
|
* @category services
|
|
30
|
+
* @since 4.0.0
|
|
12
31
|
*/
|
|
13
|
-
export class OpenAiConfig extends
|
|
32
|
+
export class OpenAiConfig extends Context.Service<
|
|
14
33
|
OpenAiConfig,
|
|
15
34
|
OpenAiConfig.Service
|
|
16
35
|
>()("@effect/ai-openai/OpenAiConfig") {
|
|
17
36
|
/**
|
|
18
|
-
*
|
|
37
|
+
* Gets the configured OpenAI service from the current context when present.
|
|
38
|
+
*
|
|
39
|
+
* @since 4.0.0
|
|
19
40
|
*/
|
|
20
41
|
static readonly getOrUndefined: Effect.Effect<typeof OpenAiConfig.Service | undefined> = Effect.map(
|
|
21
|
-
Effect.
|
|
42
|
+
Effect.context<never>(),
|
|
22
43
|
(context) => context.mapUnsafe.get(OpenAiConfig.key)
|
|
23
44
|
)
|
|
24
45
|
}
|
|
25
46
|
|
|
26
47
|
/**
|
|
27
|
-
*
|
|
48
|
+
* Types used by the `OpenAiConfig` context service.
|
|
49
|
+
*
|
|
50
|
+
* @since 4.0.0
|
|
28
51
|
*/
|
|
29
52
|
export declare namespace OpenAiConfig {
|
|
30
53
|
/**
|
|
31
|
-
*
|
|
54
|
+
* Configuration values read by OpenAI provider operations when executing
|
|
55
|
+
* requests.
|
|
56
|
+
*
|
|
32
57
|
* @category models
|
|
58
|
+
* @since 4.0.0
|
|
33
59
|
*/
|
|
34
60
|
export interface Service {
|
|
35
61
|
readonly transformClient?: ((client: HttpClient) => HttpClient) | undefined
|
|
@@ -37,18 +63,27 @@ export declare namespace OpenAiConfig {
|
|
|
37
63
|
}
|
|
38
64
|
|
|
39
65
|
/**
|
|
40
|
-
*
|
|
66
|
+
* Provides a scoped transform for the OpenAI HTTP client used by provider
|
|
67
|
+
* operations.
|
|
68
|
+
*
|
|
41
69
|
* @category configuration
|
|
70
|
+
* @since 4.0.0
|
|
42
71
|
*/
|
|
43
72
|
export const withClientTransform: {
|
|
44
73
|
/**
|
|
45
|
-
*
|
|
74
|
+
* Provides a scoped transform for the OpenAI HTTP client used by provider
|
|
75
|
+
* operations.
|
|
76
|
+
*
|
|
46
77
|
* @category configuration
|
|
78
|
+
* @since 4.0.0
|
|
47
79
|
*/
|
|
48
80
|
(transform: (client: HttpClient) => HttpClient): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, R>
|
|
49
81
|
/**
|
|
50
|
-
*
|
|
82
|
+
* Provides a scoped transform for the OpenAI HTTP client used by provider
|
|
83
|
+
* operations.
|
|
84
|
+
*
|
|
51
85
|
* @category configuration
|
|
86
|
+
* @since 4.0.0
|
|
52
87
|
*/
|
|
53
88
|
<A, E, R>(
|
|
54
89
|
self: Effect.Effect<A, E, R>,
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Embedding Model implementation.
|
|
3
|
+
*
|
|
4
|
+
* Provides an EmbeddingModel implementation for OpenAI's embeddings API.
|
|
5
|
+
*
|
|
6
|
+
* @since 4.0.0
|
|
7
|
+
*/
|
|
8
|
+
import * as Context from "effect/Context"
|
|
9
|
+
import * as Effect from "effect/Effect"
|
|
10
|
+
import { dual } from "effect/Function"
|
|
11
|
+
import * as Layer from "effect/Layer"
|
|
12
|
+
import type { Simplify } from "effect/Types"
|
|
13
|
+
import * as AiError from "effect/unstable/ai/AiError"
|
|
14
|
+
import * as EmbeddingModel from "effect/unstable/ai/EmbeddingModel"
|
|
15
|
+
import * as AiModel from "effect/unstable/ai/Model"
|
|
16
|
+
import { OpenAiClient } from "./OpenAiClient.ts"
|
|
17
|
+
import type * as OpenAiSchema from "./OpenAiSchema.ts"
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Model identifiers supported by OpenAI's embeddings API.
|
|
21
|
+
*
|
|
22
|
+
* @category models
|
|
23
|
+
* @since 4.0.0
|
|
24
|
+
*/
|
|
25
|
+
export type Model = "text-embedding-ada-002" | "text-embedding-3-small" | "text-embedding-3-large"
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Service definition for OpenAI embedding model configuration.
|
|
29
|
+
*
|
|
30
|
+
* @category services
|
|
31
|
+
* @since 4.0.0
|
|
32
|
+
*/
|
|
33
|
+
export class Config extends Context.Service<
|
|
34
|
+
Config,
|
|
35
|
+
Simplify<
|
|
36
|
+
& Partial<
|
|
37
|
+
Omit<
|
|
38
|
+
typeof OpenAiSchema.CreateEmbeddingRequest.Encoded,
|
|
39
|
+
"input"
|
|
40
|
+
>
|
|
41
|
+
>
|
|
42
|
+
& {
|
|
43
|
+
readonly [x: string]: unknown
|
|
44
|
+
}
|
|
45
|
+
>
|
|
46
|
+
>()("@effect/ai-openai/OpenAiEmbeddingModel/Config") {}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Creates an `AiModel` for an OpenAI embedding model with its configured vector dimensions.
|
|
50
|
+
*
|
|
51
|
+
* @category constructors
|
|
52
|
+
* @since 4.0.0
|
|
53
|
+
*/
|
|
54
|
+
export const model = (
|
|
55
|
+
model: (string & {}) | Model,
|
|
56
|
+
options: {
|
|
57
|
+
readonly dimensions: number
|
|
58
|
+
readonly config?: Omit<typeof Config.Service, "model" | "dimensions">
|
|
59
|
+
}
|
|
60
|
+
): AiModel.Model<"openai", EmbeddingModel.EmbeddingModel | EmbeddingModel.Dimensions, OpenAiClient> =>
|
|
61
|
+
AiModel.make(
|
|
62
|
+
"openai",
|
|
63
|
+
model,
|
|
64
|
+
Layer.merge(
|
|
65
|
+
layer({
|
|
66
|
+
model,
|
|
67
|
+
config: {
|
|
68
|
+
...options.config,
|
|
69
|
+
dimensions: options.dimensions
|
|
70
|
+
}
|
|
71
|
+
}),
|
|
72
|
+
Layer.succeed(EmbeddingModel.Dimensions, options.dimensions)
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Creates an OpenAI embedding model service.
|
|
78
|
+
*
|
|
79
|
+
* @category constructors
|
|
80
|
+
* @since 4.0.0
|
|
81
|
+
*/
|
|
82
|
+
export const make = Effect.fnUntraced(function*({ model, config: providerConfig }: {
|
|
83
|
+
readonly model: (string & {}) | Model
|
|
84
|
+
readonly config?: Omit<typeof Config.Service, "model"> | undefined
|
|
85
|
+
}): Effect.fn.Return<EmbeddingModel.Service, never, OpenAiClient> {
|
|
86
|
+
const client = yield* OpenAiClient
|
|
87
|
+
|
|
88
|
+
const makeConfig = Effect.gen(function*() {
|
|
89
|
+
const services = yield* Effect.context<never>()
|
|
90
|
+
return { model, ...providerConfig, ...services.mapUnsafe.get(Config.key) }
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
return yield* EmbeddingModel.make({
|
|
94
|
+
embedMany: Effect.fnUntraced(function*({ inputs }) {
|
|
95
|
+
const config = yield* makeConfig
|
|
96
|
+
const response = yield* client.createEmbedding({ ...config, input: inputs })
|
|
97
|
+
return yield* mapProviderResponse(inputs.length, response)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Creates a layer for the OpenAI embedding model.
|
|
104
|
+
*
|
|
105
|
+
* @category layers
|
|
106
|
+
* @since 4.0.0
|
|
107
|
+
*/
|
|
108
|
+
export const layer = (options: {
|
|
109
|
+
readonly model: (string & {}) | Model
|
|
110
|
+
readonly config?: Omit<typeof Config.Service, "model"> | undefined
|
|
111
|
+
}): Layer.Layer<EmbeddingModel.EmbeddingModel, never, OpenAiClient> =>
|
|
112
|
+
Layer.effect(EmbeddingModel.EmbeddingModel, make(options))
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Provides config overrides for OpenAI embedding model operations.
|
|
116
|
+
*
|
|
117
|
+
* @category configuration
|
|
118
|
+
* @since 4.0.0
|
|
119
|
+
*/
|
|
120
|
+
export const withConfigOverride: {
|
|
121
|
+
/**
|
|
122
|
+
* Provides config overrides for OpenAI embedding model operations.
|
|
123
|
+
*
|
|
124
|
+
* @category configuration
|
|
125
|
+
* @since 4.0.0
|
|
126
|
+
*/
|
|
127
|
+
(overrides: typeof Config.Service): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Config>>
|
|
128
|
+
/**
|
|
129
|
+
* Provides config overrides for OpenAI embedding model operations.
|
|
130
|
+
*
|
|
131
|
+
* @category configuration
|
|
132
|
+
* @since 4.0.0
|
|
133
|
+
*/
|
|
134
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, overrides: typeof Config.Service): Effect.Effect<A, E, Exclude<R, Config>>
|
|
135
|
+
} = dual<
|
|
136
|
+
/**
|
|
137
|
+
* Provides config overrides for OpenAI embedding model operations.
|
|
138
|
+
*
|
|
139
|
+
* @category configuration
|
|
140
|
+
* @since 4.0.0
|
|
141
|
+
*/
|
|
142
|
+
(overrides: typeof Config.Service) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Config>>,
|
|
143
|
+
/**
|
|
144
|
+
* Provides config overrides for OpenAI embedding model operations.
|
|
145
|
+
*
|
|
146
|
+
* @category configuration
|
|
147
|
+
* @since 4.0.0
|
|
148
|
+
*/
|
|
149
|
+
<A, E, R>(self: Effect.Effect<A, E, R>, overrides: typeof Config.Service) => Effect.Effect<A, E, Exclude<R, Config>>
|
|
150
|
+
>(2, (self, overrides) =>
|
|
151
|
+
Effect.flatMap(
|
|
152
|
+
Effect.serviceOption(Config),
|
|
153
|
+
(config) =>
|
|
154
|
+
Effect.provideService(self, Config, {
|
|
155
|
+
...(config._tag === "Some" ? config.value : {}),
|
|
156
|
+
...overrides
|
|
157
|
+
})
|
|
158
|
+
))
|
|
159
|
+
|
|
160
|
+
const mapProviderResponse = (
|
|
161
|
+
inputLength: number,
|
|
162
|
+
response: typeof OpenAiSchema.CreateEmbeddingResponse.Type
|
|
163
|
+
): Effect.Effect<EmbeddingModel.ProviderResponse, AiError.AiError> => {
|
|
164
|
+
if (response.data.length !== inputLength) {
|
|
165
|
+
return Effect.fail(
|
|
166
|
+
invalidOutput("Provider returned " + response.data.length + " embeddings but expected " + inputLength)
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const results = new Array<Array<number>>(inputLength)
|
|
171
|
+
const seen = new Set<number>()
|
|
172
|
+
|
|
173
|
+
for (const entry of response.data) {
|
|
174
|
+
if (!Number.isInteger(entry.index) || entry.index < 0 || entry.index >= inputLength) {
|
|
175
|
+
return Effect.fail(invalidOutput("Provider returned invalid embedding index: " + entry.index))
|
|
176
|
+
}
|
|
177
|
+
if (seen.has(entry.index)) {
|
|
178
|
+
return Effect.fail(invalidOutput("Provider returned duplicate embedding index: " + entry.index))
|
|
179
|
+
}
|
|
180
|
+
if (!Array.isArray(entry.embedding)) {
|
|
181
|
+
return Effect.fail(invalidOutput("Provider returned non-vector embedding at index " + entry.index))
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
seen.add(entry.index)
|
|
185
|
+
results[entry.index] = [...entry.embedding]
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (seen.size !== inputLength) {
|
|
189
|
+
return Effect.fail(
|
|
190
|
+
invalidOutput("Provider returned embeddings for " + seen.size + " inputs but expected " + inputLength)
|
|
191
|
+
)
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return Effect.succeed({
|
|
195
|
+
results,
|
|
196
|
+
usage: {
|
|
197
|
+
inputTokens: response.usage?.prompt_tokens
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const invalidOutput = (description: string): AiError.AiError =>
|
|
203
|
+
AiError.make({
|
|
204
|
+
module: "OpenAiEmbeddingModel",
|
|
205
|
+
method: "embedMany",
|
|
206
|
+
reason: new AiError.InvalidOutputError({ description })
|
|
207
|
+
})
|