Module: Ask::Eval::Assertions::Deterministic
- Defined in:
- lib/ask/eval/assertions/deterministic.rb
Overview
Deterministic (non-LLM) assertion checks. Each method returns { passed: Boolean, score: Float, reason: String }.
Class Method Summary collapse
-
.contains(output, value:) ⇒ Hash
{ passed:, score:, reason: }.
-
.email(output, **_kwargs) ⇒ Hash
{ passed:, score:, reason: }.
-
.ends_with(output, suffix:) ⇒ Hash
{ passed:, score:, reason: }.
-
.equals(output, value:) ⇒ Hash
{ passed:, score:, reason: }.
-
.is_json(output, **_kwargs) ⇒ Hash
{ passed:, score:, reason: }.
-
.max_length(output, max:) ⇒ Hash
{ passed:, score:, reason: }.
-
.max_tokens(output, max:) ⇒ Hash
{ passed:, score:, reason: }.
-
.min_length(output, min:) ⇒ Hash
{ passed:, score:, reason: }.
-
.not_contains(output, value:) ⇒ Hash
{ passed:, score:, reason: }.
-
.regex(output, pattern:) ⇒ Hash
{ passed:, score:, reason: }.
-
.starts_with(output, prefix:) ⇒ Hash
{ passed:, score:, reason: }.
-
.url(output, **_kwargs) ⇒ Hash
{ passed:, score:, reason: }.
Class Method Details
.contains(output, value:) ⇒ Hash
Returns { passed:, score:, reason: }.
16 17 18 19 20 21 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 16 def contains(output, value:) passed = output.to_s.include?(value.to_s) result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output contains #{value.inspect}" : "Output does not contain #{value.inspect}") end |
.email(output, **_kwargs) ⇒ Hash
Returns { passed:, score:, reason: }.
131 132 133 134 135 136 137 138 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 131 def email(output, **_kwargs) # Simple but effective email regex pattern = /\A[^@\s]+@[^@\s]+\.[^@\s]+\z/ passed = pattern.match?(output.to_s.strip) result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output is a valid email address" : "Output is not a valid email address") end |
.ends_with(output, suffix:) ⇒ Hash
Returns { passed:, score:, reason: }.
78 79 80 81 82 83 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 78 def ends_with(output, suffix:) passed = output.to_s.end_with?(suffix.to_s) result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output ends with #{suffix.inspect}" : "Output does not end with #{suffix.inspect}") end |
.equals(output, value:) ⇒ Hash
Returns { passed:, score:, reason: }.
88 89 90 91 92 93 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 88 def equals(output, value:) passed = output.to_s == value.to_s result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output equals #{value.inspect}" : "Output does not equal #{value.inspect}") end |
.is_json(output, **_kwargs) ⇒ Hash
Returns { passed:, score:, reason: }.
47 48 49 50 51 52 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 47 def is_json(output, **_kwargs) JSON.parse(output.to_s) result(true, score: 1.0, reason: "Output is valid JSON") rescue JSON::ParserError => e result(false, score: 0.0, reason: "Output is not valid JSON: #{e.}") end |
.max_length(output, max:) ⇒ Hash
Returns { passed:, score:, reason: }.
109 110 111 112 113 114 115 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 109 def max_length(output, max:) len = output.to_s.length passed = len <= max result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output length #{len} <= #{max}" : "Output length #{len} > #{max}") end |
.max_tokens(output, max:) ⇒ Hash
Returns { passed:, score:, reason: }.
57 58 59 60 61 62 63 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 57 def max_tokens(output, max:) count = approximate_tokens(output.to_s) passed = count <= max result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output has ~#{count} tokens (max: #{max})" : "Output has ~#{count} tokens (max: #{max})") end |
.min_length(output, min:) ⇒ Hash
Returns { passed:, score:, reason: }.
98 99 100 101 102 103 104 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 98 def min_length(output, min:) len = output.to_s.length passed = len >= min result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output length #{len} >= #{min}" : "Output length #{len} < #{min}") end |
.not_contains(output, value:) ⇒ Hash
Returns { passed:, score:, reason: }.
26 27 28 29 30 31 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 26 def not_contains(output, value:) passed = !output.to_s.include?(value.to_s) result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output does not contain #{value.inspect}" : "Output contains #{value.inspect}") end |
.regex(output, pattern:) ⇒ Hash
Returns { passed:, score:, reason: }.
36 37 38 39 40 41 42 43 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 36 def regex(output, pattern:) re = pattern.is_a?(Regexp) ? pattern : Regexp.new(pattern.to_s) match = re.match(output.to_s) passed = !match.nil? result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output matches #{re.inspect}#{" at #{match[0].inspect}" if match}" : "Output does not match #{re.inspect}") end |
.starts_with(output, prefix:) ⇒ Hash
Returns { passed:, score:, reason: }.
68 69 70 71 72 73 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 68 def starts_with(output, prefix:) passed = output.to_s.start_with?(prefix.to_s) result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output starts with #{prefix.inspect}" : "Output does not start with #{prefix.inspect}") end |
.url(output, **_kwargs) ⇒ Hash
Returns { passed:, score:, reason: }.
119 120 121 122 123 124 125 126 127 |
# File 'lib/ask/eval/assertions/deterministic.rb', line 119 def url(output, **_kwargs) uri = URI.parse(output.to_s.strip) passed = uri.is_a?(URI::HTTP) || uri.is_a?(URI::HTTPS) result(passed, score: passed ? 1.0 : 0.0, reason: passed ? "Output is a valid URL" : "Output is not a valid URL") rescue URI::InvalidURIError result(false, score: 0.0, reason: "Output is not a valid URL (parse error)") end |