llm_chain_tools/tools/
python.rs

1use crate::description::{Describe, Format, ToolDescription};
2use crate::tool::{gen_invoke_function, Tool};
3use serde::{Deserialize, Serialize};
4use std::process::Command;
5
6pub struct PythonTool {}
7
8impl PythonTool {
9    pub fn new() -> Self {
10        PythonTool {}
11    }
12}
13
14impl Default for PythonTool {
15    fn default() -> Self {
16        Self::new()
17    }
18}
19
20#[derive(Serialize, Deserialize)]
21pub struct PythonToolInput {
22    code: String,
23}
24
25#[derive(Serialize, Deserialize)]
26pub struct PythonToolOutput {
27    result: String,
28    stderr: String,
29}
30
31impl Describe for PythonToolInput {
32    fn describe() -> Format {
33        vec![("code", "The Python code to execute.").into()].into()
34    }
35}
36
37impl Describe for PythonToolOutput {
38    fn describe() -> Format {
39        vec![
40            ("result", "The result of the executed Python code.").into(),
41            ("stderr", "The stderr output of the Python code execution.").into(),
42        ]
43        .into()
44    }
45}
46
47impl PythonTool {
48    fn invoke_typed(&self, input: &PythonToolInput) -> Result<PythonToolOutput, String> {
49        let output = Command::new("python3")
50            .arg("-c")
51            .arg(&input.code)
52            .output()
53            .map_err(|_e| "failed to execute process")?;
54        Ok(PythonToolOutput {
55            result: String::from_utf8(output.stdout).unwrap(),
56            stderr: String::from_utf8(output.stderr).unwrap(),
57        })
58    }
59}
60
61impl Tool for PythonTool {
62    gen_invoke_function!();
63    fn description(&self) -> ToolDescription {
64        ToolDescription::new(
65            "PythonTool",
66            "A tool that executes Python code.",
67            "Use this to execute Python code to solve your goals",
68            PythonToolInput::describe(),
69            PythonToolOutput::describe(),
70        )
71    }
72}