Class: RSpec::LLM::Matchers::BeSemanticallySimilarTo

Inherits:
Object
  • Object
show all
Defined in:
lib/rspec/llm/matchers/be_semantically_similar_to.rb

Overview

Embeds the actual and expected texts via the configured embedder and asserts cosine similarity >= threshold (default from configuration, overridable with .within(0.9)).

Instance Method Summary collapse

Constructor Details

#initialize(expected) ⇒ BeSemanticallySimilarTo

Returns a new instance of BeSemanticallySimilarTo.



10
11
12
13
# File 'lib/rspec/llm/matchers/be_semantically_similar_to.rb', line 10

def initialize(expected)
  @expected = expected
  @threshold = nil
end

Instance Method Details

#descriptionObject



28
29
30
# File 'lib/rspec/llm/matchers/be_semantically_similar_to.rb', line 28

def description
  "be semantically similar to #{@expected.inspect} (>= #{threshold_value})"
end

#failure_messageObject



32
33
34
35
36
# File 'lib/rspec/llm/matchers/be_semantically_similar_to.rb', line 32

def failure_message
  "expected response to be semantically similar to expected text " \
    "(similarity #{format_similarity} < threshold #{threshold_value}).\n" \
    "Expected: #{@expected.inspect}\nActual:   #{@actual.inspect}"
end

#failure_message_when_negatedObject



38
39
40
41
42
# File 'lib/rspec/llm/matchers/be_semantically_similar_to.rb', line 38

def failure_message_when_negated
  "expected response NOT to be semantically similar to expected text " \
    "(similarity #{format_similarity} >= threshold #{threshold_value}).\n" \
    "Expected: #{@expected.inspect}\nActual:   #{@actual.inspect}"
end

#matches?(actual) ⇒ Boolean

Returns:

  • (Boolean)


20
21
22
23
24
25
26
# File 'lib/rspec/llm/matchers/be_semantically_similar_to.rb', line 20

def matches?(actual)
  @actual = actual.to_s
  @actual_vec = embedder.call(@actual)
  @expected_vec = embedder.call(@expected.to_s)
  @similarity = cosine(@actual_vec, @expected_vec)
  @similarity >= threshold_value
end

#within(threshold) ⇒ Object



15
16
17
18
# File 'lib/rspec/llm/matchers/be_semantically_similar_to.rb', line 15

def within(threshold)
  @threshold = threshold
  self
end