Class: SemanticCache::Cache

Inherits:
Object
  • Object
show all
Defined in:
lib/semantic_cache/cache.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(similarity_threshold: nil, embedding_model: nil, store: nil, store_options: {}, default_ttl: nil, namespace: nil, track_costs: nil, max_size: nil) ⇒ Cache

Returns a new instance of Cache.



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
# File 'lib/semantic_cache/cache.rb', line 9

def initialize(
  similarity_threshold: nil,
  embedding_model: nil,
  store: nil,
  store_options: {},
  default_ttl: nil,
  namespace: nil,
  track_costs: nil,
  max_size: nil
)
  config = SemanticCache.configuration

  @threshold = similarity_threshold || config.similarity_threshold
  @default_ttl = default_ttl || config.default_ttl
  @track_costs = track_costs.nil? ? config.track_costs : track_costs
  @namespace = namespace || config.namespace
  @max_size = max_size || config.max_cache_size

  @embedding = Embedding.new(
    model: embedding_model || config.embedding_model,
    api_key: config.openai_api_key
  )

  @store = build_store(store || config.store, store_options.empty? ? config.store_options : store_options)
  @stats = Stats.new
end

Instance Attribute Details

#statsObject (readonly)

Returns the value of attribute stats.



7
8
9
# File 'lib/semantic_cache/cache.rb', line 7

def stats
  @stats
end

Instance Method Details

#clearObject

Clear all cached entries.



111
112
113
114
# File 'lib/semantic_cache/cache.rb', line 111

def clear
  @store.clear
  @stats.reset!
end

#current_statsObject

Return current cache statistics as a Hash.



117
118
119
# File 'lib/semantic_cache/cache.rb', line 117

def current_stats
  @stats.to_h
end

#detailed_statsObject

Return a formatted stats report string.



122
123
124
# File 'lib/semantic_cache/cache.rb', line 122

def detailed_stats
  @stats.report
end

#fetch(query, ttl: nil, tags: [], model: nil, metadata: {}, &block) ⇒ Object

Fetch a cached response or execute the block and cache the result.

cache.fetch("What is Ruby?") do
openai.chat(messages: [{ role: "user", content: "What is Ruby?" }])
end

Options:

ttl:   - Time-to-live in seconds (overrides default)
tags:  - Array of tags for grouped invalidation
model: - Model name for cost tracking

Raises:



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
# File 'lib/semantic_cache/cache.rb', line 46

def fetch(query, ttl: nil, tags: [], model: nil, metadata: {}, &block)
  raise ArgumentError, "A block is required" unless block_given?
  validate_query!(query)

  start_time = Time.now

  # Generate embedding for the query
  query_embedding = @embedding.generate(query)

  # Search for a semantically similar cached entry
  match = find_similar(query_embedding)

  if match
    elapsed = ((Time.now - start_time) * 1000).round(2)
    saved_cost = estimate_cost(model)
    @stats.record_hit(saved_cost: saved_cost, response_time: elapsed)
    return match.response
  end

  # Cache miss — execute the block
  response = block.call

  elapsed = ((Time.now - start_time) * 1000).round(2)
  @stats.record_miss(response_time: elapsed)

  # Store the new entry
  entry = Entry.new(
    query: query,
    embedding: query_embedding,
    response: response,
    model: model,
    tags: Array(tags),
    ttl: ttl || @default_ttl,
    metadata: 
  )

  key = generate_key(query)
  @store.write(key, entry)

  response
end

#fetch_anthropic(query, model: "claude-sonnet-4-20250514", **options, &block) ⇒ Object



94
95
96
# File 'lib/semantic_cache/cache.rb', line 94

def fetch_anthropic(query, model: "claude-sonnet-4-20250514", **options, &block)
  fetch(query, model: model, **options, &block)
end

#fetch_gemini(query, model: "gemini-pro", **options, &block) ⇒ Object



98
99
100
# File 'lib/semantic_cache/cache.rb', line 98

def fetch_gemini(query, model: "gemini-pro", **options, &block)
  fetch(query, model: model, **options, &block)
end

#fetch_openai(query, model: "gpt-4o", **options, &block) ⇒ Object

Convenience methods for specific providers



90
91
92
# File 'lib/semantic_cache/cache.rb', line 90

def fetch_openai(query, model: "gpt-4o", **options, &block)
  fetch(query, model: model, **options, &block)
end

#invalidate(tags:) ⇒ Object

Invalidate cached entries by tags.

cache.invalidate(tags: [:product_info])
cache.invalidate(tags: "user_data")


106
107
108
# File 'lib/semantic_cache/cache.rb', line 106

def invalidate(tags:)
  @store.invalidate_by_tags(Array(tags))
end

#savings_reportObject

Savings report string.



127
128
129
130
# File 'lib/semantic_cache/cache.rb', line 127

def savings_report
  s = @stats
  "Total saved: #{format("$%.2f", s.total_savings)} (#{s.hits} cached calls)"
end

#sizeObject

Number of entries currently in the cache.



133
134
135
# File 'lib/semantic_cache/cache.rb', line 133

def size
  @store.size
end