From 8fcd870867d55828f8f486b0c0a8219f83bd322f Mon Sep 17 00:00:00 2001 From: horita-yuya Date: Wed, 24 Sep 2025 15:39:10 +0900 Subject: [PATCH 1/6] Support citations in amazon-bedrock-provider --- .changeset/silver-falcons-count.md | 5 + .../amazon-bedrock/src/bedrock-api-types.ts | 3 + .../src/bedrock-chat-options.ts | 23 +++ .../convert-to-bedrock-chat-messages.test.ts | 161 ++++++++++++++++++ .../src/convert-to-bedrock-chat-messages.ts | 20 +++ 5 files changed, 212 insertions(+) create mode 100644 .changeset/silver-falcons-count.md diff --git a/.changeset/silver-falcons-count.md b/.changeset/silver-falcons-count.md new file mode 100644 index 000000000000..cfdbd09a8198 --- /dev/null +++ b/.changeset/silver-falcons-count.md @@ -0,0 +1,5 @@ +--- +'@ai-sdk/amazon-bedrock': patch +--- + +Support citations in amazon-bedrock-provider diff --git a/packages/amazon-bedrock/src/bedrock-api-types.ts b/packages/amazon-bedrock/src/bedrock-api-types.ts index cfe3965f86c6..6e75f32bfe98 100644 --- a/packages/amazon-bedrock/src/bedrock-api-types.ts +++ b/packages/amazon-bedrock/src/bedrock-api-types.ts @@ -127,6 +127,9 @@ export interface BedrockDocumentBlock { source: { bytes: string; }; + citations?: { + enabled: boolean; + }; }; } diff --git a/packages/amazon-bedrock/src/bedrock-chat-options.ts b/packages/amazon-bedrock/src/bedrock-chat-options.ts index 847d197af005..7b2532e68e12 100644 --- a/packages/amazon-bedrock/src/bedrock-chat-options.ts +++ b/packages/amazon-bedrock/src/bedrock-chat-options.ts @@ -65,6 +65,29 @@ export type BedrockChatModelId = | 'us.meta.llama4-maverick-17b-instruct-v1:0' | (string & {}); +/** + * Bedrock file part provider options for document-specific features. + * These options apply to individual file parts (documents). + */ +export const bedrockFilePartProviderOptions = z.object({ + /** + * Citation configuration for this document. + * When enabled, this document will generate citations in the response. + */ + citations: z + .object({ + /** + * Enable citations for this document + */ + enabled: z.boolean(), + }) + .optional(), +}); + +export type BedrockFilePartProviderOptions = z.infer< + typeof bedrockFilePartProviderOptions +>; + export const bedrockProviderOptions = z.object({ /** * Additional inference parameters that the model supports, diff --git a/packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.test.ts b/packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.test.ts index f44f77ea91cb..95f4a13c13be 100644 --- a/packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.test.ts +++ b/packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.test.ts @@ -749,6 +749,167 @@ describe('tool messages', () => { }); }); +describe('citations', () => { + it('should handle citations enabled for PDF', async () => { + const pdfData = new Uint8Array([0, 1, 2, 3]); + + const result = await convertToBedrockChatMessages([ + { + role: 'user', + content: [ + { + type: 'file', + data: Buffer.from(pdfData).toString('base64'), + mediaType: 'application/pdf', + providerOptions: { + bedrock: { + citations: { + enabled: true, + }, + }, + }, + }, + ], + }, + ]); + + expect(result.messages[0].content[0]).toEqual({ + document: { + format: 'pdf', + name: 'document-1', + source: { + bytes: 'AAECAw==', + }, + citations: { + enabled: true, + }, + }, + }); + }); + + it('should handle citations disabled for PDF', async () => { + const pdfData = new Uint8Array([0, 1, 2, 3]); + + const result = await convertToBedrockChatMessages([ + { + role: 'user', + content: [ + { + type: 'file', + data: Buffer.from(pdfData).toString('base64'), + mediaType: 'application/pdf', + providerOptions: { + bedrock: { + citations: { + enabled: false, + }, + }, + }, + }, + ], + }, + ]); + + expect(result.messages[0].content[0]).toEqual({ + document: { + format: 'pdf', + name: 'document-1', + source: { + bytes: 'AAECAw==', + }, + }, + }); + }); + + it('should handle no citations specified for PDF (default)', async () => { + const pdfData = new Uint8Array([0, 1, 2, 3]); + + const result = await convertToBedrockChatMessages([ + { + role: 'user', + content: [ + { + type: 'file', + data: Buffer.from(pdfData).toString('base64'), + mediaType: 'application/pdf', + }, + ], + }, + ]); + + expect(result.messages[0].content[0]).toEqual({ + document: { + format: 'pdf', + name: 'document-1', + source: { + bytes: 'AAECAw==', + }, + }, + }); + }); + + it('should handle multiple PDFs with different citation settings', async () => { + const pdfData1 = new Uint8Array([0, 1, 2, 3]); + const pdfData2 = new Uint8Array([4, 5, 6, 7]); + + const result = await convertToBedrockChatMessages([ + { + role: 'user', + content: [ + { + type: 'file', + data: Buffer.from(pdfData1).toString('base64'), + mediaType: 'application/pdf', + providerOptions: { + bedrock: { + citations: { + enabled: true, + }, + }, + }, + }, + { + type: 'file', + data: Buffer.from(pdfData2).toString('base64'), + mediaType: 'application/pdf', + providerOptions: { + bedrock: { + citations: { + enabled: false, + }, + }, + }, + }, + ], + }, + ]); + + expect(result.messages[0].content).toEqual([ + { + document: { + format: 'pdf', + name: 'document-1', + source: { + bytes: 'AAECAw==', + }, + citations: { + enabled: true, + }, + }, + }, + { + document: { + format: 'pdf', + name: 'document-2', + source: { + bytes: 'BAUGBw==', + }, + }, + }, + ]); + }); +}); + describe('additional file format tests', () => { it('should throw an error for unsupported file mime type in user message content', async () => { await expect( diff --git a/packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.ts b/packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.ts index 51c4318e1549..3f945e62e8e8 100644 --- a/packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.ts +++ b/packages/amazon-bedrock/src/convert-to-bedrock-chat-messages.ts @@ -21,6 +21,7 @@ import { BedrockUserMessage, } from './bedrock-api-types'; import { bedrockReasoningMetadataSchema } from './bedrock-chat-language-model'; +import { bedrockFilePartProviderOptions } from './bedrock-chat-options'; function getCachePoint( providerMetadata: SharedV2ProviderMetadata | undefined, @@ -28,6 +29,18 @@ function getCachePoint( return providerMetadata?.bedrock?.cachePoint as BedrockCachePoint | undefined; } +async function shouldEnableCitations( + providerMetadata: SharedV2ProviderMetadata | undefined, +): Promise { + const bedrockOptions = await parseProviderOptions({ + provider: 'bedrock', + providerOptions: providerMetadata, + schema: bedrockFilePartProviderOptions, + }); + + return bedrockOptions?.citations?.enabled ?? false; +} + export async function convertToBedrockChatMessages( prompt: LanguageModelV2Prompt, ): Promise<{ @@ -108,11 +121,18 @@ export async function convertToBedrockChatMessages( }); } + const enableCitations = await shouldEnableCitations( + part.providerOptions, + ); + bedrockContent.push({ document: { format: getBedrockDocumentFormat(part.mediaType), name: generateDocumentName(), source: { bytes: convertToBase64(part.data) }, + ...(enableCitations && { + citations: { enabled: true }, + }), }, }); } From fa7c366b94ac7748076544260f359394fce8e72f Mon Sep 17 00:00:00 2001 From: horita-yuya Date: Thu, 25 Sep 2025 13:10:22 +0900 Subject: [PATCH 2/6] Add examples of citations for amazon bedrock --- .../01-ai-sdk-providers/08-amazon-bedrock.mdx | 44 +++++++++++++++++++ .../amazon-bedrock-document-citations.ts | 40 +++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts diff --git a/content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx b/content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx index 8fe252d2d175..eb6cdd2810f0 100644 --- a/content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx +++ b/content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx @@ -272,6 +272,50 @@ if (result.providerMetadata?.bedrock.trace) { See the [Amazon Bedrock Guardrails documentation](https://docs.aws.amazon.com/bedrock/latest/userguide/guardrails.html) for more information. +### Citations + +Amazon Bedrock supports citations for document-based inputs across compatible models. When enabled: +- Some models can read documents with visual understanding, not just extracting text +- Models can cite specific parts of documents you provide, making it easier to trace information back to its source (Not Supported Yet) + +```ts +import { bedrock } from '@ai-sdk/amazon-bedrock'; +import { generateObject } from 'ai'; +import { z } from 'zod'; +import fs from 'fs'; + +const result = await generateObject({ + model: bedrock('apac.anthropic.claude-sonnet-4-20250514-v1:0'), + schema: z.object({ + summary: z.string().describe('Summary of the PDF document'), + keyPoints: z.array(z.string()).describe('Key points from the PDF'), + }), + messages: [ + { + role: 'user', + content: [ + { + type: 'text', + text: 'Summarize this PDF and provide key points.', + }, + { + type: 'file', + data: fs.readFileSync('./document.pdf'), + mediaType: 'application/pdf', + providerOptions: { + bedrock: { + citations: { enabled: true }, + }, + }, + }, + ], + }, + ], +}); + +console.log('Response:', result.object); +``` + ### Cache Points diff --git a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts new file mode 100644 index 000000000000..d0ac0085f985 --- /dev/null +++ b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts @@ -0,0 +1,40 @@ +import { bedrock } from '@ai-sdk/amazon-bedrock'; +import { generateObject } from 'ai'; +import { z } from 'zod'; +import fs from 'fs'; +import 'dotenv/config'; + +async function main() { + const result = await generateObject({ + model: bedrock('apac.anthropic.claude-sonnet-4-20250514-v1:0'), + schema: z.object({ + summary: z.string().describe('Summary of the PDF document'), + keyPoints: z.array(z.string()).describe('Key points from the PDF'), + }), + messages: [ + { + role: 'user', + content: [ + { + type: 'text', + text: 'Summarize this PDF and provide key points.', + }, + { + type: 'file', + data: fs.readFileSync('./document.pdf'), + mediaType: 'application/pdf', + providerOptions: { + bedrock: { + citations: { enabled: true }, + }, + }, + }, + ], + }, + ], + }); + + console.log('Response:', result.object); +} + +main().catch(console.error); \ No newline at end of file From 4668992a70051228a61dafe1a69772feeb0bc86d Mon Sep 17 00:00:00 2001 From: horita-yuya Date: Fri, 26 Sep 2025 07:14:35 +0900 Subject: [PATCH 3/6] Update examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts Co-authored-by: Gregor Martynus <39992+gr2m@users.noreply.github.com> --- .../src/generate-object/amazon-bedrock-document-citations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts index d0ac0085f985..21cc783e2d47 100644 --- a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts +++ b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts @@ -21,7 +21,7 @@ async function main() { }, { type: 'file', - data: fs.readFileSync('./document.pdf'), + data: fs.readFileSync('./data/ai.pdf'), mediaType: 'application/pdf', providerOptions: { bedrock: { From 47e5cc07c9ee842371551f1ff24c8f6e25957f38 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 25 Sep 2025 15:34:10 -0700 Subject: [PATCH 4/6] Apply suggestion from @gr2m --- .../src/generate-object/amazon-bedrock-document-citations.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts index 21cc783e2d47..1bd7dd4407bc 100644 --- a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts +++ b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts @@ -6,7 +6,7 @@ import 'dotenv/config'; async function main() { const result = await generateObject({ - model: bedrock('apac.anthropic.claude-sonnet-4-20250514-v1:0'), + model: bedrock('us.anthropic.claude-sonnet-4-20250514-v1:0'), schema: z.object({ summary: z.string().describe('Summary of the PDF document'), keyPoints: z.array(z.string()).describe('Key points from the PDF'), From 42723a6260ff4d47d6718c713832035734b84b1e Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 25 Sep 2025 15:39:49 -0700 Subject: [PATCH 5/6] style: prettier --- .../providers/01-ai-sdk-providers/08-amazon-bedrock.mdx | 1 + .../generate-object/amazon-bedrock-document-citations.ts | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx b/content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx index eb6cdd2810f0..f08ad2aff397 100644 --- a/content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx +++ b/content/providers/01-ai-sdk-providers/08-amazon-bedrock.mdx @@ -275,6 +275,7 @@ See the [Amazon Bedrock Guardrails documentation](https://docs.aws.amazon.com/be ### Citations Amazon Bedrock supports citations for document-based inputs across compatible models. When enabled: + - Some models can read documents with visual understanding, not just extracting text - Models can cite specific parts of documents you provide, making it easier to trace information back to its source (Not Supported Yet) diff --git a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts index 1bd7dd4407bc..5d82f68ecbe8 100644 --- a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts +++ b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts @@ -1,8 +1,9 @@ -import { bedrock } from '@ai-sdk/amazon-bedrock'; +import { bedrock, BedrockProviderOptions } from '@ai-sdk/amazon-bedrock'; import { generateObject } from 'ai'; import { z } from 'zod'; import fs from 'fs'; import 'dotenv/config'; +import { BedrockFilePartProviderOptions } from '../../../../packages/amazon-bedrock/src/bedrock-chat-options'; async function main() { const result = await generateObject({ @@ -26,7 +27,7 @@ async function main() { providerOptions: { bedrock: { citations: { enabled: true }, - }, + } satisfies BedrockFilePartProviderOptions, }, }, ], @@ -34,7 +35,7 @@ async function main() { ], }); - console.log('Response:', result.object); + console.log('Response:', JSON.stringify(result, null, 2)); } -main().catch(console.error); \ No newline at end of file +main().catch(console.error); From 3f42708dd38a18f96c34da0fb23e7033452ec7b0 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Thu, 25 Sep 2025 16:08:00 -0700 Subject: [PATCH 6/6] Enable citations in Bedrock provider options --- .../src/generate-object/amazon-bedrock-document-citations.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts index 5d82f68ecbe8..520605cc0d7e 100644 --- a/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts +++ b/examples/ai-core/src/generate-object/amazon-bedrock-document-citations.ts @@ -3,7 +3,6 @@ import { generateObject } from 'ai'; import { z } from 'zod'; import fs from 'fs'; import 'dotenv/config'; -import { BedrockFilePartProviderOptions } from '../../../../packages/amazon-bedrock/src/bedrock-chat-options'; async function main() { const result = await generateObject({ @@ -27,7 +26,7 @@ async function main() { providerOptions: { bedrock: { citations: { enabled: true }, - } satisfies BedrockFilePartProviderOptions, + }, }, }, ],