sentiment_agent.rb 2.8 KB

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