sentiment_agent.rb 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. require 'csv'
  2. module Agents
  3. class SentimentAgent < Agent
  4. class_attribute :anew
  5. cannot_be_scheduled!
  6. description <<-MD
  7. The Sentiment Agent generates `good-bad` (psychological valence or happiness index), `active-passive` (arousal), and `strong-weak` (dominance) score. It will output a value between 1 and 9. It will only work on English content.
  8. Make sure the content this agent is analyzing is of sufficient length to get respectable results.
  9. Provide a JSONPath in `content` field where content is residing and set `expected_receive_period_in_days` to the maximum number of days you would allow to be passed between events being received by this agent.
  10. MD
  11. event_description <<-MD
  12. Events look like:
  13. {
  14. "content": "The quick brown fox jumps over the lazy dog.",
  15. "valence": 6.196666666666666,
  16. "arousal": 4.993333333333333,
  17. "dominance": 5.63
  18. }
  19. MD
  20. def default_options
  21. {
  22. 'content' => "$.message.text[*]",
  23. 'expected_receive_period_in_days' => 1
  24. }
  25. end
  26. def working?
  27. last_receive_at && last_receive_at > interpolated['expected_receive_period_in_days'].to_i.days.ago && !recent_error_logs?
  28. end
  29. def receive(incoming_events)
  30. anew = self.class.sentiment_hash
  31. incoming_events.each do |event|
  32. Utils.values_at(event.payload, interpolated['content']).each do |content|
  33. sent_values = sentiment_values anew, content
  34. create_event :payload => { 'content' => content,
  35. 'valence' => sent_values[0],
  36. 'arousal' => sent_values[1],
  37. 'dominance' => sent_values[2],
  38. 'original_event' => event.payload }
  39. end
  40. end
  41. end
  42. def validate_options
  43. errors.add(:base, "content and expected_receive_period_in_days must be present") unless options['content'].present? && options['expected_receive_period_in_days'].present?
  44. end
  45. def self.sentiment_hash
  46. unless self.anew
  47. self.anew = {}
  48. CSV.foreach Rails.root.join('data/anew.csv') do |row|
  49. self.anew[row[0]] = row.values_at(2, 4, 6).map { |val| val.to_f }
  50. end
  51. end
  52. self.anew
  53. end
  54. def sentiment_values(anew, text)
  55. valence, arousal, dominance, freq = [0] * 4
  56. text.downcase.strip.gsub(/[^a-z ]/, "").split.each do |word|
  57. if anew.has_key? word
  58. valence += anew[word][0]
  59. arousal += anew[word][1]
  60. dominance += anew[word][2]
  61. freq += 1
  62. end
  63. end
  64. if valence != 0
  65. [valence/freq, arousal/freq, dominance/freq]
  66. else
  67. ["Insufficient data for meaningful answer"] * 3
  68. end
  69. end
  70. end
  71. end