ããã«ã¡ã¯ãåºéã§ãã 以äžã®èšäºã®ç¶ç·šèšäºã§ããRAG ã§ CSV ããŒã¿ããã®æ€çŽ¢ç²ŸåºŠåäžãç®æããŠã¿ãŸãããæ¬èšäºã¯å®è£
ç·šã§ãäž»ã«ããã¯ãšã³ãã®èšå®ã«ã€ããŠèšèŒããŠããŸããUI ãå®éã®åäœã«ã€ããŠã¯ç¶ç·šèšäºã® UI ç·šã§ç޹ä»ããŸãã Amazon Bedrock Knowledge Bases ã§æ§é åããŒã¿(CSV)ã䜿çšãã RAG ãã€ãã -ã¢ãŒããã¯ãã£ç·š- Amazon Bedrock Knowledge Bases ãš Amazon S3 Vectors ã§æ§ç¯ãã RAG ç°å¢ã§ãæ§é åããŒã¿ãããŒã¿ãœãŒã¹ã«ãããšãã®æ€çŽ¢ç²ŸåºŠåäžãç®æããŸãããæ¬èšäºã¯ã¢ãŒããã¯ãã£ç·šã§ãã blog.usize-tech.com 2026.03.09 ããããããš (åæ²) 以äžã®ãããªæ¶ç©ºã®ãã«ããã¹ã¯åãåããå±¥æŽããŒã¿ (CSV) ãçšæããŸããã ãã«ããã¹ã¯æ
åœè
ãæ°ããªåãåãããåãããšãã«ã䌌ããããªéå»ã®å¯Ÿå¿å±¥æŽãåŒãåœãŠãããããã«ãããããšããã®ãç®çã§ãã LLM ã«ãä»å±ããæ°ããåãåããã«å¯Ÿããåçæ¡ãææ¡ããããã åçæ¡ãçæããããã«ãèªç¶èšèªã§æžãããåãåããå
容ãšåçå
容ãããæå³çã«è¿ãããŒã¿ãåŒãåœãŠããã ã«ããŽãªã§æ€çŽ¢å¯Ÿè±¡ããã£ã«ã¿ãããããã®æ¹ã粟床ãäžããã±ãŒã¹ããããšèããããã LLM ãåçæ¡ãææ¡ãããšãã«ã¯ãåèã«ããéå»å¯Ÿå¿å±¥æŽãã©ã®ååãçªå·ã®ãã®ããæç€ºããããããã®ååãçªå·ãããŒã«ãçã®å¯Ÿå¿å±¥æŽããŒã¿ãåç
§ã§ããããã«ãããã 以äžã®åæããããŸãã ããŒã¿ãœãŒã¹ãšãªã CSV ãã¡ã€ã«ã¯ 1ã€ã®ã¿ãéå»ã®å¯Ÿå¿å±¥æŽã¯ 1 ã€ã® CSV ãã¡ã€ã«ã«åãŸã£ãŠãããšããããšã ã€ãŸããããŒã¿ã®1è¡ã1ä»¶ã®åãåããã§ããããã®é
ç®éã«ã¯æå³çãªã€ãªãããããã ãŸããããããäžè¬çãªããŒãºã§ã¯ãªãããšæããŸãã é¢é£èšäº 以åãç§ãå
¬éãã Amazon Bedrock Knowledge Bases ã Amazon S3 Vectors ã䜿çšãã RAG åºç€ã®èšäºã§ããä»åã¯ãã®åºç€ã®ãã£ã³ãã³ã°æŠç¥ãã«ã¹ã¿ãã€ãºããŠèšã¿ãŸããã React ã§ Amazon Bedrock Knowledge Bases ããŒã¹ã®ç°¡æ RAG ãã£ããããããã€ãã [2026幎1æç] ã¢ãŒããã¯ãã£æŠèŠç·š AWS re:Invent 2025 ã§ãAmazon S3 Vectors ã GA ãããŸããããããåããŠã以åäœæãã RAG ãã£ããããããã¢ã¬ã³ãžããŠã¿ãŸããã blog.usize-tech.com 2026.01.06 æ¬èšäºã®èšåç¯å² RAG ãã®ãã®ããRAG åºç€ã«ã€ããŠã¯æ¬èšäºã§ã¯èªããŸããã 以äžã®ã¢ãŒããã¯ãã£å³ã®äžã®ãèµ€æ ã®éšåã«çç®ããŸãããã¯ãã«ããŒã¿ãæ ŒçŽãããŸã§ã®ããŒã¿ãœãŒã¹ã®ã«ã¹ã¿ã ãã£ã³ãã³ã°ãšããããå®è£
ãã Amazon Bedrock Knowledge Bases ã«ã©ãåãåããããããã§ãã ã¢ãŒããã¯ã㣠(åæ²) ååèšäºã§ç޹ä»ãããã«ã¹ã¿ã ãã£ã³ãã³ã°ãå®è£
ããã¢ãŒããã¯ãã£ã§ãã å®è£
Amazon Bedrock Knowledge Bases ã«ã¹ã¿ã ãã£ã³ãã³ã°ã®äžé£ã®åŠçã¯ãAmazon Bedrock Knowledge Bases ã§è¡ãããŸããåçš®èšå®ã®å
šäœå㯠AWS ãããžã¡ã³ãã³ã³ãœãŒã«ã®ç»é¢ã§äžæã§ããŸãã ã«ã¹ã¿ã ãã£ã³ãã³ã°ã AWS Lambda 颿°ã«åŠçãããã®ã§ãåœç¶ Lambda 颿°ãå¿
èŠã§ãã(å
容ã¯åŸè¿°) Lambda 颿°ãåºåãããã£ã³ã¯åå²åŸã®ããŒã¿ (äžéææç©ã® JSON) ãä¿åãã S3 ãã±ãããå¿
èŠã§ããããã¯ãªãªãžãã«ã®ããã¥ã¡ã³ãé
çœ®çš S3 ãã±ãããšã¯å¥ã«ããå¿
èŠããããŸãã ãã£ã³ãã³ã°æŠç¥ã¯ NO ã«ããŸããNO ã«ãããšããªãªãžãã«ã®ããã¥ã¡ã³ãã®å
容ããã®ãŸãŸ Lambda 颿°ã«æž¡ããŠãããŸããå¥ã®æŠç¥ãéžæãããšããã®æŠç¥ã«ãã£ãŠãã£ã³ã¯åå²ãããããŒã¿ããšã« Lambda 颿°ãå®è¡ããŠããŸãã®ã§ãæåŸ
ããã«ã¹ã¿ã ãã£ã³ã¯åå²ãã§ããªããªããŸãã è§£ææŠç¥ã¯ Default ã«ããŸãã ãã£ã³ãã³ã°æŠç¥ãšè§£ææŠç¥ã¯ãããŒã¿ãœãŒã¹äœæåŸã«ã¯å€æŽã§ããŸããã倿Žããããšãã¯äœãçŽãã«ãªããŸãã ããŒã¿åé€ããªã·ãŒã¯ DELETE ã«ããããšããå§ãããŸããåæãããããšãã«éå»ã®ããŒã¿ãæ®ããã©ããã®èšå®ã§ãæ®ããŠããŸããšå€ãæ
å ±ãæ€çŽ¢ã«åŒã£æãã£ãŠããŸããŸãã AWS Lambda 颿° (ã«ã¹ã¿ã ãã£ã³ãã³ã°) ã«ã¹ã¿ã ãã£ã³ãã³ã°ãã Lambda 颿°ã³ãŒã (Python) ã§ãã åé ã«ç޹ä»ãã CSV ããAmazon Bedrock Knowledge Bases ãçè§£ã§ãããã©ãŒãããã® JSON ããŒã¿ã«å€æããŸããå
éšçã«ã¯ 1 ãã£ã³ã¯ããšã«èªç¶èšèªã§æ€çŽ¢ããããããŒã¿ãšã¡ã¿ããŒã¿ã«åããŠåºåããŸãã Lambda ã¬ã€ã€ãŒã¯äžèŠã§ããã¢ãžã¥ãŒã«ã¯ Lambda æšæºã§ãµããŒãããŠãããã®ã ãã§å®è£
å¯èœã§ããã ã€ã³ããããšãªã S3 ãã±ããå
ã® CSV ããŒã¿ã®ã¡ã¿ããŒã¿ã¯ãAmazon Bedrock Knowledge Bases ããã® Lambda 颿°ãåŒã³åºããšãã«æž¡ããŠãããã®ã§ããã¡ããç¹ã«æ°ã«ããããšã¯ãããŸãããåãåã£ããã±ããåãããŒãã CSV ããŒã¿ãååŸãã«è¡ããŸããåºåå
ãšãªã S3 ãã±ãããããŒåã Amazon Bedrock Knowledge Bases ããæž¡ãããŸãã®ã§ãã®é¢æ°å
ã§ãã¿æžãããããšã¯ãããŸããã ããŒã¿ãã©ãŒãããã®å€æåŠçã®å
容çã«ã¯ããããªã«é£ããããšã¯ããŠããŸããã倧äºãªã®ã¯åºåãã©ãŒãããã§ãã import json import csv import boto3 from io import StringIO s3 = boto3.client('s3') def lambda_handler(event, context): try: bucket_name = event.get('bucketName') input_files = event.get('inputFiles', []) output_files = [] for file_info in input_files: original_file_location = file_info.get('originalFileLocation', {}) s3_location = original_file_location.get('s3Location', {}) original_uri = s3_location.get('uri', '') content_batches = file_info.get('contentBatches', []) output_batches = [] for batch in content_batches: input_key = batch.get('key') # Read input file from S3 response = s3.get_object(Bucket=bucket_name, Key=input_key) input_content = json.loads(response['Body'].read().decode('utf-8')) # Extract CSV content csv_content = input_content['fileContents'][0]['contentBody'] # Remove BOM if present (input may have BOM) if csv_content.startswith('\ufeff'): csv_content = csv_content[1:] csv_reader = csv.DictReader(StringIO(csv_content)) # Process each row as a chunk file_contents = [] for row in csv_reader: content_body = f"ååãçªå·: {row.get('ååãçªå·', '')}\nååçªå·: {row.get('ååçªå·', '')}\n\nååãå
容:\n{row.get('ååãå
容', '')}\n\nåçå
容:\n{row.get('åçå
容', '')}" content_metadata = { "ååãçªå·": row.get('ååãçªå·', ''), "販売圢æ
": row.get('販売圢æ
', ''), "å仿¥æ": row.get('å仿¥æ', ''), "å®äºæ¥æ": row.get('å®äºæ¥æ', ''), "ååçªå·": row.get('ååçªå·', ''), "ã«ããŽãª": row.get('ã«ããŽãª', ''), "ã¹ããŒã¿ã¹": row.get('ã¹ããŒã¿ã¹', '') } file_contents.append({ "contentBody": content_body, "contentType": "TEXT", "contentMetadata": content_metadata }) # Write output file to S3 output_key = input_key.replace('.json', '_transformed.json') output_data = {"fileContents": file_contents} s3.put_object( Bucket=bucket_name, Key=output_key, Body=json.dumps(output_data, ensure_ascii=False), ContentType='application/json' ) output_batches.append({"key": output_key}) output_files.append({ "originalFileLocation": original_file_location, "fileMetadata": file_info.get('fileMetadata', {}), "contentBatches": output_batches }) return {"outputFiles": output_files} except Exception as e: print(f"Error: {str(e)}") import traceback traceback.print_exc() raise ãã£ã³ã¯åå²ãããåŸã®ããŒã¿æ§é (åæ²) Lambda 颿°ããã£ã³ã¯åå²ããåŸã®ããŒã¿æ§é (äžã®ã¢ãŒããã¯ãã£å³ã§ã¯ 5çªã®åŠçã«ãã£ãŠäœæããããã®) ã¯ã以äžã®ããã«ãªããŸãã { "fileContents": [ { "contentBody": "ååãçªå·: AB01234569\nååçªå·: SH001-01BL\n\nååãå
容:\n[ååãå
å®¹ã®æç« ]\n\nåçå
容:\n[åçå
å®¹ã®æç« ]", "contentType": "TEXT", "contentMetadata": { "ååãçªå·": "AB01234569", "販売圢æ
": "代çåº", "å仿¥æ": "2026/2/23 12:59", "å®äºæ¥æ": "2026/2/23 13:39", "ååçªå·": "SH001-01BL", "ã«ããŽãª": "å®¶åºçšåçŽæ£", "ã¹ããŒã¿ã¹": "å®äº" } }, { "contentBody": "ååãçªå·: AB01234573\nååçªå·: TB19541\n\nååãå
容:\n[ååãå
å®¹ã®æç« ]\n\nåçå
容:\n[åçå
å®¹ã®æç« ]", "contentType": "TEXT", "contentMetadata": { "ååãçªå·": "AB01234573", "販売圢æ
": "çŽè²©", "å仿¥æ": "2026/2/24 9:15", "å®äºæ¥æ": "2026/2/24 14:30", "ååçªå·": "TB19541", "ã«ããŽãª": "å®¶åºçšããŒãã«", "ã¹ããŒã¿ã¹": "å®äº" } } ] } fileContents é
åã®åèŠçŽ ã 1 ãã£ã³ã¯ïŒCSV ã® 1 è¡ã«çžåœïŒ contentBody ããã¯ãã«åã»æ€çŽ¢å¯Ÿè±¡ã«ã§ããããã¹ã contentMetadata ãåŒçšè¡šç€ºããã£ã«ã¿ãªã³ã°ã«äœ¿çšãããã¡ã¿ããŒã¿ â»contentBody ããã¡ããåŒçšå¯èœ ãããŸã§å®è£
ã§ãããšãAmazon Bedrock Knowledge Bases ã«å¯Ÿã㊠contentBody ã«æžãããå
容ã«å¯ŸããŠèªç¶èšèªã§æ€çŽ¢ã§ããããæ€çŽ¢æã«ã¡ã¿ããŒã¿ã®é
ç®åäœã§ãã£ã«ã¿ãªã³ã°ã§ããããã«ãªããŸãã ã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°ã«ã€ã㊠Amazon Bedrock Knowledge Bases ãã§ããŠããŸãã°ãèªç¶èšèªã«ããåãåãã㯠RetrieveAndGenerate API ã䜿çšããŠæ¥µè«ããã³ããããéãã°ããã®ã§ãé£ããããšã¯ãããŸãããããããã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°æ©èœã远å ãããšãèšèšæ¬¡ç¬¬ã§ã¯ã³ãŒããè€éã«ãªããŸãã ããã§ãã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°ã«ã€ããŠä»æ§ã説æããŸãã ã¡ã¿ããŒã¿æ¡ä»¶ã«ããããããã£ã³ã¯ã®ã¿ã«ãã¯ãã«æ€çŽ¢ãè¡ããããäžèŠãªçµæãæé€ããããšãã§ããæ€çŽ¢ç²ŸåºŠã®åäžãæåŸ
ã§ããã ã¡ã¿ããŒã¿é
ç®ã«å¯ŸããŠãããããæååæ€çŽ¢æ¡ä»¶ã¯ãå®å
šäžèŽããæå®ããæååãå«ãããªã©ããããã§ãããAmazon S3 Vectors ã§ãµããŒãããŠããæ¡ä»¶ã¯ä»¥äžå
¬åŒããã¥ã¡ã³ããåç
§ã ã¡ã¿ããŒã¿é
ç®ã¯ãè€æ°é
ç®ã And ã Or ã§çµã¿åãããããšãå¯èœã メタデータフィルタリング - Amazon Simple Storage Service ã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°ã䜿çšããŠããã¯ãã«ã«ã¢ã¿ãããããç¹å®ã®å±æ§ã«åºã¥ããŠã¯ãšãªçµæãçµãèŸŒãæ¹æ³ã«ã€ããŠèª¬æããŸãã docs.aws.amazon.com ã€ãŸããããªã现ãããã£ã«ã¿ãªã³ã°ãã§ãããšããããšã§ãã 以äžã«ã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°ãèšå®ãããšãã® Lambda 颿°ã³ãŒãã®äžéšã玹ä»ããŸãã åäžã®ã¡ã¿ããŒã¿æ¡ä»¶ ã販売圢æ
ã代çåºã§å®å
šäžèŽãã§ãã£ã«ã¿ãªã³ã°ããããšã retrievalConfiguration={ "vectorSearchConfiguration": { "filter": { "equals": { "key": "販売圢æ
", "value": "代çåº" } } } } è€æ°ã®ã¡ã¿ããŒã¿æ¡ä»¶ ã販売圢æ
ã代çåºã§å®å
šäžèŽããã€ãã«ããŽãªãå®¶åºçšã³ã¿ãã§å®å
šäžèŽãã§ãã£ã«ã¿ãªã³ã°ããããšã retrievalConfiguration={ "vectorSearchConfiguration": { "filter": { "andAll": [ { "equals": { "key": "販売圢æ
", "value": "代çåº" } }, { "equals": { "key": "ã«ããŽãª", "value": "å®¶åºçšã³ã¿ã" } } ] } } } èŠãŠãããããšããããšæããŸãããè€æ°ã®ã¡ã¿ããŒã¿æ¡ä»¶ã§ã¯ 2 ã€ã® equals æ¡ä»¶ã andAll ã§å²ãã§ãããšæããŸããäžèšã¯ãŸã ã·ã³ãã«ã§ãããè€æ°ã®æ¡ä»¶ãéãªãã°éãªãã»ã©ããã®ãããªéå±€æ§é ãããã«ã³ãŒãã£ã³ã°ããªããã°ãªããŸãããOr æ¡ä»¶ãå¯èœãšãããšãããã«è€éã«ãªãããã§ãã ä»åã®ããã°èšäºã§ã¯ãç°¡ç¥åã®ããäžèšã®ããã«ã販売圢æ
ããšãã«ããŽãªãã® 2 ã€ã®ã¡ã¿ããŒã¿ã®ã¿ãã£ã«ã¿ãªã³ã°å¯èœãªããã«èšèšããŸãã ãã£ã«ã¿å¯Ÿè±¡é
ç® è²©å£²åœ¢æ
ïŒ2çš®é¡: çŽè²©, 代çåºïŒ ã«ããŽãªïŒ10çš®é¡: å®¶åºçšã³ã¿ã, å®¶åºçšããŒãã«, å®¶åºçšåçŽæ£, å®¶åºçšãã§ã¢, å®¶åºçšãã¹ã¯, æ¥åçšã©ãã¯, æ¥åçšãã£ãããã, æ¥åçšäŒè°ããŒãã«, æ¥åçšãã§ã¢, æ¥åçšãã¹ã¯ïŒ ãã£ã«ã¿æ¡ä»¶éžææã®åäœ äž¡æ¹æªéžæ â ãã£ã«ã¿ãªã³ã°ãªãïŒå
šä»¶æ€çŽ¢ïŒ çæ¹ã®ã¿éžæ â éžæããããŒã¯ãŒãã«å®å
šäžèŽã§åäžæ¡ä»¶æ€çŽ¢ äž¡æ¹éžæ â AND æ¡ä»¶æ€çŽ¢ãããããéžæããããŒã¯ãŒãã«å®å
šäžèŽãšãã AWS Lambda 颿° (ãã¬ããžããŒã¹ãžã®åãåãã) åè¿°ã®ã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°æ©èœãå®è£
ãããAmazon Bedrock Knowledge Bases ã® RetrieveAndGenerate API ãã³ãŒã«ãã AWS Lambda 颿°ã³ãŒãã¯ä»¥äžã®ããã«ãªããŸãã Amazon API Gateway REST API ããåŒã³åºãããAWS AppSync Events ã«ã¹ããªãŒã ã¬ã¹ãã³ã¹ãè¿ãæ§æã§ããã³ã¡ã³ãã§ ã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°ã®çµã¿ç«ãŠ ãšæžããŠããéšåãå
ã»ã©èª¬æããéšåã®å®è£
ã§ãã ã€ã³ããããšã㊠"filters": [ {"販売圢æ
": "代çåº"}, {"ã«ããŽãª": "å®¶åºçšã³ã¿ã"} ] ã®ãããªã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°ãã©ã¡ãŒã¿ãåãåãæ³å®ã§ããæ¡ä»¶ã2ã€ããã° andAll ã§å²ãåŠçãå®è£
ããŠããŸãã import os import json import boto3 import urllib.request from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest # common objects and valiables session = boto3.session.Session() bedrock_agent = boto3.client('bedrock-agent-runtime') endpoint = os.environ['APPSYNC_API_ENDPOINT'] model_arn = os.environ['MODEL_ARN'] knowledge_base_id = os.environ['KNOWLEDGE_BASE_ID'] region = os.environ['REGION'] service = 'appsync' headers = {'Content-Type': 'application/json'} # AppSync publish message function def publish_appsync_message(sub, appsync_session_id, payload, credentials): body = json.dumps({ "channel": f"rag-stream-response/{sub}/{appsync_session_id}", "events": [ json.dumps(payload) ] }).encode("utf-8") aws_request = AWSRequest( method='POST', url=endpoint, data=body, headers=headers ) SigV4Auth(credentials, service, region).add_auth(aws_request) req = urllib.request.Request( url=endpoint, data=aws_request.body, method='POST' ) for k, v in aws_request.headers.items(): req.add_header(k, v) with urllib.request.urlopen(req) as res: return res.read().decode('utf-8') # handler def lambda_handler(event, context): try: credentials = session.get_credentials().get_frozen_credentials() # API Gateway ããã®ã€ã³ããããååŸ prompt = event['body']['prompt'] appsync_session_id = event['body']['appsyncSessionId'] bedrock_session_id = event['body'].get('bedrockSessionId') sub = event['sub'] # Amazon Bedrock Knowledge Bases ãžã®åãåãããã©ã¡ãŒã¿äœæ request = { "input": { "text": prompt }, "retrieveAndGenerateConfiguration": { "type": "KNOWLEDGE_BASE", "knowledgeBaseConfiguration": { "knowledgeBaseId": knowledge_base_id, "modelArn": model_arn, "generationConfiguration": { "inferenceConfig": { "textInferenceConfig": { "maxTokens": 10000, "temperature": 0.5, "topP": 0.9 } }, "performanceConfig": { "latency": "standard" }, "promptTemplate": { "textPromptTemplate": ( "ããªãã¯åªç§ãªãã«ããã¹ã¯ã¢ã·ã¹ã¿ã³ãã§ãããã«ããã¹ã¯æ
åœè
ããã®è³ªåã«å¯ŸããŠãå¿
ãæ¥æ¬èªã§åçããŠãã ããã" "é©åãªåçãèŠã€ãããªãå Žåã¯ãæ£çŽã«ãåãããŸããããšåçããŠãã ããã\n\n" "æ€çŽ¢çµæ:\n$search_results$\n\n" "åçæç€º: $output_format_instructions$" ) } } } } } # ã¡ã¿ããŒã¿ãã£ã«ã¿æ¡ä»¶ã®çµã¿ç«ãŠ filters = event['body'].get('filters', []) if filters: conditions = [{"equals": {"key": k, "value": v}} for f in filters for k, v in f.items()] if len(conditions) == 1: retrieval_filter = conditions[0] else: retrieval_filter = {"andAll": conditions} request["retrieveAndGenerateConfiguration"]["knowledgeBaseConfiguration"]["retrievalConfiguration"] = { "vectorSearchConfiguration": { "filter": retrieval_filter } } # Bedrock sessionId ã¯ååšãããšãã®ã¿æž¡ã (ç¶ç¶äŒè©±æã®ã¿) if bedrock_session_id: request["sessionId"] = bedrock_session_id # Bedrock Knowledge Bases ãžã®åãåãã response = bedrock_agent.retrieve_and_generate_stream(**request) # Bedrock sessionId if "sessionId" in response: publish_appsync_message( sub, appsync_session_id, { "type": "bedrock_session", "bedrock_session_id": response["sessionId"] }, credentials ) for chunk in response["stream"]: payload = None # Generated text if "output" in chunk and "text" in chunk["output"]: payload = { "type": "text", "message": chunk["output"]["text"] } print({"t": chunk["output"]["text"]}) # Citation elif "citation" in chunk: payload = { "type": "citation", "citation": chunk['citation']['retrievedReferences'] } print({"c": chunk['citation']['retrievedReferences']}) # Continue if not payload: continue # Publish AppSync publish_appsync_message(sub, appsync_session_id, payload, credentials) except Exception as e: print(str(e)) raise AWS CloudFormation ãã³ãã¬ãŒã Amazon API Gateway REST API ã AWS AppSync Events API ãªã©ãé¢é£ãããªãœãŒã¹ãäžåŒãããã€ãããã³ãã¬ãŒããæ²èŒããŸããããåäœã§ã¯åããªããšæããŸãã®ã§ãåèãŸã§ã«ããããŸã§å®è£
ã§ãããšãã¢ã㪠UI ãã API ãã³ãŒã«ããããšã§ãã£ããããã UI ãäœããŸãã AWSTemplateFormatVersion: 2010-09-09 Description: The CloudFormation template that creates a S3 vector bucket and index as a RAG Knowledge base. # ------------------------------------------------------------# # Input Parameters # ------------------------------------------------------------# Parameters: SystemName: Type: String Description: System name. use lower case only. (e.g. example) Default: example MaxLength: 10 MinLength: 1 SubName: Type: String Description: System sub name. use lower case only. (e.g. prod or dev) Default: dev MaxLength: 10 MinLength: 1 DomainName: Type: String Description: Domain name for URL. xxxxx.xxx (e.g. example.com) Default: example.com AllowedPattern: "[^\\s@]+\\.[^\\s@]+" SubDomainName: Type: String Description: Sub domain name for URL. (e.g. example-prod or example-dev) Default: example-dev MaxLength: 20 MinLength: 1 Dimension: Type: Number Description: The dimensions of the vectors to be inserted into the vector index. The value depends on the embedding model. Default: 1024 MaxValue: 4096 MinValue: 1 EmbeddingModelId: Type: String Description: The embedding model ID. Default: amazon.titan-embed-text-v2:0 MaxLength: 100 MinLength: 1 LlmModelId: Type: String Description: The LLM model ID for the Knowledge base. Default: global.amazon.nova-2-lite-v1:0 MaxLength: 100 MinLength: 1 Metadata: AWS::CloudFormation::Interface: ParameterGroups: - Label: default: "General Configuration" Parameters: - SystemName - SubName - Label: default: "Domain Configuration" Parameters: - DomainName - SubDomainName - Label: default: "Embedding Configuration" Parameters: - Dimension - EmbeddingModelId - Label: default: "Knowledge Base Configuration" Parameters: - LlmModelId Resources: # ------------------------------------------------------------# # S3 # ------------------------------------------------------------# S3BucketKbDatasource: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${SystemName}-${SubName}-kbdatasource PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true CorsConfiguration: CorsRules: - AllowedHeaders: - "*" AllowedMethods: - "GET" - "HEAD" - "PUT" - "POST" - "DELETE" AllowedOrigins: - !Sub https://${SubDomainName}.${DomainName} ExposedHeaders: - last-modified - content-type - content-length - etag - x-amz-version-id - x-amz-request-id - x-amz-id-2 - x-amz-cf-id - x-amz-storage-class - date - access-control-expose-headers MaxAge: 3000 Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} S3BucketPolicyKbDatasource: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3BucketKbDatasource PolicyDocument: Version: "2012-10-17" Statement: - Effect: Deny Principal: "*" Action: "s3:*" Resource: - !Sub "arn:aws:s3:::${S3BucketKbDatasource}" - !Sub "arn:aws:s3:::${S3BucketKbDatasource}/*" Condition: Bool: "aws:SecureTransport": "false" DependsOn: - S3BucketKbDatasource S3VectorBucket: Type: AWS::S3Vectors::VectorBucket Properties: VectorBucketName: !Sub ${SystemName}-${SubName}-vectordb S3BucketKbIntermediate: Type: AWS::S3::Bucket Properties: BucketName: !Sub ${SystemName}-${SubName}-kbintermediate PublicAccessBlockConfiguration: BlockPublicAcls: true BlockPublicPolicy: true IgnorePublicAcls: true RestrictPublicBuckets: true Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} S3BucketPolicyKbIntermediate: Type: AWS::S3::BucketPolicy Properties: Bucket: !Ref S3BucketKbIntermediate PolicyDocument: Version: "2012-10-17" Statement: - Effect: Deny Principal: "*" Action: "s3:*" Resource: - !Sub "arn:aws:s3:::${S3BucketKbIntermediate}" - !Sub "arn:aws:s3:::${S3BucketKbIntermediate}/*" Condition: Bool: "aws:SecureTransport": "false" DependsOn: - S3BucketKbIntermediate S3VectorBucketIndex: Type: AWS::S3Vectors::Index Properties: IndexName: !Sub ${SystemName}-${SubName}-vectordb-index DataType: float32 Dimension: !Ref Dimension DistanceMetric: cosine VectorBucketArn: !GetAtt S3VectorBucket.VectorBucketArn MetadataConfiguration: NonFilterableMetadataKeys: - AMAZON_BEDROCK_TEXT - AMAZON_BEDROCK_METADATA DependsOn: - S3VectorBucket # ------------------------------------------------------------# # Bedrock Knowledge Base # ------------------------------------------------------------# BedrockKnowledgeBase: Type: AWS::Bedrock::KnowledgeBase Properties: Name: !Sub ${SystemName}-${SubName}-kb Description: !Sub RAG Knowledge Base for ${SystemName}-${SubName} KnowledgeBaseConfiguration: Type: VECTOR VectorKnowledgeBaseConfiguration: EmbeddingModelArn: !Sub arn:aws:bedrock:${AWS::Region}::foundation-model/${EmbeddingModelId} RoleArn: !GetAtt IAMRoleBedrockKb.Arn StorageConfiguration: Type: S3_VECTORS S3VectorsConfiguration: IndexArn: !GetAtt S3VectorBucketIndex.IndexArn VectorBucketArn: !GetAtt S3VectorBucket.VectorBucketArn Tags: Cost: !Sub ${SystemName}-${SubName} DependsOn: - IAMRoleBedrockKb BedrockKnowledgeBaseDataSource: Type: AWS::Bedrock::DataSource Properties: Name: !Sub ${SystemName}-${SubName}-kb-datasource Description: !Sub RAG Knowledge Base Data Source for ${SystemName}-${SubName} KnowledgeBaseId: !Ref BedrockKnowledgeBase DataDeletionPolicy: DELETE DataSourceConfiguration: Type: S3 S3Configuration: BucketArn: !GetAtt S3BucketKbDatasource.Arn VectorIngestionConfiguration: ChunkingConfiguration: ChunkingStrategy: NONE CustomTransformationConfiguration: Transformations: - TransformationFunction: TransformationLambdaConfiguration: LambdaArn: !GetAtt LambdaCsvChunker.Arn StepToApply: POST_CHUNKING IntermediateStorage: S3Location: URI: !Sub s3://${S3BucketKbIntermediate}/ DependsOn: - S3BucketKbDatasource - BedrockKnowledgeBase - S3BucketKbIntermediate # ------------------------------------------------------------# # AppSync Events # ------------------------------------------------------------# AppSyncChannelNamespaceRagSR: Type: AWS::AppSync::ChannelNamespace Properties: Name: rag-stream-response ApiId: Fn::ImportValue: !Sub AppSyncApiId-${SystemName}-${SubName} CodeHandlers: | import { util } from '@aws-appsync/utils'; export function onSubscribe(ctx) { const requested = ctx.info.channel.path; if (!requested.startsWith(`/rag-stream-response/${ctx.identity.sub}`)) { util.unauthorized(); } } Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} # ------------------------------------------------------------# # API Gateway REST API # ------------------------------------------------------------# RestApiRagSR: Type: AWS::ApiGateway::RestApi Properties: Name: !Sub rag-sr-${SystemName}-${SubName} Description: !Sub REST API to call Lambda rag-stream-response-${SystemName}-${SubName} EndpointConfiguration: Types: - REGIONAL IpAddressType: dualstack Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} RestApiDeploymentRagSR: Type: AWS::ApiGateway::Deployment Properties: RestApiId: !Ref RestApiRagSR DependsOn: - RestApiMethodRagSRPost - RestApiMethodRagSROptions RestApiStageRagSR: Type: AWS::ApiGateway::Stage Properties: StageName: prod Description: production stage RestApiId: !Ref RestApiRagSR DeploymentId: !Ref RestApiDeploymentRagSR MethodSettings: - ResourcePath: "/*" HttpMethod: "*" LoggingLevel: INFO DataTraceEnabled : true TracingEnabled: false AccessLogSetting: DestinationArn: !GetAtt LogGroupRestApiRagSR.Arn Format: '{"requestId":"$context.requestId","status":"$context.status","sub":"$context.authorizer.claims.sub","email":"$context.authorizer.claims.email","resourcePath":"$context.resourcePath","requestTime":"$context.requestTime","sourceIp":"$context.identity.sourceIp","userAgent":"$context.identity.userAgent","apigatewayError":"$context.error.message","authorizerError":"$context.authorizer.error","integrationError":"$context.integration.error"}' Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} RestApiAuthorizerRagSR: Type: AWS::ApiGateway::Authorizer Properties: Name: !Sub restapi-authorizer-ragsr-${SystemName}-${SubName} RestApiId: !Ref RestApiRagSR Type: COGNITO_USER_POOLS ProviderARNs: - Fn::ImportValue: !Sub CognitoArn-${SystemName}-${SubName} AuthorizerResultTtlInSeconds: 300 IdentitySource: method.request.header.Authorization RestApiResourceRagSR: Type: AWS::ApiGateway::Resource Properties: RestApiId: !Ref RestApiRagSR ParentId: !GetAtt RestApiRagSR.RootResourceId PathPart: ragsr RestApiMethodRagSRPost: Type: AWS::ApiGateway::Method Properties: RestApiId: !Ref RestApiRagSR ResourceId: !Ref RestApiResourceRagSR HttpMethod: POST AuthorizationType: COGNITO_USER_POOLS AuthorizerId: !Ref RestApiAuthorizerRagSR Integration: Type: AWS IntegrationHttpMethod: POST Credentials: Fn::ImportValue: !Sub ApigLambdaInvocationRoleArn-${SystemName}-${SubName} Uri: !Sub "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaRagSR.Arn}/invocations" PassthroughBehavior: NEVER RequestTemplates: application/json: | { "body": $input.json('$'), "sub": "$context.authorizer.claims.sub" } RequestParameters: integration.request.header.X-Amz-Invocation-Type: "'Event'" IntegrationResponses: - ResponseParameters: method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Cache-Control'" method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'" method.response.header.Access-Control-Allow-Origin: !Sub "'https://${SubDomainName}.${DomainName}'" ResponseTemplates: application/json: '' StatusCode: '202' MethodResponses: - StatusCode: '202' ResponseModels: application/json: Empty ResponseParameters: method.response.header.Access-Control-Allow-Origin: true method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true RestApiMethodRagSROptions: Type: AWS::ApiGateway::Method Properties: RestApiId: !Ref RestApiRagSR ResourceId: !Ref RestApiResourceRagSR HttpMethod: OPTIONS AuthorizationType: NONE Integration: Type: MOCK Credentials: Fn::ImportValue: !Sub ApigLambdaInvocationRoleArn-${SystemName}-${SubName} IntegrationResponses: - ResponseParameters: method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,Cache-Control'" method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'" method.response.header.Access-Control-Allow-Origin: !Sub "'https://${SubDomainName}.${DomainName}'" ResponseTemplates: application/json: '' StatusCode: '200' PassthroughBehavior: WHEN_NO_MATCH RequestTemplates: application/json: '{"statusCode": 200}' MethodResponses: - ResponseModels: application/json: Empty ResponseParameters: method.response.header.Access-Control-Allow-Headers: true method.response.header.Access-Control-Allow-Methods: true method.response.header.Access-Control-Allow-Origin: true StatusCode: '200' # ------------------------------------------------------------# # API Gateway LogGroup (CloudWatch Logs) # ------------------------------------------------------------# LogGroupRestApiRagSR: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/apigateway/${RestApiRagSR} RetentionInDays: 365 Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} # ------------------------------------------------------------# # Lambda # ------------------------------------------------------------# LambdaRagSR: Type: AWS::Lambda::Function Properties: FunctionName: !Sub rag-sr-${SystemName}-${SubName} Description: !Sub Lambda Function to invoke Bedrock Knowledge Bases for ${SystemName}-${SubName} Architectures: - x86_64 Runtime: python3.14 Timeout: 300 MemorySize: 128 Environment: Variables: APPSYNC_API_ENDPOINT: Fn::ImportValue: !Sub AppSyncEventsEndpointHttp-${SystemName}-${SubName} MODEL_ARN: !Sub "arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:inference-profile/${LlmModelId}" KNOWLEDGE_BASE_ID: !Ref BedrockKnowledgeBase REGION: !Ref AWS::Region Role: !GetAtt LambdaBedrockKbRole.Arn Handler: index.lambda_handler Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} Code: ZipFile: | import os import json import boto3 import urllib.request from botocore.auth import SigV4Auth from botocore.awsrequest import AWSRequest # common objects and valiables session = boto3.session.Session() bedrock_agent = boto3.client('bedrock-agent-runtime') endpoint = os.environ['APPSYNC_API_ENDPOINT'] model_arn = os.environ['MODEL_ARN'] knowledge_base_id = os.environ['KNOWLEDGE_BASE_ID'] region = os.environ['REGION'] service = 'appsync' headers = {'Content-Type': 'application/json'} # AppSync publish message function def publish_appsync_message(sub, appsync_session_id, payload, credentials): body = json.dumps({ "channel": f"rag-stream-response/{sub}/{appsync_session_id}", "events": [ json.dumps(payload) ] }).encode("utf-8") aws_request = AWSRequest( method='POST', url=endpoint, data=body, headers=headers ) SigV4Auth(credentials, service, region).add_auth(aws_request) req = urllib.request.Request( url=endpoint, data=aws_request.body, method='POST' ) for k, v in aws_request.headers.items(): req.add_header(k, v) with urllib.request.urlopen(req) as res: return res.read().decode('utf-8') # handler def lambda_handler(event, context): try: credentials = session.get_credentials().get_frozen_credentials() # API Gateway ããã®ã€ã³ããããååŸ prompt = event['body']['prompt'] appsync_session_id = event['body']['appsyncSessionId'] bedrock_session_id = event['body'].get('bedrockSessionId') sub = event['sub'] # Amazon Bedrock Knowledge Bases ãžã®åãåãããã©ã¡ãŒã¿äœæ request = { "input": { "text": prompt }, "retrieveAndGenerateConfiguration": { "type": "KNOWLEDGE_BASE", "knowledgeBaseConfiguration": { "knowledgeBaseId": knowledge_base_id, "modelArn": model_arn, "generationConfiguration": { "inferenceConfig": { "textInferenceConfig": { "maxTokens": 10000, "temperature": 0.5, "topP": 0.9 } }, "performanceConfig": { "latency": "standard" }, "promptTemplate": { "textPromptTemplate": ( "ããªãã¯åªç§ãªãã«ããã¹ã¯ã¢ã·ã¹ã¿ã³ãã§ãããã«ããã¹ã¯æ
åœè
ããã®è³ªåã«å¯ŸããŠãå¿
ãæ¥æ¬èªã§åçããŠãã ããã" "é©åãªåçãèŠã€ãããªãå Žåã¯ãæ£çŽã«ãåãããŸããããšåçããŠãã ããã\n\n" "æ€çŽ¢çµæ:\n$search_results$\n\n" "åçæç€º: $output_format_instructions$" ) } } } } } # ã¡ã¿ããŒã¿ãã£ã«ã¿æ¡ä»¶ã®çµã¿ç«ãŠ filters = event['body'].get('filters', []) if filters: conditions = [{"equals": {"key": k, "value": v}} for f in filters for k, v in f.items()] if len(conditions) == 1: retrieval_filter = conditions[0] else: retrieval_filter = {"andAll": conditions} request["retrieveAndGenerateConfiguration"]["knowledgeBaseConfiguration"]["retrievalConfiguration"] = { "vectorSearchConfiguration": { "filter": retrieval_filter } } # Bedrock sessionId ã¯ååšãããšãã®ã¿æž¡ã (ç¶ç¶äŒè©±æã®ã¿) if bedrock_session_id: request["sessionId"] = bedrock_session_id # Bedrock Knowledge Bases ãžã®åãåãã response = bedrock_agent.retrieve_and_generate_stream(**request) # Bedrock sessionId if "sessionId" in response: publish_appsync_message( sub, appsync_session_id, { "type": "bedrock_session", "bedrock_session_id": response["sessionId"] }, credentials ) for chunk in response["stream"]: payload = None # Generated text if "output" in chunk and "text" in chunk["output"]: payload = { "type": "text", "message": chunk["output"]["text"] } print({"t": chunk["output"]["text"]}) # Citation elif "citation" in chunk: payload = { "type": "citation", "citation": chunk['citation']['retrievedReferences'] } print({"c": chunk['citation']['retrievedReferences']}) # Continue if not payload: continue # Publish AppSync publish_appsync_message(sub, appsync_session_id, payload, credentials) except Exception as e: print(str(e)) raise DependsOn: - LambdaBedrockKbRole - BedrockKnowledgeBase LambdaRagSREventInvokeConfig: Type: AWS::Lambda::EventInvokeConfig Properties: FunctionName: !GetAtt LambdaRagSR.Arn Qualifier: $LATEST MaximumRetryAttempts: 0 MaximumEventAgeInSeconds: 300 LambdaCsvChunker: Type: AWS::Lambda::Function Properties: FunctionName: !Sub csv-chunker-${SystemName}-${SubName} Description: !Sub Lambda Function to embed with custom chunk for ${SystemName}-${SubName} Architectures: - x86_64 Runtime: python3.14 Handler: index.lambda_handler Timeout: 900 MemorySize: 512 Role: !GetAtt LambdaCsvChunkerRole.Arn Tags: - Key: Cost Value: !Sub ${SystemName}-${SubName} Code: ZipFile: | import json import csv import boto3 from io import StringIO s3 = boto3.client('s3') def lambda_handler(event, context): try: bucket_name = event.get('bucketName') input_files = event.get('inputFiles', []) output_files = [] for file_info in input_files: original_file_location = file_info.get('originalFileLocation', {}) s3_location = original_file_location.get('s3Location', {}) original_uri = s3_location.get('uri', '') content_batches = file_info.get('contentBatches', []) output_batches = [] for batch in content_batches: input_key = batch.get('key') # Read input file from S3 response = s3.get_object(Bucket=bucket_name, Key=input_key) input_content = json.loads(response['Body'].read().decode('utf-8')) # Extract CSV content csv_content = input_content['fileContents'][0]['contentBody'] # Remove BOM if present (input may have BOM) if csv_content.startswith('\ufeff'): csv_content = csv_content[1:] csv_reader = csv.DictReader(StringIO(csv_content)) # Process each row as a chunk file_contents = [] for row in csv_reader: content_body = f"ååãçªå·: {row.get('ååãçªå·', '')}\nååçªå·: {row.get('ååçªå·', '')}\n\nååãå
容:\n{row.get('ååãå
容', '')}\n\nåçå
容:\n{row.get('åçå
容', '')}" content_metadata = { "ååãçªå·": row.get('ååãçªå·', ''), "販売圢æ
": row.get('販売圢æ
', ''), "å仿¥æ": row.get('å仿¥æ', ''), "å®äºæ¥æ": row.get('å®äºæ¥æ', ''), "ååçªå·": row.get('ååçªå·', ''), "ã«ããŽãª": row.get('ã«ããŽãª', ''), "ã¹ããŒã¿ã¹": row.get('ã¹ããŒã¿ã¹', '') } file_contents.append({ "contentBody": content_body, "contentType": "TEXT", "contentMetadata": content_metadata }) # Write output file to S3 output_key = input_key.replace('.json', '_transformed.json') output_data = {"fileContents": file_contents} s3.put_object( Bucket=bucket_name, Key=output_key, Body=json.dumps(output_data, ensure_ascii=False), ContentType='application/json' ) output_batches.append({"key": output_key}) output_files.append({ "originalFileLocation": original_file_location, "fileMetadata": file_info.get('fileMetadata', {}), "contentBatches": output_batches }) return {"outputFiles": output_files} except Exception as e: print(f"Error: {str(e)}") import traceback traceback.print_exc() raise LambdaInvokePermissionCsvChunker: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref LambdaCsvChunker Action: lambda:InvokeFunction Principal: bedrock.amazonaws.com SourceAccount: !Ref AWS::AccountId # SourceArn: !Sub "arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:knowledge-base/${BedrockKnowledgeBase}" DependsOn: - LambdaCsvChunker # - BedrockKnowledgeBase # ------------------------------------------------------------# # Lambda Role (IAM) # ------------------------------------------------------------# LambdaBedrockKbRole: Type: AWS::IAM::Role Properties: RoleName: !Sub LambdaBedrockKbRole-${SystemName}-${SubName} Description: This role allows Lambda functions to invoke Bedrock Knowledge Bases and AppSync Events API. AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole - arn:aws:iam::aws:policy/AWSXRayDaemonWriteAccess Policies: - PolicyName: !Sub LambdaBedrockKbPolicy-${SystemName}-${SubName} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "bedrock:InvokeModel" - "bedrock:InvokeModelWithResponseStream" - "bedrock:GetInferenceProfile" - "bedrock:ListInferenceProfiles" Resource: - !Sub "arn:aws:bedrock:*::foundation-model/*" - !Sub "arn:aws:bedrock:*:${AWS::AccountId}:inference-profile/*" - Effect: Allow Action: - "bedrock:RetrieveAndGenerate" - "bedrock:Retrieve" Resource: - !GetAtt BedrockKnowledgeBase.KnowledgeBaseArn - Effect: Allow Action: - "appsync:connect" Resource: - Fn::ImportValue: !Sub AppSyncApiArn-${SystemName}-${SubName} - Effect: Allow Action: - "appsync:publish" - "appsync:EventPublish" Resource: - Fn::Join: - "" - - Fn::ImportValue: !Sub AppSyncApiArn-${SystemName}-${SubName} - /channelNamespace/rag-stream-response LambdaCsvChunkerRole: Type: AWS::IAM::Role Properties: RoleName: !Sub LambdaCsvChunkerRole-${SystemName}-${SubName} AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: !Sub LambdaCsvChunkerPolicy-${SystemName}-${SubName} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "s3:GetObject" - "s3:PutObject" - "s3:ListObject" Resource: - !GetAtt S3BucketKbDatasource.Arn - !Sub ${S3BucketKbDatasource.Arn}/* - !GetAtt S3BucketKbIntermediate.Arn - !Sub ${S3BucketKbIntermediate.Arn}/* # ------------------------------------------------------------# # IAM Role for Bedrock Knowledge Base # ------------------------------------------------------------# IAMRoleBedrockKb: Type: AWS::IAM::Role Properties: RoleName: !Sub BedrockKbRole-${SystemName}-${SubName} AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - sts:AssumeRole Principal: Service: - bedrock.amazonaws.com Condition: StringEquals: "aws:SourceAccount": !Ref AWS::AccountId # ArnLike: # "aws:SourceArn": !Sub "arn:aws:bedrock:${AWS::Region}:${AWS::AccountId}:knowledge-base/*" Policies: - PolicyName: !Sub BedrockKbPolicy-${SystemName}-${SubName} PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - "s3:GetObject" - "s3:ListBucket" - "s3:PutObject" Resource: - !GetAtt S3BucketKbDatasource.Arn - !Sub ${S3BucketKbDatasource.Arn}/* - !GetAtt S3BucketKbIntermediate.Arn - !Sub ${S3BucketKbIntermediate.Arn}/* - Effect: Allow Action: - "s3vectors:GetIndex" - "s3vectors:QueryVectors" - "s3vectors:PutVectors" - "s3vectors:GetVectors" - "s3vectors:DeleteVectors" Resource: - !GetAtt S3VectorBucketIndex.IndexArn - Effect: Allow Action: - "bedrock:InvokeModel" Resource: - !Sub arn:aws:bedrock:${AWS::Region}::foundation-model/${EmbeddingModelId} - Effect: Allow Action: - "lambda:InvokeFunction" Resource: - !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:csv-chunker-${SystemName}-${SubName}*" DependsOn: - S3BucketKbDatasource - S3VectorBucketIndex - LambdaCsvChunker - S3BucketKbIntermediate # ------------------------------------------------------------# # Output Parameters # ------------------------------------------------------------# Outputs: # S3 S3BucketKbDatasourceName: Value: !Ref S3BucketKbDatasource # API Gateway APIGatewayEndpointRagSR: Value: !Sub https://${RestApiRagSR}.execute-api.${AWS::Region}.${AWS::URLSuffix}/${RestApiStageRagSR}/ragsr Export: Name: !Sub RestApiEndpointRagSR-${SystemName}-${SubName} ç¶ç·šèšäº Amazon Bedrock Knowledge Bases ã§æ§é åããŒã¿(CSV)ã䜿çšãã RAG ãã€ãã -UIç·š- Amazon Bedrock Knowledge Bases ãš Amazon S3 Vectors ã§æ§ç¯ãã RAG ç°å¢ã§ãæ§é åããŒã¿ãããŒã¿ãœãŒã¹ã«ãããšãã®æ€çŽ¢ç²ŸåºŠåäžãç®æããŸãããæ¬èšäºã¯ UI ç·šã§ãã blog.usize-tech.com 2026.03.23 ãŸãšã ãããã§ããã§ããããã ã¡ã¿ããŒã¿ãã£ã«ã¿ãªã³ã°ã¯èšèšæ¬¡ç¬¬ã§ããªã现ããæ€çŽ¢ãã§ãããã§ããããã®åã³ãŒãã£ã³ã°ã倧å€ã§ããããã¿ã«æ±çšçãªãã£ã«ã¿èšå®ãå®è£
ããããšãããšéçºè² æ
å¢ããã°ã®æž©åºã«ãªããããªã®ã§ããã£ã«ã¿å¯Ÿè±¡é
ç®ã¯ãªãã¹ãå³éžããæ¹ããããšæããŸãã æ¬èšäºãçæ§ã®ã圹ã«ç«ãŠãã°å¹žãã§ãã