dspy_rs/
lib.rs

1pub mod adapter;
2pub mod core;
3pub mod data;
4pub mod evaluate;
5pub mod optimizer;
6pub mod predictors;
7pub mod utils;
8
9pub use adapter::chat::*;
10pub use core::*;
11pub use data::*;
12pub use evaluate::*;
13pub use optimizer::*;
14pub use predictors::*;
15pub use utils::*;
16
17pub use dsrs_macros::*;
18
19#[macro_export]
20macro_rules! example {
21    // Pattern: { "key": <__dsrs_field_type>: "value", ... }
22    { $($key:literal : $field_type:literal => $value:expr),* $(,)? } => {{
23        use std::collections::HashMap;
24        use dspy_rs::data::example::Example;
25
26        let mut input_keys = vec![];
27        let mut output_keys = vec![];
28
29        let mut fields = HashMap::new();
30        $(
31            if $field_type == "input" {
32                input_keys.push($key.to_string());
33            } else {
34                output_keys.push($key.to_string());
35            }
36
37            fields.insert($key.to_string(), serde_json::to_value($value).unwrap());
38        )*
39
40        Example::new(
41            fields,
42            input_keys,
43            output_keys,
44        )
45    }};
46}
47
48#[macro_export]
49macro_rules! prediction {
50    { $($key:literal => $value:expr),* $(,)? } => {{
51        use std::collections::HashMap;
52        use dspy_rs::{Prediction, LmUsage};
53
54        let mut fields = HashMap::new();
55        $(
56            fields.insert($key.to_string(), serde_json::to_value($value).unwrap());
57        )*
58
59        Prediction::new(fields, LmUsage::default())
60    }};
61}
62
63#[macro_export]
64macro_rules! field {
65    // Example Usage: field! {
66    //   input["Description"] => question: String
67    // }
68    //
69    // Example Output:
70    //
71    // {
72    //   "question": {
73    //     "type": "String",
74    //     "desc": "Description",
75    //     "schema": ""
76    //   },
77    //   ...
78    // }
79
80    // Pattern for field definitions with descriptions
81    { $($field_type:ident[$desc:literal] => $field_name:ident : $field_ty:ty),* $(,)? } => {{
82        use serde_json::json;
83
84        let mut result = serde_json::Map::new();
85
86        $(
87            let type_str = stringify!($field_ty);
88            let schema = {
89                let schema = schemars::schema_for!($field_ty);
90                let schema_json = serde_json::to_value(schema).unwrap();
91                // Extract just the properties if it's an object schema
92                if let Some(obj) = schema_json.as_object() {
93                    if obj.contains_key("properties") {
94                        schema_json["properties"].clone()
95                    } else {
96                        "".to_string().into()
97                    }
98                } else {
99                    "".to_string().into()
100                }
101            };
102            result.insert(
103                stringify!($field_name).to_string(),
104                json!({
105                    "type": type_str,
106                    "desc": $desc,
107                    "schema": schema,
108                    "__dsrs_field_type": stringify!($field_type)
109                })
110            );
111        )*
112
113        serde_json::Value::Object(result)
114    }};
115
116    // Pattern for field definitions without descriptions
117    { $($field_type:ident => $field_name:ident : $field_ty:ty),* $(,)? } => {{
118        use serde_json::json;
119
120        let mut result = serde_json::Map::new();
121
122        $(
123            let type_str = stringify!($field_ty);
124            let schema = {
125                let schema = schemars::schema_for!($field_ty);
126                let schema_json = serde_json::to_value(schema).unwrap();
127                // Extract just the properties if it's an object schema
128                if let Some(obj) = schema_json.as_object() {
129                    if obj.contains_key("properties") {
130                        schema_json["properties"].clone()
131                    } else {
132                        "".to_string().into()
133                    }
134                } else {
135                    "".to_string().into()
136                }
137            };
138            result.insert(
139                stringify!($field_name).to_string(),
140                json!({
141                    "type": type_str,
142                    "desc": "",
143                    "schema": schema,
144                    "__dsrs_field_type": stringify!($field_type)
145                })
146            );
147        )*
148
149        serde_json::Value::Object(result)
150    }};
151}
152
153#[macro_export]
154macro_rules! sign {
155    // Example Usage: signature! {
156    //     question: String, random: bool -> answer: String
157    // }
158    //
159    // Example Output:
160    //
161    // #[derive(Signature)]
162    // struct InlineSignature {
163    //     question: In<String>,
164    //     random: In<bool>,
165    //     answer: Out<String>,
166    // }
167    //
168    // InlineSignature::new()
169
170    // Pattern: input fields -> output fields
171    { ($($input_name:ident : $input_type:ty),* $(,)?) -> $($output_name:ident : $output_type:ty),* $(,)? } => {{
172        use dspy_rs::Signature;
173        let mut input_fields = serde_json::Map::new();
174        let mut output_fields = serde_json::Map::new();
175
176        #[Signature]
177        struct InlineSignature {
178            $(
179                #[input]
180                $input_name: $input_type,
181            )*
182            $(
183                #[output]
184                $output_name: $output_type,
185            )*
186        }
187
188        InlineSignature::new()
189    }};
190}
191
192/// Source: https://github.com/wholesome-ghoul/hashmap_macro/blob/master/src/lib.rs
193/// Author: https://github.com/wholesome-ghoul
194/// License: MIT
195/// Description: This macro creates a HashMap from a list of key-value pairs.
196/// Reason for Reuse: Want to avoid adding a dependency for a simple macro.
197#[macro_export]
198macro_rules! hashmap {
199    () => {
200        ::std::collections::HashMap::new()
201    };
202
203    ($($key:expr => $value:expr),+ $(,)?) => {
204        ::std::collections::HashMap::from([ $(($key, $value)),* ])
205    };
206}