🙆

RustでBedrock Modelをたたいてみた。

2024/12/14に公開

Amazon Bedrock Advent Calendar 2024 の14日目の記事になります。

なぜ、Rust。Rustのメリットを

https://aws.amazon.com/blogs/devops/why-aws-is-the-best-place-to-run-rust/

実行するための前準備

https://www.rust-lang.org/tools/install

Cargo.toml

[package]
name = "bedrock-sample"
version = "0.1.0"
edition = "2021"

[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"]}
axum = "0.6.0"

https://solid.kmckk.com/SOLID/doc/latest/solid_rust/ecosystem/cargo.html

Cargo パッケージマネージャー、cargo updateで依存モジュールも含めて更新してくれて便利でした。

HTTP Server

3,000ポートで待ち受けする設定

    let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
    println!("Listening on http://{}", addr);

    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .await
        .unwrap();

Routing

async fn app() -> Router   {

    Router::new()
        .route("/", get(handler))
        .route("/users", post(get_users))

}

/usersパスでPOSTリクエストされた場合、get_users呼び出されます

BedrockModel リクエストカプセル化

#[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>
}

Contentにcache_controlを付与すれば、Prompt Cachingにもいけると思われます。(申請とおってないので確認できず

Bedrock Request Message

Fundation Modelにリクエストするメッセージを生成します。

 async fn create_blob(prompt: &str) -> Blob {
 // async fn create_blob(prompt: String) -> 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())

}

invoke Model

POSTによる、下記jsonをdataとしてリクエストする実装になります。

{
  "user_prompt": "Amazon BedrockとAzureOpenAIのメリットデメリットは?"
}
    let user_prompt = match body_json.0.get("user_prompt"){
      Some(user_prompt) => user_prompt.as_str().expect("user_prompt should be a string"),
      None => panic!("error")
    };
    println!("{}", user_prompt);
    let config = aws_config::load_from_env().await;
    let client = aws_sdk_bedrockruntime::Client::new(&config);
    let builder = client.invoke_model();
    let prompt: &str = user_prompt;
    let blob = create_blob(prompt).await;
    let output = builder
        .model_id("anthropic.claude-3-5-sonnet-20240620-v1:0")
        .body(blob)
        .content_type("application/json")
        .send()
        .await;

load_from_envは環境変数のAWS_REGIONをみるようです。
https://docs.aws.amazon.com/ja_jp/sdk-for-rust/latest/dg/region.html

Response

Bedrock Modelからのレスポンスが入っている outputからJSONとしてクライアントに返す。

     match output {
        Ok(output) => {
            let  body=String::from_utf8_lossy(&output.body.as_ref());
            println!("Success: {:?}", body);
            return (
                StatusCode::OK,
                Json(Body {
                    Body: body.to_string()
                })
            )
        }

        Err(e) => {
            println!("Error: {:?}", e);
            return (
                StatusCode::OK,
                Json(Body {
                    Body: "error".to_string()
                })
            )
        }

動作確認

curl -X POST http://127.0.0.1:3000/users -H "Content-Type: application/json" -d '{"user_prompt": "AWSとAzureの活用ユースケースを教えて"}'
{"Body":"{\"id\":\"msg_bdrk_012zNnvpSBqbbRR2PFoJAHGb\",\"type\":\"message\",\"role\":\"assistant\",\"model\":\"claude-3-5-sonnet-20240620\",\"content\":[{\"type\":\"text\",\"text\":\"AWSとAzureは、どちらも幅広いクラウドサービスを提供していますが、それぞれに特徴があり、様々なユースケースで活用されています。以下に、AWSとAzureの一般的な活用ユースケースをいくつか紹介します。\\n\\nAWS (Amazon Web Services) の活用ユースケース:\\n\\n1. ウェブホスティングとコンテンツ配信:\\n   - Amazon S3とCloudFrontを使用して、静的ウェブサイトをホストし、コンテンツを高速配信。\\n\\n2. ビッグデータ分析:\\n   - Amazon EMR、Redshift、Athenaを使用して大規模なデータ分析を実行。\\n\\n3. サーバーレスアプリケーション:\\n   - AWS Lambdaを使用して、イベント駆動型のサーバーレスアプリケーションを構築。\\n\\n4. 機械学習と人工知能:\\n   - Amazon SageMakerを使用して、機械学習モデルの開発、トレーニング、デプロイを行う。\\n\\n5. IoTソリューション:\\n   - AWS IoT Coreを使用して、IoTデバイスの接続と管理を行う。\\n\\nAzure (Microsoft Azure) の活用ユースケース:\\n\\n1. エンタープライズアプリケーション:\\n   - Azure Active DirectoryとAzure ADFSを使用して、企業のID管理とシングルサインオンを実現。\\n\\n2. ハイブリッドクラウド:\\n   - Azure Stack HCIを使用して、オンプレミスとクラウドのハイブリッド環境を構築。\\n\\n3. DevOpsとCI/CD:\\n   - Azure DevOpsを使用して、ソフ\"}],\"stop_reason\":\"max_tokens\",\"stop_sequence\":null,\"usage\":{\"input_tokens\":25,\"output_tokens\":499}}"}⏎

索引

aws_sdk_bedrockruntime

https://docs.rs/aws-sdk-bedrockruntime/latest/aws_sdk_bedrockruntime/index.html

RustのTokio製WEBフレームワークaxum version 0.5.6 を使ってみた

https://zenn.dev/asamin/articles/7891f65a719ad3

Discussion