GenU のバックエンド (CDK) 詳細解説　 ⑩GenerativeAiUseCasesStack > Database, Api スタックの確認

## はじめに

皆さん、こんにちは。

私は業務でデータ利活用基盤を取り扱っていること、2024 AWS Japan Top Engineer に選出されたということから、[AWS GenU](https://aws-samples.github.io/generative-ai-use-cases-jp/) およびそれに必要なデータ基盤の探求 ([Snowflake](https://www.snowflake.com/ja/), [dbt](https://www.getdbt.com/), [Iceberg](https://iceberg.apache.org/), etc) に取り組む必要があると考えています。

本投稿では、[GenU のバックエンドである CDK コード](https://github.com/aws-samples/generative-ai-use-cases-jp/tree/main/packages/cdk)を詳細に解説します。
自身そして閲覧して頂いた皆様の GenU への理解が少しでも深まり、生成 AI の民主化につながっていければと考えています。

## 前回までのおさらい

前回までで、以下が完了しました。

- [①AWS CDK のセットアップ](https://qiita.com/siruko/items/fd25fdcf89615cb85262)
- [②AWS CDK の動作確認](https://qiita.com/siruko/items/73169f986b4173e3d3a5)
- [③GenU の概要](https://qiita.com/siruko/items/625801b9e1847b305c1e)
- [④GenU CDK スタックの概要](https://qiita.com/siruko/items/8570ed43f7162ea4b907)
- [⑤CloudFrontWafStack スタックの解説](https://qiita.com/siruko/items/30439576ee7c63165d21)
- [⑥RagKnowledgeBaseStack スタックの解説](https://qiita.com/siruko/items/1223c9d22e73168a8809)
- [⑦WebSearchAgentStack スタックの解説](https://qiita.com/siruko/items/aef0a9599df60d47eb1e)
- [⑧GuardrailStack スタックの解説](https://qiita.com/siruko/items/d16e9fe27df4673d7554)
- [⑨GenerativeAiUseCasesStack > Auth スタックの解説](https://qiita.com/siruko/items/0c14040a1af132f42382)

GenU の CDK は最大で以下の 6 つの子スタックを作成します。

- `CloudFrontWafStack`
- `RagKnowledgeBaseStack`
- `AgentStack`
- `GuardrailStack`
- `GenerativeAiUseCasesStack` ※メインスタック
- `DashboardStack`

第 9 回から GenU 内の本丸である `GenerativeAiUseCasesStack` スタックを解説しています。

### GenerativeAiUseCasesStack スタック

GenerativeAiUseCasesStack スタックでは、以下のリソースを作成しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217144/b37f0e2a-9b6f-44c8-8c85-a7fad70ec6d0.png)

- `Auth`
- `Database`
- `Api`
- `CommonWebAcl`
- `Web`
- `Rag`
- `RagKnowledgeBase`
- `UseCaseBuilder`
- `Transcribe`

今回は `Database`, `Api` リソースを解説していきます。

#### GenerativeAiUseCasesStack > Database リソース

Database リソースは、アーキテクチャ図でいうと以下の赤枠の部分にあたります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217144/4db7243f-159d-44f3-af5e-bf8036fd4dbe.png)

Database リソースの実体は `packages/cdk/lib/construct/database.ts` にあります。
以下のソースコードが Database の定義です。

```typescript:packages/cdk/lib/generative-ai-use-cases-stack.ts (抜粋)
    // Database
    const database = new Database(this, 'Database');
```

```typescript:packages/cdk/lib/construct/database.ts
import { Construct } from 'constructs';
import * as ddb from 'aws-cdk-lib/aws-dynamodb';

export class Database extends Construct {
  public readonly table: ddb.Table;
  public readonly feedbackIndexName: string;
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const feedbackIndexName = 'FeedbackIndex';
    const table = new ddb.Table(this, 'Table', {
      partitionKey: {
        name: 'id',
        type: ddb.AttributeType.STRING,
      },
      sortKey: {
        name: 'createdDate',
        type: ddb.AttributeType.STRING,
      },
      billingMode: ddb.BillingMode.PAY_PER_REQUEST,
    });

    table.addGlobalSecondaryIndex({
      indexName: feedbackIndexName,
      partitionKey: {
        name: 'feedback',
        type: ddb.AttributeType.STRING,
      },
    });

    this.table = table;
    this.feedbackIndexName = feedbackIndexName;
  }
}
```

この中では、[`DynamoDB`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.Table.html) テーブルを生成しています。

- 名前は `Table`
- パーティションキーに文字列型の `id` を指定
- ソートキーに文字列型の `createdDate` を指定
- 請求モードに[`PAY_PER_REQUEST:オンデマンドキャパシティモード`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_dynamodb.BillingMode.html) を指定
- GSI (グローバルセカンダリインデックス) に `FeedbackIndex` を指定
  - GSI のパーティションキーに文字列型の `feedback` を指定

#### GenerativeAiUseCasesStack > Api リソース

Api リソースは、アーキテクチャ図でいうと以下の赤枠の部分にあたります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/217144/c9b27ae6-301a-47ab-8961-e65954ddf7c6.png)

Api リソースの実体は `packages/cdk/lib/construct/api.ts` にあります。
以下のソースコードが Api の定義です。

```typescript:packages/cdk/lib/generative-ai-use-cases-stack.ts (抜粋)
    // API
    const api = new Api(this, 'API', {
      modelRegion: params.modelRegion,
      modelIds: params.modelIds,
      imageGenerationModelIds: params.imageGenerationModelIds,
      endpointNames: params.endpointNames,
      customAgents: params.agents,
      queryDecompositionEnabled: params.queryDecompositionEnabled,
      rerankingModelId: params.rerankingModelId,
      crossAccountBedrockRoleArn: params.crossAccountBedrockRoleArn,

      userPool: auth.userPool,
      idPool: auth.idPool,
      userPoolClient: auth.client,
      table: database.table,
      knowledgeBaseId: params.ragKnowledgeBaseId || props.knowledgeBaseId,
      agents: props.agents,
      guardrailIdentify: props.guardrailIdentifier,
      guardrailVersion: props.guardrailVersion,
    });
```

[`packages/cdk/lib/construct/api.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lib/construct/api.ts) (長いためリンク先のソースを参照)

相当長いです。これまで最長かもしれません。
この中では、以下の AWS リソースを生成するコンストラクトを定義しています。

- `Bucket`
- `NodejsFunction` ※ predict.ts
- `NodejsFunction` ※ predictStream.ts
- `NodejsFunction` ※ invokeFlow.ts
- `NodejsFunction` ※ predictTitle.ts
- `NodejsFunction` ※ generateImage.ts
- `NodejsFunction` ※ optimizePrompt.ts
- `PolicyStatement` ※ SageMaker Endpoint
- `PolicyStatement` ※ Bedrock
- `PolicyStatement` ※ crossAccountBedrockRoleArn の場合
- `NodejsFunction` ※ createChat.ts
- `NodejsFunction` ※ deleteChat.ts
- `NodejsFunction` ※ createMessages.ts
- `NodejsFunction` ※ updateTitle.ts
- `NodejsFunction` ※ listChats.ts
- `NodejsFunction` ※ findChatById.ts
- `NodejsFunction` ※ listMessages.ts
- `NodejsFunction` ※ updateFeedback.ts
- `NodejsFunction` ※ getWebText.ts
- `NodejsFunction` ※ createShareId.ts
- `NodejsFunction` ※ getSharedChat.ts
- `NodejsFunction` ※ findShareId.ts
- `NodejsFunction` ※ deleteShareId.ts
- `NodejsFunction` ※ listSystemContexts.ts
- `NodejsFunction` ※ createSystemContext.ts
- `NodejsFunction` ※ updateSystemContextTitle.ts
- `NodejsFunction` ※ deleteSystemContext.ts
- `NodejsFunction` ※ getFileUploadSignedUrl.ts
- `NodejsFunction` ※ getFileDownloadSignedUrl.ts
- `NodejsFunction` ※ deleteFile.ts
- `CognitoUserPoolsAuthorizer`
- `RestApi`
- 【CDK 用関数】allowDownloadFile

1 つのバケットと、26 の Lambda 関数 (API の実体)、1 つの認証付き RestAPI を作成しています。

ここでは、`Bucket` と `RestApi` に分けて解説していきます。

##### GenerativeAiUseCasesStack > Api > Bucket リソース

[`Bucket`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.Bucket.html) はファイル参照用の S3 バケットのリソースです。

以下のソースコードが Bucket の定義です。

```typescript:packages/cdk/lib/construct/api.ts (抜粋)
    // S3 (File Bucket)
    const fileBucket = new Bucket(this, 'FileBucket', {
      encryption: BucketEncryption.S3_MANAGED,
      removalPolicy: RemovalPolicy.DESTROY,
      autoDeleteObjects: true,
      enforceSSL: true,
      blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
    });
    fileBucket.addCorsRule({
      allowedOrigins: ['*'],
      allowedMethods: [HttpMethods.GET, HttpMethods.POST, HttpMethods.PUT],
      allowedHeaders: ['*'],
      exposedHeaders: [],
      maxAge: 3000,
    });
```

- 名前は `FileBucket`
- S3 マネージドキーでの暗号化
- スタック削除時はバケットを削除 (中に含まれるオブジェクトも削除)
- SSL 接続を強制する
- ブロックパブリックアクセスはブロック
- [CORS 設定](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_s3.CorsRule.html)を許可する
  - すべてのオリジン
  - GET/POST/PUT リクエストを許可
  - すべての Access-Control-Request-Headers を許可
  - アクセスできるヘッダ情報はなし
  - ブラウザのキャッシュ時間は 50 分(3000 秒)

##### GenerativeAiUseCasesStack > Api > RestApi リソース

[`RestApi`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html) は API GW の REST API リソースです。
また、Cognito ユーザプールをオーソライザーとして使用しています。

以下のソースコードが RestApi の定義です。

```typescript:packages/cdk/lib/construct/api.ts (抜粋)
    // API Gateway
    const authorizer = new CognitoUserPoolsAuthorizer(this, 'Authorizer', {
      cognitoUserPools: [userPool],
    });

    const commonAuthorizerProps = {
      authorizationType: AuthorizationType.COGNITO,
      authorizer,
    };

    const api = new RestApi(this, 'Api', {
      deployOptions: {
        stageName: 'api',
      },
      defaultCorsPreflightOptions: {
        allowOrigins: Cors.ALL_ORIGINS,
        allowMethods: Cors.ALL_METHODS,
      },
      cloudWatchRole: true,
    });

    api.addGatewayResponse('Api4XX', {
      type: ResponseType.DEFAULT_4XX,
      responseHeaders: {
        'Access-Control-Allow-Origin': "'*'",
      },
    });

    api.addGatewayResponse('Api5XX', {
      type: ResponseType.DEFAULT_5XX,
      responseHeaders: {
        'Access-Control-Allow-Origin': "'*'",
      },
    });
```

- [`CognitoUserPoolsAuthorizer`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.CognitoUserPoolsAuthorizer.html)
  - 名前は `Authorizer`
  - Cognito ユーザプールに Auth スタックで作成したユーザプールを指定
- [`RestApi`](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.RestApi.html)
  - 名前は `Api`
  - ステージ名は `api`
  - [CORS 設定](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_apigateway.CorsOptions.html)は「すべてのオリジンからすべてのメソッドのリクエストを許可」
  - CloudWatch ロールを自動的に作成

この API に対し、Lambda 関数を紐づけていきます。

###### RestApi リソース、メソッドと Lambda 関数のひも付き

`RestApi` リソースによって作成される API GW は、23 個の Lambda 関数と紐づいています。
なお、全てのメソッドに前述のオーソライザが指定されています。

API GW と Lambda 関数の紐づきは以下の通りです。

- `/chats` (POST) => [`createChatFunction`](#createchatfunction)
- `/chats` (GET) => [`listChatsFunction`](#listchatsfunction)
- `/chats/{chatId}` (GET) => [`findChatbyIdFunction`](#findchatbyidfunction)
- `/chats/{chatId}` (DELETE) => [`deleteChatFunction`](#deletechatfunction)
- `/chats/{chatId}/title` (PUT) => [`updateChatTitleFunction`](#updatechattitlefunction)
- `/chats/{chatId}/messages` (POST) => [`createMessagesFunction`](#createmessagesfunction)
- `/chats/{chatId}/messages` (GET) => [`listMessagesFunction`](#listmessagesfunction)
- `/chats/{chatId}/feedbacks` (POST) => [`updateFeedbackFunction`](#updatefeedbackfunction)
- `/file/url` (POST) => [`getSignedUrlFunction`](#getsignedurlfunction)
- `/file/url` (GET) => [`getFileDownloadSignedUrlFunction`](#getfiledownloadsignedurlfunction)
- `/file/{fileName}` (DELETE) => [`deleteFileFunction`](#deletefilefunction)
- `/image/generate` (POST) => [`generateImageFunction`](#generateimagefunction)
- `/predict` (POST) => [`predictFunction`](#predictfunction)
- `/predict/title` (POST) => [`predictTitleFunction`](#predicttitlefunction)
- `/shares/chat/{chatId}` (POST) => [`createShareId`](#createshareid)
- `/shares/chat/{chatId}` (GET) => [`findShareId`](#findshareid)
- `/shares/share/{shareId}` (GET) => [`getSharedChat`](#getsharedchat)
- `/shares/share/{shareId}` (DELETE) => [`deleteShareId`](#deleteshareid)
- `/systemcontexts` (POST) => [`createSystemContextFunction`](#createsystemcontextfunction)
- `/systemcontexts` (GET) => [`listSystemContextsFunction`](#listsystemcontextsfunction)
- `/systemcontexts/{systemContextId}` (DELETE) => [`deleteSystemContextFunction`](#deletesystemcontextfunction)
- `/systemcontexts/{systemContextId}/title` (PUT) => [`updateSystemContextTitleFunction`](#updatesystemcontexttitlefunction)
- `/web-text` (GET) => [`getWebTextFunction`](#getwebtextfunction)

##### API GW から呼び出される Lambda 関数

API GW から呼び出される Lambda 関数は以下の通りです。
ランタイムは全て NodeJS の最新版、タイムアウトは 15 分で定義されています。
メモリサイズは指定がなければデフォルト値です。

###### createChatFunction

- `/chats` (POST)
- 名前は `CreateChat`
- ソースコードは [`packages/cdk/lambda/createChat.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/createChat.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の createChat 関数を呼び出して DynamoDB テーブルにデータを登録
    - `id`: `user#` + Cognito ユーザ ID
    - `chatId`: `chat#` + ランダム UUID

###### listChatsFunction

- `/chats` (GET)
- 名前は `ListChats`
- ソースコードは [`packages/cdk/lambda/listChats.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/listChats.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の listChats 関数を呼び出して DynamoDB テーブルからデータを取得
    - `id`: `user#` + Cognito ユーザ ID
    - `取得件数 Limit`: 100 件
    - `ExclusiveStartKey`: `event.queryStringParameters` があればそのキーから取得する

###### findChatbyIdFunction

- `/chats/{chatId}` (GET)
- 名前は `FindChatbyId`
- ソースコードは [`packages/cdk/lambda/findChatById.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/findChatById.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の findChatById 関数を呼び出して DynamoDB テーブルからデータを取得
    - `id`: `user#` + Cognito ユーザ ID
    - `chatId`: `chat#` + パスパラメータの `chatId`

###### deleteChatFunction

- `/chats/{chatId}` (DELETE)
- 名前は `DeleteChat`
- ソースコードは [`packages/cdk/lambda/deleteChat.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/deleteChat.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の deleteChat 関数を呼び出して DynamoDB テーブルからデータを削除
    - `id`: `user#` + Cognito ユーザ ID
    - `chatId`: `chat#` + パスパラメータの `chatId`
  - 同 findShareId 関数を呼び出して DynamoDB テーブルから共有 ID を取得
    - `id`: `user#` + Cognito ユーザ ID + `_` + `chat#` + パスパラメータの `chatId`
  - 共有 ID があれば、同 deleteShareId 関数を呼び出して DynamoDB テーブルからデータを削除

###### updateChatTitleFunction

- `/chats/{chatId}/title` (PUT)
- 名前は `UpdateChatTitle`
- ソースコードは [`packages/cdk/lambda/updateTitle.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/updateTitle.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の findChatById 関数を呼び出して DynamoDB テーブルからデータを取得
    - `id`: `user#` + Cognito ユーザ ID
    - `chatId`: `chat#` + パスパラメータの `chatId`
  - 同 setChatTitle 関数を呼び出して DynamoDB テーブルのデータを更新
    - `id`: 取得した id
    - `createdDate`: 取得した createDate
    - `title`: `event.body.title`

###### createMessagesFunction

- `/chats/{chatId}/messages` (POST)
- 名前は `CreateMessages`
- ソースコードは [`packages/cdk/lambda/createMessages.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/createMessages.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の batchCreateMessages 関数を呼び出して DynamoDB テーブルにデータを登録
    - messages: 登録対象のメッセージ配列
      - `id`: `chat#` + パスパラメータの `chatId`
      - `createdDate`: `event.body.messages.createDate` もしくは現在日時
      - `messageId`: `event.body.messages.messageId`
      - `role`: `event.body.messages.role`
      - `content`: `event.body.messages.content`
      - `trace`: `event.body.messages.trace`
      - `extraData`: `event.body.messages.extraData`
      - `userId`: `user#` + Cognito ユーザ ID
      - `feedback`: 固定値 'none'
      - `usecase`: `event.body.messages.usecase`
      - `llmType`: `event.body.messages.llmType` もしくは空

###### listMessagesFunction

- `/chats/{chatId}/messages` (GET)
- 名前は `ListMessages`
- ソースコードは [`packages/cdk/lambda/listMessages.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/listMessages.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の findChatById 関数を呼び出して DynamoDB テーブルのデータを取得
    - id: `user#` + Cognito ユーザ ID
    - chatId: `chat#` + パスパラメータの `chatId`
  - 同 listMessages 関数を呼び出して DynamoDB テーブルのデータを取得
    - id: `chat#` + パスパラメータの `chatId`

###### updateFeedbackFunction

- `/chats/{chatId}/feedbacks` (POST)
- 名前は `UpdateFeedback`
- ソースコードは [`packages/cdk/lambda/updateFeedback.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/updateFeedback.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の updateFeedback 関数を呼び出して DynamoDB テーブルのデータを更新
    - `chatId`: `chat#` + パスパラメータの `chatId`
    - `createdDate`: `event.body.createdDate`
    - `feedback`: `event.body.feedback`
    - `reasons`: `event.body.reasons`
    - `detailedFeedback`: `event.body.detailedFeedback`
  - 戻り値に更新後の全属性を設定して終了

###### getSignedUrlFunction

- `/file/url` (POST)
- 名前は `GetSignedUrl`
- ソースコードは [`packages/cdk/lambda/getFileUploadSignedUrl.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/getFileUploadSignedUrl.ts)
- 環境変数
  - `BUCKET_NAME`: Bucket リソースで作成したファイル参照用の S3 バケット
- 処理概要
  - オブジェクト[アップロード用の署名付き URL を取得](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-s3-request-presigner/)
    - `Bucket`: 環境変数の `BUCKET_NAME`
    - `Key`: [ユニーク ID](https://www.npmjs.com/package/uuidv4) + `event.body.filename`
    - 有効期限は 1 時間 (3600 秒)
  - 戻り値にオブジェクトアップロード用の署名付き URL を設定して終了

###### getFileDownloadSignedUrlFunction

- `/file/url` (GET)
- 名前は `GetFileDownloadSignedUrlFunction`
- ソースコードは [`packages/cdk/lambda/getFileDownloadSignedUrl.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/getFileDownloadSignedUrl.ts)
- 処理概要
  - オブジェクト[ダウンロード用の署名付き URL を取得](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/Package/-aws-sdk-s3-request-presigner/)
    - `region`: クエリパラメータ文字列の `region`
    - `Bucket`: クエリパラメータ文字列の `bucketName`
    - `Key`: クエリパラメータ文字列の `filePrefix`
    - `ResponseContentType`: クエリパラメータ文字列の `contentType`
    - 有効期限は 1 分 (60 秒)
  - 戻り値にオブジェクトダウンロード用の署名付き URL を設定して終了

###### deleteFileFunction

- `/file/{fileName}` (DELETE)
- 名前は `DeleteFileFunction`
- ソースコードは [`packages/cdk/lambda/deleteFile.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/deleteFile.ts)
- 環境変数
  - `BUCKET_NAME`: Bucket リソースで作成したファイル参照用の S3 バケット
- 処理概要
  - オブジェクトを削除
    - `Bucket`: 環境変数の `BUCKET_NAME`
    - `Key`: クエリパラメータ文字列の `fileName`

###### generateImageFunction

- `/image/generate` (POST)
- 名前は `GenerateImage`
- ソースコードは [`packages/cdk/lambda/generateImage.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/generateImage.ts)
- 環境変数
  - `MODEL_REGION`: スタック作成時のパラメータ `modelRegion` (デフォルト値は `us-east-1`)
  - `MODEL_IDS`: スタック作成時のパラメータ `modelIds` (デフォルト値は以下)
    - `us.anthropic.claude-3-5-sonnet-20241022-v2:0`
    - `us.anthropic.claude-3-5-haiku-20241022-v1:0`
    - `us.amazon.nova-pro-v1:0`
    - `us.amazon.nova-lite-v1:0`
    - `us.amazon.nova-micro-v1:0`
  - `IMAGE_GENERATION_MODEL_IDS`: スタック作成時のパラメータ `imageGenerationModelIds` (デフォルト値は以下)
    - `amazon.nova-canvas-v1:0`
  - `CROSS_ACCOUNT_BEDROCK_ROLE_ARN`: スタック作成時のパラメータ `crossAccountBedrockRoleArn` (デフォルト値は null)
- 追加インストールモジュール
  - [`@aws-sdk/client-bedrock-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-runtime)
- 処理概要
  - パラメータから使用するモデル情報 (`event.body.model`) を取得する
    - デフォルト値は [`packages/cdk/lambda/utils/models.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/models.ts) で設定
    - `type`: `'bedrock' | 'bedrockAgent' | 'bedrockKb' | 'sagemaker'` (デフォルト値は `'bedrock'`)
    - `modelId`: デフォルト値は環境変数の `IMAGE_GENERATION_MODEL_IDS` の 1 件目
    - `modelParameters`: 任意で設定
    - `sessionId`: 任意で設定
  - [`packages/cdk/lambda/utils/api.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/api.ts)の generateImage 関数を呼び出して画像を生成
    - `type` が `bedrock` の場合 [`packages/cdk/lambda/utils/bedrockApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockApi.ts)
      - 環境変数の `CROSS_ACCOUNT_BEDROCK_ROLE_ARN` が指定されている場合、STS から認証情報を取得してクライアントを初期化
      - 画像を生成
        - `modelId`: モデル情報の `modelId`
        - `body`: モデルに応じたパラメータを[`packages/cdk/lambda/utils/models.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/models.ts)で生成して指定
        - `contentType`: 固定値 `'application/json'`
    - `type` が `bedrockAgent` の場合 [`packages/cdk/lambda/utils/bedrockAgentApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockAgentApi.ts)
      - 定義なし (恐らくエラー)
    - `type` が `bedrockKb` の場合 [`packages/cdk/lambda/utils/bedrockKbApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockKbApi.ts)
      - 定義なし (恐らくエラー)
    - `type` が `sagemaker` の場合 [`packages/cdk/lambda/utils/sagemakerApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/sagemakerApi.ts)
      - エラー 'Not Implemented' を返却
  - 戻り値に画像データ (base64 エンコード) を設定して終了

###### predictFunction

- `/predict` (POST)
- 名前は `Predict`
- ソースコードは [`packages/cdk/lambda/predict.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/predict.ts)
- 環境変数
  - `MODEL_REGION`: スタック作成時のパラメータ `modelRegion` (デフォルト値は `us-east-1`)
  - `MODEL_IDS`: スタック作成時のパラメータ `modelIds` (デフォルト値は以下)
    - `us.anthropic.claude-3-5-sonnet-20241022-v2:0`
    - `us.anthropic.claude-3-5-haiku-20241022-v1:0`
    - `us.amazon.nova-pro-v1:0`
    - `us.amazon.nova-lite-v1:0`
    - `us.amazon.nova-micro-v1:0`
  - `IMAGE_GENERATION_MODEL_IDS`: スタック作成時のパラメータ `imageGenerationModelIds` (デフォルト値は以下)
    - `amazon.nova-canvas-v1:0`
  - `CROSS_ACCOUNT_BEDROCK_ROLE_ARN`: スタック作成時のパラメータ `crossAccountBedrockRoleArn` (デフォルト値は null)
  - `GUARDRAIL_IDENTIFIER`: `GuardrailStack` スタックを生成している場合、その `guardrailIdentifier` を設定
  - `GUARDRAIL_VERSION`: `GuardrailStack` スタックを生成している場合、固定値 `'DRAFT'` を設定
- 追加インストールモジュール
  - [`@aws-sdk/client-bedrock-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-runtime)
- 処理概要
  - パラメータから使用するモデル情報 (`event.body.model`) を取得する
    - デフォルト値は [`packages/cdk/lambda/utils/models.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/models.ts) で設定
    - `type`: `'bedrock' | 'bedrockAgent' | 'bedrockKb' | 'sagemaker'` (デフォルト値は `'bedrock'`)
    - `modelId`: デフォルト値は環境変数の `IMAGE_GENERATION_MODEL_IDS` の 1 件目
    - `modelParameters`: 任意で設定
    - `sessionId`: 任意で設定
  - [`packages/cdk/lambda/utils/api.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/api.ts)の invoke 関数を呼び出してテキストを生成
    - `type` が `bedrock` の場合 [`packages/cdk/lambda/utils/bedrockApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockApi.ts)
      - 環境変数の `CROSS_ACCOUNT_BEDROCK_ROLE_ARN` が指定されている場合、STS から認証情報を取得してクライアントを初期化
      - モデルに応じたパラメータを[`packages/cdk/lambda/utils/models.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/models.ts)で指定してテキスト生成
        - `modelId`: モデル情報の `modelId`
        - `messages`: `event.body.messages`
        - `id`: `event.body.id`
    - `type` が `bedrockAgent` の場合 [`packages/cdk/lambda/utils/bedrockAgentApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockAgentApi.ts)
      - 定義なし
    - `type` が `bedrockKb` の場合 [`packages/cdk/lambda/utils/bedrockKbApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockKbApi.ts)
      - 定義なし
    - `type` が `sagemaker` の場合 [`packages/cdk/lambda/utils/sagemakerApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/sagemakerApi.ts)
      - `modelId`: モデル情報の `modelId`
      - `body`: モデルに応じたプロンプトを[`packages/cdk/lambda/utils/models.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/models.ts)で生成して指定
      - `ContentType`: 固定値 `'application/json'`
      - `Accept`: 固定値 `'application/json'`
  - 戻り値に生成したテキストを設定して終了

###### predictTitleFunction

- `/predict/title` (POST)
- 名前は `PredictTitle`
- ソースコードは [`packages/cdk/lambda/predictTitle.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/predictTitle.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
  - `MODEL_REGION`: スタック作成時のパラメータ `modelRegion` (デフォルト値は `us-east-1`)
  - `MODEL_IDS`: スタック作成時のパラメータ `modelIds` (デフォルト値は以下)
    - `us.anthropic.claude-3-5-sonnet-20241022-v2:0`
    - `us.anthropic.claude-3-5-haiku-20241022-v1:0`
    - `us.amazon.nova-pro-v1:0`
    - `us.amazon.nova-lite-v1:0`
    - `us.amazon.nova-micro-v1:0`
  - `IMAGE_GENERATION_MODEL_IDS`: スタック作成時のパラメータ `imageGenerationModelIds` (デフォルト値は以下)
    - `amazon.nova-canvas-v1:0`
  - `CROSS_ACCOUNT_BEDROCK_ROLE_ARN`: スタック作成時のパラメータ `crossAccountBedrockRoleArn` (デフォルト値は null)
  - `GUARDRAIL_IDENTIFIER`: `GuardrailStack` スタックを生成している場合、その `guardrailIdentifier` を設定
  - `GUARDRAIL_VERSION`: `GuardrailStack` スタックを生成している場合、固定値 `'DRAFT'` を設定
- 追加インストールモジュール
  - [`@aws-sdk/client-bedrock-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-runtime)
- 処理概要
  - パラメータから使用するモデル情報 (`event.body.model`) を取得する
    - デフォルト値は [`packages/cdk/lambda/utils/models.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/models.ts) で設定
    - `type`: `'bedrock' | 'bedrockAgent' | 'bedrockKb' | 'sagemaker'` (デフォルト値は `'bedrock'`)
    - `modelId`: デフォルト値は環境変数の `IMAGE_GENERATION_MODEL_IDS` の 1 件目
    - `modelParameters`: 任意で設定
    - `sessionId`: 任意で設定
  - 入力チェックを実施する (以下のいずれかが設定されていない場合、エラー)
    - `event.body.id`
    - `event.body.prompt`
    - `event.body.chat.id`
    - `event.body.chat.createdDate`
  - 環境変数の `MODEL_IDS` から軽量モデルを取得し、存在すれば優先的に使用する
  - [`packages/cdk/lambda/utils/api.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/api.ts)の invoke 関数を呼び出してタイトルを生成
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の setChatTitle 関数を呼び出して DynamoDB テーブルのデータを更新
    - `TableName`: 環境変数の `TABLE_NAME`
    - `id`: `event.body.chat.id`
    - `createdDate`: `event.body.chat.createdDate`
    - `title`: 生成したタイトル
  - 戻り値に生成したタイトルを設定して終了

###### createShareId

- `/shares/chat/{chatId}` (POST)
- 名前は `CreateShareId`
- ソースコードは [`packages/cdk/lambda/createShareId.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/createShareId.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の createShareId 関数を呼び出して DynamoDB テーブルのデータを登録
    - `itemShareId` データ
      - `id`: `user#` + Cognito ユーザ ID + `_` + `chat#` + パスパラメータの `chatId`
      - `createdDate`: 現在日時
      - `shareId`: `share#`+ ランダム ID 文字列
    - `itemUserIdAndChatId` データ
      - `id`: `share#`+ ランダム ID 文字列 ※上記同様
      - `createdDate`: 現在日時
      - `userId`: `user#` + Cognito ユーザ ID
      - `chatId`: `chat#` + パスパラメータの `chatId`
  - 戻り値に更新データを設定して終了

###### findShareId

- `/shares/chat/{chatId}` (GET)
- 名前は `FindShareId`
- ソースコードは [`packages/cdk/lambda/findShareId.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/main/packages/cdk/lambda/findShareId.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の findShareId 関数を呼び出して DynamoDB テーブルのデータを検索
    - `id`: `user#` + Cognito ユーザ ID + `_` + `chat#` + パスパラメータの `chatId`
  - 戻り値に取得データを設定して終了

###### getSharedChat

- `/shares/share/{shareId}` (GET)
- 名前は `GetSharedChat`
- ソースコードは [`packages/cdk/lambda/getSharedChat.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/main/packages/cdk/lambda/getSharedChat.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の findUserIdAndChatId 関数を呼び出して DynamoDB テーブルのデータを検索
    - `id`: `share#` + パスパラメータの `shareId`
  - 同 findChatById 関数を呼び出して DynamoDB テーブルのデータを検索
    - `userId`: 取得した `userID`
    - `chatId`: 取得した `chatID`
  - 同 listMessages 関数を呼び出して DynamoDB テーブルのデータを検索
    - `chatId`: 取得した `chatID`
  - 戻り値に取得データを設定して終了

###### deleteShareId

- `/shares/share/{shareId}` (DELETE)
- 名前は `DeleteShareId`
- ソースコードは [`packages/cdk/lambda/deleteShareId.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/deleteShareId.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の deleteShareId 関数を呼び出して DynamoDB テーブルのデータを削除
    - 同 findUserIdAndChatId 関数を呼び出して DynamoDB テーブルからユーザ、チャットデータを取得
      - `id`: `share#` + パスパラメータの `shareId`
    - 同 findShareId 関数を呼び出して DynamoDB テーブルから共有データを取得
      - `id`: 取得データの `userId` + `_` + 取得データの `chatId`
    - DynamoDB テーブルから共有データを削除
      - `id`: 共有データの `id`
      - `createdDate`: 共有データの `createdDate`
    - DynamoDB テーブルから共有データを削除
      - `id`: ユーザ、チャットデータの `id`
      - `createdDate`: ユーザ、チャットデータの `createdDate`

###### createSystemContextFunction

- `/systemcontexts` (POST)
- 名前は `CreateSystemContexts`
- ソースコードは [`packages/cdk/lambda/createSystemContext.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/createSystemContext.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の createSystemContext 関数を呼び出して DynamoDB テーブルのデータを登録
    - `id`: `systemContext#` + Cognito ユーザ ID
    - `createdDate`: 現在日時
    - `systemContextId`: `systemContext#` + ランダム UUID
    - `systemContext`: `event.body.systemContext`
    - `systemContextTitle`: `event.body.title`
  - 戻り値に登録データを設定して終了

###### listSystemContextsFunction

- `/systemcontexts` (GET)
- 名前は `ListSystemContexts`
- ソースコードは [`packages/cdk/lambda/listSystemContexts.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/listSystemContexts.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の listSystemContexts 関数を呼び出して DynamoDB テーブルのデータを登録
    - `id`: `systemContext#` + Cognito ユーザ ID
  - 戻り値に取得データを設定して終了

###### deleteSystemContextFunction

- `/systemcontexts/{systemContextId}` (DELETE)
- 名前は `DeleteSystemContexts`
- ソースコードは [`packages/cdk/lambda/deleteSystemContext.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/deleteSystemContext.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の deleteSystemContext 関数を呼び出して DynamoDB テーブルのデータを削除
    - 同 findSystemContextById 関数を呼び出して System Context データの取得
      - `id`: `systemContext#` + Cognito ユーザ ID
      - `systemContextId`: `systemContext#` + パスパラメータの `systemContextId`
    - DynamoDB テーブルのデータを削除
      - `id`: System Context データの `id`
      - `createdDate`: System Context データの `createdDate`

###### updateSystemContextTitleFunction

- `/systemcontexts/{systemContextId}/title` (PUT)
- 名前は `UpdateSystemContextTitle`
- ソースコードは [`packages/cdk/lambda/updateSystemContextTitle.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/updateSystemContextTitle.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - Cognito ユーザ ID を取得
  - [`packages/cdk/lambda/repository.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/80498fb1c5ab76621557a16b358c4905b9e8a0e4/packages/cdk/lambda/repository.ts)の updateSystemContextTitle 関数を呼び出して DynamoDB テーブルのデータを削除
    - 同 findSystemContextById 関数を呼び出して System Context データの取得
      - `id`: `systemContext#` + Cognito ユーザ ID
      - `systemContextId`: `systemContext#` + パスパラメータの `systemContextId`
    - DynamoDB テーブルのデータを削除
      - `id`: System Context データの `id`
      - `createdDate`: System Context データの `createdDate`
      - `systemContextTitle`: `event.body.title`
  - 戻り値に更新後のデータを設定して終了

###### getWebTextFunction

- `/web-text` (GET)
- 名前は `GetWebText`
- ソースコードは [`packages/cdk/lambda/getWebText.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/getWebText.ts)
- 環境変数
  - `TABLE_NAME`: Database リソースで作成した DynamoDB テーブル
- 処理概要
  - クエリ文字列の `url` の情報を取得
  - 取得した HTML タグをサニタイズ
  - [`node-html-parser`](https://www.npmjs.com/package/node-html-parser)で HTML をパース
    - コメントを削除
    - `script` タグのテキストコンテンツを保持しない
    - `noscript` タグのテキストコンテンツを保持しない
    - `style` タグのテキストコンテンツを保持しない
    - `pre` タグのテキストコンテンツを保持しない
  - パースしたテキストの `body` タグを空白を除いて取り出し
  - 戻り値に取得したデータを設定して終了

##### その他の Lambda 関数

API GW から呼び出される Lambda 関数以外に、以下の Lambda 関数が定義されています。

###### predictStreamFunction

- 名前は `PredictStream`
- ソースコードは [`packages/cdk/lambda/predictStream.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/predictStream.ts)
- メモリサイズは 256MB
- 環境変数
  - `USER_POOL_ID`: `Auth` スタックを作成している場合、`userPoolId` を設定
  - `USER_POOL_CLIENT_ID`: `Auth` スタックを作成している場合、`userPoolClientId` を設定
  - `MODEL_REGION`: スタック作成時のパラメータ `modelRegion` (デフォルト値は `us-east-1`)
  - `MODEL_IDS`: スタック作成時のパラメータ `modelIds` (デフォルト値は以下)
    - `us.anthropic.claude-3-5-sonnet-20241022-v2:0`
    - `us.anthropic.claude-3-5-haiku-20241022-v1:0`
    - `us.amazon.nova-pro-v1:0`
    - `us.amazon.nova-lite-v1:0`
    - `us.amazon.nova-micro-v1:0`
  - `IMAGE_GENERATION_MODEL_IDS`: スタック作成時のパラメータ `imageGenerationModelIds` (デフォルト値は以下)
    - `amazon.nova-canvas-v1:0`
  - `AGENT_MAP`: `Agent` スタックを作成している場合、作成したエージェント (SearchAgent, CodeInterpreterAgent) を設定
  - `CROSS_ACCOUNT_BEDROCK_ROLE_ARN`: スタック作成時のパラメータ `crossAccountBedrockRoleArn` (デフォルト値は null)
  - `BUCKET_NAME`: Bucket リソースで作成したファイル参照用の S3 バケット
  - `KNOWLEDGE_BASE_ID`: 以下が設定されている場合、設定 (上が優先)
    - スタック作成時のパラメータ `ragKnowledgeBaseId` (デフォルト値は null)
    - `RagKnowledgeBaseStack` を作成している場合、その `knowledgeBaseId` を設定
  - `GUARDRAIL_IDENTIFIER`: `GuardrailStack` スタックを生成している場合、その `guardrailIdentifier` を設定
  - `GUARDRAIL_VERSION`: `GuardrailStack` スタックを生成している場合、固定値 `'DRAFT'` を設定
  - `QUERY_DECOMPOSITION_ENABLED`: スタック作成時のパラメータ `queryDecompositionEnabled` (デフォルト値は false)
  - `RERANKING_MODEL_ID`: スタック作成時のパラメータ `rerankingModelId` (デフォルト値は null)
- 追加インストールモジュール
  - [`@aws-sdk/client-bedrock-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-runtime)
  - [`@aws-sdk/client-bedrock-agent-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-agent-runtime)
  - [`@aws-sdk/client-sagemaker-runtime`](https://www.npmjs.com/package/@aws-sdk/client-sagemaker-runtime)
- 処理概要
  - パラメータから使用するモデル情報 (`event.body.model`) を取得する
    - デフォルト値は [`packages/cdk/lambda/utils/models.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/models.ts) で設定
    - `type`: `'bedrock' | 'bedrockAgent' | 'bedrockKb' | 'sagemaker'` (デフォルト値は `'bedrock'`)
    - `modelId`: デフォルト値は環境変数の `IMAGE_GENERATION_MODEL_IDS` の 1 件目
    - `sessionId`: 任意で設定
  - [`packages/cdk/lambda/utils/api.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/api.ts) の invokeStream 関数を呼び出してテキストを生成
    - `type` が `bedrock` の場合 [`packages/cdk/lambda/utils/bedrockApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockApi.ts)
      - 環境変数の `CROSS_ACCOUNT_BEDROCK_ROLE_ARN` が指定されている場合、STS から認証情報を取得してクライアントを初期化
      - モデルに応じたパラメータを[`packages/cdk/lambda/utils/models.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/models.ts)で指定してテキスト生成
        - `modelId`: モデル情報の `modelId`
        - `messages`: `event.body.messages`
        - `id`: `event.body.id`
    - `type` が `bedrockAgent` の場合 [`packages/cdk/lambda/utils/bedrockAgentApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockAgentApi.ts) の invokeStream 関数を呼び出してテキストを生成
      - モデル情報の `modelId` と環境変数の `AGENT_MAP` から、`agentId`, `agentAliasId` を取得
      - `agentId`, `agentAliasId` からエージェントの情報を取得
      - エージェントを実行
        - `event.messages[最後の要素].extraData` からファイル情報を取得して設定
        - エージェント情報の `codeInterpreterEnabled` の値で `useCase` を設定
          - true の場合、`CODE_INTERPRETER`
          - false の場合、`CHAT`
        - `agentId`: 取得した `agentId`
        - `agentAliasId`: 取得した `agentAliasId`
        - `sessionId`: モデル情報の `sessionId`
        - `enableTrace`: 固定値 true
        - `inputText`: `event.messages[最後の要素].content`
      - 画像は S3 にアップロードし画像として設定
      - ファイルは S3 にアップロードしリファレンスを設定
      - 思考過程および Code Interpreter の実行コードを設定
      - ナレッジベース (RAG) があればソース URL を設定
    - `type` が `bedrockKb` の場合 [`packages/cdk/lambda/utils/bedrockKbApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockKbApi.ts) の invokeStream 関数を呼び出してテキストを生成
      - `event.body.idToken` を検証
      - エージェントを実行
        - `input`: `event.messages[最後の要素].content`
        - `sessionId`: モデル情報の `sessionId`
        - `retrieveAndGenerateConfiguration`
          - `type`: 固定値 `KNOWLEDGE_BASE`
          - `knowledgeBaseConfiguration`
            - `knowledgeBaseId`: 環境変数の `KNOWLEDGE_BASE_ID`
            - `modelArn`: モデル情報の `modelId`
            - Filter, Implicit Filter, Rerank を設定
      - ナレッジベース (RAG) 上の参照 URL を設定
      - 末尾にリファレンスを設定
    - `type` が `sagemaker` の場合 [`packages/cdk/lambda/utils/sagemakerApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/sagemakerApi.ts) の invokeStream 関数を呼び出してテキストを生成
      - コマンドを生成
        - `EndpointName`: モデル情報の `modelId`
        - `Body`: モデル情報の `modelId` と `event.body.messages` からテキストを取得
        - `ContentType`: 固定値 `application/json`
        - `Accept`: 固定値 `application/json`
      - コマンドを SageMakerRuntimeClient に送信
      - 取得したテキストをデコード
  - 戻り値に生成したテキストを設定して終了

###### invokeFlowFunction

- 名前は `InvokeFlow`
- ソースコードは [`packages/cdk/lambda/invokeFlow.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/invokeFlow.ts)
- 追加インストールモジュール
  - [`@aws-sdk/client-bedrock-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-runtime)
  - [`@aws-sdk/client-bedrock-agent-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-agent-runtime)
- 処理概要
  - [`packages/cdk/lambda/utils/bedrockFlowApi.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockFlowApi.ts) の invokeFlow 関数を呼び出してフローを実行
    - `flowIdentifier`: `event.flowIdentifier`
    - `flowAliasIdentifier`: `event.flowAliasIdentifier`
    - `inputs`:
      - `nodeName`: 固定値 'FlowInputNode'
      - `nodeOutputName`: 固定値 'document'
      - `content`:
        - `document`: `event.document`

###### optimizePromptFunction

- 名前は `OptimizePromptFunction`
- ソースコードは [`packages/cdk/lambda/optimizePrompt.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/optimizePrompt.ts)
- 環境変数
  - `MODEL_REGION`: スタック作成時のパラメータ `modelRegion` (デフォルト値は `us-east-1`)
- 追加インストールモジュール
  - [`@aws-sdk/client-bedrock-agent-runtime`](https://www.npmjs.com/package/@aws-sdk/client-bedrock-agent-runtime)
- 処理概要
  - [`packages/cdk/lambda/utils/bedrockOptimizePrompt.ts`](https://github.com/aws-samples/generative-ai-use-cases-jp/blob/a3002c273332bf8386c90f547d507eee1a727509/packages/cdk/lambda/utils/bedrockOptimizePrompt.ts) の execute 関数を呼び出してプロンプト最適化を実行
    - `input`:
      - `textPrompt`:
        - `text`: `event.prompt`
    - `targetModelId`: `event.targetModelId`

##### 【CDK 用関数】allowDownloadFile

最後に、`Api` リソースの中で `allowDownloadFile` 関数を定義しています。
この関数の引数に S3 バケット名を指定して呼び出すことで、対象の S3 バケット内のファイルに対し `getFileDownloadSignedUrlFunction` 関数で署名付き URL を作成することができるようになります。

```typescript: packages/cdk/lib/construct/api.ts
  // Bucket 名を指定してダウンロード可能にする
  allowDownloadFile(bucketName: string) {
    this.getFileDownloadSignedUrlFunction.role?.addToPrincipalPolicy(
      new PolicyStatement({
        effect: Effect.ALLOW,
        resources: [
          `arn:aws:s3:::${bucketName}`,
          `arn:aws:s3:::${bucketName}/*`,
        ],
        actions: ['s3:GetBucket*', 's3:GetObject*', 's3:List*'],
      })
    );
  }
```

`Database` と `Api` でとんでもなく長くなってしまいました。
次回は GenU 内の `GenerativeAiUseCasesStack` スタックの `CommonWebAcl` リソースから解説したいと思います。

## (参考) GenU のバックエンド (CDK) 詳細解説投稿一覧

- [①AWS CDK のセットアップ](https://qiita.com/siruko/items/fd25fdcf89615cb85262)
- [②AWS CDK の動作確認](https://qiita.com/siruko/items/73169f986b4173e3d3a5)
- [③GenU の概要](https://qiita.com/siruko/items/625801b9e1847b305c1e)
- [④GenU CDK スタックの概要](https://qiita.com/siruko/items/8570ed43f7162ea4b907)
- [⑤CloudFrontWafStack スタックの解説](https://qiita.com/siruko/items/30439576ee7c63165d21)
- [⑥RagKnowledgeBaseStack スタックの解説](https://qiita.com/siruko/items/1223c9d22e73168a8809)
- [⑦WebSearchAgentStack スタックの解説](https://qiita.com/siruko/items/aef0a9599df60d47eb1e)
- [⑧GuardrailStack スタックの解説](https://qiita.com/siruko/items/d16e9fe27df4673d7554)
- [⑨GenerativeAiUseCasesStack > Auth スタックの解説](https://qiita.com/siruko/items/0c14040a1af132f42382)
- [⑩GenerativeAiUseCasesStack > Database, Api スタックの解説](https://qiita.com/siruko/items/5f249f11847f3829c18a)
- [⑪GenerativeAiUseCasesStack > CommonWebAcl, Web, Rag スタックの解説](https://qiita.com/siruko/items/1063daa2efe0b374a3fc)
- [⑫GenerativeAiUseCasesStack > RagKnowledgeBase, UseCaseBuilder, Transcribe スタックの解説](https://qiita.com/siruko/items/73d6006004caf8648594)
- [⑬DashBoard スタックの解説](https://qiita.com/siruko/items/73a75c7d0146d12ecbc3)
- [⑭GenU の Outputs の解説](https://qiita.com/siruko/items/afc14128a5b1a15ab69c)