diff --git a/dev-packages/node-integration-tests/suites/aws-serverless/bedrock/test.ts b/dev-packages/node-integration-tests/suites/aws-serverless/bedrock/test.ts index 018326729159..de0d7878c826 100644 --- a/dev-packages/node-integration-tests/suites/aws-serverless/bedrock/test.ts +++ b/dev-packages/node-integration-tests/suites/aws-serverless/bedrock/test.ts @@ -34,7 +34,7 @@ function assertBedrockSpans(container: SerializedStreamedSpanContainer): void { expect(converseSpan!.attributes[GEN_AI_REQUEST_TOP_P].value).toBe(0.9); expect(converseSpan!.attributes[GEN_AI_USAGE_INPUT_TOKENS].value).toBe(12); expect(converseSpan!.attributes[GEN_AI_USAGE_OUTPUT_TOKENS].value).toBe(8); - expect(converseSpan!.attributes[GEN_AI_RESPONSE_FINISH_REASONS].value).toEqual(['end_turn']); + expect(converseSpan!.attributes[GEN_AI_RESPONSE_FINISH_REASONS].value).toBe('["end_turn"]'); // InvokeModel (non-streaming, anthropic.claude request/response body) const invokeModelSpan = container.items.find(span => span.name === `generate_content ${MODEL_ID}`); @@ -49,7 +49,7 @@ function assertBedrockSpans(container: SerializedStreamedSpanContainer): void { expect(invokeModelSpan!.attributes[GEN_AI_REQUEST_TOP_P].value).toBe(0.9); expect(invokeModelSpan!.attributes[GEN_AI_USAGE_INPUT_TOKENS].value).toBe(15); expect(invokeModelSpan!.attributes[GEN_AI_USAGE_OUTPUT_TOKENS].value).toBe(9); - expect(invokeModelSpan!.attributes[GEN_AI_RESPONSE_FINISH_REASONS].value).toEqual(['end_turn']); + expect(invokeModelSpan!.attributes[GEN_AI_RESPONSE_FINISH_REASONS].value).toBe('["end_turn"]'); } describe('awsIntegration - Bedrock', () => { diff --git a/packages/server-utils/src/integrations/aws-sdk/services/bedrock-runtime.ts b/packages/server-utils/src/integrations/aws-sdk/services/bedrock-runtime.ts index 97854b017c8c..c7ba139f9f48 100644 --- a/packages/server-utils/src/integrations/aws-sdk/services/bedrock-runtime.ts +++ b/packages/server-utils/src/integrations/aws-sdk/services/bedrock-runtime.ts @@ -296,7 +296,7 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, responseBody.results[0].tokenCount); } if (responseBody.results?.[0]?.completionReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.results[0].completionReason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([responseBody.results[0].completionReason])); } } else if (currentModelId.includes('amazon.nova')) { if (responseBody.usage !== undefined) { @@ -308,7 +308,7 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { } } if (responseBody.stopReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.stopReason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([responseBody.stopReason])); } } else if (currentModelId.includes('anthropic.claude')) { const usage = responseBody.usage; @@ -324,7 +324,7 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { ), ); if (responseBody.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.stop_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([responseBody.stop_reason])); } } else if (currentModelId.includes('meta.llama')) { if (responseBody.prompt_token_count !== undefined) { @@ -334,28 +334,31 @@ export class BedrockRuntimeServiceExtension implements ServiceExtension { span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, responseBody.generation_token_count); } if (responseBody.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.stop_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([responseBody.stop_reason])); } } else if (currentModelId.includes('cohere.command-r')) { if (responseBody.text !== undefined) { span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, Math.ceil(responseBody.text.length / 6)); } if (responseBody.finish_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.finish_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([responseBody.finish_reason])); } } else if (currentModelId.includes('cohere.command')) { if (responseBody.generations?.[0]?.text !== undefined) { span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, Math.ceil(responseBody.generations[0].text.length / 6)); } if (responseBody.generations?.[0]?.finish_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.generations[0].finish_reason]); + span.setAttribute( + GEN_AI_RESPONSE_FINISH_REASONS, + JSON.stringify([responseBody.generations[0].finish_reason]), + ); } } else if (currentModelId.includes('mistral')) { if (responseBody.outputs?.[0]?.text !== undefined) { span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, Math.ceil(responseBody.outputs[0].text.length / 6)); } if (responseBody.outputs?.[0]?.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [responseBody.outputs[0].stop_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([responseBody.outputs[0].stop_reason])); } } } @@ -445,7 +448,7 @@ function setStreamErrorStatus(span: Span, abortSignal: AbortSignal | undefined): function setStopReason(span: Span, stopReason: string | undefined): void { if (stopReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [stopReason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([stopReason])); } } @@ -503,7 +506,7 @@ function recordNovaAttributes(parsedChunk: ParsedChunk, span: Span): void { } } if (parsedChunk.messageStop?.stopReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.messageStop.stopReason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([parsedChunk.messageStop.stopReason])); } } @@ -514,7 +517,7 @@ function recordClaudeAttributes(parsedChunk: ParsedChunk, span: Span): void { span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, parsedChunk.usage.output_tokens); } if (parsedChunk.delta?.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.delta.stop_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([parsedChunk.delta.stop_reason])); } } @@ -526,7 +529,7 @@ function recordTitanAttributes(parsedChunk: ParsedChunk, span: Span): void { span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, parsedChunk.totalOutputTextTokenCount); } if (parsedChunk.completionReason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.completionReason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([parsedChunk.completionReason])); } } @@ -538,7 +541,7 @@ function recordLlamaAttributes(parsedChunk: ParsedChunk, span: Span): void { span.setAttribute(GEN_AI_USAGE_OUTPUT_TOKENS, parsedChunk.generation_token_count); } if (parsedChunk.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.stop_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([parsedChunk.stop_reason])); } } @@ -559,20 +562,20 @@ function recordInvocationMetrics(parsedChunk: ParsedChunk, span: Span): void { function recordMistralAttributes(parsedChunk: ParsedChunk, span: Span): void { recordInvocationMetrics(parsedChunk, span); if (parsedChunk.outputs?.[0]?.stop_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.outputs[0].stop_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([parsedChunk.outputs[0].stop_reason])); } } function recordCohereAttributes(parsedChunk: ParsedChunk, span: Span): void { recordInvocationMetrics(parsedChunk, span); if (parsedChunk.generations?.[0]?.finish_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.generations[0].finish_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([parsedChunk.generations[0].finish_reason])); } } function recordCohereRAttributes(parsedChunk: ParsedChunk, span: Span): void { recordInvocationMetrics(parsedChunk, span); if (parsedChunk.finish_reason !== undefined) { - span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, [parsedChunk.finish_reason]); + span.setAttribute(GEN_AI_RESPONSE_FINISH_REASONS, JSON.stringify([parsedChunk.finish_reason])); } }