Class: SmartPrompt::RelevanceBasedStrategy

Inherits:
Object
  • Object
show all
Includes:
ContextStrategy
Defined in:
lib/smart_prompt/relevance_based_strategy.rb

Overview

RelevanceBasedStrategy implements a context selection strategy based on semantic relevance and importance scoring

This strategy:

  • Calculates importance scores combining recency and relevance

  • Selects top-k most important messages

  • Supports both keyword-based and embedding-based similarity

  • Maintains temporal ordering of selected messages

  • Trims to token limits while preserving important context

Instance Method Summary collapse

Constructor Details

#initialize(config = {}) ⇒ RelevanceBasedStrategy

Initialize the relevance-based strategy

Parameters:

  • config (Hash) (defaults to: {})

    Configuration options

Options Hash (config):

  • :top_k (Integer) — default: 10

    Number of top messages to select

  • :recency_weight (Float) — default: 0.3

    Weight for recency in scoring (0.0-1.0)

  • :relevance_weight (Float) — default: 0.7

    Weight for relevance in scoring (0.0-1.0)

  • :embedding_service (Object) — default: nil

    Optional embedding service for semantic similarity



22
23
24
25
26
27
# File 'lib/smart_prompt/relevance_based_strategy.rb', line 22

def initialize(config = {})
  @top_k = config[:top_k] || 10
  @recency_weight = config[:recency_weight] || 0.3
  @relevance_weight = config[:relevance_weight] || 0.7
  @embedding_service = config[:embedding_service]
end

Instance Method Details

#select_messages(messages, max_tokens, current_message = nil) ⇒ Array<Message>

Select messages based on relevance and importance

Parameters:

  • messages (Array<Message>)

    All messages in the session

  • max_tokens (Integer, nil)

    Maximum token limit for selected messages

  • current_message (Message, nil) (defaults to: nil)

    The current message for relevance calculation

Returns:

  • (Array<Message>)

    Selected messages ordered by timestamp



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
# File 'lib/smart_prompt/relevance_based_strategy.rb', line 34

def select_messages(messages, max_tokens, current_message = nil)
  return [] if messages.nil? || messages.empty?
  
  # If no current message, fall back to recency-only selection
  unless current_message
    log_debug "No current message provided, falling back to recency-based selection"
    return select_by_recency(messages, max_tokens)
  end

  # Calculate importance score for each message
  scored_messages = messages.map.with_index do |msg, idx|
    score = calculate_score(msg, idx, messages.length, current_message)
    [msg, score]
  end

  # Log top scores for debugging
  top_scores = scored_messages.sort_by { |_, score| -score }.take(5).map { |_, s| s.round(3) }
  log_debug "RelevanceBasedStrategy: calculated scores for #{messages.count} messages, top 5 scores: #{top_scores.inspect}"

  # Sort by score (descending) and take top-k
  selected = scored_messages
    .sort_by { |_, score| -score }
    .take(@top_k)
    .map(&:first)

  log_debug "RelevanceBasedStrategy: selected top #{selected.count}/#{messages.count} messages by importance (recency_weight=#{@recency_weight}, relevance_weight=#{@relevance_weight})"

  # Re-order by timestamp to maintain conversation flow
  selected = selected.sort_by(&:timestamp)

  # Trim to token limit if specified
  result = max_tokens ? trim_to_token_limit(selected, max_tokens) : selected
  
  if max_tokens && result.count < selected.count
    tokens_before = selected.sum { |m| m.token_count || 0 }
    tokens_after = result.sum { |m| m.token_count || 0 }
    log_debug "RelevanceBasedStrategy: trimmed to token limit #{max_tokens}: #{selected.count} -> #{result.count} messages, #{tokens_before} -> #{tokens_after} tokens"
  end
  
  result
end

#should_compress?(session) ⇒ Boolean

Determine if compression should be triggered Recommends compression when message count exceeds 3x top_k

Parameters:

  • session (Session)

    The session to evaluate

Returns:

  • (Boolean)

    true if message count > 3 * top_k



80
81
82
# File 'lib/smart_prompt/relevance_based_strategy.rb', line 80

def should_compress?(session)
  session.message_count > @top_k * 3
end