0x00

리서치 / 일일 리포트

  • 읽은 자료 2건
  • 정본 반영 2개 파일 (services/x.md, services/netflix.md)
  • 레이더 0건
한 줄 요약X의 랭킹 모델 Phoenix 학습이 Adam에서 Muon optimizer로 전환됐다. 이 저장소가 반영해 온 프로덕션 recsys 학습 파이프라인에서 Muon 채택을 코드로 확인한 첫 사례다.

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

  • 같은 X 커밋에서 Phoenix가 검색 랭킹으로 확장됐고, Phoenix proto에 reward 헤드와 link-open 확률 5분위 헤드가 생겼다.
  • 같은 커밋에는 Following 전용 필터, Grok 4.6에 실트래픽 10%를 보내는 dial, 노출 판정 shadow 미러링, 플래그 4개의 train-default ON 승격도 있다.
  • Netflix는 아트워크를 CLIP two-tower로, 비디오 프리뷰를 자체 tri-modal 모델 MediaFM으로 개인화한 프로덕션 결과를 논문으로 냈다.

1Phoenix의 학습 optimizer가 Adam에서 Muon으로 바뀌었다 — X

자료 xai-org/x-algorithm @ aad7179 — "Open-source X Recommendation Algorithm" — 2026-08-19 21:25 UTC, 공개 소스코드. 이 노트들은 4세대 공개 뒤의 X 커밋에 차례로 번호를 붙여 부르며, 이 커밋은 4세대+4다. 파일 79개에 +3,303/−651 규모이며, 4세대+3(8/18)의 파일 14개와 비교하면 5.6배다. 성격도 4세대+1부터 +3까지 이어진 "소규모 정교화"에서 인프라와 학습 파이프라인의 대규모 확장으로 바뀌었다. 특이하게도 README의 #latest-updates 섹션은 8/14의 August 14th 항목이 여전히 최신이다. 이 커밋의 변경 사항은 문서 갱신 없이 코드로만 반영됐다.

배경 이 저장소는 4세대 초대형 공개(2026-08-13, 47c1bcd) 이후로 후속 커밋을 매일 반영해 왔다. canon(이 저장소의 정본 문서)은 이 흐름을 "매일 커밋"이라는 주기로 관찰해 왔다.

  • 8/14(c65aa17, 4세대+1)에서는 가중치 해석 규칙과 Brazil 필터, Thompson sampling, Phoenix bool 3종을 확인했다.
  • 8/17(b089ce6, 4세대+2)에서는 광고 안전 V2와 cross-validation, 인덱싱 게이트를 확인했다.
  • 8/18(11a71f8, 4세대+3)에서는 V2 헬퍼를 하루 만에 재설계한 내용과 Following VF hydrator, Phoenix Kafka v3를 확인했다.
    • VF(visibility-filtering)는 포스트마다 이 뷰어에게 보여도 되는지 판정하는 서비스다.

4세대+3 다음 날(8/19)에 나온 이번 커밋은 규모(파일 79, +3.3k lines)와 성격 양쪽에서 후속 소규모 정리를 넘어선 대형 확장이다. 커밋 규모는 79 파일 +3,303/−651이다. 4세대+3(파일 14개, +208/−70)과 비교하면 파일 수는 5.6배, 변경 줄 수는 약 14배다. 성격 면에서는 학습 파이프라인 대개편, retrieval 지면 확장, 안전 인프라 shadow 구성이 들어 있다.

Muon optimizer는 Keller Jordan 등이 2024년에 제안한 dense-parameter optimizer다. 기존 momentum-adam 계열과 달리 Newton-Schulz iteration으로 gradient momentum을 근사 직교화(orthogonalization)한다. Kimi K2와 Moonshot 등의 대규모 LLM 학습에서 채택된 사례가 있다. 임베딩과 norm, logits 등에는 여전히 Adam을 쓰는 하이브리드 구성이 표준이다. 이 저장소가 반영해 온 프로덕션 recsys 학습 파이프라인 가운데 Muon 채택을 코드로 확인한 첫 사례라는 점이 오늘 자료에서 가장 중요한 신호다.

새로 알게 된 것

(1) Phoenix의 dense-parameter optimizer가 Adam에서 Muon으로 바뀌었다

Phoenix 학습은 dense-parameter를 Newton-Schulz orthogonalization을 쓰는 Muon으로 옮기고, embedding·logits·norm은 그대로 Adam에 남기는 하이브리드가 됐다. 파일 두 개가 새로 추가됐다.

  • 새 optimizer 구현체가 240줄짜리 파일로 추가됐다 확인 — phoenix/xrex/optimizers/recsys/muon.py.
    • optax.contrib._muon의 orthogonalize_via_newton_schulz와 MuonDimensionNumbers를 감싸는 얇은 어댑터다.
    • xrex 파라미터 트리에 맞게 라벨링과 마스킹을 수행한다.
  • 이 optimizer를 config로 노출하는 47줄짜리 파일도 추가됐다 확인 — phoenix/xrex/optimizers/recsys/dense_optim.py.

하이브리드의 핵심 패턴은 matrix-shaped 파라미터만 Muon으로 처리하고, 아래 이름 패턴에 걸리는 파라미터는 Adam으로 남기는 것이다.

muon_adam_patterns: str = "embed,_emb,logits,vocab,norm,table"

— phoenix/xrex/optimizers/recsys/dense_optim.py:14

즉 임베딩 테이블과 출력 logits 헤드, vocab, layernorm/rmsnorm은 Adam에 남고, 트랜스포머 body의 attention과 FFN weight matrix만 Muon으로 학습된다. 이는 Keller Jordan이 2024년에 낸 원본과 Kimi K2 계열이 쓰는 표준 패턴과 일치한다.

기본 config _home_direct_packed_base()에서 optim 관련 값이 전면 교체됐다 확인 — phoenix/xrex/configs/xrecsys.py:302-330.

"optim_config": RecsysDenseOptimConfig(
    optim="muon",
    muon_consistent_rms=0.2,
    muon_matrix_weight_decay=0.014,
    muon_split_fused="qkv:128",
    adam_embedding_weight_decay=0.014,
    b1=0.95,
    b2=0.98,
),

— phoenix/xrex/configs/xrecsys.py:309-317

바뀐 값을 이전 값과 나란히 놓으면 다음과 같다.

파라미터 3세대~4세대+3 4세대+4 (aad7179)
optim Adam (기본) "muon"
learning_rate (dense) 1e-3 7.1e-4
emb_learning_rate 0.2 (config에 명시) (embedding config로 이동)
muon_consistent_rms — 0.2
muon_matrix_weight_decay — 0.014
muon_split_fused — "qkv:128" (fused QKV 프로젝션을 128-dim block 단위로 분할해 각각 직교화한다)
adam_embedding_weight_decay — 0.014
b1, b2 — 0.95, 0.98
embedding optim rowwise_adagrad (LR 0.2) RecsysRowwiseAdagradConfig(learning_rate=0.28, half_life_steps=2500, lazy_decay=True, weight_decay=2.8e-4)

GB300 override도 같은 방향으로 Muon을 채택했다. 설정은 LR 5e-4, half_life_steps=5000, weight_decay=0.01이다.

  • muon_split_fused="qkv:128"는 fused QKV projection의 output axis를 128-dim block으로 잘라서, 각 block을 orthogonalization의 독립된 단위로 다룬다는 뜻이다.

    • scale_by_muon_shaped가 block 단위로 dim_nums를 다시 계산해서 Newton-Schulz를 병렬로 수행한다.
    if block is not None and x.shape[-1] > block:
        n_blocks = x.shape[-1] // block
        xs = x.reshape(x.shape[:-1] + (n_blocks, block))
        dn = optax_contrib.MuonDimensionNumbers(reduction_axis=-3, output_axis=-1)
        o = orthogonalize_via_newton_schulz(xs, ns_coeffs, ns_steps, preconditioning, 1e-8, dn)
    

    — phoenix/xrex/optimizers/recsys/muon.py:135-141

  • muon_consistent_rms=0.2 옵션은 Muon 업데이트에 sqrt(max(fan_in, fan_out)) × consistent_rms 스케일을 적용해서, layer마다 update magnitude를 일관되게 유지하는 조절 값이다.

    • 원본 Muon의 fan-in/fan-out 스케일링을 대신해서 쓸 수 있는 안정화 파라미터이기도 하다.

의미 LLM 학습에서 자리 잡은 optimizer인 Muon이 랭커와 retrieval 학습으로 넘어왔다는 관찰 항목이 새로 생겼다. 이 저장소가 반영해 온 프로덕션 recsys 학습 파이프라인(Netflix FM, Meta HSTU/GEM, Kuaishou OneRec 등) 가운데 Muon 채택을 코드로 확인한 첫 사례이므로, 오늘 자료에서 가장 먼저 다룰 항목이다. 다른 회사들이 뒤따르는지는 앞으로 3~6개월 동안 확인해야 한다.

(2) Phoenix가 검색 랭킹으로 확장됐고 검색 전용 학습 config가 생겼다

Phoenix가 검색 랭킹으로 확장됐다. For You 피드 학습 config xrecsys 옆에 xrecsys_search가 나란히 추가됐다 확인 — phoenix/xrex/configs/xrecsys.py:435-473. 새 config xrecsys_search는 별도 vocab과 함께 use_product_surface, condition_search_relevance_on_prompt를 갖췄다. 주요 차이는 다음과 같다.

  • vocab을 대폭 확장했다. For You config의 vocab보다 훨씬 큰데, 검색 쿼리와 클릭 코퍼스는 사용자와 아이템의 다양성이 커서 vocab을 넓혀야 하기 때문이다.
    • 값은 user_vocab_size=100_000_000, item_vocab_size=100_000_000, author_vocab_size=30_000_000, ip_vocab_size=10_000_000이다.
  • 아키텍처는 KV head를 query head보다 적게 두는 GQA 구성이다.
    • 값은 num_layers=8, emb_size=2560, emb_table_width=1024, query_heads=20, kv_heads=4(GQA), history_seq_len=1022, candidate_seq_len=64다.
  • 분산 설정에서는 expert-parallel이 512로 For You base config보다 EP 축이 훨씬 크고, 따라서 MoE 라우팅도 검색 config 쪽이 훨씬 크다.
    • 값은 ep=512, dp=2, fsdp=1, tp=1이다.
  • 검색에 특화된 플래그가 붙었다.
    • use_product_surface=True는 제품 지면 컨디셔닝을 켠다.
    • output_vocab_size=128은 action을 128종으로 확장한다.
    • 나머지는 condition_search_relevance_on_prompt=True, use_dense_action_table=True, metric_group="search"다.
  • 훈련 시그널은 group_id="user_action_sequence_xrecsys"로 별도 그룹을 두고, log_q_correction=True를 켠다.
"xrecsys_search": _make_cfg(
    {
        "history_seq_len": 1022,
        "candidate_seq_len": 64,
        ...
        "num_layers": 8,
        "emb_size": 2560,
        "emb_table_width": 1024,
        "query_heads": 20,
        "kv_heads": 4,
        ...
        "ep": 512,
        "fsdp": 1,
        "dp": 2,
        ...
        "use_product_surface": True,
        "output_vocab_size": 128,
        "metric_group": "search",
        "use_dense_action_table": True,
        "condition_search_relevance_on_prompt": True,
    },
    user_vocab_size=100_000_000,
    item_vocab_size=100_000_000,
    author_vocab_size=30_000_000,
    ip_vocab_size=10_000_000,
),

— phoenix/xrex/configs/xrecsys.py:436-472

이 config는 proto에 새로 들어온 action 열거 두 개와 짝을 이룬다. proto에는 CLIENT_TWEET_(NOT_)RELEVANT_TO_SEARCH 액션 두 개가 새 번호로 정의됐다.

  • 새 번호는 CLIENT_TWEET_RELEVANT_TO_SEARCH = 105와 CLIENT_TWEET_NOT_RELEVANT_TO_SEARCH = 106이다.

  • 기존 161번과 162번 자리는 *_DEPRECATED로 남았다.

    CLIENT_TWEET_RELEVANT_TO_SEARCH_DEPRECATED = 161;
    CLIENT_TWEET_NOT_RELEVANT_TO_SEARCH_DEPRECATED = 162;
    

    — phoenix/crates/serving/xai-recsys-proto/proto/recsys.proto:379-380

의미 같은 Phoenix 트랜스포머 아키텍처가 지면별 config만 바꿔 끼우면 검색과 피드를 모두 서빙하는 방향으로 통합이 진행되고 있다는 사실을 새로 확인했다. 지금까지 canon은 각 지면(For You, Following, 검색)이 별개 코드베이스라고 이해해 왔다. 이 통합은 Netflix UniCoRn(2024)이 내세운 "검색·pre-query·More Like This 단일 컨텍스추얼 랭커"와 GenRec(2026)의 "언어화 기반 단일 채점기"와 방향이 같다. X가 여기에 어떤 지면(트윗 검색, 유저 검색, 미디어 검색)을 붙일지, 프로덕션 배포는 언제인지가 다음에 확인할 지점이다.

Phoenix proto에 reward 헤드와 link-open 확률 5분위 헤드가 정의됐다. Phoenix의 예측 출력 스키마가 두 방향으로 확장됐다 확인 — phoenix/crates/serving/xai-recsys-proto/proto/recsys.proto.

(a) RewardOutputs 메시지가 신설됐다. NextActionDistribution에 RewardOutputs rewardOutputs = 8 필드가 추가됐다.

message RewardOutputs {
  repeated float values = 1;
  repeated float policyLogits = 2;
}

— recsys.proto:229-234

ScoreInfo에도 rewardRerankSlotProb 필드가 새로 생겼다. 선언은 optional double rewardRerankSlotProb = 5다. 즉 Phoenix가 확률 예측 헤드 24개와 나란히 reward value 헤드와 policy logits 헤드를 함께 낼 수 있도록 스캐폴딩이 준비됐다. actor-critic은 value와 policy를 함께 두는 구조다. actor-critic 방식이거나 reward-model-guided 재순위 슬레이트 결정에 쓰려는 것으로 보이지만, 어느 스코어러가 이 필드를 사용하는지는 아직 연결되어 있지 않다 추정(proto에 정의만 됐고, home-mixer/scorers/에서 이 필드를 소비하는 코드는 이 커밋에 없다).

(b) link-open 확률 5분위 헤드가 생겼다. PLACE_HOLDER_167/168/169/170/253 다섯 자리에 각각 이름이 붙었다.

P_OPEN_LINK_P10 = 167;
P_OPEN_LINK_P25 = 168;
P_OPEN_LINK_P50 = 169;
P_OPEN_LINK_P75 = 170;
...
P_OPEN_LINK_P90 = 253;

— recsys.proto:385-388, 442

링크를 여는 확률을 단일 스칼라가 아니라 분위 5개로 이루어진 분포로 예측한다는 뜻이다. 지금까지 X의 예측 헤드는 단일 확률이나 스칼라 계열이었으므로, 이 헤드는 분포 형태를 예측하는 방식이 랭커에 처음 도입된 사례다. 실체가 quantile regression인지 categorical mixture head인지는 recsys_model.py를 심층 분석해서 확인해야 한다. 이 파일은 +265/−25로 대폭 개편됐다.

(c) SlateContext에 SID(semantic ID) 필드 7개가 추가됐다. sidKnown과 sidK1/2/3, sidGap1/2/3이 새로 생겼다. 이 필드들은 4세대+3(8/18)에서 VMRanker에 연결된 SID 필드와 프로토 수준에서 짝이 맞는다. SID는 포스트를 coarse에서 fine 계층의 codeword 시퀀스로 나타내는 ID다. VMRanker는 슬레이트 재정렬 서비스다.

새로 알게 된 것그 밖의 변경

  • Following 파이프라인 전용 muted-keyword 필터와 quoted text hydrator가 추가됐다. Following 파이프라인 하드닝을 이어 간 변경이다.
    • FollowingViewerMutedKeywordFilter(65줄 신규)는 quoted text와 ancestor까지 매치한다.
    • QuotedPostTextHydrator(106줄 신규)는 TES에서 quoted text를 가져온다.
    • TES(Tweet Entity Service)는 X 내부의 트윗 메타데이터 조회 서비스다.
  • grox PTOS에 Grok 4.6 internal 10% dial을 넣어, 아동 안전 cross-validation과 deluxe 4.3 카테고리 재분류에서 호출의 10%를 4.5 대신 4.6으로 보내기 시작했다 확인 — grox/flows/ptos/classifier.py:276-300.
    • 4.6의 응답도 4.5와 똑같이 self._parse_policy(raw)로 파싱해 판정에 쓴다. 결과를 버리는 shadow가 아니라 실트래픽을 나누는 점진 롤아웃이다(L281-290, L477-482).
    • grox는 Grok 기반 nearline 주석 파이프라인이다. PTOS는 grox 안전 파이프라인에서 정책 기반으로 위반 카테고리를 판정하는 계층이다.
    • dial은 grox PTOS classifier.py의 _GROK_4_6_INTERNAL_DIAL = 0.1이다.
    • prior_nsfw.py(34줄 신규)로 Manhattan lookup 캐시를 분리했다.
  • VF에 env-gated shadow deployment 미러링 인프라가 구성됐다.
    • 구성 코드는 visibility-filtering/dark_traffic_setup.rs(109줄 신규)다.
    • shadow deployment 이름은 xai-vf-shadow.prod.visibility다.
  • Phoenix 기본 config에서 bool 3종과 engagement counts 플래그가 train-default ON으로 승격됐다.
    • 기본 config는 _home_direct_packed_base()다.
    • bool 3종은 4세대+1(8/14)에 값이 채워지기 시작한 enable_stale_post, enable_is_author_followed_by_viewer, enable_is_author_following_viewer다.
    • engagement counts 플래그는 enable_engagement_counts다.

정본 반영 services/x.md를 다음과 같이 고쳤다.

  • 세대 테이블에 4세대+4 (aad7179, 2026-08-19) 행을 추가했다.
  • 한 줄 요약에는 Muon, xrecsys_search, RewardOutputs, link-open 5분위, Following filter, Grok 4.6 dial, dark_traffic, train-default 승격까지 8개 항목을 담았다.
  • "Phoenix 학습·인덱스" 절을 대폭 확장해서 소절 3개를 새로 만들었다. 소절은 "4세대+4 Phoenix dense-parameter optimizer가 Adam → Muon 전환", "Phoenix가 검색 랭킹으로 확장", "Phoenix proto에 reward head + link-open 5분위 헤드 신설"이다.
  • bool feature 표 아래에는 train-default ON 승격 항목을 추가했다.
  • 필터 절에는 "4세대+4 신규 — Following 파이프라인 전용 muted-keyword filter + quoted-text hydrator" 소절을 추가했다.
  • Grox → PtOS 절에는 "4세대+4 Grok 4.6 internal 10% 트래픽 dial + NSFW 재분류 스킵 캐시" 소절을 추가했다.
  • 안전 절에는 "4세대+4 visibility-filtering shadow deployment(xai-vf-shadow) 배선"을 신설했다.
  • 열린 질문 절에는 "4세대+4 공개로 해소된 것" 서브섹션을 신설해서, 해소 8개와 심층 분석이 필요한 6개를 정리했다.
  • 출처 절에는 aad7179 관련 파일 링크 10개를 추가했다.

의미 8/17부터 사흘 연속 이어진 후속 커밋의 성격이 오늘 크게 바뀌었다. 8/14부터 8/18까지(4세대+1부터 +3까지)는 brand safety 문구 조정과 filter 신설, hydrator 분기, 흐름 통합처럼 "매일 소규모 정교화"에 해당했다. 4세대+4는 다음 세 축에서 실질적으로 확장됐다.

  • 학습 파이프라인을 대개편했다(Muon).
  • retrieval 지면을 확장했다(검색).
  • 안전 인프라를 신설했다(dark traffic).

Phoenix에 관한 다음 네 가지는 canon이 3세대부터 4세대+3까지 이해해 온 내용에 없던 새로운 축이다.

  • Phoenix가 LLM optimizer인 Muon으로 학습된다.
  • Phoenix가 검색 지면까지 담당한다.
  • Phoenix가 reward head를 갖춘다.
  • Phoenix가 링크 클릭 확률을 분포 형태로 예측한다.

특히 Muon 채택은 이 저장소가 반영해 온 대규모 프로덕션 recsys 학습 파이프라인 가운데 코드로 확인한 첫 사례이며, LLM 학습에서 시작된 optimizer가 랭커와 retrieval 학습으로 퍼지고 있다는 관찰의 첫 데이터포인트이므로 topics/sequence-transformer-ranking.md에 새로 확인할 축이 하나 생긴다. 검색 지면 확장은 Netflix UniCoRn과 GenRec이 개척한 "검색·추천 단일 랭커" 흐름을 뒤따르는 두 번째 회사 진술 후보이므로, 프로덕션 배포가 확인되는지를 다음 커밋에서 살펴야 한다. Muon 채택과 Phoenix 검색 확장은 이 저장소가 반영해 온 대규모 프로덕션 recsys 학습 파이프라인에서 처음 확인한 두 가지 사실이므로 심층 분석 대상으로 잡았다.

2아트워크·프리뷰 개인화가 CLIP two-tower와 MediaFM으로 세대 전환했다 — Netflix

자료 Multimedia Asset Personalization via Multimodal Embeddings at Netflix (arXiv 2608.18322) — arXiv, 2026-08-18 제출, 논문. 저자 8명이 모두 Netflix 소속이다. 저자는 Emma Yanyang Kong, Aditya Deshpande, Bowei Yan, Asad Abbasi, Santiago Castro, Avneesh Saluja, David Fagnan, Ashish Rastogi이고, 소속은 제목과 소속 표기로 확인했다.

배경 Netflix의 아트워크 개인화는 2017년에 블로그로 전면 배포 진술이 나온 뒤로, canon이 큰 갱신 없이 "재순위·다양성"에서 한 줄 언급하는 수준으로 유지돼 왔다. 2017년의 밴딧 접근은 캔버스별 별도 모델을 두는 방식이어서, 캔버스 5종(billboard / vertical box / horizontal panel / short panel / landscape panel)마다 다르게 학습하고 서빙했다. 또 이미지의 콘텐츠 자체는 모델 밖에서 다뤄졌기 때문에 신규 타이틀과 에셋의 콜드스타트가 근본적으로 어려웠다. 이번 논문은 2017년의 그 아키텍처가 CLIP 기반 통합 two-tower와 자체 tri-modal foundation model인 MediaFM으로 세대 전환했다는 사실을 A/B 정량치와 함께 처음 공식화한 자료다.

새로 등장하는 개념은 다음과 같다.

  • CLIP은 OpenAI가 2021년에 낸 vision-language 모델이다. 이미지와 텍스트를 같은 임베딩 공간에 매핑해서 zero-shot 이미지 분류와 검색을 가능하게 했다. 여기서는 이미지 인코더를 사전학습한 결과인 768차원 임베딩을 그대로 재활용한다.
  • two-tower 모델은 유저 tower와 아이템 tower가 각각 표현을 만들고 dot product로 매칭 스코어를 내는 retrieval/ranking 아키텍처다. 이 논문에서는 아이템 tower에 CLIP 이미지 임베딩을 concat한다.
  • SeqCLIP은 CLIP 방식의 프레임 시퀀스 인코더다. 비디오 프리뷰의 shot들을 순서대로 처리해서 shot별 시각 표현을 만든다.
  • wav2vec 2.0은 Facebook 2020, 음성 self-supervised 표현 학습 모델이다. 여기서는 프리뷰 shot의 오디오 트랙 표현을 담당한다.
  • text-embedding-3-large는 OpenAI가 2024년에 낸 텍스트 임베딩 모델이다. 여기서는 shot의 timed-text를 처리한다. timed-text는 자막과 대사에 타임스탬프를 붙인 텍스트다.
  • Masked Shot Modeling은 BERT의 Masked Language Modeling을 shot 단위로 옮긴 self-supervised objective다. shot의 20%를 마스킹하고 cosine distance loss로 복원한다.
  • IPS(Inverse Propensity Scoring) lift는 off-policy evaluation에서 자주 쓰는 오프라인 지표다. 로그로 남은 무작위 노출 데이터로 새 모델의 counterfactual 성능을 추정한다.

새로 알게 된 것

CLIP 기반 통합 two-tower가 캔버스 5종을 단일 모델로 합쳤다

캔버스별로 따로 두던 모델 5개가 CLIP 이미지 임베딩(768-d)을 item tower에 concat한 단일 two-tower로 통합됐다 확인 §3.

  • 학습은 reward-weighted 방식이다. 캔버스별 학습 예제를 reward 가중치로 균형 잡아서 특정 캔버스로 쏠리지 않게 한다.
  • 콜드스타트 면에서는 신규 타이틀과 에셋을 상호작용 이력 없이도 CLIP 임베딩만으로 "day zero"에 서빙할 수 있다. ID만 쓰는 모델이 지닌 근본적인 한계를 해소했다.

"Augmenting a two-tower model with CLIP image embeddings lets a single model serve all five Netflix artwork canvas types, replacing five separately trained per-canvas models and substantially improving cold-start performance." — arXiv 2608.18322 abstract

온라인 A/B 결과는 네 가지다.

  • 코어 discovery 메트릭이 상대적으로 +0.127% 올랐다(p<0.005) 확인 §5.1.
  • Eclipse UI 홀드백과 비교하면 discovery가 +0.233%, streaming hours가 +0.184% 올랐다 확인 §5.1.
    • 홀드백은 변경을 적용하지 않고 남겨 둔 비교 집단이다.
  • 저자는 연간 ≈350M streaming hours가 추가된다고 추정한다 확인 §5.1.
  • CLIP의 joint text-image space를 재활용해서 query-aware artwork를 검색 캔버스에 적용했고, playthrough rate가 +0.36% 올랐다(p<0.05) 확인 §5.1.

MediaFM은 Netflix가 자체 학습한 tri-modal foundation model이다

  • MediaFM은 비디오 프리뷰 개인화를 위해 자체 학습한 tri-modal FM이다 확인 §4.
    • 시각, 음성, timed-text 세 모달리티를 쓰고, 각각 SeqCLIP, wav2vec 2.0, text-embedding-3-large가 맡는다.
    • shot마다 이들을 concat한 뒤 2,304-d unit-normed 벡터로 만든다.
    • 인코더는 BERT 방식의 3-layer / 8-head transformer다.
    • Masked Shot Modeling(shot의 20%를 마스킹한다)과 cosine distance loss로 self-supervised 사전학습을 수행한다.
    • 프리뷰 표현은 contextualized shot embedding을 mean-pool해서 얻는다.
    • 학습 코퍼스는 Netflix 쇼 카탈로그에서 뽑은 대규모 shot corpus다. 구체적인 규모는 공개하지 않았다.
    • 모든 디바이스 플랫폼의 비디오 프리뷰 개인화에 적용한다. 프리뷰 길이는 30~90초다.
    • TV UI 서피스에서 이득이 가장 크다.

"MediaFM, our in-house tri-modal foundation model trained on a large-scale corpus of shots from the Netflix show catalog, fusing visual (SeqCLIP), audio (wav2vec 2.0), and timed-text signals; adopted for video preview personalization, it outperforms strong visual-only baselines both offline and in online A/B tests." — arXiv 2608.18322 abstract

  • 온라인 A/B에서 streaming 메트릭이 상대적으로 +0.193% 올랐다(p<0.02) 확인 §5.2.
  • 오프라인 IPS lift는 0.380%다 확인 §5.2.
  • visual-only 베이스라인보다 tri-modal이 낫다는 점이 오프라인과 온라인 양쪽에서 확인됐다 확인 §5.2.
    • 즉 modality 세 개가 모두 붙어야 이득이 자리를 잡는다.

새 MediaFM 체크포인트는 오프라인 프록시 태스크로 gating한다

MediaFM 체크포인트의 릴리스를 gating하려고 Popularity-Based Winner라는 새 오프라인 프록시를 배치했다 확인 §5.4.

  • 이 프록시는 "만약 unpersonalized·uniform serving policy로 노출했다면 어떤 에셋이 이겼을까"를 에셋 콘텐츠 임베딩만 입력으로 받아서 예측한다.
    • 방식은 linear probe binary classification이다. linear probe는 고정된 임베딩 위에 선형 분류기만 학습해 표현 품질을 재는 방법이다.
  • 이 프록시가 유효한 이유는 end-to-end integration이나 A/B test 없이도 임베딩 quality의 순위를 매길 수 있다는 점이다.
    • 온라인 결과와 상관관계도 관찰됐다. 프로브 정확도 순위와 오프라인 IPS, 온라인 A/B 결과 순위가 세 시그널에서 모두 일치했다.
  • MediaFM의 프로브 정확도는 pick-at-random과 비교해 +25.90 percentage points 높다.
    • SeqCLIP 단독은 +18.75 pp다.
    • 트리모달의 uplift가 shot-level 프록시에서도 재현된다.
  • 새 MediaFM 체크포인트는 모두 이 프록시로 gating한다. 후보 공간을 pruning한 뒤에야 A/B로 넘어간다.
    • Netflix가 오랫동안 안고 있던 문제, 즉 오프라인 지표가 A/B를 예측하지 못한다는 문제를 임베딩 quality 하나만 다루는 단일 태스크로 부분적으로 우회한 사례다.

Netflix Embedding Store는 플랫폼 레이어에서 3단으로 캐싱한다

Netflix Embedding Store는 플랫폼 레이어에서 3단으로 캐싱한다 확인 §4.3.

  1. 콘텐츠 임베딩은 에셋이 카탈로그에 유입되는 순간에 미리 계산한다(ingestion time).
  2. Item-tower projection은 에셋마다 캐시한다.
  3. 일일 materialization으로 프로필별 상위 약 500개 타이틀을 골라 미리 계산한다.

이 3단 캐싱 덕분에 저지연 서빙과 값싼 스크리닝이 동시에 가능해졌다. netflix.md 후보 생성 절에 적었듯이, FM 시대에 이미 회원 임베딩을 배치로 생산하는 일이 프로덕션에 올라와 있었다. FM은 회원의 상호작용 이력을 토큰 시퀀스로 바꿔 학습하는 Netflix의 foundation model이다. MediaFM은 아이템 쪽 임베딩 파이프라인을 같은 방식으로 확립했다. 회원 쪽에 대응하는 사실이다.

정본 반영 services/netflix.md를 다음과 같이 고쳤다.

  • 재순위·다양성·필터 절에서 아트워크 관련 한 줄을 갱신해서, 2017년 밴딧에서 2026년 MediaFM으로 세대가 바뀐 점을 명시했다.
  • "아트워크·비디오 프리뷰 개인화 — MediaFM tri-modal FM (2026-08 프로덕션)" 절을 신설했다. 소절 5개는 CLIP 기반 통합 two-tower, MediaFM tri-modal FM, Popularity-Based Winner 오프라인 프록시, Netflix Embedding Store 인프라, 의미다.
  • 최종 갱신 날짜는 2026-08-21로 바꿨다.
  • 출처 절에는 arXiv 2608.18322 항목을 추가했다.

의미 이 논문은 아트워크 개인화 축을 별도의 프로덕션 시스템으로 확립했다. 지금까지 canon은 아트워크 개인화를 "재순위·다양성"에서 한 줄 언급하는 정도로만 다뤘다. 2017년 밴딧 이후로 큰 갱신이 없었기 때문이다. 달라진 점은 네 가지다.

  1. 아키텍처가 캔버스별 모델에서 단일 모델로 통합됐다(5개에서 1개로).
  2. modality가 시각 하나에서 tri-modal로 확장됐고, audio와 timed-text의 uplift가 정량적으로 검증됐다.
  3. 콜드스타트를 담당하는 위치가 랭커 안이 아니라 사전학습된 임베딩으로 옮겨졌다(day-zero CLIP 임베딩).
  4. 오프라인 gating이 A/B의 전제조건으로 프로덕션 프로세스에 편입됐다(popularity-based winner).

이는 Netflix가 진행해 온 "FM으로 회원 표현을 중앙화한다"는 흐름에서 아이템 쪽에 대응하는 작업이라고 볼 수 있다. 회원은 FM(2025)이 담당하고 아이템은 MediaFM(2026)이 담당한다. 두 임베딩이 결합되어 랭커와 retrieval, 아트워크, 프리뷰의 공통 하부구조가 되는 방향이다. Netflix는 Foundation Model과 GenRec, MediaFM, GenPage로 이루어진 4대 FM 스택을 코드와 논문으로 모두 공개한 셈이 됐다. 회원 중앙화에 대응하는 축인 아이템 중앙화도 이 저장소의 canon에 반영됐다.

다음에 볼 것