Amazon Bedrock Claude3 Haiku モデルを AWS SDK for Rust を使ってプロンプトを動かす
はじめに
巷で話題の Amazon Bedrock。
3月には、Claude3 の Haiku モデルが登場し、4月にも Opus モデルが登場しています。
さらに、これらのモデルは GPT 系のモデルよりも優れているとされていて、私も興味関心があります。
今回は、Claude3 の Haiku モデルを AWS SDK for Rust を使って簡単に叩いてみようと思います。
環境準備
Rust プロジェクトの作成
$ cargo new bedrock-sample
$ cd bedrock-sample
Cargo.toml
に以下のパッケージを追加します。
aws-sdk-bedrockruntime
というクレートを使って、動かしていきます。
[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"] }
念の為、cargo run
を実行し、Hello, World! が出力されることを確認しておきましょう。
実装
クライアントの作成
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への認証については、こちらの記事が参考になるかと思います。
構造体の作成
Claude3 のテキストプロンプトを送信するために、以下のような構造体を定義しておく必要があります。
type
プロパティはちょっと混乱しちゃいますね。
#[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>,
}
さらに、関数を作成していきます。
これは、後ほど、プロンプトを送信する際に使用する Blob
という型に変換しつつ構造体を作っていきます。
※わりと雑に unwrap()
使っているのはご容赦いただければと思います。。
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_id
と body
、content_type
を指定します。
// プロンプトの作成
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}
}
「なぜ、空は青いのか?」の問いに対してしっかりと回答が返ってきましたね!!
最後に、全記述文を掲載して、おわりにしたいと思います。
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) の基盤構築をしてみたい方の参考となれば幸いです。
Discussion