🤖

Amazon Bedrock Claude3 Haiku モデルを AWS SDK for Rust を使ってプロンプトを動かす

2024/04/21に公開

はじめに

巷で話題の Amazon Bedrock。
3月には、Claude3 の Haiku モデルが登場し、4月にも Opus モデルが登場しています。
さらに、これらのモデルは GPT 系のモデルよりも優れているとされていて、私も興味関心があります。

今回は、Claude3 の Haiku モデルを AWS SDK for Rust を使って簡単に叩いてみようと思います。
https://aws.amazon.com/jp/blogs/news/anthropics-claude-3-haiku-model-is-now-available-in-amazon-bedrock/
https://aws.amazon.com/jp/blogs/news/anthropics-claude-3-opus-model-on-amazon-bedrock/

環境準備

Rust プロジェクトの作成

$ cargo new bedrock-sample
$ cd bedrock-sample

Cargo.tomlに以下のパッケージを追加します。
aws-sdk-bedrockruntimeというクレートを使って、動かしていきます。

Cargo.toml
[dependencies]
aws-config = { version = "1.1.7", features = ["behavior-version-latest"] }
aws-sdk-bedrockruntime = "1.21.0"
tokio = { version = "1", features = ["full"] }
serde_json = "1.0.64"
serde = { version = "1.0", features = ["derive"] }

https://docs.rs/aws-sdk-bedrockruntime/1.21.0/aws_sdk_bedrockruntime/

念の為、cargo runを実行し、Hello, World! が出力されることを確認しておきましょう。

実装

クライアントの作成

main.rsの上あたりに以下のような形で、クライアント群を生成します。

main.rs
let config = aws_config::load_from_env().await;
let client = aws_sdk_bedrockruntime::Client::new(&config);
let builder = client.invoke_model();

さらにこの段階で、AWS CLIで、AWSへの認証を済ませておいてください。

AWSへの認証については、こちらの記事が参考になるかと思います。
https://zenn.dev/akkie1030/articles/aws-cli-setup-tutorial

構造体の作成

Claude3 のテキストプロンプトを送信するために、以下のような構造体を定義しておく必要があります。
typeプロパティはちょっと混乱しちゃいますね。

main.rs
#[derive(Serialize, Deserialize, Debug)]
struct Content {
    r#type: String,
    text: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct Message {
    role: String,
    content: Vec<Content>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Payload {
    anthropic_version: String,
    max_tokens: u32,
    messages: Vec<Message>,
}

https://docs.aws.amazon.com/bedrock/latest/userguide/bedrock-runtime_example_bedrock-runtime_Claude3_Text_section.html

さらに、関数を作成していきます。
これは、後ほど、プロンプトを送信する際に使用する Blobという型に変換しつつ構造体を作っていきます。
※わりと雑に unwrap()使っているのはご容赦いただければと思います。。

main.rs
async fn create_blob(prompt: &str) -> Blob {
    let payload = Payload {
        anthropic_version: "bedrock-2023-05-31".to_string(),
        max_tokens: 500,
        messages: vec![Message {
            role: "user".to_string(),
            content: vec![Content {
                r#type: "text".to_string(),
                text: prompt.to_string(),
            }],
        }],
    };

    Blob::new(serde_json::to_vec(&payload).unwrap())
}

プロンプトの送信

以下のようにプロンプトの文字列を指定して、実際に送信していきます。
前述した、InvokeModelFluentBuilderに対して model_idbodycontent_typeを指定します。

main.rs
// プロンプトの作成
let prompt: &str = "なぜ空は青い?";

// Blob 型のペイロードを作成
let blob = create_blob(prompt).await;

// モデル名を指定
// https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/model-ids.html
let model_id = "anthropic.claude-3-haiku-20240307-v1:0";

// プロンプトの送信
let output = builder
    .model_id(model_id)
    .body(blob)
    .content_type("application/json")
    .send()
    .await;

// エラーハンドリング、出力
match output {
    Ok(output) => {
        let body = String::from_utf8_lossy(&output.body.as_ref());
        println!("{}", body.trim());
    }
    Err(err) => {
        eprintln!("Bedrock Error: {:?}", err);
    }
}

出力する

cargo runを実行し、プロンプトを表示させてみようと思います。

$ cargo run

{
"id":"xxxxxxx",
"type":"message",
"role":"assistant",
"content":[
{
"type":"text",
"text":"空が青く見えるのには主に2つの理由があります。\n\n1.
レイリー散乱\n\n
地球の大気には小さな分子が多数存在しています。これらの分子は太陽光線と相互作用し、散乱を起こします。この散乱の過程で、短波長の光(青や紫の光)がより多く散乱されるため、空全体が青く見えるようになります。これがレイリー散乱の原理です。\n\n2.
オゾン層の影響\n\n
地球の大気中にあるオゾン層は、紫外線を吸収する性質を持っています。この効果によって、空の色が青っぽく見えるようになります。オゾン層が無ければ、空は他の色に見えるはずです。\n\n
つまり、大気中の分子による光の散乱と、オゾン層による紫外線吸収の2つの要因が、私たちが見る空の青色を生み出しているのです。これらの物理的な過程によって、私たちの目に見える空の色が決まっているのです。"
}],
"model":"claude-3-haiku-48k-20240307",
"stop_reason":"end_turn",
"stop_sequence":null,
"usage":{"input_tokens":16,"output_tokens":319}
}

「なぜ、空は青いのか?」の問いに対してしっかりと回答が返ってきましたね!!
最後に、全記述文を掲載して、おわりにしたいと思います。

main.rs
use aws_sdk_bedrockruntime::primitives::Blob;
use serde::{Deserialize, Serialize};

#[::tokio::main]
async fn main() {
    // クライアントの初期化
    let config = aws_config::load_from_env().await;
    let client = aws_sdk_bedrockruntime::Client::new(&config);
    let builder = client.invoke_model();

    // プロンプトの作成
    let prompt: &str = "なぜ空は青い?";

    // Blob 型のペイロードを作成
    let blob = create_blob(prompt).await;

    // モデル名を指定
    // https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/model-ids.html
    let model_id = "anthropic.claude-3-haiku-20240307-v1:0";

    // プロンプトの送信
    let output = builder
        .model_id(model_id)
        .body(blob)
        .content_type("application/json")
        .send()
        .await;

    // エラーハンドリング、出力
    match output {
        Ok(output) => {
            let body = String::from_utf8_lossy(&output.body.as_ref());
            println!("{}", body.trim());
        }
        Err(err) => {
            eprintln!("Bedrock Error: {:?}", err);
        }
    }
}

#[derive(Serialize, Deserialize, Debug)]
struct Content {
    r#type: String,
    text: String,
}

#[derive(Serialize, Deserialize, Debug)]
struct Message {
    role: String,
    content: Vec<Content>,
}

#[derive(Serialize, Deserialize, Debug)]
struct Payload {
    anthropic_version: String,
    max_tokens: u32,
    messages: Vec<Message>,
}

// ペイロードの作成
async fn create_blob(prompt: &str) -> Blob {
    let payload = Payload {
        anthropic_version: "bedrock-2023-05-31".to_string(),
        max_tokens: 500,
        messages: vec![Message {
            role: "user".to_string(),
            content: vec![Content {
                r#type: "text".to_string(),
                text: prompt.to_string(),
            }],
        }],
    };

    Blob::new(serde_json::to_vec(&payload).unwrap())
}

おわりに

Amazon Bedrock Claude3 Haiku モデルを AWS SDK for Rust を使ってプロンプトを動化してみました。いかがだったでしょうか。

ぜひ、これから SDK を使って Bedrock(生成AI) の基盤構築をしてみたい方の参考となれば幸いです。

コラボスタイル Developers

Discussion