@arizeai/openinference-instrumentation-openai 4.2.6 → 4.3.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.
Files changed (45) hide show
  1. package/README.md +7 -0
  2. package/dist/esm/instrumentation.d.ts.map +1 -1
  3. package/dist/esm/instrumentation.js +8 -1
  4. package/dist/esm/instrumentation.js.map +1 -1
  5. package/dist/esm/responsesAttributes.d.ts.map +1 -1
  6. package/dist/esm/responsesAttributes.js +2 -0
  7. package/dist/esm/responsesAttributes.js.map +1 -1
  8. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  9. package/dist/esm/typeUtils.d.ts +6 -0
  10. package/dist/esm/typeUtils.d.ts.map +1 -1
  11. package/dist/esm/typeUtils.js +11 -0
  12. package/dist/esm/typeUtils.js.map +1 -1
  13. package/dist/esm/version.d.ts +1 -1
  14. package/dist/esm/version.js +1 -1
  15. package/dist/esnext/instrumentation.d.ts.map +1 -1
  16. package/dist/esnext/instrumentation.js +8 -1
  17. package/dist/esnext/instrumentation.js.map +1 -1
  18. package/dist/esnext/responsesAttributes.d.ts.map +1 -1
  19. package/dist/esnext/responsesAttributes.js +2 -0
  20. package/dist/esnext/responsesAttributes.js.map +1 -1
  21. package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -1
  22. package/dist/esnext/typeUtils.d.ts +6 -0
  23. package/dist/esnext/typeUtils.d.ts.map +1 -1
  24. package/dist/esnext/typeUtils.js +11 -0
  25. package/dist/esnext/typeUtils.js.map +1 -1
  26. package/dist/esnext/version.d.ts +1 -1
  27. package/dist/esnext/version.js +1 -1
  28. package/dist/src/instrumentation.d.ts.map +1 -1
  29. package/dist/src/instrumentation.js +7 -0
  30. package/dist/src/instrumentation.js.map +1 -1
  31. package/dist/src/responsesAttributes.d.ts.map +1 -1
  32. package/dist/src/responsesAttributes.js +2 -0
  33. package/dist/src/responsesAttributes.js.map +1 -1
  34. package/dist/src/typeUtils.d.ts +6 -0
  35. package/dist/src/typeUtils.d.ts.map +1 -1
  36. package/dist/src/typeUtils.js +12 -0
  37. package/dist/src/typeUtils.js.map +1 -1
  38. package/dist/src/version.d.ts +1 -1
  39. package/dist/src/version.js +1 -1
  40. package/dist/tsconfig.tsbuildinfo +1 -1
  41. package/package.json +3 -3
  42. package/src/instrumentation.ts +14 -2
  43. package/src/responsesAttributes.ts +6 -0
  44. package/src/typeUtils.ts +11 -0
  45. package/src/version.ts +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arizeai/openinference-instrumentation-openai",
3
- "version": "4.2.6",
3
+ "version": "4.3.0",
4
4
  "private": false,
5
5
  "description": "OpenInference instrumentation for OpenAI",
6
6
  "keywords": [],
@@ -28,8 +28,8 @@
28
28
  "@opentelemetry/api": "^1.9.0",
29
29
  "@opentelemetry/core": "^2.8.0",
30
30
  "@opentelemetry/instrumentation": "^0.46.0",
31
- "@arizeai/openinference-core": "2.7.0",
32
- "@arizeai/openinference-semantic-conventions": "2.11.0"
31
+ "@arizeai/openinference-core": "2.7.2",
32
+ "@arizeai/openinference-semantic-conventions": "2.13.0"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@opentelemetry/exporter-trace-otlp-proto": "^0.50.0",
@@ -44,7 +44,7 @@ import {
44
44
  getResponsesOutputMessagesAttributes,
45
45
  getResponsesUsageAttributes,
46
46
  } from "./responsesAttributes";
47
- import { assertUnreachable, isString } from "./typeUtils";
47
+ import { assertUnreachable, getNumberProperty, isString } from "./typeUtils";
48
48
  import { VERSION } from "./version";
49
49
 
50
50
  const MODULE_NAME = "openai";
@@ -81,6 +81,7 @@ export const HOST_SUFFIX_TO_PROVIDER: Record<string, LLMProvider> = {
81
81
  "api.minimax.io": LLMProvider.MINIMAX,
82
82
  "api.minimaxi.com": LLMProvider.MINIMAX,
83
83
  "api.minimax.chat": LLMProvider.MINIMAX,
84
+ "oci.oraclecloud.com": LLMProvider.ORACLE,
84
85
  };
85
86
 
86
87
  /**
@@ -788,7 +789,9 @@ function getCompletionInputValueAndMimeType(body: CompletionCreateParamsBase): A
788
789
  /**
789
790
  * Get usage attributes
790
791
  */
791
- function getUsageAttributes(completion: ChatCompletion | Completion): Attributes {
792
+ function getUsageAttributes(
793
+ completion: ChatCompletion | Completion | ChatCompletionChunk,
794
+ ): Attributes {
792
795
  if (completion.usage) {
793
796
  const usageAttributes: Attributes = {
794
797
  [SemanticConventions.LLM_TOKEN_COUNT_COMPLETION]: completion.usage.completion_tokens,
@@ -796,6 +799,10 @@ function getUsageAttributes(completion: ChatCompletion | Completion): Attributes
796
799
  [SemanticConventions.LLM_TOKEN_COUNT_TOTAL]: completion.usage.total_tokens,
797
800
  [SemanticConventions.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ]:
798
801
  completion.usage.prompt_tokens_details?.cached_tokens,
802
+ [SemanticConventions.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE]: getNumberProperty(
803
+ completion.usage.prompt_tokens_details,
804
+ "cache_write_tokens",
805
+ ),
799
806
  [SemanticConventions.LLM_TOKEN_COUNT_PROMPT_DETAILS_AUDIO]:
800
807
  completion.usage.prompt_tokens_details?.audio_tokens,
801
808
  [SemanticConventions.LLM_TOKEN_COUNT_COMPLETION_DETAILS_AUDIO]:
@@ -938,6 +945,11 @@ async function consumeChatCompletionStreamChunks(stream: Stream<ChatCompletionCh
938
945
  let finishReason: string | undefined;
939
946
  // The first message is for the assistant response so we start at 1
940
947
  for await (const chunk of stream) {
948
+ // With `stream_options.include_usage`, the final chunk carries the request's
949
+ // usage and an empty `choices` array, so read it before the guard below.
950
+ if (chunk.usage) {
951
+ span.setAttributes(getUsageAttributes(chunk));
952
+ }
941
953
  if (chunk.choices.length <= 0) {
942
954
  continue;
943
955
  }
@@ -11,6 +11,8 @@ import type { Stream } from "openai/streaming";
11
11
  import { safelyJSONStringify } from "@arizeai/openinference-core";
12
12
  import { SemanticConventions } from "@arizeai/openinference-semantic-conventions";
13
13
 
14
+ import { getNumberProperty } from "./typeUtils";
15
+
14
16
  /**
15
17
  * Get attributes for responses api Items that are not typical messages with role
16
18
  * @param item - The item to get attributes for
@@ -217,6 +219,10 @@ export function getResponsesUsageAttributes(response: ResponseType): Attributes
217
219
  [SemanticConventions.LLM_TOKEN_COUNT_TOTAL]: response.usage.total_tokens,
218
220
  [SemanticConventions.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_READ]:
219
221
  response.usage.input_tokens_details?.cached_tokens,
222
+ [SemanticConventions.LLM_TOKEN_COUNT_PROMPT_DETAILS_CACHE_WRITE]: getNumberProperty(
223
+ response.usage.input_tokens_details,
224
+ "cache_write_tokens",
225
+ ),
220
226
  [SemanticConventions.LLM_TOKEN_COUNT_COMPLETION_DETAILS_REASONING]:
221
227
  response.usage.output_tokens_details?.reasoning_tokens,
222
228
  // no audio tokens for response inputs or outputs
package/src/typeUtils.ts CHANGED
@@ -11,3 +11,14 @@ export function assertUnreachable(_: never): never {
11
11
  export function isString(value: unknown): value is string {
12
12
  return typeof value === "string";
13
13
  }
14
+
15
+ /**
16
+ * Read a numeric property that the installed OpenAI SDK types may not declare yet
17
+ * (for example `prompt_tokens_details.cache_write_tokens`). Returns undefined when
18
+ * the object is missing or the property is not a number.
19
+ */
20
+ export function getNumberProperty(obj: object | null | undefined, key: string): number | undefined {
21
+ if (obj == null) return undefined;
22
+ const value: unknown = Reflect.get(obj, key);
23
+ return typeof value === "number" ? value : undefined;
24
+ }
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  // this is an auto-generated file. see js/scripts/version-update.js
2
- export const VERSION = "4.2.6";
2
+ export const VERSION = "4.3.0";