@arizeai/openinference-instrumentation-openai 4.0.6 → 4.1.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.
- package/dist/esm/instrumentation.d.ts +9 -0
- package/dist/esm/instrumentation.d.ts.map +1 -1
- package/dist/esm/instrumentation.js +60 -15
- package/dist/esm/instrumentation.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esnext/instrumentation.d.ts +9 -0
- package/dist/esnext/instrumentation.d.ts.map +1 -1
- package/dist/esnext/instrumentation.js +61 -18
- package/dist/esnext/instrumentation.js.map +1 -1
- package/dist/esnext/tsconfig.esnext.tsbuildinfo +1 -1
- package/dist/esnext/version.d.ts +1 -1
- package/dist/esnext/version.js +1 -1
- package/dist/src/instrumentation.d.ts +9 -0
- package/dist/src/instrumentation.d.ts.map +1 -1
- package/dist/src/instrumentation.js +63 -19
- package/dist/src/instrumentation.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
- package/src/instrumentation.ts +65 -15
- 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.0
|
|
3
|
+
"version": "4.1.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": "^1.25.1",
|
|
30
30
|
"@opentelemetry/instrumentation": "^0.46.0",
|
|
31
|
-
"@arizeai/openinference-core": "2.0.
|
|
32
|
-
"@arizeai/openinference-semantic-conventions": "2.
|
|
31
|
+
"@arizeai/openinference-core": "2.0.8",
|
|
32
|
+
"@arizeai/openinference-semantic-conventions": "2.3.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.50.0",
|
package/src/instrumentation.ts
CHANGED
|
@@ -51,6 +51,45 @@ const MODULE_NAME = "openai";
|
|
|
51
51
|
|
|
52
52
|
const INSTRUMENTATION_NAME = "@arizeai/openinference-instrumentation-openai";
|
|
53
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Maps hostname suffixes to their corresponding LLM provider value.
|
|
56
|
+
*/
|
|
57
|
+
export const HOST_SUFFIX_TO_PROVIDER: Record<string, LLMProvider> = {
|
|
58
|
+
"api.openai.com": LLMProvider.OPENAI,
|
|
59
|
+
"openai.azure.com": LLMProvider.AZURE,
|
|
60
|
+
"services.ai.azure.com": LLMProvider.AZURE,
|
|
61
|
+
"cognitiveservices.azure.com": LLMProvider.AZURE,
|
|
62
|
+
"api.anthropic.com": LLMProvider.ANTHROPIC,
|
|
63
|
+
"api.cohere.com": LLMProvider.COHERE,
|
|
64
|
+
"api.cohere.ai": LLMProvider.COHERE,
|
|
65
|
+
"api.mistral.ai": LLMProvider.MISTRALAI,
|
|
66
|
+
"generativelanguage.googleapis.com": LLMProvider.GOOGLE,
|
|
67
|
+
"aiplatform.googleapis.com": LLMProvider.GOOGLE,
|
|
68
|
+
"amazonaws.com": LLMProvider.AWS,
|
|
69
|
+
"api.x.ai": LLMProvider.XAI,
|
|
70
|
+
"api.deepseek.com": LLMProvider.DEEPSEEK,
|
|
71
|
+
"api.groq.com": LLMProvider.GROQ,
|
|
72
|
+
"api.fireworks.ai": LLMProvider.FIREWORKS,
|
|
73
|
+
"api.moonshot.cn": LLMProvider.MOONSHOT,
|
|
74
|
+
"api.cerebras.ai": LLMProvider.CEREBRAS,
|
|
75
|
+
"api.perplexity.ai": LLMProvider.PERPLEXITY,
|
|
76
|
+
"api.together.ai": LLMProvider.TOGETHER,
|
|
77
|
+
"api.together.xyz": LLMProvider.TOGETHER,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Return the LLM provider name for the given API hostname.
|
|
82
|
+
*/
|
|
83
|
+
export function getProviderFromHost(host: string): LLMProvider | undefined {
|
|
84
|
+
const normalised = host.toLowerCase().trim();
|
|
85
|
+
for (const [suffix, provider] of Object.entries(HOST_SUFFIX_TO_PROVIDER)) {
|
|
86
|
+
if (normalised.endsWith(suffix)) {
|
|
87
|
+
return provider;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
54
93
|
/**
|
|
55
94
|
* Flag to check if the openai module has been patched
|
|
56
95
|
* Note: This is a fallback in case the module is made immutable (e.x. Deno, webpack, etc.)
|
|
@@ -84,9 +123,9 @@ function getExecContext(span: Span) {
|
|
|
84
123
|
* Gets the appropriate LLM provider based on the OpenAI client instance
|
|
85
124
|
* Follows the same logic as the Python implementation by checking the baseURL host
|
|
86
125
|
* @param clientInstance The OpenAI client instance
|
|
87
|
-
* @returns
|
|
126
|
+
* @returns LLM provider based on the API hostname
|
|
88
127
|
*/
|
|
89
|
-
function getLLMProvider(clientInstance: unknown): LLMProvider {
|
|
128
|
+
function getLLMProvider(clientInstance: unknown): LLMProvider | undefined {
|
|
90
129
|
try {
|
|
91
130
|
// The clientInstance might be a sub-object (like Completions) that has a _client property
|
|
92
131
|
// pointing to the actual OpenAI/AzureOpenAI client
|
|
@@ -124,24 +163,13 @@ function getLLMProvider(clientInstance: unknown): LLMProvider {
|
|
|
124
163
|
}
|
|
125
164
|
|
|
126
165
|
if (host && typeof host === "string") {
|
|
127
|
-
|
|
128
|
-
if (host.includes("api.openai.com")) {
|
|
129
|
-
return LLMProvider.OPENAI;
|
|
130
|
-
} else if (host.includes("openai.azure.com")) {
|
|
131
|
-
return LLMProvider.AZURE;
|
|
132
|
-
} else if (host.includes("api.microsoft.com")) {
|
|
133
|
-
// Additional Azure endpoint pattern
|
|
134
|
-
return LLMProvider.AZURE;
|
|
135
|
-
}
|
|
166
|
+
return getProviderFromHost(host);
|
|
136
167
|
}
|
|
137
168
|
} catch (error) {
|
|
138
|
-
// If we can't determine, default to regular OpenAI
|
|
139
169
|
diag.debug("Failed to determine LLM provider from instance", error);
|
|
140
170
|
}
|
|
141
|
-
|
|
142
|
-
// Default to OpenAI if we can't determine
|
|
143
|
-
return LLMProvider.OPENAI;
|
|
144
171
|
}
|
|
172
|
+
|
|
145
173
|
/**
|
|
146
174
|
* An auto instrumentation class for OpenAI that creates {@link https://github.com/Arize-ai/openinference/blob/main/spec/semantic_conventions.md|OpenInference} Compliant spans for the OpenAI API
|
|
147
175
|
* @param instrumentationConfig The config for the instrumentation @see {@link InstrumentationConfig}
|
|
@@ -294,6 +322,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<typeof openai> {
|
|
|
294
322
|
// Override the model from the value sent by the server
|
|
295
323
|
[SemanticConventions.LLM_MODEL_NAME]: result.model,
|
|
296
324
|
...getChatCompletionLLMOutputMessagesAttributes(result),
|
|
325
|
+
...getChatCompletionFinishReasonAttributes(result),
|
|
297
326
|
...getUsageAttributes(result),
|
|
298
327
|
});
|
|
299
328
|
span.setStatus({ code: SpanStatusCode.OK });
|
|
@@ -400,6 +429,7 @@ export class OpenAIInstrumentation extends InstrumentationBase<typeof openai> {
|
|
|
400
429
|
[SemanticConventions.EMBEDDING_MODEL_NAME]: body.model,
|
|
401
430
|
[SemanticConventions.INPUT_VALUE]: isStringInput ? input : JSON.stringify(input),
|
|
402
431
|
[SemanticConventions.INPUT_MIME_TYPE]: isStringInput ? MimeType.TEXT : MimeType.JSON,
|
|
432
|
+
[SemanticConventions.LLM_SYSTEM]: LLMSystem.OPENAI,
|
|
403
433
|
[SemanticConventions.LLM_PROVIDER]: getLLMProvider(this),
|
|
404
434
|
...getEmbeddingTextAttributes(body),
|
|
405
435
|
},
|
|
@@ -762,6 +792,19 @@ function getChatCompletionLLMOutputMessagesAttributes(chatCompletion: ChatComple
|
|
|
762
792
|
}, {} as Attributes);
|
|
763
793
|
}
|
|
764
794
|
|
|
795
|
+
/**
|
|
796
|
+
* Extracts the llm.finish_reason attribute from a chat completion response.
|
|
797
|
+
*/
|
|
798
|
+
function getChatCompletionFinishReasonAttributes(chatCompletion: ChatCompletion): Attributes {
|
|
799
|
+
const choice = chatCompletion.choices[0];
|
|
800
|
+
if (!choice?.finish_reason) {
|
|
801
|
+
return {};
|
|
802
|
+
}
|
|
803
|
+
return {
|
|
804
|
+
[SemanticConventions.LLM_FINISH_REASON]: choice.finish_reason,
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
765
808
|
function getChatCompletionOutputMessageAttributes(message: ChatCompletionMessage): Attributes {
|
|
766
809
|
const role = message.role;
|
|
767
810
|
const attributes: Attributes = {
|
|
@@ -856,6 +899,7 @@ async function consumeChatCompletionStreamChunks(stream: Stream<ChatCompletionCh
|
|
|
856
899
|
// So the final tool and function calls need to be aggregated
|
|
857
900
|
// across chunks
|
|
858
901
|
const toolAndFunctionCallAttributes: Attributes = {};
|
|
902
|
+
let finishReason: string | undefined;
|
|
859
903
|
// The first message is for the assistant response so we start at 1
|
|
860
904
|
for await (const chunk of stream) {
|
|
861
905
|
if (chunk.choices.length <= 0) {
|
|
@@ -865,6 +909,9 @@ async function consumeChatCompletionStreamChunks(stream: Stream<ChatCompletionCh
|
|
|
865
909
|
if (choice.delta.content) {
|
|
866
910
|
streamResponse += choice.delta.content;
|
|
867
911
|
}
|
|
912
|
+
if (choice.finish_reason) {
|
|
913
|
+
finishReason = choice.finish_reason;
|
|
914
|
+
}
|
|
868
915
|
// Accumulate the tool and function call attributes
|
|
869
916
|
const toolAndFunctionCallAttributesDiff =
|
|
870
917
|
getToolAndFunctionCallAttributesFromStreamChunk(chunk);
|
|
@@ -885,6 +932,9 @@ async function consumeChatCompletionStreamChunks(stream: Stream<ChatCompletionCh
|
|
|
885
932
|
[`${messageIndexPrefix}${SemanticConventions.MESSAGE_CONTENT}`]: streamResponse,
|
|
886
933
|
[`${messageIndexPrefix}${SemanticConventions.MESSAGE_ROLE}`]: "assistant",
|
|
887
934
|
};
|
|
935
|
+
if (finishReason) {
|
|
936
|
+
attributes[SemanticConventions.LLM_FINISH_REASON] = finishReason;
|
|
937
|
+
}
|
|
888
938
|
// Add the tool and function call attributes
|
|
889
939
|
for (const [key, value] of Object.entries(toolAndFunctionCallAttributes)) {
|
|
890
940
|
attributes[`${messageIndexPrefix}${key}`] = value;
|
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.0
|
|
2
|
+
export const VERSION = "4.1.0";
|