Skip to main content

rig_core/embeddings/
tool.rs

1//! The module defines the [ToolSchema] struct, which is used to embed an object that implements [crate::tool::ToolEmbedding]
2
3use crate::{Embed, tool::ToolEmbeddingDyn};
4use serde::Serialize;
5
6use super::embed::EmbedError;
7
8/// Embeddable document that is used as an intermediate representation of a tool when
9/// RAGging tools.
10#[derive(Clone, Serialize, Default, Eq, PartialEq)]
11pub struct ToolSchema {
12    pub name: String,
13    pub context: serde_json::Value,
14    pub embedding_docs: Vec<String>,
15}
16
17impl Embed for ToolSchema {
18    fn embed(&self, embedder: &mut super::embed::TextEmbedder) -> Result<(), EmbedError> {
19        for doc in &self.embedding_docs {
20            embedder.embed(doc.clone());
21        }
22        Ok(())
23    }
24}
25
26impl ToolSchema {
27    /// Convert item that implements [ToolEmbeddingDyn] to an [ToolSchema].
28    ///
29    /// # Example
30    /// ```rust
31    /// use rig_core::{
32    ///     embeddings::ToolSchema,
33    ///     tool::{Tool, ToolEmbedding, ToolEmbeddingDyn},
34    /// };
35    ///
36    /// #[derive(Debug, thiserror::Error)]
37    /// #[error("Math error")]
38    /// struct NothingError;
39    ///
40    /// #[derive(Debug, thiserror::Error)]
41    /// #[error("Init error")]
42    /// struct InitError;
43    ///
44    /// struct Nothing;
45    /// impl Tool for Nothing {
46    ///     const NAME: &'static str = "nothing";
47    ///
48    ///     type Error = NothingError;
49    ///     type Args = ();
50    ///     type Output = ();
51    ///
52    ///     fn description(&self) -> String {
53    ///         "nothing".to_string()
54    ///     }
55    ///
56    ///     fn parameters(&self) -> serde_json::Value {
57    ///         serde_json::json!({})
58    ///     }
59    ///
60    ///     async fn call(&self, _args: Self::Args) -> Result<Self::Output, Self::Error> {
61    ///         Ok(())
62    ///     }
63    /// }
64    ///
65    /// impl ToolEmbedding for Nothing {
66    ///     type InitError = InitError;
67    ///     type Context = ();
68    ///     type State = ();
69    ///
70    ///     fn init(_state: Self::State, _context: Self::Context) -> Result<Self, Self::InitError> {
71    ///         Ok(Nothing)
72    ///     }
73    ///
74    ///     fn embedding_docs(&self) -> Vec<String> {
75    ///         vec!["Do nothing.".into()]
76    ///     }
77    ///
78    ///     fn context(&self) -> Self::Context {}
79    /// }
80    ///
81    /// let tool = ToolSchema::try_from(&Nothing).unwrap();
82    ///
83    /// assert_eq!(tool.name, "nothing".to_string());
84    /// assert_eq!(tool.embedding_docs, vec!["Do nothing.".to_string()]);
85    /// ```
86    pub fn try_from(tool: &dyn ToolEmbeddingDyn) -> Result<Self, EmbedError> {
87        Self::from_tool(tool.name(), tool)
88    }
89
90    /// Convert a tool to a schema using an explicit registered name.
91    ///
92    /// Registry paths should pass the key under which the tool was registered so
93    /// vector-store IDs resolve back to the same entry even if `tool.name()` is
94    /// computed dynamically.
95    pub fn from_tool(
96        name: impl Into<String>,
97        tool: &dyn ToolEmbeddingDyn,
98    ) -> Result<Self, EmbedError> {
99        Ok(ToolSchema {
100            name: name.into(),
101            context: tool.context().map_err(EmbedError::new)?,
102            embedding_docs: tool.embedding_docs(),
103        })
104    }
105}