0x00 EN

리서치 / 일일 리포트

  • 읽은 자료 2건
  • 정본 반영 3개 파일
  • 레이더 1건
한 줄 요약X가 사흘 전 slot-spread로 바꾼 For You 기본 광고 블렌더를 다시 multi-risk로 되돌렸다. 같은 커밋에서 홈 랭커 학습 프리셋이 경과 시간 입력을 켰다.

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

  • X의 Under the Hood 점수 응답이 헤드 확률 전체 대신 가중합에 크게 기여한 헤드 세 개까지만 보여 준다.
  • Alibaba 1688이 생성형 추천의 인기 쏠림을 teacher 두 개로 줄여 GMV를 3.4% 올렸다고 보고했다.

1기본 광고 블렌더가 사흘 만에 multi-risk로 돌아갔다 — X

자료 xai-org/x-algorithm b220448 — X(xAI), 2026-11-03, 코드. 이 노트들이 붙인 번호로는 4세대+55다(4세대+N은 이 노트들이 2026-08-13 4세대 공개 뒤의 커밋에 차례로 붙인 번호다).

배경 X For You(팔로우하지 않은 계정의 포스트까지 섞어 주는 추천 타임라인)는 유기 포스트 사이에 광고를 끼우고, 광고 위아래 포스트의 브랜드 안전 등급을 보고 자리를 정한다. 이 일을 하는 부품이 광고 블렌더이고, 2026-10-31 커밋은 기본 블렌더를 multi_risk에서 새로 만든 slot_spread로 바꿨다. 그때 이 노트는 실험 없이 이틀 만에 기본값으로 올린 점을 짚었다. 이번 커밋은 기본 블렌더를 multi_risk로 되돌리고, Phoenix(X의 Grok 기반 랭킹 모델) 홈 랭커 학습 프리셋에 경과 시간 입력을 켰다.

새로 알게 된 것A. 기본 광고 블렌더가 다시 multi_risk다

  • 광고 블렌더를 고르는 스위치의 기본값이 slot_spread에서 multi_risk로 돌아갔다 확인 — home-mixer/params/param.rs:937-942.

    • 스위치 이름은 AdsBlenderType(rust_home_mixer_ads_blender)다.
    • slot_spread 블렌더 코드는 그대로 남아 있어, 스위치 값으로 다시 고를 수 있다.
    param!(
        AdsBlenderType,
        String,
        "rust_home_mixer_ads_blender",
        "multi_risk"
    );
    
  • multi_risk는 HighRisk 포스트 옆에는 광고를 두지 않고, MediumRisk 포스트 옆에는 광고주가 민감한 맥락을 허용한(BSR-high) 광고만 둔다 확인 — x.md 광고 절.

    • slot_spread도 같은 안전 조건을 지켰고, 차이는 광고 슬롯을 페이지 전체에 고르게 먼저 정하느냐였다.
  • 사흘 만에 되돌린 이유는 공개 코드에 없다 추정. 근거는 이 파일이 내부 feature switch(코드 배포 없이 기능을 켜고 끄는 설정) 기본값의 미러라서 실험 결과를 담지 않는다는 점이다.

    • 미러 동기화 시각은 2026-10-30T22:59:56Z에서 2026-11-02T16:00:39Z로 바뀌었다.

새로 알게 된 것B. H100 홈 랭커 학습 프리셋이 경과 시간 입력을 켰다

  • H100 GPU용 홈 랭커 학습 프리셋이 "이력 항목이 요청보다 얼마나 앞섰나"와 "후보가 마지막 이력보다 얼마나 뒤인가"를 입력으로 켰다 확인 — phoenix/xrex/configs/xrecsys.py:479-512.

    • 프리셋 이름은 home_direct_packed이고, 켜는 옵션은 enable_time_gap=True, time_gap_lr_scale=4.0이다.
    • FeaturePrepConfig의 전역 기본값은 enable_time_gap=False다 — recsys_feature_prep.py.
  • 간격은 1분부터 두 배씩 넓어지는 경계로 버킷을 나누고, 버킷마다 학습되는 임베딩을 이력과 후보 토큰에 더한다 확인 — recsys_feature_prep.py:73-78.

    • 버킷은 19개이고, 0번은 시각을 모르는 경우다. 마지막 경계는 60×2^16초, 약 45일이다.
    • 임베딩은 0으로 초기화하고 학습률을 4배로 준다. 이력 쪽 이름은 hist_time_gap_emb, 후보 쪽은 cand_time_since_history_emb이다(같은 파일 1026-1039, 1083-1098행).
    def _compute_time_gap_bucket(request_ts, impr_ts):
        gap = request_ts - impr_ts
        edges = jnp.asarray([60 * 2**k for k in range(TIME_GAP_CARDINALITY - 2)], dtype=gap.dtype)
        bucket = 1 + jnp.searchsorted(edges, gap, side="right", method="compare_all")
        known = (request_ts > 0) & (impr_ts > 0) & (gap >= 0)
        return jnp.where(known, bucket, 0).astype(jnp.int32)
    
  • 서빙 쪽 입력 버퍼도 요청 시각과 가장 최근 이력 시각을 채운다 확인 — xai-recsys/src/util.rs:409-446.

    • 요청 시각은 후보 노출 시각 가운데 가장 이른 값으로 정한다.
    • 학습 데이터 로더도 같은 규칙으로 두 값을 계산한다 — recsys_batch.py.
    • 빌드 스크립트는 피처 정의에 두 필드가 다 있을 때만 이 코드를 켜고, 하나만 있으면 빌드를 멈춘다 — build.rs:166-186.
  • 2026-10-30 커밋의 시각 입력(wallclock_recency, 기본 off)과는 다른 경로다 확인. 그쪽은 기존 피처 준비 경로와 함께 켤 수 없었고, 이번 입력은 그 피처 준비 경로 안에 들어갔다.

  • 같은 프리셋은 체류, 미체류, 영상 품질 시청(VQV) 세 헤드의 학습 손실 비중을 0.5로 낮췄다 확인 — recsys_model.py:5004-5010.

    • 대상 행동은 CLIENT_TWEET_RECAP_DWELLED, CLIENT_TWEET_RECAP_NOT_DWELLED, CLIENT_TWEET_VIDEO_QUALITY_VIEW다 — constants.py:553-557.
    • 옵션 view_loss_weight의 전역 기본값은 1.0이다.
  • 이 프리셋이 프로덕션 홈 랭커 학습에 그대로 쓰이는지는 코드로 알 수 없다 추정. 근거는 레포에 하드웨어별 학습 프리셋이 여럿 있고, 그중 어느 것이 프로덕션 학습에 쓰이는지 코드가 밝히지 않는다는 점이다.

새로 알게 된 것C. Under the Hood 점수 응답은 기여가 큰 헤드만 보여 준다

  • home-mixer(For You 요청을 받아 후보 수집부터 배치까지 조율하는 서비스)의 Under the Hood 점수 응답이 헤드 확률 전체 대신 상위 기여 헤드를 싣는다 확인 — home-mixer/util/under_the_hood.rs.

    • Under the Hood는 X가 랭킹과 노출 판정의 근거를 보여 주려고 만든 투명성 경로이고, 이 점수 응답을 켜는 EnableUnderTheHood는 2026-10-06 커밋부터 기본 off다.
    • 헤드는 Phoenix가 행동마다 내는 예측 확률이고, 최종 점수는 헤드 확률에 가중치를 곱해 더한 가중합이다.
  • 기여분은 "헤드 확률 × 가중치"이고, 절댓값이 큰 순서로 최대 3개를 고르되 전체 절댓값 합의 10% 미만이면 거기서 멈춘다 확인 — vm-ranker/scoring/value_model.rs:220-240.

    • VMRanker(가중합과 DPP 다양성 재정렬을 계산하는 X 랭킹 서비스)가 계산해 응답에 싣는다. 가중합을 항 29개로 나눠 돌려주는 함수 weighted_terms가 공유 crate xai-value-model에 생겼다.
    const TOP_HEADS: usize = 3;
    const MIN_HEAD_SHARE: f64 = 0.10;
    
  • Under the Hood 요청은 캐시된 포스트가 있어도 debias(뷰어별 기본 성향만큼 헤드 확률을 다시 맞추는 보정)를 적용해 점수를 다시 계산한다 확인 — home-mixer/scorers/vm_ranker_request.rs:19-20.

    • 일반 요청은 이전과 같이 캐시된 포스트가 있으면 debias 입력을 보내지 않는다.

새로 알게 된 것그 밖의 변경

  • 영상 캐러셀(For You 안에서 영상 여러 개를 가로로 넘겨 보는 모듈) 후보에서 MediumRisk 포스트를 빼는 스위치가 기본 off로 생겼다 확인 — home-mixer/filters/video_carousel_filter.rs:26-41.
  • 광고 노출 로그에 라인 아이템, 캠페인, 광고 목표 필드가 늘 실린다 확인 — home-mixer/ads/drops.rs.
  • H100 프리셋의 학습률 배율(트랜스포머 행렬, 출력 헤드, 은닉 투영 각 0.25)과 임베딩 optimizer 설정이 바뀌었다 확인 — xrecsys.py:495-506.
  • 이용자 행동 집계 종류에 중복 귀속을 걸러 낸 장기 체류 집계가 추가됐다 확인 — recsys.proto.
  • VF(포스트 노출을 판정하는 visibility-filtering 서비스)가 삭제된 포스트를 '찾을 수 없음'과 구분해 기록하지만, 판정은 이전과 같다 확인 — visibility-filtering/models/verdict.rs.
  • SID(아이템을 짧은 의미 토큰 열로 나타낸 Semantic ID) 조회 캐시를 여러 조각으로 나눌 수 있게 됐다 확인 — sid_client.rs.

"// mirrored from config feature-switch defaults; last sync 2026-11-02T16:00:39Z" — home-mixer/params/param.rs:1, 2026-11-03 (코드)

정본 반영 services/x.md ## 재순위·다양성·필터의 블렌더 불릿에서 기본값을 multi_risk와 기준 커밋으로 고쳤고, 캐러셀 필터 불릿 아래에 MediumRisk 스위치 불릿을 추가했다. ## 광고 도입의 기본 블렌더 문장을 다시 쓰고 절 변경 이력의 기본 블렌더 줄에 2026-11-03을 더했다. Under the Hood 절에 상위 헤드 응답 불릿을, 랭커 입력 피처 절 도입에 경과 시간 입력 문장과 단락을 추가했다. ## 한 줄 요약과 ## 출처의 기준 커밋을 b220448로 올리고 변경 이력 요약표에 한 행을 추가했다. topics/llm-in-recsys.md의 브랜드 안전성 불릿에서 기본 블렌더 주장을 고쳤다.

의미 ⚠ 주장 변경: "X의 기본 광고 블렌더는 slot-spread다"라는 2026-11-01의 주장이 2026-11-03 커밋부터 맞지 않는다. slot-spread는 사흘 동안만 기본값이었고, 되돌린 이유는 공개되지 않았다 확인. 경과 시간 입력은 학습 프리셋 하나에서만 켜졌으므로, 프로덕션 랭커가 이미 이 입력을 쓴다고 보지 않는다 추정.

레이더

  • Alibaba 1688 HERO는 생성형 추천의 인기 쏠림을 인기·비인기 전용 teacher 두 개로 줄여, 1688 홈 추천 지면의 15일 A/B에서 GMV(거래액) +3.412%를 보고했다. radar.md "생성형 retrieval / semantic ID" 스레드에 추가 근거로 붙였다 — arXiv 2611.03272.
    • on-policy distillation(student가 직접 생성한 결과 위에서 teacher의 토큰 분포를 따라 배우는 학습)이 인기 아이템 쏠림을 키운다는 진단이 핵심이다.
  • arXiv cs.IR 30건을 triage했다. Kuaishou 지역 서비스 광고의 agentic 추천(EvoRec)과 Microsoft 검색 실험 지표(SSR)는 A/B 진술이 있지만 피드 메커니즘과 거리가 있어 넣지 않았다.

다음에 볼 것