@traceloop/instrumentation-bedrock 0.23.0 → 0.24.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/dist/index.d.ts +12 -1
- package/dist/index.js +322 -98
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +324 -101
- package/dist/src/instrumentation.d.ts +4 -0
- package/dist/src/types.d.ts +7 -0
- package/package.json +8 -6
package/dist/index.js
CHANGED
|
@@ -5,9 +5,40 @@ var api = require('@opentelemetry/api');
|
|
|
5
5
|
var instrumentation = require('@opentelemetry/instrumentation');
|
|
6
6
|
var aiSemanticConventions = require('@traceloop/ai-semantic-conventions');
|
|
7
7
|
var incubating = require('@opentelemetry/semantic-conventions/incubating');
|
|
8
|
+
var instrumentationUtils = require('@traceloop/instrumentation-utils');
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
exports.BedrockVendor = void 0;
|
|
11
|
+
(function (BedrockVendor) {
|
|
12
|
+
BedrockVendor["AI21"] = "ai21";
|
|
13
|
+
BedrockVendor["AMAZON"] = "amazon";
|
|
14
|
+
BedrockVendor["ANTHROPIC"] = "anthropic";
|
|
15
|
+
BedrockVendor["COHERE"] = "cohere";
|
|
16
|
+
BedrockVendor["META"] = "meta";
|
|
17
|
+
})(exports.BedrockVendor || (exports.BedrockVendor = {}));
|
|
10
18
|
|
|
19
|
+
var version = "0.24.0";
|
|
20
|
+
|
|
21
|
+
const bedrockFinishReasonMap = {
|
|
22
|
+
// AI21
|
|
23
|
+
endoftext: aiSemanticConventions.FinishReasons.STOP,
|
|
24
|
+
// Amazon Titan / Nova
|
|
25
|
+
FINISH: aiSemanticConventions.FinishReasons.STOP,
|
|
26
|
+
LENGTH: aiSemanticConventions.FinishReasons.LENGTH,
|
|
27
|
+
CONTENT_FILTERED: aiSemanticConventions.FinishReasons.CONTENT_FILTER,
|
|
28
|
+
// Anthropic
|
|
29
|
+
end_turn: aiSemanticConventions.FinishReasons.STOP,
|
|
30
|
+
max_tokens: aiSemanticConventions.FinishReasons.LENGTH,
|
|
31
|
+
stop_sequence: aiSemanticConventions.FinishReasons.STOP,
|
|
32
|
+
tool_use: aiSemanticConventions.FinishReasons.TOOL_CALL,
|
|
33
|
+
// Cohere
|
|
34
|
+
COMPLETE: aiSemanticConventions.FinishReasons.STOP,
|
|
35
|
+
MAX_TOKENS: aiSemanticConventions.FinishReasons.LENGTH,
|
|
36
|
+
ERROR: aiSemanticConventions.FinishReasons.ERROR,
|
|
37
|
+
ERROR_TOXIC: aiSemanticConventions.FinishReasons.CONTENT_FILTER,
|
|
38
|
+
// Meta
|
|
39
|
+
stop: aiSemanticConventions.FinishReasons.STOP,
|
|
40
|
+
length: aiSemanticConventions.FinishReasons.LENGTH,
|
|
41
|
+
};
|
|
11
42
|
class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
12
43
|
constructor(config = {}) {
|
|
13
44
|
super("@traceloop/instrumentation-bedrock", version, config);
|
|
@@ -38,9 +69,11 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
38
69
|
// eslint-disable-next-line
|
|
39
70
|
return (original) => {
|
|
40
71
|
return function method(...args) {
|
|
72
|
+
var _a, _b, _c;
|
|
41
73
|
const span = plugin._startSpan({
|
|
42
74
|
params: args[0],
|
|
43
75
|
});
|
|
76
|
+
const modelId = (_c = (_b = (_a = args[0]) === null || _a === void 0 ? void 0 : _a.input) === null || _b === void 0 ? void 0 : _b.modelId) !== null && _c !== void 0 ? _c : "";
|
|
44
77
|
const execContext = api.trace.setSpan(api.context.active(), span);
|
|
45
78
|
const execPromise = instrumentation.safeExecuteInTheMiddle(() => {
|
|
46
79
|
return api.context.with(execContext, () => {
|
|
@@ -51,17 +84,18 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
51
84
|
plugin._diag.error(`Error in bedrock instrumentation`, e);
|
|
52
85
|
}
|
|
53
86
|
});
|
|
54
|
-
const wrappedPromise = plugin._wrapPromise(span, execPromise);
|
|
87
|
+
const wrappedPromise = plugin._wrapPromise(span, execPromise, modelId);
|
|
55
88
|
return api.context.bind(execContext, wrappedPromise);
|
|
56
89
|
};
|
|
57
90
|
};
|
|
58
91
|
}
|
|
59
|
-
_wrapPromise(span, promise) {
|
|
92
|
+
_wrapPromise(span, promise, modelId) {
|
|
60
93
|
return promise
|
|
61
94
|
.then((result) => tslib.__awaiter(this, void 0, void 0, function* () {
|
|
62
95
|
yield this._endSpan({
|
|
63
96
|
span,
|
|
64
97
|
result: result,
|
|
98
|
+
modelId,
|
|
65
99
|
});
|
|
66
100
|
return new Promise((resolve) => resolve(result));
|
|
67
101
|
}))
|
|
@@ -80,17 +114,21 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
80
114
|
_startSpan({ params, }) {
|
|
81
115
|
var _a, _b;
|
|
82
116
|
let attributes = {};
|
|
117
|
+
let spanName = "bedrock.completion";
|
|
83
118
|
try {
|
|
84
119
|
const input = params.input;
|
|
85
120
|
const { modelVendor, model } = this._extractVendorAndModel(input.modelId || "");
|
|
86
121
|
attributes = {
|
|
87
|
-
[incubating.
|
|
122
|
+
[incubating.ATTR_GEN_AI_PROVIDER_NAME]: incubating.GEN_AI_PROVIDER_NAME_VALUE_AWS_BEDROCK,
|
|
88
123
|
[incubating.ATTR_GEN_AI_REQUEST_MODEL]: model,
|
|
89
|
-
[incubating.ATTR_GEN_AI_RESPONSE_MODEL]: input.modelId,
|
|
90
|
-
[aiSemanticConventions.SpanAttributes.LLM_REQUEST_TYPE]: aiSemanticConventions.LLMRequestTypeValues.COMPLETION,
|
|
91
124
|
};
|
|
92
125
|
if (typeof input.body === "string") {
|
|
93
126
|
const requestBody = JSON.parse(input.body);
|
|
127
|
+
const operationType = this._getOperationType(modelVendor, requestBody);
|
|
128
|
+
spanName = `${operationType} ${model}`;
|
|
129
|
+
// Set operation name before _setRequestAttributes so it is always
|
|
130
|
+
// present even if _setRequestAttributes throws for an unexpected body.
|
|
131
|
+
attributes = Object.assign(Object.assign({}, attributes), { [incubating.ATTR_GEN_AI_OPERATION_NAME]: operationType });
|
|
94
132
|
attributes = Object.assign(Object.assign({}, attributes), this._setRequestAttributes(modelVendor, requestBody));
|
|
95
133
|
}
|
|
96
134
|
}
|
|
@@ -98,50 +136,57 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
98
136
|
this._diag.debug(e);
|
|
99
137
|
(_b = (_a = this._config).exceptionLogger) === null || _b === void 0 ? void 0 : _b.call(_a, e);
|
|
100
138
|
}
|
|
101
|
-
return this.tracer.startSpan(
|
|
139
|
+
return this.tracer.startSpan(spanName, {
|
|
102
140
|
kind: api.SpanKind.CLIENT,
|
|
103
141
|
attributes,
|
|
104
142
|
});
|
|
105
143
|
}
|
|
106
144
|
_endSpan(_a) {
|
|
107
|
-
return tslib.__awaiter(this, arguments, void 0, function* ({ span, result, }) {
|
|
145
|
+
return tslib.__awaiter(this, arguments, void 0, function* ({ span, result, modelId, }) {
|
|
108
146
|
var _b, e_1, _c, _d;
|
|
109
|
-
var _e, _f, _g;
|
|
147
|
+
var _e, _f, _g, _h;
|
|
110
148
|
try {
|
|
111
149
|
if ("body" in result) {
|
|
112
150
|
const attributes = "attributes" in span
|
|
113
151
|
? span["attributes"]
|
|
114
152
|
: {};
|
|
115
|
-
if (incubating.
|
|
116
|
-
const modelId = attributes[incubating.ATTR_GEN_AI_RESPONSE_MODEL];
|
|
153
|
+
if (incubating.ATTR_GEN_AI_PROVIDER_NAME in attributes) {
|
|
117
154
|
const { modelVendor, model } = this._extractVendorAndModel(modelId);
|
|
118
155
|
span.setAttribute(incubating.ATTR_GEN_AI_RESPONSE_MODEL, model);
|
|
119
156
|
if (!(result.body instanceof Object.getPrototypeOf(Uint8Array))) {
|
|
120
157
|
const rawRes = result.body;
|
|
121
158
|
let streamedContent = "";
|
|
122
159
|
try {
|
|
123
|
-
for (var
|
|
160
|
+
for (var _j = true, rawRes_1 = tslib.__asyncValues(rawRes), rawRes_1_1; rawRes_1_1 = yield rawRes_1.next(), _b = rawRes_1_1.done, !_b; _j = true) {
|
|
124
161
|
_d = rawRes_1_1.value;
|
|
125
|
-
|
|
162
|
+
_j = false;
|
|
126
163
|
const value = _d;
|
|
127
164
|
// Convert it to a JSON String
|
|
128
165
|
const jsonString = new TextDecoder().decode((_e = value.chunk) === null || _e === void 0 ? void 0 : _e.bytes);
|
|
129
166
|
// Parse the JSON string
|
|
130
167
|
const parsedResponse = JSON.parse(jsonString);
|
|
131
168
|
if ("amazon-bedrock-invocationMetrics" in parsedResponse) {
|
|
132
|
-
span.setAttribute(incubating.
|
|
133
|
-
span.setAttribute(incubating.
|
|
134
|
-
|
|
135
|
-
parsedResponse["amazon-bedrock-invocationMetrics"]["outputTokenCount"]
|
|
169
|
+
span.setAttribute(incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS, parsedResponse["amazon-bedrock-invocationMetrics"]["inputTokenCount"]);
|
|
170
|
+
span.setAttribute(incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, parsedResponse["amazon-bedrock-invocationMetrics"]["outputTokenCount"]);
|
|
171
|
+
const totalTokens = parsedResponse["amazon-bedrock-invocationMetrics"]["inputTokenCount"] +
|
|
172
|
+
parsedResponse["amazon-bedrock-invocationMetrics"]["outputTokenCount"];
|
|
173
|
+
span.setAttribute(aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, totalTokens);
|
|
136
174
|
}
|
|
137
|
-
|
|
175
|
+
this._handleNovaStreamingMetadata(span, parsedResponse);
|
|
176
|
+
const responseAttributes = this._setResponseAttributes(modelVendor, parsedResponse, true);
|
|
138
177
|
// ! NOTE: This make sure the content always have all streamed chunks
|
|
139
178
|
if (this._shouldSendPrompts()) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
179
|
+
const chunkContent = this._getStreamChunkContent(modelVendor, parsedResponse);
|
|
180
|
+
if (chunkContent !== undefined) {
|
|
181
|
+
streamedContent += chunkContent;
|
|
182
|
+
}
|
|
183
|
+
// When finish reason is available (final chunk), set OTel 1.40 output message
|
|
184
|
+
if (responseAttributes[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]) {
|
|
185
|
+
const finishReasons = responseAttributes[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS];
|
|
186
|
+
responseAttributes[incubating.ATTR_GEN_AI_OUTPUT_MESSAGES] =
|
|
187
|
+
instrumentationUtils.formatOutputMessage(streamedContent, (_f = finishReasons[0]) !== null && _f !== void 0 ? _f : null, {}, // already mapped by _setResponseAttributes
|
|
188
|
+
attributes[incubating.ATTR_GEN_AI_OPERATION_NAME], instrumentationUtils.mapBedrockContentBlock);
|
|
189
|
+
}
|
|
145
190
|
}
|
|
146
191
|
span.setAttributes(responseAttributes);
|
|
147
192
|
}
|
|
@@ -149,7 +194,7 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
149
194
|
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
150
195
|
finally {
|
|
151
196
|
try {
|
|
152
|
-
if (!
|
|
197
|
+
if (!_j && !_b && (_c = rawRes_1.return)) yield _c.call(rawRes_1);
|
|
153
198
|
}
|
|
154
199
|
finally { if (e_1) throw e_1.error; }
|
|
155
200
|
}
|
|
@@ -167,34 +212,51 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
167
212
|
}
|
|
168
213
|
catch (e) {
|
|
169
214
|
this._diag.debug(e);
|
|
170
|
-
(
|
|
215
|
+
(_h = (_g = this._config).exceptionLogger) === null || _h === void 0 ? void 0 : _h.call(_g, e);
|
|
171
216
|
}
|
|
172
217
|
span.setStatus({ code: api.SpanStatusCode.OK });
|
|
173
218
|
span.end();
|
|
174
219
|
});
|
|
175
220
|
}
|
|
176
221
|
_setRequestAttributes(vendor, requestBody) {
|
|
222
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
177
223
|
switch (vendor) {
|
|
178
|
-
case
|
|
179
|
-
|
|
224
|
+
case exports.BedrockVendor.AI21: {
|
|
225
|
+
// Jamba format: messages array + max_tokens + top_p
|
|
226
|
+
if (requestBody["messages"]) {
|
|
227
|
+
return Object.assign({ [incubating.ATTR_GEN_AI_REQUEST_TOP_P]: requestBody["top_p"], [incubating.ATTR_GEN_AI_REQUEST_TEMPERATURE]: requestBody["temperature"], [incubating.ATTR_GEN_AI_REQUEST_MAX_TOKENS]: requestBody["max_tokens"] }, (this._shouldSendPrompts()
|
|
228
|
+
? {
|
|
229
|
+
[incubating.ATTR_GEN_AI_INPUT_MESSAGES]: instrumentationUtils.formatInputMessages(requestBody["messages"], instrumentationUtils.mapBedrockContentBlock),
|
|
230
|
+
}
|
|
231
|
+
: {}));
|
|
232
|
+
}
|
|
233
|
+
// Legacy Jurassic format: prompt + topP + maxTokens
|
|
234
|
+
return Object.assign({ [incubating.ATTR_GEN_AI_REQUEST_TOP_P]: requestBody["topP"], [incubating.ATTR_GEN_AI_REQUEST_TEMPERATURE]: requestBody["temperature"], [incubating.ATTR_GEN_AI_REQUEST_MAX_TOKENS]: requestBody["maxTokens"], [incubating.ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY]: (_a = requestBody["presencePenalty"]) === null || _a === void 0 ? void 0 : _a["scale"], [incubating.ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY]: (_b = requestBody["frequencyPenalty"]) === null || _b === void 0 ? void 0 : _b["scale"] }, (this._shouldSendPrompts()
|
|
180
235
|
? {
|
|
181
|
-
[
|
|
182
|
-
[`${incubating.ATTR_GEN_AI_PROMPT}.0.content`]: requestBody["prompt"],
|
|
236
|
+
[incubating.ATTR_GEN_AI_INPUT_MESSAGES]: instrumentationUtils.formatInputMessagesFromPrompt(requestBody["prompt"]),
|
|
183
237
|
}
|
|
184
238
|
: {}));
|
|
185
239
|
}
|
|
186
|
-
case
|
|
187
|
-
|
|
240
|
+
case exports.BedrockVendor.AMAZON: {
|
|
241
|
+
// Amazon Nova format: messages array + inferenceConfig
|
|
242
|
+
if (requestBody["messages"]) {
|
|
243
|
+
return Object.assign({ [incubating.ATTR_GEN_AI_REQUEST_TOP_P]: (_c = requestBody["inferenceConfig"]) === null || _c === void 0 ? void 0 : _c["topP"], [incubating.ATTR_GEN_AI_REQUEST_TEMPERATURE]: (_d = requestBody["inferenceConfig"]) === null || _d === void 0 ? void 0 : _d["temperature"], [incubating.ATTR_GEN_AI_REQUEST_MAX_TOKENS]: (_e = requestBody["inferenceConfig"]) === null || _e === void 0 ? void 0 : _e["maxTokens"] }, (this._shouldSendPrompts()
|
|
244
|
+
? {
|
|
245
|
+
[incubating.ATTR_GEN_AI_INPUT_MESSAGES]: instrumentationUtils.formatInputMessages(requestBody["messages"], instrumentationUtils.mapBedrockContentBlock),
|
|
246
|
+
}
|
|
247
|
+
: {}));
|
|
248
|
+
}
|
|
249
|
+
// Amazon Titan format: inputText + textGenerationConfig
|
|
250
|
+
return Object.assign({ [incubating.ATTR_GEN_AI_REQUEST_TOP_P]: (_f = requestBody["textGenerationConfig"]) === null || _f === void 0 ? void 0 : _f["topP"], [incubating.ATTR_GEN_AI_REQUEST_TEMPERATURE]: (_g = requestBody["textGenerationConfig"]) === null || _g === void 0 ? void 0 : _g["temperature"], [incubating.ATTR_GEN_AI_REQUEST_MAX_TOKENS]: (_h = requestBody["textGenerationConfig"]) === null || _h === void 0 ? void 0 : _h["maxTokenCount"] }, (this._shouldSendPrompts()
|
|
188
251
|
? {
|
|
189
|
-
[
|
|
190
|
-
[`${incubating.ATTR_GEN_AI_PROMPT}.0.content`]: requestBody["inputText"],
|
|
252
|
+
[incubating.ATTR_GEN_AI_INPUT_MESSAGES]: instrumentationUtils.formatInputMessagesFromPrompt(requestBody["inputText"]),
|
|
191
253
|
}
|
|
192
254
|
: {}));
|
|
193
255
|
}
|
|
194
|
-
case
|
|
256
|
+
case exports.BedrockVendor.ANTHROPIC: {
|
|
195
257
|
const baseAttributes = {
|
|
196
258
|
[incubating.ATTR_GEN_AI_REQUEST_TOP_P]: requestBody["top_p"],
|
|
197
|
-
[
|
|
259
|
+
[incubating.ATTR_GEN_AI_REQUEST_TOP_K]: requestBody["top_k"],
|
|
198
260
|
[incubating.ATTR_GEN_AI_REQUEST_TEMPERATURE]: requestBody["temperature"],
|
|
199
261
|
[incubating.ATTR_GEN_AI_REQUEST_MAX_TOKENS]: requestBody["max_tokens_to_sample"] || requestBody["max_tokens"],
|
|
200
262
|
};
|
|
@@ -203,39 +265,35 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
203
265
|
}
|
|
204
266
|
// Handle new messages API format (used by langchain)
|
|
205
267
|
if (requestBody["messages"]) {
|
|
206
|
-
const promptAttributes = {
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
promptAttributes[
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
: JSON.stringify(message.content);
|
|
214
|
-
});
|
|
268
|
+
const promptAttributes = {
|
|
269
|
+
[incubating.ATTR_GEN_AI_INPUT_MESSAGES]: instrumentationUtils.formatInputMessages(requestBody["messages"], instrumentationUtils.mapBedrockContentBlock),
|
|
270
|
+
};
|
|
271
|
+
if (requestBody["system"] !== undefined) {
|
|
272
|
+
promptAttributes[incubating.ATTR_GEN_AI_SYSTEM_INSTRUCTIONS] =
|
|
273
|
+
instrumentationUtils.formatSystemInstructions(requestBody["system"]);
|
|
274
|
+
}
|
|
215
275
|
return Object.assign(Object.assign({}, baseAttributes), promptAttributes);
|
|
216
276
|
}
|
|
217
277
|
// Handle legacy prompt format
|
|
218
278
|
if (requestBody["prompt"]) {
|
|
219
|
-
return Object.assign(Object.assign({}, baseAttributes), { [
|
|
220
|
-
// The format is removing when we are setting span attribute
|
|
279
|
+
return Object.assign(Object.assign({}, baseAttributes), { [incubating.ATTR_GEN_AI_INPUT_MESSAGES]: instrumentationUtils.formatInputMessagesFromPrompt(requestBody["prompt"]
|
|
221
280
|
.replace("\n\nHuman:", "")
|
|
222
|
-
.replace("\n\nAssistant:", "") });
|
|
281
|
+
.replace("\n\nAssistant:", "")) });
|
|
223
282
|
}
|
|
224
283
|
return baseAttributes;
|
|
225
284
|
}
|
|
226
|
-
case
|
|
227
|
-
return
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
285
|
+
case exports.BedrockVendor.COHERE: {
|
|
286
|
+
return {
|
|
287
|
+
[incubating.ATTR_GEN_AI_REQUEST_TOP_P]: requestBody["p"],
|
|
288
|
+
[incubating.ATTR_GEN_AI_REQUEST_TOP_K]: requestBody["k"],
|
|
289
|
+
[incubating.ATTR_GEN_AI_REQUEST_TEMPERATURE]: requestBody["temperature"],
|
|
290
|
+
[incubating.ATTR_GEN_AI_REQUEST_MAX_TOKENS]: requestBody["max_tokens"],
|
|
291
|
+
};
|
|
233
292
|
}
|
|
234
|
-
case
|
|
293
|
+
case exports.BedrockVendor.META: {
|
|
235
294
|
return Object.assign({ [incubating.ATTR_GEN_AI_REQUEST_TOP_P]: requestBody["top_p"], [incubating.ATTR_GEN_AI_REQUEST_TEMPERATURE]: requestBody["temperature"], [incubating.ATTR_GEN_AI_REQUEST_MAX_TOKENS]: requestBody["max_gen_len"] }, (this._shouldSendPrompts()
|
|
236
295
|
? {
|
|
237
|
-
[
|
|
238
|
-
[`${incubating.ATTR_GEN_AI_PROMPT}.0.content`]: requestBody["prompt"],
|
|
296
|
+
[incubating.ATTR_GEN_AI_INPUT_MESSAGES]: instrumentationUtils.formatInputMessagesFromPrompt(requestBody["prompt"]),
|
|
239
297
|
}
|
|
240
298
|
: {}));
|
|
241
299
|
}
|
|
@@ -244,71 +302,182 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
244
302
|
}
|
|
245
303
|
}
|
|
246
304
|
_setResponseAttributes(vendor, response, isStream = false) {
|
|
247
|
-
var _a, _b, _c, _d;
|
|
305
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
|
|
248
306
|
switch (vendor) {
|
|
249
|
-
case
|
|
250
|
-
|
|
307
|
+
case exports.BedrockVendor.AI21: {
|
|
308
|
+
// Jamba format: choices[0].message + choices[0].finish_reason
|
|
309
|
+
if (response["choices"]) {
|
|
310
|
+
const usage = response["usage"];
|
|
311
|
+
const finishReason = (_a = response["choices"][0]) === null || _a === void 0 ? void 0 : _a["finish_reason"];
|
|
312
|
+
const content = isStream
|
|
313
|
+
? (_c = (_b = response["choices"][0]) === null || _b === void 0 ? void 0 : _b["delta"]) === null || _c === void 0 ? void 0 : _c["content"]
|
|
314
|
+
: (_e = (_d = response["choices"][0]) === null || _d === void 0 ? void 0 : _d["message"]) === null || _e === void 0 ? void 0 : _e["content"];
|
|
315
|
+
return Object.assign(Object.assign(Object.assign({}, (finishReason != null
|
|
316
|
+
? {
|
|
317
|
+
[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
318
|
+
(_f = bedrockFinishReasonMap[finishReason]) !== null && _f !== void 0 ? _f : finishReason,
|
|
319
|
+
],
|
|
320
|
+
}
|
|
321
|
+
: {})), (usage
|
|
322
|
+
? {
|
|
323
|
+
[incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: usage["prompt_tokens"],
|
|
324
|
+
[incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: usage["completion_tokens"],
|
|
325
|
+
[aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS]: usage["total_tokens"],
|
|
326
|
+
}
|
|
327
|
+
: {})), (this._shouldSendPrompts()
|
|
328
|
+
? {
|
|
329
|
+
[incubating.ATTR_GEN_AI_OUTPUT_MESSAGES]: instrumentationUtils.formatOutputMessage(content !== null && content !== void 0 ? content : "", finishReason, bedrockFinishReasonMap, incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION, instrumentationUtils.mapBedrockContentBlock),
|
|
330
|
+
}
|
|
331
|
+
: {}));
|
|
332
|
+
}
|
|
333
|
+
// Legacy Jurassic format: completions[0].data.text
|
|
334
|
+
const jurassicFinishReason = response["completions"][0]["finishReason"]["reason"];
|
|
335
|
+
const jurassicContent = response["completions"][0]["data"]["text"];
|
|
336
|
+
return Object.assign({ [incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
337
|
+
(_g = bedrockFinishReasonMap[jurassicFinishReason]) !== null && _g !== void 0 ? _g : jurassicFinishReason,
|
|
338
|
+
] }, (this._shouldSendPrompts()
|
|
251
339
|
? {
|
|
252
|
-
[
|
|
340
|
+
[incubating.ATTR_GEN_AI_OUTPUT_MESSAGES]: instrumentationUtils.formatOutputMessage(jurassicContent, jurassicFinishReason, bedrockFinishReasonMap, incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION, instrumentationUtils.mapBedrockContentBlock),
|
|
253
341
|
}
|
|
254
342
|
: {}));
|
|
255
343
|
}
|
|
256
|
-
case
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
344
|
+
case exports.BedrockVendor.AMAZON: {
|
|
345
|
+
if (isStream) {
|
|
346
|
+
// Amazon Nova format: contentBlockDelta has text, messageStop has stopReason
|
|
347
|
+
const novaFinishReason = (_h = response["messageStop"]) === null || _h === void 0 ? void 0 : _h["stopReason"];
|
|
348
|
+
// Amazon Titan format: outputText, completionReason
|
|
349
|
+
const titanFinishReason = response["completionReason"];
|
|
350
|
+
const finishReason = novaFinishReason !== null && novaFinishReason !== void 0 ? novaFinishReason : titanFinishReason;
|
|
351
|
+
return Object.assign(Object.assign({}, (finishReason != null
|
|
352
|
+
? {
|
|
353
|
+
[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
354
|
+
(_j = bedrockFinishReasonMap[finishReason]) !== null && _j !== void 0 ? _j : finishReason,
|
|
355
|
+
],
|
|
356
|
+
}
|
|
357
|
+
: {})), (response["inputTextTokenCount"] != null
|
|
358
|
+
? {
|
|
359
|
+
[incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: response["inputTextTokenCount"],
|
|
360
|
+
[incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: response["totalOutputTextTokenCount"],
|
|
361
|
+
[aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS]: response["inputTextTokenCount"] +
|
|
362
|
+
response["totalOutputTextTokenCount"],
|
|
363
|
+
}
|
|
364
|
+
: {}));
|
|
365
|
+
}
|
|
366
|
+
// Amazon Titan token fields
|
|
367
|
+
const titanInputTokens = response["inputTextTokenCount"];
|
|
368
|
+
const titanOutputTokens = (_l = (_k = response["results"]) === null || _k === void 0 ? void 0 : _k[0]) === null || _l === void 0 ? void 0 : _l["tokenCount"];
|
|
369
|
+
// Amazon Nova token fields
|
|
370
|
+
const novaUsage = response["usage"];
|
|
371
|
+
const amazonFinishReason = (_p = (_o = (_m = response["results"]) === null || _m === void 0 ? void 0 : _m[0]) === null || _o === void 0 ? void 0 : _o["completionReason"]) !== null && _p !== void 0 ? _p : response["stopReason"];
|
|
372
|
+
const novaRawContent = (_r = (_q = response["output"]) === null || _q === void 0 ? void 0 : _q["message"]) === null || _r === void 0 ? void 0 : _r["content"];
|
|
373
|
+
const titanContent = (_t = (_s = response["results"]) === null || _s === void 0 ? void 0 : _s[0]) === null || _t === void 0 ? void 0 : _t["outputText"];
|
|
374
|
+
const outputContent = (_u = novaRawContent !== null && novaRawContent !== void 0 ? novaRawContent : titanContent) !== null && _u !== void 0 ? _u : "";
|
|
375
|
+
const operationType = novaRawContent
|
|
376
|
+
? incubating.GEN_AI_OPERATION_NAME_VALUE_CHAT
|
|
377
|
+
: incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION;
|
|
378
|
+
return Object.assign(Object.assign(Object.assign({}, (amazonFinishReason != null
|
|
266
379
|
? {
|
|
267
|
-
[
|
|
268
|
-
|
|
269
|
-
|
|
380
|
+
[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
381
|
+
(_v = bedrockFinishReasonMap[amazonFinishReason]) !== null && _v !== void 0 ? _v : amazonFinishReason,
|
|
382
|
+
],
|
|
383
|
+
}
|
|
384
|
+
: {})), (titanInputTokens != null
|
|
385
|
+
? {
|
|
386
|
+
[incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: titanInputTokens,
|
|
387
|
+
[incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: titanOutputTokens,
|
|
388
|
+
[aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS]: titanInputTokens + titanOutputTokens,
|
|
389
|
+
}
|
|
390
|
+
: novaUsage != null
|
|
391
|
+
? {
|
|
392
|
+
[incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: novaUsage["inputTokens"],
|
|
393
|
+
[incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: novaUsage["outputTokens"],
|
|
394
|
+
[aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS]: novaUsage["totalTokens"],
|
|
395
|
+
}
|
|
396
|
+
: {})), (this._shouldSendPrompts()
|
|
397
|
+
? {
|
|
398
|
+
[incubating.ATTR_GEN_AI_OUTPUT_MESSAGES]: instrumentationUtils.formatOutputMessage(outputContent, amazonFinishReason, bedrockFinishReasonMap, operationType, instrumentationUtils.mapBedrockContentBlock),
|
|
270
399
|
}
|
|
271
400
|
: {}));
|
|
272
401
|
}
|
|
273
|
-
case
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
402
|
+
case exports.BedrockVendor.ANTHROPIC: {
|
|
403
|
+
if (isStream) {
|
|
404
|
+
// New messages API streaming: content_block_delta has delta.text,
|
|
405
|
+
// message_delta has delta.stop_reason
|
|
406
|
+
const stopReason = (_x = (_w = response["delta"]) === null || _w === void 0 ? void 0 : _w["stop_reason"]) !== null && _x !== void 0 ? _x : response["stop_reason"];
|
|
407
|
+
const finishReason = stopReason !== null && stopReason !== void 0 ? stopReason : undefined;
|
|
408
|
+
return Object.assign({}, (finishReason != null
|
|
409
|
+
? {
|
|
410
|
+
[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
411
|
+
(_y = bedrockFinishReasonMap[finishReason]) !== null && _y !== void 0 ? _y : finishReason,
|
|
412
|
+
],
|
|
413
|
+
}
|
|
414
|
+
: {}));
|
|
415
|
+
}
|
|
416
|
+
const stopReason = response["stop_reason"];
|
|
417
|
+
const usage = response["usage"];
|
|
418
|
+
const baseAttributes = Object.assign(Object.assign({}, (stopReason != null
|
|
419
|
+
? {
|
|
420
|
+
[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
421
|
+
(_z = bedrockFinishReasonMap[stopReason]) !== null && _z !== void 0 ? _z : stopReason,
|
|
422
|
+
],
|
|
423
|
+
}
|
|
424
|
+
: {})), (usage
|
|
425
|
+
? {
|
|
426
|
+
[incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: usage["input_tokens"],
|
|
427
|
+
[incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: usage["output_tokens"],
|
|
428
|
+
[aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS]: (usage["input_tokens"] || 0) + (usage["output_tokens"] || 0),
|
|
429
|
+
}
|
|
430
|
+
: {}));
|
|
278
431
|
if (!this._shouldSendPrompts()) {
|
|
279
432
|
return baseAttributes;
|
|
280
433
|
}
|
|
281
434
|
// Handle new messages API format response
|
|
282
435
|
if (response["content"]) {
|
|
283
436
|
const content = Array.isArray(response["content"])
|
|
284
|
-
? response["content"]
|
|
437
|
+
? response["content"]
|
|
285
438
|
: response["content"];
|
|
286
|
-
return Object.assign(Object.assign({}, baseAttributes), { [
|
|
439
|
+
return Object.assign(Object.assign({}, baseAttributes), { [incubating.ATTR_GEN_AI_OUTPUT_MESSAGES]: instrumentationUtils.formatOutputMessage(content, stopReason, bedrockFinishReasonMap, incubating.GEN_AI_OPERATION_NAME_VALUE_CHAT, instrumentationUtils.mapBedrockContentBlock) });
|
|
287
440
|
}
|
|
288
441
|
// Handle legacy completion format
|
|
289
442
|
if (response["completion"]) {
|
|
290
|
-
return Object.assign(Object.assign({}, baseAttributes), { [
|
|
443
|
+
return Object.assign(Object.assign({}, baseAttributes), { [incubating.ATTR_GEN_AI_OUTPUT_MESSAGES]: instrumentationUtils.formatOutputMessage(response["completion"], stopReason, bedrockFinishReasonMap, incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION, instrumentationUtils.mapBedrockContentBlock) });
|
|
291
444
|
}
|
|
292
445
|
return baseAttributes;
|
|
293
446
|
}
|
|
294
|
-
case
|
|
295
|
-
const
|
|
447
|
+
case exports.BedrockVendor.COHERE: {
|
|
448
|
+
const cohereFinishReason = (_2 = (_1 = (_0 = response["generations"]) === null || _0 === void 0 ? void 0 : _0[0]) === null || _1 === void 0 ? void 0 : _1["finish_reason"]) !== null && _2 !== void 0 ? _2 : response["finish_reason"];
|
|
449
|
+
const cohereText = (_5 = (_4 = (_3 = response["generations"]) === null || _3 === void 0 ? void 0 : _3[0]) === null || _4 === void 0 ? void 0 : _4["text"]) !== null && _5 !== void 0 ? _5 : response["text"];
|
|
450
|
+
return Object.assign(Object.assign(Object.assign({}, (cohereFinishReason != null
|
|
296
451
|
? {
|
|
297
|
-
[
|
|
452
|
+
[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
453
|
+
(_6 = bedrockFinishReasonMap[cohereFinishReason]) !== null && _6 !== void 0 ? _6 : cohereFinishReason,
|
|
454
|
+
],
|
|
455
|
+
}
|
|
456
|
+
: {})), (((_7 = response["meta"]) === null || _7 === void 0 ? void 0 : _7["billed_units"])
|
|
457
|
+
? {
|
|
458
|
+
[incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: response["meta"]["billed_units"]["input_tokens"],
|
|
459
|
+
[incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: response["meta"]["billed_units"]["output_tokens"],
|
|
460
|
+
[aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS]: (response["meta"]["billed_units"]["input_tokens"] || 0) +
|
|
461
|
+
(response["meta"]["billed_units"]["output_tokens"] || 0),
|
|
462
|
+
}
|
|
463
|
+
: {})), (this._shouldSendPrompts() && cohereText != null
|
|
464
|
+
? {
|
|
465
|
+
[incubating.ATTR_GEN_AI_OUTPUT_MESSAGES]: instrumentationUtils.formatOutputMessage(cohereText, cohereFinishReason, bedrockFinishReasonMap, incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION, instrumentationUtils.mapBedrockContentBlock),
|
|
298
466
|
}
|
|
299
467
|
: {}));
|
|
300
|
-
// Add token usage if available
|
|
301
|
-
if (response["meta"] && response["meta"]["billed_units"]) {
|
|
302
|
-
const billedUnits = response["meta"]["billed_units"];
|
|
303
|
-
return Object.assign(Object.assign({}, baseAttributes), { [incubating.ATTR_GEN_AI_USAGE_PROMPT_TOKENS]: billedUnits["input_tokens"], [incubating.ATTR_GEN_AI_USAGE_COMPLETION_TOKENS]: billedUnits["output_tokens"], [aiSemanticConventions.SpanAttributes.LLM_USAGE_TOTAL_TOKENS]: (billedUnits["input_tokens"] || 0) +
|
|
304
|
-
(billedUnits["output_tokens"] || 0) });
|
|
305
|
-
}
|
|
306
|
-
return baseAttributes;
|
|
307
468
|
}
|
|
308
|
-
case
|
|
309
|
-
|
|
469
|
+
case exports.BedrockVendor.META: {
|
|
470
|
+
const metaFinishReason = response["stop_reason"];
|
|
471
|
+
const metaContent = response["generation"];
|
|
472
|
+
return Object.assign(Object.assign(Object.assign({}, (metaFinishReason != null
|
|
473
|
+
? {
|
|
474
|
+
[incubating.ATTR_GEN_AI_RESPONSE_FINISH_REASONS]: [
|
|
475
|
+
(_8 = bedrockFinishReasonMap[metaFinishReason]) !== null && _8 !== void 0 ? _8 : metaFinishReason,
|
|
476
|
+
],
|
|
477
|
+
}
|
|
478
|
+
: {})), { [incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS]: response["prompt_token_count"], [incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]: response["generation_token_count"], [aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS]: response["prompt_token_count"] + response["generation_token_count"] }), (this._shouldSendPrompts()
|
|
310
479
|
? {
|
|
311
|
-
[
|
|
480
|
+
[incubating.ATTR_GEN_AI_OUTPUT_MESSAGES]: instrumentationUtils.formatOutputMessage(metaContent !== null && metaContent !== void 0 ? metaContent : "", metaFinishReason, bedrockFinishReasonMap, incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION, instrumentationUtils.mapBedrockContentBlock),
|
|
312
481
|
}
|
|
313
482
|
: {}));
|
|
314
483
|
}
|
|
@@ -316,6 +485,15 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
316
485
|
return {};
|
|
317
486
|
}
|
|
318
487
|
}
|
|
488
|
+
_handleNovaStreamingMetadata(span, parsedResponse) {
|
|
489
|
+
var _a;
|
|
490
|
+
if ("metadata" in parsedResponse && ((_a = parsedResponse["metadata"]) === null || _a === void 0 ? void 0 : _a["usage"])) {
|
|
491
|
+
const usage = parsedResponse["metadata"]["usage"];
|
|
492
|
+
span.setAttribute(incubating.ATTR_GEN_AI_USAGE_INPUT_TOKENS, usage["inputTokens"]);
|
|
493
|
+
span.setAttribute(incubating.ATTR_GEN_AI_USAGE_OUTPUT_TOKENS, usage["outputTokens"]);
|
|
494
|
+
span.setAttribute(aiSemanticConventions.SpanAttributes.GEN_AI_USAGE_TOTAL_TOKENS, usage["totalTokens"]);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
319
497
|
_shouldSendPrompts() {
|
|
320
498
|
const contextShouldSendPrompts = api.context
|
|
321
499
|
.active()
|
|
@@ -327,17 +505,63 @@ class BedrockInstrumentation extends instrumentation.InstrumentationBase {
|
|
|
327
505
|
? this._config.traceContent
|
|
328
506
|
: true;
|
|
329
507
|
}
|
|
508
|
+
_getOperationType(vendor, requestBody) {
|
|
509
|
+
switch (vendor) {
|
|
510
|
+
case exports.BedrockVendor.AI21:
|
|
511
|
+
case exports.BedrockVendor.AMAZON:
|
|
512
|
+
case exports.BedrockVendor.ANTHROPIC:
|
|
513
|
+
return requestBody["messages"]
|
|
514
|
+
? incubating.GEN_AI_OPERATION_NAME_VALUE_CHAT
|
|
515
|
+
: incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION;
|
|
516
|
+
case exports.BedrockVendor.COHERE:
|
|
517
|
+
case exports.BedrockVendor.META:
|
|
518
|
+
return incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION;
|
|
519
|
+
default:
|
|
520
|
+
return incubating.GEN_AI_OPERATION_NAME_VALUE_TEXT_COMPLETION;
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
_getStreamChunkContent(vendor, response) {
|
|
524
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
525
|
+
switch (vendor) {
|
|
526
|
+
case exports.BedrockVendor.AMAZON:
|
|
527
|
+
return ((_c = (_b = (_a = response["contentBlockDelta"]) === null || _a === void 0 ? void 0 : _a["delta"]) === null || _b === void 0 ? void 0 : _b["text"]) !== null && _c !== void 0 ? _c : response["outputText"]);
|
|
528
|
+
case exports.BedrockVendor.ANTHROPIC:
|
|
529
|
+
return (_e = (_d = response["delta"]) === null || _d === void 0 ? void 0 : _d["text"]) !== null && _e !== void 0 ? _e : response["completion"];
|
|
530
|
+
case exports.BedrockVendor.AI21:
|
|
531
|
+
return (_h = (_g = (_f = response["choices"]) === null || _f === void 0 ? void 0 : _f[0]) === null || _g === void 0 ? void 0 : _g["delta"]) === null || _h === void 0 ? void 0 : _h["content"];
|
|
532
|
+
case exports.BedrockVendor.META:
|
|
533
|
+
return response["generation"];
|
|
534
|
+
default:
|
|
535
|
+
return undefined;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
330
538
|
_extractVendorAndModel(modelId) {
|
|
331
539
|
if (!modelId) {
|
|
332
540
|
return { modelVendor: "", model: "" };
|
|
333
541
|
}
|
|
334
|
-
|
|
542
|
+
// Handle cross-region inference profile IDs like "us.anthropic.claude-3-5-sonnet-20241022-v2:0"
|
|
543
|
+
// Mirrors Python's _cross_region_check logic.
|
|
544
|
+
const prefixes = ["us", "us-gov", "eu", "apac"];
|
|
545
|
+
const hasCrossRegionPrefix = prefixes.some((prefix) => modelId.startsWith(prefix + "."));
|
|
546
|
+
if (hasCrossRegionPrefix) {
|
|
547
|
+
const parts = modelId.split(".");
|
|
548
|
+
if (parts.length > 2) {
|
|
549
|
+
parts.shift(); // remove region prefix ("us", "eu", etc.)
|
|
550
|
+
}
|
|
551
|
+
return { modelVendor: parts[0] || "", model: parts[1] || "" };
|
|
552
|
+
}
|
|
553
|
+
// Standard format: "vendor.model-name"
|
|
554
|
+
const dotIndex = modelId.indexOf(".");
|
|
555
|
+
if (dotIndex === -1) {
|
|
556
|
+
return { modelVendor: modelId, model: "" };
|
|
557
|
+
}
|
|
335
558
|
return {
|
|
336
|
-
modelVendor:
|
|
337
|
-
model:
|
|
559
|
+
modelVendor: modelId.slice(0, dotIndex),
|
|
560
|
+
model: modelId.slice(dotIndex + 1),
|
|
338
561
|
};
|
|
339
562
|
}
|
|
340
563
|
}
|
|
341
564
|
|
|
342
565
|
exports.BedrockInstrumentation = BedrockInstrumentation;
|
|
566
|
+
exports.bedrockFinishReasonMap = bedrockFinishReasonMap;
|
|
343
567
|
//# sourceMappingURL=index.js.map
|