in packages/instrumentation-openai/src/instrumentation.ts [399:469]
for await (const chunk of streamIter as any) {
yield chunk;
// Gather telemetry from this chunk.
debug('OpenAI.Chat.Completions.create stream chunk: %O', chunk);
if (config.captureMessageContent) {
const contentPart = chunk.choices[0]?.delta?.content;
if (contentPart) {
contentParts.push(contentPart);
}
}
// Assume delta.tool_calls, if exists, is an array of length 1.
const toolCallPart = chunk.choices[0]?.delta?.tool_calls?.[0];
if (toolCallPart) {
if (toolCallPart.id) {
// First chunk in a tool call.
toolCalls.push({
id: toolCallPart.id,
type: toolCallPart.type,
function: {
name: toolCallPart.function?.name,
arguments: toolCallPart.function?.arguments ?? '',
},
});
} else if (toolCalls.length > 0) {
// A tool call chunk with more of the `function.arguments`.
toolCalls[toolCalls.length - 1].function.arguments +=
toolCallPart.function?.arguments ?? '';
}
}
if (!id && chunk.id) {
id = chunk.id;
span.setAttribute(ATTR_GEN_AI_RESPONSE_ID, id);
}
if (!model && chunk.model) {
model = chunk.model;
span.setAttribute(ATTR_GEN_AI_RESPONSE_MODEL, model);
}
if (!role) {
role = chunk.choices[0]?.delta?.role;
}
if (!finishReason) {
finishReason = chunk.choices[0]?.finish_reason;
if (finishReason) {
span.setAttribute(ATTR_GEN_AI_RESPONSE_FINISH_REASONS, [
finishReason,
]);
}
}
if (chunk.usage) {
// A final usage chunk if `stream_options.include_usage: true`.
span.setAttribute(
ATTR_GEN_AI_USAGE_INPUT_TOKENS,
chunk.usage.prompt_tokens
);
span.setAttribute(
ATTR_GEN_AI_USAGE_OUTPUT_TOKENS,
chunk.usage.completion_tokens
);
this._genaiClientTokenUsage.record(chunk.usage.prompt_tokens, {
...commonAttrs,
[ATTR_GEN_AI_RESPONSE_MODEL]: model,
[ATTR_GEN_AI_TOKEN_TYPE]: 'input',
});
this._genaiClientTokenUsage.record(chunk.usage.completion_tokens, {
...commonAttrs,
[ATTR_GEN_AI_RESPONSE_MODEL]: model,
[ATTR_GEN_AI_TOKEN_TYPE]: 'output',
});
}
}