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}