llm-chain-tools 0.4.0

A library for providing Large Language Models with tools (also known as 'actions') that they can trigger
Documentation
use crate::tool::Tool;
use serde::{Deserialize, Serialize};

pub struct ToolCollection {
    tools: Vec<Box<dyn Tool>>,
}

impl ToolCollection {
    pub fn new(tools: Vec<Box<dyn Tool>>) -> Self {
        Self { tools }
    }
    pub fn invoke(
        &self,
        name: &str,
        input: &serde_yaml::Value,
    ) -> Result<serde_yaml::Value, String> {
        let tool = self
            .tools
            .iter()
            .find(|t| t.matches(name))
            .ok_or("Tool not found")?;
        tool.invoke(input.clone())
    }
    pub fn process_chat_input(&self, data: &str) -> Result<String, String> {
        let (yaml_start, yaml_end) = match (data.find("```"), data.find("```yaml")) {
            (Some(start), _) => {
                let end = &data[start + 6..];
                match end.find("```") {
                    Some(end_pos) => (start + 6, start + 6 + end_pos),
                    None => return Err("Could not find end of code block".to_string()),
                }
            }
            (_, Some(start)) => {
                let end = &data[start + 7..];
                match end.find("```") {
                    Some(end_pos) => (start + 7, start + 7 + end_pos),
                    None => return Err("Could not find end of code block".to_string()),
                }
            }
            _ => (0, data.len()),
        };

        let yaml_str = &data[yaml_start..yaml_end];
        let yaml_str = yaml_str.trim_start_matches("yaml\n").trim_start();
        let res: serde_yaml::Result<ToolInvocationInput> = serde_yaml::from_str(yaml_str);
        let input = res.map_err(|_e| "INPUT MUST BE YAML ONLY".to_string())?;
        let output = self.invoke(&input.command, &input.input)?;
        Ok(serde_yaml::to_string(&output).unwrap())
    }

    pub fn describe(&self) -> String {
        let des: Vec<_> = self.tools.iter().map(|t| t.description()).collect();
        serde_yaml::to_string(&des).unwrap()
    }
}

#[derive(Serialize, Deserialize)]
struct ToolInvocationInput {
    command: String,
    input: serde_yaml::Value,
}