@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.
- package/README.md +30 -1
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/instrumentation.d.ts +15 -0
- package/dist/esm/instrumentation.d.ts.map +1 -0
- package/dist/esm/instrumentation.js +164 -0
- package/dist/esm/instrumentation.js.map +1 -0
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esm/version.d.ts +2 -0
- package/dist/esm/version.d.ts.map +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/esnext/index.d.ts +2 -0
- package/dist/esnext/index.d.ts.map +1 -0
- package/dist/esnext/index.js +2 -0
- package/dist/esnext/index.js.map +1 -0
- package/dist/esnext/instrumentation.d.ts +15 -0
- package/dist/esnext/instrumentation.d.ts.map +1 -0
- package/dist/esnext/instrumentation.js +127 -0
- package/dist/esnext/instrumentation.js.map +1 -0
- package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -1
- package/dist/esnext/version.d.ts +2 -0
- package/dist/esnext/version.d.ts.map +1 -0
- package/dist/esnext/version.js +3 -0
- package/dist/esnext/version.js.map +1 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +18 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/instrumentation.d.ts +15 -0
- package/dist/src/instrumentation.d.ts.map +1 -0
- package/dist/src/instrumentation.js +131 -0
- package/dist/src/instrumentation.js.map +1 -0
- package/dist/src/version.d.ts +2 -0
- package/dist/src/version.d.ts.map +1 -0
- package/dist/src/version.js +6 -0
- package/dist/src/version.js.map +1 -0
- package/dist/test/openai.test.d.ts +2 -0
- package/dist/test/openai.test.d.ts.map +1 -0
- package/dist/test/openai.test.js +130 -0
- package/dist/test/openai.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/instrumentation.ts +92 -8
- 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.
|
|
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.
|
|
13
|
+
"@arizeai/openinference-semantic-conventions": "0.0.11"
|
|
14
14
|
},
|
|
15
15
|
"keywords": [],
|
|
16
16
|
"files": [
|
package/src/instrumentation.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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.
|
|
2
|
+
export const VERSION = "0.0.2";
|