llm_chain/tools/tools/
python.rs

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