@effect/ai 0.26.0 → 0.27.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/Chat/package.json +6 -0
- package/EmbeddingModel/package.json +6 -0
- package/IdGenerator/package.json +6 -0
- package/LanguageModel/package.json +6 -0
- package/Model/package.json +6 -0
- package/Prompt/package.json +6 -0
- package/Response/package.json +6 -0
- package/Telemetry/package.json +6 -0
- package/Tool/package.json +6 -0
- package/Toolkit/package.json +6 -0
- package/dist/cjs/AiError.js +575 -11
- package/dist/cjs/AiError.js.map +1 -1
- package/dist/cjs/Chat.js +302 -0
- package/dist/cjs/Chat.js.map +1 -0
- package/dist/cjs/EmbeddingModel.js +184 -0
- package/dist/cjs/EmbeddingModel.js.map +1 -0
- package/dist/cjs/IdGenerator.js +255 -0
- package/dist/cjs/IdGenerator.js.map +1 -0
- package/dist/cjs/LanguageModel.js +584 -0
- package/dist/cjs/LanguageModel.js.map +1 -0
- package/dist/cjs/McpServer.js +12 -4
- package/dist/cjs/McpServer.js.map +1 -1
- package/dist/cjs/Model.js +118 -0
- package/dist/cjs/Model.js.map +1 -0
- package/dist/cjs/Prompt.js +649 -0
- package/dist/cjs/Prompt.js.map +1 -0
- package/dist/cjs/Response.js +635 -0
- package/dist/cjs/Response.js.map +1 -0
- package/dist/cjs/Telemetry.js +176 -0
- package/dist/cjs/Telemetry.js.map +1 -0
- package/dist/cjs/Tokenizer.js +87 -8
- package/dist/cjs/Tokenizer.js.map +1 -1
- package/dist/cjs/Tool.js +556 -0
- package/dist/cjs/Tool.js.map +1 -0
- package/dist/cjs/Toolkit.js +279 -0
- package/dist/cjs/Toolkit.js.map +1 -0
- package/dist/cjs/index.js +21 -19
- package/dist/dts/AiError.d.ts +577 -9
- package/dist/dts/AiError.d.ts.map +1 -1
- package/dist/dts/Chat.d.ts +356 -0
- package/dist/dts/Chat.d.ts.map +1 -0
- package/dist/dts/EmbeddingModel.d.ts +153 -0
- package/dist/dts/EmbeddingModel.d.ts.map +1 -0
- package/dist/dts/IdGenerator.d.ts +272 -0
- package/dist/dts/IdGenerator.d.ts.map +1 -0
- package/dist/dts/LanguageModel.d.ts +458 -0
- package/dist/dts/LanguageModel.d.ts.map +1 -0
- package/dist/dts/McpSchema.d.ts +25 -25
- package/dist/dts/McpServer.d.ts +6 -4
- package/dist/dts/McpServer.d.ts.map +1 -1
- package/dist/dts/Model.d.ts +124 -0
- package/dist/dts/Model.d.ts.map +1 -0
- package/dist/dts/Prompt.d.ts +1119 -0
- package/dist/dts/Prompt.d.ts.map +1 -0
- package/dist/dts/Response.d.ts +1519 -0
- package/dist/dts/Response.d.ts.map +1 -0
- package/dist/dts/Telemetry.d.ts +520 -0
- package/dist/dts/Telemetry.d.ts.map +1 -0
- package/dist/dts/Tokenizer.d.ts +131 -13
- package/dist/dts/Tokenizer.d.ts.map +1 -1
- package/dist/dts/Tool.d.ts +876 -0
- package/dist/dts/Tool.d.ts.map +1 -0
- package/dist/dts/Toolkit.d.ts +310 -0
- package/dist/dts/Toolkit.d.ts.map +1 -0
- package/dist/dts/index.d.ts +498 -13
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/esm/AiError.js +570 -10
- package/dist/esm/AiError.js.map +1 -1
- package/dist/esm/Chat.js +291 -0
- package/dist/esm/Chat.js.map +1 -0
- package/dist/esm/EmbeddingModel.js +173 -0
- package/dist/esm/EmbeddingModel.js.map +1 -0
- package/dist/esm/IdGenerator.js +245 -0
- package/dist/esm/IdGenerator.js.map +1 -0
- package/dist/esm/LanguageModel.js +572 -0
- package/dist/esm/LanguageModel.js.map +1 -0
- package/dist/esm/McpServer.js +12 -4
- package/dist/esm/McpServer.js.map +1 -1
- package/dist/esm/Model.js +108 -0
- package/dist/esm/Model.js.map +1 -0
- package/dist/esm/Prompt.js +633 -0
- package/dist/esm/Prompt.js.map +1 -0
- package/dist/esm/Response.js +619 -0
- package/dist/esm/Response.js.map +1 -0
- package/dist/esm/Telemetry.js +166 -0
- package/dist/esm/Telemetry.js.map +1 -0
- package/dist/esm/Tokenizer.js +87 -8
- package/dist/esm/Tokenizer.js.map +1 -1
- package/dist/esm/Tool.js +534 -0
- package/dist/esm/Tool.js.map +1 -0
- package/dist/esm/Toolkit.js +269 -0
- package/dist/esm/Toolkit.js.map +1 -0
- package/dist/esm/index.js +498 -13
- package/dist/esm/index.js.map +1 -1
- package/package.json +76 -68
- package/src/AiError.ts +739 -9
- package/src/Chat.ts +546 -0
- package/src/EmbeddingModel.ts +311 -0
- package/src/IdGenerator.ts +320 -0
- package/src/LanguageModel.ts +1074 -0
- package/src/McpServer.ts +337 -194
- package/src/Model.ts +155 -0
- package/src/Prompt.ts +1616 -0
- package/src/Response.ts +2131 -0
- package/src/Telemetry.ts +655 -0
- package/src/Tokenizer.ts +145 -24
- package/src/Tool.ts +1267 -0
- package/src/Toolkit.ts +516 -0
- package/src/index.ts +499 -13
- package/AiChat/package.json +0 -6
- package/AiEmbeddingModel/package.json +0 -6
- package/AiInput/package.json +0 -6
- package/AiLanguageModel/package.json +0 -6
- package/AiModel/package.json +0 -6
- package/AiResponse/package.json +0 -6
- package/AiTelemetry/package.json +0 -6
- package/AiTool/package.json +0 -6
- package/AiToolkit/package.json +0 -6
- package/dist/cjs/AiChat.js +0 -122
- package/dist/cjs/AiChat.js.map +0 -1
- package/dist/cjs/AiEmbeddingModel.js +0 -109
- package/dist/cjs/AiEmbeddingModel.js.map +0 -1
- package/dist/cjs/AiInput.js +0 -458
- package/dist/cjs/AiInput.js.map +0 -1
- package/dist/cjs/AiLanguageModel.js +0 -351
- package/dist/cjs/AiLanguageModel.js.map +0 -1
- package/dist/cjs/AiModel.js +0 -37
- package/dist/cjs/AiModel.js.map +0 -1
- package/dist/cjs/AiResponse.js +0 -681
- package/dist/cjs/AiResponse.js.map +0 -1
- package/dist/cjs/AiTelemetry.js +0 -58
- package/dist/cjs/AiTelemetry.js.map +0 -1
- package/dist/cjs/AiTool.js +0 -150
- package/dist/cjs/AiTool.js.map +0 -1
- package/dist/cjs/AiToolkit.js +0 -157
- package/dist/cjs/AiToolkit.js.map +0 -1
- package/dist/cjs/internal/common.js +0 -21
- package/dist/cjs/internal/common.js.map +0 -1
- package/dist/dts/AiChat.d.ts +0 -101
- package/dist/dts/AiChat.d.ts.map +0 -1
- package/dist/dts/AiEmbeddingModel.d.ts +0 -65
- package/dist/dts/AiEmbeddingModel.d.ts.map +0 -1
- package/dist/dts/AiInput.d.ts +0 -590
- package/dist/dts/AiInput.d.ts.map +0 -1
- package/dist/dts/AiLanguageModel.d.ts +0 -302
- package/dist/dts/AiLanguageModel.d.ts.map +0 -1
- package/dist/dts/AiModel.d.ts +0 -25
- package/dist/dts/AiModel.d.ts.map +0 -1
- package/dist/dts/AiResponse.d.ts +0 -863
- package/dist/dts/AiResponse.d.ts.map +0 -1
- package/dist/dts/AiTelemetry.d.ts +0 -242
- package/dist/dts/AiTelemetry.d.ts.map +0 -1
- package/dist/dts/AiTool.d.ts +0 -334
- package/dist/dts/AiTool.d.ts.map +0 -1
- package/dist/dts/AiToolkit.d.ts +0 -96
- package/dist/dts/AiToolkit.d.ts.map +0 -1
- package/dist/dts/internal/common.d.ts +0 -2
- package/dist/dts/internal/common.d.ts.map +0 -1
- package/dist/esm/AiChat.js +0 -111
- package/dist/esm/AiChat.js.map +0 -1
- package/dist/esm/AiEmbeddingModel.js +0 -98
- package/dist/esm/AiEmbeddingModel.js.map +0 -1
- package/dist/esm/AiInput.js +0 -433
- package/dist/esm/AiInput.js.map +0 -1
- package/dist/esm/AiLanguageModel.js +0 -340
- package/dist/esm/AiLanguageModel.js.map +0 -1
- package/dist/esm/AiModel.js +0 -29
- package/dist/esm/AiModel.js.map +0 -1
- package/dist/esm/AiResponse.js +0 -657
- package/dist/esm/AiResponse.js.map +0 -1
- package/dist/esm/AiTelemetry.js +0 -48
- package/dist/esm/AiTelemetry.js.map +0 -1
- package/dist/esm/AiTool.js +0 -134
- package/dist/esm/AiTool.js.map +0 -1
- package/dist/esm/AiToolkit.js +0 -147
- package/dist/esm/AiToolkit.js.map +0 -1
- package/dist/esm/internal/common.js +0 -14
- package/dist/esm/internal/common.js.map +0 -1
- package/src/AiChat.ts +0 -251
- package/src/AiEmbeddingModel.ts +0 -169
- package/src/AiInput.ts +0 -602
- package/src/AiLanguageModel.ts +0 -685
- package/src/AiModel.ts +0 -53
- package/src/AiResponse.ts +0 -986
- package/src/AiTelemetry.ts +0 -333
- package/src/AiTool.ts +0 -579
- package/src/AiToolkit.ts +0 -265
- package/src/internal/common.ts +0 -12
package/src/Telemetry.ts
ADDED
|
@@ -0,0 +1,655 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `Telemetry` module provides OpenTelemetry integration for operations
|
|
3
|
+
* performed against a large language model provider by defining telemetry
|
|
4
|
+
* attributes and utilities that follow the OpenTelemetry GenAI semantic
|
|
5
|
+
* conventions.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { Telemetry } from "@effect/ai"
|
|
10
|
+
* import { Effect } from "effect"
|
|
11
|
+
*
|
|
12
|
+
* // Add telemetry attributes to a span
|
|
13
|
+
* const addTelemetry = Effect.gen(function* () {
|
|
14
|
+
* const span = yield* Effect.currentSpan
|
|
15
|
+
*
|
|
16
|
+
* Telemetry.addGenAIAnnotations(span, {
|
|
17
|
+
* system: "openai",
|
|
18
|
+
* operation: { name: "chat" },
|
|
19
|
+
* request: {
|
|
20
|
+
* model: "gpt-4",
|
|
21
|
+
* temperature: 0.7,
|
|
22
|
+
* maxTokens: 1000
|
|
23
|
+
* },
|
|
24
|
+
* usage: {
|
|
25
|
+
* inputTokens: 100,
|
|
26
|
+
* outputTokens: 50
|
|
27
|
+
* }
|
|
28
|
+
* })
|
|
29
|
+
* })
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* @since 1.0.0
|
|
33
|
+
*/
|
|
34
|
+
import * as Context from "effect/Context"
|
|
35
|
+
import { dual } from "effect/Function"
|
|
36
|
+
import * as Predicate from "effect/Predicate"
|
|
37
|
+
import * as String from "effect/String"
|
|
38
|
+
import type { Span } from "effect/Tracer"
|
|
39
|
+
import type { Simplify } from "effect/Types"
|
|
40
|
+
import type { ProviderOptions } from "./LanguageModel.js"
|
|
41
|
+
import type * as Response from "./Response.js"
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* The attributes used to describe telemetry in the context of Generative
|
|
45
|
+
* Artificial Intelligence (GenAI) Models requests and responses.
|
|
46
|
+
*
|
|
47
|
+
* {@see https://opentelemetry.io/docs/specs/semconv/attributes-registry/gen-ai/}
|
|
48
|
+
*
|
|
49
|
+
* @since 1.0.0
|
|
50
|
+
* @category Models
|
|
51
|
+
*/
|
|
52
|
+
export type GenAITelemetryAttributes = Simplify<
|
|
53
|
+
& AttributesWithPrefix<BaseAttributes, "gen_ai">
|
|
54
|
+
& AttributesWithPrefix<OperationAttributes, "gen_ai.operation">
|
|
55
|
+
& AttributesWithPrefix<TokenAttributes, "gen_ai.token">
|
|
56
|
+
& AttributesWithPrefix<UsageAttributes, "gen_ai.usage">
|
|
57
|
+
& AttributesWithPrefix<RequestAttributes, "gen_ai.request">
|
|
58
|
+
& AttributesWithPrefix<ResponseAttributes, "gen_ai.response">
|
|
59
|
+
>
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* All telemetry attributes which are part of the GenAI specification.
|
|
63
|
+
*
|
|
64
|
+
* @since 1.0.0
|
|
65
|
+
* @category Models
|
|
66
|
+
*/
|
|
67
|
+
export type AllAttributes =
|
|
68
|
+
& BaseAttributes
|
|
69
|
+
& OperationAttributes
|
|
70
|
+
& TokenAttributes
|
|
71
|
+
& UsageAttributes
|
|
72
|
+
& RequestAttributes
|
|
73
|
+
& ResponseAttributes
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Telemetry attributes which are part of the GenAI specification and are
|
|
77
|
+
* namespaced by `gen_ai`.
|
|
78
|
+
*
|
|
79
|
+
* @since 1.0.0
|
|
80
|
+
* @category Models
|
|
81
|
+
*/
|
|
82
|
+
export interface BaseAttributes {
|
|
83
|
+
/**
|
|
84
|
+
* The Generative AI product as identified by the client or server
|
|
85
|
+
* instrumentation.
|
|
86
|
+
*/
|
|
87
|
+
readonly system?: (string & {}) | WellKnownSystem | null | undefined
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Telemetry attributes which are part of the GenAI specification and are
|
|
92
|
+
* namespaced by `gen_ai.operation`.
|
|
93
|
+
*
|
|
94
|
+
* @since 1.0.0
|
|
95
|
+
* @category Models
|
|
96
|
+
*/
|
|
97
|
+
export interface OperationAttributes {
|
|
98
|
+
readonly name?: (string & {}) | WellKnownOperationName | null | undefined
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Telemetry attributes which are part of the GenAI specification and are
|
|
103
|
+
* namespaced by `gen_ai.token`.
|
|
104
|
+
*
|
|
105
|
+
* @since 1.0.0
|
|
106
|
+
* @category Models
|
|
107
|
+
*/
|
|
108
|
+
export interface TokenAttributes {
|
|
109
|
+
readonly type?: string | null | undefined
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Telemetry attributes which are part of the GenAI specification and are
|
|
114
|
+
* namespaced by `gen_ai.usage`.
|
|
115
|
+
*
|
|
116
|
+
* @since 1.0.0
|
|
117
|
+
* @category Models
|
|
118
|
+
*/
|
|
119
|
+
export interface UsageAttributes {
|
|
120
|
+
readonly inputTokens?: number | null | undefined
|
|
121
|
+
readonly outputTokens?: number | null | undefined
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Telemetry attributes which are part of the GenAI specification and are
|
|
126
|
+
* namespaced by `gen_ai.request`.
|
|
127
|
+
*
|
|
128
|
+
* @since 1.0.0
|
|
129
|
+
* @category Models
|
|
130
|
+
*/
|
|
131
|
+
export interface RequestAttributes {
|
|
132
|
+
/**
|
|
133
|
+
* The name of the GenAI model a request is being made to.
|
|
134
|
+
*/
|
|
135
|
+
readonly model?: string | null | undefined
|
|
136
|
+
/**
|
|
137
|
+
* The temperature setting for the GenAI request.
|
|
138
|
+
*/
|
|
139
|
+
readonly temperature?: number | null | undefined
|
|
140
|
+
/**
|
|
141
|
+
* The temperature setting for the GenAI request.
|
|
142
|
+
*/
|
|
143
|
+
readonly topK?: number | null | undefined
|
|
144
|
+
/**
|
|
145
|
+
* The top_k sampling setting for the GenAI request.
|
|
146
|
+
*/
|
|
147
|
+
readonly topP?: number | null | undefined
|
|
148
|
+
/**
|
|
149
|
+
* The top_p sampling setting for the GenAI request.
|
|
150
|
+
*/
|
|
151
|
+
readonly maxTokens?: number | null | undefined
|
|
152
|
+
/**
|
|
153
|
+
* The encoding formats requested in an embeddings operation, if specified.
|
|
154
|
+
*/
|
|
155
|
+
readonly encodingFormats?: ReadonlyArray<string> | null | undefined
|
|
156
|
+
/**
|
|
157
|
+
* List of sequences that the model will use to stop generating further
|
|
158
|
+
* tokens.
|
|
159
|
+
*/
|
|
160
|
+
readonly stopSequences?: ReadonlyArray<string> | null | undefined
|
|
161
|
+
/**
|
|
162
|
+
* The frequency penalty setting for the GenAI request.
|
|
163
|
+
*/
|
|
164
|
+
readonly frequencyPenalty?: number | null | undefined
|
|
165
|
+
/**
|
|
166
|
+
* The presence penalty setting for the GenAI request.
|
|
167
|
+
*/
|
|
168
|
+
readonly presencePenalty?: number | null | undefined
|
|
169
|
+
/**
|
|
170
|
+
* The seed setting for the GenAI request. Requests with same seed value
|
|
171
|
+
* are more likely to return same result.
|
|
172
|
+
*/
|
|
173
|
+
readonly seed?: number | null | undefined
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Telemetry attributes which are part of the GenAI specification and are
|
|
178
|
+
* namespaced by `gen_ai.response`.
|
|
179
|
+
*
|
|
180
|
+
* @since 1.0.0
|
|
181
|
+
* @category Models
|
|
182
|
+
*/
|
|
183
|
+
export interface ResponseAttributes {
|
|
184
|
+
/**
|
|
185
|
+
* The unique identifier for the completion.
|
|
186
|
+
*/
|
|
187
|
+
readonly id?: string | null | undefined
|
|
188
|
+
/**
|
|
189
|
+
* The name of the model that generated the response.
|
|
190
|
+
*/
|
|
191
|
+
readonly model?: string | null | undefined
|
|
192
|
+
/**
|
|
193
|
+
* Array of reasons the model stopped generating tokens, corresponding to
|
|
194
|
+
* each generation received.
|
|
195
|
+
*/
|
|
196
|
+
readonly finishReasons?: ReadonlyArray<string> | null | undefined
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* The `gen_ai.operation.name` attribute has the following list of well-known
|
|
201
|
+
* values.
|
|
202
|
+
*
|
|
203
|
+
* If one of them applies, then the respective value **MUST** be used;
|
|
204
|
+
* otherwise, a custom value **MAY** be used.
|
|
205
|
+
*
|
|
206
|
+
* @since 1.0.0
|
|
207
|
+
* @category Models
|
|
208
|
+
*/
|
|
209
|
+
export type WellKnownOperationName = "chat" | "embeddings" | "text_completion"
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* The `gen_ai.system` attribute has the following list of well-known values.
|
|
213
|
+
*
|
|
214
|
+
* If one of them applies, then the respective value **MUST** be used;
|
|
215
|
+
* otherwise, a custom value **MAY** be used.
|
|
216
|
+
*
|
|
217
|
+
* @since 1.0.0
|
|
218
|
+
* @category Models
|
|
219
|
+
*/
|
|
220
|
+
export type WellKnownSystem =
|
|
221
|
+
| "anthropic"
|
|
222
|
+
| "aws.bedrock"
|
|
223
|
+
| "az.ai.inference"
|
|
224
|
+
| "az.ai.openai"
|
|
225
|
+
| "cohere"
|
|
226
|
+
| "deepseek"
|
|
227
|
+
| "gemini"
|
|
228
|
+
| "groq"
|
|
229
|
+
| "ibm.watsonx.ai"
|
|
230
|
+
| "mistral_ai"
|
|
231
|
+
| "openai"
|
|
232
|
+
| "perplexity"
|
|
233
|
+
| "vertex_ai"
|
|
234
|
+
| "xai"
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Utility type for prefixing attribute names with a namespace.
|
|
238
|
+
*
|
|
239
|
+
* Transforms attribute keys by adding a prefix and formatting them according to
|
|
240
|
+
* OpenTelemetry conventions (camelCase to snake_case).
|
|
241
|
+
*
|
|
242
|
+
* @template Attributes - Record type containing the attributes to prefix
|
|
243
|
+
* @template Prefix - String literal type for the prefix to add
|
|
244
|
+
*
|
|
245
|
+
* @example
|
|
246
|
+
* ```ts
|
|
247
|
+
* import { Telemetry } from "@effect/ai"
|
|
248
|
+
*
|
|
249
|
+
* type RequestAttrs = {
|
|
250
|
+
* modelName: string
|
|
251
|
+
* maxTokens: number
|
|
252
|
+
* }
|
|
253
|
+
*
|
|
254
|
+
* type PrefixedAttrs = Telemetry.AttributesWithPrefix<RequestAttrs, "gen_ai.request">
|
|
255
|
+
* // Results in: {
|
|
256
|
+
* // "gen_ai.request.model_name": string
|
|
257
|
+
* // "gen_ai.request.max_tokens": number
|
|
258
|
+
* // }
|
|
259
|
+
* ```
|
|
260
|
+
*
|
|
261
|
+
* @since 1.0.0
|
|
262
|
+
* @category Utility Types
|
|
263
|
+
*/
|
|
264
|
+
export type AttributesWithPrefix<Attributes extends Record<string, any>, Prefix extends string> = {
|
|
265
|
+
[Name in keyof Attributes as `${Prefix}.${FormatAttributeName<Name>}`]: Attributes[Name]
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Utility type for converting camelCase names to snake_case format.
|
|
270
|
+
*
|
|
271
|
+
* This type recursively transforms string literal types from camelCase to
|
|
272
|
+
* snake_case, which is the standard format for OpenTelemetry attributes.
|
|
273
|
+
*
|
|
274
|
+
* @template T - String literal type to format
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* ```ts
|
|
278
|
+
* import { Telemetry } from "@effect/ai"
|
|
279
|
+
*
|
|
280
|
+
* type Formatted1 = Telemetry.FormatAttributeName<"modelName"> // "model_name"
|
|
281
|
+
* type Formatted2 = Telemetry.FormatAttributeName<"maxTokens"> // "max_tokens"
|
|
282
|
+
* type Formatted3 = Telemetry.FormatAttributeName<"temperature"> // "temperature"
|
|
283
|
+
* ```
|
|
284
|
+
*
|
|
285
|
+
* @since 1.0.0
|
|
286
|
+
* @category Utility Types
|
|
287
|
+
*/
|
|
288
|
+
export type FormatAttributeName<T extends string | number | symbol> = T extends string ?
|
|
289
|
+
T extends `${infer First}${infer Rest}`
|
|
290
|
+
? `${First extends Uppercase<First> ? "_" : ""}${Lowercase<First>}${FormatAttributeName<Rest>}`
|
|
291
|
+
: T :
|
|
292
|
+
never
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Creates a function to add attributes to a span with a given prefix and key transformation.
|
|
296
|
+
*
|
|
297
|
+
* This utility function is used internally to create specialized functions for adding
|
|
298
|
+
* different types of telemetry attributes to OpenTelemetry spans.
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* ```ts
|
|
302
|
+
* import { Telemetry } from "@effect/ai"
|
|
303
|
+
* import { String, Tracer } from "effect"
|
|
304
|
+
*
|
|
305
|
+
* const addCustomAttributes = Telemetry.addSpanAttributes(
|
|
306
|
+
* "custom.ai",
|
|
307
|
+
* String.camelToSnake
|
|
308
|
+
* )
|
|
309
|
+
*
|
|
310
|
+
* // Usage with a span
|
|
311
|
+
* declare const span: Tracer.Span
|
|
312
|
+
* addCustomAttributes(span, {
|
|
313
|
+
* modelName: "gpt-4",
|
|
314
|
+
* maxTokens: 1000
|
|
315
|
+
* })
|
|
316
|
+
* // Results in attributes: "custom.ai.model_name" and "custom.ai.max_tokens"
|
|
317
|
+
* ```
|
|
318
|
+
*
|
|
319
|
+
* @since 1.0.0
|
|
320
|
+
* @category Utilities
|
|
321
|
+
*/
|
|
322
|
+
export const addSpanAttributes = (
|
|
323
|
+
/**
|
|
324
|
+
* The prefix to add to all attribute keys.
|
|
325
|
+
*/
|
|
326
|
+
keyPrefix: string,
|
|
327
|
+
/**
|
|
328
|
+
* Function to transform attribute keys (e.g., camelCase to snake_case).
|
|
329
|
+
*/
|
|
330
|
+
transformKey: (key: string) => string
|
|
331
|
+
) =>
|
|
332
|
+
<Attributes extends Record<string, any>>(
|
|
333
|
+
/**
|
|
334
|
+
* The OpenTelemetry span to add attributes to.
|
|
335
|
+
*/
|
|
336
|
+
span: Span,
|
|
337
|
+
/**
|
|
338
|
+
* The attributes to add to the span.
|
|
339
|
+
*/
|
|
340
|
+
attributes: Attributes
|
|
341
|
+
): void => {
|
|
342
|
+
for (const [key, value] of Object.entries(attributes)) {
|
|
343
|
+
if (Predicate.isNotNullable(value)) {
|
|
344
|
+
span.attribute(`${keyPrefix}.${transformKey(key)}`, value)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const addSpanBaseAttributes = addSpanAttributes("gen_ai", String.camelToSnake)<BaseAttributes>
|
|
350
|
+
const addSpanOperationAttributes = addSpanAttributes("gen_ai.operation", String.camelToSnake)<OperationAttributes>
|
|
351
|
+
const addSpanRequestAttributes = addSpanAttributes("gen_ai.request", String.camelToSnake)<RequestAttributes>
|
|
352
|
+
const addSpanResponseAttributes = addSpanAttributes("gen_ai.response", String.camelToSnake)<ResponseAttributes>
|
|
353
|
+
const addSpanTokenAttributes = addSpanAttributes("gen_ai.token", String.camelToSnake)<TokenAttributes>
|
|
354
|
+
const addSpanUsageAttributes = addSpanAttributes("gen_ai.usage", String.camelToSnake)<UsageAttributes>
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Configuration options for GenAI telemetry attributes.
|
|
358
|
+
*
|
|
359
|
+
* Combines base attributes with optional grouped attributes for comprehensive
|
|
360
|
+
* telemetry coverage of AI operations.
|
|
361
|
+
*
|
|
362
|
+
* @example
|
|
363
|
+
* ```ts
|
|
364
|
+
* import { Telemetry } from "@effect/ai"
|
|
365
|
+
*
|
|
366
|
+
* const telemetryOptions: Telemetry.GenAITelemetryAttributeOptions = {
|
|
367
|
+
* system: "openai",
|
|
368
|
+
* operation: {
|
|
369
|
+
* name: "chat"
|
|
370
|
+
* },
|
|
371
|
+
* request: {
|
|
372
|
+
* model: "gpt-4-turbo",
|
|
373
|
+
* temperature: 0.7,
|
|
374
|
+
* maxTokens: 2000
|
|
375
|
+
* },
|
|
376
|
+
* response: {
|
|
377
|
+
* id: "chatcmpl-123",
|
|
378
|
+
* model: "gpt-4-turbo-2024-04-09",
|
|
379
|
+
* finishReasons: ["stop"]
|
|
380
|
+
* },
|
|
381
|
+
* usage: {
|
|
382
|
+
* inputTokens: 50,
|
|
383
|
+
* outputTokens: 25
|
|
384
|
+
* }
|
|
385
|
+
* }
|
|
386
|
+
* ```
|
|
387
|
+
*
|
|
388
|
+
* @since 1.0.0
|
|
389
|
+
* @category Models
|
|
390
|
+
*/
|
|
391
|
+
export type GenAITelemetryAttributeOptions = BaseAttributes & {
|
|
392
|
+
/**
|
|
393
|
+
* Operation-specific attributes (e.g., operation name).
|
|
394
|
+
*/
|
|
395
|
+
readonly operation?: OperationAttributes | undefined
|
|
396
|
+
/**
|
|
397
|
+
* Request-specific attributes (e.g., model parameters).
|
|
398
|
+
*/
|
|
399
|
+
readonly request?: RequestAttributes | undefined
|
|
400
|
+
/**
|
|
401
|
+
* Response-specific attributes (e.g., response metadata).
|
|
402
|
+
*/
|
|
403
|
+
readonly response?: ResponseAttributes | undefined
|
|
404
|
+
/**
|
|
405
|
+
* Token-specific attributes.
|
|
406
|
+
*/
|
|
407
|
+
readonly token?: TokenAttributes | undefined
|
|
408
|
+
/**
|
|
409
|
+
* Usage statistics attributes (e.g., token counts).
|
|
410
|
+
*/
|
|
411
|
+
readonly usage?: UsageAttributes | undefined
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/**
|
|
415
|
+
* Applies GenAI telemetry attributes to an OpenTelemetry span.
|
|
416
|
+
*
|
|
417
|
+
* This function adds standardized GenAI attributes to a span following OpenTelemetry
|
|
418
|
+
* semantic conventions. It supports both curried and direct application patterns.
|
|
419
|
+
*
|
|
420
|
+
* **Note**: This function mutates the provided span in-place.
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* ```ts
|
|
424
|
+
* import { Telemetry } from "@effect/ai"
|
|
425
|
+
* import { Effect } from "effect"
|
|
426
|
+
*
|
|
427
|
+
* const directUsage = Effect.gen(function* () {
|
|
428
|
+
* const span = yield* Effect.currentSpan
|
|
429
|
+
*
|
|
430
|
+
* Telemetry.addGenAIAnnotations(span, {
|
|
431
|
+
* system: "openai",
|
|
432
|
+
* request: { model: "gpt-4", temperature: 0.7 },
|
|
433
|
+
* usage: { inputTokens: 100, outputTokens: 50 }
|
|
434
|
+
* })
|
|
435
|
+
* })
|
|
436
|
+
* ```
|
|
437
|
+
*
|
|
438
|
+
* @since 1.0.0
|
|
439
|
+
* @category Utilities
|
|
440
|
+
*/
|
|
441
|
+
export const addGenAIAnnotations: {
|
|
442
|
+
/**
|
|
443
|
+
* Applies GenAI telemetry attributes to an OpenTelemetry span.
|
|
444
|
+
*
|
|
445
|
+
* This function adds standardized GenAI attributes to a span following OpenTelemetry
|
|
446
|
+
* semantic conventions. It supports both curried and direct application patterns.
|
|
447
|
+
*
|
|
448
|
+
* **Note**: This function mutates the provided span in-place.
|
|
449
|
+
*
|
|
450
|
+
* @example
|
|
451
|
+
* ```ts
|
|
452
|
+
* import { Telemetry } from "@effect/ai"
|
|
453
|
+
* import { Effect } from "effect"
|
|
454
|
+
*
|
|
455
|
+
* const directUsage = Effect.gen(function* () {
|
|
456
|
+
* const span = yield* Effect.currentSpan
|
|
457
|
+
*
|
|
458
|
+
* Telemetry.addGenAIAnnotations(span, {
|
|
459
|
+
* system: "openai",
|
|
460
|
+
* request: { model: "gpt-4", temperature: 0.7 },
|
|
461
|
+
* usage: { inputTokens: 100, outputTokens: 50 }
|
|
462
|
+
* })
|
|
463
|
+
* })
|
|
464
|
+
* ```
|
|
465
|
+
*
|
|
466
|
+
* @since 1.0.0
|
|
467
|
+
* @category Utilities
|
|
468
|
+
*/
|
|
469
|
+
(
|
|
470
|
+
/**
|
|
471
|
+
* Telemetry attribute options to apply to the span.
|
|
472
|
+
*/
|
|
473
|
+
options: GenAITelemetryAttributeOptions
|
|
474
|
+
): (
|
|
475
|
+
/**
|
|
476
|
+
* OpenTelemetry span to add attributes to.
|
|
477
|
+
*/
|
|
478
|
+
span: Span
|
|
479
|
+
) => void
|
|
480
|
+
/**
|
|
481
|
+
* Applies GenAI telemetry attributes to an OpenTelemetry span.
|
|
482
|
+
*
|
|
483
|
+
* This function adds standardized GenAI attributes to a span following OpenTelemetry
|
|
484
|
+
* semantic conventions. It supports both curried and direct application patterns.
|
|
485
|
+
*
|
|
486
|
+
* **Note**: This function mutates the provided span in-place.
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```ts
|
|
490
|
+
* import { Telemetry } from "@effect/ai"
|
|
491
|
+
* import { Effect } from "effect"
|
|
492
|
+
*
|
|
493
|
+
* const directUsage = Effect.gen(function* () {
|
|
494
|
+
* const span = yield* Effect.currentSpan
|
|
495
|
+
*
|
|
496
|
+
* Telemetry.addGenAIAnnotations(span, {
|
|
497
|
+
* system: "openai",
|
|
498
|
+
* request: { model: "gpt-4", temperature: 0.7 },
|
|
499
|
+
* usage: { inputTokens: 100, outputTokens: 50 }
|
|
500
|
+
* })
|
|
501
|
+
* })
|
|
502
|
+
* ```
|
|
503
|
+
*
|
|
504
|
+
* @since 1.0.0
|
|
505
|
+
* @category Utilities
|
|
506
|
+
*/
|
|
507
|
+
(
|
|
508
|
+
/**
|
|
509
|
+
* OpenTelemetry span to add attributes to.
|
|
510
|
+
*/
|
|
511
|
+
span: Span,
|
|
512
|
+
/**
|
|
513
|
+
* Telemetry attribute options to apply to the span.
|
|
514
|
+
*/
|
|
515
|
+
options: GenAITelemetryAttributeOptions
|
|
516
|
+
): void
|
|
517
|
+
} = dual<
|
|
518
|
+
/**
|
|
519
|
+
* Applies GenAI telemetry attributes to an OpenTelemetry span.
|
|
520
|
+
*
|
|
521
|
+
* This function adds standardized GenAI attributes to a span following OpenTelemetry
|
|
522
|
+
* semantic conventions. It supports both curried and direct application patterns.
|
|
523
|
+
*
|
|
524
|
+
* **Note**: This function mutates the provided span in-place.
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* ```ts
|
|
528
|
+
* import { Telemetry } from "@effect/ai"
|
|
529
|
+
* import { Effect } from "effect"
|
|
530
|
+
*
|
|
531
|
+
* const directUsage = Effect.gen(function* () {
|
|
532
|
+
* const span = yield* Effect.currentSpan
|
|
533
|
+
*
|
|
534
|
+
* Telemetry.addGenAIAnnotations(span, {
|
|
535
|
+
* system: "openai",
|
|
536
|
+
* request: { model: "gpt-4", temperature: 0.7 },
|
|
537
|
+
* usage: { inputTokens: 100, outputTokens: 50 }
|
|
538
|
+
* })
|
|
539
|
+
* })
|
|
540
|
+
* ```
|
|
541
|
+
*
|
|
542
|
+
* @since 1.0.0
|
|
543
|
+
* @category Utilities
|
|
544
|
+
*/
|
|
545
|
+
(options: GenAITelemetryAttributeOptions) => (span: Span) => void,
|
|
546
|
+
/**
|
|
547
|
+
* Applies GenAI telemetry attributes to an OpenTelemetry span.
|
|
548
|
+
*
|
|
549
|
+
* This function adds standardized GenAI attributes to a span following OpenTelemetry
|
|
550
|
+
* semantic conventions. It supports both curried and direct application patterns.
|
|
551
|
+
*
|
|
552
|
+
* **Note**: This function mutates the provided span in-place.
|
|
553
|
+
*
|
|
554
|
+
* @example
|
|
555
|
+
* ```ts
|
|
556
|
+
* import { Telemetry } from "@effect/ai"
|
|
557
|
+
* import { Effect } from "effect"
|
|
558
|
+
*
|
|
559
|
+
* const directUsage = Effect.gen(function* () {
|
|
560
|
+
* const span = yield* Effect.currentSpan
|
|
561
|
+
*
|
|
562
|
+
* Telemetry.addGenAIAnnotations(span, {
|
|
563
|
+
* system: "openai",
|
|
564
|
+
* request: { model: "gpt-4", temperature: 0.7 },
|
|
565
|
+
* usage: { inputTokens: 100, outputTokens: 50 }
|
|
566
|
+
* })
|
|
567
|
+
* })
|
|
568
|
+
* ```
|
|
569
|
+
*
|
|
570
|
+
* @since 1.0.0
|
|
571
|
+
* @category Utilities
|
|
572
|
+
*/
|
|
573
|
+
(span: Span, options: GenAITelemetryAttributeOptions) => void
|
|
574
|
+
>(2, (span, options) => {
|
|
575
|
+
addSpanBaseAttributes(span, { system: options.system })
|
|
576
|
+
if (Predicate.isNotNullable(options.operation)) addSpanOperationAttributes(span, options.operation)
|
|
577
|
+
if (Predicate.isNotNullable(options.request)) addSpanRequestAttributes(span, options.request)
|
|
578
|
+
if (Predicate.isNotNullable(options.response)) addSpanResponseAttributes(span, options.response)
|
|
579
|
+
if (Predicate.isNotNullable(options.token)) addSpanTokenAttributes(span, options.token)
|
|
580
|
+
if (Predicate.isNotNullable(options.usage)) addSpanUsageAttributes(span, options.usage)
|
|
581
|
+
})
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* A function that can transform OpenTelemetry spans based on AI operation data.
|
|
585
|
+
*
|
|
586
|
+
* Span transformers receive the complete request/response context from AI operations
|
|
587
|
+
* and can add custom telemetry attributes, metrics, or other observability data.
|
|
588
|
+
*
|
|
589
|
+
* @example
|
|
590
|
+
* ```ts
|
|
591
|
+
* import { Telemetry } from "@effect/ai"
|
|
592
|
+
*
|
|
593
|
+
* const customTransformer: Telemetry.SpanTransformer = (options) => {
|
|
594
|
+
* // Add custom attributes based on the response
|
|
595
|
+
* const textParts = options.response.filter(part => part.type === "text")
|
|
596
|
+
* const totalTextLength = textParts.reduce((sum, part) =>
|
|
597
|
+
* sum + (part.type === "text" ? part.text.length : 0), 0
|
|
598
|
+
* )
|
|
599
|
+
*
|
|
600
|
+
* // Add custom metrics
|
|
601
|
+
* console.log(`Generated ${totalTextLength} characters of text`)
|
|
602
|
+
* }
|
|
603
|
+
* ```
|
|
604
|
+
*
|
|
605
|
+
* @since 1.0.0
|
|
606
|
+
* @category Models
|
|
607
|
+
*/
|
|
608
|
+
export interface SpanTransformer {
|
|
609
|
+
(
|
|
610
|
+
options: ProviderOptions & {
|
|
611
|
+
/**
|
|
612
|
+
* Array of response parts generated by the AI model.
|
|
613
|
+
*/
|
|
614
|
+
readonly response: ReadonlyArray<Response.AllParts<any>>
|
|
615
|
+
}
|
|
616
|
+
): void
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Context tag for providing a span transformer to large langauge model
|
|
621
|
+
* operations.
|
|
622
|
+
*
|
|
623
|
+
* The CurrentSpanTransformer allows you to inject custom span transformation
|
|
624
|
+
* logic into AI operations, enabling application-specific telemetry and
|
|
625
|
+
* observability patterns.
|
|
626
|
+
*
|
|
627
|
+
* @example
|
|
628
|
+
* ```ts
|
|
629
|
+
* import { Telemetry } from "@effect/ai"
|
|
630
|
+
* import { Context, Effect } from "effect"
|
|
631
|
+
*
|
|
632
|
+
* // Create a custom span transformer
|
|
633
|
+
* const loggingTransformer: Telemetry.SpanTransformer = (options) => {
|
|
634
|
+
* console.log(`AI request completed: ${options.model}`)
|
|
635
|
+
* options.response.forEach((part, index) => {
|
|
636
|
+
* console.log(`Part ${index}: ${part.type}`)
|
|
637
|
+
* })
|
|
638
|
+
* }
|
|
639
|
+
*
|
|
640
|
+
* // Provide the transformer to your AI operations
|
|
641
|
+
* const program = myAIOperation.pipe(
|
|
642
|
+
* Effect.provideService(
|
|
643
|
+
* Telemetry.CurrentSpanTransformer,
|
|
644
|
+
* Telemetry.CurrentSpanTransformer.of(loggingTransformer)
|
|
645
|
+
* )
|
|
646
|
+
* )
|
|
647
|
+
* ```
|
|
648
|
+
*
|
|
649
|
+
* @since 1.0.0
|
|
650
|
+
* @category Context
|
|
651
|
+
*/
|
|
652
|
+
export class CurrentSpanTransformer extends Context.Tag("@effect/ai/Telemetry/CurrentSpanTransformer")<
|
|
653
|
+
CurrentSpanTransformer,
|
|
654
|
+
SpanTransformer
|
|
655
|
+
>() {}
|