octorecommender 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e8c71b55542fbe8ecfc53e19f2943491a5a1510d
4
+ data.tar.gz: 320d5056ee304ab7b94f82a71496d8b660c86d21
5
+ SHA512:
6
+ metadata.gz: 3fa4e9b0d64fa9e6838d46924e89a92e8a5e6a79d19a2fdd3fb67c9a428084870836cca057fee2428c8525c75fb6794a42ce8c4cfb8b2018ca22d7ec400bac19
7
+ data.tar.gz: a437e579d27d2e103a9ff4f6a75bb14ba00b876174fecfae784753032ee2e382ec5f23fd5275dce1095ef36df73bc4d80bffb17b3da5fbd199d2f089c1d3d214
File without changes
@@ -0,0 +1,20 @@
1
+ require 'predictor'
2
+ require 'octocore'
3
+
4
+ require 'octorecommender/recommenders'
5
+ require 'octorecommender/version'
6
+ require 'octorecommender/helpers'
7
+ require 'octorecommender/octohooks'
8
+ require 'octorecommender/scheduler'
9
+
10
+ module Octo
11
+
12
+ # Override Octo's default connection to include
13
+ # connection to Predictor as well
14
+ # See Octo#connect
15
+ def self.connect(configuration)
16
+ self._connect(configuration)
17
+ Predictor.redis = Cequel::Record.redis
18
+ end
19
+
20
+ end
@@ -0,0 +1,2 @@
1
+ require 'octorecommender/helpers/record'
2
+ require 'octorecommender/helpers/generic'
@@ -0,0 +1,11 @@
1
+ module Octo
2
+
3
+ private
4
+
5
+ # Generate the recommender instance
6
+ # @return [Octo::Recommender]
7
+ def recommender
8
+ @recommender = Octo::Recommender.new unless @recommender
9
+ @recommender
10
+ end
11
+ end
@@ -0,0 +1,20 @@
1
+ # Overriding Product class so as to add
2
+ # recommender related helper methods
3
+ module Octo
4
+ module Record
5
+
6
+ def similarities(opts={})
7
+ eid = self.enterprise.id
8
+ recommender.similar_products self, opts
9
+ end
10
+
11
+ private
12
+
13
+ # Generate the recommender instance
14
+ # @return [Octo::Recommender]
15
+ def recommender
16
+ @recommender = Octo::Recommender.new unless @recommender
17
+ @recommender
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,31 @@
1
+ require 'octocore/callbacks'
2
+
3
+ module Octo
4
+
5
+ module OctoHooks
6
+
7
+ # Define the custom tasks that need to be done
8
+ # upon various hooks
9
+ Octo::Callbacks.after_productpage_view lambda { |opts|
10
+ update_recommenders opts
11
+ }
12
+
13
+ # Extend the methods here
14
+ module ClassMethods
15
+
16
+ # Updates the recommenders
17
+ # @param [Hash] opts The options hash as passed
18
+ def update_recommenders(opts)
19
+ user = opts[:user]
20
+ product = opts[:product]
21
+
22
+ if user and product
23
+ recommender = Octo::Recommender.new
24
+ recommender.register_user_product_view(user, product)
25
+ recommender.register_user_action_time(user, Time.now.floor)
26
+ end
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,143 @@
1
+ require 'predictor'
2
+ require 'octorecommender/recommenders/product_recommender'
3
+ require 'octorecommender/recommenders/time_recommender'
4
+
5
+
6
+ module Octo
7
+ class Recommender
8
+
9
+ # Queue for resque worker processing
10
+ @queue = :recommender
11
+
12
+ # Time format to convert a Time into HHMM format
13
+ TIME_HHMM = '%H%M'
14
+
15
+ # Initializes the Recommender.
16
+ def initialize
17
+ @product_recommenders = {}
18
+ @time_recommenders = {}
19
+
20
+ # This option chosen as ruby seems to take a LOOOOOOOOOOT of time
21
+ # in processing.
22
+ Octo::Recommenders::ProductRecommender.processing_technique(:union)
23
+ Octo::Recommenders::ProductRecommender.processing_technique :union
24
+
25
+ Octo::Enterprise.each do |enterprise|
26
+ @product_recommenders[enterprise.id] = Octo::Recommenders::ProductRecommender.new(enterprise.id)
27
+ @time_recommenders[enterprise.id] = Octo::Recommenders::TimeRecommender.new(enterprise.id)
28
+ end
29
+ end
30
+
31
+ # Register a user, product view relation.
32
+ # @param [Octo::User] user The user object
33
+ # @param [Octo::Product] product The product object
34
+ def register_user_product_view(user, product)
35
+ @product_recommenders[user.enterprise_id].add_to_matrix(:users,
36
+ user.id,
37
+ product.id
38
+ )
39
+
40
+ register_product product
41
+ end
42
+
43
+ # Register a Product for recommendation
44
+ # @param [Octo::Product] product The product object
45
+ def register_product(product)
46
+ eid = product.enterprise_id
47
+ product.categories.each do |cat_text|
48
+ @product_recommenders[eid].add_to_matrix(:categories,
49
+ cat_text,
50
+ product.id
51
+ )
52
+ end
53
+ product.tags.each do |tag_text|
54
+ @product_recommenders[eid].add_to_matrix(:tags,
55
+ tag_text,
56
+ product.id
57
+ )
58
+ end
59
+ end
60
+
61
+ # Register a user, action-time view relation.
62
+ # @param [Octo::User] user The user object
63
+ # @param [Time] ts The time at which user takes some action
64
+ def register_user_action_time(user, ts = Time.now.floor)
65
+ eid = user.enterprise_id
66
+ @time_recommenders[eid].add_to_matrix(:users,
67
+ user.id,
68
+ ts.to_i
69
+ )
70
+
71
+ @time_recommenders[eid].add_to_matrix(:hourminutes,
72
+ ts.strftime(TIME_HHMM),
73
+ ts.to_i
74
+ )
75
+
76
+ @time_recommenders[eid].add_to_matrix(:days,
77
+ ts.strftime('%A'),
78
+ ts.to_i
79
+ )
80
+ end
81
+
82
+ # Get recommended products for a user
83
+ # @param [Octo::User] user The user object for whom product
84
+ # recommendations to be fetched
85
+ # @return [Array<Octo::Product>] An array of Octo::Product recommended
86
+ def recommended_products(user)
87
+ eid = user.enterprise_id
88
+ recommendations = @product_recommenders[eid].predictions_for(
89
+ user.id,
90
+ matrix_label: :users
91
+ )
92
+ recommendations.collect do |x|
93
+ args = { enterprise_id: eid, id: x.to_i}
94
+ Octo::Product.get_cached(args)
95
+ end
96
+ end
97
+
98
+ # Get similar products for products
99
+ # @param [Octo::Product] product The product for which similarities
100
+ # have to be found
101
+ # @return [Array<Octo::Product>] An array containing similar
102
+ # products
103
+ def similar_products(product, opts={})
104
+ eid = product.enterprise.id
105
+ @product_recommenders[eid].similarities_for(product.id, opts)
106
+ end
107
+
108
+ # Get recommended time for a user
109
+ # @param [Octo::User] user The user for whom time to be fetched
110
+ # @return [Array<Time>] The array of time recommended
111
+ def recommended_time(user)
112
+ eid = user.enterprise_id
113
+ recommendations = @time_recommenders[eid].predictions_for(user.id, matrix_label: :users)
114
+ recommendations.map do |ts|
115
+ convert_to_future(Time.at(ts.to_i))
116
+ end
117
+ end
118
+
119
+ # Creates a delayed job to process all the recommenders for all the
120
+ # enterprises or can provide specific options as well
121
+ def process!(opts = {})
122
+ @product_recommenders.values.each do |recomm|
123
+ recomm.process!
124
+ end
125
+ @time_recommenders.values.each do |recomm|
126
+ recomm.process!
127
+ end
128
+ end
129
+
130
+ # Converts a time from past to a similar time in future.
131
+ # This is necessary as CF would return one of the dates
132
+ # from past. We need sometime from future.
133
+ def convert_to_future(ts)
134
+ ts + (Time.now.beginning_of_day - ts.beginning_of_day) + 7.day
135
+ end
136
+
137
+ # Callback method for resque worker
138
+ def self.perform
139
+ self.new.process!
140
+ end
141
+
142
+ end
143
+ end
@@ -0,0 +1,33 @@
1
+ require 'predictor'
2
+ require 'octorecommender'
3
+
4
+ module Octo
5
+ module Recommenders
6
+ # The product recommender class. This class is responsible for recommending
7
+ # a (user, product)
8
+ class ProductRecommender
9
+ include Predictor::Base
10
+
11
+ def initialize(prefix)
12
+ @prefix = prefix
13
+ end
14
+
15
+ def get_redis_prefix
16
+ @prefix
17
+ end
18
+
19
+ limit_similarities_to 20
20
+
21
+ # Stores the user and product relation
22
+ input_matrix :users, weight: 3.0
23
+
24
+ # Store the relation between products asserted by their tags
25
+ input_matrix :tags, weight: 2.0
26
+
27
+ # Store the relation between products asserted by their
28
+ # categories
29
+ input_matrix :categories, weight: 1.0
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,41 @@
1
+ require 'predictor'
2
+ require 'octorecommender'
3
+
4
+ module Octo
5
+
6
+ module Recommenders
7
+
8
+ # The time recommender class. This class would be responsible for recommending
9
+ # the next set of time for a (user, action)
10
+ class TimeRecommender
11
+ include Predictor::Base
12
+
13
+ def initialize(prefix)
14
+ @prefix = prefix
15
+ end
16
+
17
+ def get_redis_prefix
18
+ @prefix
19
+ end
20
+
21
+ limit_similarities_to 20
22
+
23
+ # This matrix stores the user and their action
24
+ input_matrix :users, weight: 1.0
25
+
26
+ # This matrix stores the relation between times in terms of
27
+ # HHMM.
28
+ # Ex:
29
+ # 11/3/2016 11:30 and 12/3/2016 11:30 have the same HHMM
30
+ input_matrix :hourminutes, weight: 3.0
31
+
32
+ # This matrix stores the relation between times in terms of
33
+ # days.
34
+ # Ex:
35
+ # 4/4/2016 (Monday) and 11/4/2016 (Monday) have the same day
36
+ input_matrix :days, weight: 2.0
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,19 @@
1
+
2
+ module Octo
3
+ module Scheduler
4
+
5
+ # Setup Schedule for recommenders
6
+ def schedule_recommender
7
+ name = 'recommender_processing'
8
+ config = {
9
+ class: 'Octo::Recommender',
10
+ args: [],
11
+ cron: '0,30 * * * *',
12
+ persist: true,
13
+ queue: 'recommender'
14
+ }
15
+ Resque.set_schedule name, config
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ module Octo
2
+ module Recommenders
3
+
4
+ # The version of Recommender module
5
+ VERSION = '0.0.1'
6
+ end
7
+ end
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: octorecommender
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Pranav Prakash
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: predictor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.3.1
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 2.3.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 2.3.1
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 2.3.0
33
+ - !ruby/object:Gem::Dependency
34
+ name: octocore
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.0.1
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.0.1
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: 0.0.1
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: 0.0.1
53
+ description: |2
54
+ Contains recommendation specific stuff
55
+ email: pp@octo.ai
56
+ executables: []
57
+ extensions: []
58
+ extra_rdoc_files:
59
+ - README.md
60
+ files:
61
+ - README.md
62
+ - lib/octorecommender.rb
63
+ - lib/octorecommender/helpers.rb
64
+ - lib/octorecommender/helpers/generic.rb
65
+ - lib/octorecommender/helpers/record.rb
66
+ - lib/octorecommender/octohooks.rb
67
+ - lib/octorecommender/recommenders.rb
68
+ - lib/octorecommender/recommenders/product_recommender.rb
69
+ - lib/octorecommender/recommenders/time_recommender.rb
70
+ - lib/octorecommender/scheduler.rb
71
+ - lib/octorecommender/version.rb
72
+ homepage: http://phab.octo.ai/diffusion/GEMS/
73
+ licenses:
74
+ - MIT
75
+ metadata: {}
76
+ post_install_message:
77
+ rdoc_options: []
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '2.0'
85
+ required_rubygems_version: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 2.4.6
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Octo Recommender(s) Module
96
+ test_files: []
97
+ has_rdoc: true