File: intentional_user_model.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (130 lines) | stat: -rw-r--r-- 5,016 bytes parent folder | download | duplicates (9)
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