From f008971bd1ae71647143bddfdec7542594a58106 Mon Sep 17 00:00:00 2001 From: James Grugett Date: Sat, 30 Apr 2022 11:54:44 -0400 Subject: [PATCH] Compute recommendation scores from updateUserFeed --- common/recommended-contracts.ts | 34 ++++++------------------- functions/src/scripts/update-feed.ts | 6 ++--- functions/src/update-recommendations.ts | 14 +++------- functions/src/update-user-feed.ts | 24 ++++++----------- 4 files changed, 22 insertions(+), 56 deletions(-) diff --git a/common/recommended-contracts.ts b/common/recommended-contracts.ts index efbd6416..eb5cf4a7 100644 --- a/common/recommended-contracts.ts +++ b/common/recommended-contracts.ts @@ -142,36 +142,18 @@ export const getWordScores = ( return normalizedWordScores } -export function getContractScores( - contracts: Contract[], +export function getContractScore( + contract: Contract, wordScores: { [word: string]: number } ) { - const scorePairs = contracts.map((contract) => { - const wordFrequency = contractToWordFrequency(contract) - - const score = _.sumBy(Object.keys(wordFrequency), (word) => { - const wordFreq = wordFrequency[word] ?? 0 - const weight = wordScores[word] ?? 0 - return wordFreq * weight - }) - - return [contract, score] as [Contract, number] + const wordFrequency = contractToWordFrequency(contract) + const score = _.sumBy(Object.keys(wordFrequency), (word) => { + const wordFreq = wordFrequency[word] ?? 0 + const weight = wordScores[word] ?? 0 + return wordFreq * weight }) - /* - const questionPairs = _.sortBy( - scorePairs.map( - ([contract, score]) => [contract.question, score] as [string, number] - ), - ([, score]) => -score - ) - - console.log('score', questionPairs.slice(0, 100), questionPairs.slice(-100)) - */ - - return _.fromPairs( - scorePairs.map(([contract, score]) => [contract.id, score]) - ) + return score } // Caluculate Term Frequency-Inverse Document Frequency (TF-IDF): diff --git a/functions/src/scripts/update-feed.ts b/functions/src/scripts/update-feed.ts index 6932e134..3a30f85a 100644 --- a/functions/src/scripts/update-feed.ts +++ b/functions/src/scripts/update-feed.ts @@ -8,7 +8,7 @@ import { getValues } from '../utils' import { User } from '../../../common/user' import { batchedWaitAll } from '../../../common/util/promise' import { Contract } from '../../../common/contract' -import { updateUserRecommendations } from '../update-recommendations' +import { updateWordScores } from '../update-recommendations' import { getFeedContracts, updateFeed as updateUserFeed, @@ -23,13 +23,13 @@ async function updateFeed() { const feedContracts = await getFeedContracts() const users = await getValues( firestore.collection('users') - //.where('username', '==', 'JamesGrugett') + // .where('username', '==', 'JamesGrugett') ) await batchedWaitAll( users.map((user) => async () => { console.log('Updating recs for', user.username) - await updateUserRecommendations(user, contracts) + await updateWordScores(user, contracts) console.log('Updating feed for', user.username) await updateUserFeed(user, feedContracts) }) diff --git a/functions/src/update-recommendations.ts b/functions/src/update-recommendations.ts index 95868583..392f6393 100644 --- a/functions/src/update-recommendations.ts +++ b/functions/src/update-recommendations.ts @@ -7,10 +7,7 @@ import { Contract } from '../../common/contract' import { Bet } from '../../common/bet' import { User } from '../../common/user' import { ClickEvent } from '../../common/tracking' -import { - getContractScores, - getWordScores, -} from '../../common/recommended-contracts' +import { getWordScores } from '../../common/recommended-contracts' import { batchedWaitAll } from '../../common/util/promise' const firestore = admin.firestore() @@ -25,14 +22,11 @@ export const updateRecommendations = functions.pubsub const users = await getValues(firestore.collection('users')) await batchedWaitAll( - users.map((user) => () => updateUserRecommendations(user, contracts)) + users.map((user) => () => updateWordScores(user, contracts)) ) }) -export const updateUserRecommendations = async ( - user: User, - contracts: Contract[] -) => { +export const updateWordScores = async (user: User, contracts: Contract[]) => { const [bets, viewCounts, clicks] = await Promise.all([ getValues( firestore.collectionGroup('bets').where('userId', '==', user.id) @@ -50,11 +44,9 @@ export const updateUserRecommendations = async ( ]) const wordScores = getWordScores(contracts, viewCounts ?? {}, clicks, bets) - const contractScores = getContractScores(contracts, wordScores) const cachedCollection = firestore.collection( `private-users/${user.id}/cache` ) await cachedCollection.doc('wordScores').set(wordScores) - await cachedCollection.doc('contractScores').set(contractScores) } diff --git a/functions/src/update-user-feed.ts b/functions/src/update-user-feed.ts index 924d807e..9242be85 100644 --- a/functions/src/update-user-feed.ts +++ b/functions/src/update-user-feed.ts @@ -15,6 +15,7 @@ import { Bet } from '../../common/bet' import { Comment } from '../../common/comment' import { User } from '../../common/user' import { batchedWaitAll } from '../../common/util/promise' +import { getContractScore } from '../../common/recommended-contracts' const firestore = admin.firestore() @@ -59,27 +60,17 @@ export const updateFeed = async (user: User, contracts: Contract[]) => { const userCacheCollection = firestore.collection( `private-users/${user.id}/cache` ) - const [recommendationScores, lastViewedTime] = await Promise.all([ - getValue<{ [contractId: string]: number }>( - userCacheCollection.doc('contractScores') - ), + const [wordScores, lastViewedTime] = await Promise.all([ + getValue<{ [word: string]: number }>(userCacheCollection.doc('wordScores')), getValue<{ [contractId: string]: number }>( userCacheCollection.doc('lastViewTime') ), ]).then((dicts) => dicts.map((dict) => dict ?? {})) - const averageRecScore = - 1 + - _.sumBy( - contracts.filter((c) => recommendationScores[c.id] !== undefined), - (c) => recommendationScores[c.id] - ) / - (contracts.length + 1) - const scoredContracts = contracts.map((contract) => { const score = scoreContract( contract, - recommendationScores[contract.id] ?? averageRecScore, + wordScores, lastViewedTime[contract.id] ) return [contract, score] as [Contract, number] @@ -105,12 +96,13 @@ export const updateFeed = async (user: User, contracts: Contract[]) => { function scoreContract( contract: Contract, - recommendationScore: number, + wordScores: { [word: string]: number }, viewTime: number | undefined ) { - const lastViewedScore = getLastViewedScore(viewTime) + const recommendationScore = getContractScore(contract, wordScores) const activityScore = getActivityScore(contract, viewTime) - return recommendationScore * lastViewedScore * activityScore + const lastViewedScore = getLastViewedScore(viewTime) + return recommendationScore * activityScore * lastViewedScore } function getActivityScore(contract: Contract, viewTime: number | undefined) {