Skip to main content

brainwires_cognition/prompting/
techniques.rs

1//! Prompting Technique Definitions
2//!
3//! This module defines the 15 prompting techniques from the paper
4//! "Adaptive Selection of Prompting Techniques" (arXiv:2510.18162),
5//! with SEAL quality integration for intelligent technique filtering.
6
7use serde::{Deserialize, Serialize};
8
9/// Prompting technique categories from the paper
10#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
11pub enum TechniqueCategory {
12    /// Role assignment (e.g., "You are an expert...")
13    RoleAssignment,
14    /// Emotional stimulus (e.g., "This is important...")
15    EmotionalStimulus,
16    /// Reasoning techniques (e.g., Chain-of-Thought)
17    Reasoning,
18    /// Supporting techniques (e.g., Scratchpad)
19    Others,
20}
21
22/// 15 prompting techniques from the paper (Table 1)
23#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
24pub enum PromptingTechnique {
25    /// Role-playing persona assignment.
26    RolePlaying,
27
28    /// Emotion-based prompting stimulus.
29    EmotionPrompting,
30    /// Stress / urgency-based prompting stimulus.
31    StressPrompting,
32
33    /// Chain-of-thought reasoning.
34    ChainOfThought,
35    /// Logic-of-thought structured reasoning.
36    LogicOfThought,
37    /// Least-to-most decomposition.
38    LeastToMost,
39    /// Thread-of-thought sequential reasoning.
40    ThreadOfThought,
41    /// Plan-and-solve two-stage reasoning.
42    PlanAndSolve,
43    /// Skeleton-of-thought parallel generation.
44    SkeletonOfThought,
45    /// Scratchpad-based working memory.
46    ScratchpadPrompting,
47
48    /// Decomposed multi-step prompting.
49    DecomposedPrompting,
50    /// Ignore irrelevant conditions filtering.
51    IgnoreIrrelevantConditions,
52    /// Highlighted chain-of-thought.
53    HighlightedCoT,
54    /// Skills-in-context grounding.
55    SkillsInContext,
56    /// Automatic information filtering.
57    AutomaticInformationFiltering,
58}
59
60impl PromptingTechnique {
61    /// Parse technique from string ID
62    pub fn parse_id(s: &str) -> Result<Self, &'static str> {
63        match s.to_lowercase().as_str() {
64            "role_playing" | "roleplaying" => Ok(Self::RolePlaying),
65            "emotion_prompting" | "emotionprompting" => Ok(Self::EmotionPrompting),
66            "stress_prompting" | "stressprompting" => Ok(Self::StressPrompting),
67            "chain_of_thought" | "chainofthought" | "cot" => Ok(Self::ChainOfThought),
68            "logic_of_thought" | "logicofthought" | "lot" => Ok(Self::LogicOfThought),
69            "least_to_most" | "leasttomost" => Ok(Self::LeastToMost),
70            "thread_of_thought" | "threadofthought" | "tot" => Ok(Self::ThreadOfThought),
71            "plan_and_solve" | "planandsolve" => Ok(Self::PlanAndSolve),
72            "skeleton_of_thought" | "skeletonofthought" | "sot" => Ok(Self::SkeletonOfThought),
73            "scratchpad_prompting" | "scratchpadprompting" | "scratchpad" => {
74                Ok(Self::ScratchpadPrompting)
75            }
76            "decomposed_prompting" | "decomposedprompting" => Ok(Self::DecomposedPrompting),
77            "ignore_irrelevant_conditions" | "ignoreirrelevantconditions" => {
78                Ok(Self::IgnoreIrrelevantConditions)
79            }
80            "highlighted_cot" | "highlightedcot" => Ok(Self::HighlightedCoT),
81            "skills_in_context" | "skillsincontext" => Ok(Self::SkillsInContext),
82            "automatic_information_filtering" | "automaticinformationfiltering" => {
83                Ok(Self::AutomaticInformationFiltering)
84            }
85            _ => Err("Unknown technique"),
86        }
87    }
88
89    /// Convert technique to string ID
90    pub fn to_str(&self) -> &'static str {
91        match self {
92            Self::RolePlaying => "role_playing",
93            Self::EmotionPrompting => "emotion_prompting",
94            Self::StressPrompting => "stress_prompting",
95            Self::ChainOfThought => "chain_of_thought",
96            Self::LogicOfThought => "logic_of_thought",
97            Self::LeastToMost => "least_to_most",
98            Self::ThreadOfThought => "thread_of_thought",
99            Self::PlanAndSolve => "plan_and_solve",
100            Self::SkeletonOfThought => "skeleton_of_thought",
101            Self::ScratchpadPrompting => "scratchpad_prompting",
102            Self::DecomposedPrompting => "decomposed_prompting",
103            Self::IgnoreIrrelevantConditions => "ignore_irrelevant_conditions",
104            Self::HighlightedCoT => "highlighted_cot",
105            Self::SkillsInContext => "skills_in_context",
106            Self::AutomaticInformationFiltering => "automatic_information_filtering",
107        }
108    }
109}
110
111/// Complexity level for SEAL quality filtering
112#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
113pub enum ComplexityLevel {
114    /// Use when SEAL quality < 0.5 (simple, basic techniques)
115    Simple,
116    /// Use when SEAL quality 0.5-0.8 (moderate complexity)
117    Moderate,
118    /// Use when SEAL quality > 0.8 (advanced, sophisticated techniques)
119    Advanced,
120}
121
122/// Task characteristics for technique matching
123#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
124pub enum TaskCharacteristic {
125    /// Requires multi-step reasoning chains.
126    MultiStepReasoning,
127    /// Involves numerical calculations.
128    NumericalCalculation,
129    /// Requires logical deduction.
130    LogicalDeduction,
131    /// Creative or open-ended generation.
132    CreativeGeneration,
133    /// Summarization of long context.
134    LongContextSummarization,
135    /// Spatial reasoning tasks.
136    SpatialReasoning,
137    /// Visual understanding tasks.
138    VisualUnderstanding,
139    /// Code generation tasks.
140    CodeGeneration,
141    /// Algorithmic problem solving.
142    AlgorithmicProblem,
143}
144
145/// Metadata for each technique (SEAL-enhanced)
146#[derive(Debug, Clone)]
147pub struct TechniqueMetadata {
148    /// The prompting technique this metadata describes.
149    pub technique: PromptingTechnique,
150    /// Category of the technique.
151    pub category: TechniqueCategory,
152    /// Human-readable name.
153    pub name: String,
154    /// Description of the technique.
155    pub description: String,
156    /// Template string for generating prompts.
157    pub template: String,
158    /// Task characteristics this technique works best for.
159    pub best_for: Vec<TaskCharacteristic>,
160
161    // SEAL integration
162    /// Minimum SEAL quality to use this technique (0.0-1.0)
163    pub min_seal_quality: f32,
164    /// Complexity level for filtering
165    pub complexity_level: ComplexityLevel,
166    /// Can this technique be promoted to BKS?
167    pub bks_promotion_eligible: bool,
168}
169
170impl TechniqueMetadata {
171    /// Create new technique metadata
172    #[allow(clippy::too_many_arguments)]
173    pub fn new(
174        technique: PromptingTechnique,
175        category: TechniqueCategory,
176        name: impl Into<String>,
177        description: impl Into<String>,
178        template: impl Into<String>,
179        best_for: Vec<TaskCharacteristic>,
180        min_seal_quality: f32,
181        complexity_level: ComplexityLevel,
182        bks_promotion_eligible: bool,
183    ) -> Self {
184        Self {
185            technique,
186            category,
187            name: name.into(),
188            description: description.into(),
189            template: template.into(),
190            best_for,
191            min_seal_quality,
192            complexity_level,
193            bks_promotion_eligible,
194        }
195    }
196}
197
198#[cfg(test)]
199mod tests {
200    use super::*;
201
202    #[test]
203    fn test_technique_enum_all_variants() {
204        // Ensure all 15 techniques can be created
205        let techniques = vec![
206            PromptingTechnique::RolePlaying,
207            PromptingTechnique::EmotionPrompting,
208            PromptingTechnique::StressPrompting,
209            PromptingTechnique::ChainOfThought,
210            PromptingTechnique::LogicOfThought,
211            PromptingTechnique::LeastToMost,
212            PromptingTechnique::ThreadOfThought,
213            PromptingTechnique::PlanAndSolve,
214            PromptingTechnique::SkeletonOfThought,
215            PromptingTechnique::ScratchpadPrompting,
216            PromptingTechnique::DecomposedPrompting,
217            PromptingTechnique::IgnoreIrrelevantConditions,
218            PromptingTechnique::HighlightedCoT,
219            PromptingTechnique::SkillsInContext,
220            PromptingTechnique::AutomaticInformationFiltering,
221        ];
222        assert_eq!(techniques.len(), 15);
223    }
224
225    #[test]
226    fn test_technique_category_variants() {
227        let categories = vec![
228            TechniqueCategory::RoleAssignment,
229            TechniqueCategory::EmotionalStimulus,
230            TechniqueCategory::Reasoning,
231            TechniqueCategory::Others,
232        ];
233        assert_eq!(categories.len(), 4);
234    }
235
236    #[test]
237    fn test_complexity_level_ordering() {
238        // Test complexity levels
239        let simple = ComplexityLevel::Simple;
240        let moderate = ComplexityLevel::Moderate;
241        let advanced = ComplexityLevel::Advanced;
242
243        // Ensure they can be compared
244        assert_eq!(simple, ComplexityLevel::Simple);
245        assert_eq!(moderate, ComplexityLevel::Moderate);
246        assert_eq!(advanced, ComplexityLevel::Advanced);
247    }
248
249    #[test]
250    fn test_technique_string_conversion() {
251        // Test from_str and to_string
252        let technique = PromptingTechnique::ChainOfThought;
253        let serialized = serde_json::to_string(&technique).unwrap();
254        let deserialized: PromptingTechnique = serde_json::from_str(&serialized).unwrap();
255        assert_eq!(technique, deserialized);
256    }
257
258    #[test]
259    fn test_technique_metadata_creation() {
260        let metadata = TechniqueMetadata::new(
261            PromptingTechnique::ChainOfThought,
262            TechniqueCategory::Reasoning,
263            "Chain-of-Thought",
264            "Step-by-step reasoning",
265            "Think step by step",
266            vec![TaskCharacteristic::MultiStepReasoning],
267            0.0,
268            ComplexityLevel::Simple,
269            true,
270        );
271
272        assert_eq!(metadata.technique, PromptingTechnique::ChainOfThought);
273        assert_eq!(metadata.category, TechniqueCategory::Reasoning);
274        assert_eq!(metadata.name, "Chain-of-Thought");
275        assert_eq!(metadata.min_seal_quality, 0.0);
276        assert_eq!(metadata.complexity_level, ComplexityLevel::Simple);
277        assert!(metadata.bks_promotion_eligible);
278    }
279
280    #[test]
281    fn test_task_characteristic_variants() {
282        let characteristics = vec![
283            TaskCharacteristic::MultiStepReasoning,
284            TaskCharacteristic::NumericalCalculation,
285            TaskCharacteristic::LogicalDeduction,
286            TaskCharacteristic::CreativeGeneration,
287            TaskCharacteristic::LongContextSummarization,
288            TaskCharacteristic::SpatialReasoning,
289            TaskCharacteristic::VisualUnderstanding,
290        ];
291        assert_eq!(characteristics.len(), 7);
292    }
293}