Skip to content

Commit

Permalink
handle mixed stale and fresh recommendations in non-hybrid feed for l…
Browse files Browse the repository at this point in the history
…oad more
  • Loading branch information
b0b3rt committed May 15, 2024
1 parent d325027 commit b8f776b
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 31 deletions.
39 changes: 17 additions & 22 deletions packages/lesswrong/components/posts/RecombeePostsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,34 +75,29 @@ const isWithinLoadMoreWindow = (recGeneratedAt: Date) => {
};

const getLoadMoreSettings = (resolverName: RecombeeResolver, results: RecommendedPost[], loadMoreCount: number): LoadMoreSettings => {
const staleRecommIds = filterNonnull(uniq(
results
.filter(({ generatedAt }) => generatedAt && !isWithinLoadMoreWindow(generatedAt))
.map(({ recommId }) => recommId)
));

const staleRecomms = results.filter(({ recommId }) => recommId && staleRecommIds.includes(recommId));
const freshRecomms = results.filter(({ recommId }) => recommId && !staleRecommIds.includes(recommId));

const excludedPostIds = staleRecomms.map(({ post: { _id } }) => _id);
const [firstRecommId, secondRecommId] = filterNonnull(uniq(freshRecomms.map(({ recommId }) => recommId)));

switch (resolverName) {
case DEFAULT_RESOLVER_NAME: {
const prevRecomm = results.find((result): result is RecombeeRecommendedPost => !!result.recommId);
if (!prevRecomm) {
return undefined;
}

const isStale = prevRecomm.generatedAt && !isWithinLoadMoreWindow(prevRecomm.generatedAt);
if (isStale) {
const excludedPostIds = results.filter(({ recommId }) => prevRecomm.recommId === recommId).map(({ post: { _id } }) => _id);
if (staleRecomms.length && !freshRecomms.length) {
return { excludedPostIds };
} else if (!staleRecomms.length && freshRecomms.length) {
return { loadMore: { prevRecommId: firstRecommId } };
} else {
return { excludedPostIds, loadMore: { prevRecommId: firstRecommId } };
}

return { loadMore: { prevRecommId: prevRecomm.recommId } };
}
case HYBRID_RESOLVER_NAME: {
const staleRecommIds = filterNonnull(uniq(
results
.filter(({ generatedAt }) => generatedAt && !isWithinLoadMoreWindow(generatedAt))
.map(({ recommId }) => recommId)
));

const staleRecomms = results.filter(({ recommId }) => recommId && staleRecommIds.includes(recommId));
const freshRecomms = results.filter(({ recommId }) => recommId && !staleRecommIds.includes(recommId));

const excludedPostIds = staleRecomms.map(({ post: { _id } }) => _id);
const [firstRecommId, secondRecommId] = filterNonnull(uniq(freshRecomms.map(({ recommId }) => recommId)));

if (staleRecomms.length && !freshRecomms.length) {
return { excludedPostIds, loadMore: { prevRecommIds: [undefined, undefined], loadMoreCount } };
} else if (!staleRecomms.length && freshRecomms.length) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,14 +123,14 @@ export interface RecombeeConfiguration {
loadMore?: {
prevRecommId?: string,
},
excludedPostIds?: string[],
}

export interface RecombeeRecommendationArgs extends RecombeeConfiguration {
// Note: these filters will not obviously be functional, check current implementation to see if used successfully
onlyUnread?: boolean,
lwRationalityOnly?: boolean,
scenario: string,
excludedPostIds?: string[],
}

export interface HybridRecombeeConfiguration {
Expand Down
20 changes: 12 additions & 8 deletions packages/lesswrong/server/recombee/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ const helpers = {
},

async getOnsitePostInfo(lwAlgoSettings: HybridRecombeeConfiguration | RecombeeConfiguration, context: ResolverContext, skipOnLoadMore = true): Promise<OnsitePostRecommendationsInfo> {
if (lwAlgoSettings.loadMore && skipOnLoadMore) {
if (helpers.isLoadMoreOperation(lwAlgoSettings) && skipOnLoadMore) {
return {
curatedPostIds: [],
stickiedPostIds: [],
Expand Down Expand Up @@ -348,7 +348,7 @@ const helpers = {
},

getCuratedPostsReadStatuses(lwAlgoSettings: HybridRecombeeConfiguration | RecombeeConfiguration, curatedPostIds: string[], userId: string, context: ResolverContext) {
return lwAlgoSettings.loadMore
return helpers.isLoadMoreOperation(lwAlgoSettings)
? Promise.resolve([])
: context.ReadStatuses.find({ postId: { $in: curatedPostIds.slice(1) }, userId, isRead: true }).fetch();
},
Expand Down Expand Up @@ -477,6 +477,10 @@ const helpers = {
...getParentTraceId()
});
},

isLoadMoreOperation(lwAlgoSettings: HybridRecombeeConfiguration | RecombeeConfiguration) {
return !!(lwAlgoSettings.loadMore || lwAlgoSettings.excludedPostIds);
},
};

const curatedPostTerms: PostsViewTerms = {
Expand All @@ -486,13 +490,13 @@ const curatedPostTerms: PostsViewTerms = {

const recombeeApi = {
async getRecommendationsForUser(userId: string, count: number, lwAlgoSettings: RecombeeRecommendationArgs, context: ResolverContext) {
const reqIsLoadMore = helpers.isLoadMoreOperation(lwAlgoSettings);
const { curatedPostIds, stickiedPostIds, excludedPostFilter } = await helpers.getOnsitePostInfo(lwAlgoSettings, context);

const curatedPostReadStatuses = await helpers.getCuratedPostsReadStatuses(lwAlgoSettings, curatedPostIds, userId, context);

const isLoadMoreOperation = !!(lwAlgoSettings.loadMore || lwAlgoSettings.excludedPostIds);
const includedCuratedPostIds = curatedPostIds.filter(id => !curatedPostReadStatuses.find(readStatus => readStatus.postId === id));
const includedCuratedAndStickiedPostIds = isLoadMoreOperation
const includedCuratedAndStickiedPostIds = reqIsLoadMore
? []
: [...includedCuratedPostIds, ...stickiedPostIds];

Expand All @@ -504,7 +508,7 @@ const recombeeApi = {
recRequest: recommendationsRequestBody,
scenario: lwAlgoSettings.scenario,
batch: false,
skipCache: isLoadMoreOperation,
skipCache: reqIsLoadMore,
context
});

Expand All @@ -527,11 +531,11 @@ const recombeeApi = {
const { curatedPostIds, stickiedPostIds, excludedPostFilter } = await helpers.getOnsitePostInfo(lwAlgoSettings, context, false);

const curatedPostReadStatuses = await helpers.getCuratedPostsReadStatuses(lwAlgoSettings, curatedPostIds, userId, context);
const isLoadMoreOperation = !!(lwAlgoSettings.loadMore || lwAlgoSettings.excludedPostIds);
const reqIsLoadMore = helpers.isLoadMoreOperation(lwAlgoSettings);
const includedCuratedPostIds = curatedPostIds.filter(id => !curatedPostReadStatuses.find(readStatus => readStatus.postId === id));
const excludeFromLatestPostIds = [...includedCuratedPostIds, ...stickiedPostIds];
// We only want to fetch the curated and stickied posts if this is the first load, not on any load more
const includedCuratedAndStickiedPostIds = isLoadMoreOperation
const includedCuratedAndStickiedPostIds = reqIsLoadMore
? []
: excludeFromLatestPostIds;

Expand Down Expand Up @@ -562,7 +566,7 @@ const recombeeApi = {
recRequest: recombeeRequest,
scenario: recombeeRequestSettings.scenario,
batch: true,
skipCache: isLoadMoreOperation,
skipCache: reqIsLoadMore,
context
});
} catch (err) {
Expand Down

0 comments on commit b8f776b

Please sign in to comment.