0x00

리서치 / 일일 리포트

  • 읽은 자료 1건(X 4세대+1 커밋 1개, Meta/Netflix 블로그 신규 0건, arXiv triage 30건 중 통과 1건 [DrEM])
  • 정본 반영 1개 파일(x.md 9개 절 갱신, 출처 6건 추가)
  • 다이어그램 갱신 1건(x-pipeline.svg 필터 17→18)
  • 레이더 갱신 1건(DrEM 소속 확정, A/B 수치 반영)
한 줄 요약X가 4세대 공개 다음 날 후속 커밋에서, 가중치는 행동 횟수가 아니라 예측 확률에 곱하는 값이라는 해석 규칙을 코드 주석에 밝혔다.

오늘 함께 본 다른 변화는 다음과 같다.

  • X는 같은 커밋에서, 브라질 2026 선거와 관련해 선거법원에 신고된 계정의 포스트를 뷰어가 그 계정을 팔로우하지 않는 한 For You에서 빼는 필터를 넣었다.
  • X 랭킹 모델의 bool 입력 3개가 처음으로 실제 값을 받기 시작했다.
  • Kuaishou의 앙상블 랭킹 논문 DrEM은 저자 소속 확인으로 프로덕션 논문임이 확정됐다.

1가중치 해석 규칙을 코드에 밝히고 브라질 선거 필터를 넣었다 — X

자료 xai-org/x-algorithm @ c65aa17 — "Open-source X Recommendation Algorithm" — 2026-08-14 20:55 UTC, 공개 소스코드. 이 노트들은 X 공개 소스의 4세대 공개(2026-08-13, 47c1bcd) 뒤에 나온 커밋에 차례로 번호를 붙여 부르며, 이 커밋은 4세대+1이다. 파일 21개가 바뀌었고 줄 수는 +2,271/−32다. 어제 공개된 4세대보다 규모는 작지만 성격은 매우 다양하다. 가중치 해석을 적은 문서화, 브라질 필터라는 규제 대응, Thompson sampling을 A/B 실험에 연결한 것, 랭킹 모델의 bool 입력 3종, 부정 계정 판정 노트를 만드는 labeling 파이프라인이 한 커밋에 섞여 있다. 관련 README도 함께 갱신됐다 #latest-updates → #august-14th-2026.

배경 어제 daily/2026-08-15.md에서 다룬 4세대 공개(47c1bcd, 2026-08-13)는 파일 300개 이상, 추가된 줄 +363K 규모였고, 파라미터 미러링, 노출 판정 서비스인 visibility-filtering, labeling 서브레포 15개를 전부 열었다. 새 README는 이 릴리즈가 "로직의 형태를 보여주는 것"에서 "값과 규칙을 검증 가능한 형태로 붙이는 것"으로 넘어왔다고 스스로 평가한다. 이번 커밋(4세대+1)은 그 다음 날 X가 추가한 4세대의 후속 정리이자 확장이며, 4세대의 성격을 하루 만에 다섯 방향으로 넓힌 셈이다. 그중 가중치 해석, 브라질 선거 필터, 랭킹 모델의 입력 피처라는 세 방향이 정본(canon, 서비스별 현재 이해를 담는 이 저장소의 노트)에 직접 영향을 준다.

새로 알게 된 것A. 가중치는 행동 횟수가 아니라 예측 확률에 곱하는 값이라고 X가 직접 밝혔다

  • home-mixer(For You 피드를 서빙하는 서비스)의 파라미터 파일 헤더 주석이 이 해석 규칙을 맨 앞에 적었다 확인 — home-mixer/params/param.rs:281-306.

    "Each weight multiplies the predicted probability of that action (P(favorite), P(repost), …) or a continuous value e.g. watch time -- the weights do not multiply raw engagement counts. One common misinterpretation is that you can read these weight ratios as count equivalences, e.g. the incorrect statement that 'one report cancels 468 likes' -- this is incorrect because the weights apply to the predicted probabilities rather than raw counts." — home-mixer/params/param.rs:283-292

  • 정본은 3세대까지 인용해 온 "reply 13.5 vs favorite 0.5 → 27배" 같은 서술을 여러 곳에서 써 왔다(예: multi-task-ranking.md). 이 서술이 원리적으로 잘못된 설명이라는 사실이 X 자신의 주석으로 확정됐다.

    • 가중치는 예측 확률에 곱해지므로 raw count의 비율이 아니다.
    • X는 4세대에서 파라미터 미러를 공개하면서, 판독 가이드가 없으면 이 값들이 오히려 오해를 낳는다는 점을 명시적으로 인정한 셈이다.
  • 같은 주석은 리포트 가중치의 절댓값이 왜 그렇게 커 보이는지도 이어서 설명한다.

    "And the baseline probability of a Report is more than 1000x lower than a Like, so it's weighted more to allow the prediction to affect the final ranking at all."

    • report −234라는 값의 크기는 가치 × 1/propensity의 곱이다. propensity는 그 행동이 일어날 기본 확률을 말한다.
    • 리포트의 propensity가 like에 비해 1000분의 1 이하이기 때문에 절댓값이 크게 나타난다.
    • 어제 정본에도 같은 방향의 주의 사항을 적어 두었는데, 이번에는 X가 코드 안에서 스스로 이렇게 서술했다.
  • 같은 주석은 대량 신고(mass reporting)에 관한 오해도 두 가지 이유를 들어 부정한다.

    "It's predicting your likelihood of the action, not summing up raw weights on counts. Also, recommendations are personalized, so reports from bad actors will primarily affect recommendations for users who are similar to the bad actors, rather than having the same effect on the post's ranking to everyone."

    • 정리하면, 봇 계정이 대량으로 리포트를 넣더라도 다음 두 가지가 성립한다.
      1. 스코어는 당신의 예측 확률이다. 그래서 대량 리포트는 그 봇들과 비슷한 유저의 추천에만 우선적으로 영향을 준다.
      2. Home Timeline에 서빙된 포스트에서 이뤄진 액션만 랭킹 신호로 반영된다. 그래서 그룹 채팅으로 링크를 공유해서 발생한 반응은 랭킹에 영향을 주지 않는다.
  • 같은 주석 블록은 home-mixer/scorers/ranking_scorer.rs:415-446에도 똑같이 들어갔고, README #scoring-and-ranking 절에도 같은 내용의 문단이 삽입됐다.

    • 세 곳에 같은 서술을 두어, 코드와 문서 중 어디를 읽더라도 오해하지 않도록 했다.

새로 알게 된 것B. For You는 브라질 2026 선거와 관련해 선거법원에 신고된 계정의 포스트를, 뷰어가 그 계정을 팔로우하지 않으면 뺀다

  • X는 브라질 선거법에 따라, 브라질 선거법원에 신고된 계정의 포스트를 For You에서 빼되 뷰어가 직접 팔로우한 계정은 남긴다고 공지했다 확인 — README.md #august-14th-2026.

    "As announced by X, in accordance with Brazilian electoral law, For You now runs Brazil2026ElectionFilter, which removes posts from accounts reported to Brazil's Electoral Court for the 2026 election, unless the viewer explicitly follows the account. A benefit of open-source is that you can see that changes like this exist, and exactly how they work — take a look at the code." — README.md, 공지 링크 @XBR

  • 관할권 필터를 코드에서 그대로 관찰할 수 있는 첫 사례가 나왔다. DSA와 GDPR, NetzDG 같은 규제 대응은 지금까지 대부분 규제 제출 문서(EU 투명성 리포트)를 통해서만 확인할 수 있었다.

  • 필터 이름은 Brazil2026ElectionFilter다. 이 필터는 브라질 선거법원(TSE)에 신고된 계정 665개를 코드 상수에 하드코딩하고, 각 ID 옆 주석에 계정 이름을 남긴다 확인 — brazil_2026_election_filter.rs:9-20.

    • 상수 위 주석은 "User ids reported to the Electoral Court for the Brazil 2026 election"이고, 근거 데이터로 TSE 후보자 데이터셋(candidatos-2026)을 링크한다.
    • 상수의 타입은 FxHashSet<u64>이고, 주석은 @username 꼴이다.
    • 뷰어가 그 계정을 팔로우하고 있으면 예외로 처리한다(정치적 성향과 무관하게 대칭적으로 적용된다).
  • 필터 본체인 home-mixer/filters/brazil_2026_election_filter.rs는 1,573줄인데, 그중 대부분은 계정 ID 상수와 주석으로 적어 둔 username이다.

    • 핵심 로직은 10줄 남짓이다.

      static BRAZIL_2026_ELECTION_USER_IDS: LazyLock<FxHashSet<u64>> = ...;  // 665개
      
      impl Brazil2026ElectionFilter {
          fn is_excluded_author(user_id: u64, followed_user_ids: &FxHashSet<u64>) -> bool {
              BRAZIL_2026_ELECTION_USER_IDS.contains(&user_id) && !followed_user_ids.contains(&user_id)
          }
          fn should_remove(candidate: &PostCandidate, followed_user_ids: &FxHashSet<u64>) -> bool {
              let is_excluded = |user_id: u64| Self::is_excluded_author(user_id, followed_user_ids);
              if is_excluded(candidate.author_id) { return true; }
              if candidate.retweeted_user_id.is_some_and(is_excluded) { return true; }
              if candidate.quoted_user_id.is_some_and(is_excluded) { return true; }
              candidate.ancestor_users.iter().copied().any(is_excluded)
          }
      }
      
  • 필터는 후보의 작성자, 리트윗 원저자, 인용 원저자, 답글 스레드의 조상 작성자 가운데 하나라도 리스트에 있고 뷰어가 그 계정을 팔로우하지 않았다면, 그 후보를 제거한다.

    • 팔로우 예외는 유저 개인의 팔로우 그래프를 기준으로 삼기 때문에, 정치적 스펙트럼과 관계없이 대칭적으로 작동한다.
  • 파일 헤더 주석이 법적 근거를 밝힌다 확인.

    "Application providers that use a recommendation system for users must exclude from the results the channels and profiles reported to the Electoral Court under the terms of § 1º of this article and, except in cases of paid boosting, the content posted on them." — home-mixer/filters/brazil_2026_election_filter.rs:9-11

  • 리스트의 근거가 된 데이터셋도 주석에 적혀 있다 확인.

    "https://dadosabertos.tse.jus.br/dataset/candidatos-2026"

  • 이 관할권 필터는 사회 그래프 필터가 뮤트와 차단을 처리한 바로 다음에 적용된다. 연결 지점은 phoenix_candidate_pipeline.rs:356-368이다.

    • AuthorSocialgraphFilter 바로 뒤이자 VideoFilter 바로 앞이다.
  • 리스트에는 여러 정당에 속한 인물이 들어 있다. 코드에서 몇 개만 발췌했다.

    • 40053694 // @FlavioBolsonaro (Flavio Bolsonaro, 자유당 상원의원)
    • 21069302 // @marcelvanhattem (Marcel van Hattem, 신자유당 하원의원)
    • 48298703 // @eduardopaes (Eduardo Paes, 사회민주당, 리우데자네이루 시장)
    • 25858078 // @ManuelaDavila (Manuela D'Avila, 공산당)
    • 33374761 // @cirogomes (Ciro Gomes, 민주노동당)
  • 코드 상단에는 이례적인 주석이 하나 있다 확인.

    "OmarAzizSenador deleted his account at the time this code was written." — home-mixer/filters/brazil_2026_election_filter.rs:15

    • TSE 리스트에는 올라 있지만 X에서 계정이 삭제된 인물까지 주석으로 따로 남겨 둘 만큼 세밀하게 문서화했다.
  • 이 관행이 유지된다면, 각국의 선거 주기마다 비슷한 필터를 코드에서 확인할 수 있게 된다. X가 2026-08-14 커밋(4세대+1)의 README에서 강조한 다음 문구가 규제 대응에도 적용된다는 신호이기도 하다: "a benefit of open-source is that you can see that changes like this exist, and exactly how they work".

  • 앞으로 지켜볼 것은 다음 3가지다.

    1. 선거 주기가 지난 뒤에 이 필터가 어떻게 정리되는가. 브라질 2026 선거는 특정 시점에 끝나는 행사이므로 이 필터도 한시적이다. X가 필터를 제거하는지, 상수만 비우고 코드는 남기는지, 별도 아카이브로 옮기는지가 open-source 관행이 얼마나 지속되는지를 판단할 지표가 된다.
    2. 다른 국가의 선거와 규제에 대응하는 필터도 같은 방식으로 추가되는가. EU 의회 선거나 인도 총선, 미국 대선에 대해서도 비슷한 필터가 코드에 나타나는지가 앞으로 6개월 동안 확인할 사항이다.
    3. docs/BIDIRECTIONAL_BOOST_CHANGE.md가 예고한 diff 문서화 관행과 어떻게 연결되는가. 어제 다룬 그 문서는 앞으로 파라미터 변경을 code diff로 문서화하겠다는 견본이었다. Brazil 필터의 665개 계정 리스트가 추가되거나 삭제될 때 그 변경이 이후 커밋에서 어떻게 문서화되는지도 이 관행의 성숙도를 보여 준다.

새로 알게 된 것C. 콜드스타트 후보를 Thompson sampling으로 고르는 경로가 생겼지만 기본은 off다

  • 콜드스타트 슬롯 선택기가 갱신됐다 확인 — home-mixer/scorers/author_cold_start.rs:151-190. 이제 콜드스타트 대상 후보 집합에서 "슬롯을 어느 후보로 채울지" 고르는 방식이 greedy max-score와 Beta reward Thompson sampling 두 갈래로 나뉜다.

    • 바뀐 파일은 author_cold_start.rs다.
    • Thompson sampling은 후보마다 Bayesian posterior에서 한 번씩 샘플을 뽑아 그 값으로 선택하며, exploration을 확률적으로 유도하는 표준 밴딧 기법이다.
  • 새로 추가된 파라미터는 6개다 확인 — home-mixer/params/param.rs:687-724.

    • EnableColdStartThompsonSampling = false: 기본값은 off다. 실제 프로덕션은 여전히 greedy로 동작한다.
    • ColdStartBetaAlpha0 = 0.75: Beta(α₀, β₀) 사전분포의 α이며, like의 사전 관측치에 해당한다.
    • ColdStartBetaBeta0 = 49.25: β₀이며, non-like의 사전 관측치에 해당한다. α₀ + β₀ = 50이 사전 분포의 유효 표본 크기이므로, 대략 "50 impression 중 0.75 like"라는 사전 지식을 뜻한다.
    • ColdStartTsTopK = 5: Beta 샘플링으로 상위 K개를 뽑은 다음, 실제 스코어로 동점을 가른다.
    • ColdStartImpressionScale = 1.0: view_count에 곱하는 스케일이다.
    • ColdStartTrackedIds = "": 쉼표로 구분한 계정 및 포스트 ID 리스트이며, 서빙 통계를 계측할 대상을 지정한다.
  • 샘플링 규칙은 같은 파일에 적혀 있다 확인.

    • 각 후보 i에 대해 posterior Beta(α₀ + likes, β₀ + max(views − likes, 0))에서 한 번 샘플을 뽑는다. 그 값으로 상위 K개를 고른 다음, 그 안에서 원래 스코어가 가장 높은 후보를 선택한다.

      fn sample_reward<R: Rng + ?Sized>(candidate: &PostCandidate, alpha0: f64, beta0: f64, scale: f64, rng: &mut R) -> f64 {
          let n = scale * candidate.view_count.unwrap_or(0) as f64;
          let x = (candidate.fav_count.unwrap_or(0).max(0) as f64).min(n);
          let alpha = alpha0 + x;
          let beta = beta0 + (n - x).max(0.0);
          Beta::new(alpha, beta).map(|d| d.sample(rng)).unwrap_or(0.5)
      }
      
  • 기본값이 off라는 사실이 중요하다. 이 릴리즈 시점에 실제 유저에게 적용되는 콜드스타트는 여전히 max-score greedy다.

    • Thompson sampling은 A/B 인프라에 연결만 된 상태이며, 실제 반영 여부는 앞으로 나올 A/B 결과에 따라 결정될 것이다.
  • ColdStartTrackedIds에 특정 계정이나 포스트 ID를 등록해 두면, 카운터가 그 계정이 콜드스타트 파이프라인의 어느 소스에서 몇 번 등장했는지 추적한다. 특정 계정을 A/B 실험에서 직접 관찰할 수 있는 개별 관찰 훅이다.

    • 카운터 이름은 home_mixer.cold_start_tracked_ids_total{id, source}다.
    • 예를 들어 정치인 계정 하나를 등록해 두면, 그 계정의 포스트가 어느 콜드스타트 경로로 몇 번 노출됐는지 셀 수 있다.
    • 이 계측 훅이 존재한다는 사실은 계정 단위 라벨 조회를 열어 준 4세대의 under-the-hood 투명성 노선과 방향이 같다. 다만 이것은 X 내부용 계측이며 외부에 공개되는 자료는 아니다.

새로 알게 된 것D. 랭킹 모델의 bool 입력 3개가 처음으로 실제 값을 받는다

  • Phoenix(X For You의 트랜스포머 랭킹 모델)의 입력 피처가 처음으로 채워졌다. 이 입력 필드는 정본에서 "죽은 필드"로 분류돼 주의할 점 목록에 남아 있었다.
    • 4세대 초까지 코드에서 관찰된 필드는 bool_features: vec![false; ...]다.
    • 이 "죽은 필드"인 bool_features는 3세대부터 4세대 초까지 vec![false; ...]로 전부 채워져 있어서, 입력으로서 아무 효력이 없었다.
  • 이번 커밋(4세대+1)에서 그중 세 개가 처음으로 채워졌다 확인 — phoenix/crates/common/xai-recsys/src/util.rs:456-540, 728-900, phoenix/crates/common/xai-recsys/src/model_config.rs:40.
    • 새로 채워진 것은 IS_STALE_POST14D와 IS_AUTHOR_FOLLOWED/FOLLOWING_BY_VIEWER_SEQ, 모두 3개의 bool 시퀀스다. 각각 stale post 14일 여부, 그리고 author와 viewer 사이의 팔로우 방향 2개를 나타낸다.
    • 코드 diff의 핵심은 vec![false; candidate_seq_len * n_post_bool]를 candidate_bool_features로 바꾼 두 곳이다. 후보 시퀀스와 이력 시퀀스 양쪽에 함께 적용됐다.
bool feature 설명
IS_STALE_POST14D enable_stale_post = true일 때 now - creation_ts > STALE_POST_14D_TTL_SEC이면 fav/reply/retweet/quote/view count를 전부 0으로 채우고 이 bool을 true로 둔다. 14일이 지난 포스트의 engagement 신호는 전부 무시하고, 랭커에게 "stale"이라는 사실만 알린다.
IS_AUTHOR_FOLLOWED_BY_VIEWER_SEQ 뷰어가 이 후보의 작성자를 팔로우하고 있는지를 나타낸다. 후보 시퀀스와 이력 시퀀스에 각각 붙는다.
IS_AUTHOR_FOLLOWING_VIEWER_SEQ 후보의 작성자가 뷰어를 팔로우하고 있는지를 나타내며, bidirectional 관계를 감지하는 입력이다.
  • stale post를 처리하는 두 신호가 짝을 이뤄 들어간다 확인.
    • stale이면 count를 0으로 만들고 bool을 세우며, stale이 아니면 실제 count를 넣는다.

      let creation_valid = candidate_post_creation_ts_sec[j] > 0;
      let original_age_sec = now_sec as i64 - candidate_post_creation_ts_sec[j] as i64;
      let is_stale = stale_post_enabled && creation_valid && original_age_sec > STALE_POST_14D_TTL_SEC;
      candidate_is_stale_post[j] = is_stale;
      if is_stale {
          stamp_engagement_counts(..., 0, 0, 0, 0, 0);
      } else {
          stamp_engagement_counts(..., candidate.fav_count, candidate.reply_count, ...);
      }
      
    • 랭커는 "count=0 + is_stale=true"인 후보와 "count=0 + is_stale=false"인 후보를 서로 다른 경우로 명시적으로 학습할 수 있다.

  • stale post 신호가 count zeroing과 짝을 이뤄 들어간다는 점이 특히 흥미롭다. 랭커에게 "이 카운트가 낮은 이유는 인기가 없어서가 아니라 오래돼서 노출이 끊겼기 때문"이라고 명시적인 라벨을 붙여 주는 것이다.
    • 이 짝은 3세대까지 정본이 관찰해 온 snowball 문제(오래된 포스트의 낮은 count가 낮은 랭킹을 낳고 그 랭킹이 다시 낮은 count를 낳는 자기강화 루프)를 랭커가 학습으로 우회하도록 만든 설계이다.
  • 정본이 3세대부터 관찰해 온 "오래된 포스트의 낮은 카운트가 낮은 랭킹을 낳고, 그 랭킹이 다시 낮은 카운트를 낳는 자기강화 루프" 문제를 랭커가 학습으로 우회하도록 만든 설계로 보인다 추정. X는 이 설계의 목적을 직접 문서화하지 않았지만, count zeroing과 bool set을 짝지은 구조가 그 방향을 강하게 시사한다.
  • 4세대에서 인용된 is_mutual_follow 부스트(reply +15)는 스코어러에 하드코딩된 조건이었다. 이제는 모델이 팔로우 방향을 개별 입력 bool로 받아서 학습으로 비슷한 패턴을 잡을 수 있게 됐다는 점도 중요하다.
    • 하드코딩된 부스트에서 학습 신호로 옮겨 가는 흐름은 3세대에서 4세대로 넘어오며 나타난 전반적 방향과 일치한다. 수작업 게이팅에서 모델 학습으로 무게가 옮겨 가는 방향이다.

새로 알게 된 것E. 부정 계정 판정 노트 생성기의 게이트와 헤드 선택 로직이 공개됐고, 설명 문장은 가려졌다

  • BDSM(계정 행동 시퀀스로 부정 계정을 탐지하는 스코어러)의 enforcement note 생성기가 부분 공개됐다.

    • 3세대부터 4세대 초까지 bdsm/runtime/score_results_sink_focal.py:78의 build_enforcement_note는 return None만 있는 스텁이었다.
  • 이번 커밋(4세대+1)에서 gate 로직과 dominant-head(점수가 가장 높은 봇 헤드) 선택 로직이 공개됐고, 템플릿 문자열만 센티널 값으로 남았다 확인 — bdsm/runtime/score_results_sink_focal.py:78-128.

    • 센티널 값은 "<redacted>"다.

    • 공개된 함수 본문은 이렇다.

      def build_enforcement_note(head_scores_list, action_hist_list):
          if not head_scores_list: return None
          total = sum(h["cnt"] for h in (action_hist_list or ()))
          if total < 30: return None                       # MIN_ACTIONS gate
          bot_heads = [(h["head_name"], h["score"]) for h in head_scores_list
                       if h["head_name"] != "LegitimateUser" and h["score"] > 0.5]
          if not bot_heads: return None
          bot_heads.sort(key=lambda x: x[1], reverse=True)
          dominant_name, dominant_score = bot_heads[0]
          note = _ENFORCEMENT_TEMPLATES.get(dominant_name, _REDACTED_TEMPLATE)
          note += f" [model: {dominant_name}={dominant_score:.2f}"
          if len(bot_heads) > 1:
              secondary = ", ".join(f"{n}={s:.2f}" for n, s in bot_heads[1:3])
              note += f", also: {secondary}"
          note += "]"
          return note
      
  • 봇 헤드 7개의 이름이 정식으로 공개됐고, 각 헤드의 템플릿 문자열은 모두 센티널로 대체돼 있다.

    • 헤드 이름은 FollowBot, LikeBot, EngagementAmplifier, ReplySpamBot, TweetSpamBot, RTBot, MultiActionBot이다.
    • 대체한 값은 _REDACTED_TEMPLATE = "<redacted>"다.
  • 노트에는 어떤 봇 계열로 얼마나 높게 판정됐는지가 그대로 나가지만, 왜 그렇게 판정됐는지(어떤 액션 패턴 때문인지)를 설명하는 문장은 공개되지 않았다.

    • 최종 노트는 "<redacted> [model: FollowBot=0.91, also: ReplySpamBot=0.60, LikeBot=0.53]"와 같은 형태가 된다.
  • README는 이렇게 절반만 공개한 이유를 밝힌다 확인 — bdsm/README.md.

    "The public package keeps the gates (MIN_ACTIONS, dominant-head pick) and the enforcement_note proto field. The template strings and the per-head key_actions interpolator are the sentinel '<redacted>' — same idea as the 9.99 operating points." — bdsm/README.md

  • 구조와 이름, 게이트는 공개하고 튜닝된 실숫값과 프롬프트 문자열은 공개하지 않는 원리는 sink_policy.yaml의 operating point 9.99 센티널과 같다.

    • 9.99 센티널은 확률 범위를 벗어난 값이어서, 이 값이 들어간 판정 임계는 절대 걸리지 않는다.
    • 어제 정본에 SafetyLevel 3-tier와 규칙 54개를 반영했는데, 오늘은 그 규칙을 참조하는 상위 계정 스코어러의 노트 생성 로직이 절반쯤 열린 셈이다.
  • proto 필드의 설명 문구도 갱신됐다 확인 — bdsm/proto/abuse_inference.proto:98-102.

    "Optional human-readable note. In this release templates and key_actions are the sentinel '<redacted>' (see README); production fills the real appeal paragraph. ActionName enums are unchanged."

  • X는 이번 커밋(4세대+1)에서 "구조는 공개하고 프롬프트와 문자열, 튜닝된 실숫값은 공개하지 않는다"는 원칙을 매우 일관되게 지켰다.

    • sink_policy의 9.99 sentinel, enforcement note의 <redacted> template, botmaker-rules에서 게이밍 방지 부분을 일부 가린 처리가 모두 같은 원리로 배치됐다.
    • 게이밍에 대한 저항성은 유지하면서, 구조와 이름, 게이트, 헤드 조합을 검증할 수 있는 여지는 최대한 넓히는 방향이다.
  • abuse-enforcement-service가 이 노트를 받아 실제 조치(label/challenge/suspension)를 판단하는 흐름에서, 그 입력에 해당하는 부분이 오늘 절반쯤 열렸다.

새로 알게 된 것그 밖의 변경

  • grox(Grok 기반 주석 파이프라인)가 답글 스팸 판정과 답글 랭킹 채점에 쓰는 팔로워 수 임계를 15,000에서 30,000으로 두 배 올렸다 확인 — grox/flows/reply_spam/task_filter.py:17, 185.
    • 바뀐 상수는 TaskSpamFilter.FOLLOWER_COUNT_THRESHOLD_FOR_SPAM_DETECTION과 TaskReplyRankingFilter.FOLLOWER_COUNT_THRESHOLD_FOR_REPLY_RANKING이다.
    • 스레드 root와 답글 대상이 모두 팔로워 30k 이하인 답글은 스팸 판정을, 하나라도 30k를 넘는 답글은 답글 랭킹 채점을 받는다(task_filter.py:77-92, 214-225).
    • 그래서 이번 상향으로 스팸 판정 대상은 넓어지고 답글 랭킹 채점 대상은 좁아졌다. 두 작업 사이에 grok 리소스 배분을 조정한 변경이다.
  • phoenix-rankall에 2주 시간창의 영상 SID(아이템을 계층 코드로 나타낸 semantic ID) window인 video_14day가 새로 생겼다 확인 — phoenix-rankall/src/config/mod.rs:177-180.
    • 기존의 video_48h, video_96h, nsfw_video_48h/168h/14day에 video_14day가 나란히 추가됐다.
    • Phoenix retrieval의 SID 기반 인기도 신호에 2주 시간창의 비디오가 포함된다는 뜻이다.
  • abuse-enforcement-service의 목 픽스처가 1줄 바뀌었다 확인. 룰 필드값 하나를 바꿨을 뿐이고 실제 로직에는 영향이 없다.

정본 반영 services/x.md의 9개 절을 갱신했다.

  • "한 줄 요약" 절에 4세대+1 후속 공개의 요약을 추가하고, 필터 총계를 20에서 21로 갱신했다.
  • "공개 소스 4세대" 세대 테이블에 4세대+1 행을 신설했다(커밋 c65aa17, +2,271/−32).
  • "가중치 — 4세대 릴리스로 값이 공개됐다" 절에 raw-count 오해를 막는 해석 규칙 인용을 삽입했다.
  • "필터 21개" 절에 Brazil2026ElectionFilter 항목을 새로 넣고, 파이프라인에서 연결되는 위치를 명시했다. 이 절의 헤딩은 이전의 "필터 20개"에서 고쳤다.
  • "콜드스타트" 절에 Thompson sampling 파라미터 6개와 샘플링 규칙을 새로 넣었다.
  • "Phoenix 학습·인덱스" 절에 bool feature 3개와 stale post count zeroing 로직을 새로 넣었다.
  • "Grox (LLM 주석) — 3세대 그대로" 헤딩을 "+ 2026-08-14 임계 상향"으로 바꾸고, 임계 조정 내용을 새로 넣었다.
  • "BDSM (계정 행동 시퀀스 부정 계정 탐지) — 4세대+1에서 enforcement note 생성 로직 부분 공개" 절을 새로 만들었다.
  • 열린 질문 절에 "4세대+1 공개로 해소된 것 (2026-08-16)" 하위 절을 신설하고 항목 5개를 넣었다.
  • 출처 절에 6건을 추가했다(c65aa17 커밋, README #latest-updates, Brazil 필터, TSE 데이터셋, @XBR 공지, BDSM sink).

assets/x-pipeline.svg에서는 필터 라벨을 "17 → 18"로, 신규 라벨을 "4 → 5 (Brazil2026 포함)"로 고쳤다.

의미 4세대 공개의 성격이 하루 뒤에 곧바로 확장됐다. 어제 관찰한 "코드 diff로 파라미터 변경을 문서화하는 관행"이 오늘 처음으로 실제 작동했다. 앞으로 X의 커밋 로그를 매일 추적하는 작업의 가치가 확실히 커지는 방향이다.

  • README #latest-updates는 이제 날짜별 하위 섹션 구조를 갖췄다. 8월 14일 다음에 8월 13일이 오는 역시간순이다.
  • 각 하위 섹션은 세 요소를 담고 있다.
    1. 변경 요약
    2. 관련 파일 링크
    3. 근거 문서와 공지 링크
  • 다음 커밋에서 어떤 param이 바뀐다면, 그 변경 자체가 A/B 결과를 뒤늦게 알려 주는 지표가 된다.
  • 어떤 필터가 새로 붙거나 사라진다면, 규제 대응을 실시간으로 관찰하는 지표가 된다.

오늘 처리하지 않고 남겨 둔 심층 분석 항목은 다음과 같다.

  • Thompson sampling의 A/B 실험이 언제 실제로 활성화되고 결과 지표가 어떻게 나오는지 계속 지켜본다.
  • 브라질 선거 필터의 665개 계정 리스트가 어떻게 갱신되는지 커밋 히스토리를 따로 추적한다.
  • BDSM _ENFORCEMENT_TEMPLATES에 FollowBot 등 7개 이외의 다른 봇 헤드가 나중에 추가되는지 확인한다.
  • Phoenix bool feature slot의 나머지가 언제 채워지는지 확인한다.

2노이즈에 강한 앙상블 랭킹 논문 DrEM의 소속이 Kuaishou로 확정됐다 — Kuaishou

자료 DrEM: Dual-Side Robust Ensemble Ranking from Noisy User Preference Predictions in Video Recommendation — arXiv:2608.12778 — arXiv, 2026-08-13 제출, 논문. 저자는 8명이다(Canwei Huang, Tiantian He, Xiaoxiao Xu, Jun Zhang, Ziran Deng, Weike Pan, Chunjie Chen, Kaiqiao Zhan).

배경 어제 radar.md에 이 논문을 소속 미확정 상태로 등록하면서, 추정 등급으로 Kuaishou 계열일 통계적 가능성만 적어 두었다. 오늘 arXiv HTML 판을 열어 저자 소속 표기를 확인한 결과, Kuaishou 이메일 도메인을 쓰는 저자가 5명 확인돼 이 회사의 프로덕션 논문임이 확정됐다. 이번 논문은 앙상블 랭킹 단계에서 상위 모델 예측의 노이즈를 라벨과 입력 양쪽에서 함께 보정하는 방법을 다룬다.

새로 알게 된 것A. DrEM은 Kuaishou가 이번 달에 낸 두 번째 프로덕션 논문이다

  • HTML 판을 확인한 결과, 이 논문은 Kuaishou Technology Beijing과 Shenzhen University의 협업으로 확정됐다.
    • Kaiqiao Zhan, Xiaoxiao Xu, Tiantian He, Jun Zhang, Chunjie Chen이 Kuaishou 이메일 도메인을 쓴다.
    • Weike Pan, Canwei Huang, Ziran Deng은 Shenzhen University 소속이다.
  • Kuaishou 연구진은 이번 달에 이미 논문 두 편을 냈다(HD-Rec 2026-08-11 radar.md, PushDualGen 2026-08-12). 이번 논문이 세 편째다.
  • 그중 프로덕션 배포를 밝힌 것은 PushDualGen이고, HD-Rec은 공개 벤치마크 결과만 낸 논문이다 확인 — arXiv 2608.06997.
    • HD-Rec 초록의 실험은 "three public cross-domain recommendation benchmarks"뿐이고, 배포나 A/B 진술이 없다.
  • 세 편이 모두 다른 알고리즘 계열이라는 점이 특징이다. 각각 SID cross-domain, SID와 CoT를 결합한 푸시, ensemble ranking의 노이즈 강건성을 다룬다.
    • 회사 차원에서 여러 팀과 여러 연구 라인이 동시에 프로덕션 SOTA 논문을 낼 만한 자원을 갖췄다는 사실이 확인된 셈이다.

새로 알게 된 것B. DrEM은 상위 모델 예측의 노이즈를 라벨과 입력 양쪽에서 함께 보정한다

  • 논문은 앙상블 랭킹 단계에 고유한 문제를 다룬다. 산업용 비디오 추천의 다단계 파이프라인에서, 하위 앙상블 랭커가 상위 멀티태스크 랭커의 예측을 입력 피처로도 쓰고 proxy preference 라벨의 출처로도 함께 쓰는 상황을 상정한다.
    • pctr, pvtr, pcmtr, pftr처럼 여러 태스크가 내놓는 예측 확률을 여기서는 pxtr로 통칭한다.
  • pxtr는 상위 모델의 출력이므로 노이즈를 포함할 수밖에 없다. 이 노이즈는 두 갈래로 작용한다.
    • proxy preference 라벨을 뒤집는다(supervision-side 노이즈).
    • feature-side 입력으로 흘러들어 순위 스코어를 흔든다(feature-side 노이즈).
  • 기존의 앙상블 랭킹 방법들은 pxtr를 신뢰할 수 있는 신호로 간주하고 노이즈를 무시했다. DrEM은 이 노이즈를 양쪽에서 동시에 보정한다.
    • 라벨 쪽에서는 쌍마다 실제 preference가 뒤집혔을 확률(pairwise flip probability, 아래에서는 줄여서 뒤집힘 확률)을 추정하고, empirical risk를 그 확률로 정정하는 risk-denoising robust loss를 도입했다. 뒤집힘 확률의 추정에 오차가 있더라도 이 loss가 basic pairwise loss보다 우월하다는 사실을 이론적으로 증명했다(Theorem 1).
    • 입력 쪽에서는 pxtr의 예측 노이즈 분포에서 perturbation을 샘플링하고, preference-preserving ranking consistency regularizer로 perturbation에 대해 출력이 안정적으로 유지되도록 학습한다.
  • 핵심은 두 보정이 공유된 노이즈 모델에서 유도된다는 점이다. supervision과 feature 양쪽의 보정 목표가 같은 노이즈 근원에 정렬되므로, 파라미터를 공유해서 서로 동기화된 보정을 수행할 수 있다.

새로 알게 된 것C. 프로덕션 A/B에서 sparse 행동의 개선폭이 dense 행동보다 컸다

  • 실험은 프로덕션 백본 EMER와 EASQ에 각각 DrEM을 붙인 두 그룹으로, 7일 동안 그룹마다 메인 트래픽의 5.1%를 유저 단위로 무작위 배정해 진행했다 확인 — HTML 판 5.4절(RQ3).

    "To answer RQ3 and validate real-world performance, we conduct online A/B tests on the industrial short-video platform. We set up two parallel experiment groups to verify the generalization of our DrEM on both representative backbones, applying our DrEM on top of production-grade EMER and EASQ backbone. The experiment runs for 7 days with 5.1% of the main traffic randomly split at the user level via hash-based assignment to each group." — arXiv 2608.12778, 5.4절

메인 A/B 결과는 다음 표와 같다(5.4절 Table 2, 모든 지표가 p < 0.005) 확인.

지표 EMER w/ DrEM EASQ w/ DrEM
Comment +1.388% +0.178%
Follow +1.197% +0.460%
Video View +0.691% +0.117%
Forward +0.683% +0.181%
Like +0.625% +0.048%
Long View +0.401% +0.043%
App Stay Time +0.116% +0.124%
LT7 +0.017% +0.020%
  • 저자가 같은 절에서 관찰한 내용을 요약하면, sparse behavior의 gain이 dense behavior보다 크다는 것이다. 팔로우 +1.20%와 댓글 +1.39%의 개선폭이 뷰 +0.69%나 롱뷰 +0.40%보다 압도적으로 크다.
  • 이는 이론과 일치한다. 스파스 태스크(pcmtr, pftr)의 pxtr는 예측 분산이 크므로 뒤집힘 확률도 크고, 그만큼 robust correction이 개선할 여지도 크기 때문이다.
  • 5.5절(RQ4)에서 뒤집힘 확률로 계층화한 heatmap도 같은 결론을 보여 준다. 뒤집힘 확률이 낮은 구간에서는 dense 태스크(pctr, pvtr)의 개선이 0이거나 약간 음수인데, 높은 구간에서는 개선폭이 급격히 양수로 올라간다.
  • 저자는 EASQ의 gain이 EMER보다 작은 이유도 설명한다. EASQ는 이미 자체 questionnaire-signal alignment로 supervision-side 노이즈를 부분적으로 완화하고 있어서, DrEM의 supervision 보정이 개선할 여지가 적다는 것이다.
    • 즉 supervision 정정이 훨씬 큰 개선을 낳고, 그 부분을 이미 처리한 백본에서는 feature-side 정정만 남는다고 계층적으로 이해할 수 있다.

정본 반영 radar.md DrEM 절에서 소속을 확정해 등급을 추정에서 확인으로 갱신했다. A/B 실험 설정(트래픽 5.1%, 7일)과 지표 8개의 실측값을 추가하고, 이론적 관찰인 sparse > dense도 적었다. Kuaishou 서비스는 정본 추적 대상이 아니기 때문에, services 폴더의 정본에는 아직 반영하지 않았다.

의미 이 논문은 Kuaishou가 이번 달에 낸 논문 세 편 가운데 정본과 가장 밀접하다. 다른 서비스들도 같은 노이즈 문제를 겪는다. X의 26개 헤드 가중합, Meta의 다목적 랭킹, Netflix의 멀티태스크 FM(추천 foundation model)은 모두 상위 pxtr가 하위 스코어러의 입력이자 라벨이 되는 구조를 갖는다.

다만 DrEM이 다루는 특정 문제인 앙상블 랭킹 단계의 pxtr 노이즈가 X와 Meta, Netflix에서 별도 컴포넌트로 존재하는지, 아니면 다른 방식으로 완화되고 있는지는 문헌으로 확인되지 않는다. 두 번째 회사에서 비슷한 진술이 나온다면 topics/multi-task-ranking.md에 절을 새로 만들 후보가 된다.

다음에 볼 것