1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/segmentation_platform/embedder/default_model/intentional_user_model.h"
#include <array>
#include "base/task/sequenced_task_runner.h"
#include "components/segmentation_platform/internal/metadata/metadata_writer.h"
#include "components/segmentation_platform/public/config.h"
#include "components/segmentation_platform/public/constants.h"
#include "components/segmentation_platform/public/features.h"
#include "components/segmentation_platform/public/model_provider.h"
#include "components/segmentation_platform/public/proto/model_metadata.pb.h"
namespace segmentation_platform {
namespace {
using proto::SegmentId;
// Default parameters for intentional user model.
constexpr SegmentId kIntentionalUserSegmentId =
SegmentId::INTENTIONAL_USER_SEGMENT;
// Store 28 buckets of input data (28 days).
constexpr int64_t kIntentionalUserSignalStorageLength = 28;
// Wait until we have 7 days of data.
constexpr int64_t kIntentionalUserMinSignalCollectionLength = 7;
// Refresh result every 7 days.
constexpr int64_t kIntentionalUserResultTTLDays = 7;
// Threshold for our heuristic, if the user launched Chrome directly at least 2
// times in the last 28 days then we consider them an intentional user.
constexpr int64_t kIntentionalLaunchThreshold = 2;
constexpr int64_t kIntentionalUserModelVersion = 2;
// InputFeatures.
// MobileStartup.LaunchCause enum values to record an aggregate, these values
// come from LaunchCauseMetrics.LaunchCause.
constexpr std::array<int32_t, 1> kLaunchCauseMainLauncherIcon{
6 // MAIN_LAUNCHER_ICON.
};
// Set UMA metrics to use as input.
constexpr std::array<MetadataWriter::UMAFeature, 1>
kIntentionalUserUMAFeatures = {
// This input is the sum of all times MobileStartup.LaunchCause was
// recorded with a value of MAIN_LAUNCHER_ICON in the last 28 days.
MetadataWriter::UMAFeature::FromEnumHistogram(
"MobileStartup.LaunchCause",
/* This is the number of buckets to store and aggregate, each bucket
is 1 day according to kIntentionalUserTimeUnit and
kIntentionalUserBucketDuration. */
28,
kLaunchCauseMainLauncherIcon.data(),
kLaunchCauseMainLauncherIcon.size())};
} // namespace
// static
std::unique_ptr<Config> IntentionalUserModel::GetConfig() {
if (!base::FeatureList::IsEnabled(
features::kSegmentationPlatformIntentionalUser)) {
return nullptr;
}
auto config = std::make_unique<Config>();
config->segmentation_key = kIntentionalUserKey;
config->segmentation_uma_name = kIntentionalUserUmaName;
config->AddSegmentId(SegmentId::INTENTIONAL_USER_SEGMENT,
std::make_unique<IntentionalUserModel>());
config->auto_execute_and_cache = true;
config->is_boolean_segment = true;
return config;
}
IntentionalUserModel::IntentionalUserModel()
: DefaultModelProvider(kIntentionalUserSegmentId) {}
std::unique_ptr<DefaultModelProvider::ModelConfig>
IntentionalUserModel::GetModelConfig() {
proto::SegmentationModelMetadata intentional_user_metadata;
MetadataWriter writer(&intentional_user_metadata);
writer.SetDefaultSegmentationMetadataConfig(
kIntentionalUserMinSignalCollectionLength,
kIntentionalUserSignalStorageLength);
// If the result from ExecuteModelWithInput is greater than 0.5 then return
// the intentional user label, otherwise return the non-intentional label.
writer.AddOutputConfigForBinaryClassifier(
/*threshold=*/0.5f, /*positive_label=*/
SegmentIdToHistogramVariant(SegmentId::INTENTIONAL_USER_SEGMENT),
/*negative_label=*/kLegacyNegativeLabel);
writer.AddPredictedResultTTLInOutputConfig(
/*top_label_to_ttl_list=*/{},
/*default_ttl=*/kIntentionalUserResultTTLDays,
/*time_unit=*/proto::TimeUnit::DAY);
// Set features.
writer.AddUmaFeatures(kIntentionalUserUMAFeatures.data(),
kIntentionalUserUMAFeatures.size());
return std::make_unique<ModelConfig>(std::move(intentional_user_metadata),
kIntentionalUserModelVersion);
}
void IntentionalUserModel::ExecuteModelWithInput(
const ModelProvider::Request& inputs,
ExecutionCallback callback) {
// Invalid inputs.
if (inputs.size() != kIntentionalUserUMAFeatures.size()) {
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), std::nullopt));
return;
}
const int main_launcher_clicks = inputs[0];
float result = 0;
if (main_launcher_clicks >= kIntentionalLaunchThreshold) {
result = 1; // User is intentionally using Chrome.
}
base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), ModelProvider::Response(1, result)));
}
} // namespace segmentation_platform
|