Skip to content

Commit

Permalink
Support RecommendNextItems endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
OndraFiedler committed Jan 14, 2021
1 parent df1b1ef commit 01e40fc
Show file tree
Hide file tree
Showing 14 changed files with 158 additions and 27 deletions.
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,13 @@ begin
client.send(Batch.new(purchases))

# Get recommendations for user 'user-25'
recommended = client.send(RecommendItemsToUser.new('user-25', 5))
puts "Recommended items for user-25: #{recommended}"
response = client.send(RecommendItemsToUser.new('user-25', 5))
puts "Recommended items for user-25: #{response}"

# User scrolled down - get next 3 recommended items
response = client.send(RecommendNextItems.new(response['recommId'], 3))
puts "Next recommended items for user-25: #{response}"

rescue APIError => e
puts e
# Use fallback
Expand Down Expand Up @@ -146,7 +151,7 @@ recommended = client.send(

# Perform personalized full-text search with a user's search query (e.g. 'computers').
matches = client.send(
SearchItems.new('user-42', 'computers', 5)
SearchItems.new('user-42', 'computers', 5, {:scenario => 'search_top'})
)
puts "Matched items: #{matches}"
```
Expand Down
2 changes: 1 addition & 1 deletion lib/recombee_api_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class RecombeeClient
include HTTParty

BATCH_MAX_SIZE = 10000
USER_AGENT = {'User-Agent' => 'recombee-ruby-api-client/3.0.0'}
USER_AGENT = {'User-Agent' => 'recombee-ruby-api-client/3.1.0'}

##
# - +account+ -> Name of your account at Recombee
Expand Down
17 changes: 12 additions & 5 deletions lib/recombee_api_client/api/recommend_items_to_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,14 @@ module RecombeeApiClient
##
#Recommends set of items that are somehow related to one given item, *X*. Typical scenario is when user *A* is viewing *X*. Then you may display items to the user that he might be also interested in. Recommend items to item request gives you Top-N such items, optionally taking the target user *A* into account.
#
#It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters.
#The returned items are sorted by relevance (first item being the most relevant).
#
#Besides the recommended items, also a unique `recommId` is returned in the response. It can be used to:
#
#The returned items are sorted by relevancy (first item being the most relevant).
#- Let Recombee know that this recommendation was successful (e.g. user clicked one of the recommended items). See [Reported metrics](https://docs.recombee.com/admin_ui.html#reported-metrics).
#- Get subsequent recommended items when the user scrolls down (*infinite scroll*) or goes to the next page. See [Recommend Next Items](https://docs.recombee.com/api.html#recommend-next-items).
#
#It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters.
#
class RecommendItemsToItem < ApiRequest
attr_reader :item_id, :target_user_id, :count, :scenario, :cascade_create, :return_properties, :included_properties, :filter, :booster, :logic, :user_impact, :diversity, :min_relevance, :rotation_rate, :rotation_time, :expert_settings, :return_ab_group
Expand Down Expand Up @@ -75,7 +80,8 @@ class RecommendItemsToItem < ApiRequest
# "url": "myshop.com/mixer-42"
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand All @@ -101,7 +107,8 @@ class RecommendItemsToItem < ApiRequest
# "price": 39
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand All @@ -124,7 +131,7 @@ class RecommendItemsToItem < ApiRequest
#
# - +diversity+ -> **Expert option** Real number from [0.0, 1.0] which determines how much mutually dissimilar should the recommended items be. The default value is 0.0, i.e., no diversification. Value 1.0 means maximal diversification.
#
# - +minRelevance+ -> **Expert option** If the *targetUserId* is provided: Specifies the threshold of how much relevant must the recommended items be to the user. Possible values one of: "low", "medium", "high". The default value is "low", meaning that the system attempts to recommend number of items equal to *count* at any cost. If there are not enough data (such as interactions or item properties), this may even lead to bestseller-based recommendations to be appended to reach the full *count*. This behavior may be suppressed by using "medium" or "high" values. In such case, the system only recommends items of at least the requested relevancy, and may return less than *count* items when there is not enough data to fulfill it.
# - +minRelevance+ -> **Expert option** If the *targetUserId* is provided: Specifies the threshold of how much relevant must the recommended items be to the user. Possible values one of: "low", "medium", "high". The default value is "low", meaning that the system attempts to recommend number of items equal to *count* at any cost. If there are not enough data (such as interactions or item properties), this may even lead to bestseller-based recommendations to be appended to reach the full *count*. This behavior may be suppressed by using "medium" or "high" values. In such case, the system only recommends items of at least the requested relevance, and may return less than *count* items when there is not enough data to fulfill it.
#
# - +rotationRate+ -> **Expert option** If the *targetUserId* is provided: If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per-request in backward fashion. You may penalize an item for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example `rotationRate=0.2` for only slight rotation of recommended items.
#
Expand Down
17 changes: 12 additions & 5 deletions lib/recombee_api_client/api/recommend_items_to_user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ module RecombeeApiClient
#
#The most typical use cases are recommendations at homepage, in some "Picked just for you" section or in email.
#
#It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters.
#The returned items are sorted by relevance (first item being the most relevant).
#
#Besides the recommended items, also a unique `recommId` is returned in the response. It can be used to:
#
#The returned items are sorted by relevancy (first item being the most relevant).
#- Let Recombee know that this recommendation was successful (e.g. user clicked one of the recommended items). See [Reported metrics](https://docs.recombee.com/admin_ui.html#reported-metrics).
#- Get subsequent recommended items when the user scrolls down (*infinite scroll*) or goes to the next page. See [Recommend Next Items](https://docs.recombee.com/api.html#recommend-next-items).
#
#It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters.
#
class RecommendItemsToUser < ApiRequest
attr_reader :user_id, :count, :scenario, :cascade_create, :return_properties, :included_properties, :filter, :booster, :logic, :diversity, :min_relevance, :rotation_rate, :rotation_time, :expert_settings, :return_ab_group
Expand Down Expand Up @@ -61,7 +66,8 @@ class RecommendItemsToUser < ApiRequest
# "url": "myshop.com/mixer-42"
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand All @@ -87,7 +93,8 @@ class RecommendItemsToUser < ApiRequest
# "price": 39
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand All @@ -108,7 +115,7 @@ class RecommendItemsToUser < ApiRequest
#
# - +diversity+ -> **Expert option** Real number from [0.0, 1.0] which determines how much mutually dissimilar should the recommended items be. The default value is 0.0, i.e., no diversification. Value 1.0 means maximal diversification.
#
# - +minRelevance+ -> **Expert option** Specifies the threshold of how much relevant must the recommended items be to the user. Possible values one of: "low", "medium", "high". The default value is "low", meaning that the system attempts to recommend number of items equal to *count* at any cost. If there are not enough data (such as interactions or item properties), this may even lead to bestseller-based recommendations to be appended to reach the full *count*. This behavior may be suppressed by using "medium" or "high" values. In such case, the system only recommends items of at least the requested relevancy, and may return less than *count* items when there is not enough data to fulfill it.
# - +minRelevance+ -> **Expert option** Specifies the threshold of how much relevant must the recommended items be to the user. Possible values one of: "low", "medium", "high". The default value is "low", meaning that the system attempts to recommend number of items equal to *count* at any cost. If there are not enough data (such as interactions or item properties), this may even lead to bestseller-based recommendations to be appended to reach the full *count*. This behavior may be suppressed by using "medium" or "high" values. In such case, the system only recommends items of at least the requested relevance, and may return less than *count* items when there is not enough data to fulfill it.
#
# - +rotationRate+ -> **Expert option** If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per-request in backward fashion. You may penalize an item for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example `rotationRate=0.2` for only slight rotation of recommended items. Default: `0.1`.
#
Expand Down
69 changes: 69 additions & 0 deletions lib/recombee_api_client/api/recommend_next_items.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#
# This file is auto-generated, do not edit
#

module RecombeeApiClient
require_relative 'request'
require_relative '../errors'

##
#Returns items that shall be shown to a user as next recommendations when the user e.g. scrolls the page down (*infinite scroll*) or goes to a next page.
#
#It accepts `recommId` of a base recommendation request (e.g. request from the first page) and number of items that shall be returned (`count`).
#The base request can be one of:
# - [Recommend items to item](https://docs.recombee.com/api.html#recommend-items-to-item)
# - [Recommend items to user](https://docs.recombee.com/api.html#recommend-items-to-user)
# - [Search items](https://docs.recombee.com/api.html#search-items)
#
#All the other parameters are inherited from the base request.
#
#*Recommend next items* can be called many times for a single `recommId` and each call returns different (previously not recommended) items.
#The number of *Recommend next items* calls performed so far is returned in the `numberNextRecommsCalls` field.
#
#*Recommend next items* can be requested up to 30 minutes after the base request or a previous *Recommend next items* call.
#
#For billing purposes, each call to *Recommend next items* is counted as a separate recommendation request.
#
class RecommendNextItems < ApiRequest
attr_reader :recomm_id, :count
attr_accessor :timeout
attr_accessor :ensure_https

##
# * *Required arguments*
# - +recomm_id+ -> ID of the base recommendation request for which next recommendations should be returned
# - +count+ -> Number of items to be recommended
#
#
def initialize(recomm_id, count)
@recomm_id = recomm_id
@count = count
@timeout = 3000
@ensure_https = false
end

# HTTP method
def method
:post
end

# Values of body parameters as a Hash
def body_parameters
p = Hash.new
p['count'] = @count
p
end

# Values of query parameters as a Hash.
# name of parameter => value of the parameter
def query_parameters
params = {}
params
end

# Relative path to the endpoint
def path
"/{databaseId}/recomms/next/items/#{@recomm_id}"
end
end
end
6 changes: 4 additions & 2 deletions lib/recombee_api_client/api/recommend_users_to_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ class RecommendUsersToItem < ApiRequest
# "sex": "M"
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand All @@ -77,7 +78,8 @@ class RecommendUsersToItem < ApiRequest
# "country": "CAN"
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand Down
8 changes: 5 additions & 3 deletions lib/recombee_api_client/api/recommend_users_to_user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ class RecommendUsersToUser < ApiRequest
# "sex": "M"
# }
# }
# ]
# }
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
# - +includedProperties+ -> Allows to specify, which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list.
Expand All @@ -77,7 +78,8 @@ class RecommendUsersToUser < ApiRequest
# "country": "CAN"
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand Down
15 changes: 11 additions & 4 deletions lib/recombee_api_client/api/search_items.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ module RecombeeApiClient
#
#This endpoint should be used in a search box at your website/app. It can be called multiple times as the user is typing the query in order to get the most viable suggestions based on current state of the query, or once after submitting the whole query.
#
#It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters.
#The returned items are sorted by relevance (first item being the most relevant).
#
#Besides the recommended items, also a unique `recommId` is returned in the response. It can be used to:
#
#The returned items are sorted by relevancy (first item being the most relevant).
#- Let Recombee know that this search was successful (e.g. user clicked one of the recommended items). See [Reported metrics](https://docs.recombee.com/admin_ui.html#reported-metrics).
#- Get subsequent search results when the user scrolls down or goes to the next page. See [Recommend Next Items](https://docs.recombee.com/api.html#recommend-next-items).
#
#It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters.
#
class SearchItems < ApiRequest
attr_reader :user_id, :search_query, :count, :scenario, :cascade_create, :return_properties, :included_properties, :filter, :booster, :logic, :expert_settings, :return_ab_group
Expand Down Expand Up @@ -62,7 +67,8 @@ class SearchItems < ApiRequest
# "url": "myshop.com/mixer-42"
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand All @@ -88,7 +94,8 @@ class SearchItems < ApiRequest
# "price": 39
# }
# }
# ]
# ],
# "numberNextRecommsCalls": 0
# }
#```
#
Expand Down
2 changes: 1 addition & 1 deletion lib/recombee_api_client/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module RecombeeApiClient
VERSION = '3.0.0'
VERSION = '3.1.0'
end
2 changes: 1 addition & 1 deletion spec/api/add_entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
end

it 'fails with invalid entity id' do
req = described_class.new('$$$not_valid$$$')
req = described_class.new('***not_valid$$$')
expect { @client.send(req) }.to raise_exception { |exception|
expect(exception).to be_a(RecombeeApiClient::ResponseError)
expect(exception.status_code).to eq 400
Expand Down
2 changes: 1 addition & 1 deletion spec/api/delete_entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
end

it 'fails with invalid entity id' do
req = described_class.new('$$$not_valid$$$')
req = described_class.new('***not_valid$$$')
expect { @client.send(req) }.to raise_exception { |exception|
expect(exception).to be_a(RecombeeApiClient::ResponseError)
expect(exception.status_code).to eq 400
Expand Down
2 changes: 1 addition & 1 deletion spec/api/delete_property.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
end

it 'fails with invalid property' do
req = described_class.new('$$$not_valid$$$')
req = described_class.new('***not_valid$$$')
expect { @client.send(req) }.to raise_exception { |exception|
expect(exception).to be_a(RecombeeApiClient::ResponseError)
expect(exception.status_code).to eq 400
Expand Down
22 changes: 22 additions & 0 deletions spec/api/next_items_recommendation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#
# This file is auto-generated, do not edit
#

require 'spec_helper'
require_relative 'set_environment'
shared_examples 'next items recommendation' do
include_context 'set environment'
include_context 'set recomm entities'

it 'recommends' do
req = RecommendItemsToUser.new('entity_id',3,{'returnProperties' => true})
resp = @client.send(req)
req = described_class.new(resp['recommId'],3)
resp = @client.send(req)
expect(resp['recomms'].size).to eq 3
req = described_class.new(resp['recommId'],3)
resp = @client.send(req)
expect(resp['recomms'].size).to eq 3
end

end
10 changes: 10 additions & 0 deletions spec/api/recommend_next_items_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#
# This file is auto-generated, do not edit
#

require 'spec_helper'
require_relative "next_items_recommendation"

describe RecombeeApiClient::RecommendNextItems do
it_behaves_like "next items recommendation"
end

0 comments on commit 01e40fc

Please sign in to comment.