@arizeai/openinference-instrumentation-openai 1.1.2 → 2.0.1

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.
@@ -1,123 +1,16 @@
1
- var __extends = (this && this.__extends) || (function () {
2
- var extendStatics = function (d, b) {
3
- extendStatics = Object.setPrototypeOf ||
4
- ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5
- function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6
- return extendStatics(d, b);
7
- };
8
- return function (d, b) {
9
- if (typeof b !== "function" && b !== null)
10
- throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
11
- extendStatics(d, b);
12
- function __() { this.constructor = d; }
13
- d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14
- };
15
- })();
16
- var __assign = (this && this.__assign) || function () {
17
- __assign = Object.assign || function(t) {
18
- for (var s, i = 1, n = arguments.length; i < n; i++) {
19
- s = arguments[i];
20
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
21
- t[p] = s[p];
22
- }
23
- return t;
24
- };
25
- return __assign.apply(this, arguments);
26
- };
27
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
28
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
29
- return new (P || (P = Promise))(function (resolve, reject) {
30
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
31
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
32
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
33
- step((generator = generator.apply(thisArg, _arguments || [])).next());
34
- });
35
- };
36
- var __generator = (this && this.__generator) || function (thisArg, body) {
37
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
38
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
39
- function verb(n) { return function (v) { return step([n, v]); }; }
40
- function step(op) {
41
- if (f) throw new TypeError("Generator is already executing.");
42
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
43
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
44
- if (y = 0, t) op = [op[0] & 2, t.value];
45
- switch (op[0]) {
46
- case 0: case 1: t = op; break;
47
- case 4: _.label++; return { value: op[1], done: false };
48
- case 5: _.label++; y = op[1]; op = [0]; continue;
49
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
50
- default:
51
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
52
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
53
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
54
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
55
- if (t[2]) _.ops.pop();
56
- _.trys.pop(); continue;
57
- }
58
- op = body.call(thisArg, _);
59
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
60
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
61
- }
62
- };
63
- var __rest = (this && this.__rest) || function (s, e) {
64
- var t = {};
65
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
66
- t[p] = s[p];
67
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
68
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
69
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
70
- t[p[i]] = s[p[i]];
71
- }
72
- return t;
73
- };
74
- var __asyncValues = (this && this.__asyncValues) || function (o) {
75
- if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
76
- var m = o[Symbol.asyncIterator], i;
77
- return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
78
- function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
79
- function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
80
- };
81
- var __read = (this && this.__read) || function (o, n) {
82
- var m = typeof Symbol === "function" && o[Symbol.iterator];
83
- if (!m) return o;
84
- var i = m.call(o), r, ar = [], e;
85
- try {
86
- while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
87
- }
88
- catch (error) { e = { error: error }; }
89
- finally {
90
- try {
91
- if (r && !r.done && (m = i["return"])) m.call(i);
92
- }
93
- finally { if (e) throw e.error; }
94
- }
95
- return ar;
96
- };
97
- var __values = (this && this.__values) || function(o) {
98
- var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
99
- if (m) return m.call(o);
100
- if (o && typeof o.length === "number") return {
101
- next: function () {
102
- if (o && i >= o.length) o = void 0;
103
- return { value: o && o[i++], done: !o };
104
- }
105
- };
106
- throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
107
- };
108
1
  import { InstrumentationBase, InstrumentationNodeModuleDefinition, safeExecuteInTheMiddle, } from "@opentelemetry/instrumentation";
109
2
  import { diag, context, trace, SpanKind, SpanStatusCode, } from "@opentelemetry/api";
110
- import { VERSION } from "./version";
3
+ import { VERSION } from "./version.js";
111
4
  import { SemanticConventions, OpenInferenceSpanKind, MimeType, LLMSystem, LLMProvider, } from "@arizeai/openinference-semantic-conventions";
112
- import { assertUnreachable, isString } from "./typeUtils";
5
+ import { assertUnreachable, isString } from "./typeUtils.js";
113
6
  import { isTracingSuppressed } from "@opentelemetry/core";
114
7
  import { OITracer, safelyJSONStringify, } from "@arizeai/openinference-core";
115
- var MODULE_NAME = "openai";
8
+ const MODULE_NAME = "openai";
116
9
  /**
117
10
  * Flag to check if the openai module has been patched
118
11
  * Note: This is a fallback in case the module is made immutable (e.x. Deno, webpack, etc.)
119
12
  */
120
- var _isOpenInferencePatched = false;
13
+ let _isOpenInferencePatched = false;
121
14
  /**
122
15
  * function to check if instrumentation is enabled / disabled
123
16
  */
@@ -130,9 +23,9 @@ export function isPatched() {
130
23
  * @param span
131
24
  */
132
25
  function getExecContext(span) {
133
- var activeContext = context.active();
134
- var suppressTracing = isTracingSuppressed(activeContext);
135
- var execContext = suppressTracing
26
+ const activeContext = context.active();
27
+ const suppressTracing = isTracingSuppressed(activeContext);
28
+ const execContext = suppressTracing
136
29
  ? trace.setSpan(context.active(), span)
137
30
  : activeContext;
138
31
  // Drop the span from the context
@@ -146,59 +39,60 @@ function getExecContext(span) {
146
39
  * @param instrumentationConfig The config for the instrumentation @see {@link InstrumentationConfig}
147
40
  * @param traceConfig The OpenInference trace configuration. Can be used to mask or redact sensitive information on spans. @see {@link TraceConfigOptions}
148
41
  */
149
- var OpenAIInstrumentation = /** @class */ (function (_super) {
150
- __extends(OpenAIInstrumentation, _super);
151
- function OpenAIInstrumentation(_a) {
152
- var _b = _a === void 0 ? {} : _a, instrumentationConfig = _b.instrumentationConfig, traceConfig = _b.traceConfig;
153
- var _this = _super.call(this, "@arizeai/openinference-instrumentation-openai", VERSION, Object.assign({}, instrumentationConfig)) || this;
154
- _this.oiTracer = new OITracer({ tracer: _this.tracer, traceConfig: traceConfig });
155
- return _this;
42
+ export class OpenAIInstrumentation extends InstrumentationBase {
43
+ constructor({ instrumentationConfig, traceConfig, } = {}) {
44
+ super("@arizeai/openinference-instrumentation-openai", VERSION, Object.assign({}, instrumentationConfig));
45
+ this.oiTracer = new OITracer({ tracer: this.tracer, traceConfig });
156
46
  }
157
- OpenAIInstrumentation.prototype.init = function () {
158
- var module = new InstrumentationNodeModuleDefinition("openai", ["^4.0.0"], this.patch.bind(this), this.unpatch.bind(this));
47
+ init() {
48
+ const module = new InstrumentationNodeModuleDefinition("openai", ["^4.0.0"], this.patch.bind(this), this.unpatch.bind(this));
159
49
  return module;
160
- };
50
+ }
161
51
  /**
162
52
  * Manually instruments the OpenAI module. This is needed when the module is not loaded via require (commonjs)
163
53
  * @param {openai} module
164
54
  */
165
- OpenAIInstrumentation.prototype.manuallyInstrument = function (module) {
166
- diag.debug("Manually instrumenting ".concat(MODULE_NAME));
55
+ manuallyInstrument(module) {
56
+ diag.debug(`Manually instrumenting ${MODULE_NAME}`);
167
57
  this.patch(module);
168
- };
58
+ }
169
59
  /**
170
60
  * Patches the OpenAI module
171
61
  */
172
- OpenAIInstrumentation.prototype.patch = function (module, moduleVersion) {
173
- diag.debug("Applying patch for ".concat(MODULE_NAME, "@").concat(moduleVersion));
174
- if ((module === null || module === void 0 ? void 0 : module.openInferencePatched) || _isOpenInferencePatched) {
62
+ patch(module, moduleVersion) {
63
+ diag.debug(`Applying patch for ${MODULE_NAME}@${moduleVersion}`);
64
+ if (module?.openInferencePatched || _isOpenInferencePatched) {
175
65
  return module;
176
66
  }
177
67
  // eslint-disable-next-line @typescript-eslint/no-this-alias
178
- var instrumentation = this;
68
+ const instrumentation = this;
179
69
  // Patch create chat completions
180
70
  this._wrap(module.OpenAI.Chat.Completions.prototype, "create",
181
71
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
182
- function (original) {
183
- return function patchedCreate() {
184
- var _a;
185
- var _this = this;
186
- var args = [];
187
- for (var _i = 0; _i < arguments.length; _i++) {
188
- args[_i] = arguments[_i];
189
- }
190
- var body = args[0];
191
- var _messages = body.messages, invocationParameters = __rest(body, ["messages"]);
192
- var span = instrumentation.oiTracer.startSpan("OpenAI Chat Completions", {
72
+ (original) => {
73
+ return function patchedCreate(...args) {
74
+ const body = args[0];
75
+ const { messages: _messages, ...invocationParameters } = body;
76
+ const span = instrumentation.oiTracer.startSpan(`OpenAI Chat Completions`, {
193
77
  kind: SpanKind.INTERNAL,
194
- attributes: __assign(__assign((_a = {}, _a[SemanticConventions.OPENINFERENCE_SPAN_KIND] = OpenInferenceSpanKind.LLM, _a[SemanticConventions.LLM_MODEL_NAME] = body.model, _a[SemanticConventions.INPUT_VALUE] = JSON.stringify(body), _a[SemanticConventions.INPUT_MIME_TYPE] = MimeType.JSON, _a[SemanticConventions.LLM_INVOCATION_PARAMETERS] = JSON.stringify(invocationParameters), _a[SemanticConventions.LLM_SYSTEM] = LLMSystem.OPENAI, _a[SemanticConventions.LLM_PROVIDER] = LLMProvider.OPENAI, _a), getLLMInputMessagesAttributes(body)), getLLMToolsJSONSchema(body)),
78
+ attributes: {
79
+ [SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.LLM,
80
+ [SemanticConventions.LLM_MODEL_NAME]: body.model,
81
+ [SemanticConventions.INPUT_VALUE]: JSON.stringify(body),
82
+ [SemanticConventions.INPUT_MIME_TYPE]: MimeType.JSON,
83
+ [SemanticConventions.LLM_INVOCATION_PARAMETERS]: JSON.stringify(invocationParameters),
84
+ [SemanticConventions.LLM_SYSTEM]: LLMSystem.OPENAI,
85
+ [SemanticConventions.LLM_PROVIDER]: LLMProvider.OPENAI,
86
+ ...getLLMInputMessagesAttributes(body),
87
+ ...getLLMToolsJSONSchema(body),
88
+ },
195
89
  });
196
- var execContext = getExecContext(span);
197
- var execPromise = safeExecuteInTheMiddle(function () {
198
- return context.with(trace.setSpan(execContext, span), function () {
199
- return original.apply(_this, args);
90
+ const execContext = getExecContext(span);
91
+ const execPromise = safeExecuteInTheMiddle(() => {
92
+ return context.with(trace.setSpan(execContext, span), () => {
93
+ return original.apply(this, args);
200
94
  });
201
- }, function (error) {
95
+ }, (error) => {
202
96
  // Push the error to the span
203
97
  if (error) {
204
98
  span.recordException(error);
@@ -209,11 +103,17 @@ var OpenAIInstrumentation = /** @class */ (function (_super) {
209
103
  span.end();
210
104
  }
211
105
  });
212
- var wrappedPromise = execPromise.then(function (result) {
213
- var _a;
106
+ const wrappedPromise = execPromise.then((result) => {
214
107
  if (isChatCompletionResponse(result)) {
215
108
  // Record the results
216
- span.setAttributes(__assign(__assign((_a = {}, _a[SemanticConventions.OUTPUT_VALUE] = JSON.stringify(result), _a[SemanticConventions.OUTPUT_MIME_TYPE] = MimeType.JSON, _a[SemanticConventions.LLM_MODEL_NAME] = result.model, _a), getChatCompletionLLMOutputMessagesAttributes(result)), getUsageAttributes(result)));
109
+ span.setAttributes({
110
+ [SemanticConventions.OUTPUT_VALUE]: JSON.stringify(result),
111
+ [SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
112
+ // Override the model from the value sent by the server
113
+ [SemanticConventions.LLM_MODEL_NAME]: result.model,
114
+ ...getChatCompletionLLMOutputMessagesAttributes(result),
115
+ ...getUsageAttributes(result),
116
+ });
217
117
  span.setStatus({ code: SpanStatusCode.OK });
218
118
  span.end();
219
119
  }
@@ -221,7 +121,7 @@ var OpenAIInstrumentation = /** @class */ (function (_super) {
221
121
  // This is a streaming response
222
122
  // handle the chunks and add them to the span
223
123
  // First split the stream via tee
224
- var _b = __read(result.tee(), 2), leftStream = _b[0], rightStream = _b[1];
124
+ const [leftStream, rightStream] = result.tee();
225
125
  consumeChatCompletionStreamChunks(rightStream, span);
226
126
  result = leftStream;
227
127
  }
@@ -232,26 +132,27 @@ var OpenAIInstrumentation = /** @class */ (function (_super) {
232
132
  });
233
133
  this._wrap(module.OpenAI.Completions.prototype, "create",
234
134
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
235
- function (original) {
236
- return function patchedCreate() {
237
- var _a;
238
- var _this = this;
239
- var args = [];
240
- for (var _i = 0; _i < arguments.length; _i++) {
241
- args[_i] = arguments[_i];
242
- }
243
- var body = args[0];
244
- var _prompt = body.prompt, invocationParameters = __rest(body, ["prompt"]);
245
- var span = instrumentation.oiTracer.startSpan("OpenAI Completions", {
135
+ (original) => {
136
+ return function patchedCreate(...args) {
137
+ const body = args[0];
138
+ const { prompt: _prompt, ...invocationParameters } = body;
139
+ const span = instrumentation.oiTracer.startSpan(`OpenAI Completions`, {
246
140
  kind: SpanKind.INTERNAL,
247
- attributes: __assign((_a = {}, _a[SemanticConventions.OPENINFERENCE_SPAN_KIND] = OpenInferenceSpanKind.LLM, _a[SemanticConventions.LLM_MODEL_NAME] = body.model, _a[SemanticConventions.LLM_INVOCATION_PARAMETERS] = JSON.stringify(invocationParameters), _a[SemanticConventions.LLM_SYSTEM] = LLMSystem.OPENAI, _a[SemanticConventions.LLM_PROVIDER] = LLMProvider.OPENAI, _a), getCompletionInputValueAndMimeType(body)),
141
+ attributes: {
142
+ [SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.LLM,
143
+ [SemanticConventions.LLM_MODEL_NAME]: body.model,
144
+ [SemanticConventions.LLM_INVOCATION_PARAMETERS]: JSON.stringify(invocationParameters),
145
+ [SemanticConventions.LLM_SYSTEM]: LLMSystem.OPENAI,
146
+ [SemanticConventions.LLM_PROVIDER]: LLMProvider.OPENAI,
147
+ ...getCompletionInputValueAndMimeType(body),
148
+ },
248
149
  });
249
- var execContext = getExecContext(span);
250
- var execPromise = safeExecuteInTheMiddle(function () {
251
- return context.with(trace.setSpan(execContext, span), function () {
252
- return original.apply(_this, args);
150
+ const execContext = getExecContext(span);
151
+ const execPromise = safeExecuteInTheMiddle(() => {
152
+ return context.with(trace.setSpan(execContext, span), () => {
153
+ return original.apply(this, args);
253
154
  });
254
- }, function (error) {
155
+ }, (error) => {
255
156
  // Push the error to the span
256
157
  if (error) {
257
158
  span.recordException(error);
@@ -262,11 +163,17 @@ var OpenAIInstrumentation = /** @class */ (function (_super) {
262
163
  span.end();
263
164
  }
264
165
  });
265
- var wrappedPromise = execPromise.then(function (result) {
266
- var _a;
166
+ const wrappedPromise = execPromise.then((result) => {
267
167
  if (isCompletionResponse(result)) {
268
168
  // Record the results
269
- span.setAttributes(__assign(__assign((_a = {}, _a[SemanticConventions.OUTPUT_VALUE] = JSON.stringify(result), _a[SemanticConventions.OUTPUT_MIME_TYPE] = MimeType.JSON, _a[SemanticConventions.LLM_MODEL_NAME] = result.model, _a), getCompletionOutputValueAndMimeType(result)), getUsageAttributes(result)));
169
+ span.setAttributes({
170
+ [SemanticConventions.OUTPUT_VALUE]: JSON.stringify(result),
171
+ [SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.JSON,
172
+ // Override the model from the value sent by the server
173
+ [SemanticConventions.LLM_MODEL_NAME]: result.model,
174
+ ...getCompletionOutputValueAndMimeType(result),
175
+ ...getUsageAttributes(result),
176
+ });
270
177
  span.setStatus({ code: SpanStatusCode.OK });
271
178
  span.end();
272
179
  }
@@ -277,31 +184,31 @@ var OpenAIInstrumentation = /** @class */ (function (_super) {
277
184
  });
278
185
  this._wrap(module.OpenAI.Embeddings.prototype, "create",
279
186
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
280
- function (original) {
281
- return function patchedEmbeddingCreate() {
282
- var _a;
283
- var _this = this;
284
- var args = [];
285
- for (var _i = 0; _i < arguments.length; _i++) {
286
- args[_i] = arguments[_i];
287
- }
288
- var body = args[0];
289
- var input = body.input;
290
- var isStringInput = typeof input === "string";
291
- var span = instrumentation.oiTracer.startSpan("OpenAI Embeddings", {
187
+ (original) => {
188
+ return function patchedEmbeddingCreate(...args) {
189
+ const body = args[0];
190
+ const { input } = body;
191
+ const isStringInput = typeof input === "string";
192
+ const span = instrumentation.oiTracer.startSpan(`OpenAI Embeddings`, {
292
193
  kind: SpanKind.INTERNAL,
293
- attributes: __assign((_a = {}, _a[SemanticConventions.OPENINFERENCE_SPAN_KIND] = OpenInferenceSpanKind.EMBEDDING, _a[SemanticConventions.EMBEDDING_MODEL_NAME] = body.model, _a[SemanticConventions.INPUT_VALUE] = isStringInput
294
- ? input
295
- : JSON.stringify(input), _a[SemanticConventions.INPUT_MIME_TYPE] = isStringInput
296
- ? MimeType.TEXT
297
- : MimeType.JSON, _a), getEmbeddingTextAttributes(body)),
194
+ attributes: {
195
+ [SemanticConventions.OPENINFERENCE_SPAN_KIND]: OpenInferenceSpanKind.EMBEDDING,
196
+ [SemanticConventions.EMBEDDING_MODEL_NAME]: body.model,
197
+ [SemanticConventions.INPUT_VALUE]: isStringInput
198
+ ? input
199
+ : JSON.stringify(input),
200
+ [SemanticConventions.INPUT_MIME_TYPE]: isStringInput
201
+ ? MimeType.TEXT
202
+ : MimeType.JSON,
203
+ ...getEmbeddingTextAttributes(body),
204
+ },
298
205
  });
299
- var execContext = getExecContext(span);
300
- var execPromise = safeExecuteInTheMiddle(function () {
301
- return context.with(trace.setSpan(execContext, span), function () {
302
- return original.apply(_this, args);
206
+ const execContext = getExecContext(span);
207
+ const execPromise = safeExecuteInTheMiddle(() => {
208
+ return context.with(trace.setSpan(execContext, span), () => {
209
+ return original.apply(this, args);
303
210
  });
304
- }, function (error) {
211
+ }, (error) => {
305
212
  // Push the error to the span
306
213
  if (error) {
307
214
  span.recordException(error);
@@ -312,10 +219,13 @@ var OpenAIInstrumentation = /** @class */ (function (_super) {
312
219
  span.end();
313
220
  }
314
221
  });
315
- var wrappedPromise = execPromise.then(function (result) {
222
+ const wrappedPromise = execPromise.then((result) => {
316
223
  if (result) {
317
224
  // Record the results
318
- span.setAttributes(__assign({}, getEmbeddingEmbeddingsAttributes(result)));
225
+ span.setAttributes({
226
+ // Do not record the output data as it can be large
227
+ ...getEmbeddingEmbeddingsAttributes(result),
228
+ });
319
229
  }
320
230
  span.setStatus({ code: SpanStatusCode.OK });
321
231
  span.end();
@@ -330,15 +240,15 @@ var OpenAIInstrumentation = /** @class */ (function (_super) {
330
240
  module.openInferencePatched = true;
331
241
  }
332
242
  catch (e) {
333
- diag.debug("Failed to set ".concat(MODULE_NAME, " patched flag on the module"), e);
243
+ diag.debug(`Failed to set ${MODULE_NAME} patched flag on the module`, e);
334
244
  }
335
245
  return module;
336
- };
246
+ }
337
247
  /**
338
248
  * Un-patches the OpenAI module's chat completions API
339
249
  */
340
- OpenAIInstrumentation.prototype.unpatch = function (moduleExports, moduleVersion) {
341
- diag.debug("Removing patch for ".concat(MODULE_NAME, "@").concat(moduleVersion));
250
+ unpatch(moduleExports, moduleVersion) {
251
+ diag.debug(`Removing patch for ${MODULE_NAME}@${moduleVersion}`);
342
252
  this._unwrap(moduleExports.OpenAI.Chat.Completions.prototype, "create");
343
253
  this._unwrap(moduleExports.OpenAI.Completions.prototype, "create");
344
254
  this._unwrap(moduleExports.OpenAI.Embeddings.prototype, "create");
@@ -348,12 +258,10 @@ var OpenAIInstrumentation = /** @class */ (function (_super) {
348
258
  moduleExports.openInferencePatched = false;
349
259
  }
350
260
  catch (e) {
351
- diag.warn("Failed to unset ".concat(MODULE_NAME, " patched flag on the module"), e);
261
+ diag.warn(`Failed to unset ${MODULE_NAME} patched flag on the module`, e);
352
262
  }
353
- };
354
- return OpenAIInstrumentation;
355
- }(InstrumentationBase));
356
- export { OpenAIInstrumentation };
263
+ }
264
+ }
357
265
  /**
358
266
  * type-guard that checks if the response is a chat completion response
359
267
  */
@@ -370,29 +278,18 @@ function isCompletionResponse(response) {
370
278
  * type-guard that checks if completion prompt attribute is an array of strings
371
279
  */
372
280
  function isPromptStringArray(prompt) {
373
- return (Array.isArray(prompt) && prompt.every(function (item) { return typeof item === "string"; }));
281
+ return (Array.isArray(prompt) && prompt.every((item) => typeof item === "string"));
374
282
  }
375
283
  /**
376
284
  * Converts the body of a chat completions request to LLM input messages
377
285
  */
378
286
  function getLLMInputMessagesAttributes(body) {
379
- return body.messages.reduce(function (acc, message, index) {
380
- var e_1, _a;
381
- var messageAttributes = getChatCompletionInputMessageAttributes(message);
382
- var indexPrefix = "".concat(SemanticConventions.LLM_INPUT_MESSAGES, ".").concat(index, ".");
383
- try {
384
- // Flatten the attributes on the index prefix
385
- for (var _b = __values(Object.entries(messageAttributes)), _c = _b.next(); !_c.done; _c = _b.next()) {
386
- var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
387
- acc["".concat(indexPrefix).concat(key)] = value;
388
- }
389
- }
390
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
391
- finally {
392
- try {
393
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
394
- }
395
- finally { if (e_1) throw e_1.error; }
287
+ return body.messages.reduce((acc, message, index) => {
288
+ const messageAttributes = getChatCompletionInputMessageAttributes(message);
289
+ const indexPrefix = `${SemanticConventions.LLM_INPUT_MESSAGES}.${index}.`;
290
+ // Flatten the attributes on the index prefix
291
+ for (const [key, value] of Object.entries(messageAttributes)) {
292
+ acc[`${indexPrefix}${key}`] = value;
396
293
  }
397
294
  return acc;
398
295
  }, {});
@@ -405,9 +302,9 @@ function getLLMToolsJSONSchema(body) {
405
302
  // If tools is undefined, return an empty object
406
303
  return {};
407
304
  }
408
- return body.tools.reduce(function (acc, tool, index) {
409
- var toolJsonSchema = safelyJSONStringify(tool);
410
- var key = "".concat(SemanticConventions.LLM_TOOLS, ".").concat(index, ".").concat(SemanticConventions.TOOL_JSON_SCHEMA);
305
+ return body.tools.reduce((acc, tool, index) => {
306
+ const toolJsonSchema = safelyJSONStringify(tool);
307
+ const key = `${SemanticConventions.LLM_TOOLS}.${index}.${SemanticConventions.TOOL_JSON_SCHEMA}`;
411
308
  if (toolJsonSchema) {
412
309
  acc[key] = toolJsonSchema;
413
310
  }
@@ -415,25 +312,24 @@ function getLLMToolsJSONSchema(body) {
415
312
  }, {});
416
313
  }
417
314
  function getChatCompletionInputMessageAttributes(message) {
418
- var _a;
419
- var role = message.role;
420
- var attributes = (_a = {},
421
- _a[SemanticConventions.MESSAGE_ROLE] = role,
422
- _a);
315
+ const role = message.role;
316
+ const attributes = {
317
+ [SemanticConventions.MESSAGE_ROLE]: role,
318
+ };
423
319
  // Add the content only if it is a string
424
320
  if (typeof message.content === "string") {
425
321
  attributes[SemanticConventions.MESSAGE_CONTENT] = message.content;
426
322
  }
427
323
  else if (Array.isArray(message.content)) {
428
- message.content.forEach(function (part, index) {
429
- var contentsIndexPrefix = "".concat(SemanticConventions.MESSAGE_CONTENTS, ".").concat(index, ".");
324
+ message.content.forEach((part, index) => {
325
+ const contentsIndexPrefix = `${SemanticConventions.MESSAGE_CONTENTS}.${index}.`;
430
326
  if (part.type === "text") {
431
- attributes["".concat(contentsIndexPrefix).concat(SemanticConventions.MESSAGE_CONTENT_TYPE)] = "text";
432
- attributes["".concat(contentsIndexPrefix).concat(SemanticConventions.MESSAGE_CONTENT_TEXT)] = part.text;
327
+ attributes[`${contentsIndexPrefix}${SemanticConventions.MESSAGE_CONTENT_TYPE}`] = "text";
328
+ attributes[`${contentsIndexPrefix}${SemanticConventions.MESSAGE_CONTENT_TEXT}`] = part.text;
433
329
  }
434
330
  else if (part.type === "image_url") {
435
- attributes["".concat(contentsIndexPrefix).concat(SemanticConventions.MESSAGE_CONTENT_TYPE)] = "image";
436
- attributes["".concat(contentsIndexPrefix).concat(SemanticConventions.MESSAGE_CONTENT_IMAGE)] = part.image_url.url;
331
+ attributes[`${contentsIndexPrefix}${SemanticConventions.MESSAGE_CONTENT_TYPE}`] = "image";
332
+ attributes[`${contentsIndexPrefix}${SemanticConventions.MESSAGE_CONTENT_IMAGE}`] = part.image_url.url;
437
333
  }
438
334
  });
439
335
  }
@@ -443,16 +339,16 @@ function getChatCompletionInputMessageAttributes(message) {
443
339
  break;
444
340
  case "assistant":
445
341
  if (message.tool_calls) {
446
- message.tool_calls.forEach(function (toolCall, index) {
447
- var toolCallIndexPrefix = "".concat(SemanticConventions.MESSAGE_TOOL_CALLS, ".").concat(index, ".");
342
+ message.tool_calls.forEach((toolCall, index) => {
343
+ const toolCallIndexPrefix = `${SemanticConventions.MESSAGE_TOOL_CALLS}.${index}.`;
448
344
  // Add the tool call id if it exists
449
345
  if (toolCall.id) {
450
- attributes["".concat(toolCallIndexPrefix).concat(SemanticConventions.TOOL_CALL_ID)] = toolCall.id;
346
+ attributes[`${toolCallIndexPrefix}${SemanticConventions.TOOL_CALL_ID}`] = toolCall.id;
451
347
  }
452
348
  // Make sure the tool call has a function
453
349
  if (toolCall.function) {
454
- attributes["".concat(toolCallIndexPrefix).concat(SemanticConventions.TOOL_CALL_FUNCTION_NAME)] = toolCall.function.name;
455
- attributes["".concat(toolCallIndexPrefix).concat(SemanticConventions.TOOL_CALL_FUNCTION_ARGUMENTS_JSON)] = toolCall.function.arguments;
350
+ attributes[`${toolCallIndexPrefix}${SemanticConventions.TOOL_CALL_FUNCTION_NAME}`] = toolCall.function.name;
351
+ attributes[`${toolCallIndexPrefix}${SemanticConventions.TOOL_CALL_FUNCTION_ARGUMENTS_JSON}`] = toolCall.function.arguments;
456
352
  }
457
353
  });
458
354
  }
@@ -462,13 +358,16 @@ function getChatCompletionInputMessageAttributes(message) {
462
358
  break;
463
359
  case "tool":
464
360
  if (message.tool_call_id) {
465
- attributes["".concat(SemanticConventions.MESSAGE_TOOL_CALL_ID)] =
361
+ attributes[`${SemanticConventions.MESSAGE_TOOL_CALL_ID}`] =
466
362
  message.tool_call_id;
467
363
  }
468
364
  break;
469
365
  case "system":
470
366
  // There's nothing to add for the system. Content is captured above
471
367
  break;
368
+ case "developer":
369
+ // There's nothing to add for the developer. Content is captured above
370
+ break;
472
371
  default:
473
372
  assertUnreachable(role);
474
373
  break;
@@ -479,22 +378,21 @@ function getChatCompletionInputMessageAttributes(message) {
479
378
  * Converts the body of a completions request to input attributes
480
379
  */
481
380
  function getCompletionInputValueAndMimeType(body) {
482
- var _a, _b;
483
381
  if (typeof body.prompt === "string") {
484
- return _a = {},
485
- _a[SemanticConventions.INPUT_VALUE] = body.prompt,
486
- _a[SemanticConventions.INPUT_MIME_TYPE] = MimeType.TEXT,
487
- _a;
382
+ return {
383
+ [SemanticConventions.INPUT_VALUE]: body.prompt,
384
+ [SemanticConventions.INPUT_MIME_TYPE]: MimeType.TEXT,
385
+ };
488
386
  }
489
387
  else if (isPromptStringArray(body.prompt)) {
490
- var prompt = body.prompt[0]; // Only single prompts are currently supported
388
+ const prompt = body.prompt[0]; // Only single prompts are currently supported
491
389
  if (prompt === undefined) {
492
390
  return {};
493
391
  }
494
- return _b = {},
495
- _b[SemanticConventions.INPUT_VALUE] = prompt,
496
- _b[SemanticConventions.INPUT_MIME_TYPE] = MimeType.TEXT,
497
- _b;
392
+ return {
393
+ [SemanticConventions.INPUT_VALUE]: prompt,
394
+ [SemanticConventions.INPUT_MIME_TYPE]: MimeType.TEXT,
395
+ };
498
396
  }
499
397
  // Other cases in which the prompt is a token or array of tokens are currently unsupported
500
398
  return {};
@@ -503,13 +401,12 @@ function getCompletionInputValueAndMimeType(body) {
503
401
  * Get usage attributes
504
402
  */
505
403
  function getUsageAttributes(completion) {
506
- var _a;
507
404
  if (completion.usage) {
508
- return _a = {},
509
- _a[SemanticConventions.LLM_TOKEN_COUNT_COMPLETION] = completion.usage.completion_tokens,
510
- _a[SemanticConventions.LLM_TOKEN_COUNT_PROMPT] = completion.usage.prompt_tokens,
511
- _a[SemanticConventions.LLM_TOKEN_COUNT_TOTAL] = completion.usage.total_tokens,
512
- _a;
405
+ return {
406
+ [SemanticConventions.LLM_TOKEN_COUNT_COMPLETION]: completion.usage.completion_tokens,
407
+ [SemanticConventions.LLM_TOKEN_COUNT_PROMPT]: completion.usage.prompt_tokens,
408
+ [SemanticConventions.LLM_TOKEN_COUNT_TOTAL]: completion.usage.total_tokens,
409
+ };
513
410
  }
514
411
  return {};
515
412
  }
@@ -518,46 +415,34 @@ function getUsageAttributes(completion) {
518
415
  */
519
416
  function getChatCompletionLLMOutputMessagesAttributes(chatCompletion) {
520
417
  // Right now support just the first choice
521
- var choice = chatCompletion.choices[0];
418
+ const choice = chatCompletion.choices[0];
522
419
  if (!choice) {
523
420
  return {};
524
421
  }
525
- return [choice.message].reduce(function (acc, message, index) {
526
- var e_2, _a;
527
- var indexPrefix = "".concat(SemanticConventions.LLM_OUTPUT_MESSAGES, ".").concat(index, ".");
528
- var messageAttributes = getChatCompletionOutputMessageAttributes(message);
529
- try {
530
- // Flatten the attributes on the index prefix
531
- for (var _b = __values(Object.entries(messageAttributes)), _c = _b.next(); !_c.done; _c = _b.next()) {
532
- var _d = __read(_c.value, 2), key = _d[0], value = _d[1];
533
- acc["".concat(indexPrefix).concat(key)] = value;
534
- }
535
- }
536
- catch (e_2_1) { e_2 = { error: e_2_1 }; }
537
- finally {
538
- try {
539
- if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
540
- }
541
- finally { if (e_2) throw e_2.error; }
422
+ return [choice.message].reduce((acc, message, index) => {
423
+ const indexPrefix = `${SemanticConventions.LLM_OUTPUT_MESSAGES}.${index}.`;
424
+ const messageAttributes = getChatCompletionOutputMessageAttributes(message);
425
+ // Flatten the attributes on the index prefix
426
+ for (const [key, value] of Object.entries(messageAttributes)) {
427
+ acc[`${indexPrefix}${key}`] = value;
542
428
  }
543
429
  return acc;
544
430
  }, {});
545
431
  }
546
432
  function getChatCompletionOutputMessageAttributes(message) {
547
- var _a;
548
- var role = message.role;
549
- var attributes = (_a = {},
550
- _a[SemanticConventions.MESSAGE_ROLE] = role,
551
- _a);
433
+ const role = message.role;
434
+ const attributes = {
435
+ [SemanticConventions.MESSAGE_ROLE]: role,
436
+ };
552
437
  if (message.content) {
553
438
  attributes[SemanticConventions.MESSAGE_CONTENT] = message.content;
554
439
  }
555
440
  if (message.tool_calls) {
556
- message.tool_calls.forEach(function (toolCall, index) {
557
- var toolCallIndexPrefix = "".concat(SemanticConventions.MESSAGE_TOOL_CALLS, ".").concat(index, ".");
441
+ message.tool_calls.forEach((toolCall, index) => {
442
+ const toolCallIndexPrefix = `${SemanticConventions.MESSAGE_TOOL_CALLS}.${index}.`;
558
443
  // Add the tool call id if it exists
559
444
  if (toolCall.id) {
560
- attributes["".concat(toolCallIndexPrefix).concat(SemanticConventions.TOOL_CALL_ID)] = toolCall.id;
445
+ attributes[`${toolCallIndexPrefix}${SemanticConventions.TOOL_CALL_ID}`] = toolCall.id;
561
446
  }
562
447
  // Double check that the tool call has a function
563
448
  // NB: OpenAI only supports tool calls with functions right now but this may change
@@ -580,33 +465,31 @@ function getChatCompletionOutputMessageAttributes(message) {
580
465
  * Converts the completion result to output attributes
581
466
  */
582
467
  function getCompletionOutputValueAndMimeType(completion) {
583
- var _a;
584
468
  // Right now support just the first choice
585
- var choice = completion.choices[0];
469
+ const choice = completion.choices[0];
586
470
  if (!choice) {
587
471
  return {};
588
472
  }
589
- return _a = {},
590
- _a[SemanticConventions.OUTPUT_VALUE] = String(choice.text),
591
- _a[SemanticConventions.OUTPUT_MIME_TYPE] = MimeType.TEXT,
592
- _a;
473
+ return {
474
+ [SemanticConventions.OUTPUT_VALUE]: String(choice.text),
475
+ [SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.TEXT,
476
+ };
593
477
  }
594
478
  /**
595
479
  * Converts the embedding result payload to embedding attributes
596
480
  */
597
481
  function getEmbeddingTextAttributes(request) {
598
- var _a;
599
482
  if (typeof request.input === "string") {
600
- return _a = {},
601
- _a["".concat(SemanticConventions.EMBEDDING_EMBEDDINGS, ".0.").concat(SemanticConventions.EMBEDDING_TEXT)] = request.input,
602
- _a;
483
+ return {
484
+ [`${SemanticConventions.EMBEDDING_EMBEDDINGS}.0.${SemanticConventions.EMBEDDING_TEXT}`]: request.input,
485
+ };
603
486
  }
604
487
  else if (Array.isArray(request.input) &&
605
488
  request.input.length > 0 &&
606
489
  typeof request.input[0] === "string") {
607
- return request.input.reduce(function (acc, input, index) {
608
- var indexPrefix = "".concat(SemanticConventions.EMBEDDING_EMBEDDINGS, ".").concat(index, ".");
609
- acc["".concat(indexPrefix).concat(SemanticConventions.EMBEDDING_TEXT)] = input;
490
+ return request.input.reduce((acc, input, index) => {
491
+ const indexPrefix = `${SemanticConventions.EMBEDDING_EMBEDDINGS}.${index}.`;
492
+ acc[`${indexPrefix}${SemanticConventions.EMBEDDING_TEXT}`] = input;
610
493
  return acc;
611
494
  }, {});
612
495
  }
@@ -617,9 +500,9 @@ function getEmbeddingTextAttributes(request) {
617
500
  * Converts the embedding result payload to embedding attributes
618
501
  */
619
502
  function getEmbeddingEmbeddingsAttributes(response) {
620
- return response.data.reduce(function (acc, embedding, index) {
621
- var indexPrefix = "".concat(SemanticConventions.EMBEDDING_EMBEDDINGS, ".").concat(index, ".");
622
- acc["".concat(indexPrefix).concat(SemanticConventions.EMBEDDING_VECTOR)] =
503
+ return response.data.reduce((acc, embedding, index) => {
504
+ const indexPrefix = `${SemanticConventions.EMBEDDING_EMBEDDINGS}.${index}.`;
505
+ acc[`${indexPrefix}${SemanticConventions.EMBEDDING_VECTOR}`] =
623
506
  embedding.embedding;
624
507
  return acc;
625
508
  }, {});
@@ -627,103 +510,47 @@ function getEmbeddingEmbeddingsAttributes(response) {
627
510
  /**
628
511
  * Consumes the stream chunks and adds them to the span
629
512
  */
630
- function consumeChatCompletionStreamChunks(stream, span) {
631
- return __awaiter(this, void 0, void 0, function () {
632
- var streamResponse, toolAndFunctionCallAttributes, chunk, choice, toolAndFunctionCallAttributesDiff, _a, _b, _c, key, value, e_3_1, messageIndexPrefix, attributes, _d, _e, _f, key, value;
633
- var e_4, _g, _h, e_5, _j;
634
- var _k, stream_1, stream_1_1;
635
- var _l, e_3, _m, _o;
636
- return __generator(this, function (_p) {
637
- switch (_p.label) {
638
- case 0:
639
- streamResponse = "";
640
- toolAndFunctionCallAttributes = {};
641
- _p.label = 1;
642
- case 1:
643
- _p.trys.push([1, 6, 7, 12]);
644
- _k = true, stream_1 = __asyncValues(stream);
645
- _p.label = 2;
646
- case 2: return [4 /*yield*/, stream_1.next()];
647
- case 3:
648
- if (!(stream_1_1 = _p.sent(), _l = stream_1_1.done, !_l)) return [3 /*break*/, 5];
649
- _o = stream_1_1.value;
650
- _k = false;
651
- chunk = _o;
652
- if (chunk.choices.length <= 0) {
653
- return [3 /*break*/, 4];
654
- }
655
- choice = chunk.choices[0];
656
- if (choice.delta.content) {
657
- streamResponse += choice.delta.content;
658
- }
659
- toolAndFunctionCallAttributesDiff = getToolAndFunctionCallAttributesFromStreamChunk(chunk);
660
- try {
661
- for (_a = (e_4 = void 0, __values(Object.entries(toolAndFunctionCallAttributesDiff))), _b = _a.next(); !_b.done; _b = _a.next()) {
662
- _c = __read(_b.value, 2), key = _c[0], value = _c[1];
663
- if (isString(toolAndFunctionCallAttributes[key]) && isString(value)) {
664
- toolAndFunctionCallAttributes[key] += value;
665
- }
666
- else if (isString(value)) {
667
- toolAndFunctionCallAttributes[key] = value;
668
- }
669
- }
670
- }
671
- catch (e_4_1) { e_4 = { error: e_4_1 }; }
672
- finally {
673
- try {
674
- if (_b && !_b.done && (_g = _a.return)) _g.call(_a);
675
- }
676
- finally { if (e_4) throw e_4.error; }
677
- }
678
- _p.label = 4;
679
- case 4:
680
- _k = true;
681
- return [3 /*break*/, 2];
682
- case 5: return [3 /*break*/, 12];
683
- case 6:
684
- e_3_1 = _p.sent();
685
- e_3 = { error: e_3_1 };
686
- return [3 /*break*/, 12];
687
- case 7:
688
- _p.trys.push([7, , 10, 11]);
689
- if (!(!_k && !_l && (_m = stream_1.return))) return [3 /*break*/, 9];
690
- return [4 /*yield*/, _m.call(stream_1)];
691
- case 8:
692
- _p.sent();
693
- _p.label = 9;
694
- case 9: return [3 /*break*/, 11];
695
- case 10:
696
- if (e_3) throw e_3.error;
697
- return [7 /*endfinally*/];
698
- case 11: return [7 /*endfinally*/];
699
- case 12:
700
- messageIndexPrefix = "".concat(SemanticConventions.LLM_OUTPUT_MESSAGES, ".0.");
701
- attributes = (_h = {},
702
- _h[SemanticConventions.OUTPUT_VALUE] = streamResponse,
703
- _h[SemanticConventions.OUTPUT_MIME_TYPE] = MimeType.TEXT,
704
- _h["".concat(messageIndexPrefix).concat(SemanticConventions.MESSAGE_CONTENT)] = streamResponse,
705
- _h["".concat(messageIndexPrefix).concat(SemanticConventions.MESSAGE_ROLE)] = "assistant",
706
- _h);
707
- try {
708
- // Add the tool and function call attributes
709
- for (_d = __values(Object.entries(toolAndFunctionCallAttributes)), _e = _d.next(); !_e.done; _e = _d.next()) {
710
- _f = __read(_e.value, 2), key = _f[0], value = _f[1];
711
- attributes["".concat(messageIndexPrefix).concat(key)] = value;
712
- }
713
- }
714
- catch (e_5_1) { e_5 = { error: e_5_1 }; }
715
- finally {
716
- try {
717
- if (_e && !_e.done && (_j = _d.return)) _j.call(_d);
718
- }
719
- finally { if (e_5) throw e_5.error; }
720
- }
721
- span.setAttributes(attributes);
722
- span.end();
723
- return [2 /*return*/];
513
+ async function consumeChatCompletionStreamChunks(stream, span) {
514
+ let streamResponse = "";
515
+ // Tool and function call attributes can also arrive in the stream
516
+ // NB: the tools and function calls arrive in partial diffs
517
+ // So the final tool and function calls need to be aggregated
518
+ // across chunks
519
+ const toolAndFunctionCallAttributes = {};
520
+ // The first message is for the assistant response so we start at 1
521
+ for await (const chunk of stream) {
522
+ if (chunk.choices.length <= 0) {
523
+ continue;
524
+ }
525
+ const choice = chunk.choices[0];
526
+ if (choice.delta.content) {
527
+ streamResponse += choice.delta.content;
528
+ }
529
+ // Accumulate the tool and function call attributes
530
+ const toolAndFunctionCallAttributesDiff = getToolAndFunctionCallAttributesFromStreamChunk(chunk);
531
+ for (const [key, value] of Object.entries(toolAndFunctionCallAttributesDiff)) {
532
+ if (isString(toolAndFunctionCallAttributes[key]) && isString(value)) {
533
+ toolAndFunctionCallAttributes[key] += value;
724
534
  }
725
- });
726
- });
535
+ else if (isString(value)) {
536
+ toolAndFunctionCallAttributes[key] = value;
537
+ }
538
+ }
539
+ }
540
+ const messageIndexPrefix = `${SemanticConventions.LLM_OUTPUT_MESSAGES}.0.`;
541
+ // Append the attributes to the span as a message
542
+ const attributes = {
543
+ [SemanticConventions.OUTPUT_VALUE]: streamResponse,
544
+ [SemanticConventions.OUTPUT_MIME_TYPE]: MimeType.TEXT,
545
+ [`${messageIndexPrefix}${SemanticConventions.MESSAGE_CONTENT}`]: streamResponse,
546
+ [`${messageIndexPrefix}${SemanticConventions.MESSAGE_ROLE}`]: "assistant",
547
+ };
548
+ // Add the tool and function call attributes
549
+ for (const [key, value] of Object.entries(toolAndFunctionCallAttributes)) {
550
+ attributes[`${messageIndexPrefix}${key}`] = value;
551
+ }
552
+ span.setAttributes(attributes);
553
+ span.end();
727
554
  }
728
555
  /**
729
556
  * Extracts the semantic attributes from the stream chunk for tool_calls and function_calls
@@ -732,14 +559,14 @@ function getToolAndFunctionCallAttributesFromStreamChunk(chunk) {
732
559
  if (chunk.choices.length <= 0) {
733
560
  return {};
734
561
  }
735
- var choice = chunk.choices[0];
736
- var attributes = {};
562
+ const choice = chunk.choices[0];
563
+ const attributes = {};
737
564
  if (choice.delta.tool_calls) {
738
- choice.delta.tool_calls.forEach(function (toolCall, index) {
739
- var toolCallIndexPrefix = "".concat(SemanticConventions.MESSAGE_TOOL_CALLS, ".").concat(index, ".");
565
+ choice.delta.tool_calls.forEach((toolCall, index) => {
566
+ const toolCallIndexPrefix = `${SemanticConventions.MESSAGE_TOOL_CALLS}.${index}.`;
740
567
  // Add the tool call id if it exists
741
568
  if (toolCall.id) {
742
- attributes["".concat(toolCallIndexPrefix).concat(SemanticConventions.TOOL_CALL_ID)] = toolCall.id;
569
+ attributes[`${toolCallIndexPrefix}${SemanticConventions.TOOL_CALL_ID}`] = toolCall.id;
743
570
  }
744
571
  // Double check that the tool call has a function
745
572
  // NB: OpenAI only supports tool calls with functions right now but this may change