1crate::ix!();
3
4#[derive(
5 Debug,
6 Clone,
7 PartialEq,
8 Getters,
9 Builder,
10 Serialize,
11 Deserialize,
12 SaveLoad,
13)]
14#[builder(pattern = "owned", setter(into))]
15#[getset(get = "pub")]
16pub struct GrowerModel {
17 grower_inputs: GrowerInputs,
18
19 #[serde(alias="maybe_ungrown_justified_grower_tree_configuration")]
20 justified_grower_tree_configuration: JustifiedGrowerTreeConfiguration,
21
22 #[serde(alias="maybe_ungrown_justified_string_skeleton")]
23 justified_string_skeleton: JustifiedStringSkeleton,
24
25 #[serde(alias="maybe_ungrown_stripped_string_skeleton")]
26 stripped_string_skeleton: StrippedStringSkeleton,
27
28 #[serde(alias="maybe_ungrown_core_string_skeleton")]
29 core_string_skeleton: CoreStringSkeleton,
30
31 #[serde(alias="maybe_ungrown_annotated_leaf_holder_expansions")]
32 annotated_leaf_holder_expansions: AnnotatedLeafHolderExpansions,
33}
34
35impl GrowerModel {
36
37 pub async fn new(
41 seed: PartiallyGrownModel,
42 client: &GrowerLanguageModelClient,
43 ) -> Result<Self,GrowerModelGenerationError> {
44
45 seed.validate();
46 let justified_grower_tree_configuration = seed.maybe_grow_justified_tree_configuration(client).await?;
47 let justified_string_skeleton = seed.maybe_grow_justified_string_skeleton(client).await?;
48 let stripped_string_skeleton = StrippedStringSkeleton::from(justified_string_skeleton.clone());
49 let core_string_skeleton = seed.maybe_grow_core_string_skeleton(client).await?;
50 let annotated_leaf_holder_expansions = seed.maybe_grow_annotated_leaf_holder_expansions(client).await?;
51
52 Ok(Self {
53 grower_inputs: seed.grower_inputs().clone().unwrap(),
54 justified_grower_tree_configuration,
55 justified_string_skeleton,
56 stripped_string_skeleton,
57 core_string_skeleton,
58 annotated_leaf_holder_expansions,
59 })
60 }
61
62 #[instrument(level = "trace", skip_all)]
65 pub fn finalize_from_valid_partial(
66 partial: PartiallyGrownModel,
67 ) -> Result<Self, GrowerModelGenerationError> {
68 partial.validate().map_err(GrowerModelGenerationError::InvalidPartial)?;
70
71 let grower_inputs = partial
73 .grower_inputs()
74 .clone()
75 .expect("Validation guarantees grower_inputs is present");
76 let justified_grower_tree_configuration = partial
77 .maybe_ungrown_justified_grower_tree_configuration()
78 .clone()
79 .expect("Validation guarantees this is present");
80 let justified_string_skeleton = partial
81 .maybe_ungrown_justified_string_skeleton()
82 .clone()
83 .expect("Validation guarantees this is present");
84 let stripped_string_skeleton = partial
85 .maybe_ungrown_stripped_string_skeleton()
86 .clone()
87 .expect("Validation guarantees this is present");
88 let core_string_skeleton = partial
89 .maybe_ungrown_core_string_skeleton()
90 .clone()
91 .expect("Validation guarantees this is present");
92 let annotated_leaf_holder_expansions = partial
93 .maybe_ungrown_annotated_leaf_holder_expansions()
94 .clone()
95 .expect("Validation guarantees this is present");
96
97 Ok(GrowerModel {
98 grower_inputs,
99 justified_grower_tree_configuration,
100 justified_string_skeleton,
101 stripped_string_skeleton,
102 core_string_skeleton,
103 annotated_leaf_holder_expansions,
104 })
105 }
106
107 pub async fn show_all_generation_queries(&self) {
109 trace!("Preparing to show all generation queries for GrowerModel");
110
111 let query_cfg = Self::grower_tree_configuration_generation_query_string(
112 self.grower_inputs(),
113 );
114 info!("GrowerTreeConfiguration query:\n{query_cfg}");
115
116 let query_skel = Self::string_skeleton_generation_query_string(
117 self.grower_inputs(),
118 self.justified_grower_tree_configuration(),
119 );
120 info!("StringSkeleton query:\n{query_skel}");
121
122 let query_core = Self::core_string_skeleton_generation_query_string(
123 self.grower_inputs(),
124 self.justified_grower_tree_configuration(),
125 self.stripped_string_skeleton(),
126 );
127 info!("CoreStringSkeleton query:\n{query_core}");
128
129 let query_leaf = Self::annotated_leaf_holder_expansions_generation_query_string(
130 self.grower_inputs(),
131 self.justified_grower_tree_configuration(),
132 self.core_string_skeleton(),
133 );
134 info!("AnnotatedLeafHolderExpansions query:\n{query_leaf}");
135
136 trace!("Done showing all generation queries for GrowerModel");
137 }
138}
139
140impl PartiallyGrownModel {
141
142 pub async fn maybe_grow_justified_tree_configuration(
143 &self,
144 client: &GrowerLanguageModelClient,
145 ) -> Result<JustifiedGrowerTreeConfiguration, GrowerModelGenerationError> {
146 trace!("maybe_grow_justified_tree_configuration called with partial: {:?}", self);
147 match &self.maybe_ungrown_justified_grower_tree_configuration() {
148 Some(cfg) => {
149 debug!("maybe_ungrown_justified_grower_tree_configuration already present");
150 Ok(cfg.clone())
151 }
152 None => {
153 debug!("maybe_ungrown_justified_grower_tree_configuration not present, generating now");
154 let generated = match GrowerModel::generate_grower_tree_configuration(
155 client,
156 self.grower_inputs().as_ref().unwrap()
157 ).await {
158 Ok(g) => g,
159 Err(e) => {
160 GrowerModel::handle_grower_tree_configuration_generation_error(
161 e,
162 client,
163 self.grower_inputs().as_ref().unwrap()
164 ).await?
165 }
166 };
167 Ok(generated)
168 }
169 }
170 }
171
172 pub async fn maybe_grow_justified_string_skeleton(
173 &self,
174 client: &GrowerLanguageModelClient,
175 ) -> Result<JustifiedStringSkeleton, GrowerModelGenerationError> {
176 trace!("maybe_grow_justified_string_skeleton called with partial: {:?}", self);
177 match &self.maybe_ungrown_justified_string_skeleton() {
178 Some(skel) => {
179 debug!("maybe_ungrown_justified_string_skeleton already present");
180 Ok(skel.clone())
181 }
182 None => {
183 debug!("maybe_ungrown_justified_string_skeleton not present, generating now");
184 let tree_conf = self
185 .maybe_ungrown_justified_grower_tree_configuration()
186 .as_ref()
187 .expect("Validation should have prevented missing JustifiedGrowerTreeConfiguration");
188
189 let generated = match GrowerModel::generate_string_skeleton(
190 client,
191 self.grower_inputs().as_ref().unwrap(),
192 tree_conf
193 ).await {
194 Ok(g) => g,
195 Err(e) => {
196 GrowerModel::handle_string_skeleton_generation_error(
197 e,
198 client,
199 self.grower_inputs().as_ref().unwrap(),
200 tree_conf
201 ).await?
202 }
203 };
204 Ok(generated)
205 }
206 }
207 }
208
209 pub async fn maybe_grow_core_string_skeleton(
210 &self,
211 client: &GrowerLanguageModelClient,
212 ) -> Result<CoreStringSkeleton, GrowerModelGenerationError> {
213 trace!("maybe_grow_core_string_skeleton called with partial: {:?}", self);
214 match &self.maybe_ungrown_core_string_skeleton() {
215 Some(exp) => {
216 debug!("maybe_ungrown_core_string_skeleton already present");
217 Ok(exp.clone())
218 }
219 None => {
220 debug!("maybe_ungrown_core_string_skeleton not present, generating now");
221 let tree_conf = self
222 .maybe_ungrown_justified_grower_tree_configuration()
223 .as_ref()
224 .expect("Validation should have prevented missing JustifiedGrowerTreeConfiguration");
225 let skeleton = self
226 .maybe_ungrown_justified_string_skeleton()
227 .as_ref()
228 .expect("Validation should have prevented missing JustifiedStringSkeleton");
229 let stripped = StrippedStringSkeleton::from(skeleton.clone());
230
231 let generated = match GrowerModel::generate_core_string_skeleton(
232 client,
233 self.grower_inputs().as_ref().unwrap(),
234 tree_conf,
235 &stripped
236 ).await {
237 Ok(g) => g,
238 Err(e) => {
239 GrowerModel::handle_core_string_skeleton_generation_error(
240 e,
241 client,
242 self.grower_inputs().as_ref().unwrap(),
243 tree_conf,
244 skeleton,
245 &stripped
246 ).await?
247 }
248 };
249 Ok(generated)
250 }
251 }
252 }
253
254 pub async fn maybe_grow_annotated_leaf_holder_expansions(
255 &self,
256 client: &GrowerLanguageModelClient,
257 ) -> Result<AnnotatedLeafHolderExpansions, GrowerModelGenerationError> {
258 trace!("maybe_grow_annotated_leaf_holder_expansions called with partial: {:?}", self);
259 match &self.maybe_ungrown_annotated_leaf_holder_expansions() {
260 Some(exp) => {
261 debug!("maybe_ungrown_annotated_leaf_holder_expansions already present");
262 Ok(exp.clone())
263 }
264 None => {
265 debug!("maybe_ungrown_annotated_leaf_holder_expansions not present, generating now");
266 let tree_conf = self
267 .maybe_ungrown_justified_grower_tree_configuration()
268 .as_ref()
269 .expect("Validation should have prevented missing JustifiedGrowerTreeConfiguration");
270 let skeleton = self
271 .maybe_ungrown_justified_string_skeleton()
272 .as_ref()
273 .expect("Validation should have prevented missing JustifiedStringSkeleton");
274 let stripped = StrippedStringSkeleton::from(skeleton.clone());
275 let core_string_skeleton = self
276 .maybe_ungrown_core_string_skeleton()
277 .as_ref()
278 .expect("Validation should have prevented missing CoreStringSkeleton");
279
280 let generated = match GrowerModel::generate_annotated_leaf_holder_expansions(
281 client,
282 self.grower_inputs().as_ref().unwrap(),
283 tree_conf,
284 &stripped,
285 core_string_skeleton
286 ).await {
287 Ok(g) => g,
288 Err(e) => {
289 GrowerModel::handle_annotated_leaf_holder_expansion_generation_error(
290 e,
291 client,
292 self.grower_inputs().as_ref().unwrap(),
293 tree_conf,
294 skeleton,
295 &stripped,
296 core_string_skeleton
297 ).await?
298 }
299 };
300 Ok(generated)
301 }
302 }
303 }
304}
305
306#[cfg(test)]
307#[disable]
308mod verify_show_all_generation_queries {
309 use super::*;
310 use std::collections::HashMap;
311
312 #[traced_test]
313 async fn it_displays_all_generation_queries_without_error() {
314 trace!("Starting test: it_displays_all_generation_queries_without_error");
315
316 let grower_inputs = GrowerInputsBuilder::default()
318 .target(CLASSIC_SKILL)
319 .global_environment_descriptor(YOU_ARE_HERE.to_string())
320 .sub_environments(
321 CLASSIC_SUB_ENVIRONMENTS
322 .iter()
323 .map(|s| s.to_string())
324 .collect::<Vec<_>>()
325 )
326 .neighbors(
327 CLASSIC_SKILL_NEIGHBORS
328 .iter()
329 .map(|s| s.to_string())
330 .collect::<Vec<_>>()
331 )
332 .build()
333 .expect("Failed to build GrowerInputs for test");
334
335 let level_skipping_config = LevelSkippingConfigurationBuilder::default()
337 .leaf_probability_per_level(vec![0.15, 0.3])
338 .build()
339 .expect("Failed building LevelSkippingConfiguration");
340
341 let weighted_branching_config = WeightedBranchingConfigurationBuilder::default()
342 .mean(3)
343 .variance(1)
344 .build()
345 .expect("Failed building WeightedBranchingConfiguration");
346
347 let tree_level_specific_config = TreeLevelSpecificConfigurationBuilder::default()
348 .breadth_per_level(vec![2, 4])
349 .density_per_level(vec![2, 3])
350 .build()
351 .expect("Failed building TreeLevelSpecificConfiguration");
352
353 let capstone_config = CapstoneGenerationConfigurationBuilder::default()
354 .mode(CapstoneMode::Probabilistic)
355 .probability(0.2)
356 .build()
357 .expect("Failed building CapstoneGenerationConfiguration");
358
359 let ai_conf = AiTreeBranchingConfidenceConfigurationBuilder::default()
360 .base_factor(2)
361 .factor_multiplier(1.5)
362 .build()
363 .expect("Failed building AiTreeBranchingConfidenceConfiguration");
364
365 let tree_config = GrowerTreeConfigurationBuilder::default()
366 .depth(3)
367 .breadth(2)
368 .density(2)
369 .leaf_granularity(0.8)
370 .balance_symmetry(0.4)
371 .complexity(ConfigurationComplexity::Balanced)
372 .level_specific(Some(tree_level_specific_config))
373 .weighted_branching(Some(weighted_branching_config))
374 .level_skipping(Some(level_skipping_config))
375 .capstone(Some(capstone_config))
376 .ordering(Some(SubBranchOrdering::Alphabetical))
377 .ai_confidence(Some(ai_conf))
378 .aggregator_preference(0.7)
379 .allow_early_leaves(true)
380 .partial_subbranch_probability(0.3)
381 .tree_expansion_policy(
382 TreeExpansionPolicy::Weighted(
383 WeightedNodeVariantPolicyBuilder::default()
384 .aggregator_weight(0.4)
385 .dispatch_weight(0.4)
386 .leaf_holder_weight(0.2)
387 .build()
388 .expect("Failed building WeightedNodeVariantPolicy")
389 )
390 )
391 .aggregator_depth_limit(Some(5))
392 .dispatch_depth_limit(Some(4))
393 .leaf_min_depth(Some(1))
394 .build()
395 .expect("Failed to build GrowerTreeConfiguration");
396
397 let justified_grower_tree_configuration = JustifiedGrowerTreeConfigurationBuilder::default()
420 .item(tree_config)
421 .justification(
422 GrowerTreeConfigurationJustification {
423 depth_justification: "Depth=3 => moderate hierarchy.".to_string(),
425 breadth_justification: "Breadth=2 => keep it simpler at each level.".to_string(),
426 density_justification: "Density=2 => each leaf node spawns 2 variants.".to_string(),
427 leaf_granularity_justification: "0.8 => quite detailed leaves but not too big.".to_string(),
428 balance_symmetry_justification: "0.4 => partial symmetry only.".to_string(),
429
430 complexity_justification: ConfigurationComplexityJustification {
432 enum_variant_justification: "Using Balanced variant for middle-of-the-road complexity.".to_string(),
433 },
434
435 level_specific_justification: TreeLevelSpecificConfigurationJustification {
443 breadth_per_level_justification: "Level 0 => 2, Level 1 => 4 sub-branches".to_string(),
444 density_per_level_justification: "Level 0 => density=2, Level 1 => density=3".to_string(),
445 },
446
447 weighted_branching_justification: WeightedBranchingConfigurationJustification {
449 mean_justification: "Mean=3 => typical branching factor.".to_string(),
450 variance_justification: "Variance=1 => slight randomness in branching.".to_string(),
451 },
452
453 level_skipping_justification: LevelSkippingConfigurationJustification {
455 leaf_probability_per_level_justification: "At Level0 => p=0.15, Level1 => p=0.3 => some skipping.".to_string(),
456 },
457
458 capstone_justification: CapstoneGenerationConfigurationJustification {
460 mode_justification: CapstoneModeJustification {
461 enum_variant_justification: "Probabilistic => not always a capstone leaf.".to_string(),
462 },
463 probability_justification: "p=0.2 => about 1 in 5 leaves becomes capstone.".to_string(),
464 },
465
466 ordering_justification: SubBranchOrderingJustification {
468 enum_variant_justification: "Alphabetical ordering for sub-branches.".to_string(),
469 },
470
471 ai_confidence_justification: AiTreeBranchingConfidenceConfigurationJustification {
473 base_factor_justification: "Base=2 => expansions double in certain contexts.".to_string(),
474 factor_multiplier_justification: "1.5 => expansions ramp up more if AI is sure.".to_string(),
475 },
476
477 aggregator_preference_justification: "0.7 => aggregator nodes favored frequently.".to_string(),
478 allow_early_leaves_justification: "true => sub-branches can terminate earlier.".to_string(),
479 partial_subbranch_probability_justification: "0.3 => some sub-branches appear optionally.".to_string(),
480
481 tree_expansion_policy_justification: TreeExpansionPolicyJustification {
483 enum_variant_justification: "Weighted aggregator=0.4, dispatch=0.4, leaf=0.2 => variety.".to_string(),
484 },
485
486 aggregator_depth_limit_justification: "No aggregator deeper than level=5.".to_string(),
487 dispatch_depth_limit_justification: "Stop dispatch deeper than level=4.".to_string(),
488 leaf_min_depth_justification: "Leaf-holders not before depth=1.".to_string(),
489 }
490 )
491 .confidence(
492 GrowerTreeConfigurationConfidence {
493 depth_confidence: 0.95,
494 breadth_confidence: 0.9,
495 density_confidence: 0.85,
496 leaf_granularity_confidence: 0.88,
497 balance_symmetry_confidence: 0.7,
498
499 complexity_confidence: ConfigurationComplexityConfidence {
501 enum_variant_confidence: 0.8,
502 },
503
504 level_specific_confidence: TreeLevelSpecificConfigurationConfidence {
506 breadth_per_level_confidence: 0.92,
507 density_per_level_confidence: 0.86,
508 },
509
510 weighted_branching_confidence: WeightedBranchingConfigurationConfidence {
512 mean_confidence: 0.77,
513 variance_confidence: 0.75,
514 },
515
516 level_skipping_confidence: LevelSkippingConfigurationConfidence {
518 leaf_probability_per_level_confidence: 0.65,
519 },
520
521 capstone_confidence: CapstoneGenerationConfigurationConfidence {
523 mode_confidence: CapstoneModeConfidence {
524 enum_variant_confidence: 0.6,
525 },
526 probability_confidence: 0.4,
527 },
528
529 ordering_confidence: SubBranchOrderingConfidence {
531 enum_variant_confidence: 0.9,
532 },
533
534 ai_confidence_confidence: AiTreeBranchingConfidenceConfigurationConfidence {
536 base_factor_confidence: 0.8,
537 factor_multiplier_confidence: 0.75,
538 },
539
540 aggregator_preference_confidence: 0.88,
541 allow_early_leaves_confidence: 0.82,
542 partial_subbranch_probability_confidence: 0.75,
543
544 tree_expansion_policy_confidence: TreeExpansionPolicyConfidence {
545 enum_variant_confidence: 0.85,
546 },
547
548 aggregator_depth_limit_confidence: 0.7,
549 dispatch_depth_limit_confidence: 0.65,
550 leaf_min_depth_confidence: 0.6,
551 }
552 )
553 .build()
554 .expect("Failed to build JustifiedGrowerTreeConfiguration");
555
556 let mut root_children = HashMap::new();
558 root_children.insert(
559 "AggregatorBranch".to_string(),
560 DispatchChildSpecBuilder::default()
561 .branch_selection_likelihood(100)
562 .build()
563 .expect("Failed building DispatchChildSpec")
564 );
565 root_children.insert(
566 "LeafBranch".to_string(),
567 DispatchChildSpecBuilder::default()
568 .branch_selection_likelihood(100)
569 .build()
570 .expect("Failed building leaf_holder DispatchChildSpec")
571 );
572
573 let root_node = StringSkeletonNode::Dispatch {
574 name: "RootDispatch".to_string(),
575 ordering: Some(SubBranchOrdering::Alphabetical),
576 children: root_children,
577 };
578
579 let mut aggregator_children = HashMap::new();
580 aggregator_children.insert(
581 "SubAggregator".to_string(),
582 AggregateChildSpecBuilder::default()
583 .psome_likelihood(80)
584 .optional(false)
585 .build()
586 .expect("Failed building aggregator child spec")
587 );
588
589 let aggregator_node = StringSkeletonNode::Aggregate {
590 name: "AggregatorBranch".to_string(),
591 ordering: None,
592 children: aggregator_children,
593 };
594
595 let leaf_node = StringSkeletonNode::LeafHolder {
596 name: "LeafBranch".to_string(),
597 ordering: None,
598 n_leaves: 10,
599 capstone: false,
600 };
601
602 let mut skel_map = HashMap::new();
603 skel_map.insert("root".to_string(), root_node);
604 skel_map.insert("AggregatorBranch".to_string(), aggregator_node);
605 skel_map.insert("LeafBranch".to_string(), leaf_node);
606
607 let string_skeleton = StringSkeletonBuilder::default()
608 .map(skel_map)
609 .build()
610 .expect("Failed to build StringSkeleton");
611
612 let justified_string_skeleton = JustifiedStringSkeletonBuilder::default()
614 .item(string_skeleton)
615 .justification(
616 StringSkeletonJustification {
617 map_justification: "Multiple branches illustrate distinct skill pathways.".to_string(),
618 }
619 )
620 .confidence(
621 StringSkeletonConfidence {
622 map_confidence: 0.85,
623 }
624 )
625 .build()
626 .expect("Failed to build JustifiedStringSkeleton");
627
628 let stripped_string_skeleton = StrippedStringSkeleton::from(&justified_string_skeleton);
630
631 let core_aggregate_node = CoreSkeletalAggregateNodeBuilder::default()
633 .name("CoreAggregateExample".to_string())
634 .descriptor("An aggregator example in the core skeleton".to_string())
635 .children(vec![])
636 .build()
637 .expect("Failed building CoreSkeletalAggregateNode");
638
639 let core_dispatch_node = CoreSkeletalDispatchNodeBuilder::default()
640 .name("CoreDispatchExample".to_string())
641 .descriptor("A dispatch example in the core skeleton".to_string())
642 .children(vec![])
643 .build()
644 .expect("Failed building CoreSkeletalDispatchNode");
645
646 let core_leaf_node = CoreSkeletalLeafHolderNodeBuilder::default()
647 .name("CoreLeafHolderExample".to_string())
648 .descriptor("A leaf holder example in the core skeleton".to_string())
649 .leaves(vec!["leaf_a".to_string(), "leaf_b".to_string(), "leaf_c".to_string()])
650 .build()
651 .expect("Failed building CoreSkeletalLeafHolderNode");
652
653 let core_string_skeleton = CoreStringSkeletonBuilder::default()
654 .dispatch_nodes(vec![core_dispatch_node])
655 .aggregate_nodes(vec![core_aggregate_node])
656 .leaf_holder_nodes(vec![core_leaf_node])
657 .build()
658 .expect("Failed to build CoreStringSkeleton");
659
660 let annotated_leaf_holder_node = AnnotatedLeafHolderNodeBuilder::default()
662 .leaf_holder_name("CoreLeafHolderExample".to_string())
663 .annotated_leaves(vec![
664 AnnotatedLeafBuilder::default()
665 .leaf_name("leaf_a".to_string())
666 .leaf_descriptor("This is an advanced skill technique.".to_string())
667 .build()
668 .expect("Failed building leaf_a"),
669 AnnotatedLeafBuilder::default()
670 .leaf_name("leaf_b".to_string())
671 .leaf_descriptor("A specialized sub-skill extension.".to_string())
672 .build()
673 .expect("Failed building leaf_b"),
674 ])
675 .build()
676 .expect("Failed building AnnotatedLeafHolderNode");
677
678 let annotated_leaf_holder_expansions = AnnotatedLeafHolderExpansionsBuilder::default()
679 .annotated_leaf_holders(vec![annotated_leaf_holder_node])
680 .build()
681 .expect("Failed to build AnnotatedLeafHolderExpansions");
682
683 let model = GrowerModel {
685 grower_inputs,
686 justified_grower_tree_configuration,
687 justified_string_skeleton,
688 stripped_string_skeleton,
689 core_string_skeleton,
690 annotated_leaf_holder_expansions,
691 };
692
693 model.show_all_generation_queries().await;
695
696 assert!(false);
697 }
698}