1. はじめに
デジタル庁がオープンソースとして公開している生成AI利活用基盤「源内(GitHub: digital-go-jp/genai-ai-api)」。その中に含まれる「行政実務用RAG(aws/query-expansion-rag)」は、クエリ拡張やリランキングが組み込まれた非常に完成度の高いAWS RAG環境です。
しかし、デフォルト構成のままデプロイすると Amazon OpenSearch Serverless (AOSS) の待機課金により、使っていなくても月額数万円の固定費が発生してしまいます。
本記事では、この源内RAGを Amazon Bedrock S3 Vectors と Amazon Nova Lite に切り替えます。これにより、「待機固定費ゼロ・月額千円以下・1クエリ約0.1円」 で動かす最安構成を実現しました。具体的なデプロイ手順と、遭遇しやすいエラーの解消Tipsをまとめます。
2. 前提環境
- OS: Linux / macOS
- Node.js: v22.x
- Python: 3.12 〜 3.14
-
AWS CLI: v2.x(
aws configure設定済み) -
AWS環境: 東京リージョン(
ap-northeast-1)
3. 最安構成への設定変更手順
リポジトリをクローンした後、aws/query-expansion-rag 配下の設定ファイルを2箇所書き換えます。
git clone https://github.com/digital-go-jp/genai-ai-api.git
cd genai-ai-api/aws/query-expansion-rag
npm ci
① ベクトルストアを S3 Vectors に切り替え
parameter.ts および cdk.json 内で、OpenSearch用の設定を外し、S3 Vectors用スタックを有効化します。
// OpenSearch構成を無効化(空配列に)
export const qeRagAppNamesWithSharedCmek: string[] = [];
// S3 Vectors構成を有効化
export const qeRagAppNamesWithS3Vectors: string[] = ['qerag-s3v-1'];
これで待機中のOCU課金が完全にゼロになります。
② LLMを Amazon Nova Lite に統一
config/apps/qerag.toml を開き、モデルIDと出力トークン数を設定します。
[query_expansion]
modelId = "amazon.nova-lite-v1:0"
maxTokens = 5000
[rerank]
modelId = "amazon.nova-lite-v1:0"
maxTokens = 5000
[generation]
modelId = "amazon.nova-lite-v1:0"
maxTokens = 5000
embeddingModelId = "amazon.titan-embed-text-v2:0"
[!NOTE]
maxTokensを5000に設定している理由は後述のTipsを参照してください。
4. デプロイとデータ同期
① CDK デプロイの実行
以下のコマンドで、API Gateway、Lambda、Bedrock Knowledge Base、S3等の全スタックを一括デプロイします。
npx cdk deploy --all -c env=-dev
正常に完了すると、CloudFormation Outputs に API エンドポイントや Knowledge Base ID が出力されます。
② 投入データの前処理(Shift_JIS → UTF-8 変換)
官公庁のオープンデータや e-Stat の統計表(CSV)は Shift_JIS(CP932) で配布されているケースが多くあります。
しかし、AWS Bedrock Knowledge Base は UTF-8 前提のため、そのままアップロードすると文字化けして正常に検索されません。
Pythonの encode/decode 等を用いて、投入前に必ず UTF-8 へ一括変換しておきます。
import chardet
with open("raw_data.csv", "rb") as f:
raw = f.read()
encoding = chardet.detect(raw)["encoding"]
text = raw.decode(encoding or "cp932")
with open("processed_data.csv", "w", encoding="utf-8") as f:
f.write(text)
③ S3 へのアップロードとナレッジベース同期
データソース用の S3 バケットの docs/ フォルダ配下にファイルを同期し、Bedrockの取り込みジョブを開始します。
[!IMPORTANT]
【重要】S3に置くだけでは検索に反映されません!
Bedrock Knowledge BaseはS3イベント自動連携ではないため、ファイルを配置しただけではベクトル化されません。必ず以下のstart-ingestion-jobを実行して明示的に取り込みを開始してください。
# S3へアップロード
aws s3 sync ./processed/ s3://<データソースバケット名>/docs/ --region ap-northeast-1
# Knowledge Base の同期開始
aws bedrock-agent start-ingestion-job \
--knowledge-base-id <KNOWLEDGE_BASE_ID> \
--data-source-id <DATA_SOURCE_ID> \
--region ap-northeast-1
5. 遭遇しやすいエラーと即効解消Tips 7選
Tips 1: CDK ブートストラップの SSM パラメータアクセス拒否
-
エラー:
AccessDeniedException: User: ... is not authorized to perform: ssm:GetParameter on resource: .../cdk-bootstrap/... -
原因:
CDK標準のシンセサイザーが SSM Parameter Store や AssumeRole を前提としているため発生します。 -
解決策:
bin/qe-rag-apis.tsでCliCredentialsStackSynthesizerを適用し、CLIの直接認証モードに切り替えます。bin/qe-rag-apis.tsconst app = new cdk.App({ defaultStackSynthesizer: new cdk.CliCredentialsStackSynthesizer() });
Tips 2: AWS SSOロール前提コードによるデプロイ失敗
-
エラー:
Invalid principal in policy (Service: CloudFormation, Status Code: 400) -
原因:
本家のswitch-role-stack.tsが IAM Identity Center(旧AWS SSO)のロールを前提としているため、個人環境で失敗します。 -
解決策:
SSOロール未利用時は自アカウントのルートへフォールバックする条件分岐を追加します。aws/query-expansion-rag/lib/switch-role-stack.tsconst assumeRolePrincipal = (props.switchRoleName === 'DummyRole' || props.switchRoleName === 'root') ? new iam.AccountRootPrincipal() : new iam.ArnPrincipal( `arn:aws:iam::${awsAccount}:role/aws-reserved/sso.amazonaws.com/${awsRegion}/${props.switchRoleName}` ).withConditions({ StringLike: { 'aws:userid': props.idcUserNames.map((user) => `*:${user}`), }, });
Tips 3: メタデータJSONがない場合の引用ファイル名欠落
-
現象:
ドキュメントに個別のメタデータJSON(.metadata.json)を付けていない場合、Lambda側でファイル名を取得できず引用表示が空になります。 -
解決策:
Lambda(kb_response_processor.py)で S3 URI から直接ファイル名を抽出するフォールバック処理を実装します。rag-lambda/invokeModel/services/kb_response_processor.py# locationからS3 URIを取得してファイル名を抽出 s3_uri = reference.get("location", {}).get("s3Location", {}).get("uri", "") fallback_file_name = s3_uri.split("/")[-1] if s3_uri else None if METADATA in reference: metadata.file_name = reference[METADATA].get(FILE_NAME) or fallback_file_name metadata.url = reference[METADATA].get(URL) or s3_uri else: metadata.file_name = fallback_file_name metadata.url = s3_uri
Tips 4: AWS WAF の IPSet CIDR フォーマットエラー
-
エラー:
parameter contains formatting that is not valid., field: IP_ADDRESS, parameter: 0.0.0.0/0 -
原因:
AWS WAFv2 の IPSet では0.0.0.0/0の指定が許可されていません(/1〜/32のみ)。 -
解決策:
開発環境のアクセス元IP(xxx.xxx.xxx.xxx/32)を指定するか、IP制限が不要な場合はallowedIpV4AddressRanges: nullを渡します。
Tips 5: API Gateway 統合タイムアウト(29秒)の超過
-
エラー:
Timeout should be between 50 ms and 29000 ms (Service: ApiGateway, Status Code: 400) -
原因:
REST API の統合タイムアウト上限は 29秒(29,000ms)です。デフォルトの180秒のままではデプロイが拒否されます。 -
解決策:
parameter.tsおよびcdk.jsonのapiLambdaIntegrationTimeoutを29に設定します。
Tips 6: Amazon Nova Lite の最大トークン数エラー
-
エラー:
ValidationException: The maximum tokens you requested exceeds the model limit of 10000 -
原因:
Bedrock Converse API において、Nova Lite の最大出力トークン(maxTokens)の上限は10,000です。Claude向けの設定値(20,000〜40,000)のままではエラーになります。 -
解決策:
config/apps/qerag.toml内の全maxTokensを5000程度に引き下げて設定します。
Tips 7: cdk destroy 時に「Unable to delete data from vector store...」で削除失敗する罠
-
エラー:
Unable to delete data from vector store for data source with ID xxxxx... -
原因:
データソースの削除ポリシー(dataDeletionPolicy)がデフォルトのDELETEになっているためです。CDK破棄時にS3が先に消えると、ベクトルストア削除APIが失敗してスタック削除がブロックされます。 -
解決策:
データソースのdataDeletionPolicyをRETAINに更新してから削除します。cleanup_fix.pyimport boto3 client = boto3.client('bedrock-agent', region_name='ap-northeast-1') # 1. ポリシーを RETAIN に更新(ベクトルストアへのアクセスをスキップ) ds = client.get_data_source(knowledgeBaseId=KB_ID, dataSourceId=DS_ID)['dataSource'] client.update_data_source( knowledgeBaseId=KB_ID, dataSourceId=DS_ID, name=ds['name'], dataDeletionPolicy='RETAIN', dataSourceConfiguration=ds['dataSourceConfiguration'] ) # 2. データソースとKBを削除 client.delete_data_source(knowledgeBaseId=KB_ID, dataSourceId=DS_ID) client.delete_knowledge_base(knowledgeBaseId=KB_ID)
6. コストとレスポンスの実績
この最安構成でテストクエリを実行したパイロット検証の実測値です。
- 平均レスポンス時間: 約 5.4 秒 / リクエスト
- 消費トークン数: 約 89,000 tokens
- 検証全体の総費用: $0.01188(約 1.8 円)
- 1リクエストあたりのコスト: 約 0.1 円
- 待機固定費: 0円(S3保存料のみ)
クエリ拡張+リランキング+回答生成という4段階パイプラインを実行しても、1回あたり約0.1円という圧倒的な低コストで運用可能です。
7. まとめ
デジタル庁の「源内AI」AWS RAGテンプレートは、S3 Vectors と Amazon Nova Lite を組み合わせることで、個人や小規模チームでもお財布に優しく安全に動かすことができます。
社内ドキュメントの検索や業務効率化のPoC環境として、ぜひ試してみてください。
関連記事・お問い合わせ
-
デジタル庁 源内AI 公式リポジトリ:
行政実務用RAGやマルチクラウド基盤の公式コードは、GitHub(digital-go-jp/genai-ai-api) で公開されています。 -
開発背景・アーキテクチャの解説:
本構成の設計思想や構造別ベンチマークによる精度検証ログ(検索成功率88.9%)の詳細は、Zennの解説記事 をご覧ください。 -
業務導入・受託開発のご相談:
AI Nexusでは、業務効率化ツールの受託開発やAI導入コンサルティングを行っています。詳細は AI Nexus 公式サイト をご覧ください。