langchain_rust/tools/tool.rs
1use std::error::Error;
2use std::string::String;
3
4use async_trait::async_trait;
5use serde_json::{json, Value};
6
7#[async_trait]
8pub trait Tool: Send + Sync {
9 /// Returns the name of the tool.
10 fn name(&self) -> String;
11
12 /// Provides a description of what the tool does and when to use it.
13 fn description(&self) -> String;
14 /// This are the parametters for OpenAi-like function call.
15 /// You should return a jsnon like this one
16 /// ```json
17 /// {
18 /// "type": "object",
19 /// "properties": {
20 /// "command": {
21 /// "type": "string",
22 /// "description": "The raw command you want executed"
23 /// }
24 /// },
25 /// "required": ["command"]
26 /// }
27 ///
28 /// If there s no implementation the defaul will be the self.description()
29 ///```
30 fn parameters(&self) -> Value {
31 json!({
32 "type": "object",
33 "properties": {
34 "input": {
35 "type": "string",
36 "description":self.description()
37 }
38 },
39 "required": ["input"]
40 })
41 }
42
43 /// Processes an input string and executes the tool's functionality, returning a `Result`.
44 ///
45 /// This function utilizes `parse_input` to parse the input and then calls `run`.
46 /// Its used by the Agent
47 async fn call(&self, input: &str) -> Result<String, Box<dyn Error>> {
48 let input = self.parse_input(input).await;
49 self.run(input).await
50 }
51
52 /// Executes the core functionality of the tool.
53 ///
54 /// Example implementation:
55 /// ```rust,ignore
56 /// async fn run(&self, input: Value) -> Result<String, Box<dyn Error>> {
57 /// let input_str = input.as_str().ok_or("Input should be a string")?;
58 /// self.simple_search(input_str).await
59 /// }
60 /// ```
61 async fn run(&self, input: Value) -> Result<String, Box<dyn Error>>;
62
63 /// Parses the input string, which could be a JSON value or a raw string, depending on the LLM model.
64 ///
65 /// Implement this function to extract the parameters needed for your tool. If a simple
66 /// string is sufficient, the default implementation can be used.
67 async fn parse_input(&self, input: &str) -> Value {
68 log::info!("Using default implementation: {}", input);
69 match serde_json::from_str::<Value>(input) {
70 Ok(input) => {
71 if input["input"].is_string() {
72 Value::String(input["input"].as_str().unwrap().to_string())
73 } else {
74 Value::String(input.to_string())
75 }
76 }
77 Err(_) => Value::String(input.to_string()),
78 }
79 }
80}