「Amazon Bedrockを使用した生成型AIアプリ:Go開発者のための入門ガイド」

「バイパーでのGo開発者のための生成型AIアプリ:Amazon Bedrockを使った入門ガイド」

この記事は、APIを介してAmazonとサードパーティのモデルプロバイダから提供されるAmazon Bedrockのベースモデルにアクセスできる完全管理されたサービスであるAmazon Bedrockを使用してジェネラティブAIアプリケーションを構築したいGo開発者のための入門ガイドです。

Amazon BedrockのためにこのGitHubリポジトリにコードの例があります。

始める前に

まず、既にGoを最新バージョンにインストールしていない場合は、インストールする必要があります。

Amazon Bedrockを構成してセットアップする方法について調べてください(Foundationモデルへのアクセスをリクエストすることも含まれます)。

例を実行する際には、ローカルマシンからAmazon Bedrock API操作を呼び出すためにAWS Go SDKを使用します。そのためには以下が必要です。

  1. IAMユーザー/ロールを使用してプログラムアクセスを許可する。
  2. 利用しているIAM IDに以下の権限を許可する。
{    "Version": "2012-10-17",    "Statement": [        {            "Effect": "Allow",            "Action": "bedrock:*",            "Resource": "*"        }    ]}

AWS Go SDK認証に関する注意事項

AWS Go SDKを使用したことがある場合は、これに慣れているかもしれませんが、そうでない場合は、コードサンプルでは、以下のように構成を読み込んで認証に必要な資格情報を指定しています。

cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRegion(region))

config.LoadDefaultConfigを使用してaws.Configインスタンスを初期化すると、AWS Go SDKはデフォルトの認証チェーンを使用してAWSの資格情報を検索します。詳細についてはこちらをご覧ください。しかし私の場合、既に<USER_HOME>/.awscredentialsファイルがあり、SDKによって検出されて使用されています。

Amazon Bedrockクライアントタイプ

Amazon Bedrock Go SDKでは、2つのクライアントタイプがサポートされています:

  1. bedrock.Clientは、ベースのFoundationモデルに関する情報を取得したり、カスタムモデルファインチューニングジョブを作成してベースモデルをカスタマイズするなどの操作に使用できます。
  2. bedrockruntime.Clientは、Foundationモデルで推論を実行するためにbedrockruntimeパッケージで使用されます(これが興味深い部分です!)。

Amazon Bedrock Foundationモデルの一覧表示

始める前に、Amazon Bedrockのコントロールプレーンクライアントを使用してAmazon Bedrock内のfoundationモデルの一覧表示のシンプルな例を見てみましょう(エラーハンドリングやログ出力は省略しています)。

    region := os.Getenv("AWS_REGION")    if region == "" {        region = defaultRegion    }    cfg, err := config.LoadDefaultConfig(context.Background(), config.WithRegion(region))    bc := bedrock.NewFromConfig(cfg)    fms, err := bc.ListFoundationModels(context.Background(), &bedrock.ListFoundationModelsInput{        //ByProvider: aws.String("Amazon"),        //ByOutputModality: types.ModelModalityText,    })    for _, fm := range fms.ModelSummaries {        info := fmt.Sprintf("Name: %s | Provider: %s | Id: %s", *fm.ModelName, *fm.ProviderName, *fm.ModelId)        fmt.Println(info)    }

Amazon BedrockのサポートされるFoundation Modelsを取得するために、bedrock.Clientインスタンスを作成し、ListFoundationModels APIを使用します。

GitHubリポジトリをクローンし、正しいディレクトリに変更します:

git clone https://github.com/build-on-aws/amazon-bedrock-go-sdk-examplescd amazon-bedrock-go-sdk-examplesgo mod tidy

次の例を実行します:

go run bedrock-basic/main.go

サポートされるFoundation Modelsのリストが表示されるはずです。

なお、 ListFoundationModelsInputでプロバイダ、モーダリティ(入力/出力)などでフィルタリングも行うことができます。

推論のためにモデルを呼び出す(bedrockruntime APIを使用)

まず、Anthropic Claude(v2)モデルを使用してみましょう。以下のプロンプトを使用したシンプルなコンテンツ生成シナリオの例です:

<paragraph> "1758年、スウェーデンの植物学者で動物学者のカール・リンネが、彼の『自然体系』という著書で、種の二語名づけ(二名法)を発表しました。Canisはラテン語で「犬」という意味であり、この属(genus)の中で、彼は家庭犬、オオカミ、そしてゴールデンジャッカルをリストアップしました。"</paragraph>5年生が理解できるように上記の段落を書き換えてください。<rewrite></rewrite> タグであなたの書き直しを出力してください。

プログラムを実行するには:

go run claude-content-generation/main.go

出力は、あなたの場合には若干異なるかもしれませんが、次のようになるはずです:

<rewrite>カール・リンネはスウェーデンの科学者で、植物と動物を研究しました。1758年には、Systema Naturaeという本を出版しました。この中で、彼はすべての種について二語の名前を与えました。例えば、彼は犬をCanis familiarisと呼びました。Canisはラテン語で犬の意味です。Canisという名前の下で、リンネはペットの犬、オオカミ、そしてゴールデンジャッカルをリストアップしました。つまり、彼は最初の言葉Canisを、犬、オオカミ、ジャッカルなど、関連する動物をグループ化するために使用しました。このような二語の名前で種を命名する方法は二名法と呼ばれ、今日でも科学者によって使用されています。</rewrite>

ここにはコードスニペット(エラーハンドリングなどを省いたもの)があります。

    //...    brc := bedrockruntime.NewFromConfig(cfg)    payload := {        Prompt:            fmt.Sprintf(claudePromptFormat, prompt),        MaxTokensToSample: 2048,        Temperature:       0.5,        TopK:              250,        TopP:              1,    }    payloadBytes, err := json.Marshal(payload)    output, err := brc.InvokeModel(context.Background(), &bedrockruntime.InvokeModelInput{        Body:        payloadBytes,        ModelId:     aws.String(claudeV2ModelID),        ContentType: aws.String("application/json"),    })    var resp Response    err = json.Unmarshal(output.Body, &resp)    //.....

bedrockruntime.Clientインスタンスを取得し、Amazon Bedrockに送信する必要があるリクエストを含むペイロードを作成します(プロンプトも含まれます)。ペイロードはJSON形式であり、その詳細はFoundationモデルの推論パラメータでよくドキュメント化されています。

その後、ペイロードをInvokeModelの呼び出しに含めます。呼び出しでのModelIdに注意してください。これはベースモデルIDの一覧から取得できます。その後、JSONの応答をResponse構造体に変換します。

この「ワークフロー」(プロンプト付きのペイロードの準備、ペイロードのマーシャリング、モデルの呼び出し、アンマーシャリング)は、私たちの例(おそらくあなたのアプリケーションも)で共通して使用され、モデル/ユースケースに応じてわずかに変更されます。

このプロンプトを使用して情報抽出シナリオも試すことができます。

<directory>電話帳:ジョンラトラブ、800-232-1995、[email protected]ジョシーラナ、800-759-2905、[email protected]ケヴィンスティーブンス、800-980-7000、[email protected]電話帳はHRマネージャーによって常に最新の状態に保たれます。"<directory>テキスト内に含まれている電子メールアドレスを、テキスト内の出現順に1行ずつ出力してください。テキストに電子メールアドレスが含まれていない場合は、"N/A"を出力してください。

プログラムを実行するには:

go run claude-information-extraction/main.go

チャット:典型的なGenAIの例

チャットアプリケーションがないGenAIの記事は考えられませんよね?

Claudeモデルで続けましょう。こちらは会話例です。一つだけのメッセージではなく、複数のメッセージ(チャット)をやり取りし、会話履歴も保持する方法を示しています。

シンプルな実装のため、状態はメモリに保持されています。

アプリケーションを実行するには:

go run claude-chat/main.go# LLMとのメッセージのやり取りをログに記録したい場合は、# プログラムを詳細モードで実行するgo run claude-chat/main.go --verbose

以下は私が行った会話の出力です。チャット履歴の保持により、最後の応答が前の応答に基づいて生成されていることに注目してください。

ストリーミングAPIの使用

前のチャットの例では、完全な出力を取得するまで数秒待つ必要がありました。これはプロセスが完全に同期的であるためです。モデルを呼び出して完全な応答を待ちます。

InvokeModelWithResponseStream APIを使用すると、非同期な手法である「ストリーミング」として知られるアプローチを採用できます。これは、応答をユーザーに表示したり、応答が生成される際に応答を処理したりする場合に便利です。これにより、アプリケーションに「レスポンシブ」なエクスペリエンスが提供されます。

試すために、コンテンツ生成例と同じプロンプトを使用します。

  <rewrite>カール・リンネはスウェーデンの科学者で、植物と動物を研究しました。1758年に、彼はSystema Naturaeという本を出版しました。この本で彼はすべての種に二つの単語の名前を与えました。例えば、彼は犬をCanis familiarisと呼びました。Canisは犬のラテン語です。Canisの下では、Linnaeusはペットの犬、オオカミ、そしてジャッカルをリストアップしました。犬、オオカミ、ジャッカルなど、犬に関連する動物をグループ化するために彼は最初の単語Canisを使用しました。この二つの単語で種を命名する方法は二名法命名法と呼ばれ、現在も科学者によって使用されています。</rewrite>

アプリケーションを実行する:

go run streaming-claude-basic/main.go

Amazon Bedrockによってパーツが生成されるのをコンソールに出力するのを見るはずです。

コードを見てみましょう。

最初のパートは普通のビジネスです。プロンプト(およびパラメータ)を使用してペイロードを作成し、InvokeModelWithResponseStream APIを呼び出し、bedrockruntime.InvokeModelWithResponseStreamOutputのインスタンスを返します。

    //...    brc := bedrockruntime.NewFromConfig(cfg)    payload := Request{        Prompt:            fmt.Sprintf(claudePromptFormat, prompt),        MaxTokensToSample: 2048,        Temperature:       0.5,        TopK:              250,        TopP:              1,    }    payloadBytes, err := json.Marshal(payload)    output, err := brc.InvokeModelWithResponseStream(context.Background(), &bedrockruntime.InvokeModelWithResponseStreamInput{        Body:        payloadBytes,        ModelId:     aws.String(claudeV2ModelID),        ContentType: aws.String("application/json"),    })    //....

次のパートは、InvokeModel APIと比較して異なります。 InvokeModelWithResponseStreamOutputインスタンスにはまだ完全な応答がありませんので、単純に呼び出し元に返すことはできません(またはすべきではありません)。その代わりに、この出力をprocessStreamingOutput関数で少しずつ処理することを選択します。

それに渡される関数は、type StreamingOutputHandler func(ctx context.Context, part []byte) errorという型です。これは呼び出し元アプリケーションが出力チャンクの処理方法を指定する方法を提供するために定義したカスタム型です。この場合、単にコンソール(標準出力)に出力します。

    //...    _, err = processStreamingOutput(output, func(ctx context.Context, part []byte) error {        fmt.Print(string(part))        return nil    })    //...

processStreamingOutput関数が行うことを見てみましょう(簡潔さのために一部のコードは省略されています)。InvokeModelWithResponseStreamOutputは、イベントのチャネル(types.ResponseStream型)へのアクセスを提供します。これは、LLMによって部分的に生成された応答のJSON形式の文字列であり、これをResponse構造体に変換します。

私たちはhandler関数(部分的な応答をコンソールに表示する)を呼び出し、部分ビットを追加して完全な応答を構築するために保持します。完全な応答は最終的に関数から返されます。

func processStreamingOutput(output *bedrockruntime.InvokeModelWithResponseStreamOutput, handler StreamingOutputHandler) (Response, error) {    var combinedResult string    resp := Response{}    for event := range output.GetStream().Events() {        switch v := event.(type) {        case *types.ResponseStreamMemberChunk:            var resp Response            err := json.NewDecoder(bytes.NewReader(v.Value.Bytes)).Decode(&resp)            if err != nil {                return resp, err            }            handler(context.Background(), []byte(resp.Completion))            combinedResult += resp.Completion            //....    }    resp.Completion = combinedResult    return resp, nil}

レスポンシブなチャットアプリケーション、ストリーミングAPIのおかげで

ストリーミング応答の処理方法の理解ができたので、シンプルなチャットアプリケーションはこれを使用するのに最適です!

コードを再度詳しく説明することはしません。チャットアプリケーションをInvokeModelWithResponseStream APIを使用して更新し、前の例と同様に応答を処理するようにしました。

新しいバージョンのアプリを実行するには:

go run claude-chat-streaming/main.go

これまでにAnthropic Claude v2モデルを使用しました。テキスト生成のCohereモデルの例も試すことができます。実行するには:go run cohere-text-generation/main.go

画像生成

画像生成はGenerative AIの典型的なユースケースの一つです!この例では、Amazon BedrockのStable Diffusion XLモデルを使用して、プロンプトと他のパラメータに基づいて画像を生成します。

試してみるには:

go run stablediffusion-image-gen/main.go "<あなたのプロンプト>"# 例: go run stablediffusion-image-gen/main.go "Sri lankaの紅茶畑"go run stablediffusion-image-gen/main.go "森から打ち上げられるロケット船、花園の下には青い空が広がっている、巧妙、ジブリ"

出力として、生成されたJPGファイルが表示されます。

以下は、コードのクイックな説明です(エラーハンドリングは除く)。

InvokeModel呼び出しの出力ペイロードは、Response構造体に変換され、更にbase64イメージ([]byteとしてエンコードされている)を抽出し、encoding/base64を使用してデコードし、最終的に[]byteを出力ファイル(形式:output-<タイムスタンプ>.jpg)に書き込みます。

    //...    brc := bedrockruntime.NewFromConfig(cfg)    prompt := os.Args[1]    payload := Request{        TextPrompts: []TextPrompt{{Text: prompt}},        CfgScale:    10,        Seed:        0,        Steps:       50,    }    payloadBytes, err := json.Marshal(payload)    output, err := brc.InvokeModel(context.Background(), &bedrockruntime.InvokeModelInput{        Body:        payloadBytes,        ModelId:     aws.String(stableDiffusionXLModelID),        ContentType: aws.String("application/json"),    })    var resp Response    err = json.Unmarshal(output.Body, &resp)    decoded, err := resp.Artifacts[0].DecodeImage()    outputFile := fmt.Sprintf("output-%d.jpg", time.Now().Unix())    err = os.WriteFile(outputFile, decoded, 0644)    //...

モデルのパラメータ(CfgScaleSeedSteps)に注目してください。それらの値は利用目的によって異なります。たとえば、CfgScaleは最終的な画像がプロンプトをどれくらい描写するかを決定します。乱数を増やすためには、より低い数値を使用します。詳細については、Amazon Bedrockのインファレンスパラメータのドキュメントを参照してください。

テキストから埋め込みを作成する

テキストの埋め込みは、ドキュメント、段落、文などの構造化されていないテキストの意味のあるベクトル表現を表します。Amazon Bedrockでは、現在、テキストの埋め込みのためのTitan Embeddings G1 - Textモデルをサポートしています。これはテキストの検索、意味の類似性、クラスタリングをサポートします。最大の入力テキスト長は8Kトークンであり、最大の出力ベクトル長は1536です。

を実行するには:

go run titan-text-embedding/main.go "<あなたの入力>"# 例:go run titan-text-embedding/main.go "猫"go run titan-text-embedding/main.go "犬"go run titan-text-embedding/main.go "トレックス"

これはおそらく見るのが一番つまらない出力です!実際には、float64のスライスを見ただけでは何もわかりません。

これは、ベクトルデータベース(これらの埋め込みを保存するためのもの)と意味検索(これらの埋め込みを利用するためのもの)など、他のコンポーネントと組み合わせて使用するとさらに関連性が高くなります。これらのトピックは将来のブログ投稿でカバーされます。今のところ、「動作する」という事実だけを忍耐してください。

まとめ

これがFoundationモデルをAmazon Bedrockで使用してGenAIアプリケーションをパワーアップするためのGo開発者のための出発点として役立つことを願っています。

さらに、Go開発者向けのGenerative AIトピックに関する記事をお楽しみに。それまで、幸せな開発を!

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

人工知能

「ReactとChatGPT APIを使用して独自のAIチャットボットを作成する方法」

このブログでは、ReactとChatGPT APIを使用して独自の人工知能(AI)チャットボットを作成するプロセスを案内します

機械学習

「Amazon SageMakerでのRayを使用した効果的な負荷分散」

以前の記事(たとえば、ここ)では、DNNトレーニングワークロードのプロファイリングとパフォーマンスの最適化の重要性につい...

人工知能

「今日の市場においてAIパワードモバイルアプリが際立っているのは何か?」

AIはモバイルアプリを革命し、個人の経験を提供します最新技術を駆使したアプリ開発の利点、成功、そして将来を探求してください

機械学習

「ひとつのAIモデルで全てのオーディオタスクをこなせるのか?UniAudioに出会ってください:新しいユニバーサルオーディオ生成システム」

生成AIの重要な側面の1つは音声生成です。近年、生成AIの人気の高まりにより、音声制作における多様で新興のニーズがますます...

機械学習

「トランスフォーマーの単純化:あなたが理解する言葉を使った最先端の自然言語処理(NLP)— パート1 — イントロ」

「トランスフォーマーは、AIの進歩に大きく貢献したディープラーニングのアーキテクチャですそれはAIとテクノロジー全体の範...

機械学習

ラストマイルAIは、AiConfigをリリースしました:オープンソースの構成駆動型、ソースコントロールに対応したAIアプリケーション開発フレームワーク

AIアプリケーション開発の進化する風景の中で、AI Configは、LastMile Ai から登場し、開発者がAIモデルを統合し、管理する方...