Class: Insika::Safety::Corpus::Compiled

Inherits:
Data
  • Object
show all
Defined in:
lib/insika/safety/corpus.rb

Overview

The compiled corpus for ONE agent: the input families + output detectors filtered by its languages and extended by its extra patterns. Immutable (Data + deep-frozen collections) and shared safely.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#inputObject (readonly)

Returns the value of attribute input

Returns:

  • (Object)

    the current value of input



109
110
111
# File 'lib/insika/safety/corpus.rb', line 109

def input
  @input
end

#languagesObject (readonly)

Returns the value of attribute languages

Returns:

  • (Object)

    the current value of languages



109
110
111
# File 'lib/insika/safety/corpus.rb', line 109

def languages
  @languages
end

#piiObject (readonly)

Returns the value of attribute pii

Returns:

  • (Object)

    the current value of pii



109
110
111
# File 'lib/insika/safety/corpus.rb', line 109

def pii
  @pii
end

Instance Method Details

#detect_output(name, text) ⇒ Object

Runs a NAMED output detector over text -> the matched substring | nil. "pii_leak" = union of all patterns; an entirely UNKNOWN name fails LOUD (a typo'd assertion must never silently pass); a name the corpus knows but whose language was cleared matches nothing.



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/insika/safety/corpus.rb', line 120

def detect_output(name, text)
  patterns =
    if name.to_s == "pii_leak"
      pii.values
    else
      p = pii[name.to_s]
      if p.nil? && !Corpus::PII.key?(name.to_s)
        raise ArgumentError, "unknown detector: #{name.inspect}"
      end

      p ? [p] : []
    end
  patterns.each { |re| (m = text.to_s.match(re)) && (return m[0]) }
  nil
end

#input_categories(categories) ⇒ Object

The subset of categories (symbols) that have patterns in this corpus — the strictness gate applied to the compiled set.



112
113
114
# File 'lib/insika/safety/corpus.rb', line 112

def input_categories(categories)
  categories.select { |cat| Array(input[cat.to_s]).any? }
end

#match_ranges(text) ⇒ Object

[[begin, end), ...] byte-index ranges of every PII/secret match in text (used by the OutputFilter to avoid splitting a complete match at a chunk boundary).



153
154
155
156
157
158
159
# File 'lib/insika/safety/corpus.rb', line 153

def match_ranges(text)
  ranges = []
  pii.each_value do |re|
    text.to_s.scan(re) { ranges << [Regexp.last_match.begin(0), Regexp.last_match.end(0)] }
  end
  ranges
end

#open_tailObject

The universal open-tail pattern (see Corpus::OPEN_TAIL).



162
# File 'lib/insika/safety/corpus.rb', line 162

def open_tail = Corpus::OPEN_TAIL

#redact(text) ⇒ Object

Replaces every PII/secret occurrence with an opaque [REDACTED:<name>] marker — the raw value NEVER survives. -> [redacted_text, => count].



138
139
140
141
142
143
144
145
146
147
148
# File 'lib/insika/safety/corpus.rb', line 138

def redact(text)
  counts = Hash.new(0)
  out = text.to_s.dup
  pii.each do |name, re|
    out = out.gsub(re) do
      counts[name] += 1
      "[REDACTED:#{name}]"
    end
  end
  [out, counts]
end