Class: Vangrail::Engine
- Inherits:
-
Object
- Object
- Vangrail::Engine
- Defined in:
- lib/vangrail/engine.rb
Overview
Runs ordered rails over text and reports one Result.
The rules are short enough to state in full:
- Rails run in the order given. The first :blocked ends the pass.
- A :modified result replaces the text for every rail after it, and the engine reports :modified unless something later blocks.
- A rail that raises is not a rail that passed.
on_error: :allow(the default) keeps going and marks the pass uncertain;:blockstops. - An empty rail list returns :passed with certain false. Nothing ran.
Threading rewrites through later rails is the part worth being explicit about: a redaction rail that runs before a policy rail should have the policy rail judge the redacted text, not the original.
Defined Under Namespace
Classes: Screening
Instance Attribute Summary collapse
-
#cache ⇒ Object
readonly
Returns the value of attribute cache.
-
#context_rails ⇒ Object
readonly
Returns the value of attribute context_rails.
-
#input_rails ⇒ Object
readonly
Returns the value of attribute input_rails.
-
#on_error ⇒ Object
readonly
Returns the value of attribute on_error.
-
#output_rails ⇒ Object
readonly
Returns the value of attribute output_rails.
Instance Method Summary collapse
-
#check_context(text, **context) ⇒ Object
One retrieved document, before it goes anywhere near a prompt.
- #check_input(text, context = {}) ⇒ Object
- #check_output(text, user_input: nil, passages: nil, **context) ⇒ Object
- #describe ⇒ Object
- #empty? ⇒ Boolean
-
#initialize(input: [], context: [], output: [], on_error: :allow, cache: true) ⇒ Engine
constructor
A new instance of Engine.
-
#offline? ⇒ Boolean
True when every configured rail decides without a network call, which is the only case where an unreachable endpoint cannot weaken the check.
- #rail_names(side) ⇒ Object
- #rails(side) ⇒ Object
-
#screen(documents, **context) ⇒ Object
Screens a set of retrieved documents and reports what survived.
- #to_h ⇒ Object
Constructor Details
#initialize(input: [], context: [], output: [], on_error: :allow, cache: true) ⇒ Engine
Returns a new instance of Engine.
26 27 28 29 30 31 32 33 34 |
# File 'lib/vangrail/engine.rb', line 26 def initialize(input: [], context: [], output: [], on_error: :allow, cache: true) @input_rails = Array(input) @context_rails = Array(context) @output_rails = Array(output) @on_error = on_error.to_sym raise ArgumentError, 'on_error must be :allow or :block' unless %i[allow block].include?(@on_error) @cache = cache.is_a?(ResultCache) ? cache : (ResultCache.new if cache) end |
Instance Attribute Details
#cache ⇒ Object (readonly)
Returns the value of attribute cache.
24 25 26 |
# File 'lib/vangrail/engine.rb', line 24 def cache @cache end |
#context_rails ⇒ Object (readonly)
Returns the value of attribute context_rails.
24 25 26 |
# File 'lib/vangrail/engine.rb', line 24 def context_rails @context_rails end |
#input_rails ⇒ Object (readonly)
Returns the value of attribute input_rails.
24 25 26 |
# File 'lib/vangrail/engine.rb', line 24 def input_rails @input_rails end |
#on_error ⇒ Object (readonly)
Returns the value of attribute on_error.
24 25 26 |
# File 'lib/vangrail/engine.rb', line 24 def on_error @on_error end |
#output_rails ⇒ Object (readonly)
Returns the value of attribute output_rails.
24 25 26 |
# File 'lib/vangrail/engine.rb', line 24 def output_rails @output_rails end |
Instance Method Details
#check_context(text, **context) ⇒ Object
One retrieved document, before it goes anywhere near a prompt.
45 46 47 |
# File 'lib/vangrail/engine.rb', line 45 def check_context(text, **context) run(:context, context_rails, text, context) end |
#check_input(text, context = {}) ⇒ Object
36 37 38 |
# File 'lib/vangrail/engine.rb', line 36 def check_input(text, context = {}) run(:input, input_rails, text, context) end |
#check_output(text, user_input: nil, passages: nil, **context) ⇒ Object
40 41 42 |
# File 'lib/vangrail/engine.rb', line 40 def check_output(text, user_input: nil, passages: nil, **context) run(:output, output_rails, text, context.merge(user_input: user_input, passages: passages)) end |
#describe ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/vangrail/engine.rb', line 129 def describe return 'no rails' if empty? parts = [] parts << "input=#{rail_names(:input).join('+')}" unless input_rails.empty? parts << "context=#{rail_names(:context).join('+')}" unless context_rails.empty? parts << "output=#{rail_names(:output).join('+')}" unless output_rails.empty? parts << "on_error=#{on_error}" parts << 'offline' if offline? parts.join(' ') end |
#empty? ⇒ Boolean
114 115 116 |
# File 'lib/vangrail/engine.rb', line 114 def empty? input_rails.empty? && context_rails.empty? && output_rails.empty? end |
#offline? ⇒ Boolean
True when every configured rail decides without a network call, which is the only case where an unreachable endpoint cannot weaken the check.
109 110 111 112 |
# File 'lib/vangrail/engine.rb', line 109 def offline? all = input_rails + context_rails + output_rails !all.empty? && all.all?(&:offline?) end |
#rail_names(side) ⇒ Object
103 104 105 |
# File 'lib/vangrail/engine.rb', line 103 def rail_names(side) rails(side).map(&:name) end |
#rails(side) ⇒ Object
95 96 97 98 99 100 101 |
# File 'lib/vangrail/engine.rb', line 95 def rails(side) case side.to_sym when :input then input_rails when :context then context_rails else output_rails end end |
#screen(documents, **context) ⇒ Object
Screens a set of retrieved documents and reports what survived.
A document that fails is dropped rather than failing the whole turn. One poisoned wiki page should cost a reader that page, not their answer, and an application that refuses outright teaches its readers that the guardrail is the problem.
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/vangrail/engine.rb', line 55 def screen(documents, **context) kept = [] rejected = [] uncertain = nil Array(documents).each_with_index do |document, index| result = check_context(text_of(document), **context, document: document, index: index) uncertain ||= result unless result.certain? if result.blocked? rejected << { document: document, result: result } else kept << (result.modified? ? replace_text(document, result.content) : document) end end Screening.new(kept: kept, rejected: rejected, certain: uncertain.nil?, reason: uncertain&.reason) end |
#to_h ⇒ Object
118 119 120 121 122 123 124 125 126 127 |
# File 'lib/vangrail/engine.rb', line 118 def to_h { 'input' => rail_names(:input), 'context' => (rail_names(:context) unless context_rails.empty?), 'output' => rail_names(:output), 'on_error' => on_error.to_s, 'offline' => offline?, 'cache' => cache&.to_h }.compact end |