@effect/ai-openai-compat 4.0.0-beta.7 → 4.0.0-beta.71
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/OpenAiClient.d.ts +250 -51
- package/dist/OpenAiClient.d.ts.map +1 -1
- package/dist/OpenAiClient.js +108 -9
- package/dist/OpenAiClient.js.map +1 -1
- package/dist/OpenAiConfig.d.ts +83 -10
- package/dist/OpenAiConfig.d.ts.map +1 -1
- package/dist/OpenAiConfig.js +51 -7
- package/dist/OpenAiConfig.js.map +1 -1
- package/dist/OpenAiEmbeddingModel.d.ts +214 -0
- package/dist/OpenAiEmbeddingModel.d.ts.map +1 -0
- package/dist/OpenAiEmbeddingModel.js +218 -0
- package/dist/OpenAiEmbeddingModel.js.map +1 -0
- package/dist/OpenAiError.d.ts +109 -35
- package/dist/OpenAiError.d.ts.map +1 -1
- package/dist/OpenAiError.js +14 -1
- package/dist/OpenAiLanguageModel.d.ts +326 -18
- package/dist/OpenAiLanguageModel.d.ts.map +1 -1
- package/dist/OpenAiLanguageModel.js +126 -25
- package/dist/OpenAiLanguageModel.js.map +1 -1
- package/dist/OpenAiTelemetry.d.ts +72 -22
- package/dist/OpenAiTelemetry.d.ts.map +1 -1
- package/dist/OpenAiTelemetry.js +47 -8
- package/dist/OpenAiTelemetry.js.map +1 -1
- package/dist/index.d.ts +10 -17
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -17
- 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/OpenAiClient.ts +283 -49
- package/src/OpenAiConfig.ts +84 -11
- package/src/OpenAiEmbeddingModel.ts +360 -0
- package/src/OpenAiError.ts +111 -35
- package/src/OpenAiLanguageModel.ts +409 -40
- package/src/OpenAiTelemetry.ts +103 -27
- package/src/index.ts +11 -17
- package/src/internal/errors.ts +4 -4
|
@@ -1,21 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* The `OpenAiLanguageModel` module adapts OpenAI-compatible chat-completions
|
|
3
|
+
* providers to the shared Effect AI `LanguageModel` interface. It translates
|
|
4
|
+
* provider-neutral prompts, tools, structured output schemas, and streaming
|
|
5
|
+
* responses into the request and response shapes used by `OpenAiClient`.
|
|
3
6
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
7
|
+
* Use this module when an application wants to talk to OpenAI-compatible
|
|
8
|
+
* endpoints through Effect AI abstractions rather than constructing provider
|
|
9
|
+
* payloads directly. The exported constructors build a language model service
|
|
10
|
+
* from a model id, while `Config` and {@link withConfigOverride} provide scoped
|
|
11
|
+
* defaults for request fields such as temperature, reasoning options, text
|
|
12
|
+
* format, and provider-specific file handling.
|
|
6
13
|
*
|
|
7
|
-
*
|
|
14
|
+
* **Common tasks**
|
|
15
|
+
*
|
|
16
|
+
* - Create a model descriptor with {@link model}
|
|
17
|
+
* - Build or provide the `LanguageModel` service with {@link make} or
|
|
18
|
+
* {@link layer}
|
|
19
|
+
* - Scope request defaults with {@link Config} and {@link withConfigOverride}
|
|
20
|
+
* - Send tool calls, structured output schemas, images, files, and reasoning
|
|
21
|
+
* metadata through the provider-neutral Effect AI prompt types
|
|
22
|
+
*
|
|
23
|
+
* **Gotchas**
|
|
24
|
+
*
|
|
25
|
+
* - The module requires an `OpenAiClient` service; configure authentication,
|
|
26
|
+
* base URL, and HTTP behavior through that client layer.
|
|
27
|
+
* - Compatibility depends on the provider supporting the OpenAI request fields
|
|
28
|
+
* being used. Optional capabilities such as strict JSON schemas, reasoning
|
|
29
|
+
* metadata, and tool status fields may vary across providers.
|
|
30
|
+
* - `fileIdPrefixes` tells the prompt conversion which file references are
|
|
31
|
+
* provider file IDs instead of base64 file contents.
|
|
32
|
+
*
|
|
33
|
+
* @since 4.0.0
|
|
8
34
|
*/
|
|
35
|
+
import * as Context from "effect/Context"
|
|
9
36
|
import * as DateTime from "effect/DateTime"
|
|
10
37
|
import * as Effect from "effect/Effect"
|
|
11
38
|
import * as Encoding from "effect/Encoding"
|
|
12
39
|
import { dual } from "effect/Function"
|
|
13
40
|
import * as Layer from "effect/Layer"
|
|
41
|
+
import * as Option from "effect/Option"
|
|
14
42
|
import * as Predicate from "effect/Predicate"
|
|
15
43
|
import * as Redactable from "effect/Redactable"
|
|
16
44
|
import type * as Schema from "effect/Schema"
|
|
17
45
|
import * as AST from "effect/SchemaAST"
|
|
18
|
-
import * as ServiceMap from "effect/ServiceMap"
|
|
19
46
|
import * as Stream from "effect/Stream"
|
|
20
47
|
import type { Span } from "effect/Tracer"
|
|
21
48
|
import type { DeepMutable, Simplify } from "effect/Types"
|
|
@@ -60,10 +87,18 @@ type ImageDetail = "auto" | "low" | "high"
|
|
|
60
87
|
/**
|
|
61
88
|
* Service definition for OpenAI language model configuration.
|
|
62
89
|
*
|
|
63
|
-
*
|
|
90
|
+
* **When to use**
|
|
91
|
+
*
|
|
92
|
+
* Use as the context service for OpenAI-compatible language model request
|
|
93
|
+
* configuration, especially when a scoped operation should override the defaults
|
|
94
|
+
* supplied to `model`, `make`, or `layer`.
|
|
95
|
+
*
|
|
96
|
+
* @see {@link withConfigOverride} for scoping language model request overrides
|
|
97
|
+
*
|
|
64
98
|
* @category context
|
|
99
|
+
* @since 4.0.0
|
|
65
100
|
*/
|
|
66
|
-
export class Config extends
|
|
101
|
+
export class Config extends Context.Service<
|
|
67
102
|
Config,
|
|
68
103
|
Simplify<
|
|
69
104
|
& Partial<
|
|
@@ -101,6 +136,7 @@ export class Config extends ServiceMap.Service<
|
|
|
101
136
|
* Defaults to `true`.
|
|
102
137
|
*/
|
|
103
138
|
readonly strictJsonSchema?: boolean | undefined
|
|
139
|
+
readonly [x: string]: unknown
|
|
104
140
|
}
|
|
105
141
|
>
|
|
106
142
|
>()("@effect/ai-openai-compat/OpenAiLanguageModel/Config") {}
|
|
@@ -110,7 +146,16 @@ export class Config extends ServiceMap.Service<
|
|
|
110
146
|
// =============================================================================
|
|
111
147
|
|
|
112
148
|
declare module "effect/unstable/ai/Prompt" {
|
|
149
|
+
/**
|
|
150
|
+
* OpenAI-compatible options for file prompt parts.
|
|
151
|
+
*
|
|
152
|
+
* @category request
|
|
153
|
+
* @since 4.0.0
|
|
154
|
+
*/
|
|
113
155
|
export interface FilePartOptions extends ProviderOptions {
|
|
156
|
+
/**
|
|
157
|
+
* Provider-specific file options for OpenAI-compatible APIs.
|
|
158
|
+
*/
|
|
114
159
|
readonly openai?: {
|
|
115
160
|
/**
|
|
116
161
|
* The detail level of the image to be sent to the model. One of `high`, `low`, or `auto`. Defaults to `auto`.
|
|
@@ -119,7 +164,16 @@ declare module "effect/unstable/ai/Prompt" {
|
|
|
119
164
|
} | null
|
|
120
165
|
}
|
|
121
166
|
|
|
167
|
+
/**
|
|
168
|
+
* OpenAI-compatible options for reasoning prompt parts.
|
|
169
|
+
*
|
|
170
|
+
* @category request
|
|
171
|
+
* @since 4.0.0
|
|
172
|
+
*/
|
|
122
173
|
export interface ReasoningPartOptions extends ProviderOptions {
|
|
174
|
+
/**
|
|
175
|
+
* Provider-specific reasoning options for OpenAI-compatible APIs.
|
|
176
|
+
*/
|
|
123
177
|
readonly openai?: {
|
|
124
178
|
/**
|
|
125
179
|
* The ID of the item to reference.
|
|
@@ -134,40 +188,67 @@ declare module "effect/unstable/ai/Prompt" {
|
|
|
134
188
|
} | null
|
|
135
189
|
}
|
|
136
190
|
|
|
191
|
+
/**
|
|
192
|
+
* OpenAI-compatible options for assistant tool-call prompt parts.
|
|
193
|
+
*
|
|
194
|
+
* @category request
|
|
195
|
+
* @since 4.0.0
|
|
196
|
+
*/
|
|
137
197
|
export interface ToolCallPartOptions extends ProviderOptions {
|
|
198
|
+
/**
|
|
199
|
+
* Provider-specific tool-call options for OpenAI-compatible APIs.
|
|
200
|
+
*/
|
|
138
201
|
readonly openai?: {
|
|
139
202
|
/**
|
|
140
203
|
* The ID of the item to reference.
|
|
141
204
|
*/
|
|
142
205
|
readonly itemId?: string | null
|
|
143
206
|
/**
|
|
144
|
-
* The status
|
|
207
|
+
* The status to send for the tool-call item.
|
|
145
208
|
*/
|
|
146
209
|
readonly status?: MessageStatus | null
|
|
147
210
|
} | null
|
|
148
211
|
}
|
|
149
212
|
|
|
213
|
+
/**
|
|
214
|
+
* OpenAI-compatible options for tool-result prompt parts.
|
|
215
|
+
*
|
|
216
|
+
* @category request
|
|
217
|
+
* @since 4.0.0
|
|
218
|
+
*/
|
|
150
219
|
export interface ToolResultPartOptions extends ProviderOptions {
|
|
220
|
+
/**
|
|
221
|
+
* Provider-specific tool-result options for OpenAI-compatible APIs.
|
|
222
|
+
*/
|
|
151
223
|
readonly openai?: {
|
|
152
224
|
/**
|
|
153
225
|
* The ID of the item to reference.
|
|
154
226
|
*/
|
|
155
227
|
readonly itemId?: string | null
|
|
156
228
|
/**
|
|
157
|
-
* The status
|
|
229
|
+
* The status to send for the tool-result item.
|
|
158
230
|
*/
|
|
159
231
|
readonly status?: MessageStatus | null
|
|
160
232
|
} | null
|
|
161
233
|
}
|
|
162
234
|
|
|
235
|
+
/**
|
|
236
|
+
* OpenAI-compatible options for text prompt parts.
|
|
237
|
+
*
|
|
238
|
+
* @category request
|
|
239
|
+
* @since 4.0.0
|
|
240
|
+
*/
|
|
163
241
|
export interface TextPartOptions extends ProviderOptions {
|
|
242
|
+
/**
|
|
243
|
+
* Provider-specific text options for OpenAI-compatible APIs.
|
|
244
|
+
*/
|
|
164
245
|
readonly openai?: {
|
|
165
246
|
/**
|
|
166
247
|
* The ID of the item to reference.
|
|
167
248
|
*/
|
|
168
249
|
readonly itemId?: string | null
|
|
169
250
|
/**
|
|
170
|
-
* The status
|
|
251
|
+
* The status to send for the text item.
|
|
171
252
|
*/
|
|
172
253
|
readonly status?: MessageStatus | null
|
|
173
254
|
/**
|
|
@@ -179,8 +260,20 @@ declare module "effect/unstable/ai/Prompt" {
|
|
|
179
260
|
}
|
|
180
261
|
|
|
181
262
|
declare module "effect/unstable/ai/Response" {
|
|
263
|
+
/**
|
|
264
|
+
* OpenAI-compatible metadata attached to a complete text response part.
|
|
265
|
+
*
|
|
266
|
+
* @category response
|
|
267
|
+
* @since 4.0.0
|
|
268
|
+
*/
|
|
182
269
|
export interface TextPartMetadata extends ProviderMetadata {
|
|
270
|
+
/**
|
|
271
|
+
* Provider-specific metadata returned for the text part.
|
|
272
|
+
*/
|
|
183
273
|
readonly openai?: {
|
|
274
|
+
/**
|
|
275
|
+
* The OpenAI item ID associated with the text part.
|
|
276
|
+
*/
|
|
184
277
|
readonly itemId?: string | null
|
|
185
278
|
/**
|
|
186
279
|
* If the model emits a refusal content part, the refusal explanation
|
|
@@ -189,7 +282,7 @@ declare module "effect/unstable/ai/Response" {
|
|
|
189
282
|
*/
|
|
190
283
|
readonly refusal?: string | null
|
|
191
284
|
/**
|
|
192
|
-
* The status
|
|
285
|
+
* The status returned for the text item.
|
|
193
286
|
*/
|
|
194
287
|
readonly status?: MessageStatus | null
|
|
195
288
|
/**
|
|
@@ -199,55 +292,163 @@ declare module "effect/unstable/ai/Response" {
|
|
|
199
292
|
}
|
|
200
293
|
}
|
|
201
294
|
|
|
295
|
+
/**
|
|
296
|
+
* OpenAI-compatible metadata emitted when a streamed text part starts.
|
|
297
|
+
*
|
|
298
|
+
* @category response
|
|
299
|
+
* @since 4.0.0
|
|
300
|
+
*/
|
|
202
301
|
export interface TextStartPartMetadata extends ProviderMetadata {
|
|
302
|
+
/**
|
|
303
|
+
* Provider-specific metadata returned for the streamed text start.
|
|
304
|
+
*/
|
|
203
305
|
readonly openai?: {
|
|
306
|
+
/**
|
|
307
|
+
* The OpenAI item ID associated with the streamed text part.
|
|
308
|
+
*/
|
|
204
309
|
readonly itemId?: string | null
|
|
205
310
|
} | null
|
|
206
311
|
}
|
|
207
312
|
|
|
313
|
+
/**
|
|
314
|
+
* OpenAI-compatible metadata emitted when a streamed text part ends.
|
|
315
|
+
*
|
|
316
|
+
* @category response
|
|
317
|
+
* @since 4.0.0
|
|
318
|
+
*/
|
|
208
319
|
export interface TextEndPartMetadata extends ProviderMetadata {
|
|
320
|
+
/**
|
|
321
|
+
* Provider-specific metadata returned for the streamed text end.
|
|
322
|
+
*/
|
|
209
323
|
readonly openai?: {
|
|
324
|
+
/**
|
|
325
|
+
* The OpenAI item ID associated with the streamed text part.
|
|
326
|
+
*/
|
|
210
327
|
readonly itemId?: string | null
|
|
328
|
+
/**
|
|
329
|
+
* The annotations collected for the completed streamed text part.
|
|
330
|
+
*/
|
|
211
331
|
readonly annotations?: ReadonlyArray<Annotation> | null
|
|
212
332
|
} | null
|
|
213
333
|
}
|
|
214
334
|
|
|
335
|
+
/**
|
|
336
|
+
* OpenAI-compatible metadata attached to a complete reasoning response part.
|
|
337
|
+
*
|
|
338
|
+
* @category response
|
|
339
|
+
* @since 4.0.0
|
|
340
|
+
*/
|
|
215
341
|
export interface ReasoningPartMetadata extends ProviderMetadata {
|
|
342
|
+
/**
|
|
343
|
+
* Provider-specific metadata returned for the reasoning part.
|
|
344
|
+
*/
|
|
216
345
|
readonly openai?: {
|
|
346
|
+
/**
|
|
347
|
+
* The OpenAI item ID associated with the reasoning part.
|
|
348
|
+
*/
|
|
217
349
|
readonly itemId?: string | null
|
|
350
|
+
/**
|
|
351
|
+
* Encrypted reasoning content that can be sent back in later requests.
|
|
352
|
+
*/
|
|
218
353
|
readonly encryptedContent?: string | null
|
|
219
354
|
} | null
|
|
220
355
|
}
|
|
221
356
|
|
|
357
|
+
/**
|
|
358
|
+
* OpenAI-compatible metadata emitted when a streamed reasoning part starts.
|
|
359
|
+
*
|
|
360
|
+
* @category response
|
|
361
|
+
* @since 4.0.0
|
|
362
|
+
*/
|
|
222
363
|
export interface ReasoningStartPartMetadata extends ProviderMetadata {
|
|
364
|
+
/**
|
|
365
|
+
* Provider-specific metadata returned for the streamed reasoning start.
|
|
366
|
+
*/
|
|
223
367
|
readonly openai?: {
|
|
368
|
+
/**
|
|
369
|
+
* The OpenAI item ID associated with the reasoning part.
|
|
370
|
+
*/
|
|
224
371
|
readonly itemId?: string | null
|
|
372
|
+
/**
|
|
373
|
+
* Encrypted reasoning content that can be sent back in later requests.
|
|
374
|
+
*/
|
|
225
375
|
readonly encryptedContent?: string | null
|
|
226
376
|
} | null
|
|
227
377
|
}
|
|
228
378
|
|
|
379
|
+
/**
|
|
380
|
+
* OpenAI-compatible metadata emitted for a streamed reasoning delta.
|
|
381
|
+
*
|
|
382
|
+
* @category response
|
|
383
|
+
* @since 4.0.0
|
|
384
|
+
*/
|
|
229
385
|
export interface ReasoningDeltaPartMetadata extends ProviderMetadata {
|
|
386
|
+
/**
|
|
387
|
+
* Provider-specific metadata returned for the streamed reasoning delta.
|
|
388
|
+
*/
|
|
230
389
|
readonly openai?: {
|
|
390
|
+
/**
|
|
391
|
+
* The OpenAI item ID associated with the reasoning part.
|
|
392
|
+
*/
|
|
231
393
|
readonly itemId?: string | null
|
|
232
394
|
} | null
|
|
233
395
|
}
|
|
234
396
|
|
|
397
|
+
/**
|
|
398
|
+
* OpenAI-compatible metadata emitted when a streamed reasoning part ends.
|
|
399
|
+
*
|
|
400
|
+
* @category response
|
|
401
|
+
* @since 4.0.0
|
|
402
|
+
*/
|
|
235
403
|
export interface ReasoningEndPartMetadata extends ProviderMetadata {
|
|
404
|
+
/**
|
|
405
|
+
* Provider-specific metadata returned for the streamed reasoning end.
|
|
406
|
+
*/
|
|
236
407
|
readonly openai?: {
|
|
408
|
+
/**
|
|
409
|
+
* The OpenAI item ID associated with the reasoning part.
|
|
410
|
+
*/
|
|
237
411
|
readonly itemId?: string | null
|
|
412
|
+
/**
|
|
413
|
+
* Encrypted reasoning content that can be sent back in later requests.
|
|
414
|
+
*/
|
|
238
415
|
readonly encryptedContent?: string
|
|
239
416
|
} | null
|
|
240
417
|
}
|
|
241
418
|
|
|
419
|
+
/**
|
|
420
|
+
* OpenAI-compatible metadata attached to tool-call response parts.
|
|
421
|
+
*
|
|
422
|
+
* @category response
|
|
423
|
+
* @since 4.0.0
|
|
424
|
+
*/
|
|
242
425
|
export interface ToolCallPartMetadata extends ProviderMetadata {
|
|
426
|
+
/**
|
|
427
|
+
* Provider-specific metadata returned for the tool call.
|
|
428
|
+
*/
|
|
243
429
|
readonly openai?: {
|
|
430
|
+
/**
|
|
431
|
+
* The OpenAI item ID associated with the tool call.
|
|
432
|
+
*/
|
|
244
433
|
readonly itemId?: string | null
|
|
245
434
|
} | null
|
|
246
435
|
}
|
|
247
436
|
|
|
437
|
+
/**
|
|
438
|
+
* OpenAI-compatible metadata attached to document source citations.
|
|
439
|
+
*
|
|
440
|
+
* @category response
|
|
441
|
+
* @since 4.0.0
|
|
442
|
+
*/
|
|
248
443
|
export interface DocumentSourcePartMetadata extends ProviderMetadata {
|
|
444
|
+
/**
|
|
445
|
+
* Provider-specific citation metadata for OpenAI-compatible APIs.
|
|
446
|
+
*/
|
|
249
447
|
readonly openai?:
|
|
250
448
|
| {
|
|
449
|
+
/**
|
|
450
|
+
* Identifies a citation to an uploaded file.
|
|
451
|
+
*/
|
|
251
452
|
readonly type: "file_citation"
|
|
252
453
|
/**
|
|
253
454
|
* The index of the file in the list of files.
|
|
@@ -259,6 +460,9 @@ declare module "effect/unstable/ai/Response" {
|
|
|
259
460
|
readonly fileId: string
|
|
260
461
|
}
|
|
261
462
|
| {
|
|
463
|
+
/**
|
|
464
|
+
* Identifies a citation to a generated file path.
|
|
465
|
+
*/
|
|
262
466
|
readonly type: "file_path"
|
|
263
467
|
/**
|
|
264
468
|
* The index of the file in the list of files.
|
|
@@ -270,6 +474,9 @@ declare module "effect/unstable/ai/Response" {
|
|
|
270
474
|
readonly fileId: string
|
|
271
475
|
}
|
|
272
476
|
| {
|
|
477
|
+
/**
|
|
478
|
+
* Identifies a citation to a file inside a container.
|
|
479
|
+
*/
|
|
273
480
|
readonly type: "container_file_citation"
|
|
274
481
|
/**
|
|
275
482
|
* The ID of the file.
|
|
@@ -283,8 +490,20 @@ declare module "effect/unstable/ai/Response" {
|
|
|
283
490
|
| null
|
|
284
491
|
}
|
|
285
492
|
|
|
493
|
+
/**
|
|
494
|
+
* OpenAI-compatible metadata attached to URL source citations.
|
|
495
|
+
*
|
|
496
|
+
* @category response
|
|
497
|
+
* @since 4.0.0
|
|
498
|
+
*/
|
|
286
499
|
export interface UrlSourcePartMetadata extends ProviderMetadata {
|
|
500
|
+
/**
|
|
501
|
+
* Provider-specific URL citation metadata for OpenAI-compatible APIs.
|
|
502
|
+
*/
|
|
287
503
|
readonly openai?: {
|
|
504
|
+
/**
|
|
505
|
+
* Identifies a citation to a URL.
|
|
506
|
+
*/
|
|
288
507
|
readonly type: "url_citation"
|
|
289
508
|
/**
|
|
290
509
|
* The index of the first character of the URL citation in the message.
|
|
@@ -297,8 +516,20 @@ declare module "effect/unstable/ai/Response" {
|
|
|
297
516
|
} | null
|
|
298
517
|
}
|
|
299
518
|
|
|
519
|
+
/**
|
|
520
|
+
* OpenAI-compatible metadata attached to finish response parts.
|
|
521
|
+
*
|
|
522
|
+
* @category response
|
|
523
|
+
* @since 4.0.0
|
|
524
|
+
*/
|
|
300
525
|
export interface FinishPartMetadata extends ProviderMetadata {
|
|
526
|
+
/**
|
|
527
|
+
* Provider-specific metadata returned when generation finishes.
|
|
528
|
+
*/
|
|
301
529
|
readonly openai?: {
|
|
530
|
+
/**
|
|
531
|
+
* The service tier reported by the OpenAI-compatible provider.
|
|
532
|
+
*/
|
|
302
533
|
readonly serviceTier?: "default" | "auto" | "flex" | "scale" | "priority" | null
|
|
303
534
|
} | null
|
|
304
535
|
}
|
|
@@ -309,31 +540,56 @@ declare module "effect/unstable/ai/Response" {
|
|
|
309
540
|
// =============================================================================
|
|
310
541
|
|
|
311
542
|
/**
|
|
312
|
-
*
|
|
543
|
+
* Creates an OpenAI-compatible model descriptor that can be provided with `Effect.provide`.
|
|
544
|
+
*
|
|
545
|
+
* **When to use**
|
|
546
|
+
*
|
|
547
|
+
* Use when you want an OpenAI-compatible language model value that carries
|
|
548
|
+
* provider and model metadata and can be supplied directly to an Effect program.
|
|
549
|
+
*
|
|
550
|
+
* @see {@link layer} for creating a `LanguageModel.LanguageModel` layer directly
|
|
551
|
+
* @see {@link make} for constructing the language model service effectfully
|
|
552
|
+
*
|
|
313
553
|
* @category constructors
|
|
554
|
+
* @since 4.0.0
|
|
314
555
|
*/
|
|
315
556
|
export const model = (
|
|
316
557
|
model: string,
|
|
317
558
|
config?: Omit<typeof Config.Service, "model">
|
|
318
559
|
): AiModel.Model<"openai", LanguageModel.LanguageModel, OpenAiClient> =>
|
|
319
|
-
AiModel.make("openai", layer({ model, config }))
|
|
560
|
+
AiModel.make("openai", model, layer({ model, config }))
|
|
320
561
|
|
|
321
562
|
// TODO
|
|
322
563
|
// /**
|
|
323
|
-
// * @since
|
|
564
|
+
// * @since 4.0.0
|
|
324
565
|
// * @category constructors
|
|
325
566
|
// */
|
|
326
567
|
// export const modelWithTokenizer = (
|
|
327
568
|
// model: string,
|
|
328
569
|
// config?: Omit<typeof Config.Service, "model">
|
|
329
570
|
// ): AiModel.Model<"openai", LanguageModel.LanguageModel | Tokenizer.Tokenizer, OpenAiClient> =>
|
|
330
|
-
// AiModel.make("openai", layerWithTokenizer({ model, config }))
|
|
571
|
+
// AiModel.make("openai", model, layerWithTokenizer({ model, config }))
|
|
331
572
|
|
|
332
573
|
/**
|
|
333
|
-
* Creates an OpenAI
|
|
574
|
+
* Creates an OpenAI-compatible `LanguageModel` service from a model identifier and optional request defaults.
|
|
575
|
+
*
|
|
576
|
+
* **When to use**
|
|
577
|
+
*
|
|
578
|
+
* Use when an Effect needs to construct a `LanguageModel.Service` value backed
|
|
579
|
+
* by `OpenAiClient`.
|
|
580
|
+
*
|
|
581
|
+
* **Details**
|
|
582
|
+
*
|
|
583
|
+
* The returned effect requires `OpenAiClient`. Request defaults from the
|
|
584
|
+
* `config` option are merged with any `Config` service in the context, with
|
|
585
|
+
* context values taking precedence. The service supports both `generateText` and
|
|
586
|
+
* `streamText`.
|
|
587
|
+
*
|
|
588
|
+
* @see {@link layer} for providing the service as a `Layer`
|
|
589
|
+
* @see {@link model} for creating a model descriptor for `AiModel.provide`
|
|
334
590
|
*
|
|
335
|
-
* @since 1.0.0
|
|
336
591
|
* @category constructors
|
|
592
|
+
* @since 4.0.0
|
|
337
593
|
*/
|
|
338
594
|
export const make = Effect.fnUntraced(function*({ model, config: providerConfig }: {
|
|
339
595
|
readonly model: string
|
|
@@ -342,7 +598,7 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig
|
|
|
342
598
|
const client = yield* OpenAiClient
|
|
343
599
|
|
|
344
600
|
const makeConfig = Effect.gen(function*() {
|
|
345
|
-
const services = yield* Effect.
|
|
601
|
+
const services = yield* Effect.context<never>()
|
|
346
602
|
return { model, ...providerConfig, ...services.mapUnsafe.get(Config.key) }
|
|
347
603
|
})
|
|
348
604
|
|
|
@@ -370,8 +626,9 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig
|
|
|
370
626
|
config,
|
|
371
627
|
options
|
|
372
628
|
})
|
|
629
|
+
const { fileIdPrefixes: _fip, strictJsonSchema: _sjs, ...apiConfig } = config
|
|
373
630
|
const request: CreateResponse = {
|
|
374
|
-
...
|
|
631
|
+
...apiConfig,
|
|
375
632
|
input: messages,
|
|
376
633
|
include: include.size > 0 ? Array.from(include) : null,
|
|
377
634
|
text: {
|
|
@@ -386,6 +643,7 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig
|
|
|
386
643
|
)
|
|
387
644
|
|
|
388
645
|
return yield* LanguageModel.make({
|
|
646
|
+
codecTransformer: toCodecOpenAI,
|
|
389
647
|
generateText: Effect.fnUntraced(
|
|
390
648
|
function*(options) {
|
|
391
649
|
const config = yield* makeConfig
|
|
@@ -423,17 +681,23 @@ export const make = Effect.fnUntraced(function*({ model, config: providerConfig
|
|
|
423
681
|
})
|
|
424
682
|
)
|
|
425
683
|
)
|
|
426
|
-
})
|
|
427
|
-
LanguageModel.CurrentCodecTransformer,
|
|
428
|
-
toCodecOpenAI
|
|
429
|
-
))
|
|
684
|
+
})
|
|
430
685
|
})
|
|
431
686
|
|
|
432
687
|
/**
|
|
433
|
-
* Creates a layer for the OpenAI language model.
|
|
688
|
+
* Creates a layer for the OpenAI-compatible language model.
|
|
689
|
+
*
|
|
690
|
+
* **When to use**
|
|
691
|
+
*
|
|
692
|
+
* Use when composing application layers and you want OpenAI-compatible APIs to
|
|
693
|
+
* satisfy `LanguageModel.LanguageModel` while supplying `OpenAiClient` from
|
|
694
|
+
* another layer.
|
|
695
|
+
*
|
|
696
|
+
* @see {@link make} for constructing the language model service effectfully
|
|
697
|
+
* @see {@link model} for creating an AI model descriptor
|
|
434
698
|
*
|
|
435
|
-
* @since 1.0.0
|
|
436
699
|
* @category layers
|
|
700
|
+
* @since 4.0.0
|
|
437
701
|
*/
|
|
438
702
|
export const layer = (options: {
|
|
439
703
|
readonly model: string
|
|
@@ -442,39 +706,99 @@ export const layer = (options: {
|
|
|
442
706
|
Layer.effect(LanguageModel.LanguageModel, make(options))
|
|
443
707
|
|
|
444
708
|
/**
|
|
445
|
-
* Provides config overrides for OpenAI language model operations.
|
|
709
|
+
* Provides scoped config overrides for OpenAI-compatible language model operations.
|
|
710
|
+
*
|
|
711
|
+
* **When to use**
|
|
712
|
+
*
|
|
713
|
+
* Use to override request configuration for a single language model effect
|
|
714
|
+
* without changing the defaults supplied to `model`, `make`, or `layer`.
|
|
715
|
+
*
|
|
716
|
+
* **Details**
|
|
717
|
+
*
|
|
718
|
+
* Existing `Config` values from the Effect context are merged with `overrides`,
|
|
719
|
+
* and the override values take precedence.
|
|
720
|
+
*
|
|
721
|
+
* @see {@link Config} for the configuration shape
|
|
446
722
|
*
|
|
447
|
-
* @since 1.0.0
|
|
448
723
|
* @category configuration
|
|
724
|
+
* @since 4.0.0
|
|
449
725
|
*/
|
|
450
726
|
export const withConfigOverride: {
|
|
451
727
|
/**
|
|
452
|
-
* Provides config overrides for OpenAI language model operations.
|
|
728
|
+
* Provides scoped config overrides for OpenAI-compatible language model operations.
|
|
729
|
+
*
|
|
730
|
+
* **When to use**
|
|
731
|
+
*
|
|
732
|
+
* Use to override request configuration for a single language model effect
|
|
733
|
+
* without changing the defaults supplied to `model`, `make`, or `layer`.
|
|
734
|
+
*
|
|
735
|
+
* **Details**
|
|
736
|
+
*
|
|
737
|
+
* Existing `Config` values from the Effect context are merged with `overrides`,
|
|
738
|
+
* and the override values take precedence.
|
|
739
|
+
*
|
|
740
|
+
* @see {@link Config} for the configuration shape
|
|
453
741
|
*
|
|
454
|
-
* @since 1.0.0
|
|
455
742
|
* @category configuration
|
|
743
|
+
* @since 4.0.0
|
|
456
744
|
*/
|
|
457
745
|
(overrides: typeof Config.Service): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Config>>
|
|
458
746
|
/**
|
|
459
|
-
* Provides config overrides for OpenAI language model operations.
|
|
747
|
+
* Provides scoped config overrides for OpenAI-compatible language model operations.
|
|
748
|
+
*
|
|
749
|
+
* **When to use**
|
|
750
|
+
*
|
|
751
|
+
* Use to override request configuration for a single language model effect
|
|
752
|
+
* without changing the defaults supplied to `model`, `make`, or `layer`.
|
|
753
|
+
*
|
|
754
|
+
* **Details**
|
|
755
|
+
*
|
|
756
|
+
* Existing `Config` values from the Effect context are merged with `overrides`,
|
|
757
|
+
* and the override values take precedence.
|
|
758
|
+
*
|
|
759
|
+
* @see {@link Config} for the configuration shape
|
|
460
760
|
*
|
|
461
|
-
* @since 1.0.0
|
|
462
761
|
* @category configuration
|
|
762
|
+
* @since 4.0.0
|
|
463
763
|
*/
|
|
464
764
|
<A, E, R>(self: Effect.Effect<A, E, R>, overrides: typeof Config.Service): Effect.Effect<A, E, Exclude<R, Config>>
|
|
465
765
|
} = dual<
|
|
466
766
|
/**
|
|
467
|
-
* Provides config overrides for OpenAI language model operations.
|
|
767
|
+
* Provides scoped config overrides for OpenAI-compatible language model operations.
|
|
768
|
+
*
|
|
769
|
+
* **When to use**
|
|
770
|
+
*
|
|
771
|
+
* Use to override request configuration for a single language model effect
|
|
772
|
+
* without changing the defaults supplied to `model`, `make`, or `layer`.
|
|
773
|
+
*
|
|
774
|
+
* **Details**
|
|
775
|
+
*
|
|
776
|
+
* Existing `Config` values from the Effect context are merged with `overrides`,
|
|
777
|
+
* and the override values take precedence.
|
|
778
|
+
*
|
|
779
|
+
* @see {@link Config} for the configuration shape
|
|
468
780
|
*
|
|
469
|
-
* @since 1.0.0
|
|
470
781
|
* @category configuration
|
|
782
|
+
* @since 4.0.0
|
|
471
783
|
*/
|
|
472
784
|
(overrides: typeof Config.Service) => <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, Config>>,
|
|
473
785
|
/**
|
|
474
|
-
* Provides config overrides for OpenAI language model operations.
|
|
786
|
+
* Provides scoped config overrides for OpenAI-compatible language model operations.
|
|
787
|
+
*
|
|
788
|
+
* **When to use**
|
|
789
|
+
*
|
|
790
|
+
* Use to override request configuration for a single language model effect
|
|
791
|
+
* without changing the defaults supplied to `model`, `make`, or `layer`.
|
|
792
|
+
*
|
|
793
|
+
* **Details**
|
|
794
|
+
*
|
|
795
|
+
* Existing `Config` values from the Effect context are merged with `overrides`,
|
|
796
|
+
* and the override values take precedence.
|
|
797
|
+
*
|
|
798
|
+
* @see {@link Config} for the configuration shape
|
|
475
799
|
*
|
|
476
|
-
* @since 1.0.0
|
|
477
800
|
* @category configuration
|
|
801
|
+
* @since 4.0.0
|
|
478
802
|
*/
|
|
479
803
|
<A, E, R>(self: Effect.Effect<A, E, R>, overrides: typeof Config.Service) => Effect.Effect<A, E, Exclude<R, Config>>
|
|
480
804
|
>(2, (self, overrides) =>
|
|
@@ -782,7 +1106,7 @@ const buildHttpRequestDetails = (
|
|
|
782
1106
|
method: request.method,
|
|
783
1107
|
url: request.url,
|
|
784
1108
|
urlParams: Array.from(request.urlParams),
|
|
785
|
-
hash: request.hash,
|
|
1109
|
+
hash: Option.getOrUndefined(request.hash),
|
|
786
1110
|
headers: Redactable.redact(request.headers) as Record<string, string>
|
|
787
1111
|
})
|
|
788
1112
|
|
|
@@ -1002,11 +1326,13 @@ const makeStreamResponse = Effect.fnUntraced(
|
|
|
1002
1326
|
hasToolCalls = hasToolCalls || choice.delta.tool_calls.length > 0
|
|
1003
1327
|
choice.delta.tool_calls.forEach((deltaTool, indexInChunk) => {
|
|
1004
1328
|
const toolIndex = deltaTool.index ?? indexInChunk
|
|
1005
|
-
const
|
|
1329
|
+
const activeToolCall = activeToolCalls[toolIndex]
|
|
1330
|
+
const toolId = activeToolCall?.id ?? deltaTool.id ?? `${event.id}_tool_${toolIndex}`
|
|
1006
1331
|
const providerToolName = deltaTool.function?.name
|
|
1007
|
-
const toolName =
|
|
1332
|
+
const toolName = providerToolName !== undefined
|
|
1333
|
+
? toolNameMapper.getCustomName(providerToolName)
|
|
1334
|
+
: activeToolCall?.name ?? toolNameMapper.getCustomName("unknown_tool")
|
|
1008
1335
|
const argumentsDelta = deltaTool.function?.arguments ?? ""
|
|
1009
|
-
const activeToolCall = activeToolCalls[toolIndex]
|
|
1010
1336
|
|
|
1011
1337
|
if (Predicate.isUndefined(activeToolCall)) {
|
|
1012
1338
|
activeToolCalls[toolIndex] = {
|
|
@@ -1169,7 +1495,7 @@ const prepareTools = Effect.fnUntraced(function*<Tools extends ReadonlyArray<Too
|
|
|
1169
1495
|
|
|
1170
1496
|
// Convert the tools in the toolkit to the provider-defined format
|
|
1171
1497
|
for (const tool of allowedTools) {
|
|
1172
|
-
if (Tool.isUserDefined(tool)) {
|
|
1498
|
+
if (Tool.isUserDefined(tool) || Tool.isDynamic(tool)) {
|
|
1173
1499
|
const strict = Tool.getStrictMode(tool) ?? config.strictJsonSchema ?? true
|
|
1174
1500
|
const parameters = yield* tryToolJsonSchema(tool, "prepareTools")
|
|
1175
1501
|
tools.push({
|
|
@@ -1220,6 +1546,7 @@ const toChatCompletionsRequest = (payload: CreateResponse): CreateResponseReques
|
|
|
1220
1546
|
const toolChoice = toChatToolChoice(payload.tool_choice)
|
|
1221
1547
|
|
|
1222
1548
|
return {
|
|
1549
|
+
...extractCustomRequestProperties(payload),
|
|
1223
1550
|
model: payload.model ?? "",
|
|
1224
1551
|
messages: messages.length > 0 ? messages : [{ role: "user", content: "" }],
|
|
1225
1552
|
...(payload.temperature !== undefined ? { temperature: payload.temperature } : undefined),
|
|
@@ -1231,12 +1558,54 @@ const toChatCompletionsRequest = (payload: CreateResponse): CreateResponseReques
|
|
|
1231
1558
|
? { parallel_tool_calls: payload.parallel_tool_calls }
|
|
1232
1559
|
: undefined),
|
|
1233
1560
|
...(payload.service_tier !== undefined ? { service_tier: payload.service_tier } : undefined),
|
|
1561
|
+
...(payload.reasoning !== undefined ? { reasoning: payload.reasoning } : undefined),
|
|
1234
1562
|
...(responseFormat !== undefined ? { response_format: responseFormat } : undefined),
|
|
1235
1563
|
...(tools.length > 0 ? { tools } : undefined),
|
|
1236
1564
|
...(toolChoice !== undefined ? { tool_choice: toolChoice } : undefined)
|
|
1237
1565
|
}
|
|
1238
1566
|
}
|
|
1239
1567
|
|
|
1568
|
+
const createResponseKnownProperties = new Set<string>([
|
|
1569
|
+
"metadata",
|
|
1570
|
+
"top_logprobs",
|
|
1571
|
+
"temperature",
|
|
1572
|
+
"top_p",
|
|
1573
|
+
"user",
|
|
1574
|
+
"safety_identifier",
|
|
1575
|
+
"prompt_cache_key",
|
|
1576
|
+
"service_tier",
|
|
1577
|
+
"prompt_cache_retention",
|
|
1578
|
+
"previous_response_id",
|
|
1579
|
+
"model",
|
|
1580
|
+
"reasoning",
|
|
1581
|
+
"background",
|
|
1582
|
+
"max_output_tokens",
|
|
1583
|
+
"max_tool_calls",
|
|
1584
|
+
"text",
|
|
1585
|
+
"tools",
|
|
1586
|
+
"tool_choice",
|
|
1587
|
+
"truncation",
|
|
1588
|
+
"input",
|
|
1589
|
+
"include",
|
|
1590
|
+
"parallel_tool_calls",
|
|
1591
|
+
"store",
|
|
1592
|
+
"instructions",
|
|
1593
|
+
"stream",
|
|
1594
|
+
"conversation",
|
|
1595
|
+
"modalities",
|
|
1596
|
+
"seed"
|
|
1597
|
+
])
|
|
1598
|
+
|
|
1599
|
+
const extractCustomRequestProperties = (payload: CreateResponse): Record<string, unknown> => {
|
|
1600
|
+
const customProperties: Record<string, unknown> = {}
|
|
1601
|
+
for (const [key, value] of Object.entries(payload)) {
|
|
1602
|
+
if (!createResponseKnownProperties.has(key)) {
|
|
1603
|
+
customProperties[key] = value
|
|
1604
|
+
}
|
|
1605
|
+
}
|
|
1606
|
+
return customProperties
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1240
1609
|
const toChatResponseFormat = (
|
|
1241
1610
|
format: TextResponseFormatConfiguration | undefined
|
|
1242
1611
|
): CreateResponseRequestJson["response_format"] | undefined => {
|