Skip to main content

brainwires_knowledge/prompting/
library.rs

1//! Technique Library with BKS Integration
2//!
3//! This module provides a library of all 15 prompting techniques with metadata,
4//! integrated with the Behavioral Knowledge System (BKS) for querying shared
5//! technique effectiveness across users.
6
7use super::techniques::{
8    ComplexityLevel, PromptingTechnique, TaskCharacteristic, TechniqueCategory, TechniqueMetadata,
9};
10#[cfg(feature = "knowledge")]
11use crate::knowledge::bks_pks::{BehavioralKnowledgeCache, BehavioralTruth};
12use anyhow::Result;
13use std::collections::HashMap;
14use std::sync::Arc;
15use tokio::sync::Mutex;
16
17/// Library of all prompting techniques
18pub struct TechniqueLibrary {
19    techniques: HashMap<PromptingTechnique, TechniqueMetadata>,
20    bks_cache: Option<Arc<Mutex<BehavioralKnowledgeCache>>>,
21}
22
23impl TechniqueLibrary {
24    /// Create a new technique library with all 15 techniques
25    pub fn new() -> Self {
26        let mut techniques = HashMap::new();
27
28        // === Role Assignment (1 technique) ===
29        techniques.insert(
30            PromptingTechnique::RolePlaying,
31            TechniqueMetadata::new(
32                PromptingTechnique::RolePlaying,
33                TechniqueCategory::RoleAssignment,
34                "Role Playing",
35                "Assign expert role to elicit domain-specific knowledge",
36                "You are a {role} with expertise in {domain}. ",
37                vec![
38                    TaskCharacteristic::MultiStepReasoning,
39                    TaskCharacteristic::CodeGeneration,
40                    TaskCharacteristic::AlgorithmicProblem,
41                ],
42                0.0, // Always usable
43                ComplexityLevel::Simple,
44                true,
45            ),
46        );
47
48        // === Emotional Stimulus (2 techniques) ===
49        techniques.insert(
50            PromptingTechnique::EmotionPrompting,
51            TechniqueMetadata::new(
52                PromptingTechnique::EmotionPrompting,
53                TechniqueCategory::EmotionalStimulus,
54                "Emotion Prompting",
55                "Add emotional cues to increase engagement",
56                "This is an important {task_type} that requires {quality}. ",
57                vec![
58                    TaskCharacteristic::MultiStepReasoning,
59                    TaskCharacteristic::NumericalCalculation,
60                ],
61                0.0,
62                ComplexityLevel::Simple,
63                true,
64            ),
65        );
66
67        techniques.insert(
68            PromptingTechnique::StressPrompting,
69            TechniqueMetadata::new(
70                PromptingTechnique::StressPrompting,
71                TechniqueCategory::EmotionalStimulus,
72                "Stress Prompting",
73                "Induce moderate stress conditions for focus",
74                "This task requires immediate attention and precision. Time is limited. ",
75                vec![
76                    TaskCharacteristic::LogicalDeduction,
77                    TaskCharacteristic::AlgorithmicProblem,
78                ],
79                0.0,
80                ComplexityLevel::Simple,
81                true,
82            ),
83        );
84
85        // === Reasoning (7 techniques) ===
86        techniques.insert(
87            PromptingTechnique::ChainOfThought,
88            TechniqueMetadata::new(
89                PromptingTechnique::ChainOfThought,
90                TechniqueCategory::Reasoning,
91                "Chain-of-Thought",
92                "Require explicit step-by-step reasoning",
93                "Think step by step. Show your reasoning process clearly. ",
94                vec![
95                    TaskCharacteristic::MultiStepReasoning,
96                    TaskCharacteristic::LogicalDeduction,
97                    TaskCharacteristic::NumericalCalculation,
98                ],
99                0.0, // Always usable
100                ComplexityLevel::Simple,
101                true,
102            ),
103        );
104
105        techniques.insert(
106            PromptingTechnique::LogicOfThought,
107            TechniqueMetadata::new(
108                PromptingTechnique::LogicOfThought,
109                TechniqueCategory::Reasoning,
110                "Logic-of-Thought",
111                "Embed propositional logic for formal reasoning",
112                "Use propositional logic notation. Let P, Q, R represent propositions. Apply logical inference rules. ",
113                vec![
114                    TaskCharacteristic::LogicalDeduction,
115                    TaskCharacteristic::MultiStepReasoning,
116                ],
117                0.8, // Requires high SEAL quality
118                ComplexityLevel::Advanced,
119                true,
120            ),
121        );
122
123        techniques.insert(
124            PromptingTechnique::LeastToMost,
125            TechniqueMetadata::new(
126                PromptingTechnique::LeastToMost,
127                TechniqueCategory::Reasoning,
128                "Least-to-Most",
129                "Decompose into simpler sub-problems progressively",
130                "Break this problem into simpler sub-problems. Solve from simplest to most complex. ",
131                vec![
132                    TaskCharacteristic::MultiStepReasoning,
133                    TaskCharacteristic::AlgorithmicProblem,
134                ],
135                0.5, // Moderate complexity
136                ComplexityLevel::Moderate,
137                true,
138            ),
139        );
140
141        techniques.insert(
142            PromptingTechnique::ThreadOfThought,
143            TechniqueMetadata::new(
144                PromptingTechnique::ThreadOfThought,
145                TechniqueCategory::Reasoning,
146                "Thread-of-Thought",
147                "Summarize long contexts progressively",
148                "Summarize the context progressively as you reason through it. Maintain a running summary. ",
149                vec![
150                    TaskCharacteristic::LongContextSummarization,
151                    TaskCharacteristic::MultiStepReasoning,
152                ],
153                0.7, // Advanced technique
154                ComplexityLevel::Advanced,
155                true,
156            ),
157        );
158
159        techniques.insert(
160            PromptingTechnique::PlanAndSolve,
161            TechniqueMetadata::new(
162                PromptingTechnique::PlanAndSolve,
163                TechniqueCategory::Reasoning,
164                "Plan-and-Solve",
165                "Generate execution plan first, then solve step by step",
166                "First, devise a plan. Then, solve the problem step by step according to the plan. ",
167                vec![
168                    TaskCharacteristic::MultiStepReasoning,
169                    TaskCharacteristic::LogicalDeduction,
170                    TaskCharacteristic::AlgorithmicProblem,
171                ],
172                0.5, // Moderate complexity
173                ComplexityLevel::Moderate,
174                true,
175            ),
176        );
177
178        techniques.insert(
179            PromptingTechnique::SkeletonOfThought,
180            TechniqueMetadata::new(
181                PromptingTechnique::SkeletonOfThought,
182                TechniqueCategory::Reasoning,
183                "Skeleton-of-Thought",
184                "Generate skeleton, then fill details",
185                "First, generate a skeleton outline. Then, fill in the details for each part. ",
186                vec![
187                    TaskCharacteristic::CreativeGeneration,
188                    TaskCharacteristic::CodeGeneration,
189                ],
190                0.7, // Advanced technique
191                ComplexityLevel::Advanced,
192                true,
193            ),
194        );
195
196        techniques.insert(
197            PromptingTechnique::ScratchpadPrompting,
198            TechniqueMetadata::new(
199                PromptingTechnique::ScratchpadPrompting,
200                TechniqueCategory::Reasoning,
201                "Scratchpad Prompting",
202                "Provide draft space for intermediate steps",
203                "Use the following scratchpad format for intermediate calculations:\n\
204                <scratchpad>\n\
205                [Your work here]\n\
206                </scratchpad>\n",
207                vec![
208                    TaskCharacteristic::NumericalCalculation,
209                    TaskCharacteristic::AlgorithmicProblem,
210                ],
211                0.0,
212                ComplexityLevel::Simple,
213                true,
214            ),
215        );
216
217        // === Others (6 techniques) ===
218        techniques.insert(
219            PromptingTechnique::DecomposedPrompting,
220            TechniqueMetadata::new(
221                PromptingTechnique::DecomposedPrompting,
222                TechniqueCategory::Others,
223                "Decomposed Prompting",
224                "Break into sub-tasks explicitly",
225                "Decompose this task into independent sub-tasks. Solve each sub-task separately. ",
226                vec![
227                    TaskCharacteristic::MultiStepReasoning,
228                    TaskCharacteristic::AlgorithmicProblem,
229                ],
230                0.5,
231                ComplexityLevel::Moderate,
232                true,
233            ),
234        );
235
236        techniques.insert(
237            PromptingTechnique::IgnoreIrrelevantConditions,
238            TechniqueMetadata::new(
239                PromptingTechnique::IgnoreIrrelevantConditions,
240                TechniqueCategory::Others,
241                "Ignore Irrelevant Conditions",
242                "Detect and disregard noise in the problem",
243                "Identify and ignore any irrelevant information. Focus only on what's essential. ",
244                vec![
245                    TaskCharacteristic::LogicalDeduction,
246                    TaskCharacteristic::MultiStepReasoning,
247                ],
248                0.6,
249                ComplexityLevel::Moderate,
250                true,
251            ),
252        );
253
254        techniques.insert(
255            PromptingTechnique::HighlightedCoT,
256            TechniqueMetadata::new(
257                PromptingTechnique::HighlightedCoT,
258                TechniqueCategory::Others,
259                "Highlighted CoT",
260                "Highlight essential information before reasoning",
261                "First, highlight the essential information. Then, reason step by step based on the highlights. ",
262                vec![
263                    TaskCharacteristic::MultiStepReasoning,
264                    TaskCharacteristic::LogicalDeduction,
265                ],
266                0.5,
267                ComplexityLevel::Moderate,
268                true,
269            ),
270        );
271
272        techniques.insert(
273            PromptingTechnique::SkillsInContext,
274            TechniqueMetadata::new(
275                PromptingTechnique::SkillsInContext,
276                TechniqueCategory::Others,
277                "Skills-in-Context",
278                "Compose basic skills for complex tasks",
279                "Identify the basic skills required. Compose them systematically to solve the task. ",
280                vec![
281                    TaskCharacteristic::AlgorithmicProblem,
282                    TaskCharacteristic::CodeGeneration,
283                ],
284                0.7,
285                ComplexityLevel::Advanced,
286                true,
287            ),
288        );
289
290        techniques.insert(
291            PromptingTechnique::AutomaticInformationFiltering,
292            TechniqueMetadata::new(
293                PromptingTechnique::AutomaticInformationFiltering,
294                TechniqueCategory::Others,
295                "Automatic Information Filtering",
296                "Preprocess to remove irrelevant information",
297                "Filter the input to retain only relevant information before processing. ",
298                vec![
299                    TaskCharacteristic::LongContextSummarization,
300                    TaskCharacteristic::LogicalDeduction,
301                ],
302                0.6,
303                ComplexityLevel::Moderate,
304                true,
305            ),
306        );
307
308        Self {
309            techniques,
310            bks_cache: None,
311        }
312    }
313
314    /// Set BKS cache for querying shared technique effectiveness
315    pub fn with_bks(mut self, bks_cache: Arc<Mutex<BehavioralKnowledgeCache>>) -> Self {
316        self.bks_cache = Some(bks_cache);
317        self
318    }
319
320    /// Get technique metadata by enum
321    pub fn get(&self, technique: &PromptingTechnique) -> Option<&TechniqueMetadata> {
322        self.techniques.get(technique)
323    }
324
325    /// Get all techniques
326    pub fn get_all(&self) -> Vec<&TechniqueMetadata> {
327        self.techniques.values().collect()
328    }
329
330    /// Get techniques filtered by SEAL quality score
331    pub fn get_by_seal_quality(&self, seal_quality: f32) -> Vec<&TechniqueMetadata> {
332        self.techniques
333            .values()
334            .filter(|t| t.min_seal_quality <= seal_quality)
335            .collect()
336    }
337
338    /// Get techniques by category
339    pub fn get_by_category(&self, category: TechniqueCategory) -> Vec<&TechniqueMetadata> {
340        self.techniques
341            .values()
342            .filter(|t| t.category == category)
343            .collect()
344    }
345
346    /// Query BKS for technique effectiveness in a specific cluster
347    ///
348    /// Returns techniques that have been successfully promoted to BKS for this cluster,
349    /// indicating they work well based on collective user experience.
350    pub async fn get_bks_recommended_techniques(
351        &self,
352        cluster_id: &str,
353    ) -> Result<Vec<PromptingTechnique>> {
354        if let Some(ref bks_cache) = self.bks_cache {
355            let bks = bks_cache.lock().await;
356
357            // Query BKS for truths matching the cluster context
358            // Example: "For numerical_reasoning, ChainOfThought achieves 92% success"
359            let truths = bks.get_matching_truths(cluster_id);
360
361            let mut recommended = Vec::new();
362            for truth in truths {
363                // Parse technique from truth rule/rationale
364                if let Some(technique) = self.parse_technique_from_truth(truth) {
365                    recommended.push(technique);
366                }
367            }
368
369            Ok(recommended)
370        } else {
371            Ok(Vec::new())
372        }
373    }
374
375    /// Parse technique enum from BKS truth rule/rationale
376    fn parse_technique_from_truth(&self, truth: &BehavioralTruth) -> Option<PromptingTechnique> {
377        // Example rule: "Use ChainOfThought for numerical reasoning"
378        // Example rationale: "ChainOfThought achieves 92% success rate"
379        let text = format!("{} {}", truth.rule, truth.rationale);
380
381        for (technique_enum, metadata) in &self.techniques {
382            // Check if technique name appears in the truth text
383            if text.contains(&metadata.name) || text.contains(technique_enum.to_str()) {
384                return Some(technique_enum.clone());
385            }
386        }
387
388        None
389    }
390
391    /// Get count of techniques by complexity level
392    pub fn count_by_complexity(&self, level: ComplexityLevel) -> usize {
393        self.techniques
394            .values()
395            .filter(|t| t.complexity_level == level)
396            .count()
397    }
398}
399
400impl Default for TechniqueLibrary {
401    fn default() -> Self {
402        Self::new()
403    }
404}
405
406#[cfg(test)]
407mod tests {
408    use super::*;
409
410    #[test]
411    fn test_library_contains_all_15_techniques() {
412        let library = TechniqueLibrary::new();
413        assert_eq!(library.techniques.len(), 15);
414    }
415
416    #[test]
417    fn test_library_categories() {
418        let library = TechniqueLibrary::new();
419
420        assert_eq!(
421            library
422                .get_by_category(TechniqueCategory::RoleAssignment)
423                .len(),
424            1
425        );
426        assert_eq!(
427            library
428                .get_by_category(TechniqueCategory::EmotionalStimulus)
429                .len(),
430            2
431        );
432        assert_eq!(
433            library.get_by_category(TechniqueCategory::Reasoning).len(),
434            7
435        );
436        assert_eq!(library.get_by_category(TechniqueCategory::Others).len(), 5);
437    }
438
439    #[test]
440    fn test_seal_quality_filtering() {
441        let library = TechniqueLibrary::new();
442
443        // Low quality (0.3) → only simple techniques
444        let low_quality = library.get_by_seal_quality(0.3);
445        assert!(low_quality.iter().all(|t| t.min_seal_quality <= 0.3));
446
447        // High quality (0.9) → all techniques available
448        let high_quality = library.get_by_seal_quality(0.9);
449        assert_eq!(high_quality.len(), 15); // All techniques pass
450    }
451
452    #[test]
453    fn test_technique_string_conversion() {
454        assert_eq!(
455            PromptingTechnique::parse_id("chain_of_thought").unwrap(),
456            PromptingTechnique::ChainOfThought
457        );
458        assert_eq!(
459            PromptingTechnique::parse_id("CoT").unwrap(),
460            PromptingTechnique::ChainOfThought
461        );
462        assert_eq!(
463            PromptingTechnique::ChainOfThought.to_str(),
464            "chain_of_thought"
465        );
466    }
467}