@arizeai/openinference-instrumentation-openai 0.0.1-rc8 → 0.0.2

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 (47) hide show
  1. package/README.md +30 -1
  2. package/dist/esm/index.d.ts +2 -0
  3. package/dist/esm/index.d.ts.map +1 -0
  4. package/dist/esm/index.js +2 -0
  5. package/dist/esm/index.js.map +1 -0
  6. package/dist/esm/instrumentation.d.ts +15 -0
  7. package/dist/esm/instrumentation.d.ts.map +1 -0
  8. package/dist/esm/instrumentation.js +164 -0
  9. package/dist/esm/instrumentation.js.map +1 -0
  10. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  11. package/dist/esm/version.d.ts +2 -0
  12. package/dist/esm/version.d.ts.map +1 -0
  13. package/dist/esm/version.js +3 -0
  14. package/dist/esm/version.js.map +1 -0
  15. package/dist/esnext/index.d.ts +2 -0
  16. package/dist/esnext/index.d.ts.map +1 -0
  17. package/dist/esnext/index.js +2 -0
  18. package/dist/esnext/index.js.map +1 -0
  19. package/dist/esnext/instrumentation.d.ts +15 -0
  20. package/dist/esnext/instrumentation.d.ts.map +1 -0
  21. package/dist/esnext/instrumentation.js +127 -0
  22. package/dist/esnext/instrumentation.js.map +1 -0
  23. package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -1
  24. package/dist/esnext/version.d.ts +2 -0
  25. package/dist/esnext/version.d.ts.map +1 -0
  26. package/dist/esnext/version.js +3 -0
  27. package/dist/esnext/version.js.map +1 -0
  28. package/dist/src/index.d.ts +2 -0
  29. package/dist/src/index.d.ts.map +1 -0
  30. package/dist/src/index.js +18 -0
  31. package/dist/src/index.js.map +1 -0
  32. package/dist/src/instrumentation.d.ts +15 -0
  33. package/dist/src/instrumentation.d.ts.map +1 -0
  34. package/dist/src/instrumentation.js +131 -0
  35. package/dist/src/instrumentation.js.map +1 -0
  36. package/dist/src/version.d.ts +2 -0
  37. package/dist/src/version.d.ts.map +1 -0
  38. package/dist/src/version.js +6 -0
  39. package/dist/src/version.js.map +1 -0
  40. package/dist/test/openai.test.d.ts +2 -0
  41. package/dist/test/openai.test.d.ts.map +1 -0
  42. package/dist/test/openai.test.js +130 -0
  43. package/dist/test/openai.test.js.map +1 -0
  44. package/dist/tsconfig.tsbuildinfo +1 -1
  45. package/package.json +2 -2
  46. package/src/instrumentation.ts +92 -8
  47. 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": "0.0.1-rc8",
3
+ "version": "0.0.2",
4
4
  "description": "OpenInference instrumentation for OpenAI",
5
5
  "private": false,
6
6
  "main": "dist/src/index.js",
@@ -10,7 +10,7 @@
10
10
  "dependencies": {
11
11
  "@opentelemetry/api": "^1.7.0",
12
12
  "@opentelemetry/instrumentation": "^0.46.0",
13
- "@arizeai/openinference-semantic-conventions": "0.0.8"
13
+ "@arizeai/openinference-semantic-conventions": "0.0.11"
14
14
  },
15
15
  "keywords": [],
16
16
  "files": [
@@ -10,17 +10,22 @@ import {
10
10
  diag,
11
11
  context,
12
12
  trace,
13
- isSpanContextValid,
14
- Span,
15
13
  SpanKind,
16
14
  Attributes,
15
+ SpanStatusCode,
17
16
  } from "@opentelemetry/api";
18
17
  import { VERSION } from "./version";
19
18
  import {
20
19
  SemanticConventions,
21
20
  OpenInferenceSpanKind,
21
+ MimeType,
22
22
  } from "@arizeai/openinference-semantic-conventions";
23
- import { ChatCompletionCreateParamsBase } from "openai/resources/chat/completions";
23
+ import {
24
+ ChatCompletion,
25
+ ChatCompletionChunk,
26
+ ChatCompletionCreateParamsBase,
27
+ } from "openai/resources/chat/completions";
28
+ import { Stream } from "openai/streaming";
24
29
 
25
30
  const MODULE_NAME = "openai";
26
31
 
@@ -42,18 +47,22 @@ export class OpenAIInstrumentation extends InstrumentationBase<typeof openai> {
42
47
  );
43
48
  return module;
44
49
  }
50
+ /**
51
+ * Patches the OpenAI module
52
+ */
45
53
  private patch(
46
54
  module: typeof openai & { openInferencePatched?: boolean },
47
55
  moduleVersion?: string
48
56
  ) {
49
- console.log(`Applying patch for ${MODULE_NAME}@${moduleVersion}`);
50
- const plugin = this;
57
+ diag.debug(`Applying patch for ${MODULE_NAME}@${moduleVersion}`);
51
58
  if (module?.openInferencePatched) {
52
59
  return module;
53
60
  }
54
61
  const instrumentation: OpenAIInstrumentation = this;
55
62
  type CompletionCreateType =
56
63
  typeof module.OpenAI.Chat.Completions.prototype.create;
64
+
65
+ // Patch create chat completions
57
66
  this._wrap(
58
67
  module.OpenAI.Chat.Completions.prototype,
59
68
  "create",
@@ -65,6 +74,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<typeof openai> {
65
74
  >
66
75
  ) {
67
76
  const body = args[0];
77
+ const { messages, ...invocationParameters } = body;
68
78
  const span = instrumentation.tracer.startSpan(
69
79
  `OpenAI Chat Completions`,
70
80
  {
@@ -72,6 +82,14 @@ export class OpenAIInstrumentation extends InstrumentationBase<typeof openai> {
72
82
  attributes: {
73
83
  [SemanticConventions.OPENINFERENCE_SPAN_KIND]:
74
84
  OpenInferenceSpanKind.LLM,
85
+ [SemanticConventions.LLM_MODEL_NAME]:
86
+ body.model,
87
+ [SemanticConventions.INPUT_VALUE]:
88
+ JSON.stringify(body),
89
+ [SemanticConventions.INPUT_MIME_TYPE]:
90
+ MimeType.JSON,
91
+ [SemanticConventions.LLM_INVOCATION_PARAMETERS]:
92
+ JSON.stringify(invocationParameters),
75
93
  ...getLLMInputMessagesAttributes(body),
76
94
  },
77
95
  }
@@ -86,11 +104,25 @@ export class OpenAIInstrumentation extends InstrumentationBase<typeof openai> {
86
104
  });
87
105
  },
88
106
  (error) => {
89
- // TODO handler the error
107
+ // Push the error to the span
108
+ if (error) {
109
+ span.recordException(error);
110
+ }
90
111
  }
91
112
  );
92
113
  const wrappedPromise = execPromise.then((result) => {
93
- // TODO set span attributes
114
+ if (result) {
115
+ // Record the results
116
+ span.setAttributes({
117
+ [SemanticConventions.OUTPUT_VALUE]:
118
+ JSON.stringify(result),
119
+ [SemanticConventions.OUTPUT_MIME_TYPE]:
120
+ MimeType.JSON,
121
+ ...getLLMOutputMessagesAttributes(result),
122
+ ...getUsageAttributes(result),
123
+ });
124
+ }
125
+ span.setStatus({ code: SpanStatusCode.OK });
94
126
  span.end();
95
127
  return result;
96
128
  });
@@ -101,13 +133,17 @@ export class OpenAIInstrumentation extends InstrumentationBase<typeof openai> {
101
133
  module.openInferencePatched = true;
102
134
  return module;
103
135
  }
136
+ /**
137
+ * Un-patches the OpenAI module's chat completions API
138
+ */
104
139
  private unpatch(moduleExports: typeof openai, moduleVersion?: string) {
105
140
  diag.debug(`Removing patch for ${MODULE_NAME}@${moduleVersion}`);
141
+ this._unwrap(moduleExports.OpenAI.Chat.Completions.prototype, "create");
106
142
  }
107
143
  }
108
144
 
109
145
  /**
110
- * Converts the body input
146
+ * Converts the body of the request to LLM input messages
111
147
  */
112
148
  function getLLMInputMessagesAttributes(
113
149
  body: ChatCompletionCreateParamsBase
@@ -123,3 +159,51 @@ function getLLMInputMessagesAttributes(
123
159
  return acc;
124
160
  }, {} as Attributes);
125
161
  }
162
+
163
+ /**
164
+ * Get Usage attributes
165
+ */
166
+ function getUsageAttributes(
167
+ response: Stream<ChatCompletionChunk> | ChatCompletion
168
+ ) {
169
+ if (response.hasOwnProperty("usage")) {
170
+ const completion = response as ChatCompletion;
171
+ if (completion.usage) {
172
+ return {
173
+ [SemanticConventions.LLM_TOKEN_COUNT_COMPLETION]:
174
+ completion.usage.completion_tokens,
175
+ [SemanticConventions.LLM_TOKEN_COUNT_PROMPT]:
176
+ completion.usage.prompt_tokens,
177
+ [SemanticConventions.LLM_TOKEN_COUNT_TOTAL]:
178
+ completion.usage.total_tokens,
179
+ };
180
+ }
181
+ }
182
+ return {};
183
+ }
184
+
185
+ /**
186
+ * Converts the result to LLM output attributes
187
+ */
188
+ function getLLMOutputMessagesAttributes(
189
+ response: Stream<ChatCompletionChunk> | ChatCompletion
190
+ ): Attributes {
191
+ // Handle chat completion
192
+ if (response.hasOwnProperty("choices")) {
193
+ const completion = response as ChatCompletion;
194
+ // Right now support just the first choice
195
+ const choice = completion.choices[0];
196
+ if (!choice) {
197
+ return {};
198
+ }
199
+ return [choice.message].reduce((acc, message, index) => {
200
+ const index_prefix = `${SemanticConventions.LLM_OUTPUT_MESSAGES}.${index}`;
201
+ acc[`${index_prefix}.${SemanticConventions.MESSAGE_CONTENT}`] =
202
+ String(message.content);
203
+ acc[`${index_prefix}.${SemanticConventions.MESSAGE_ROLE}`] =
204
+ message.role;
205
+ return acc;
206
+ }, {} as Attributes);
207
+ }
208
+ return {};
209
+ }
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 = "0.0.1-rc7";
2
+ export const VERSION = "0.0.2";