@arizeai/openinference-genai 0.1.6 → 0.1.8

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/src/attributes.ts CHANGED
@@ -1,8 +1,3 @@
1
- import {
2
- OpenInferenceSpanKind,
3
- SemanticConventions,
4
- } from "@arizeai/openinference-semantic-conventions";
5
-
6
1
  import type { Attributes } from "@opentelemetry/api";
7
2
  import {
8
3
  ATTR_GEN_AI_AGENT_DESCRIPTION,
@@ -31,10 +26,12 @@ import {
31
26
  ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
32
27
  } from "@opentelemetry/semantic-conventions/incubating";
33
28
 
34
- import type {
35
- ChatMessage,
36
- GenericPart,
37
- } from "./__generated__/opentelemetryInputMessages.js";
29
+ import {
30
+ OpenInferenceSpanKind,
31
+ SemanticConventions,
32
+ } from "@arizeai/openinference-semantic-conventions";
33
+
34
+ import type { ChatMessage, GenericPart } from "./__generated__/opentelemetryInputMessages.js";
38
35
  import type { OutputMessage } from "./__generated__/opentelemetryOutputMessages.js";
39
36
  import {
40
37
  getMimeType,
@@ -80,8 +77,7 @@ type AnyPart = GenAIInputMessagePart | GenAIOutputMessagePart;
80
77
  const isGenAIChatMessage = (value: unknown): value is ChatMessage => {
81
78
  if (typeof value !== "object" || value === null) return false;
82
79
  if (!("role" in value) || !("parts" in value)) return false;
83
- if (typeof value.role !== "string" || !Array.isArray(value.parts))
84
- return false;
80
+ if (typeof value.role !== "string" || !Array.isArray(value.parts)) return false;
85
81
  if (!value.parts || !Array.isArray(value.parts)) return false;
86
82
  return true;
87
83
  };
@@ -120,16 +116,8 @@ const processMessageParts = ({
120
116
  if (text !== undefined) {
121
117
  // MESSAGE_CONTENTS entries
122
118
  const contentPrefix = `${msgPrefix}${SemanticConventions.MESSAGE_CONTENTS}.${contentIndex}.`;
123
- set(
124
- attrs,
125
- `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TYPE}`,
126
- "text",
127
- );
128
- set(
129
- attrs,
130
- `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TEXT}`,
131
- text,
132
- );
119
+ set(attrs, `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TYPE}`, "text");
120
+ set(attrs, `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TEXT}`, text);
133
121
  contentIndex += 1;
134
122
  }
135
123
  continue;
@@ -140,11 +128,7 @@ const processMessageParts = ({
140
128
  const args = part.arguments ?? {};
141
129
  const toolPrefix = `${msgPrefix}${SemanticConventions.MESSAGE_TOOL_CALLS}.${toolIndex}.`;
142
130
  set(attrs, `${toolPrefix}${SemanticConventions.TOOL_CALL_ID}`, id);
143
- set(
144
- attrs,
145
- toolPrefix + SemanticConventions.TOOL_CALL_FUNCTION_NAME,
146
- name,
147
- );
131
+ set(attrs, toolPrefix + SemanticConventions.TOOL_CALL_FUNCTION_NAME, name);
148
132
  set(
149
133
  attrs,
150
134
  toolPrefix + SemanticConventions.TOOL_CALL_FUNCTION_ARGUMENTS_JSON,
@@ -157,22 +141,10 @@ const processMessageParts = ({
157
141
  const id = part.id ?? undefined;
158
142
  const response = toStringContent(part.response);
159
143
 
160
- set(
161
- attrs,
162
- `${msgPrefix}${SemanticConventions.MESSAGE_TOOL_CALL_ID}`,
163
- id,
164
- );
144
+ set(attrs, `${msgPrefix}${SemanticConventions.MESSAGE_TOOL_CALL_ID}`, id);
165
145
  const contentPrefix = `${msgPrefix}${SemanticConventions.MESSAGE_CONTENTS}.${contentIndex}.`;
166
- set(
167
- attrs,
168
- `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TYPE}`,
169
- "text",
170
- );
171
- set(
172
- attrs,
173
- `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TEXT}`,
174
- response,
175
- );
146
+ set(attrs, `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TYPE}`, "text");
147
+ set(attrs, `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TEXT}`, response);
176
148
  contentIndex += 1;
177
149
  continue;
178
150
  }
@@ -181,21 +153,9 @@ const processMessageParts = ({
181
153
  const genericPart = part as GenericPart;
182
154
  const genericText = toStringContent(genericPart);
183
155
  const contentPrefix = `${msgPrefix}${SemanticConventions.MESSAGE_CONTENTS}.${contentIndex}.`;
184
- set(
185
- attrs,
186
- `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TYPE}`,
187
- genericPart.type,
188
- );
189
- set(
190
- attrs,
191
- `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TEXT}`,
192
- genericText,
193
- );
194
- set(
195
- attrs,
196
- `${msgPrefix}${SemanticConventions.MESSAGE_CONTENT}`,
197
- genericText,
198
- );
156
+ set(attrs, `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TYPE}`, genericPart.type);
157
+ set(attrs, `${contentPrefix}${SemanticConventions.MESSAGE_CONTENT_TEXT}`, genericText);
158
+ set(attrs, `${msgPrefix}${SemanticConventions.MESSAGE_CONTENT}`, genericText);
199
159
  contentIndex += 1;
200
160
  }
201
161
  }
@@ -230,9 +190,7 @@ export const convertGenAISpanAttributesToOpenInferenceSpanAttributes = (
230
190
  * @param spanAttributes - The span attributes containing provider and system to map
231
191
  * @returns The mapped provider and system attributes
232
192
  */
233
- export const mapProviderAndSystem = (
234
- spanAttributes: Attributes,
235
- ): Attributes => {
193
+ export const mapProviderAndSystem = (spanAttributes: Attributes): Attributes => {
236
194
  const attrs: Attributes = {};
237
195
  const provider = getString(spanAttributes[ATTR_GEN_AI_PROVIDER_NAME]);
238
196
  set(attrs, SemanticConventions.LLM_PROVIDER, provider);
@@ -281,42 +239,29 @@ export const mapSpanKind = (spanAttributes: Attributes): Attributes => {
281
239
  * @param spanAttributes - The span attributes containing invocation parameters to map
282
240
  * @returns The mapped invocation parameters attributes
283
241
  */
284
- export const mapInvocationParameters = (
285
- spanAttributes: Attributes,
286
- ): Attributes => {
242
+ export const mapInvocationParameters = (spanAttributes: Attributes): Attributes => {
287
243
  const attrs: Attributes = {};
288
244
  const requestModel = getString(spanAttributes[ATTR_GEN_AI_REQUEST_MODEL]);
289
245
  const maxTokens = getNumber(spanAttributes[ATTR_GEN_AI_REQUEST_MAX_TOKENS]);
290
- const temperature = getNumber(
291
- spanAttributes[ATTR_GEN_AI_REQUEST_TEMPERATURE],
292
- );
246
+ const temperature = getNumber(spanAttributes[ATTR_GEN_AI_REQUEST_TEMPERATURE]);
293
247
  const topP = getNumber(spanAttributes[ATTR_GEN_AI_REQUEST_TOP_P]);
294
248
  const topK = getNumber(spanAttributes[ATTR_GEN_AI_REQUEST_TOP_K]);
295
- const presencePenalty = getNumber(
296
- spanAttributes[ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY],
297
- );
298
- const frequencyPenalty = getNumber(
299
- spanAttributes[ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY],
300
- );
249
+ const presencePenalty = getNumber(spanAttributes[ATTR_GEN_AI_REQUEST_PRESENCE_PENALTY]);
250
+ const frequencyPenalty = getNumber(spanAttributes[ATTR_GEN_AI_REQUEST_FREQUENCY_PENALTY]);
301
251
  const seed = getNumber(spanAttributes[ATTR_GEN_AI_REQUEST_SEED]);
302
- const stopSequences = getStringArray(
303
- spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES],
304
- );
252
+ const stopSequences = getStringArray(spanAttributes[ATTR_GEN_AI_REQUEST_STOP_SEQUENCES]);
305
253
  const invocationParameters: Record<string, unknown> = {};
306
254
  if (requestModel) invocationParameters.model = requestModel;
307
- if (typeof temperature === "number")
308
- invocationParameters.temperature = temperature;
255
+ if (typeof temperature === "number") invocationParameters.temperature = temperature;
309
256
  if (typeof topP === "number") invocationParameters.top_p = topP;
310
257
  if (typeof topK === "number") invocationParameters.top_k = topK;
311
- if (typeof presencePenalty === "number")
312
- invocationParameters.presence_penalty = presencePenalty;
258
+ if (typeof presencePenalty === "number") invocationParameters.presence_penalty = presencePenalty;
313
259
  if (typeof frequencyPenalty === "number")
314
260
  invocationParameters.frequency_penalty = frequencyPenalty;
315
261
  if (typeof seed === "number") invocationParameters.seed = seed;
316
262
  if (stopSequences && stopSequences.length > 0)
317
263
  invocationParameters.stop_sequences = stopSequences;
318
- if (typeof maxTokens === "number")
319
- invocationParameters.max_completion_tokens = maxTokens;
264
+ if (typeof maxTokens === "number") invocationParameters.max_completion_tokens = maxTokens;
320
265
  if (Object.keys(invocationParameters).length > 0) {
321
266
  set(
322
267
  attrs,
@@ -374,9 +319,7 @@ export const mapOutputValue = (spanAttributes: Attributes): Attributes => {
374
319
  */
375
320
  export const mapInputMessages = (spanAttributes: Attributes): Attributes => {
376
321
  const attrs: Attributes = {};
377
- const genAIInputMessages = safelyParseJSON(
378
- spanAttributes[ATTR_GEN_AI_INPUT_MESSAGES],
379
- );
322
+ const genAIInputMessages = safelyParseJSON(spanAttributes[ATTR_GEN_AI_INPUT_MESSAGES]);
380
323
 
381
324
  if (Array.isArray(genAIInputMessages)) {
382
325
  (genAIInputMessages as unknown[]).forEach((msg, msgIndex) => {
@@ -399,9 +342,7 @@ export const mapInputMessages = (spanAttributes: Attributes): Attributes => {
399
342
  */
400
343
  export const mapOutputMessages = (spanAttributes: Attributes): Attributes => {
401
344
  const attrs: Attributes = {};
402
- const genAIOutputMessages = safelyParseJSON(
403
- spanAttributes[ATTR_GEN_AI_OUTPUT_MESSAGES],
404
- );
345
+ const genAIOutputMessages = safelyParseJSON(spanAttributes[ATTR_GEN_AI_OUTPUT_MESSAGES]);
405
346
 
406
347
  if (Array.isArray(genAIOutputMessages) && genAIOutputMessages.length > 0) {
407
348
  // recast as unknown[] for safety, as Array.isArray() retypes to any[]
@@ -426,9 +367,7 @@ export const mapOutputMessages = (spanAttributes: Attributes): Attributes => {
426
367
  export const mapTokenCounts = (spanAttributes: Attributes): Attributes => {
427
368
  const attrs: Attributes = {};
428
369
  const inputTokens = getNumber(spanAttributes[ATTR_GEN_AI_USAGE_INPUT_TOKENS]);
429
- const outputTokens = getNumber(
430
- spanAttributes[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS],
431
- );
370
+ const outputTokens = getNumber(spanAttributes[ATTR_GEN_AI_USAGE_OUTPUT_TOKENS]);
432
371
  if (typeof inputTokens === "number") {
433
372
  set(attrs, SemanticConventions.LLM_TOKEN_COUNT_PROMPT, inputTokens);
434
373
  }
@@ -436,11 +375,7 @@ export const mapTokenCounts = (spanAttributes: Attributes): Attributes => {
436
375
  set(attrs, SemanticConventions.LLM_TOKEN_COUNT_COMPLETION, outputTokens);
437
376
  }
438
377
  if (typeof inputTokens === "number" && typeof outputTokens === "number") {
439
- set(
440
- attrs,
441
- SemanticConventions.LLM_TOKEN_COUNT_TOTAL,
442
- inputTokens + outputTokens,
443
- );
378
+ set(attrs, SemanticConventions.LLM_TOKEN_COUNT_TOTAL, inputTokens + outputTokens);
444
379
  }
445
380
  return attrs;
446
381
  };
@@ -454,9 +389,7 @@ export const mapTokenCounts = (spanAttributes: Attributes): Attributes => {
454
389
  export const mapToolExecution = (spanAttributes: Attributes): Attributes => {
455
390
  const attrs: Attributes = {};
456
391
  const toolName = getString(spanAttributes[ATTR_GEN_AI_TOOL_NAME]);
457
- const toolDescription = getString(
458
- spanAttributes[ATTR_GEN_AI_TOOL_DESCRIPTION],
459
- );
392
+ const toolDescription = getString(spanAttributes[ATTR_GEN_AI_TOOL_DESCRIPTION]);
460
393
  const toolCallId = getString(spanAttributes[ATTR_GEN_AI_TOOL_CALL_ID]);
461
394
  // parse supported tool details
462
395
  // note: while openinference can track parameters, gen_ai does not provide this information
package/src/index.ts CHANGED
@@ -1,14 +1,13 @@
1
1
  import { convertGenAISpanAttributesToOpenInferenceSpanAttributes as unsafeConvertGenAISpanAttributesToOpenInferenceSpanAttributes } from "./attributes.js";
2
2
  import { withSafety } from "./utils.js";
3
3
 
4
- export const convertGenAISpanAttributesToOpenInferenceSpanAttributes =
5
- withSafety({
6
- fn: unsafeConvertGenAISpanAttributesToOpenInferenceSpanAttributes,
7
- onError(error) {
8
- // eslint-disable-next-line no-console
9
- console.error(
10
- "Unable to convert GenAI span attributes to OpenInference span attributes",
11
- error,
12
- );
13
- },
14
- });
4
+ export const convertGenAISpanAttributesToOpenInferenceSpanAttributes = withSafety({
5
+ fn: unsafeConvertGenAISpanAttributesToOpenInferenceSpanAttributes,
6
+ onError(error) {
7
+ // eslint-disable-next-line no-console
8
+ console.error(
9
+ "Unable to convert GenAI span attributes to OpenInference span attributes",
10
+ error,
11
+ );
12
+ },
13
+ });
package/src/utils.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { MimeType } from "@arizeai/openinference-semantic-conventions";
2
-
3
1
  import type { Attributes, AttributeValue } from "@opentelemetry/api";
4
2
 
5
- import { GenericFunction, SafeFunction } from "./types.js";
3
+ import { MimeType } from "@arizeai/openinference-semantic-conventions";
4
+
5
+ import type { GenericFunction, SafeFunction } from "./types.js";
6
6
 
7
7
  export const safelyJSONStringify = (value: unknown) => {
8
8
  try {
@@ -51,11 +51,7 @@ export const getMimeType = (value: unknown): MimeType => {
51
51
  * @param key - The key to assign the value to
52
52
  * @param value - The value to assign to the key
53
53
  */
54
- export const set = (
55
- attrs: Attributes,
56
- key: string,
57
- value?: AttributeValue | null,
58
- ) => {
54
+ export const set = (attrs: Attributes, key: string, value?: AttributeValue | null) => {
59
55
  if (value === undefined || value === null) return;
60
56
  attrs[key] = value;
61
57
  };