aimx/inference/
modifier.rs1use crate::{
2 aim::{ContextLike, Prefix, Rule, WorkflowLike},
3 expressions::ExpressionLike,
4 inference::OutputFormat,
5 values::Value,
6};
7use std::{collections::HashMap, sync::Arc};
8
9#[derive(Debug, PartialEq, Clone)]
21pub struct Modifier {
22 role: Option<Arc<Value>>,
24 instructions: Option<Arc<Value>>,
26 output_format: Option<Arc<Value>>,
28 system: Arc<str>,
30 user: Option<Arc<Value>>,
32 others: Vec<(Arc<str>, Arc<Value>)>,
34 assignments: HashMap<Arc<str>, Arc<Rule>>,
36 examples: Vec<(Arc<str>, Arc<Value>)>,
38}
39
40impl Default for Modifier {
41 fn default() -> Self {
42 Self {
43 role: None,
44 instructions: None,
45 output_format: None,
46 system: Arc::from("You are a helpful assistant"),
47 user: None,
48 others: Vec::new(),
49 assignments: HashMap::new(),
50 examples: Vec::new(),
51 }
52 }
53}
54
55impl Modifier {
56 pub fn new(workflow: Arc<dyn WorkflowLike>, context: &mut dyn ContextLike) -> Self {
57 let mut modifier = Self::default();
58
59 for rule in workflow.iter_rules() {
62 if rule.is_assignment() {
64 let ucid = rule.ucid();
66 modifier.assignments.insert(ucid, rule.clone());
68 }
69 }
70
71 for rule in workflow.iter_rules() {
73 let identifier = rule.identifier();
74 if &*identifier == "content" {
76 if let Ok(value) = rule.evaluate(context) {
77 modifier.user = Some(value);
78 }
79 } else if rule.is_modifier() {
81 if &*identifier == "ROLE" {
83 if let Ok(value) = rule.evaluate(context) {
84 modifier.role = Some(value);
85 }
86 } else if &*identifier == "INSTRUCTIONS" {
88 if let Ok(value) = rule.evaluate(context) {
89 modifier.instructions = Some(value);
90 }
91 } else if &*identifier == "OUTPUT" {
93 if let Ok(value) = rule.evaluate(context) {
94 modifier.output_format = Some(value);
95 }
96 } else if &*identifier == "SYSTEM" {
98 if let Ok(value) = rule.evaluate(context) {
99 modifier.system = value.to_pretty_str(Prefix::None);
100 }
101 } else if rule.is_format() && modifier.assignments.contains_key(&identifier) {
103 if let Ok(value) = rule.evaluate(context) {
104 modifier.examples.push((identifier, value));
105 }
106 } else if let Ok(value) = rule.evaluate(context) {
108 modifier.others.push((identifier, value));
109 }
110 }
111 }
112
113 modifier
114 }
115
116 pub fn system_prompt(&self) -> Arc<str> {
117 self.system.clone()
118 }
119
120 pub fn role(&self, format: &mut OutputFormat) {
122 if let Some(value) = &self.role {
123 format.value(value);
124 } else {
125 format.text("You are a helpful assistant.");
126 }
127 format.section_end();
128 }
129
130 pub fn others(&self, format: &mut OutputFormat) {
132 if !self.others.is_empty() {
133 for (identifier, value) in &self.others {
134 format.section_start(identifier);
135 format.unordered_value(value);
136 }
137 format.section_end();
138 }
139 }
140
141 pub fn instructions(&self, format: &mut OutputFormat) {
143 format.section_start("INSTRUCTIONS");
144 if let Some(value) = self.instructions.clone() {
145 format.value(&value);
146 } else if !self.examples.is_empty() {
147 format.text("Derive the following values from the content:");
148 }
149 for (identifier, value) in self.examples.clone() {
150 if let Value::Format(f) = &*value {
151 format.single_item(&identifier, &f.instruction());
152 }
153 }
154 format.section_end();
155 }
156
157 pub fn output_format(&self, format: &mut OutputFormat) {
159 format.section_start("OUTPUT FORMAT");
160 if let Some(value) = self.output_format.clone() {
161 if let Value::Format(f) = &*value {
162 format.text(&f.instruction());
163 } else {
164 format.value(&value);
165 }
166 } else if !self.examples.is_empty() {
167 format.text("Provide your answer in this exact format:");
168 }
169 for (identifier, value) in self.examples.clone() {
170 if let Value::Format(f) = &*value {
171 format.single_line_tagged(&identifier, &f.template());
172 }
173 }
174 format.section_end();
175 }
176
177 pub fn examples(&self, format: &mut OutputFormat) {
179 format.section_start("EXAMPLES");
180 let mut index: usize = 0;
181 let mut length: usize = 1;
182 while index < length {
183 if let Some(value) = self.output_format.clone() && let Value::Format(f) = &*value {
184 length = f.examples().len();
185 if index < length {
186 format.single_line_quoted("USER TEXT", &f.examples()[index]);
187 }
188 }
189 for (identifier, value) in self.examples.clone() {
190 if let Value::Format(f) = &*value {
191 length = f.examples().len();
192 if index < length {
193 format.single_line(&identifier, &f.examples()[index]);
194 }
195 }
196 }
197 format.section_end();
198 index += 1;
199 }
200 }
201
202 pub fn user_text(&self, format: &mut OutputFormat) {
204 if let Some(value) = &self.user {
205 format.section_start("USER TEXT");
206 format.value(value);
207 format.section_end();
208 }
209 }
210}