Skip to content

Commit 92c91d2

Browse files
authored
feat: AWS Bedrock provider (#318)
* feat: aws-bedrock-provider Added new model provider * feat: AWS Bedrock provider - changes as requested in PR comments * feat: image generation
1 parent 88edab9 commit 92c91d2

33 files changed

+2536
-10
lines changed

Cargo.lock

+87-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ members = [
99
"rig-qdrant",
1010
"rig-core/rig-core-derive",
1111
"rig-sqlite",
12-
"rig-eternalai", "rig-fastembed",
1312
"rig-surrealdb",
13+
"rig-eternalai",
14+
"rig-fastembed",
15+
"rig-bedrock",
1416
]

rig-bedrock/Cargo.toml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
[package]
2+
name = "rig-bedrock"
3+
version = "0.1.0"
4+
edition = "2021"
5+
license = "MIT"
6+
readme = "README.md"
7+
description = "AWS Bedrock model provider for Rig integration."
8+
9+
[dependencies]
10+
rig-core = { version = "0.11.0", features = ["image"] }
11+
rig-derive = { path = "../rig-core/rig-core-derive", version = "0.1.0" }
12+
serde = { version = "1.0.193", features = ["derive"] }
13+
serde_json = "1.0.108"
14+
schemars = "0.8.16"
15+
tracing = "0.1.40"
16+
aws-config = { version = "1.6.0", features = ["behavior-version-latest"] }
17+
aws-sdk-bedrockruntime = "1.77.0"
18+
aws-smithy-types = "1.3.0"
19+
base64 = "0.22.1"
20+
async-stream = "0.3.6"
21+
22+
[dev-dependencies]
23+
anyhow = "1.0.75"
24+
tokio = { version = "1.34.0", features = ["full"] }
25+
tracing-subscriber = "0.3.18"
26+
reqwest = { version = "0.12.12", features = ["json", "stream"] }

rig-bedrock/README.md

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## Rig-Bedrock
2+
This companion crate integrates AWS Bedrock as model provider with Rig.
3+
4+
## Usage
5+
6+
Add the companion crate to your `Cargo.toml`, along with the rig-core crate:
7+
8+
```toml
9+
[dependencies]
10+
rig-bedrock = "0.1.0"
11+
rig-core = "0.9.1"
12+
```
13+
14+
You can also run `cargo add rig-bedrock rig-core` to add the most recent versions of the dependencies to your project.
15+
16+
See the [`/examples`](./examples) folder for usage examples.
17+
18+
Make sure to have AWS credentials env vars loaded before starting client such as:
19+
```shell
20+
export AWS_DEFAULT_REGION=us-east-1
21+
export AWS_SECRET_ACCESS_KEY=.......
22+
export AWS_ACCESS_KEY_ID=......
23+
```
+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
use rig::{agent::AgentBuilder, completion::Prompt, loaders::FileLoader};
2+
use rig_bedrock::{
3+
client::{Client, ClientBuilder},
4+
completion::AMAZON_NOVA_LITE,
5+
};
6+
use tracing::info;
7+
8+
mod common;
9+
10+
/// Runs 4 agents based on AWS Bedrock (derived from the agent_with_grok example)
11+
#[tokio::main]
12+
async fn main() -> Result<(), anyhow::Error> {
13+
tracing_subscriber::fmt()
14+
.with_max_level(tracing::Level::INFO)
15+
.with_target(false)
16+
.init();
17+
18+
info!("Running basic agent");
19+
basic().await?;
20+
21+
info!("\nRunning agent with tools");
22+
tools().await?;
23+
24+
info!("\nRunning agent with loaders");
25+
loaders().await?;
26+
27+
info!("\nRunning agent with context");
28+
context().await?;
29+
30+
info!("\n\nAll agents ran successfully");
31+
Ok(())
32+
}
33+
34+
async fn client() -> Client {
35+
ClientBuilder::new().build().await
36+
}
37+
38+
async fn partial_agent() -> AgentBuilder<rig_bedrock::completion::CompletionModel> {
39+
let client = client().await;
40+
client.agent(AMAZON_NOVA_LITE)
41+
}
42+
43+
/// Create an AWS Bedrock agent with a system prompt
44+
async fn basic() -> Result<(), anyhow::Error> {
45+
let agent = partial_agent()
46+
.await
47+
.preamble("Answer with json format only")
48+
.build();
49+
50+
let response = agent.prompt("Describe solar system").await?;
51+
info!("{}", response);
52+
53+
Ok(())
54+
}
55+
56+
/// Create an AWS Bedrock with tools
57+
async fn tools() -> Result<(), anyhow::Error> {
58+
let calculator_agent = partial_agent()
59+
.await
60+
.preamble("You must only do math by using a tool.")
61+
.max_tokens(1024)
62+
.tool(common::Adder)
63+
.build();
64+
65+
info!(
66+
"Calculator Agent: add 400 and 20\nResult: {}",
67+
calculator_agent.prompt("add 400 and 20").await?
68+
);
69+
70+
Ok(())
71+
}
72+
73+
async fn context() -> Result<(), anyhow::Error> {
74+
let model = client().await.completion_model(AMAZON_NOVA_LITE);
75+
76+
// Create an agent with multiple context documents
77+
let agent = AgentBuilder::new(model)
78+
.preamble("Answer the question")
79+
.context("Definition of a *flurbo*: A flurbo is a green alien that lives on cold planets")
80+
.context("Definition of a *glarb-glarb*: A glarb-glarb is a ancient tool used by the ancestors of the inhabitants of planet Jiro to farm the land.")
81+
.context("Definition of a *linglingdong*: A term used by inhabitants of the far side of the moon to describe humans.")
82+
.build();
83+
84+
// Prompt the agent and print the response
85+
let response = agent.prompt("What does \"glarb-glarb\" mean?").await?;
86+
87+
info!("What does \"glarb-glarb\" mean?\n{}", response);
88+
89+
Ok(())
90+
}
91+
92+
/// Based upon the `loaders` example
93+
///
94+
/// This example loads in all the rust examples from the rig-core crate and uses them as\\
95+
/// context for the agent
96+
async fn loaders() -> Result<(), anyhow::Error> {
97+
let model = client().await.completion_model(AMAZON_NOVA_LITE);
98+
99+
// Load in all the rust examples
100+
let examples = FileLoader::with_glob("rig-core/examples/*.rs")?
101+
.read_with_path()
102+
.ignore_errors()
103+
.into_iter();
104+
105+
// Create an agent with multiple context documents
106+
let agent = examples
107+
.fold(AgentBuilder::new(model), |builder, (path, content)| {
108+
builder.context(format!("Rust Example {:?}:\n{}", path, content).as_str())
109+
})
110+
.preamble("Answer the question")
111+
.build();
112+
113+
// Prompt the agent and print the response
114+
let response = agent
115+
.prompt("Which rust example is best suited for the operation 1 + 2")
116+
.await?;
117+
118+
info!("{}", response);
119+
120+
Ok(())
121+
}

0 commit comments

Comments
 (0)