Skip to main content
Glama
orneryd

M.I.M.I.R - Multi-agent Intelligent Memory & Insight Repository

by orneryd
kalman_adapter.go14.6 kB
// Package search - Kalman filter integration for stable search ranking. // // This file provides the KalmanAdapter that enhances the search service with: // - Similarity score smoothing: Reduce noise in vector similarity scores // - Ranking stability: Prevent results from jumping around between queries // - Trend detection: Identify documents becoming more/less relevant // - Latency prediction: Smooth query latency for better resource planning // // # Why Smooth Search Scores? // // Vector similarity scores can be noisy due to: // - Embedding model variability (same query, slightly different embeddings) // - Approximation in ANN (approximate nearest neighbor) indexes // - Edge cases where documents are equidistant from query // // Kalman filtering smooths these variations to provide: // - More consistent rankings across similar queries // - Gradual relevance transitions (not sudden jumps) // - Confidence estimates for borderline results // // # Integration Architecture // // ┌─────────────────────────────────────────────────────────────┐ // │ Kalman Search Adapter │ // ├─────────────────────────────────────────────────────────────┤ // │ ┌─────────────────┐ ┌─────────────────────────────────┐ │ // │ │ Search Service │───▶│ Kalman Filter (scores) │ │ // │ │ (raw scores) │ │ - Per-document filters │ │ // │ └────────┬────────┘ │ - Score history smoothing │ │ // │ │ └─────────────────────────────────┘ │ // │ │ │ // │ ▼ │ // │ ┌─────────────────────────────────────────────────────────┐│ // │ │ Ranking Stabilizer ││ // │ │ • Detect score ties ││ // │ │ • Apply stability boost to consistent docs ││ // │ │ • Prevent rank oscillation ││ // │ └─────────────────────────────────────────────────────────┘│ // │ │ │ // │ ▼ │ // │ ┌─────────────────────────────────────────────────────────┐│ // │ │ Latency Predictor ││ // │ │ • Smooth query latency measurements ││ // │ │ • Predict P99 latency ││ // │ │ • Resource scaling suggestions ││ // │ └─────────────────────────────────────────────────────────┘│ // └─────────────────────────────────────────────────────────────┘ // // # ELI12 (Explain Like I'm 12) // // Imagine you're searching Google for "cute cats": // // **Without Kalman:** // - Search 1: Cat A is #1, Cat B is #2 // - Search 2: Cat B is #1, Cat A is #2 (they swapped!) // - Search 3: Cat C is #1 (where did that come from?!) // // **With Kalman:** // - Kalman remembers: "Cat A has been top 3 for a while" // - When Cat B briefly gets a tiny score boost, Kalman says: // "That's probably noise. Cat A stays #1 until I see a REAL trend." // - Result: Rankings stay consistent, you find things where you expect them! // // It's like having a wise librarian who remembers "this book was popular before" // instead of reshuffling the entire library every time someone asks a question. package search import ( "context" "sync" "time" "github.com/orneryd/nornicdb/pkg/config" "github.com/orneryd/nornicdb/pkg/filter" ) // KalmanSearchConfig holds configuration for the Kalman-enhanced search adapter. type KalmanSearchConfig struct { // EnableScoreSmoothing enables Kalman filtering of similarity scores EnableScoreSmoothing bool // EnableRankingStability applies stability boost to consistent results EnableRankingStability bool // EnableLatencyPrediction tracks and predicts query latency EnableLatencyPrediction bool // SimilarityConfig for score smoothing SimilarityConfig filter.Config // LatencyConfig for latency prediction LatencyConfig filter.Config // StabilityBoost is the boost factor for consistently-ranked documents StabilityBoost float64 // StabilityWindow is how many recent queries to consider for stability StabilityWindow int // ScoreHistoryLimit is max history per document ScoreHistoryLimit int } // DefaultKalmanSearchConfig returns sensible defaults. func DefaultKalmanSearchConfig() KalmanSearchConfig { return KalmanSearchConfig{ EnableScoreSmoothing: true, EnableRankingStability: true, EnableLatencyPrediction: true, SimilarityConfig: filter.Config{ ProcessNoise: 0.05, // Scores are relatively stable MeasurementNoise: 30.0, // ANN can be noisy InitialCovariance: 20.0, VarianceScale: 8.0, }, LatencyConfig: filter.LatencyConfig(), StabilityBoost: 1.05, // 5% boost for stable docs StabilityWindow: 10, ScoreHistoryLimit: 50, } } // KalmanSearchAdapter wraps a search Service with Kalman filtering. type KalmanSearchAdapter struct { mu sync.RWMutex config KalmanSearchConfig // The underlying search service service *Service // Per-document Kalman filters for score smoothing // Key: documentID, Value: filter tracking that doc's relevance to queries docFilters map[string]*filter.Kalman // Recent rankings for stability detection recentRankings []queryRanking // Latency predictor latencyFilter *filter.KalmanVelocity // Statistics stats SearchAdapterStats } // queryRanking stores the top results from a query. type queryRanking struct { Query string Timestamp time.Time TopDocs []string // Document IDs in ranked order } // SearchAdapterStats holds adapter statistics. type SearchAdapterStats struct { TotalQueries int64 ScoresSmoothed int64 StabilityApplied int64 LatencyPredictions int64 AverageLatencyMs float64 PredictedLatencyMs float64 } // NewKalmanSearchAdapter creates a new Kalman-enhanced search adapter. // // Example: // // service := search.NewService(engine, 1024) // adapter := search.NewKalmanSearchAdapter(service, search.DefaultKalmanSearchConfig()) // // // Search with enhanced ranking // results, _ := adapter.Search(ctx, "semantic search", embedding, &SearchOptions{Limit: 10}) func NewKalmanSearchAdapter(service *Service, config KalmanSearchConfig) *KalmanSearchAdapter { return &KalmanSearchAdapter{ config: config, service: service, docFilters: make(map[string]*filter.Kalman), recentRankings: make([]queryRanking, 0, config.StabilityWindow), latencyFilter: filter.NewKalmanVelocity(filter.DefaultVelocityConfig()), } } // Search performs a Kalman-enhanced search. // // The enhancement pipeline: // 1. Execute underlying search // 2. Smooth similarity scores with Kalman filter // 3. Apply ranking stability boost // 4. Track latency for prediction // 5. Return enhanced results func (ka *KalmanSearchAdapter) Search(ctx context.Context, query string, embedding []float32, opts *SearchOptions) (*SearchResponse, error) { start := time.Now() // Execute underlying search response, err := ka.service.Search(ctx, query, embedding, opts) if err != nil { return nil, err } // Track latency latencyMs := float64(time.Since(start).Milliseconds()) ka.mu.Lock() defer ka.mu.Unlock() ka.stats.TotalQueries++ // Update latency prediction if ka.config.EnableLatencyPrediction { result := ka.latencyFilter.ProcessIfEnabled(config.FeatureKalmanLatency, latencyMs) if result.WasFiltered { ka.stats.LatencyPredictions++ } ka.stats.AverageLatencyMs = ka.latencyFilter.State() ka.stats.PredictedLatencyMs = ka.latencyFilter.Predict(10) } // Enhance results enhancedResults := make([]SearchResult, 0, len(response.Results)) for _, result := range response.Results { enhanced := ka.enhanceResult(result, query) enhancedResults = append(enhancedResults, enhanced) } // Apply ranking stability if ka.config.EnableRankingStability { enhancedResults = ka.applyRankingStability(enhancedResults, query) } // Re-sort by enhanced score ka.sortByScore(enhancedResults) // Record this ranking for future stability ka.recordRanking(query, enhancedResults) response.Results = enhancedResults return response, nil } // enhanceResult applies Kalman smoothing to a single result. func (ka *KalmanSearchAdapter) enhanceResult(result SearchResult, query string) SearchResult { if !ka.config.EnableScoreSmoothing { return result } // Get or create filter for this document docFilter, exists := ka.docFilters[result.ID] if !exists { docFilter = filter.NewKalman(ka.config.SimilarityConfig) ka.docFilters[result.ID] = docFilter } // Smooth the similarity score rawScore := result.Score filtered := docFilter.ProcessIfEnabled(config.FeatureKalmanSimilarity, rawScore, 1.0) if filtered.WasFiltered { result.Score = filtered.Filtered ka.stats.ScoresSmoothed++ } return result } // applyRankingStability boosts documents that have been consistently ranked high. func (ka *KalmanSearchAdapter) applyRankingStability(results []SearchResult, query string) []SearchResult { if len(ka.recentRankings) == 0 { return results } // Count how often each doc appeared in top positions docAppearances := make(map[string]int) docPositions := make(map[string][]int) for _, ranking := range ka.recentRankings { for pos, docID := range ranking.TopDocs { docAppearances[docID]++ docPositions[docID] = append(docPositions[docID], pos) } } // Apply stability boost for i, result := range results { appearances := docAppearances[result.ID] if appearances >= 2 { // Appeared in at least 2 recent queries // Calculate average position positions := docPositions[result.ID] avgPos := float64(0) for _, p := range positions { avgPos += float64(p) } avgPos /= float64(len(positions)) // Boost more for consistently high-ranked docs if avgPos < 5 { // Top 5 average results[i].Score *= ka.config.StabilityBoost ka.stats.StabilityApplied++ } } } return results } // recordRanking stores the current ranking for future stability checks. func (ka *KalmanSearchAdapter) recordRanking(query string, results []SearchResult) { topDocs := make([]string, 0, min(10, len(results))) for i := 0; i < len(results) && i < 10; i++ { topDocs = append(topDocs, results[i].ID) } ranking := queryRanking{ Query: query, Timestamp: time.Now(), TopDocs: topDocs, } ka.recentRankings = append(ka.recentRankings, ranking) // Trim to window size if len(ka.recentRankings) > ka.config.StabilityWindow { ka.recentRankings = ka.recentRankings[1:] } } // sortByScore sorts results by score (highest first). func (ka *KalmanSearchAdapter) sortByScore(results []SearchResult) { for i := 0; i < len(results)-1; i++ { for j := i + 1; j < len(results); j++ { if results[j].Score > results[i].Score { results[i], results[j] = results[j], results[i] } } } } // GetPredictedLatency returns the predicted latency for the next query. func (ka *KalmanSearchAdapter) GetPredictedLatency(stepsAhead int) float64 { ka.mu.RLock() defer ka.mu.RUnlock() return ka.latencyFilter.Predict(stepsAhead) } // GetLatencyTrend returns the current latency velocity (positive = getting slower). func (ka *KalmanSearchAdapter) GetLatencyTrend() float64 { ka.mu.RLock() defer ka.mu.RUnlock() return ka.latencyFilter.Velocity() } // GetDocumentRelevanceTrend returns whether a document is becoming more or less relevant. // // Returns: // - positive velocity: document is becoming more relevant (appearing higher) // - negative velocity: document is becoming less relevant (appearing lower) // - zero: stable relevance func (ka *KalmanSearchAdapter) GetDocumentRelevanceTrend(docID string) float64 { ka.mu.RLock() defer ka.mu.RUnlock() if docFilter, exists := ka.docFilters[docID]; exists { return docFilter.Velocity() } return 0 } // GetRisingDocuments returns documents whose relevance is increasing. func (ka *KalmanSearchAdapter) GetRisingDocuments(minVelocity float64) []string { ka.mu.RLock() defer ka.mu.RUnlock() var rising []string for docID, docFilter := range ka.docFilters { if docFilter.Velocity() >= minVelocity { rising = append(rising, docID) } } return rising } // GetFallingDocuments returns documents whose relevance is decreasing. func (ka *KalmanSearchAdapter) GetFallingDocuments(maxVelocity float64) []string { ka.mu.RLock() defer ka.mu.RUnlock() var falling []string for docID, docFilter := range ka.docFilters { if docFilter.Velocity() <= maxVelocity { falling = append(falling, docID) } } return falling } // GetStats returns adapter statistics. func (ka *KalmanSearchAdapter) GetStats() SearchAdapterStats { ka.mu.RLock() defer ka.mu.RUnlock() return ka.stats } // GetService returns the underlying search service. func (ka *KalmanSearchAdapter) GetService() *Service { return ka.service } // Reset clears all cached data and filters. func (ka *KalmanSearchAdapter) Reset() { ka.mu.Lock() defer ka.mu.Unlock() ka.docFilters = make(map[string]*filter.Kalman) ka.recentRankings = ka.recentRankings[:0] ka.latencyFilter = filter.NewKalmanVelocity(filter.DefaultVelocityConfig()) ka.stats = SearchAdapterStats{} }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orneryd/Mimir'

If you have feedback or need assistance with the MCP directory API, please join our Discord server