def recommendations(guid): """Return a list of recommendations provided a telemetry client_id.""" # Use the module global PROXY_MANAGER global PROXY_MANAGER if PROXY_MANAGER.getResource() is None: ctx = default_context() # Lock the context down after we've got basic bits installed root_ctx = ctx.child() instance = GuidBasedRecommender(root_ctx) PROXY_MANAGER.setResource(instance) instance = PROXY_MANAGER.getResource() cdict = {'guid': guid} recommendations = instance.recommend(client_data=cdict, limit=TAAR_MAX_RESULTS) # Strip out weights from TAAR results to maintain compatibility # with TAAR 1.0 jdata = {"results": [x[0] for x in recommendations]} response = app.response_class(response=json.dumps(jdata), status=200, mimetype='application/json') return response
def test_guidception(default_ctx, MOCK_DATA, MOCK_GUID_RANKING): EXPECTED_RESULTS = RESULTS['guidception'] install_mock_data(MOCK_DATA, MOCK_GUID_RANKING, default_ctx) recommender = GuidBasedRecommender(default_ctx) guid = "guid-2" actual = recommender.recommend({'guid': guid, 'normalize': 'guidception'}) assert actual == EXPECTED_RESULTS
def test_rownorm_sum_tiebreak(default_ctx, TIE_MOCK_DATA, MOCK_GUID_RANKING): EXPECTED_RESULTS = RESULTS['rownorm_sum_tiebreak'] install_mock_data(TIE_MOCK_DATA, MOCK_GUID_RANKING, default_ctx) recommender = GuidBasedRecommender(default_ctx) guid = "guid-2" actual = recommender.recommend({'guid': guid, 'normalize': 'rownorm_sum'}) # Note that the results have weights that are equal, but the tie # break is solved by the install rate. assert actual == EXPECTED_RESULTS
def test_row_count_recommender(default_ctx, MOCK_DATA, MOCK_GUID_RANKING): EXPECTED_RESULTS = RESULTS['row_count'] install_mock_data(MOCK_DATA, MOCK_GUID_RANKING, default_ctx) recommender = GuidBasedRecommender(default_ctx) guid = "guid-2" actual = recommender.recommend({'guid': guid, 'normalize': 'row_count'}) # Note that guid-9 is not included because it's weight is # decreased 50% to 5 assert EXPECTED_RESULTS == actual
def test_rowsum_recommender(default_ctx, MOCK_DATA, MOCK_GUID_RANKING): EXPECTED_RESULTS = RESULTS['row_sum'] install_mock_data(MOCK_DATA, MOCK_GUID_RANKING, default_ctx) recommender = GuidBasedRecommender(default_ctx) guid = "guid-2" actual = recommender.recommend({'guid': guid, 'normalize': 'row_sum'}) assert 4 == len(actual) expected_val = 50 / 155 actual_val = float(actual[0][1][:-11]) assert expected_val == pytest.approx(actual_val, rel=1e-3) assert actual == EXPECTED_RESULTS
def test_logging(default_ctx, MOCK_DATA, MOCK_GUID_RANKING): conn = boto3.resource('s3', region_name='us-west-2') conn.create_bucket(Bucket=ADDON_LIST_BUCKET) conn.Object(ADDON_LIST_BUCKET, ADDON_LIST_KEY)\ .put(Body=json.dumps(MOCK_DATA)) conn.Object(ADDON_LIST_BUCKET, GUID_RANKING_KEY)\ .put(Body=json.dumps(MOCK_GUID_RANKING)) coinstall_loader = LazyJSONLoader(default_ctx, ADDON_LIST_BUCKET, ADDON_LIST_KEY) ranking_loader = LazyJSONLoader(default_ctx, ADDON_LIST_BUCKET, GUID_RANKING_KEY) default_ctx['coinstall_loader'] = coinstall_loader default_ctx['ranking_loader'] = ranking_loader recommender = GuidBasedRecommender(default_ctx) # These would error out if the object type was incorrect recommender.logger.error('foo') recommender.logger.warn('bar') recommender.logger.info('foo') recommender.logger.debug('bar')
def test_missing_rownorm_data_issue_31(default_ctx, TIE_MOCK_DATA, MOCK_GUID_RANKING): install_mock_data(TIE_MOCK_DATA, MOCK_GUID_RANKING, default_ctx) recommender = GuidBasedRecommender(default_ctx) EXPECTED_RESULTS = RESULTS['rownorm_sum_tiebreak'] # Explicitly destroy the guid-4 key in the row_norm data del recommender._guid_maps['guid_row_norm']['guid-4'] for i, row in enumerate(EXPECTED_RESULTS): if row[0] == 'guid-4': del EXPECTED_RESULTS[i] break guid = "guid-2" actual = recommender.recommend({'guid': guid, 'normalize': 'rownorm_sum'}) assert actual == EXPECTED_RESULTS
def recommendations(guid): """Return a list of recommendations provided a telemetry client_id.""" # Use the module global PROXY_MANAGER global PROXY_MANAGER if PROXY_MANAGER.getResource() is None: ctx = default_context() logger = ctx[IMozLogging].get_logger('taar-api-lite') ctx['CACHE_URL'] = CACHE_URL logger.info("Set CACHE_URL to: [{}]".format(ctx['CACHE_URL'])) # Lock the context down after we've got basic bits installed root_ctx = ctx.child() instance = GuidBasedRecommender(root_ctx) PROXY_MANAGER.setResource(instance) instance = PROXY_MANAGER.getResource() cdict = {'guid': guid} normalization_type = request.args.get('normalize', None) if normalization_type is not None: cdict['normalize'] = normalization_type recommendations = instance.recommend(client_data=cdict, limit=TAAR_MAX_RESULTS) if len(recommendations) != TAAR_MAX_RESULTS: recommendations = [] # Strip out weights from TAAR results to maintain compatibility # with TAAR 1.0 jdata = {"results": [x[0] for x in recommendations]} response = app.response_class( response=json.dumps(jdata), status=200, mimetype='application/json' ) return response
def test_divide_by_zero_rownorm_data_issue_31(default_ctx, TIE_MOCK_DATA, MOCK_GUID_RANKING): install_mock_data(TIE_MOCK_DATA, MOCK_GUID_RANKING, default_ctx) recommender = GuidBasedRecommender(default_ctx) EXPECTED_RESULTS = RESULTS['rownorm_sum_tiebreak'] # Explicitly set the guid-4 key in the row_norm data to have a sum # of zero weights recommender._guid_maps['guid_row_norm']['guid-4'] = [0, 0, 0] # Destroy the guid-4 key in the expected results as a sum of 0 # will generate a divide by zero error for i, row in enumerate(EXPECTED_RESULTS): if row[0] == 'guid-4': del EXPECTED_RESULTS[i] break guid = "guid-2" actual = recommender.recommend({'guid': guid, 'normalize': 'rownorm_sum'}) assert actual == EXPECTED_RESULTS
def test_rownorm_sumrownorm(default_ctx, MOCK_DATA, MOCK_GUID_RANKING): EXPECTED_RESULTS = RESULTS['rownorm_sum'] install_mock_data(MOCK_DATA, MOCK_GUID_RANKING, default_ctx) recommender = GuidBasedRecommender(default_ctx) guid = "guid-2" default_actual = recommender.recommend({'guid': guid}) actual = recommender.recommend({'guid': guid, 'normalize': 'rownorm_sum'}) # Default normalization is rownorm_sum assert actual == default_actual assert actual == EXPECTED_RESULTS """ Some notes on verifying guid-1: Numerator is the row weighted value of guid-1 : 50/150 Denominator is the sum of the row weighted value of guid-1 in all other rows (guid-2) 50/150 (guid-3) 100/210 (guid-6) 5/305 This gives us: [0.3333333333333333, 0.47619047619047616, 0.01639344262295082] so the final result should be (5/150) / (50/150 + 100/210 + 5/305) That gives a final expected weight for guid-1 to be: 0.403591682 """ expected = 0.403591682 actual = float(actual[1][1][:-11]) assert expected == pytest.approx(actual, rel=1e-3)
""" import json from srgutil.context import default_context from srgutil.interfaces import IS3Data from taar_lite.recommenders import GuidBasedRecommender ADDON_LIST_BUCKET = 'telemetry-parquet' WHITELIST_KEY = 'telemetry-ml/addon_recommender/whitelist_addons_database.json' ctx = default_context() cache = ctx[IS3Data] addon_whitelist = cache.get_s3_json_content(ADDON_LIST_BUCKET, WHITELIST_KEY) grec = GuidBasedRecommender(ctx) def compute_name(guid, addon_data): guid_name = addon_data['name'].get('en-US', None) if guid_name is None: guid_name = list(addon_data['name'].values())[0] return guid_name output = {} for guid in addon_whitelist.keys(): addon_data = addon_whitelist.get(guid, None) addon_url = addon_data['url'] addon_name = compute_name(guid, addon_data)