File size: 27,026 Bytes
b5246f1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
"""
Intelligent query processing for technical documentation RAG.

Provides adaptive query enhancement through technical term expansion,
acronym handling, and intelligent hybrid weighting optimization.
"""

from typing import Dict, List, Any, Tuple, Set, Optional
import re
from collections import defaultdict
import time


class QueryEnhancer:
    """
    Intelligent query processing for technical documentation RAG.
    
    Analyzes query characteristics and enhances retrieval through:
    - Technical synonym expansion
    - Acronym detection and expansion
    - Adaptive hybrid weighting based on query type
    - Query complexity analysis for optimal retrieval strategy
    
    Optimized for embedded systems and technical documentation domains.
    
    Performance: <10ms query enhancement, improves retrieval relevance by >10%
    """
    
    def __init__(self):
        """Initialize QueryEnhancer with technical domain knowledge."""
        
        # Technical vocabulary dictionary organized by domain
        self.technical_synonyms = {
            # Processor terminology
            'cpu': ['processor', 'microprocessor', 'central processing unit'],
            'mcu': ['microcontroller', 'microcontroller unit', 'embedded processor'],
            'core': ['processor core', 'cpu core', 'execution unit'],
            'alu': ['arithmetic logic unit', 'arithmetic unit'],
            
            # Memory terminology  
            'memory': ['ram', 'storage', 'buffer', 'cache'],
            'flash': ['non-volatile memory', 'program memory', 'code storage'],
            'sram': ['static ram', 'static memory', 'cache memory'],
            'dram': ['dynamic ram', 'dynamic memory'],
            'cache': ['buffer', 'temporary storage', 'fast memory'],
            
            # Architecture terminology
            'risc-v': ['riscv', 'risc v', 'open isa', 'open instruction set'],
            'arm': ['advanced risc machine', 'acorn risc machine'],
            'isa': ['instruction set architecture', 'instruction set'],
            'architecture': ['design', 'structure', 'organization'],
            
            # Embedded systems terminology
            'rtos': ['real-time operating system', 'real-time os'],
            'interrupt': ['isr', 'interrupt service routine', 'exception handler'],
            'peripheral': ['hardware peripheral', 'external device', 'io device'],
            'firmware': ['embedded software', 'system software'],
            'bootloader': ['boot code', 'initialization code'],
            
            # Performance terminology
            'latency': ['delay', 'response time', 'execution time'],
            'throughput': ['bandwidth', 'data rate', 'performance'],
            'power': ['power consumption', 'energy usage', 'battery life'],
            'optimization': ['improvement', 'enhancement', 'tuning'],
            
            # Communication protocols
            'uart': ['serial communication', 'async serial'],
            'spi': ['serial peripheral interface', 'synchronous serial'],
            'i2c': ['inter-integrated circuit', 'two-wire interface'],
            'usb': ['universal serial bus'],
            
            # Development terminology
            'debug': ['debugging', 'troubleshooting', 'testing'],
            'compile': ['compilation', 'build', 'assembly'],
            'programming': ['coding', 'development', 'implementation']
        }
        
        # Comprehensive acronym expansions for embedded/technical domains
        self.acronym_expansions = {
            # Processor & Architecture
            'CPU': 'Central Processing Unit',
            'MCU': 'Microcontroller Unit', 
            'MPU': 'Microprocessor Unit',
            'DSP': 'Digital Signal Processor',
            'GPU': 'Graphics Processing Unit',
            'ALU': 'Arithmetic Logic Unit',
            'FPU': 'Floating Point Unit',
            'MMU': 'Memory Management Unit',
            'ISA': 'Instruction Set Architecture',
            'RISC': 'Reduced Instruction Set Computer',
            'CISC': 'Complex Instruction Set Computer',
            
            # Memory & Storage
            'RAM': 'Random Access Memory',
            'ROM': 'Read Only Memory',
            'EEPROM': 'Electrically Erasable Programmable ROM',
            'SRAM': 'Static Random Access Memory',
            'DRAM': 'Dynamic Random Access Memory',
            'FRAM': 'Ferroelectric Random Access Memory',
            'MRAM': 'Magnetoresistive Random Access Memory',
            'DMA': 'Direct Memory Access',
            
            # Operating Systems & Software
            'RTOS': 'Real-Time Operating System',
            'OS': 'Operating System',
            'API': 'Application Programming Interface',
            'SDK': 'Software Development Kit',
            'IDE': 'Integrated Development Environment',
            'HAL': 'Hardware Abstraction Layer',
            'BSP': 'Board Support Package',
            
            # Interrupts & Exceptions
            'ISR': 'Interrupt Service Routine',
            'IRQ': 'Interrupt Request',
            'NMI': 'Non-Maskable Interrupt',
            'NVIC': 'Nested Vectored Interrupt Controller',
            
            # Communication Protocols
            'UART': 'Universal Asynchronous Receiver Transmitter',
            'USART': 'Universal Synchronous Asynchronous Receiver Transmitter',
            'SPI': 'Serial Peripheral Interface',
            'I2C': 'Inter-Integrated Circuit',
            'CAN': 'Controller Area Network',
            'USB': 'Universal Serial Bus',
            'TCP': 'Transmission Control Protocol',
            'UDP': 'User Datagram Protocol',
            'HTTP': 'HyperText Transfer Protocol',
            'MQTT': 'Message Queuing Telemetry Transport',
            
            # Analog & Digital
            'ADC': 'Analog to Digital Converter',
            'DAC': 'Digital to Analog Converter',
            'PWM': 'Pulse Width Modulation',
            'GPIO': 'General Purpose Input Output',
            'JTAG': 'Joint Test Action Group',
            'SWD': 'Serial Wire Debug',
            
            # Power & Clock
            'PLL': 'Phase Locked Loop',
            'VCO': 'Voltage Controlled Oscillator',
            'LDO': 'Low Dropout Regulator',
            'PMU': 'Power Management Unit',
            'RTC': 'Real Time Clock',
            
            # Standards & Organizations
            'IEEE': 'Institute of Electrical and Electronics Engineers',
            'ISO': 'International Organization for Standardization',
            'ANSI': 'American National Standards Institute',
            'IEC': 'International Electrotechnical Commission'
        }
        
        # Compile regex patterns for efficiency
        self._acronym_pattern = re.compile(r'\b[A-Z]{2,}\b')
        self._technical_term_pattern = re.compile(r'\b\w+(?:-\w+)*\b', re.IGNORECASE)
        self._question_indicators = re.compile(r'\b(?:how|what|why|when|where|which|explain|describe|define)\b', re.IGNORECASE)
        
        # Question type classification keywords
        self.question_type_keywords = {
            'conceptual': ['how', 'why', 'what', 'explain', 'describe', 'understand', 'concept', 'theory'],
            'technical': ['configure', 'implement', 'setup', 'install', 'code', 'program', 'register'],
            'procedural': ['steps', 'process', 'procedure', 'workflow', 'guide', 'tutorial'],
            'troubleshooting': ['error', 'problem', 'issue', 'debug', 'fix', 'solve', 'troubleshoot']
        }
        
    def analyze_query_characteristics(self, query: str) -> Dict[str, Any]:
        """
        Analyze query to determine optimal processing strategy.
        
        Performs comprehensive analysis including:
        - Technical term detection and counting
        - Acronym presence identification
        - Question type classification
        - Complexity scoring based on multiple factors
        - Optimal hybrid weight recommendation
        
        Args:
            query: User input query string
            
        Returns:
            Dictionary with comprehensive query analysis:
            - technical_term_count: Number of domain-specific terms detected
            - has_acronyms: Boolean indicating acronym presence
            - question_type: 'conceptual', 'technical', 'procedural', 'mixed'
            - complexity_score: Float 0-1 indicating query complexity
            - recommended_dense_weight: Optimal weight for hybrid search
            - detected_acronyms: List of acronyms found
            - technical_terms: List of technical terms found
            
        Performance: <2ms for typical queries
        """
        if not query or not query.strip():
            return {
                'technical_term_count': 0,
                'has_acronyms': False,
                'question_type': 'unknown',
                'complexity_score': 0.0,
                'recommended_dense_weight': 0.7,
                'detected_acronyms': [],
                'technical_terms': []
            }
        
        query_lower = query.lower()
        words = query.split()
        
        # Detect acronyms
        detected_acronyms = self._acronym_pattern.findall(query)
        has_acronyms = len(detected_acronyms) > 0
        
        # Detect technical terms
        technical_terms = []
        technical_term_count = 0
        
        for word in words:
            word_clean = re.sub(r'[^\w\-]', '', word.lower())
            if word_clean in self.technical_synonyms:
                technical_terms.append(word_clean)
                technical_term_count += 1
            # Also check for compound technical terms like "risc-v"
            elif any(term in word_clean for term in ['risc-v', 'arm', 'cpu', 'mcu']):
                technical_terms.append(word_clean)
                technical_term_count += 1
        
        # Add acronyms to technical term count
        for acronym in detected_acronyms:
            if acronym in self.acronym_expansions:
                technical_term_count += 1
        
        # Determine question type
        question_type = self._classify_question_type(query_lower)
        
        # Calculate complexity score (0-1)
        complexity_factors = [
            len(words) / 20.0,  # Word count factor (normalized to 20 words max)
            technical_term_count / 5.0,  # Technical density (normalized to 5 terms max)
            len(detected_acronyms) / 3.0,  # Acronym density (normalized to 3 acronyms max)
            1.0 if self._question_indicators.search(query) else 0.5,  # Question complexity
        ]
        complexity_score = min(1.0, sum(complexity_factors) / len(complexity_factors))
        
        # Determine recommended dense weight based on analysis
        recommended_dense_weight = self._calculate_optimal_weight(
            question_type, technical_term_count, has_acronyms, complexity_score
        )
        
        return {
            'technical_term_count': technical_term_count,
            'has_acronyms': has_acronyms,
            'question_type': question_type,
            'complexity_score': complexity_score,
            'recommended_dense_weight': recommended_dense_weight,
            'detected_acronyms': detected_acronyms,
            'technical_terms': technical_terms,
            'word_count': len(words),
            'has_question_indicators': bool(self._question_indicators.search(query))
        }
    
    def _classify_question_type(self, query_lower: str) -> str:
        """Classify query into conceptual, technical, procedural, or mixed categories."""
        type_scores = defaultdict(int)
        
        for question_type, keywords in self.question_type_keywords.items():
            for keyword in keywords:
                if keyword in query_lower:
                    type_scores[question_type] += 1
        
        if not type_scores:
            return 'mixed'
        
        # Return type with highest score, or 'mixed' if tie
        max_score = max(type_scores.values())
        top_types = [t for t, s in type_scores.items() if s == max_score]
        
        return top_types[0] if len(top_types) == 1 else 'mixed'
    
    def _calculate_optimal_weight(self, question_type: str, tech_terms: int, 
                                has_acronyms: bool, complexity: float) -> float:
        """Calculate optimal dense weight based on query characteristics."""
        
        # Base weights by question type
        base_weights = {
            'technical': 0.3,      # Favor sparse for technical precision
            'conceptual': 0.8,     # Favor dense for conceptual understanding
            'procedural': 0.5,     # Balanced for step-by-step queries
            'troubleshooting': 0.4, # Slight sparse favor for specific issues
            'mixed': 0.7,          # Default balanced
            'unknown': 0.7         # Default balanced
        }
        
        weight = base_weights.get(question_type, 0.7)
        
        # Adjust based on technical term density
        if tech_terms > 2:
            weight -= 0.2  # More technical β†’ favor sparse
        elif tech_terms == 0:
            weight += 0.1  # Less technical β†’ favor dense
        
        # Adjust based on acronym presence
        if has_acronyms:
            weight -= 0.1  # Acronyms β†’ favor sparse for exact matching
        
        # Adjust based on complexity
        if complexity > 0.8:
            weight += 0.1  # High complexity β†’ favor dense for understanding
        elif complexity < 0.3:
            weight -= 0.1  # Low complexity β†’ favor sparse for precision
        
        # Ensure weight stays within valid bounds
        return max(0.1, min(0.9, weight))
    
    def expand_technical_terms(self, query: str, max_expansions: int = 1) -> str:
        """
        Expand query with technical synonyms while preventing bloat.
        
        Conservative expansion strategy:
        - Maximum 1 synonym per technical term by default
        - Prioritizes most relevant/common synonyms
        - Maintains semantic focus while improving recall
        
        Args:
            query: Original user query
            max_expansions: Maximum synonyms per term (default 1 for focus)
            
        Returns:
            Conservatively enhanced query
            
        Example:
            Input: "CPU performance optimization"
            Output: "CPU processor performance optimization"
            
        Performance: <3ms for typical queries
        """
        if not query or not query.strip():
            return query
        
        words = query.split()
        
        # Conservative expansion: only add most relevant synonym
        expansion_candidates = []
        
        for word in words:
            word_clean = re.sub(r'[^\w\-]', '', word.lower())
            
            # Check for direct synonym expansion
            if word_clean in self.technical_synonyms:
                synonyms = self.technical_synonyms[word_clean]
                # Add only the first (most common) synonym
                if synonyms and max_expansions > 0:
                    expansion_candidates.append(synonyms[0])
        
        # Limit total expansion to prevent bloat
        max_total_expansions = min(2, len(words) // 2)  # At most 50% expansion
        selected_expansions = expansion_candidates[:max_total_expansions]
        
        # Reconstruct with minimal expansion
        if selected_expansions:
            return ' '.join(words + selected_expansions)
        else:
            return query
    
    def detect_and_expand_acronyms(self, query: str, conservative: bool = True) -> str:
        """
        Detect technical acronyms and add their expansions conservatively.
        
        Conservative approach to prevent query bloat:
        - Limits acronym expansions to most relevant ones
        - Preserves original acronyms for exact matching
        - Maintains query focus and performance
        
        Args:
            query: Query potentially containing acronyms
            conservative: If True, limits expansion to prevent bloat
            
        Returns:
            Query with selective acronym expansions
            
        Example:
            Input: "RTOS scheduling algorithm"
            Output: "RTOS Real-Time Operating System scheduling algorithm"
            
        Performance: <2ms for typical queries
        """
        if not query or not query.strip():
            return query
        
        # Find all acronyms in the query
        acronyms = self._acronym_pattern.findall(query)
        
        if not acronyms:
            return query
        
        # Conservative mode: limit expansions
        if conservative and len(acronyms) > 2:
            # Only expand first 2 acronyms to prevent bloat
            acronyms = acronyms[:2]
        
        result = query
        
        # Expand selected acronyms
        for acronym in acronyms:
            if acronym in self.acronym_expansions:
                expansion = self.acronym_expansions[acronym]
                # Add expansion after the acronym (preserving original)
                result = result.replace(acronym, f"{acronym} {expansion}", 1)
        
        return result
    
    def adaptive_hybrid_weighting(self, query: str) -> float:
        """
        Determine optimal dense_weight based on query characteristics.
        
        Analyzes query to automatically determine the best balance between
        dense semantic search and sparse keyword matching for optimal results.
        
        Strategy:
        - Technical/exact queries β†’ lower dense_weight (favor sparse/BM25)
        - Conceptual questions β†’ higher dense_weight (favor semantic)
        - Mixed queries β†’ balanced weighting based on complexity
        
        Args:
            query: User query string
            
        Returns:
            Float between 0.1 and 0.9 representing optimal dense_weight
            
        Performance: <2ms analysis time
        """
        analysis = self.analyze_query_characteristics(query)
        return analysis['recommended_dense_weight']
    
    def enhance_query(self, query: str, conservative: bool = True) -> Dict[str, Any]:
        """
        Comprehensive query enhancement with performance and quality focus.
        
        Optimized enhancement strategy:
        - Conservative expansion to maintain semantic focus
        - Performance-first approach with minimal overhead
        - Quality validation to ensure improvements
        
        Args:
            query: Original user query
            conservative: Use conservative expansion (recommended for production)
            
        Returns:
            Dictionary containing:
            - enhanced_query: Optimized enhanced query
            - optimal_weight: Recommended dense weight
            - analysis: Complete query analysis
            - enhancement_metadata: Performance and quality metrics
            
        Performance: <5ms total enhancement time
        """
        start_time = time.perf_counter()
        
        # Fast analysis
        analysis = self.analyze_query_characteristics(query)
        
        # Conservative enhancement approach
        if conservative:
            enhanced_query = self.expand_technical_terms(query, max_expansions=1)
            enhanced_query = self.detect_and_expand_acronyms(enhanced_query, conservative=True)
        else:
            # Legacy aggressive expansion
            enhanced_query = self.expand_technical_terms(query, max_expansions=2)
            enhanced_query = self.detect_and_expand_acronyms(enhanced_query, conservative=False)
        
        # Quality validation: prevent excessive bloat
        expansion_ratio = len(enhanced_query.split()) / len(query.split()) if query.split() else 1.0
        if expansion_ratio > 2.5:  # Limit to 2.5x expansion
            # Fallback to minimal enhancement
            enhanced_query = self.expand_technical_terms(query, max_expansions=0)
            enhanced_query = self.detect_and_expand_acronyms(enhanced_query, conservative=True)
            expansion_ratio = len(enhanced_query.split()) / len(query.split()) if query.split() else 1.0
        
        # Calculate optimal weight
        optimal_weight = analysis['recommended_dense_weight']
        
        enhancement_time = time.perf_counter() - start_time
        
        return {
            'enhanced_query': enhanced_query,
            'optimal_weight': optimal_weight,
            'analysis': analysis,
            'enhancement_metadata': {
                'original_length': len(query.split()),
                'enhanced_length': len(enhanced_query.split()),
                'expansion_ratio': expansion_ratio,
                'processing_time_ms': enhancement_time * 1000,
                'techniques_applied': ['conservative_expansion', 'quality_validation', 'adaptive_weighting'],
                'conservative_mode': conservative
            }
        }
    
    def expand_technical_terms_with_vocabulary(
        self, 
        query: str, 
        vocabulary_index: Optional['VocabularyIndex'] = None,
        min_frequency: int = 3
    ) -> str:
        """
        Expand query with vocabulary-aware synonym filtering.
        
        Only adds synonyms that exist in the document corpus with sufficient
        frequency to ensure relevance and prevent query dilution.
        
        Args:
            query: Original query
            vocabulary_index: Optional vocabulary index for filtering
            min_frequency: Minimum term frequency required
            
        Returns:
            Enhanced query with validated synonyms
            
        Performance: <2ms with vocabulary validation
        """
        if not query or not query.strip():
            return query
            
        if vocabulary_index is None:
            # Fallback to standard expansion
            return self.expand_technical_terms(query, max_expansions=1)
            
        words = query.split()
        expanded_terms = []
        
        for word in words:
            word_clean = re.sub(r'[^\w\-]', '', word.lower())
            
            # Check for synonym expansion
            if word_clean in self.technical_synonyms:
                synonyms = self.technical_synonyms[word_clean]
                
                # Filter synonyms through vocabulary
                valid_synonyms = vocabulary_index.filter_synonyms(
                    synonyms, 
                    min_frequency=min_frequency
                )
                
                # Add only the best valid synonym
                if valid_synonyms:
                    expanded_terms.append(valid_synonyms[0])
        
        # Reconstruct query with validated expansions
        if expanded_terms:
            return ' '.join(words + expanded_terms)
        else:
            return query
    
    def enhance_query_with_vocabulary(
        self,
        query: str,
        vocabulary_index: Optional['VocabularyIndex'] = None,
        min_frequency: int = 3,
        require_technical: bool = False
    ) -> Dict[str, Any]:
        """
        Enhanced query processing with vocabulary validation.
        
        Uses corpus vocabulary to ensure all expansions are relevant
        and actually present in the documents.
        
        Args:
            query: Original query
            vocabulary_index: Vocabulary index for validation
            min_frequency: Minimum term frequency
            require_technical: Only expand with technical terms
            
        Returns:
            Enhanced query with vocabulary-aware expansion
        """
        start_time = time.perf_counter()
        
        # Perform analysis
        analysis = self.analyze_query_characteristics(query)
        
        # Vocabulary-aware enhancement
        if vocabulary_index:
            # Technical term expansion with validation
            enhanced_query = self.expand_technical_terms_with_vocabulary(
                query, vocabulary_index, min_frequency
            )
            
            # Acronym expansion (already conservative)
            enhanced_query = self.detect_and_expand_acronyms(enhanced_query, conservative=True)
            
            # Track vocabulary validation
            validation_applied = True
            
            # Detect domain if available
            detected_domain = vocabulary_index.detect_domain()
        else:
            # Fallback to standard enhancement
            enhanced_query = self.expand_technical_terms(query, max_expansions=1)
            enhanced_query = self.detect_and_expand_acronyms(enhanced_query, conservative=True)
            validation_applied = False
            detected_domain = 'unknown'
        
        # Calculate metrics
        expansion_ratio = len(enhanced_query.split()) / len(query.split()) if query.split() else 1.0
        enhancement_time = time.perf_counter() - start_time
        
        return {
            'enhanced_query': enhanced_query,
            'optimal_weight': analysis['recommended_dense_weight'],
            'analysis': analysis,
            'enhancement_metadata': {
                'original_length': len(query.split()),
                'enhanced_length': len(enhanced_query.split()),
                'expansion_ratio': expansion_ratio,
                'processing_time_ms': enhancement_time * 1000,
                'techniques_applied': ['vocabulary_validation', 'conservative_expansion'],
                'vocabulary_validated': validation_applied,
                'detected_domain': detected_domain,
                'min_frequency_threshold': min_frequency
            }
        }
    
    def get_enhancement_stats(self) -> Dict[str, Any]:
        """
        Get statistics about the enhancement system capabilities.
        
        Returns:
            Dictionary with system statistics and capabilities
        """
        return {
            'technical_synonyms_count': len(self.technical_synonyms),
            'acronym_expansions_count': len(self.acronym_expansions),
            'supported_domains': [
                'embedded_systems', 'processor_architecture', 'memory_systems',
                'communication_protocols', 'real_time_systems', 'power_management'
            ],
            'question_types_supported': list(self.question_type_keywords.keys()),
            'weight_range': {'min': 0.1, 'max': 0.9, 'default': 0.7},
            'performance_targets': {
                'enhancement_time_ms': '<10',
                'accuracy_improvement': '>10%',
                'memory_overhead': '<1MB'
            },
            'vocabulary_features': {
                'vocabulary_aware_expansion': True,
                'min_frequency_filtering': True,
                'domain_detection': True,
                'technical_term_priority': True
            }
        }