目次
はじめに
生成AIでTravelGuideアプリをアップグレードする
進む前に知っておきたいいくつかの基本概念(必要ならスキップしてOK)
Amazon Bedrock:実際に解決できる課題
Amazon Bedrockでのカスタムナレッジベースとモデルカスタマイズ
ハンズオンラボ:ナレッジベースを作成する
Amazon Bedrock GuardrailsによるAIセーフティコントロール
Bedrock API経由でAIモデルを統合する
より良い会話のための工学:プロンプトエンジニアリング
次のステップ
はじめに
私はAWSスキルを磨き、GenAIがデブオプスのパイプラインに実際にどこに当てはまるのかを理解したかったのです。単なる“持てはやし(ハイプ)”ではなく。調べているうちに、このブログ記事に行き着きました。
頭にあったのは2つのことです。AWSの専門性を深めること、そしてGenAIを本番システムに責任ある形でどのように統合するかを理解すること。
これは3本構成のシリーズの最初の記事で、CourseraのDevOps and AI on AWS Specializationを学習し、修了するまでの経験を共有します。
>生成AIでのTravelGuideアプリのアップグレード
最初のコースは「DevOps and AI on AWS: Upgrading Apps with Generative AI」と呼ばれます。タイトルから内容はかなり明確ですが、正直に言うと、これまでAmazon BedrockのようなAWSのGenAIサービスは使ったことがありませんでした。
Gemini APIをフロントエンドアプリに統合した経験はありました。以前のブログ記事を読んでくださっている方ならおそらくご存じだと思いますが、私はもともと開発者で、AIをNext.jsアプリに統合する方法を学びたくて、SummarAIというアプリを作りました。このアプリはPDFをアップロードすると、AIで重要な洞察を即座に抽出します。その際はGeminiのAI APIを使っていましたが、AWSにはAIの分野で面白いツール群があることは知っており、圧倒的に注目されるのがAmazon Bedrockです。
この最初のコースでは、さまざまな目的地の旅行情報を収集する旅行ガイドアプリを作成することに焦点を当てます。また、旅行者が従うための旅程(イティネラリ)を作ることもでき、訪れた都市についてレビューを残すことも可能にします。
EC2インスタンス上でホストされるPythonアプリで、現在はBoto3を使ってDynamoDBのテーブルからアイテムを読み取り、それらを表示しています。
>進む前に知っておきたいいくつかの基本概念(必要ならスキップしてOK)
生成AIとは何ですか?
生成型人工知能(生成AI)とは、新しいコンテンツやアイデア(会話、物語、画像、動画、音楽など)を作り出せるタイプのAIです。人間の言語、プログラミング言語、アート、化学、生物学、あるいはあらゆる複雑な領域を学習できます。そして、知っていることを再利用して新しい課題を解決します。
LLM (Large Language Model:大規模言語モデル)とは何ですか?
大規模言語モデル(LLM)としても知られる大規模なディープラーニングモデルは、膨大な量のデータで事前学習されています。基盤となるトランスフォーマは、エンコーダとデコーダで構成され、自己注意(self-attention)の能力を持つ一連のニューラルネットワークです。エンコーダとデコーダは、テキストのシーケンスから意味を抽出し、その中にある単語やフレーズ同士の関係性を理解します。
>Amazon Bedrock:実際に解決できる課題
コースを進めながら、このTravelGuideアプリにはいくつかの制限があることがわかってきました。各都市について、コンテンツは書かれて編集される必要があります。旅程(イティネラリ)について、調査して作り込むという手作業のステップが必要で、それには多くの時間がかかります。アプリがスケールして、さらに多くの都市を追加したいとなったらどうなるでしょうか。このプロセスは非常に時間がかかり、アプリの拡張(スケールアップ)をどれだけ素早く行えるかを制限します。もう一つの制限は、旅程が個々のニーズに合わせてパーソナライズできないことです。コンテンツは静的なので、パブに興味がある人向けの旅程は、夜遊びが苦手で美術館により関心がある人向けのものとはまったく異なります。
これらの課題を解決し、Amazon Bedrockというサービスを使って旅行のおすすめや旅程を生成することで、アプリを強化できるはずです。公式のWebページにある通り、Amazon Bedrockは「生産規模(production scale)で生成AIアプリケーションやエージェントを構築するためのプラットフォーム」です。基盤モデルを使って生成AIアプリを構築できるようにする、フルマネージドなAWSサービスです。
Bedrockが提供する基盤モデルをAPI経由で利用すれば、プロンプトに基づいてリアルタイムにコンテンツを作成し、結果を生成できます。これにより、旅行のおすすめや旅程を作り出しつつ、これらのモデルを実行・管理するために必要なインフラはAWSが担ってくれます。
Amazon Bedrockは複数の異なる基盤モデル(ここでは今後FMと呼びます)を提供しており、学習を始めたときに私がそう感じたように、あなたも「適切なモデルをユースケースに選ぶのは難しい」という感覚を持つかもしれません。必要なタスクに対して、どうやって適切なFMを選べばよいのでしょうか。幸いなことに、FMは扱える入力と出力によって分類できます。
入力は一般的にテキストと画像です。
出力は、テキスト、チャット、画像、そして埋め込み(embeddings)です。
「embeddings(埋め込み)」という用語を見かけて、その意味が気になるかもしれません。埋め込みをとてもクリエイティブに説明している素晴らしいWebサイトを共有したいと思います: LLM Embeddings Explained: A Visual and Intuitive Guide 。
一言でいうと、埋め込みベクトルは、情報を取得・強化するときに関連するコンテンツを見つけるために使われます。Amazon Bedrock Knowledge Bases(知識ベース)は、埋め込みを使ってRetrieval-Augmented Generation(RAG)を実装しています。
Amazon Bedrock Knowledge Bases を使うと、基盤モデルやエージェントに、企業のプライベートなデータソースから文脈に応じた情報を提供して、より関連性が高く、正確で、カスタマイズされた応答を実現できます。
こちらは、Amazon Bedrock でサポートされている基盤モデルの比較表です。
Amazon Bedrock におけるカスタム知識ベースとモデルのカスタマイズ
たとえば、プライベートな自社データを Bedrock に統合して、レビューをユーザーにとってより関連性の高いものにしたいとします。ここで言うのは、企業が保有するプライベートで独自のデータであり、デフォルトでは Amazon Bedrock はこのデータにアクセスできません。
プライベートデータは、モデルをカスタマイズするか、Knowledge Bases を使うかのどちらかで統合できます。
モデルをカスタマイズする
モデルをプライベートデータで学習させます。これにより、特定のユースケースに対してより良い性能を得られ、より良い顧客体験を作れます。Amazon Bedrock は以下の方法を提供しています:
ディスティレーション → 大きくて賢いモデル(教師)から、小さく高速でコスト効率の高いモデル(生徒)へ知識を転送します。
強化学習による微調整 → フィードバックに基づく学習によって、基盤モデルの整合性を特定のユースケースに合わせて改善します。教師あり学習とは異なり、ラベル付きの入力-出力ペアを提供しません。
教師あり微調整 → ラベル付きデータを提供することで、特定のタスクにおける性能を向上させるためにモデルを学習します。モデルは、正しい入力-出力の対応関係に関する明示的な例から学習します。
継続的な事前学習 → ラベルなしデータを使って、特定の種類の入力に慣れさせることで基盤モデルを事前学習します。ラベル付きの例を必要とせずに、モデルのドメイン知識を向上させられます。
注意:カスタマイズにはいくつかの費用がかかります。 Amazon Bedrock のエンドポイントとクォータ を参照してください。
知識ベース
自社のWebサイトにもある通り、「基盤モデルやエージェントに、企業のプライベートなデータソースから文脈に応じた情報を与えて、より関連性が高く、正確で、カスタマイズされた応答を提供できます」。このユースケースでは、モデルのファインチューニングや再学習を行わなくても、プライベートなデータソースに接続して、ユーザーが対話しながら質問できるようになります。モデルはこのデータにアクセスでき、ユーザーが必要とする回答を提供できます。
つまり、自分で用意したデータソースをアップロードして、プロンプトを強化するために使われる情報のリポジトリを作成することで機能します。これを実現するために、Retrieval Augmented Generation(RAG)という仕組みを使います。
RAGは、会社のソースからデータを取得してプロンプトを補強し、より関連性が高く、正確な応答を返すための手法です。Amazon Bedrock Knowledge Bases は、データを埋め込み(テキストの数値表現)として保存するためにベクトルデータベースを使用します。ナレッジベースは、クエリ時に最も関連性の高い情報を取得することで、Bedrock と企業のプライベートデータをつなぎます。データを意味的な類似性で検索し、最も有用なチャンクを取得して、それらを追加の文脈としてモデルに渡します。これにより、モデルは自然言語の回答を生成できます。システムが単に厳密なキーワードを一致させるのではなく、ユーザーの質問の意味と文脈を理解して、関連する情報を返します。
ハンズオンラボ:知識ベースの作成
このコースでは、Amazon Bedrock の知識ベースを作成し、アプリで使えるように設定する必要があるハンズオンラボがありました。
知識ベースを作るのはかなり簡単です。コンソールで Amazon Bedrock に移動し、Create をクリックします。Knowledge Base with vector store を選ぶと、この画面が表示されます:
知識ベースはドキュメントと同期します。この場合、アプリは Amazon S3 を使用します。別のデータソースのオプションを選択でき、知識ベースには最大5つの異なるデータソースを設定できます。
S3 バケットをデータソースとして設定し、必要なデータをアップロードします。正しいデータソース名を追加し、適切な S3 バケットを選択してください。
ベクトルストアを選択し、内容を確認して作成します。
次のオプションを選択すると、Bedrock が、これらの埋め込みを保存するための Amazon OpenSearch Serverless クラスターを作成してくれます。
詳細を確認してナレッジベースを作成します
作成できたら、検索用にコンテンツをインデックスするためにデータソースを同期することを忘れないでください。
コンソールでTest Knowledge Baseボタンをクリックしてモデルをテストできます。モデルを選択し、プロンプトを入力して、その魔法を見てください。
ナレッジベースは2通りの方法で利用できます
Retrieve APIを使用して、追加の応答なしでナレッジベースから直接情報を照会して取得します。
RetrieveAndGenerate APIを使用します。このAPIは入力としてプロンプトを受け取り、取得した情報に基づいて応答を生成します。
Amazon Bedrock Guardrails による AI セーフティコントロール
Guardrailsは、プロンプト設計だけでは管理しきれない部分を超えて、LLM の応答を保護し制御します。Bedrock は、責任あるAIの振る舞いを確実にするために設定可能なガードレールを提供します:
いくつかのコンテンツフィルタ:
- 憎悪、侮辱、暴力などの有害なカテゴリをブロックします。
グラウンディングと関連性:
グラウンディング:事実の正確性に関する信頼度のしきい値。
関連性:モデルの応答がユーザーの質問に対して関連しているかを確認します
詳細は こちら。
Bedrock API を通じて AI モデルを統合する
以下は、AWS ドキュメントにある、Amazon Titan Text モデルを使って Amazon Bedrock API と Python アプリを統合する方法の例です。
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""
会議の議事録からアクションアイテムのリストを作成する方法を、Amazon Titan Text モデル(オンデマンド)で示します。
"""
import json
import logging
import boto3
from botocore.exceptions import ClientError
class ImageError(Exception):
""Amazon Titan Text モデルが返すエラーに対するカスタム例外""
def __init__(self, message):
self.message = message
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
def generate_text(model_id, body):
"""
Amazon Titan Text モデルをオンデマンドで使用してテキストを生成します。
Args:
model_id (str): 使用するモデルID。
body (str) : 使用するリクエストボディ。
Returns:
response (json): モデルからの応答。
"""
logger.info(
""Amazon Titan Text モデル %s でテキストを生成しています"", model_id)
bedrock = boto3.client(service_name='bedrock-runtime')
accept = "application/json"
content_type = "application/json"
response = bedrock.invoke_model(
body=body, modelId=model_id, accept=accept, contentType=content_type
)
response_body = json.loads(response.get("body").read())
返却形式: {"translated": "翻訳されたHTML"}finish_reason = response_body.get("error")
if finish_reason is not None:
raise ImageError(f"テキスト生成エラー。エラーは {finish_reason} です")
logger.info(
"Amazon Titan Text モデル %s で正常にテキストを生成しました", model_id)
return response_body
def main():
"""
Amazon Titan Text モデルのサンプルのエントリポイント。
"""
try:
logging.basicConfig(level=logging.INFO,
format="%(levelname)s: %(message)s")
# モデル ID を、他の任意の Titan Text モデルに置き換えることができます。
# Titan Text モデルファミリーの model_id は、以下に記載のとおりです:
# amazon.titan-text-premier-v1:0, amazon.titan-text-express-v1, amazon.titan-text-lite-v1
model_id = 'amazon.titan-text-premier-v1:0'
prompt = """会議の議事録: ミゲル: やあブレント、新しいプロダクトのローンチに向けて
私たちの作業ストリームについて話し合いたいんだ。ブレント: もちろんミゲル、特に
何を話したいですか?ミゲル: はい、ユーザーがどのようにプロダクトに入ってくるかについて話したいです。
ブレント: 了解です。その場合、ナミタを入れましょう。ナミタ: みなさんこんにちは
ブレント: ナミタ、こんにちは。ミゲルはユーザーがどのようにプロダクトに入ってくるか
を話したいと言っています。 """
body = json.dumps({
"inputText": prompt,
"textGenerationConfig": {
"maxTokenCount": 3072,
"stopSequences": [],
"temperature": 0.7,
"topP": 0.9
}
})
response_body = generate_text(model_id, body)
print(f"入力トークン数: {response_body['inputTextTokenCount']}")
for result in response_body['results']:
print(f"トークン数: {result['tokenCount']}")
print(f"出力テキスト: {result['outputText']}")
print(f"完了理由: {result['completionReason']}")except ClientError as err:
message = err.response["Error"]["Message"]
logger.error("クライアントエラーが発生しました: %s", message)
print("クライアントエラーが発生しました: " +
format(message))
except ImageError as err:
logger.error(err.message)
print(err.message)
else:
print(
f"Amazon Titan Text Premier モデル {model_id} でテキストの生成が完了しました。")
if __name__ == "__main__":
main()
会話をより良くするエンジニアリング:プロンプトエンジニアリング
大規模言語モデル(LLM)におけるプロンプトとは、ユーザーがAIに対して特定の関連性のある正確な応答を生成するよう導くために提供する入力テキスト、指示、または質問のことです。
Amazon Bedrockでは、LLMはすでに私たちのために構築され学習済みです。これらのLLMからより良い結果を得る最も簡単な方法は、LLMに渡すプロンプトを改善することです。
優れたプロンプトを書くための、良い戦略であり覚えやすいのがCO-STAR手法(Context → Objective → Style → Tone → Audience → Response)です。強力なプロンプトの例を示します:
Context: 私たちは、観光地の罠ではなく本物のローカル体験に重点を置く旅行レビューアプリ「Wandr」をリリースします。TripAdvisorとは違い、レビュー投稿者が実際にその場所を訪れたことをGPSチェックインで検証し、写真による証拠の提出を必須にします。私たちのコミュニティは、冒険好きの旅行者とカルチャー好きの人々で構成されており、隠れた名所を見つけたいと考えています。
Objective: アプリストアの掲載ページにある「私たちについて」のセクションを、興味を持つユーザーがアプリをダウンロードしたくなるように書いてください。目標の文字数:200〜250語。必ず、主要な価値提案として「検証済みのレビュー」「ローカル発見へのこだわり」「スパムのないコミュニティ」を含めてください。
Style: 私たちが解決する問題の情景が浮かぶようなストーリーテリングのアプローチにしてください。旅行の気分を呼び起こす、鮮やかで五感に訴える言葉を使います。構成:問題 → 解決策 → 利点。旅行者が共感できる具体的な例や状況を含めてください。
Tone: 冒険的で人を引きつける一方で、信頼できて地に足がついていること。たとえば「経験豊富な旅の仲間が裏情報を教えてくれる」といったイメージで、「企業向けの旅行会社」ではありません。「wanderlust」のような決まり文句は避けてください。安っぽくならないように、あたたかく熱意をもって表現してください。
Audience: 「隠れた」レストランに行ってみたら、同じGoogle検索で見つけた観光客でごった返していた—そんな経験にうんざりしているミレニアル世代およびZ世代の旅行者です。彼らは贅沢よりも本物志向を重視し、設備よりも体験を重視し、プロの批評家よりも仲間からのおすすめを信頼します。
Response: アプリストアの説明文を提示し、その後に箇条書き3〜5個で、アプリストアの掲載文の下部に表示されうる主要な機能を要約してください。
望む結果の長さやフォーマットに関する指示を含めることができます。さらに、プロンプト内でサンプル結果を提示することも可能です。
次のステップ
以上で、AIとAWS Courseraスペシャライゼーションの3部構成シリーズの最初のパートをまとめます。率直に言うと、これから始まるコース「AWS上のDevOpsとAI:生成AIアプリケーションのためのCI/CD」にとてもワクワクしています。学んだことをあなたに共有するのが待ちきれません。お楽しみに!













