Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -701,13 +701,15 @@ function getOutputMessages(
}

/**
* The AI SDK TypeSafe provider moves each answer's `confidence` out of the answers into
* `providerMetadata.typesafe.confidence` (keyed by question id). Put it back so decide answers keep it.
* The AI SDK TypeSafe and OpenAI providers move each answer's `confidence` out of the answers into
* `providerMetadata.<provider>.confidence` (keyed by question id). Put it back so decide answers keep it.
*/
function withProviderConfidence(result: Record<string, unknown>): unknown {
const { answers, providerMetadata } = result;
const typesafe = isObjectLike(providerMetadata) ? providerMetadata.typesafe : undefined;
const confidence = isObjectLike(typesafe) && isObjectLike(typesafe.confidence) ? typesafe.confidence : undefined;
const metadata = isObjectLike(providerMetadata)
? [providerMetadata.typesafe, providerMetadata.openai].find(m => isObjectLike(m) && isObjectLike(m.confidence))
: undefined;
const confidence = isObjectLike(metadata) && isObjectLike(metadata.confidence) ? metadata.confidence : undefined;
if (!confidence || !isObjectLike(answers)) {
return answers;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
import { GEN_AI_OUTPUT_MESSAGES } from '@sentry/conventions/attributes';
import { GEN_AI_DECIDE } from '@sentry/conventions/op';
import { getMainCarrier, setCurrentClient, spanToStaticSpanJSON } from '@sentry/core';
import type { Span } from '@sentry/core';
Expand Down Expand Up @@ -41,7 +42,7 @@ describe('Vercel AI decide spans', () => {
recordOutputs: true,
},
result: { answers: { wantsRefund: { type: 'boolean', probability: 0.99 } } },
} as unknown as Message;
} satisfies Message;

const span = createSpanFromMessage(message, {} as Parameters<typeof createSpanFromMessage>[1])!;
expect(span).toBeDefined();
Expand All @@ -51,8 +52,35 @@ describe('Vercel AI decide spans', () => {
const json = spanToStaticSpanJSON(endedSpans[0]!);
expect(json.description).toBe('decide typesafe-ai/jev');
expect(json.op).toBe(GEN_AI_DECIDE);
expect(JSON.parse(json.data?.['gen_ai.output.messages'] as string)).toEqual([
expect(JSON.parse(json.data?.[GEN_AI_OUTPUT_MESSAGES] as string)).toEqual([
{ type: 'evaluation', answers: { wantsRefund: { type: 'boolean', probability: 0.99 } } },
]);
});

it.each(['typesafe', 'openai'])('restores answer confidence from `providerMetadata.%s`', provider => {
const message = {
type: 'experimental_decide',
event: {
provider,
modelId: 'gpt-6-luna',
state: 'I was charged twice',
questions: { department: { type: 'choice', criteria: { billing: 'Charges', support: 'Other' } } },
recordInputs: true,
recordOutputs: true,
},
result: {
answers: { department: { type: 'choice', choice: 'billing' } },
providerMetadata: { [provider]: { confidence: { department: 0.91 } } },
},
} satisfies Message;

const span = createSpanFromMessage(message, {} as Parameters<typeof createSpanFromMessage>[1])!;
enrichSpanOnEnd(span, message, {} as Parameters<typeof enrichSpanOnEnd>[2]);
span.end();

const json = spanToStaticSpanJSON(endedSpans[0]!);
expect(JSON.parse(json.data?.[GEN_AI_OUTPUT_MESSAGES] as string)).toEqual([
{ type: 'evaluation', answers: { department: { type: 'choice', choice: 'billing', confidence: 0.91 } } },
]);
Comment thread
cursor[bot] marked this conversation as resolved.
});
});
Loading