Add feed variants with shuffle post-ranking (#6766) [deploy]
* Add feed variants with shuffle post-ranking * Refactor tests and fix erroneous shuffle
This commit is contained in:
parent
3187514ad6
commit
da8dbd2180
4 changed files with 75 additions and 62 deletions
|
|
@ -39,6 +39,12 @@ class Stories::FeedsController < ApplicationController
|
|||
feed.more_comments_experiment
|
||||
when "more_experience_level_weight_experiment"
|
||||
feed.more_experience_level_weight_experiment
|
||||
when "more_tag_weight_randomized_at_end_experiment"
|
||||
feed.more_tag_weight_randomized_at_end_experiment
|
||||
when "more_experience_level_weight_randomized_at_end_experiment"
|
||||
feed.more_experience_level_weight_randomized_at_end_experiment
|
||||
when "more_comments_randomized_at_end_experiment"
|
||||
feed.more_comments_randomized_at_end_experiment
|
||||
when "mix_of_everything_experiment" # mix of all experiments. New experiments also added. This is the "index fund" version.
|
||||
feed.mix_of_everything_experiment
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
module Articles
|
||||
class Feed
|
||||
RANDOM_OFFSET_VALUES = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11].freeze
|
||||
RANDOM_OFFSET_VALUES = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].freeze
|
||||
|
||||
def initialize(user: nil, number_of_articles: 35, page: 1, tag: nil)
|
||||
@user = user
|
||||
|
|
@ -100,7 +100,7 @@ module Articles
|
|||
end
|
||||
|
||||
def mix_of_everything_experiment
|
||||
case rand(7)
|
||||
case rand(10)
|
||||
when 0
|
||||
default_home_feed(user_signed_in: true)
|
||||
when 1
|
||||
|
|
@ -115,11 +115,40 @@ module Articles
|
|||
more_comments_experiment
|
||||
when 6
|
||||
more_experience_level_weight_experiment
|
||||
when 7
|
||||
more_tag_weight_randomized_at_end_experiment
|
||||
when 8
|
||||
more_experience_level_weight_randomized_at_end_experiment
|
||||
when 9
|
||||
more_comments_randomized_at_end_experiment
|
||||
else
|
||||
default_home_feed(user_signed_in: true)
|
||||
end
|
||||
end
|
||||
|
||||
# Randomized at end group for next three experiments
|
||||
# Rather than randomizing *during* the ranking, rank solely by quality/match
|
||||
# and randomize the top half of the ranked results.
|
||||
# Resulting in more relevance and still more freshness.
|
||||
|
||||
def more_tag_weight_randomized_at_end_experiment
|
||||
@randomness = 0
|
||||
results = more_tag_weight_experiment
|
||||
first_half(results).shuffle + last_half(results)
|
||||
end
|
||||
|
||||
def more_experience_level_weight_randomized_at_end_experiment
|
||||
@randomness = 0
|
||||
results = more_experience_level_weight_experiment
|
||||
first_half(results).shuffle + last_half(results)
|
||||
end
|
||||
|
||||
def more_comments_randomized_at_end_experiment
|
||||
@randomness = 0
|
||||
results = more_comments_experiment
|
||||
first_half(results).shuffle + last_half(results)
|
||||
end
|
||||
|
||||
def rank_and_sort_articles(articles)
|
||||
ranked_articles = articles.each_with_object({}) do |article, result|
|
||||
article_points = score_single_article(article)
|
||||
|
|
@ -176,7 +205,7 @@ module Articles
|
|||
|
||||
def globally_hot_articles(user_signed_in)
|
||||
hot_stories = published_articles_by_tag.
|
||||
where("score > ? OR featured = ?", 8, true).
|
||||
where("score > ? OR featured = ?", 7, true).
|
||||
order("hotness_score DESC")
|
||||
featured_story = hot_stories.where.not(main_image: nil).first
|
||||
if user_signed_in
|
||||
|
|
@ -203,5 +232,13 @@ module Articles
|
|||
def user_following_users_ids
|
||||
@user_following_users_ids ||= (@user&.cached_following_users_ids || [])
|
||||
end
|
||||
|
||||
def first_half(array)
|
||||
array[0...(array.length / 2)]
|
||||
end
|
||||
|
||||
def last_half(array)
|
||||
array[(array.length / 2)..array.length]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,15 +9,21 @@ experiments:
|
|||
- more_comments_experiment
|
||||
- more_experience_level_weight_experiment
|
||||
- mix_of_everything_experiment
|
||||
- more_tag_weight_randomized_at_end_experiment
|
||||
- more_experience_level_weight_randomized_at_end_experiment
|
||||
- more_comments_randomized_at_end_experiment
|
||||
weights:
|
||||
- 25
|
||||
- 5
|
||||
- 10
|
||||
- 10
|
||||
- 15
|
||||
- 5
|
||||
- 5
|
||||
- 10
|
||||
- 10
|
||||
- 10
|
||||
- 5
|
||||
- 10
|
||||
- 5
|
||||
goals:
|
||||
- user_creates_comment
|
||||
- user_creates_reaction
|
||||
|
|
|
|||
|
|
@ -1,5 +1,18 @@
|
|||
require "rails_helper"
|
||||
|
||||
NON_DEFAULT_EXPERIMENTS = %i[
|
||||
default_home_feed_with_more_randomness_experiment
|
||||
mix_default_and_more_random_experiment
|
||||
more_tag_weight_experiment
|
||||
more_tag_weight_more_random_experiment
|
||||
more_comments_experiment
|
||||
more_experience_level_weight_experiment
|
||||
more_tag_weight_randomized_at_end_experiment
|
||||
more_experience_level_weight_randomized_at_end_experiment
|
||||
more_comments_randomized_at_end_experiment
|
||||
mix_of_everything_experiment
|
||||
].freeze
|
||||
|
||||
RSpec.describe Articles::Feed, type: :service do
|
||||
let(:user) { create(:user) }
|
||||
let!(:feed) { described_class.new(user: user, number_of_articles: 100, page: 1) }
|
||||
|
|
@ -137,63 +150,14 @@ RSpec.describe Articles::Feed, type: :service do
|
|||
end
|
||||
end
|
||||
|
||||
describe "#default_home_feed_with_more_randomness_experiment" do
|
||||
let!(:new_story) { create(:article, published_at: 10.minutes.ago, score: 10) }
|
||||
let(:stories) { feed.default_home_feed_with_more_randomness_experiment }
|
||||
|
||||
it "includes stories" do
|
||||
expect(stories).to include(old_story)
|
||||
expect(stories).to include(new_story)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#mix_default_and_more_random_experiment" do
|
||||
let!(:new_story) { create(:article, published_at: 10.minutes.ago, score: 10) }
|
||||
let(:stories) { feed.mix_default_and_more_random_experiment }
|
||||
|
||||
it "includes stories" do
|
||||
expect(stories).to include(old_story)
|
||||
expect(stories).to include(new_story)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#more_tag_weight_experiment" do
|
||||
let!(:new_story) { create(:article, published_at: 10.minutes.ago, score: 10) }
|
||||
let(:stories) { feed.more_tag_weight_experiment }
|
||||
|
||||
it "includes stories" do
|
||||
expect(stories).to include(old_story)
|
||||
expect(stories).to include(new_story)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#more_experience_level_weight_experiment" do
|
||||
let!(:new_story) { create(:article, published_at: 10.minutes.ago, score: 10) }
|
||||
let(:stories) { feed.more_experience_level_weight_experiment }
|
||||
|
||||
it "includes stories" do
|
||||
expect(stories).to include(old_story)
|
||||
expect(stories).to include(new_story)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#more_tag_weight_more_random_experiment" do
|
||||
let!(:new_story) { create(:article, published_at: 10.minutes.ago, score: 10) }
|
||||
let(:stories) { feed.more_tag_weight_more_random_experiment }
|
||||
|
||||
it "includes stories" do
|
||||
expect(stories).to include(old_story)
|
||||
expect(stories).to include(new_story)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#mix_of_everything_experiment" do
|
||||
let!(:new_story) { create(:article, published_at: 10.minutes.ago, score: 10) }
|
||||
let(:stories) { feed.mix_of_everything_experiment }
|
||||
|
||||
it "includes stories" do
|
||||
expect(stories).to include(old_story)
|
||||
expect(stories).to include(new_story)
|
||||
describe "all non-default experiments" do
|
||||
it "returns articles for all experiments" do
|
||||
new_story = create(:article, published_at: 10.minutes.ago, score: 10)
|
||||
NON_DEFAULT_EXPERIMENTS.each do |method|
|
||||
stories = feed.default_home_feed_with_more_randomness_experiment
|
||||
expect(stories).to include(old_story)
|
||||
expect(stories).to include(new_story)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue