Skip to content

Commit faacd1b

Browse files
authored
Fix case where bedrock content blocks would be populated with 'null' instead of 'undefined. (#2101)
1 parent b17a6a6 commit faacd1b

File tree

5 files changed

+90
-1
lines changed

5 files changed

+90
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@aws-amplify/ai-constructs': patch
3+
---
4+
5+
Fix case where bedrock content blocks would be populated with 'null' instead of 'undefined.

packages/ai-constructs/API.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,12 @@ type ConversationMessageContentBlock = bedrock.ContentBlock | {
7272
bytes: string;
7373
};
7474
};
75+
text?: never;
76+
document?: never;
77+
toolUse?: never;
78+
toolResult?: never;
79+
guardContent?: never;
80+
$unknown?: never;
7581
};
7682

7783
// @public (undocumented)

packages/ai-constructs/src/conversation/runtime/conversation_message_history_retriever.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,58 @@ void describe('Conversation message history retriever', () => {
342342
},
343343
],
344344
},
345+
{
346+
name: 'Replaces null values with undefined',
347+
mockListResponseMessages: [
348+
{
349+
id: event.currentMessageId,
350+
conversationId: event.conversationId,
351+
role: 'user',
352+
content: [
353+
{
354+
text: 'some_text',
355+
// @ts-expect-error Intentionally providing null outside of typing
356+
image: null,
357+
// @ts-expect-error Intentionally providing null outside of typing
358+
document: null,
359+
// @ts-expect-error Intentionally providing null outside of typing
360+
toolUse: null,
361+
// @ts-expect-error Intentionally providing null outside of typing
362+
toolResult: null,
363+
// @ts-expect-error Intentionally providing null outside of typing
364+
guardContent: null,
365+
// @ts-expect-error Intentionally providing null outside of typing
366+
$unknown: null,
367+
},
368+
{
369+
// @ts-expect-error Intentionally providing null outside of typing
370+
text: null,
371+
document: { format: 'csv', name: 'test_name', source: undefined },
372+
},
373+
],
374+
},
375+
],
376+
expectedMessages: [
377+
{
378+
role: 'user',
379+
content: [
380+
{
381+
text: 'some_text',
382+
image: undefined,
383+
document: undefined,
384+
toolUse: undefined,
385+
toolResult: undefined,
386+
guardContent: undefined,
387+
$unknown: undefined,
388+
},
389+
{
390+
text: undefined,
391+
document: { format: 'csv', name: 'test_name', source: undefined },
392+
},
393+
],
394+
},
395+
],
396+
},
345397
];
346398

347399
for (const testCase of testCases) {

packages/ai-constructs/src/conversation/runtime/conversation_message_history_retriever.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,24 @@ export class ConversationMessageHistoryRetriever {
235235
variables,
236236
});
237237

238-
return response.data[this.event.messageHistoryQuery.listQueryName].items;
238+
const items =
239+
response.data[this.event.messageHistoryQuery.listQueryName].items;
240+
241+
items.forEach((item) => {
242+
item.content?.forEach((contentBlock) => {
243+
let property: keyof typeof contentBlock;
244+
for (property in contentBlock) {
245+
// Deserialization of GraphQl query result sets these properties to 'null'
246+
// This can trigger Bedrock SDK validation as it expects 'undefined' if properties are not set.
247+
// We can't fix how GraphQl response is deserialized.
248+
// Therefore, we apply this transformation to fix the data.
249+
if (contentBlock[property] === null) {
250+
contentBlock[property] = undefined;
251+
}
252+
}
253+
});
254+
});
255+
256+
return items;
239257
};
240258
}

packages/ai-constructs/src/conversation/runtime/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ export type ConversationMessageContentBlock =
2626
// Upstream (Appsync) may send images in a form of Base64 encoded strings
2727
source: { bytes: string };
2828
};
29+
// These are needed so that union with other content block types works.
30+
// See https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-client-bedrock-runtime/TypeAlias/ContentBlock/.
31+
text?: never;
32+
document?: never;
33+
toolUse?: never;
34+
toolResult?: never;
35+
guardContent?: never;
36+
$unknown?: never;
2937
};
3038

3139
export type ToolDefinition<TJSONSchema extends JSONSchema = JSONSchema> = {

0 commit comments

Comments
 (0)