-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
first agents feature implementation #16
base: main
Are you sure you want to change the base?
first agents feature implementation #16
Conversation
WalkthroughThe changes introduce several new files that facilitate synchronous and asynchronous interactions with the Mistral API, specifically for managing agent communications. These files include examples of basic message exchanges, function calling capabilities for retrieving city temperatures, and enhancements to existing data structures and client methods for processing agent requests and responses. Changes
Recent review detailsConfiguration used: CodeRabbit UI Files selected for processing (8)
Additional comments not posted (9)
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 6
async fn execute(&self, arguments: String) -> Box<dyn Any + Send> { | ||
// Deserialize arguments, perform the logic, and return the result | ||
let GetCityTemperatureArguments { city } = serde_json::from_str(&arguments).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle deserialization errors gracefully.
Using unwrap
can cause a panic if deserialization fails. Consider using ?
to propagate errors or handling them explicitly.
Apply this diff to handle errors:
async fn execute(&self, arguments: String) -> Box<dyn Any + Send> {
- let GetCityTemperatureArguments { city } = serde_json::from_str(&arguments).unwrap();
+ let GetCityTemperatureArguments { city } = match serde_json::from_str(&arguments) {
+ Ok(args) => args,
+ Err(_) => return Box::new("Invalid arguments".to_string()),
+ };
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async fn execute(&self, arguments: String) -> Box<dyn Any + Send> { | |
// Deserialize arguments, perform the logic, and return the result | |
let GetCityTemperatureArguments { city } = serde_json::from_str(&arguments).unwrap(); | |
async fn execute(&self, arguments: String) -> Box<dyn Any + Send> { | |
let GetCityTemperatureArguments { city } = match serde_json::from_str(&arguments) { | |
Ok(args) => args, | |
Err(_) => return Box::new("Invalid arguments".to_string()), | |
}; |
fn main() { | ||
let tools = vec![Tool::new( | ||
"get_city_temperature".to_string(), | ||
"Get the current temperature in a city.".to_string(), | ||
vec![ToolFunctionParameter::new( | ||
"city".to_string(), | ||
"The name of the city.".to_string(), | ||
ToolFunctionParameterType::String, | ||
)], | ||
)]; | ||
|
||
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | ||
let mut client = Client::new(None, None, None, None).unwrap(); | ||
client.register_function( | ||
"get_city_temperature".to_string(), | ||
Box::new(GetCityTemperatureFunction), | ||
); | ||
|
||
let agid = std::env::var("MISTRAL_API_AGENT") | ||
.expect("Please export MISTRAL_API_AGENT with the agent id you want to use"); | ||
let messages = vec![AgentMessage { | ||
role: AgentMessageRole::User, | ||
content: "What's the temperature in Paris?".to_string(), | ||
tool_calls: None, | ||
}]; | ||
let options = AgentParams { | ||
random_seed: Some(42), | ||
tool_choice: Some(ToolChoice::Auto), | ||
tools: Some(tools), | ||
..Default::default() | ||
}; | ||
|
||
client.agent(agid, messages, Some(options)).unwrap(); | ||
let temperature = client | ||
.get_last_function_call_result() | ||
.unwrap() | ||
.downcast::<String>() | ||
.unwrap(); | ||
println!("The temperature in Paris is: {}.", temperature); | ||
// => "The temperature in Paris is: 20°C." | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling and environment variable checks.
The code assumes environment variables are set and does not handle errors from the agent call. Consider adding checks and handling potential errors.
Apply this diff to improve error handling:
let agid = std::env::var("MISTRAL_API_AGENT")
- .expect("Please export MISTRAL_API_AGENT with the agent id you want to use");
+ .unwrap_or_else(|_| panic!("Please export MISTRAL_API_AGENT with the agent id you want to use"));
let result = client.agent(agid, messages, Some(options));
match result {
Ok(_) => {
let temperature = client
.get_last_function_call_result()
.unwrap()
.downcast::<String>()
.unwrap();
println!("The temperature in Paris is: {}.", temperature);
}
Err(e) => eprintln!("Agent call failed: {}", e),
}
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
fn main() { | |
let tools = vec![Tool::new( | |
"get_city_temperature".to_string(), | |
"Get the current temperature in a city.".to_string(), | |
vec![ToolFunctionParameter::new( | |
"city".to_string(), | |
"The name of the city.".to_string(), | |
ToolFunctionParameterType::String, | |
)], | |
)]; | |
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | |
let mut client = Client::new(None, None, None, None).unwrap(); | |
client.register_function( | |
"get_city_temperature".to_string(), | |
Box::new(GetCityTemperatureFunction), | |
); | |
let agid = std::env::var("MISTRAL_API_AGENT") | |
.expect("Please export MISTRAL_API_AGENT with the agent id you want to use"); | |
let messages = vec![AgentMessage { | |
role: AgentMessageRole::User, | |
content: "What's the temperature in Paris?".to_string(), | |
tool_calls: None, | |
}]; | |
let options = AgentParams { | |
random_seed: Some(42), | |
tool_choice: Some(ToolChoice::Auto), | |
tools: Some(tools), | |
..Default::default() | |
}; | |
client.agent(agid, messages, Some(options)).unwrap(); | |
let temperature = client | |
.get_last_function_call_result() | |
.unwrap() | |
.downcast::<String>() | |
.unwrap(); | |
println!("The temperature in Paris is: {}.", temperature); | |
// => "The temperature in Paris is: 20°C." | |
} | |
fn main() { | |
let tools = vec![Tool::new( | |
"get_city_temperature".to_string(), | |
"Get the current temperature in a city.".to_string(), | |
vec![ToolFunctionParameter::new( | |
"city".to_string(), | |
"The name of the city.".to_string(), | |
ToolFunctionParameterType::String, | |
)], | |
)]; | |
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | |
let mut client = Client::new(None, None, None, None).unwrap(); | |
client.register_function( | |
"get_city_temperature".to_string(), | |
Box::new(GetCityTemperatureFunction), | |
); | |
let agid = std::env::var("MISTRAL_API_AGENT") | |
.unwrap_or_else(|_| panic!("Please export MISTRAL_API_AGENT with the agent id you want to use")); | |
let messages = vec![AgentMessage { | |
role: AgentMessageRole::User, | |
content: "What's the temperature in Paris?".to_string(), | |
tool_calls: None, | |
}]; | |
let options = AgentParams { | |
random_seed: Some(42), | |
tool_choice: Some(ToolChoice::Auto), | |
tools: Some(tools), | |
..Default::default() | |
}; | |
let result = client.agent(agid, messages, Some(options)); | |
match result { | |
Ok(_) => { | |
let temperature = client | |
.get_last_function_call_result() | |
.unwrap() | |
.downcast::<String>() | |
.unwrap(); | |
println!("The temperature in Paris is: {}.", temperature); | |
} | |
Err(e) => eprintln!("Agent call failed: {}", e), | |
} | |
// => "The temperature in Paris is: 20°C." | |
} |
async fn execute(&self, arguments: String) -> Box<dyn Any + Send> { | ||
// Deserialize arguments, perform the logic, and return the result | ||
let GetCityTemperatureArguments { city } = serde_json::from_str(&arguments).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle deserialization errors gracefully.
Using unwrap
can cause a panic if deserialization fails. Consider using ?
to propagate errors or handling them explicitly.
Apply this diff to handle errors:
async fn execute(&self, arguments: String) -> Box<dyn Any + Send> {
- let GetCityTemperatureArguments { city } = serde_json::from_str(&arguments).unwrap();
+ let GetCityTemperatureArguments { city } = match serde_json::from_str(&arguments) {
+ Ok(args) => args,
+ Err(_) => return Box::new("Invalid arguments".to_string()),
+ };
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
async fn execute(&self, arguments: String) -> Box<dyn Any + Send> { | |
// Deserialize arguments, perform the logic, and return the result | |
let GetCityTemperatureArguments { city } = serde_json::from_str(&arguments).unwrap(); | |
async fn execute(&self, arguments: String) -> Box<dyn Any + Send> { | |
// Deserialize arguments, perform the logic, and return the result | |
let GetCityTemperatureArguments { city } = match serde_json::from_str(&arguments) { | |
Ok(args) => args, | |
Err(_) => return Box::new("Invalid arguments".to_string()), | |
}; |
#[tokio::main] | ||
async fn main() { | ||
let tools = vec![Tool::new( | ||
"get_city_temperature".to_string(), | ||
"Get the current temperature in a city.".to_string(), | ||
vec![ToolFunctionParameter::new( | ||
"city".to_string(), | ||
"The name of the city.".to_string(), | ||
ToolFunctionParameterType::String, | ||
)], | ||
)]; | ||
|
||
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | ||
let mut client = Client::new(None, None, None, None).unwrap(); | ||
client.register_function( | ||
"get_city_temperature".to_string(), | ||
Box::new(GetCityTemperatureFunction), | ||
); | ||
|
||
let agid = std::env::var("MISTRAL_API_AGENT") | ||
.expect("Please export MISTRAL_API_AGENT with the agent id you want to use"); | ||
let messages = vec![AgentMessage { | ||
role: AgentMessageRole::User, | ||
content: "What's the temperature in Paris?".to_string(), | ||
tool_calls: None, | ||
}]; | ||
let options = AgentParams { | ||
random_seed: Some(42), | ||
tool_choice: Some(ToolChoice::Auto), | ||
tools: Some(tools), | ||
..Default::default() | ||
}; | ||
|
||
client | ||
.agent_async(agid, messages, Some(options)) | ||
.await | ||
.unwrap(); | ||
let temperature = client | ||
.get_last_function_call_result() | ||
.unwrap() | ||
.downcast::<String>() | ||
.unwrap(); | ||
println!("The temperature in Paris is: {}.", temperature); | ||
// => "The temperature in Paris is: 20°C." | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add error handling and environment variable checks.
The code assumes environment variables are set and does not handle errors from the agent call. Consider adding checks and handling potential errors.
Apply this diff to improve error handling:
let agid = std::env::var("MISTRAL_API_AGENT")
- .expect("Please export MISTRAL_API_AGENT with the agent id you want to use");
+ .unwrap_or_else(|_| panic!("Please export MISTRAL_API_AGENT with the agent id you want to use"));
let result = client.agent_async(agid, messages, Some(options)).await;
match result {
Ok(_) => {
let temperature = client
.get_last_function_call_result()
.unwrap()
.downcast::<String>()
.unwrap();
println!("The temperature in Paris is: {}.", temperature);
}
Err(e) => eprintln!("Agent call failed: {}", e),
}
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
#[tokio::main] | |
async fn main() { | |
let tools = vec![Tool::new( | |
"get_city_temperature".to_string(), | |
"Get the current temperature in a city.".to_string(), | |
vec![ToolFunctionParameter::new( | |
"city".to_string(), | |
"The name of the city.".to_string(), | |
ToolFunctionParameterType::String, | |
)], | |
)]; | |
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | |
let mut client = Client::new(None, None, None, None).unwrap(); | |
client.register_function( | |
"get_city_temperature".to_string(), | |
Box::new(GetCityTemperatureFunction), | |
); | |
let agid = std::env::var("MISTRAL_API_AGENT") | |
.expect("Please export MISTRAL_API_AGENT with the agent id you want to use"); | |
let messages = vec![AgentMessage { | |
role: AgentMessageRole::User, | |
content: "What's the temperature in Paris?".to_string(), | |
tool_calls: None, | |
}]; | |
let options = AgentParams { | |
random_seed: Some(42), | |
tool_choice: Some(ToolChoice::Auto), | |
tools: Some(tools), | |
..Default::default() | |
}; | |
client | |
.agent_async(agid, messages, Some(options)) | |
.await | |
.unwrap(); | |
let temperature = client | |
.get_last_function_call_result() | |
.unwrap() | |
.downcast::<String>() | |
.unwrap(); | |
println!("The temperature in Paris is: {}.", temperature); | |
// => "The temperature in Paris is: 20°C." | |
} | |
#[tokio::main] | |
async fn main() { | |
let tools = vec![Tool::new( | |
"get_city_temperature".to_string(), | |
"Get the current temperature in a city.".to_string(), | |
vec![ToolFunctionParameter::new( | |
"city".to_string(), | |
"The name of the city.".to_string(), | |
ToolFunctionParameterType::String, | |
)], | |
)]; | |
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | |
let mut client = Client::new(None, None, None, None).unwrap(); | |
client.register_function( | |
"get_city_temperature".to_string(), | |
Box::new(GetCityTemperatureFunction), | |
); | |
let agid = std::env::var("MISTRAL_API_AGENT") | |
.unwrap_or_else(|_| panic!("Please export MISTRAL_API_AGENT with the agent id you want to use")); | |
let messages = vec![AgentMessage { | |
role: AgentMessageRole::User, | |
content: "What's the temperature in Paris?".to_string(), | |
tool_calls: None, | |
}]; | |
let options = AgentParams { | |
random_seed: Some(42), | |
tool_choice: Some(ToolChoice::Auto), | |
tools: Some(tools), | |
..Default::default() | |
}; | |
let result = client.agent_async(agid, messages, Some(options)).await; | |
match result { | |
Ok(_) => { | |
let temperature = client | |
.get_last_function_call_result() | |
.unwrap() | |
.downcast::<String>() | |
.unwrap(); | |
println!("The temperature in Paris is: {}.", temperature); | |
} | |
Err(e) => eprintln!("Agent call failed: {}", e), | |
} | |
// => "The temperature in Paris is: 20°C." | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
#[tokio::main] | ||
async fn main() { | ||
let tools = vec![Tool::new( | ||
"get_city_temperature".to_string(), | ||
"Get the current temperature in a city.".to_string(), | ||
vec![ToolFunctionParameter::new( | ||
"city".to_string(), | ||
"The name of the city.".to_string(), | ||
ToolFunctionParameterType::String, | ||
)], | ||
)]; | ||
|
||
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | ||
let mut client = Client::new(None, None, None, None).unwrap(); | ||
client.register_function( | ||
"get_city_temperature".to_string(), | ||
Box::new(GetCityTemperatureFunction), | ||
); | ||
|
||
let agid = std::env::var("MISTRAL_API_AGENT") | ||
.expect("Please export MISTRAL_API_AGENT with the agent id you want to use"); | ||
let messages = vec![AgentMessage::new_user_message( | ||
"What's the temperature in Paris?", | ||
)]; | ||
let options = AgentParams { | ||
random_seed: Some(42), | ||
tool_choice: Some(ToolChoice::Auto), | ||
tools: Some(tools), | ||
..Default::default() | ||
}; | ||
|
||
client | ||
.agent_async(agid, messages, Some(options)) | ||
.await | ||
.unwrap(); | ||
let temperature = client | ||
.get_last_function_call_result() | ||
.unwrap() | ||
.downcast::<String>() | ||
.unwrap(); | ||
println!("The temperature in Paris is: {}.", temperature); | ||
// => "The temperature in Paris is: 20°C." | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Main function setup and execution.
The main function demonstrates the registration and usage of the new agent functionality. However, it uses unwrap
extensively, which is risky for production code as it may cause the program to panic if there are any errors.
Consider replacing unwrap
with proper error handling to ensure the program can gracefully handle potential failures.
- .unwrap();
+ .expect("Error message describing the potential failure");
Committable suggestion was skipped due to low confidence.
"{:?}: {}", | ||
result.choices[0].message.role, result.choices[0].message.content | ||
); | ||
// => "Assistant: Tower. The Eiffel Tower is a famous landmark in Paris, France." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add a comment explaining the output format.
While the output is demonstrated in a comment, it could be beneficial to explain why this specific format is used or how it relates to the functionality being demonstrated.
Consider adding a detailed comment about the output format to help users understand the context or the data structure being printed.
let agid = std::env::var("MISTRAL_API_AGENT") | ||
.expect("Please export MISTRAL_API_AGENT with the agent id you want to use"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve error messaging for environment variable retrieval.
Using .expect
provides a clear error message, which is good practice. However, consider enhancing the user experience by suggesting how to set the environment variable if it's not found.
- .expect("Please export MISTRAL_API_AGENT with the agent id you want to use");
+ .expect("Environment variable 'MISTRAL_API_AGENT' not found. Please set it with the agent id you want to use.");
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
let agid = std::env::var("MISTRAL_API_AGENT") | |
.expect("Please export MISTRAL_API_AGENT with the agent id you want to use"); | |
let agid = std::env::var("MISTRAL_API_AGENT") | |
.expect("Environment variable 'MISTRAL_API_AGENT' not found. Please set it with the agent id you want to use."); |
)], | ||
)]; | ||
|
||
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify environment variable usage in the synchronous example.
The example assumes the MISTRAL_API_KEY
environment variable is set but does not demonstrate its usage. Consider adding a comment or code to clarify.
- // This example suppose you have set the `MISTRAL_API_KEY` environment variable.
+ // Ensure the 'MISTRAL_API_KEY' environment variable is set before running this example.
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | |
// Ensure the 'MISTRAL_API_KEY' environment variable is set before running this example. |
client.agent(agid, messages, Some(options)).unwrap(); | ||
let temperature = client | ||
.get_last_function_call_result() | ||
.unwrap() | ||
.downcast::<String>() | ||
.unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improve error handling for function call results.
Using unwrap
on function call results can lead to panics if the downcast fails or if the function call did not return a result. It's important to handle these cases to prevent runtime errors.
Consider adding error handling to manage these scenarios more gracefully.
- .unwrap()
- .downcast::<String>()
- .unwrap();
+ .ok_or_else(|| "Function call did not return a result".to_string())?
+ .downcast::<String>()
+ .map_err(|_| "Failed to downcast to String".to_string())?;
Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
client.agent(agid, messages, Some(options)).unwrap(); | |
let temperature = client | |
.get_last_function_call_result() | |
.unwrap() | |
.downcast::<String>() | |
.unwrap(); | |
client.agent(agid, messages, Some(options)).unwrap(); | |
let temperature = client | |
.get_last_function_call_result() | |
.ok_or_else(|| "Function call did not return a result".to_string())? | |
.downcast::<String>() | |
.map_err(|_| "Failed to downcast to String".to_string())?; |
- Add async and blocking agent completions methods into `Client` - Implement new types into a new `agent` module. - Add a trait to get choices from responses beeing generic over the response type - impl this trait for `ChatResponse` and `AgentResponse` - Add a blocking example for agent completion.
Add examples async and with function calling.
Now you can set a prefix to control the assistant output start. It is the oportunity to improve the `AgentMessage` type. It's not a struct anymore. It became an enum having a variant per possible roles.
424b005
to
759be91
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
fn main() { | ||
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | ||
let client = Client::new(None, None, None, None).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify environment variable usage in the example.
The example assumes the MISTRAL_API_KEY
environment variable is set, but it is not explicitly used in the code. Consider adding a comment or code to demonstrate its usage.
let result = client.agent(agid, messages, Some(options)).unwrap(); | ||
println!("Assistant: {}", result.choices[0].message.content); | ||
// => "Assistant: Tower. The Eiffel Tower is a famous landmark in Paris, France." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider adding error handling for production code.
While unwrap
is acceptable in examples, for production code, consider handling errors more gracefully to avoid panics.
#[tokio::main] | ||
async fn main() { | ||
// This example suppose you have set the `MISTRAL_API_KEY` environment variable. | ||
let client = Client::new(None, None, None, None).unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify environment variable usage in the async example.
Similar to the synchronous example, the async example assumes the MISTRAL_API_KEY
environment variable is set but does not demonstrate its usage. Consider adding a comment or code to clarify.
let result = client | ||
.agent_async(agid, messages, Some(options)) | ||
.await | ||
.unwrap(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure proper error handling for asynchronous operations.
Using .unwrap()
in asynchronous operations can lead to panics if the future resolves to an error. It's crucial to handle these errors gracefully to avoid runtime panics.
Consider using .await?
to propagate errors or handle them explicitly with a match statement.
/// The parameters for the chat request. | ||
/// | ||
/// See the [API documentation](https://docs.mistral.ai/api/#operation/createChatCompletion) for more information. | ||
#[derive(Clone, Debug, Serialize)] | ||
pub struct AgentParams { | ||
/// The maximum number of tokens to generate in the completion. | ||
/// | ||
/// Defaults to `None`. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub max_tokens: Option<u32>, | ||
/// The minimum number of tokens to generate in the completion. | ||
/// | ||
/// Defaults to `None`. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub min_tokens: Option<u32>, | ||
/// Stop if one of these tokens is detected. | ||
/// | ||
///Defaults to `None` | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub stop: Option<Vec<String>>, | ||
/// The seed to use for random sampling. If set, different calls will generate deterministic results. | ||
/// | ||
/// Defaults to `None`. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub random_seed: Option<u32>, | ||
/// The format that the model must output. | ||
/// | ||
/// Defaults to `None`. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub response_format: Option<ResponseFormat>, | ||
/// A list of available tools for the model. | ||
/// | ||
/// Defaults to `None`. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub tools: Option<Vec<tool::Tool>>, | ||
/// Specifies if/how functions are called. | ||
/// | ||
/// Defaults to `None`. | ||
#[serde(skip_serializing_if = "Option::is_none")] | ||
pub tool_choice: Option<tool::ToolChoice>, | ||
} | ||
impl Default for AgentParams { | ||
fn default() -> Self { | ||
Self { | ||
max_tokens: None, | ||
min_tokens: None, | ||
stop: None, | ||
random_seed: None, | ||
response_format: None, | ||
tools: None, | ||
tool_choice: None, | ||
} | ||
} | ||
} | ||
impl AgentParams { | ||
pub fn json_default() -> Self { | ||
Self { | ||
response_format: Some(ResponseFormat::json_object()), | ||
..Default::default() | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comprehensive and flexible AgentParams
struct.
The AgentParams
struct is well-designed, offering comprehensive options to customize agent interactions. The use of optional fields and defaults simplifies the API for users, making it more accessible.
Consider adding more detailed documentation for each field to further enhance understanding and usability.
pub fn agent( | ||
&self, | ||
id: impl AsRef<str>, | ||
messages: Vec<agent::AgentMessage>, | ||
options: Option<agent::AgentParams>, | ||
) -> Result<agent::AgentResponse, error::ApiError> { | ||
let request = agent::AgentRequest::new(id.as_ref(), messages, false, options); | ||
|
||
let response = self.post_sync("/agents/completions", &request)?; | ||
let result = response.json::<agent::AgentResponse>(); | ||
match result { | ||
Ok(data) => { | ||
utils::debug_pretty_json_from_struct("Response Data", &data); | ||
|
||
self.call_function_if_any(data.clone()); | ||
|
||
Ok(data) | ||
} | ||
Err(error) => Err(self.to_api_error(error)), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method agent
correctly implements synchronous agent interactions.
The method is well-implemented with appropriate error handling and response processing. Consider adding more detailed logging for better traceability of requests and responses.
pub async fn agent_async( | ||
&self, | ||
id: impl AsRef<str>, | ||
messages: Vec<agent::AgentMessage>, | ||
options: Option<agent::AgentParams>, | ||
) -> Result<agent::AgentResponse, error::ApiError> { | ||
let request = agent::AgentRequest::new(id.as_ref(), messages, false, options); | ||
|
||
let response = self.post_async("/agents/completions", &request).await?; | ||
let result = response.json::<agent::AgentResponse>().await; | ||
match result { | ||
Ok(data) => { | ||
utils::debug_pretty_json_from_struct("Response Data", &data); | ||
|
||
self.call_function_if_any_async(data.clone()).await; | ||
|
||
Ok(data) | ||
} | ||
Err(error) => Err(self.to_api_error(error)), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Method agent_async
correctly implements asynchronous agent interactions.
The asynchronous implementation is consistent with its synchronous counterpart, ensuring non-blocking operations and proper error handling.
Consider adding automated tests to ensure consistency between the agent
and agent_async
methods.
fn call_function_if_any(&self, response: impl chat::HasChoices) -> () { | ||
let next_result = match response.choices().get(0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Modification to call_function_if_any
enhances flexibility.
The method now accepts any type implementing HasChoices
, increasing its usability across different response types.
Consider adding type constraints to ensure that the generic type meets certain conditions, enhancing type safety.
I think coderabbitai is kinda dumb. It's okay to call |
Huh. When I tried to get
@francois-caddet Any idea why this is happening? |
Description
Added the agent completion methods.
Checklist
agent
module.Client::agent
Client::agent_async
Client::agent_stream
(may be done in a later PR)