🪨

Bedrock Converse API でPDFを読み込む

に公開

はじめに

Bedrock Converse APIとは、Bedrockとのメッセージの送受信を実装できるAPIです。
プログラムを介してBedrockを利用する場合、Converse APIを通して実装を行うことになります。
今回はConverse APIのPDF対応機能を用いて、Claude Sonnet 4にPDFを読み込ませていきます。

本記事は、社内作成ツールで利用した技術について書いています。
https://zenn.dev/ncdc/articles/d0518375c583db

実装

ローカルのPDFファイルを読み込み、Bedrock経由で要約させる実装を行います。

const client = new BedrockRuntimeClient({
    // あらかじめ.envに環境変数を設定しておく
    region: process.env.BEDROCK_AWS_REGION,
    credentials: {
      accessKeyId: process.env.BEDROCK_AWS_ACCESS_KEY_ID!,
      secretAccessKey: process.env.BEDROCK_AWS_SECRET_ACCESS_KEY!,
    },
});

const pdfPath = path.join(__dirname, "sample.pdf");
const pdfData = readFileSync(pdfPath);
      
const command = new ConverseCommand({
  modelId: "us.anthropic.claude-sonnet-4-20250514-v1:0",
  messages: [
    {
      role: "user",
      content: [
        {
          text: "PDFの内容を箇条書き3つに要約してください。",
        },
        // 以降、PDF読み込み設定
        {
          document: {
            source: {
              bytes: pdfData,
            },
            name: "sample-pdf",
            format: "pdf",
            citations: {
              enabled: true,
            },
          },
        },
      ],
    },
  ],
});

const response = await client.send(command);
const contentArray = response.output?.message?.content || [];
const fullText = contentArray
  .map(content => ('text' in content ? content.text : ''))
  .filter(Boolean)
  .join('');
console.log(fullText);

実行

今回読み込ませるsample.pdfは、2000文字程度の架空の業務報告書です。

実際に箇条書き3行に要約させてみた結果がこちらです。

PDFの内容を以下の3つの要点で要約いたします:

• **DXによる経営基盤の強化**:。し、することで業務プロセスの自動化を実現した。

• **人材育成とワークスタイル変革**:。。また、。

• **財務成果と顧客価値の向上**:。顧客面ではし、という成果を上げた。

箇条書きが不自然な日本語になっていますが、PDFに含まれるテキストについては読み取れているようです。

補足

上記のコードで利用しているConverseCommandの指定ルールについて解説します。
このオブジェクトでは、Bedrockに送信したいコンテンツをcontentへと指定します。

const command = new ConverseCommand({
  modelId: "us.anthropic.claude-sonnet-4-20250514-v1:0",
  messages: [
    {
      role: "user",
      content: [
        // こちらに配列で指定
      ]
    },
  ],
});  

配列で指定するとき、各オブジェクト直下のパラメータは単一とする必要があります。
例えば、以下のように指定すると型エラーとなります。

  content: [
    {
      text: "PDFの内容を箇条書き3つに要約してください。",
      document: {
        source: {
          bytes: pdfData,
        },
        name: "PDF",
        format: "pdf",
      },
    },
  ]

contentの型はContentBlock[]となっています。(参考)
例えばTextMemberにおいては、text以外のパラメータはneverとして指定できないように定義されています。
このため、複数のデータ種別を送りたい場合は、1つずつ配列に含めることが必要です。

export declare namespace ContentBlock {
    /**
     * <p>Text to include in the message.</p>
     * @public
     */
    interface TextMember {
        text: string;
        image?: never;
        document?: never;
        video?: never;
        toolUse?: never;
        toolResult?: never;
        guardContent?: never;
        cachePoint?: never;
        reasoningContent?: never;
        citationsContent?: never;
        $unknown?: never;
    }
    /**
     * <p>Image to include in the message. </p> <note> <p>This field is only supported by Anthropic Claude 3 models.</p> </note>
     * @public
     */
    interface ImageMember {
        text?: never;
        image: ImageBlock;
        document?: never;
        video?: never;
        toolUse?: never;
        toolResult?: never;
        guardContent?: never;
        cachePoint?: never;
        reasoningContent?: never;
        citationsContent?: never;
        $unknown?: never;
    }
    // 以降省略
NCDC テックブログ

Discussion