Skip to content
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rig-bedrock/src/streaming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ impl CompletionModel {
let tool_input = serde_json::from_str(tool_call.input_json.as_str())?;
yield Ok(RawStreamingChoice::ToolCall {
name: tool_call.name,
call_id: None,
id: tool_call.id,
arguments: tool_input
});
Expand Down
3 changes: 2 additions & 1 deletion rig-bedrock/src/types/assistant_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl TryFrom<AwsConverseOutput> for completion::CompletionResponse<AwsConverseOu
.try_into()?;

let choice = match message.0 {
completion::Message::Assistant { content } => Ok(content),
completion::Message::Assistant { content, .. } => Ok(content),
_ => Err(CompletionError::ResponseError(
"Response contained no message or tool call (empty)".to_owned(),
)),
Expand All @@ -49,6 +49,7 @@ impl TryFrom<AwsConverseOutput> for completion::CompletionResponse<AwsConverseOu
return Ok(completion::CompletionResponse {
choice: OneOrMany::one(AssistantContent::ToolCall(ToolCall {
id: tool_use.id,
call_id: None,
function: ToolFunction {
name: tool_use.function.name,
arguments: tool_use.function.arguments,
Expand Down
4 changes: 2 additions & 2 deletions rig-bedrock/src/types/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl TryFrom<RigMessage> for aws_bedrock::Message {
.build()
.map_err(|e| CompletionError::RequestError(Box::new(e)))?
}
Message::Assistant { content } => aws_bedrock::Message::builder()
Message::Assistant { content, .. } => aws_bedrock::Message::builder()
.role(aws_bedrock::ConversationRole::Assistant)
.set_content(Some(
content
Expand Down Expand Up @@ -62,7 +62,7 @@ impl TryFrom<aws_bedrock::Message> for RigMessage {
let content = OneOrMany::many(assistant_content)
.map_err(|e| CompletionError::RequestError(Box::new(e)))?;

Ok(RigMessage(Message::Assistant { content }))
Ok(RigMessage(Message::Assistant { content, id: None }))
}
aws_bedrock::ConversationRole::User => {
let user_content = message
Expand Down
1 change: 1 addition & 0 deletions rig-bedrock/src/types/user_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ impl TryFrom<aws_bedrock::ContentBlock> for RigUserContent {
})?;
Ok(RigUserContent(UserContent::ToolResult(ToolResult {
id: tool_result.tool_use_id,
call_id: None,
content: tool_results,
})))
}
Expand Down
21 changes: 4 additions & 17 deletions rig-core/examples/agent_with_huggingface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ async fn main() -> Result<(), anyhow::Error> {
context().await?;

println!("\n\nAll agents ran successfully");

Ok(())
}

Expand All @@ -42,9 +41,7 @@ fn partial_agent() -> AgentBuilder<providers::huggingface::completion::Completio
client.agent("deepseek-ai/DeepSeek-R1-Distill-Qwen-32B")
}

/// Create an huggingface agent (deepseek R1) with a preamble
/// Based upon the `agent` example
///
/// Create an huggingface agent (deepseek R1) with a preamble, based upon the `agent` example.
/// This example creates a comedian agent with a preamble
async fn basic() -> Result<(), anyhow::Error> {
let comedian_agent = partial_agent()
Expand All @@ -60,9 +57,7 @@ async fn basic() -> Result<(), anyhow::Error> {
Ok(())
}

/// Create an huggingface agent (deepseek R1) with tools
/// Based upon the `tools` example
///
/// Create an huggingface agent (deepseek R1) with tools, based upon the `tools` example.
/// This example creates a calculator agent with two tools: add and subtract
async fn tools() -> Result<(), anyhow::Error> {
// Create agent with a single context prompt and two tools
Expand All @@ -72,39 +67,32 @@ async fn tools() -> Result<(), anyhow::Error> {
.tool(Adder)
.tool(Subtract)
.build();

// Prompt the agent and print the response
println!("Calculate 2 - 5");
println!(
"Calculator Agent: {}",
calculator_agent.prompt("Calculate 2 - 5").await?
);

Ok(())
}

/// Create an huggingface agent (deepseek R1) with loaders
/// Based upon the `loaders` example
///
/// Create an huggingface agent (deepseek R1) with loaders, based upon the `loaders` example
/// This example loads in all the rust examples from the rig-core crate and uses them as
/// context for the agent
async fn loaders() -> Result<(), anyhow::Error> {
let model = client().completion_model("deepseek-ai/DeepSeek-R1-Distill-Qwen-32B");

// Load in all the rust examples
let examples = FileLoader::with_glob("rig-core/examples/*.rs")?
.read_with_path()
.ignore_errors()
.into_iter()
.step_by(2);

// Create an agent with multiple context documents
let agent = examples
.fold(AgentBuilder::new(model), |builder, (path, content)| {
builder.context(format!("Rust Example {path:?}:\n{content}").as_str())
})
.build();

// Prompt the agent and print the response
let response = agent
.prompt("Which rust example is best suited for the operation 1 + 2")
Expand All @@ -117,16 +105,15 @@ async fn loaders() -> Result<(), anyhow::Error> {

async fn context() -> Result<(), anyhow::Error> {
let model = client().completion_model("deepseek-ai/DeepSeek-R1-Distill-Qwen-32B");

// Create an agent with multiple context documents
let agent = AgentBuilder::new(model)
.context("Definition of a *flurbo*: A flurbo is a green alien that lives on cold planets")
.context("Definition of a *glarb-glarb*: A glarb-glarb is an ancient tool used by the ancestors of the inhabitants of planet Jiro to farm the land.")
.context("Definition of a *linglingdong*: A term used by inhabitants of the far side of the moon to describe humans.")
.build();

// Prompt the agent and print the response
let response = agent.prompt("What does \"glarb-glarb\" mean?").await?;

println!("{response}");

Ok(())
Expand Down
13 changes: 10 additions & 3 deletions rig-core/examples/agent_with_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ impl Tool for Adder {
type Args = OperationArgs;
type Output = i32;

// NOTE: Use of `additionalProperties` is required if you're using OpenAI's strict mode
// which is on by default. Otherwise, you don't need to include it.
async fn definition(&self, _prompt: String) -> ToolDefinition {
ToolDefinition {
name: "add".to_string(),
Expand All @@ -41,7 +43,9 @@ impl Tool for Adder {
"type": "number",
"description": "The second number to add"
}
}
},
"required": ["x", "y"],
"additionalProperties": false
}),
}
}
Expand Down Expand Up @@ -77,8 +81,11 @@ impl Tool for Subtract {
"type": "number",
"description": "The number to subtract"
}
}
}
},

"required": ["x", "y"],
"additionalProperties": false
},
}))
.expect("Tool Definition")
}
Expand Down
1 change: 1 addition & 0 deletions rig-core/examples/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,6 @@ async fn main() -> Result<(), anyhow::Error> {
// Prompt the agent and print the response
let response = chain.call("What does \"glarb-glarb\" mean?").await?;
println!("{response}");

Ok(())
}
2 changes: 1 addition & 1 deletion rig-core/examples/debate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use rig::{
use std::env;

struct Debater {
gpt_4: Agent<openai::CompletionModel>,
gpt_4: Agent<openai::responses_api::ResponsesCompletionModel>,
coral: Agent<cohere::CompletionModel>,
}

Expand Down
7 changes: 4 additions & 3 deletions rig-core/examples/multi_turn_streaming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ async fn main() -> anyhow::Result<()> {
.agent(anthropic::CLAUDE_3_5_SONNET)
.preamble(
"You are an assistant here to help the user select which tool is most appropriate to perform arithmetic operations.
Follow these instructions closely.
Follow these instructions closely.
1. Consider the user's request carefully and identify the core elements of the request.
2. Select which tool among those made available to you is appropriate given the context.
3. This is very important: never perform the operation yourself.
2. Select which tool among those made available to you is appropriate given the context.
3. This is very important: never perform the operation yourself.
"
)
.tool(Add)
Expand Down Expand Up @@ -124,6 +124,7 @@ where
// Add (parallel) tool calls to chat history
if !tool_calls.is_empty() {
chat_history.push(Message::Assistant {
id: None,
content: OneOrMany::many(tool_calls).expect("Impossible EmptyListError"),
});
}
Expand Down
3 changes: 3 additions & 0 deletions rig-core/examples/openai_streaming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ use rig::streaming::{StreamingPrompt, stream_to_stdout};

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
// Uncomment tracing for debugging
tracing_subscriber::fmt().init();

// Create streaming agent with a single context prompt
let agent = openai::Client::from_env()
.agent(openai::GPT_4O)
Expand Down
22 changes: 16 additions & 6 deletions rig-core/examples/openai_streaming_with_tools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ impl Tool for Adder {
"description": "The second number to add"
}
},
"required": ["x", "y"]
"required": ["x", "y"],
"additionalProperties": false
}),
}
}
Expand Down Expand Up @@ -87,7 +88,8 @@ impl Tool for Subtract {
"description": "The number to subtract"
}
},
"required": ["x", "y"]
"required": ["x", "y"],
"additionalProperties": false
}
}))
.expect("Tool Definition")
Expand Down Expand Up @@ -118,10 +120,18 @@ async fn tool_call_helper<M: CompletionModel>(
tool_call.function.arguments.to_string(),
)
.await?;
Ok(UserContent::tool_result(
tool_call.id.clone(),
OneOrMany::one(output.into()),
))
if let Some(call_id) = tool_call.call_id.clone() {
Ok(UserContent::tool_result_with_call_id(
tool_call.id.clone(),
call_id,
OneOrMany::one(output.into()),
))
} else {
Ok(UserContent::tool_result(
tool_call.id.clone(),
OneOrMany::one(output.into()),
))
}
} else {
unreachable!("This should never happen as we already filtered for `ToolCall`")
}
Expand Down
17 changes: 13 additions & 4 deletions rig-core/src/agent/prompt_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ impl<M: CompletionModel> PromptRequest<'_, M> {
.partition(|choice| matches!(choice, AssistantContent::ToolCall(_)));

chat_history.push(Message::Assistant {
id: None,
content: resp.choice.clone(),
});

Expand Down Expand Up @@ -149,10 +150,18 @@ impl<M: CompletionModel> PromptRequest<'_, M> {
tool_call.function.arguments.to_string(),
)
.await?;
Ok(UserContent::tool_result(
tool_call.id.clone(),
OneOrMany::one(output.into()),
))
if let Some(call_id) = tool_call.call_id.clone() {
Ok(UserContent::tool_result_with_call_id(
tool_call.id.clone(),
call_id,
OneOrMany::one(output.into()),
))
} else {
Ok(UserContent::tool_result(
tool_call.id.clone(),
OneOrMany::one(output.into()),
))
}
} else {
unreachable!(
"This should never happen as we already filtered for `ToolCall`"
Expand Down
Loading