Class: Assistant::TechnicalSupport::CaseEventStream::Redactor

Inherits:
Object
  • Object
show all
Defined in:
app/services/assistant/technical_support/case_event_stream/redactor.rb

Overview

Converts case evidence to plain text and removes known people, contact data,
addresses, case references, and external URLs before an LLM sees it.

Defined Under Namespace

Classes: KnownPeople, KnownValues

Constant Summary collapse

PATTERNS =
{
  email: /\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}\b/i,
  phone: /
    (?<!\w)
    (?:\+?1[\s.-]?)?
    (?:\(\d{3}\)|\d{3})
    [\s.-]?\d{3}[\s.-]?\d{4}
    (?!\w)
  /x,
  street_address: /
    \b\d{1,6}\s+
    (?:[A-Z0-9.'-]+\s+){1,6}
    (?:ST(?:REET)?|AVE(?:NUE)?|RD|ROAD|BLVD|BOULEVARD|LN|LANE|
       DR|DRIVE|HWY|HIGHWAY|WAY|CT|COURT|CIR(?:CLE)?|PKWY|PARKWAY|TRL|TRAIL)
    \b
  /ix,
  postal_code: /\b(?:\d{5}(?:-\d{4})?|[A-Z]\d[A-Z][ -]?\d[A-Z]\d)\b/i,
  crm_reference: /\b(?:CN|ETK|INV|QT|SO|TTK)\d{4,}\b/i,
  external_url: %r{\b(?:https?://|www\.)[^\s<>"']+}i,
  signature: /\s+(?:Regards|Sincerely|Thank You|Best(?: Regards)?),?\s+.*\z/im
}.freeze
URL_POLICY =
{
  placeholder: "__warmly_yours_url_%<index>d__",
  allowed_hosts: %w[warmlyyours.com warmlyyours.ca].freeze
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(graph, known_values_class: KnownValues) ⇒ Redactor

Returns a new instance of Redactor.



32
33
34
# File 'app/services/assistant/technical_support/case_event_stream/redactor.rb', line 32

def initialize(graph, known_values_class: KnownValues)
  @known_values = known_values_class.new(graph)
end

Instance Method Details

#call(value) ⇒ String

Returns de-identified plain text.

Parameters:

  • value (Object)

    source content, often HTML

Returns:

  • (String)

    de-identified plain text



38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/services/assistant/technical_support/case_event_stream/redactor.rb', line 38

def call(value)
  text = plain_text(value).sub(PATTERNS.fetch(:signature), '')
  text, protected_urls = protect_urls(text)
  text = redact_known_values(text)
  text = text.gsub(PATTERNS.fetch(:email), '[email]')
  text = text.gsub(PATTERNS.fetch(:phone), '[phone]')
  text = text.gsub(PATTERNS.fetch(:street_address), '[address]')
  text = text.gsub(PATTERNS.fetch(:postal_code), '[address]')
  text = text.gsub(PATTERNS.fetch(:crm_reference), '[reference]')
  text = restore_urls(text, protected_urls)
  text.lines.map(&:squish).compact_blank.join("\n")
end