X (Twitter)
최종 갱신: 2026-08-29
한 줄 요약
For You 타임라인은 Thunder(인네트워크 최신) + Phoenix retrieval(OON) + SimClusters(OON, 2026-08 부활) 로 후보를 모아(레거시 tweet-mixer는 기본 off로 미러링됨), Grok 기반 트랜스포머 Phoenix가 후보당 24개(문서 기준) 참여 확률을 예측하고, 그 확률들의 가중합에 작성자 다양성 감쇠·OON 배수·새-작성자 부스트를 조합해 정렬한 뒤, 필터 21개(스코어링 전 18 + 후 3)와 VMRanker DPP(θ=0.65, K=150) 슬레이트 재정렬, 광고·팔로우추천 블렌딩을 거쳐 나간다.
가중치 숫자는 2026-08-13 4세대 드랍에서 home-mixer/params/param.rs가 프로덕션 크론 미러로 공개됐다 (예: reply 5.0, favorite 0.5, retweet 1.0, share via copy link 20.0, report −234; 상호팔로우 원본에 reply +15 boost). 2026-08-14 후속 드랍(c65aa17)에서 가중치 해석 오해(“ratio를 raw count 등가로 읽지 말라”)가 코드 주석으로 못박히고, 브라질 2026 선거 필터(665개 하드코딩 계정, 팔로잉 예외)가 신설됐으며, 콜드스타트 Thompson sampling·14일 stale post 게이팅·BDSM enforcement note 생성기 부분 공개가 붙었다. 2026-08-17 세 번째 후속 드랍(b089ce6)에서 광고 브랜드 안전 판정 V2 v1·성인 컨텐츠 판정 cross-validation 계층·Phoenix retrieval 인덱싱 게이트 제거가 붙었고, 2026-08-18 네 번째 후속 드랍(11a71f8)에서 광고 안전 V2 헬퍼 하루 만에 재설계·Following 전용 VF hydrator·VMRanker SID 배선·Phoenix Kafka v3·grox reply_spam 통합이 붙었다. 2026-08-19 다섯 번째 후속 드랍(aad7179)에서 (1) Phoenix 학습이 Adam에서 Muon optimizer로 전환 — dense-parameter 기본 optimizer가 optax 기반 Muon(Newton-Schulz orthogonalization)으로 바뀌었고 embedding·norm·logits는 여전히 Adam 하이브리드, base learning rate 1e-3 → 7.1e-4, (2) Phoenix가 검색 랭킹으로 확장 — 새 config xrecsys_search가 별도 vocab(100M user/item, 30M author)·history_seq_len 1022·use_product_surface=True·condition_search_relevance_on_prompt=True로 등장, (3) Phoenix proto에 RewardOutputs(values + policyLogits) 메시지 + rewardRerankSlotProb 필드 신설(reward-based 재순위 스캐폴딩), link-open 확률 5분위 헤드(P10/P25/P50/P75/P90) 추가, (4) Following-side 전용 FollowingViewerMutedKeywordFilter(65줄 신규)와 QuotedPostTextHydrator(106줄 신규)로 Following 파이프라인 하드닝 계속, (5) grox PTOS에 Grok 4.6 internal 10% dial 도입(_GROK_4_6_INTERNAL_DIAL = 0.1)과 새 prior_nsfw.py(Manhattan 조회로 이미 NSFW 플래그된 포스트 재분류 스킵) 신설, (6) visibility-filtering에 dark_traffic_setup.rs(109줄 신규) — env-gated로 특정 ordinal pod만 요청을 xai-vf-shadow.prod.visibility 섀도 배포로 미러링, (7) Phoenix 기본 학습 config _home_direct_packed_base()에 enable_stale_post=True·enable_is_author_followed_by_viewer=True·enable_is_author_following_viewer=True·enable_engagement_counts=True 네 피처가 train-default ON으로 승격(4세대+1에서 populated된 bool 3종이 이제 학습 기본 입력). 2026-08-20 여섯 번째 후속 드랍(d0cef2f)에서 (1) AI trend feedback context hydrator 신규(157줄) — For You 후보에 "AI trend" 라벨을 topic feedback과 나란한 두 번째 컨텍스트 채널로 붙임, top-2 trend를 후보 빈도로 뽑고 trend당 후보 1개 랜덤 선택 + https://x.com/i/trending/{trend_id} 랜딩 URL, standalone original post + non-topic + non-in-network 조건, (2) served_slate_context 배선 시작 — 4세대+4에서 준비된 proto가 실 파이프라인 소비로 이어짐, PhoenixScorer가 예측 응답의 candidate_slate_context()를 뽑아 세팅, UseServedSlateContext 게이트로 RankingScorer가 로컬 계산·캐시 대신 서빙 산출 slate context(pool_rank·fatigue·pre_diversity·SID 3계층·SID gap 3계층) 그대로 사용 (세 갈래 폴백), (3) emb_table.rs 리팩터(+189/−169) — load_tensor를 pyo3-free core(load_tensor_into) + Python wrapper로 분리, tokio runtime unwrap() → map_err, checkpoint path too short 방어, (4) Grok 4.6 internal dial 0.1 → 0.3 (하루 만에 3배), (5) grok_sampler에 stop_predicate callback + aclosing — 스트리밍 조기 종료 및 llm.sample.early_stop.count 카운터, (6) grox User 스키마에 profile_image 필드 신설. 2026-08-21 일곱 번째 후속 드랍(28e414f)에서 (1) 광고 conversion 액션 20개 신설 — proto ActionName 171–190에 MACT 인앱 이벤트 6종(purchase·add_to_cart·level_achieved·tutorial_complete·sign_up·custom) × click/view 2계열 = 12개 + view-through conversion 8개(purchase/add_to_cart/checkout_initiated/sign_up/site_visit/session/landing_page_view/upper_funnel), (2) split_head_training_by_source — delayed feedback을 학습 손실에서 분기 — kafka에 is_delayed_feedback 컬럼을 흘리면 sample_source batch 필드로 들어와 engagement head는 fresh 샘플에만·conversion head는 delayed 샘플에만 학습하도록 loss mask 갈림, fresh/delayed_clicked/delayed_non_clicked 메트릭 슬라이스 신설, mact_in_app_loss_weight·train_view_through_heads·conversion_keep_mask 튜닝 노브 노출, 새 metric group ads_slim(3 긍정 + 4 부정 + non-primary conversion click), 부정 피드백에 CLIENT_TWEET_SEARCH_QUERY_REFORMULATED 추가, (3) Muon optimizer가 export에 정식 포함 — TRAINING.md·README가 "flagship ranking config + home_direct_packed_nano가 프로덕션 Muon 레시피로 end-to-end 학습"으로 재작성, embedding rowwise AdaGrad에 accumulator half-life decay + lazy per-row decay + decoupled weight decay 세 옵션 포함, (4) NVIDIA GB300 하드웨어 오버라이드 첫 등장 — _GB300_OVERRIDES에 bs_per_device=512·ep=64·attn_impl="cutedsl_ranker_varlen_attn"·remat_policy=RematType.SAVE_GB300_RECSYS·unroll_layer_stack=True·LR 5e-4 정의, home_direct_packed_nano가 이 오버라이드 상속, (5) xai-o2 스토리지 crate 인터페이스 공개 — S3 호환 오브젝트 스토리지 클라이언트의 BaseO2Client trait + 15개 builder method 노출, 다만 build()가 항상 "the xai-o2 backend is not included in this build" 에러 반환(구현 미공개), (6) SlateContext가 NextActionDistribution 필드 #9로 추가(action distribution마다 slate context), (7) grox reply_spam follower 임계 60k → 80k(10일간 4단계 상향, 이번은 1.33배로 완만), (8) visibility-filtering dark_traffic 타깃 shadow → staging 전환 — xai-vf-shadow.prod.visibility에서 xai-vf-service.staging.visibility:grpc로 리네이밍, TLS 도메인도 .staging.으로 이동(⚠ 4세대+4의 shadow 서술 재해석), (9) Grok 4.5 internal 완전 제거 — 4세대+2의 심판 도입 이후 dial 0.1→0.3→100%로 4일 만에 완결, _eapi_4_5_internal_breaker·_sample_4_5_internal·_GROK_4_6_INTERNAL_DIAL 전부 삭제, (10) retrieval post-embedding에 65k row 청킹, (11) hotswap --hotswap_malloc_trim 옵션 — 사이클당 ~196MiB 메모리 누수 문서화. 2026-08-24 여덟 번째 후속 드랍(d011592)에서 (1) VF 레퍼런스 비교 하니스 — 새 파일 visibility-filtering/reference_compare.rs(812줄)가 Strato 기반 레퍼런스 VF(StratoVfClient)를 매 요청마다 병렬 호출해 서비스 산출 verdict와 엄격 비교(action + reason 완전 일치, is_exact_match), 다르면 JSON 라인으로 로그(라인 12KiB 예산, vf_reference_compared/exact_match/differed/error/skipped/enabled 메트릭). 환경변수 VF_DUAL_CALL_HARNESS_ENABLED + APP_ENV 게이트, APP_ENV=prod면 부팅 시 panic으로 스테이징 전용 강제. dark_traffic(트래픽만 미러링)과 별개로 실제 verdict 대조 canary가 신설된 것. (2) 브랜드 안전 판정 4단계로 확장 — BrandSafetyVerdict::HighRisk = 4 신설, 기존 medium에 있던 5종(NSFW_HIGH_PRECISION·NSFW_HIGH_RECALL·GORE_AND_VIOLENCE_HIGH_PRECISION·PDNA·EGREGIOUS_NSFW)을 HighRisk로 승격 + 신규 SOFT_NSFW도 HighRisk. V2도 대칭 이동, 광고 유틸 has_avoid()가 Medium/High 둘 다 avoid로 대접, ads_brand_safety_vf_hydrator.rs의 NSFW ancestor 승격이 Medium → High. scored_posts_server.rs가 V2 라벨 5종(GROK_SFA_V2·GROK_NSFA_LIMITED_V2·GROK_NSFA_V2·GROK_NSFA_EXPANDED_V2·PTOS_REVIEWED)의 proto HM enum 매핑을 신설(다운스트림 노출). (3) PTOS 정책 판정 cross-validator 3개 카테고리로 확장 — 4세대+6에서 완전 제거됐던 Grok 4.5가 다른 엔드포인트(EAPI_GROK_4_5_X_ALGO)로 재도입되지만 primary가 아니라 judge 전용, SafetyPtosPolicyCrossValidator 신규 클래스가 ChildSafety·ViolentMedia·IllegalAndRegulatedBehaviors 세 카테고리에 대해 primary verdict를 4.5로 재확인 후 강등만 허용(disagreement → NoViolation 또는 lighter 정책). 4세대+2의 성인 컨텐츠 judge(SafetyPtosAdultContentCrossValidationJudge)와 나란히 존재. USE_REASONING_CATEGORIES = {ViolentSpeech, SuicideOrSelfHarm}·USE_THREAD_RENDERER_CATEGORIES 신설 — 이 두 카테고리에서만 thinking 제약 해제 + 부모 스레드까지 렌더러에 포함(맥락 없이는 위해 판정 불가). (4) Phoenix 체크포인트 로더 다중 노드 프로덕션 하드닝 — xai_checkpointing/load.py에 domains(per-tensor ts.IndexDomain 슬라이스), tag(체크포인트 서브디렉토리, 기본 "orbax-ckpt"), concurrent_gb(동시 디코딩 바이트 스로틀) 인자 신설. XAI_RESTORE_NODE_SERIALIZE 환경변수(기본 on)로 노드당 fcntl.flock()으로 restore 직렬화(/dev/shm/xai_restore_node_lock), 배치 사이에 gc.collect() + malloc_trim(0). Muon 세대 이후 Phoenix 모델이 커져 다중 워커 동시 restore가 호스트 OOM을 유발하는 문제 대응. (5) reply_spam 스코어 Strato 라이트백 신설 — grox/flows/reply_spam/strato_loader.py(49줄 신규) ReplyRankingScoreStratoLoader가 grox가 생성한 reply ranking 점수를 Strato에 put하고 score ≤ 1.0이면 지역 캐시(Atla, Pdxa)에 팬아웃 + Kafka v2에 emit(다운스트림 실시간 파이프라인용). (6) reply_spam follower 임계 80k → 100k — TaskSpamFilter·TaskReplyRankingFilter 둘 다 상향. 11일간 5단계(15k → 30k → 60k → 80k → 100k)로 계속 완화. (7) grox에 X Space(오디오) 렌더링 — SpaceMetadata 클래스 신설(현재 title만), Post에 space_metadata 필드, post_mapper.py가 Strato에서 매핑, lm/post.py 렌더러가 오디오 스페이스 카드로 LLM 입력에 포함. Grok 안전 판정이 오디오 스페이스가 붙은 포스트를 인식하기 시작. (8) ads_injection_logging_side_effect.rs가 EnableAdsBrandSafetyVerdictV2 experiment의 버킷을 ddg_experiment_bucket으로 로깅에 노출(DDG=광고 리포팅 파이프라인이 V2 실험군을 추적하기 시작). 2026-08-25 아홉 번째 후속 드랍(0d3cdd8, +5,850/−586, 파일 47)에서 (1) abuse-enforcement-service generic_actions 패스스루 — service-lib/src/generic_actions.rs(663줄 신규) + growthbook.rs(+126) + lib.rs(+276)로 스코어러가 직접 요청한 액션을 하드코딩 kind allowlist(user 5종·post 2종, MAX 16개/msg) + GrowthBook 동적 allowlist(kinds·suspend_policies·labels)로 이중 검증 후 실행. 거부된 요청은 outcome.info["requested_actions_skipped"] JSON + 메트릭으로 명시적 관측. 새 규칙 act_requested_actions + skip 규칙 platform_row_without_requested_actions 짝으로 배선. 첫 클라이언트 panda_reports_embedding_v10_rough_spam(embedding 기반 spam 검출기 v10) 임시 PlatformManipulation suspend. (2) VM Ranker 경로 대폭 단순화 — AUTHOR_DIVERSITY_VALUE_MODEL_ID + MPN 폴드백 로직(128줄) + AuthorColdStart 후처리 + ranking_scorer::effective_head_weights(88줄) 모두 삭제. 새 상수는 DPP_VALUE_MODEL_ID = "dpp"만 — VMRanker가 rank server 반환 점수를 그대로 통과, DPP 다양성은 서버 측 자체 로직으로. 4세대+5의 slate context 이관과 짝을 이루는 아키텍처 리팩터링(home-mixer 얇게, gRPC 서버들이 계산 담당). (3) Following 파이프라인 블록 관계 확장 — following_blocked_by_hydrator.rs(65줄 신규)가 각 candidate의 quoted/retweeted 저자 리스트를 SocialGraphClient에 batch로 check_blocked_by 조회, author_socialgraph_filter.rs가 여섯 갈래로 필터링(뷰어→저자 mute/block, 저자→뷰어 block, quoted 저자↔뷰어 block, retweeted 저자→뷰어 블록). quote/retweet 체인의 원 저자까지 블록 관계 존중 — quote/retweet을 통한 블록 우회 명시적 차단. reverse_chron_posts_pipeline.rs(+27/−2)에 배선. (4) Brazil2026ElectionFilter 계정 리스트 갱신 — TSE dadosabertos 2026-08-25 판 반영(+3,379줄, 파일 전체 4,947줄), README에도 "(Account list updated August 25, 2026.)" 명시. user_id는 obfuscated로 유지·@username은 그대로 노출(투명성/프라이버시 절충). (5) phoenix-rankall prefloor 스냅샷 배선 — store/base.rs(+202/−61) + config/mod.rs(+51/−12). min_age 있는 window에 대해 prefloor_<window>.parquet 동시 로드, PREFLOOR_SLACK_SECS = 6.0 * 3600.0. 신규 후보가 min_age 통과 전 별도 pool에서 유지되다 통과 즉시 프로덕션 반영 가능. (6) Phoenix copy_port rate-limit 하드닝 — copy_port_client.rs(+155) join_all(futures) → join_all(futures.map(tokio::task::spawn)), in-flight cap이 순차 폴링 없이도 정확하게 지켜지도록. 회귀 테스트 2개 신규. (7) README Latest Updates → Notable Updates 리네이밍(매일 후속 커밋을 README에 매일 반영하지 않겠다는 선언 [추정]). (8) URT 마셜링 층(ad_marshaller +18, client_event +27, wtf_marshaller +14, reverse_chron_following +12)에 소소한 확장, grox upa/constants.py·generators.py 새 배선(내용 미확인), engagement_counts_hydrator +16.
공개 소스 4세대 — 이걸 먼저 알아야 나머지가 안 헷갈린다
| 세대 | 레포 | 공개 | 언어 | 상태 |
|---|---|---|---|---|
| 1세대 | twitter/the-algorithm @ ef4c5eb…72eda9a |
2023-03-31 ~ 2023-07-07 | Scala/Java | 세상에 돌아다니는 "트위터 알고리즘" 분석의 99%가 이것 |
| 2세대 | 같은 레포 @ c54bec0 |
2025-09-03 | Scala | 988 파일, +65,319/−3,195. tweet-mixer 신설, Grok·Phoenix 진입 |
| 3세대 | xai-org/x-algorithm @ aaa167b·e414c17·0bfc279 |
2026-01-20·2026-05-15 | Rust/Python | 완전 재작성. 1·2세대와 코드 중복 0. 총 216파일 (초기 79 + grox 통째 추가 187 + LFS 포인터 교체) |
| 4세대 | 같은 레포 @ 47c1bcd (+ .gitattributes 정리 a389166) |
2026-08-13 | Rust/Python | +363,246/−11,640 (파일 300+). 가중치 params 미러 신설, visibility-filtering·labeling 서브레포 15개 신설, phoenix/ 학습+합성데이터 포함, SimClusters 부활, docs/BIDIRECTIONAL_BOOST_CHANGE.md로 파라미터 diff 문서화 관행 도입 |
| 4세대+1 | 같은 레포 @ c65aa17 |
2026-08-14 | Rust/Python | +2,271/−32 (파일 21). Brazil2026ElectionFilter 신설(1,573줄, 665 계정 하드코딩), 가중치 오해 해설을 param.rs·ranking_scorer.rs 주석으로 명시, 콜드스타트 Thompson sampling(off by default), Phoenix에 IS_STALE_POST14D·IS_AUTHOR_FOLLOWED_BY_VIEWER 등 bool 시퀀스 3개 신설, BDSM enforcement note 생성기 부분 공개(gate+dominant head만), grox reply-spam 임계 15k→30k, phoenix-rankall에 video_14day SID window 추가 |
| 4세대+2 | 같은 레포 @ b089ce6 |
2026-08-17 | Rust/Python | +751/−162 (파일 34). 광고 브랜드 안전 compute_verdict_v2 신설(medium 14→16, low 3, Grok 라벨 6종 _V2 마이그레이션, strip_v1_grok_written 헬퍼로 V1 dual-write 라벨 필터 [PROMPT_OWNED_RULES = 1400/1410/1420/1500/1510/1610/1700]), v2_mirrors_v1_across_tier_matrix 검증 테스트, 성인 컨텐츠 판정 cross-validation 태스크(task_safety_ptos_adult_content_cross_validation.py 162줄 신설, safemodel↔PtOS disagreement 시 Grok 4.5 심판 호출, 강등만 허용), phoenix-rankall-strato의 build1FavIndex·buildMMEmbMetadataDump에서 favoriteCount>=1 게이트 제거 + 1fav_uec_count_race 카운터 신설 |
| 4세대+3 | 같은 레포 @ 11a71f8 |
2026-08-18 | Rust/Python | +208/−70 (파일 14). strip_v1_grok_written 하루 만에 삭제 + V2_WRITTEN_LABELS 4개(GROK_SFA_V2·GROK_NSFA_V2·GROK_NSFA_LIMITED_V2·GROK_NSFA_EXPANDED_V2) 게이트로 V2 판정 시맨틱 재설계(V2 라벨 있으면 순수 V2, 없으면 V1 폴백), 새 테스트 v2_defers_to_v1_when_v2_has_not_ruled 추가; home-mixer/candidate_hydrators/vf_following_candidate_hydrator.rs 95줄 신규(reverse_chron_posts_pipeline이 이 hydrator를 씀, VF 결과만 남기고 다른 후보 필드는 ..Default::default()); home-mixer/scorers/vm_ranker.rs에 SID 필드 7개 배선(sid_known, sid_k_l1/2/3, sid_gap_l1/2/3); author_cold_start.rs의 count_tracked_ids가 tracked 필터·author_id 카운트 제거하고 tweet_id 항상 카운트로 단순화; grox reply_spam/generators.py PostStreamTaskGenerator 삭제 + ReplyRankingTaskGenerator에 PlanSpamComment·PlanCoordinatedSpam 흡수(단일 흐름 통합), task_filter.py follower 임계 30k → 60k; Phoenix postCreationEventForwarder v3 토픽 마이그레이션 + Kafka 클러스터 이동 + KeyValue(key=Long) 매핑; visibility-filtering/server_deps.rs에 Gizmoduck Strato 클라이언트 timeout 80ms 명시 |
| 4세대+4 | 같은 레포 @ aad7179 |
2026-08-19 | Rust/Python | +3,303/−651 (파일 79). phoenix/xrex/optimizers/recsys/muon.py(240줄 신규) + dense_optim.py(47줄 신규)로 Phoenix dense-param optimizer가 Adam → Muon 전환(embedding·logits·norm은 Adam 하이브리드, muon_adam_patterns="embed,_emb,logits,vocab,norm,table"), base LR 1e-3 → 7.1e-4, muon_split_fused="qkv:128", muon_consistent_rms=0.2. 새 config xrecsys_search(Phoenix가 검색 지면으로 확장, vocab 100M/100M/30M, use_product_surface·condition_search_relevance_on_prompt). Proto에 RewardOutputs(values + policyLogits) + ScoreInfo.rewardRerankSlotProb 신설, link-open 확률 P10/P25/P50/P75/P90 5분위 헤드 신설. home-mixer/filters/following_viewer_muted_keyword_filter.rs(65줄 신규) + candidate_hydrators/quoted_post_text_hydrator.rs(106줄 신규)로 Following 파이프라인 muted-keyword·quoted-text 하드닝. grox PTOS classifier.py에 Grok 4.6 internal 10% dial(_GROK_4_6_INTERNAL_DIAL = 0.1), prior_nsfw.py(34줄 신규) Manhattan lookup으로 재분류 스킵. visibility-filtering/dark_traffic_setup.rs(109줄 신규)로 env-gated shadow deployment(xai-vf-shadow) 미러링. enable_stale_post·enable_is_author_followed_by_viewer·enable_is_author_following_viewer·enable_engagement_counts train-default ON 승격 |
| 4세대+5 | 같은 레포 @ d0cef2f |
2026-08-20 | Rust/Python | +479/−200 (파일 14). home-mixer/candidate_hydrators/ai_trend_feedback_context_hydrator.rs(157줄 신규) + post_marshaller.rs +29줄로 AI trend feedback context 채널 신설 — For You standalone original post에 top-2 trend를 붙여 URT ContextType::TOPIC으로 렌더(랜딩 URL https://x.com/i/trending/{trend_id} 포함, topic feedback 없을 때만 폴백으로 진입). phoenix/crates/serving/xai-recsys-engine/src/emb_table.rs(+189/−169) load_tensor를 pyo3-free core(load_tensor_into) + Python wrapper로 분리, tokio runtime unwrap() → map_err, checkpoint path too short 방어. PostCandidate에 served_slate_context 필드 + From<xai_recsys_proto::SlateContext> 변환 impl(sid_k_l1/l2/l3, sid_gap_l1/l2/l3) 배선, PhoenixScorer가 예측 응답에서 candidate_slate_context()를 뽑아 세팅, RankingScorer가 새 게이트 UseServedSlateContext로 로컬 계산·캐시 대신 서빙 산출을 우선 사용(세 갈래 폴백). Grok 4.6 internal dial _GROK_4_6_INTERNAL_DIAL = 0.1 → 0.3 (하루 만에 3배). grox/libs/grok_sampler/llm.py(+27/−13) stop_predicate callback + async with aclosing로 스트리밍 조기 종료 + llm.sample.early_stop.count 카운터. grox/core/data_loaders/data_types.py·post_mapper.py에 profile_image 필드 신설 |
| 4세대+6 | 같은 레포 @ 28e414f |
2026-08-21 | Rust/Python | +856/−152 (파일 35). Phoenix proto ActionName 171–190에 광고 conversion 20 액션 신설 — MACT(모바일앱 컨버전 트래킹) 6종 인앱 이벤트(purchase·add_to_cart·level_achieved·tutorial_complete·sign_up·custom) × click/view = 12개 + view-through conversion 8개(웹 컨버전). constants.py에 MACT_IN_APP_LOSS_ACTION_INDICES·VIEW_THROUGH_ACTION_INDICES·SOURCE_SPLIT_CONVERSION_HEAD_INDICES 3개 리스트 + 새 metric group ads_slim(3 긍정 신호 + 4 부정 신호 + non-primary conversion click). NEGATIVE_FEEDBACK_HEAD_INDICES에 CLIENT_TWEET_SEARCH_QUERY_REFORMULATED 추가. models/recsys_model.py(+99/−1)에 split_head_training_by_source config + sample_source batch 필드(is_delayed_feedback 컬럼에서 유입) — fresh 샘플은 engagement head만·delayed 샘플은 conversion head만 학습(loss mask 갈림), fresh/delayed_clicked/delayed_non_clicked 메트릭 슬라이스, mact_in_app_loss_weight·train_view_through_heads·conversion_keep_mask 튜닝 노브. TRAINING.md·README.md 재작성 — flagship ranking config + home_direct_packed_nano가 프로덕션 Muon 레시피로 end-to-end 학습(nano조차 GB300 오버라이드 상속), 임베딩 rowwise AdaGrad에 accumulator half-life decay + lazy per-row decay + decoupled weight decay 세 옵션 포함. _GB300_OVERRIDES 신설 — bs_per_device=512·ep=64·attn_impl="cutedsl_ranker_varlen_attn"·remat_policy=RematType.SAVE_GB300_RECSYS·unroll_layer_stack=True·LR 5e-4·checkpoint_every_n=300 + Muon config. phoenix/crates/storage/xai-o2/(154줄 신규) — BaseO2Client trait + 15 builder method 인터페이스 공개, 다만 build()가 오픈소스 빌드에서 항상 "the xai-o2 backend is not included in this build; use the default object_store backend" 에러 반환(구현 미공개). Proto NextActionDistribution에 SlateContext slateContext = 9 필드 추가(action distribution마다 slate context). grox/flows/reply_spam/task_filter.py follower 임계 60k → 80k(4단계 중 1.33배). visibility-filtering/dark_traffic_setup.rs shadow → staging 전환 — xai-vf-shadow.prod.visibility → xai-vf-service.staging.visibility:grpc, TLS 도메인 .prod. → .staging.. grox/flows/ptos/classifier.py Grok 4.5 internal 완전 제거(dial 0.3 → 100%, _eapi_4_5_internal_breaker·_sample_4_5_internal·_GROK_4_6_INTERNAL_DIAL 삭제). phoenix/xrex/train/trainer_recsys.py에 _forward_chunked(retrieval post-embedding 65k row 청킹). phoenix/xrex/inference/model_runner.py·launch_inference.py에 --hotswap_malloc_trim CLI + _glibc_malloc_trim()(도움말: "glibc slots otherwise ratchet ~196 MiB/cycle. No-op under jemalloc"). phoenix/xrex/data/parquet_recsys.py·kafkaloader.py에 conversion_keep_mask·sample_source 패딩·exclude_required_columns 추가. xrecsys_two_tower.py에 qk_norm=True·attn_logit_cap=-1·right_anchored_rope=True 3옵션. EVERGREEN retrieval dataset 파일이 evergreen_video_1825day → video_4to14day로 축소(이름과 실체 어긋남, 임시적일 가능성). request_metrics.rs deadline_shed·inflight_cap 이중 카운트 픽스. checkpoint_cloud.py·metadata.py에 orbax tmp-dir 커밋 안 된 checkpoint 스킵 헬퍼 |
| 4세대+8 | 같은 레포 @ 0d3cdd8 |
2026-08-25 | Rust/Python | +5,850/−586 (파일 47). abuse-enforcement-service/service-lib/src/generic_actions.rs(663줄 신규) + growthbook.rs(+126) + lib.rs(+276/−19) + rules.rs(+234) — AES generic_actions 패스스루 신설. 스코어러가 requested_actions 리스트를 얹어 보내면 AES가 하드코딩 kind allowlist(user 5종·post 2종, MAX_REQUESTED_ACTIONS_PER_MESSAGE=16)와 GrowthBook 동적 allowlist(kinds·suspend_policies·labels)로 이중 검증 후 실행, 거부된 요청은 outcome.info["requested_actions_skipped"]에 JSON으로 관측성 유지. Decision::ActRequestedActions variant + enforcement_user.yaml의 규칙 짝(platform_row_without_requested_actions skip + act_requested_actions act). 새 스코어러 유입 예: panda_reports_embedding_v10_rough_spam(embedding 기반 spam 검출기 v10, 임시 PlatformManipulation suspend). home-mixer/scorers/vm_ranker.rs(+11/−128) — VMRanker 경로 대폭 단순화: AUTHOR_DIVERSITY_VALUE_MODEL_ID·MPN 폴드백 로직·AuthorColdStart 후처리 모두 삭제, 새 상수는 DPP_VALUE_MODEL_ID만. 이제 VMRanker는 rank server 반환 점수를 그대로 통과. ranking_scorer.rs(+28/−201) — effective_head_weights 메서드 88줄 삭제(client-side head weights 생성이 사라짐, 서버 측 자체 로직으로 이동). home-mixer/candidate_hydrators/following_blocked_by_hydrator.rs(65줄 신규) + filters/author_socialgraph_filter.rs 재배선 + candidate_pipeline/reverse_chron_posts_pipeline.rs(+27/−2) — Following 파이프라인 블록 관계 확장: 뷰어→저자 방향 blocked/muted 외에 (a) 저자가 뷰어를 블록, (b) quoted 저자가 뷰어를 블록, (c) 뷰어가 quoted 저자를 블록, (d) 뷰어가 retweeted 저자를 블록 — 여섯 갈래로 필터링. SocialGraphClient가 batch로 check_blocked_by. home-mixer/filters/brazil_2026_election_filter.rs(+3,379/−5, 파일 전체 4,947줄) — Brazil2026ElectionFilter 계정 리스트 갱신(TSE dadosabertos 2026-08-25 판 반영), README Notable Updates에도 "(Account list updated August 25, 2026.)" 명시. user_id는 obfuscated로 유지하고 @username은 그대로 노출(투명성/프라이버시 절충). phoenix-rankall/src/store/base.rs(+202/−61) + config/mod.rs(+51/−12) + tests/integration_test.rs(+92) — rankall prefloor 스냅샷 배선. min_age 있는 window에 대해 prefloor_<window>.parquet 동시 로드, PREFLOOR_SLACK_SECS = 6.0 * 3600.0(6시간). 신규 후보가 min_age 문턱 통과 전에 별도 pool에서 유지되다 통과 즉시 프로덕션 반영. phoenix/crates/serving/xai-recsys-engine/src/copy_port_client.rs(+155/−0) — tokio::spawn 하드닝. join_all(futures) → join_all(futures.map(tokio::task::spawn))으로 rate limit이 순차 폴링 없이도 in-flight cap을 정확히 지키게. 회귀 테스트 2개(rate_limit_caps_in_flight_despite_spawn, rate_limit_paces_between_spawned_batches). README Latest Updates → Notable Updates 리네이밍. URT 마셜링 층(ad_marshaller +18, client_event +27, wtf_marshaller +14, reverse_chron_following +12)에 소소한 확장. grox upa/constants.py(+2)·generators.py(+11) 새 배선(내용 미확인). engagement_counts_hydrator +16 |
| 4세대+7 | 같은 레포 @ d011592 |
2026-08-24 | Rust/Python | +1,428/−121 (파일 19). visibility-filtering/reference_compare.rs(812줄 신규) — Strato 기반 레퍼런스 VF(StratoVfClient)를 매 요청 병렬 호출해 verdict를 엄격 비교(action + reason 완전 일치), 다르면 JSON 라인(12KiB 예산)으로만 로그, 메트릭 6종(vf_reference_compared/exact_match/differed/error/skipped/enabled). VF_DUAL_CALL_HARNESS_ENABLED + APP_ENV 게이트, APP_ENV=prod면 부팅 시 panic으로 스테이징 전용 강제. dark_traffic과 별개로 실제 verdict 대조 canary가 추가된 것. home-mixer/models/brand_safety.rs (+20/−13) — BrandSafetyVerdict::HighRisk = 4 신설, 기존 medium에서 5종(NSFW_HIGH_PRECISION·NSFW_HIGH_RECALL·GORE_AND_VIOLENCE_HIGH_PRECISION·PDNA·EGREGIOUS_NSFW) → HighRisk 승격 + 신규 SOFT_NSFW도 HighRisk (v1/v2 대칭 이동), 광고 유틸 has_avoid()가 Medium/High 둘 다 취급, ads_brand_safety_vf_hydrator.rs의 NSFW ancestor 승격이 Medium → High, scored_posts_server.rs에 V2 라벨 5종(GROK_SFA_V2·GROK_NSFA_LIMITED_V2·GROK_NSFA_V2·GROK_NSFA_EXPANDED_V2·PTOS_REVIEWED)의 proto HM enum 매핑 신설. grox/flows/ptos/classifier.py (+223/−52) — SafetyPtosPolicyCrossValidator 신규 클래스, Grok 4.5가 다른 엔드포인트(EAPI_GROK_4_5_X_ALGO)로 재도입되지만 primary 아니라 judge 전용, ChildSafety·ViolentMedia·IllegalAndRegulatedBehaviors 3개 카테고리에 대해 primary verdict를 재확인 후 강등만 허용(disagreement → NoViolation 또는 lighter). 4세대+2의 성인 컨텐츠 judge와 나란히 존재. USE_REASONING_CATEGORIES = {ViolentSpeech, SuicideOrSelfHarm} + USE_THREAD_RENDERER_CATEGORIES 신설(부모 스레드까지 포함해서 렌더). phoenix/python/training/xai-checkpointing/xai_checkpointing/load.py (+178/−36) — domains(per-tensor ts.IndexDomain 슬라이스), tag(체크포인트 서브디렉토리, 기본 "orbax-ckpt"), concurrent_gb(동시 디코딩 바이트 스로틀) 인자 신설. XAI_RESTORE_NODE_SERIALIZE(기본 on)로 노드당 fcntl.flock()(/dev/shm/xai_restore_node_lock) restore 직렬화, 배치 사이 gc.collect() + malloc_trim(0). grox/flows/reply_spam/strato_loader.py(49줄 신규) ReplyRankingScoreStratoLoader가 reply ranking 점수를 Strato put + score ≤ 1.0이면 지역 캐시(Atla, Pdxa) 팬아웃 + Kafka v2 emit. grox/flows/reply_spam/task_filter.py follower 임계 80k → 100k(11일간 5단계: 15k→30k→60k→80k→100k). grox/core/data_loaders/data_types.py + post_mapper.py + lm/post.py — SpaceMetadata 클래스 신설(현재 title만), Post에 space_metadata 필드, 렌더러가 오디오 스페이스 카드를 LLM 입력에 포함. ads_injection_logging_side_effect.rs가 EnableAdsBrandSafetyVerdictV2 experiment 버킷을 ddg_experiment_bucket으로 로깅 노출 |
[확인] git 로그 직접 확인, 2026-08-23 — xai-org/x-algorithm 커밋 11개(전일 대비 +1: 28e414f), twitter/the-algorithm 31 commits(변화 없음)
네 가지 사실이 특히 중요하다.
- 1세대와 2세대 사이에 26개월 공백이 있다. 2023-07-07 이후 2025-09-03까지 커밋이 하나도 없다.
[확인] - 2세대는 아무것도 지우지 않았다. 삭제 0건, 리네임 0건. 2023 파일 집합(6,906개)이 2025 파일 집합(7,667개)의 진부분집합이다. 즉
cr-mixer/,navi/,ann/,simclusters-ann/,src/,product-mixer/등은 2023-04 이후 단 한 바이트도 안 바뀐 채 그대로 남아 있다. 2025 커밋이 건드린 top-level 디렉토리는home-mixer/(603) +tweet-mixer/(384) +README.md(1), 그게 전부다.[확인]—git show --name-only --pretty='' c54bec0 | awk -F/ '{print $1}' | sort | uniq -c→ 함정: 레포에 파일이 있다고 현역이라는 뜻이 아니다. 폐기는 삭제가 아니라 README에서 줄을 빼는 방식으로만 드러난다. cr-mixer가 정확히 그랬다 — 2025 커밋의 유일한 문서 변경이 cr-mixer 행을 tweet-mixer 행으로 문구 그대로 두고 서비스명만 바꾼 것이다.[확인]—git show c54bec0 -- README.md - 3세대는 별개 레포다.
xai-org/x-algorithm초기 3커밋(aaa167b→e414c17→0bfc279)이 코드 재작성 +grox/추가로 216파일까지 온 상태였다.[확인] - 4세대는 3세대의 성격을 바꿨다. 3세대까지가 "로직의 형태만 공개, 값·배선·안전규칙 미공개"였다면 4세대는
home-mixer/params/param.rs로 가중치·상수 프로덕션 크론 미러 공개,visibility-filtering/+ labeling 서브레포 15개로 안전 파이프라인 통째 공개,phoenix/에 학습 코드+합성 데이터로 end-to-end 실행 가능성 확보로 성격이 바뀐다.[확인]— README.md#latest-update--august-13th-2026, 상세 분석은 daily/2026-08-15.md 참조
피드 지면
- For You — 이 문서의 주 대상. 알고리즘 추천. gRPC
get_for_you_feed/get_for_you_feed_urt.[확인]2026 —home-mixer/server.rs:273-346 - Following — 인네트워크만. 별도 지면이 아니라 같은 파이프라인의
in_network_only플래그로 구현된다. Phoenix에 들어가는product_surface도 이 플래그로HomeTimelineRankedFollowing/HomeTimelineRanking이 갈린다.[확인]2026 —home-mixer/server.rs:75-76,home-mixer/scorers/phoenix_scorer.rs:73-77.- 4세대+3 (2026-08-18)에서 reverse-chron(Following) 전용 VF hydrator가 분기됐다
[확인]—home-mixer/candidate_hydrators/vf_following_candidate_hydrator.rs(신규 95줄),home-mixer/candidate_pipeline/reverse_chron_posts_pipeline.rs:141-144. 이전엔 For You와 Following이 같은VFCandidateHydrator를 썼다. 새 hydrator는 (a) Following 파이프라인 전용 배선, (b)should_drop_ancillary헬퍼는 기존 파일에서pub(crate)로 재사용, (c) VF 조회 결과(visibility_reason+drop_ancillary_posts)만 반환하고 나머지 후보 필드는..Default::default()로 재설정. 즉 Following 파이프라인은 하이드레이션 산출이 VF 결과 두 개로 축소되고 나머지 필드는 다른 하이드레이터가 채우는 구조로 분리됐다. VF의SafetyLevel은TimelineHome으로 그대로 (Following과 For You가 안전 레벨은 공유). 의미: For You와 Following의 하이드레이션 필드 세트가 이제 명시적으로 갈렸다 — Following에서 안 쓰는 후보 필드에 대해 로직/리소스를 안 태우려는 최적화 방향[추정]
- 4세대+3 (2026-08-18)에서 reverse-chron(Following) 전용 VF hydrator가 분기됐다
- 토픽 피드 —
topic_ids가 붙은 요청. 7개 이상이면(> 6) "bulk topic request"로 취급해 후보 소스가 달라진다.[확인]2026 —home-mixer/models/query.rs:201-203 - 비디오 지면 — Thunder에 비디오 전용 ring buffer와
is_video_request경로가 완전히 구현돼 있는데 공개된 유일한 호출자가is_video_request: false로 하드코딩한다.[추정]공개 안 된 별도 지면(Reels 상당)이 이 플래그를 켜서 쓴다 — 기계가 다 만들어져 있고 stub이 아니기 때문.[확인](코드) —thunder/thunder_service.rs:287,home-mixer/sources/thunder_source.rs
중요: 유저가 allow_for_you_recommendations = false면 서버가 요청을 통째로 in_network_only로 강등한다. [확인] 2026 — home-mixer/server.rs:75-76
후보 생성 (retrieval)
현행 (2026-08 4세대)
내부 Phoenix 파이프라인 소스 7개 + 외부 For You 파이프라인 소스 5개 = 12개. [확인] — home-mixer/candidate_pipeline/phoenix_candidate_pipeline.rs, for_you_candidate_pipeline.rs, 그리고 home-mixer/params/param.rs의 EnableXxxSource 기본값
| 소스 | 무엇 | 게이트 · 기본값 |
|---|---|---|
ThunderSource |
인네트워크 최신 포스트 (in-memory, 보존 2일) | EnableThunderSource=true (기본 on), ThunderMaxResults=1200 |
PhoenixSource |
Phoenix two-tower retrieval (OON) | EnablePhoenixSource=true, PhoenixMaxResults=1000 |
SimclustersSource |
SimClusters (2026-08 부활). 클러스터 유사도로 OON 후보 | EnableSimclustersSource=true |
TweetMixerSource |
레거시 OON 집계기 (2세대 tweet-mixer를 thrift로 호출) | EnableTweetMixerSource=false 기본 off, TweetMixerMaxResults=800 |
PhoenixTopicsSource |
토픽 요청용 Phoenix retrieval | 토픽 요청 |
PhoenixMOESource |
Phoenix MoE retrieval | EnablePhoenixMOESource |
CachedPostsSource |
Redis 워밍 캐시 | has_cached_posts (다른 전부의 역조건) |
ScoredPostsSource |
위 파이프라인 전체를 재귀 실행 | 항상 |
AdsSource |
광고 | EnableAdsSource && !is_preview |
WhoToFollowSource |
팔로우 추천 (최대 3명) | EnableWhoToFollowModule |
PromptsSource |
인라인/커버 프롬프트 | EnablePrompts |
PushToHomeSource |
푸시에서 온 포스트를 0번에 고정 | push_to_home_post_id.is_some() |
2023 세대에서 살아남은 retrieval은 tweet-mixer(기본 off로 미러링) + SimClusters(부활). ⚠ 테제 변경 (2026-08-13): canon이 오래 "SimClusters, TwHIN, UTEG/GraphJet, FRS, Earlybird, Lists, Communities — 이 이름들은 home-mixer/ 어디에도 안 나온다"고 못박아 왔다. 4세대 드랍이 simclusters/ 서브레포를 홈미서 OON retrieval 소스로 재도입 (EnableSimclustersSource=true 기본 on). TwHIN/UTEG/GraphJet/FRS/Earlybird/Lists/Communities는 여전히 부재. [확인] — home-mixer/params/param.rs, README.md #candidate-sources
SimClusters 코어 알고리즘 세부(SVD 파이프라인·k·인덱스 형식·업데이트 주기)는 심층 분석 필요 — simclusters/ 서브레포 파일 목록만 확인, 개별 파일 미독. → daily/2026-08-15.md 심층 분석 필요 목록 참조
Thunder — 2026에 새로 만든 인네트워크 인덱스. Earlybird 검색 인덱스를 대체한다. [추정] 역할이 같고 Earlybird 참조가 사라졌기 때문.
- 구조:
DashMap<post_id, LightPost>+ 작성자별 ring buffer 3개(원본 / 답글·리트윗 / 비디오).[확인]—thunder/posts/post_store.rs:20-53 LightPost에 텍스트도 미디어도 참여수도 안전라벨도 없다. post_id, author_id, created_at, in_reply_to_*, is_retweet, is_reply, source_*, has_video, conversation_id 뿐.[확인]—thunder/kafka/tweet_events_listener.rs:230-248- 랭킹은 의도적으로 recency 정렬 한 줄. Phoenix가 어차피 다시 매기니까.
[확인]—thunder/thunder_service.rs:334-339 - 기본 보존기간 2일.
[확인]—post_store.rs:521-526 - 과부하 시 큐잉이 아니라 즉시 거절(
try_acquire실패 →resource_exhausted).[확인]—thunder_service.rs:160-171 - 답글 노출 규칙이 코드에 박힌 제품 정책이다: 부모가 원본이면 통과. 아니면 (부모가 대화 루트에 대한 직접 답글) 그리고 (답글 대상이 내 팔로잉)일 때만 통과. 부모가 스토어에 없으면 그냥 버린다 → 2일 지난 스레드 루트가 만료되면 그 밑 답글이 통째로 안 보인다.
[확인]—post_store.rs:291-315 - 자기 자신의 리트윗은 hot path 한 줄로 차단.
[확인]—post_store.rs:287-289
후보 배분 — 비율이 아니라 소스별 상한
"인네트워크 50% / 아웃오브네트워크 50%"는 할당량이 아니다.
2026 파이프라인에는 allocator도, ratio 파라미터도, 전역 상한도 없다. 소스들을 join_all로 병렬 실행해 결과를 그냥 이어붙인다. 에러 난 소스는 조용히 사라진다. [확인] — candidate-pipeline/candidate_pipeline.rs:257-272
각 소스가 자기 max_results를 FeatureSwitch 파라미터에서 읽어오는데, 4세대 드랍(2026-08-13)에서 값이 프로덕션 크론 미러로 공개됐다 [확인] — home-mixer/params/param.rs:
ThunderMaxResults = 1200PhoenixMaxResults = 1000TweetMixerMaxResults = 800(단EnableTweetMixerSource = false기본 off)PhoenixMOEMaxResults— 해당 param 확인 필요
인네트워크/OON 레버는 이제 retrieval이 아니라 스코어링의 배수다. [확인] — home-mixer/scorers/ranking_scorer.rs:220-239, 272-275
let final_score = match c.in_network {
Some(false) => after_diversity * effective_oon,
_ => after_diversity,
};
effective_oon은 세 갈래로 계산되고, 값이 이제 전부 공개됐다 [확인] — home-mixer/params/param.rs:247,269,275:
| param | 기본값 | 조건 |
|---|---|---|
OonWeightFactor |
0.75 | 기본 OON 배수 |
TopicOonWeightFactor |
0.5 | 토픽 요청 시 |
NewUserAgeThresholdSecs |
0 | 신규 유저 라우팅 임계 — 0초라는 것은 사실상 신규 유저 경로가 비활성 상태로 미러링돼 있다는 뜻 [추정]. NEW_USER_OON_WEIGHT_FACTOR param은 param.rs에 부재로 확인됨 |
EnableOonRescoreForInNetworkRepliesRetweets |
true | 인네트워크 답글·리트윗도 OON 배수 적용 |
→ 일반화 노트: candidate-allocation.md
레거시 (2025 Scala, tweet-mixer)
2025-09-03에 384개 파일로 통째로 등장. README도 .md 파일도 하나 없어서 모든 사실을 코드에서만 캐야 한다. [확인]
이 세대에서 신규로 들어온 retrieval 계열:
DeepRetrieval관련 19개 파일 (2023 스냅샷엔 0개)[확인]- SimClusters를 소비하는 새 파일 20개 (
SimclusterColdPostsCandidateSource.scala포함). SimClusters 코어 자체(src/scala/com/twitter/simclusters_v2,simclusters-ann/)는 2023 그대로. 즉 엔진은 안 고치고 소비 지점만 늘렸다.[확인]—git show --diff-filter=M c54bec0 | grep -ci simclusters= 0 - Earlybird 소비 파일 15개 신규, 인덱스 본체(
src/java/com/twitter/search)는 무변경[확인] - Hydra: 2023 cr-mixer에 thrift 클라이언트로 이미 있었고, 2025에 scorer + embedding generation service로 승격됐다. "Hydra는 2025 신규"는 틀린 말이다.
[확인]
SimClusters / TwHIN / DeepRetrieval 각각의 임베딩 생성·인덱스·조회 방식과 그 안에서 발견한 코드 결함들은 → embedding-retrieval.md
랭킹
Phoenix (2026, 현행) — 4세대 드랍 반영
Grok-1을 포팅한 트랜스포머. 유저 이력과 후보를 한 시퀀스에 넣고 한 번에 채점한다. 구조·마스크·파라미터 분포는 → sequence-transformer-ranking.md
예측 헤드 — 문서 기준 24개, 카테고리 5개로 분류 [확인] — README.md #scoring-and-ranking (2026-08-13):
| 카테고리 | 헤드 | param 심볼 (가중치) |
|---|---|---|
| Engagement (7) | favorite · reply · repost · quote · share · share via DM · share via copy link | FavoriteWeight · ReplyWeight · RetweetWeight · QuoteWeight · ShareWeight · ShareViaDmWeight · ShareViaCopyLinkWeight |
| Clicks (6) | post · profile · link · photo expand · video open · quoted post | ClickWeight · ProfileClickWeight · OpenLinkWeight · PhotoExpandWeight · VideoOpenWeight · QuotedClickWeight |
| Attention (5) | video quality view · dwell · dwell time · click dwell time · active seconds | VqvWeight · DwellWeight · ContDwellTimeWeight · ContClickDwellTimeWeight · ContActiveSecs5mResidualNormWeight |
| Author (1) | follow author | FollowAuthorWeight |
| Negative (5) | not interested · mute author · block author · report · not dwelled | NotInterestedWeight · MuteAuthorWeight · BlockAuthorWeight · ReportWeight · NotDwelledWeight |
여기에 없는 param이지만 스코어에 기여하는 것 2개: QuotedVqvWeight(인용 포스트 video quality view — README 카테고리엔 없으나 param 존재), PostUnexploredWeight(새 작성자 부스트 — 아래 조정 인자 절 참조). 총 유효 weight param은 26개.
canon이 오래 관찰한 "레포 안에서 헤드 수가 세 가지로 갈린다(공개 체크포인트 19 / 랭킹 스코어러 22 / VMRanker proto 21)"는 3세대까지의 사실이다. 4세대 README가 문서 기준으로 24로 못박고 home-mixer/params/param.rs의 weight 심볼도 25(prediction head) + 1(post_unexplored heuristic)로 정리됐다. 3세대에서 관찰됐던 candidate_pipeline/candidate.rs의 죽은 19필드 PhoenixScores 구조체가 4세대에서 정리됐는지는 심층 분석 필요. [확인](문서) / [추정](코드 정리 여부)
→ 헤드 설계 일반화: multi-task-ranking.md
최종 점수 계산 순서 [확인] — ranking_scorer.rs
- 26개 weight × P(head)의 가중합 (
negative_sum은 부호 반전해서 빼기). 상호팔로우 원본 포스트에 한해reply가중치에BidirectionalFollowReplyWeightBoost=15.0가산 (조건:!in_reply_to && !retweeted && is_mutual_follow_author) offset_score: 음수면(score + negative_sum) / total_sum * NEGATIVE_SCORES_OFFSET, 양수면score + NEGATIVE_SCORES_OFFSETnormalize_score— 여전히crate::util::score_normalizer(레포 밖)- 작성자 다양성 감쇠:
AuthorDiversityDecay=0.5,AuthorDiversityFloor=0.25,EnableAuthorDiversity=true→ k번째 등장에(1-0.25)*0.5^k + 0.25곱하기 - OON 배수:
OonWeightFactor=0.75(토픽 요청 시TopicOonWeightFactor=0.5) - 새-작성자 부스트 (아래 조정 인자 절 참조)
비디오 길이에 따라 vqv 가중치를 바꿔 끼우는 heuristic(vqv_weight, quoted_vqv_weight, MinVideoDurationMs 임계)은 여전히 crate::util이라 레포에 없다. [확인] — ranking_scorer.rs:132-144
VMRanker + DPP — 이제 값이 공개됐다. [확인] — home-mixer/params/param.rs:579-618:
| param | 기본값 | 의미 |
|---|---|---|
EnableVMRanker |
true | canon의 열린 질문 "VMRanker/DPP가 켜져 있는가"에 대한 직접 답 |
VMRankerValueModelId |
"dpp" |
Determinantal Point Process 선택 |
VMRankerDppTheta |
0.65 | DPP mixing 파라미터 |
VMRankerDppMaxSelectedRank |
150 | 슬레이트 크기 상한 |
VMRankerEnableFallback |
false | 실패 시 폴백 없음 = canon의 "fail-open 조용 스킵" 관찰 그대로 유효 |
VMRankerClusterId |
"Experiment3" |
서빙 클러스터 |
VMRankerSendHeadWeights |
false | VMRanker에 헤드별 가중치 전송 안 함 |
VMRanker 서비스 본체는 여전히 레포 밖(vm-ranker/ 디렉토리는 있으나 클라이언트 프로토·설정만). 응답이 candidate.score를 통째로 덮어쓰는 구조·gRPC 실패 시 fail-open 조용 스킵은 3세대에서 관찰한 그대로.
4세대+3 (2026-08-18)에서 VMRanker 요청에 SID(semantic ID) 필드 7개가 신규 배선됐다 [확인] — home-mixer/scorers/vm_ranker.rs:194-206:
| VMRanker request 필드 | source 필드 | 의미 |
|---|---|---|
sid_known |
s.sid_known |
이 후보의 SID가 known/valid인가 (bool) |
sid_k1 / sid_k2 / sid_k3 |
s.sid_k_l1 / sid_k_l2 / sid_k_l3 |
3-level 계층 semantic ID 각 레벨의 codeword |
sid_gap1 / sid_gap2 / sid_gap3 |
s.sid_gap_l1 / sid_gap_l2 / sid_gap_l3 |
각 레벨 코드북에서의 이웃 gap(신뢰도/희소성 대리 지표 [추정]) |
- 기존 필드(
k,pool_rank,pool_rank_gap)와 나란히 후보 소스별로 전달돼 VMRanker(레거시 이름은 유지하지만 이제 DPP 슬레이트 재정렬을 담당)가 아이템 다양성 판정에서 collaborative pool rank뿐 아니라 semantic ID 계층 위치를 볼 수 있게 됐다. Kuaishou HD-Rec/PushDualGen에서 관찰된 SID 계열의 X 대응물 배선[추정] - 의미: VMRanker에서 다양성 판단이 이제 (a) 후보 소스별 rank, (b) 3-level semantic ID codeword, (c) 이웃 gap의 3축 정보를 갖는다 — 3레벨 코드북 계층(coarse → fine)이 있다는 사실 자체가 새로 확인된 아키텍처 정보. Phoenix retrieval의 SID window(
video_14day·video_48h등, 4세대+1 절 참조)와 같은 SID 인프라의 rank/rerank 쪽 소비자 - 미공개: SID 코드북 정의(각 level의 vocabulary 크기·훈련 방식),
sid_gap의 정확한 계산식, VMRanker 응답 로직에서 이 필드들이 어떻게 활용되는지
새-작성자 부스트 (New-Author Boost) — 4세대에서 문서화된 세 번째 조정 인자
새 README가 스코어링 조정 인자를 세 개로 명시한다: (1) Author Diversity Decay (2) Out-of-Network Discount (3) New-Author Boost. [확인] — README.md #scoring-and-ranking
"New-Author Boost: posts from authors whose impressions are below a threshold are lifted toward a target position."
param 정의 [확인] — home-mixer/params/param.rs:351-374, #coldstart-threshold:
| param | 기본값 | 의미 |
|---|---|---|
PostUnexploredWeight |
0.02 | 새 작성자 부스트 가산값 |
PostUnexploredWeightInNetworkOnly |
true | 인네트워크에만 적용 (OON에는 안 붙음) |
EnableMultiplicativePostUnexplored |
false | 기본은 가산형, 곱셈형 비활성 |
MultiplicativePostUnexploredAlpha |
0.0 | 곱셈형 활성 시 사용될 지수 |
ColdStartImpressionThreshold |
1000 | 임프레션 1000회 미만인 작성자를 "새 작성자"로 분류 |
canon이 콜드스타트 절에서 "신규 아이템: 2026 코드에 아무 장치가 없다"고 관찰했던 것은 3세대까지의 사실이다. 4세대에서 새 작성자(계정 단위) 부스트가 문서화됐다. 여전히 개별 새 포스트(아이템 단위)에는 부스트가 없고 hash embedding 충돌 문제도 그대로. [확인]
레거시 heavy ranker (2023~2025)
멀티태스크 신경망이 참여 확률들을 예측하고 가중합으로 정렬하는 구조. 2026 Phoenix와 목적함수 형태는 같고 입력이 다르다 — 레거시는 수작업 피처를, Phoenix는 ID 임베딩을 먹는다.
2025 세대는 랭커 두 개가 나란히 돈다. [확인] — ScoredTweetsRerankingScoringPipelineConfig.scala:35-39
- Navi(프로덕션 heavy ranker) — 헤드 15개.
[확인]