ガイドに戻る技術仕様書
SPEC DOCUMENT

スコアリングシステム仕様書

投稿候補のエンゲージメント予測から最終ランキングスコア算出までの技術仕様

1.概要

Xアルゴリズムのスコアリングシステムは、投稿候補に対してユーザーエンゲージメントを予測し、最終的なランキングスコアを算出します。本システムは複数のScorerコンポーネントで構成され、パイプライン形式で順次処理を行います。

1.1アーキテクチャ

スコアリングパイプライン
入力

投稿候補

1

PhoenixScorer

2

WeightedScorer

3

AuthorDiversityScorer

4

OONScorer

出力

最終スコア

1.2Scorerトレイト

すべてのScorerは共通のトレイトを実装します:

Scorer トレイト定義rust
pub trait Scorer<Q, C>: Send + Sync {
    /// 実行可否の判定
    fn enable(&self, _query: &Q) -> bool { true }

    /// 候補のスコアリング(非同期)
    async fn score(&self, query: &Q, candidates: &[C]) -> Result<Vec<C>, String>;

    /// 単一候補の更新
    fn update(&self, candidate: &mut C, scored: C);

    /// 全候補の一括更新
    fn update_all(&self, candidates: &mut [C], scored: Vec<C>);
}

重要

scoreメソッドは入力と同じ順序・同じ数の候補を返す必要があります。候補の削除はScorerではなくFilterステージで行います。

2.Phoenix Scorer

2.1概要

Phoenix ScorerはPhoenixモデルを用いて、各投稿に対するユーザーアクションの発生確率を予測します。

2.2入力

  • user_id: ユーザーID
  • user_action_sequence: ユーザーの過去のアクション履歴
  • tweet_infos: 投稿情報(ツイートID、著者ID)

リツイートの場合、元ツイートのIDと著者IDを使用します:

rust
let tweet_id = c.retweeted_tweet_id.unwrap_or(c.tweet_id as u64);
let author_id = c.retweeted_user_id.unwrap_or(c.author_id);

2.3予測アクション一覧

ポジティブアクション(離散)

アクション名内部名説明
いいねServerTweetFavツイートにいいねを付ける
リプライServerTweetReplyツイートに返信する
リツイートServerTweetRetweetツイートをリツイートする
引用ServerTweetQuote引用ツイートを作成する
画像展開ClientTweetPhotoExpand画像を展開して表示する
クリックClientTweetClickツイート詳細を開く
プロフィールクリックClientTweetClickProfile著者プロフィールを閲覧する
ビデオ品質視聴ClientTweetVideoQualityView動画を一定時間視聴する
シェアClientTweetShareツイートをシェアする
DMでシェアClientTweetClickSendViaDirectMessageDMでツイートを共有する
リンクコピーClientTweetShareViaCopyLinkツイートリンクをコピーする
滞在ClientTweetRecapDwelledツイート上で滞在する
引用クリックClientQuotedTweetClick引用元ツイートをクリックする
フォローClientTweetFollowAuthor著者をフォローする

ネガティブアクション(離散)

アクション名内部名説明
興味なしClientTweetNotInterestedIn「興味がない」を選択する
ブロックClientTweetBlockAuthor著者をブロックする
ミュートClientTweetMuteAuthor著者をミュートする
報告ClientTweetReportツイートを報告する

連続アクション

アクション名内部名説明
滞在時間DwellTimeツイート上での滞在時間(秒)

2.4ログ確率からの変換

Phoenixモデルはアクションのログ確率を出力します。これを確率に変換します:

rust
let action_probs: HashMap<usize, f64> = distribution
    .top_log_probs
    .iter()
    .enumerate()
    .map(|(idx, log_prob)| (idx, (*log_prob as f64).exp()))
    .collect();

数学的表現

P(action) = exp(log_prob)

2.5出力: PhoenixScores

PhoenixScores 構造体rust
pub struct PhoenixScores {
    pub favorite_score: Option<f64>,        // いいね確率
    pub reply_score: Option<f64>,           // リプライ確率
    pub retweet_score: Option<f64>,         // リツイート確率
    pub photo_expand_score: Option<f64>,    // 画像展開確率
    pub click_score: Option<f64>,           // クリック確率
    pub profile_click_score: Option<f64>,   // プロフィールクリック確率
    pub vqv_score: Option<f64>,             // ビデオ品質視聴確率
    pub share_score: Option<f64>,           // シェア確率
    pub share_via_dm_score: Option<f64>,    // DMシェア確率
    pub share_via_copy_link_score: Option<f64>, // リンクコピー確率
    pub dwell_score: Option<f64>,           // 滞在確率
    pub quote_score: Option<f64>,           // 引用確率
    pub quoted_click_score: Option<f64>,    // 引用クリック確率
    pub follow_author_score: Option<f64>,   // フォロー確率
    pub not_interested_score: Option<f64>,  // 興味なし確率
    pub block_author_score: Option<f64>,    // ブロック確率
    pub mute_author_score: Option<f64>,     // ミュート確率
    pub report_score: Option<f64>,          // 報告確率
    pub dwell_time: Option<f64>,            // 予測滞在時間
}

3.Weighted Scorer

3.1概要

Weighted Scorerは、Phoenix Scorerが出力した各アクション確率に重みを掛け合わせ、最終的な重み付きスコアを算出します。

3.2重み計算式

基本計算式

Final Score = Σ (weight_i × P(action_i))
詳細な計算式rust
combined_score =
    favorite_score × FAVORITE_WEIGHT
  + reply_score × REPLY_WEIGHT
  + retweet_score × RETWEET_WEIGHT
  + photo_expand_score × PHOTO_EXPAND_WEIGHT
  + click_score × CLICK_WEIGHT
  + profile_click_score × PROFILE_CLICK_WEIGHT
  + vqv_score × VQV_WEIGHT (条件付き)
  + share_score × SHARE_WEIGHT
  + share_via_dm_score × SHARE_VIA_DM_WEIGHT
  + share_via_copy_link_score × SHARE_VIA_COPY_LINK_WEIGHT
  + dwell_score × DWELL_WEIGHT
  + quote_score × QUOTE_WEIGHT
  + quoted_click_score × QUOTED_CLICK_WEIGHT
  + dwell_time × CONT_DWELL_TIME_WEIGHT
  + follow_author_score × FOLLOW_AUTHOR_WEIGHT
  + not_interested_score × NOT_INTERESTED_WEIGHT
  + block_author_score × BLOCK_AUTHOR_WEIGHT
  + mute_author_score × MUTE_AUTHOR_WEIGHT
  + report_score × REPORT_WEIGHT

3.3アクション重みの分類

ポジティブアクション重み

アクション重みパラメータ説明
いいねFAVORITE_WEIGHTエンゲージメントの基本指標
リプライREPLY_WEIGHT会話参加の意思を示す
リツイートRETWEET_WEIGHT拡散価値の高いコンテンツ
画像展開PHOTO_EXPAND_WEIGHT視覚コンテンツへの興味
クリックCLICK_WEIGHT詳細閲覧の意思
プロフィールクリックPROFILE_CLICK_WEIGHT著者への興味
シェアSHARE_WEIGHT外部共有の意思
DMシェアSHARE_VIA_DM_WEIGHTプライベート共有
リンクコピーSHARE_VIA_COPY_LINK_WEIGHT外部参照の意図
滞在DWELL_WEIGHTコンテンツ消費時間
引用QUOTE_WEIGHTコメント付き拡散
引用クリックQUOTED_CLICK_WEIGHT引用元への興味
滞在時間CONT_DWELL_TIME_WEIGHT連続的な滞在時間
フォローFOLLOW_AUTHOR_WEIGHT継続的な関係構築

ネガティブアクション重み

注意

ネガティブアクションの重みは負の値を持ち、スコアを減少させます。
アクション重みパラメータ説明
興味なしNOT_INTERESTED_WEIGHT明示的な拒否
ブロックBLOCK_AUTHOR_WEIGHT強い拒否反応
ミュートMUTE_AUTHOR_WEIGHT中程度の拒否
報告REPORT_WEIGHT規約違反の可能性

3.4Video Quality View (VQV) 重み

VQV重みは動画投稿にのみ適用される条件付き重みです:

VQV重み適用判定rust
fn vqv_weight_eligibility(candidate: &PostCandidate) -> f64 {
    if candidate.video_duration_ms.is_some_and(|ms| ms > MIN_VIDEO_DURATION_MS) {
        VQV_WEIGHT
    } else {
        0.0
    }
}

適用条件:

  • - 投稿に動画が含まれている(video_duration_msが存在)
  • - 動画の長さが最小閾値(MIN_VIDEO_DURATION_MS)を超えている

3.5スコアオフセット処理

負のスコアを適切に処理するためのオフセット計算:

オフセット処理rust
fn offset_score(combined_score: f64) -> f64 {
    if WEIGHTS_SUM == 0.0 {
        combined_score.max(0.0)
    } else if combined_score < 0.0 {
        (combined_score + NEGATIVE_WEIGHTS_SUM) / WEIGHTS_SUM * NEGATIVE_SCORES_OFFSET
    } else {
        combined_score + NEGATIVE_SCORES_OFFSET
    }
}
  • WEIGHTS_SUM: 全重みの合計
  • NEGATIVE_WEIGHTS_SUM: ネガティブ重みの合計(絶対値)
  • NEGATIVE_SCORES_OFFSET: スコア調整用のオフセット値

4.Author Diversity Scorer

4.1概要

Author Diversity Scorerは、フィード内での著者の多様性を確保するため、同一著者の連続投稿に対してスコアを減衰させます。

4.2パラメータ

パラメータ説明
decay_factor減衰係数(0-1の範囲)
floorスコア乗数の下限値(最低保証)
デフォルト値rust
impl Default for AuthorDiversityScorer {
    fn default() -> Self {
        Self::new(AUTHOR_DIVERSITY_DECAY, AUTHOR_DIVERSITY_FLOOR)
    }
}

4.3減衰計算式

著者の投稿が表示されるたびに、その著者の次の投稿のスコア乗数が減少します:

減衰計算式

multiplier = (1 - floor) × decay_factor^position + floor
  • position: その著者の投稿が現れた回数(0から開始)
  • decay_factor: 減衰の速度を制御(例: 0.5)
  • floor: 乗数の最小値(例: 0.1)
乗数計算実装rust
fn multiplier(&self, position: usize) -> f64 {
    (1.0 - self.floor) * self.decay_factor.powf(position as f64) + self.floor
}

4.4減衰曲線の例

decay_factor = 0.5, floor = 0.1 の場合:

出現位置乗数
0 (初回)1.00
10.55
20.325
30.2125
40.15625
5+≒ 0.1 (floor)

4.5効果

連続表示の抑制

同一著者の投稿が連続して表示されることを抑制

多様性の向上

フィード全体の著者バリエーションを増加

UX改善

ユーザー体験の質を向上

5.Out-of-Network (OON) Scorer

5.1概要

OON Scorerは、ユーザーがフォローしていない著者(ネットワーク外)の投稿と、フォローしている著者(ネットワーク内)の投稿のバランスを調整します。

5.2インネットワーク優先係数

OON スコア調整rust
match c.in_network {
    Some(false) => base_score * OON_WEIGHT_FACTOR,
    _ => base_score,
}
投稿タイプスコア乗数
インネットワーク1.0 (変更なし)
アウトオブネットワークOON_WEIGHT_FACTOR

5.3効果

フォロー優先

フォローしている著者の投稿を優先表示

レコメンド制御

ネットワーク外投稿の露出を適切に制御

ソーシャルグラフ尊重

ユーザーの人間関係を尊重した表示

6.スコアの流れと最終出力

6.1スコアフィールド

PostCandidateには複数のスコアフィールドが存在します:

PostCandidate スコアフィールドrust
pub struct PostCandidate {
    // ...
    pub phoenix_scores: PhoenixScores,    // Phoenixモデルの予測結果
    pub weighted_score: Option<f64>,       // 重み付きスコア
    pub score: Option<f64>,                // 最終スコア
    // ...
}

6.2スコア計算パイプライン

スコア計算パイプライン詳細

PhoenixScorer

入力: 候補リスト + ユーザーアクション履歴

出力: phoenix_scores (各アクション確率)

WeightedScorer

入力: phoenix_scores

出力: weighted_score (重み付き合計)

AuthorDiversityScorer

入力: weighted_score

出力: score (多様性調整後)

OONScorer

入力: score

出力: score (ネットワーク調整後) ← 最終スコア

6.3スコア正規化

各段階でスコアの正規化が行われ、以下を保証します:

1. 比較可能性

スコアの比較可能性

2. 数値安定性

数値計算の安定性

3. 互換性

下流処理との互換性

7.設定パラメータ一覧

情報

すべてのスコアリング関連パラメータはparamsモジュールで定義されます(セキュリティ上の理由でオープンソースリリースから除外)。

7.1重みパラメータ

パラメータ名用途
FAVORITE_WEIGHTいいね重み
REPLY_WEIGHTリプライ重み
RETWEET_WEIGHTリツイート重み
PHOTO_EXPAND_WEIGHT画像展開重み
CLICK_WEIGHTクリック重み
PROFILE_CLICK_WEIGHTプロフィールクリック重み
VQV_WEIGHTビデオ品質視聴重み
SHARE_WEIGHTシェア重み
SHARE_VIA_DM_WEIGHTDMシェア重み
SHARE_VIA_COPY_LINK_WEIGHTリンクコピー重み
DWELL_WEIGHT滞在重み
QUOTE_WEIGHT引用重み
QUOTED_CLICK_WEIGHT引用クリック重み
CONT_DWELL_TIME_WEIGHT連続滞在時間重み
FOLLOW_AUTHOR_WEIGHTフォロー重み
NOT_INTERESTED_WEIGHT興味なし重み(負)
BLOCK_AUTHOR_WEIGHTブロック重み(負)
MUTE_AUTHOR_WEIGHTミュート重み(負)
REPORT_WEIGHT報告重み(負)

7.2多様性パラメータ

パラメータ名用途
AUTHOR_DIVERSITY_DECAY著者多様性の減衰係数
AUTHOR_DIVERSITY_FLOOR著者多様性の下限値

7.3ネットワークパラメータ

パラメータ名用途
OON_WEIGHT_FACTORネットワーク外重み係数

7.4動画パラメータ

パラメータ名用途
MIN_VIDEO_DURATION_MSVQV適用の最小動画長(ミリ秒)

7.5正規化パラメータ

パラメータ名用途
WEIGHTS_SUM全重みの合計
NEGATIVE_WEIGHTS_SUMネガティブ重みの合計
NEGATIVE_SCORES_OFFSET負スコアオフセット

8.関連ファイル

ファイル説明
/home-mixer/scorers/phoenix_scorer.rsPhoenix Scorer実装
/home-mixer/scorers/weighted_scorer.rsWeighted Scorer実装
/home-mixer/scorers/author_diversity_scorer.rsAuthor Diversity Scorer実装
/home-mixer/scorers/oon_scorer.rsOON Scorer実装
/home-mixer/candidate_pipeline/candidate.rsPostCandidate, PhoenixScores定義
/candidate-pipeline/scorer.rsScorerトレイト定義
X レコメンドアルゴリズム - オープンソース技術仕様書