- 읽은 자료 2건 (X 4세대 공개 1건
- arXiv triage 30건 중 관찰 1건)
- 정본 반영 1개 파일 (x.md 대폭 개정)
- 다이어그램 갱신 1건 (x-pipeline.svg)
- 레이더 갱신 1건
오늘 함께 본 다른 변화는 다음과 같다.
- 같은 공개에서 노출 판정 서브레포 visibility-filtering과, grox를 포함한 15개 서브시스템의 labeling 코드가 공개됐다. 규칙 일부는 빠졌다.
- SimClusters가 home-mixer(For You 피드를 조립하는 서비스) 안에, 팔로우하지 않는 계정의 포스트를 찾는 소스로 들어왔다.
- arXiv cs.IR 신규 논문 30건 가운데 영상 추천 앙상블 랭킹 논문 DrEM 1건을 레이더 관찰 항목에 올렸다.
1X가 4세대 코드에서 랭킹 가중치와 안전 판정 파이프라인을 공개했다 — X
자료 xai-org/x-algorithm @ 47c1bcd — "Open-source X Recommendation Algorithm" — xai-org 공개 저장소, 2026-08-13 17:09 UTC 커밋, 공개 소스코드. 이 노트들은 이 공개를 공개 소스 4세대라고 부른다. 뒤이어 .gitattributes를 정리한 커밋 a389166이 올라왔다. 커밋 하나로 +363,246 / −11,640 줄이 바뀌었다. 파일은 모두 300개 이상이며, GitHub API의 페이지네이션 한계 때문에 정확한 파일 수는 트리에서 재구성했다. 주요 근거 문서는 README.md #latest-update--august-13th-2026와 docs/BIDIRECTIONAL_BOOST_CHANGE.md다. 주요 코드 파일은 home-mixer/params/param.rs와 visibility-filtering/rules/registry.rs다.
배경 이 저장소의 services/x.md는 지난 3개월 동안 "공개 소스 3세대"를 정본으로 유지해 왔다. 세 세대는 아래와 같다.
- 2023 Scala 초판
- 2025 Scala 리프레시:
c54bec0, tweet-mixer 신설 - 2026 Rust 재작성:
aaa167b·e414c17·0bfc279, 총 216파일
정본에서 가장 크게 비어 있던 절은 두 개였다.
- 첫째는 가중치다. 목적함수의 형태가 가중합이라는 점은 확인됐지만, 실제 값은 세 세대 어디에도 없었다.
- 2026 Rust에서는
crate::params모듈 자체가 레포에서 빠져 있어서,FavoriteWeight같은 심볼이 호출부에만 등장하고 정의는 찾을 수 없었다. - 널리 인용되는 "reply 13.5 / good_profile_click 12.0 / report −369" 표는 2023-04-05 스냅샷 하나뿐이다. 그마저도 저자가 직접 "프로덕션과 작은 차이 있을 수 있다"고 단서를 붙여 놓은 문서였다.
- 2026 Rust에서는
- 둘째는 안전성 계열, 즉 visibility-filtering과 labeling 파이프라인이다.
- home-mixer 코드에는
VFFilter·AncillaryVFFilter가 fail-closed로 걸려 있었지만, 그 필터가 참고하는 라벨을 누가 언제 어떻게 붙이는가는 완전한 블랙박스였다. grox/(nearline 콘텐츠 분류기) 서브레포는 주석 파이프라인 골격만 부분 공개된 상태였다.- 그 밖의 계정 레벨 판단, PageRank, 인위적 행동 탐지, NSFW 미디어 분류, 규칙 엔진, 집행 서비스는 언급조차 없었다.
- home-mixer 코드에는
이번 커밋은 이 두 절의 내용을 전부 뒤집었다. 새 README는 가중치를 포함한 핵심 설정 파라미터를 추가했다는 항목으로 시작한다: "Adds key configuration parameters (including weights used to blend predicted action values into a score for a post)". 그에 맞춰 home-mixer/params/param.rs 1084줄이 새로 추가됐다. 이어지는 항목 "Adds code for systems that impact whether a post is filtered from the For You feed"와 함께 서브시스템 15개 이상이 신설됐다. Phoenix(X의 Grok 기반 트랜스포머 추천 모델)에는 학습 코드와 synthetic 데이터 생성기, QUICKSTART까지 추가되어 end-to-end로 실행할 수 있게 됐다. 새 SimClusters 서브레포는 home-mixer의 OON(out-of-network, 뷰어가 팔로우하지 않는 계정) retrieval 소스로 연결됐다.
이 노트는 이 릴리스의 성격이 "로직의 형태를 보여주는 것"에서 "값과 규칙을 검증 가능한 형태로 제시하는 것"으로 넘어왔다고 본다 추정. 이 평가는 README나 커밋 메시지("Open-source X Recommendation Algorithm" 한 줄)에 없다. 3세대 정본(이 저장소 e65f30f의 services/x.md)의 주의 목록 #1이 "공개된 것은 로직의 형태이고, 값과 배선은 빠졌다"고 적었는데, 이번 공개가 그 빠진 값을 채웠다는 것이 근거다. 여기에 짝을 이루어 x.com/i/under_the_hood라는 계정 단위 라벨 투명성 도구가 파일럿으로 공개됐다. 새 README의 주장에 따르면, 유저는 자기 계정과 포스트에 붙은 visibility 라벨을 조회할 수 있고, 그 라벨을 이 레포의 코드와 대조해 왜 그런 취급을 받았는지 확인할 수 있도록 설계됐다.
새로 알게 된 것A. 가중치는 프로덕션 기본값을 옮겨 오는 미러 파일에 실제 값으로 들어 있다
새로 공개된 가중치 파일의 숫자는 "예시"나 "데모 기본값"이 아니라, 크론이 프로덕션 primary value를 매일 밀어 넣어 만든 미러다. 정확도의 상한은 마지막 sync 시각인 2026-08-12 04:09 UTC다. 대표 값은 reply 5.0, favorite 0.5, report −234, share via copy link 20.0이다 확인.
home-mixer/params/param.rs는 코드에 명시된 프로덕션 기본값을 담고 있다. 파일 헤더의 주석이 이 파일의 성격을 정확하게 규정한다.
// mirrored from config feature-switch defaults; last sync 2026-08-12T04:09:22Z—home-mixer/params/param.rs:1
새 README의 "Experiments and Configuration" 절은 이 미러링의 의미를 이렇게 밝힌다.
"To help people understand the production defaults, we run cron scripts that set the defaults in this repository's code to be the primary production values, for example in
home-mixer/params/param.rs." — README.md#experiments-and-configuration
양수 쪽 *Weight param은 21개이고, 아래 표는 여기에 상호팔로우 boost 2개를 더해 파일에 등장하는 순서대로 적는다 확인(출처는 위 param.rs 링크).
| 헤드 | param 심볼 | 기본값 | 비고 |
|---|---|---|---|
| favorite | FavoriteWeight |
0.5 | 2023-04-05 스냅샷의 0.5와 일치 |
| reply | ReplyWeight |
5.0 | 2023 스냅샷의 13.5와 다름 |
| ↳ +상호팔로우 원본 boost | BidirectionalFollowReplyWeightBoost |
15.0 | 2026-07-13 도입 20 → 2026-07-24 15로 하향 (아래 사례 참조) |
| retweet | RetweetWeight |
1.0 | 2023 스냅샷과 일치 |
| photo_expand | PhotoExpandWeight |
0.05 | |
| video_open | VideoOpenWeight |
0.05 | |
| click (포스트) | ClickWeight |
0.4 | 2023 good_click 11·good_click_v2 10과 스케일이 다름. 별개의 헤드일 가능성 |
| open_link | OpenLinkWeight |
0.2 | |
| profile_click | ProfileClickWeight |
0.0 | 2023 스냅샷 good_profile_click 12에서 완전 제거 |
| video quality view (vqv) | VqvWeight |
0.05 | |
| share | ShareWeight |
2.0 | |
| share via DM | ShareViaDmWeight |
5.0 | |
| share via copy link | ShareViaCopyLinkWeight |
20.0 | 최고 양수 개별 헤드 |
| dwell | DwellWeight |
0.0 | 실제 dwell 신호는 아래 연속형 항목에 있음 |
| ↳ +상호팔로우 원본 boost | BidirectionalFollowDwellWeightBoost |
0.0 | 코드는 있으나 미배포 |
| quote | QuoteWeight |
5.0 | |
| quoted_click | QuotedClickWeight |
0.05 | |
| quoted_vqv | QuotedVqvWeight |
0.0 | |
| follow_author | FollowAuthorWeight |
4.0 | |
| post_unexplored | PostUnexploredWeight |
0.02 | 새-작성자 부스트, 아래 참조. PostUnexploredWeightInNetworkOnly = true |
| 연속형 dwell time | ContDwellTimeWeight |
0.004 | |
| 연속형 click dwell time | ContClickDwellTimeWeight |
0.0 | |
| 연속형 active_secs 5분 residual | ContActiveSecs5mResidualNormWeight |
0.0 | 새 README "Attention" 카테고리 |
부정 헤드 가중치는 5개다 확인.
| 헤드 | param 심볼 | 기본값 | 2023 스냅샷 대응 |
|---|---|---|---|
| not_interested | NotInterestedWeight |
−43.2 | 대응 없음 (당시 없던 헤드) |
| block_author | BlockAuthorWeight |
−31.2 | 대응 없음 |
| mute_author | MuteAuthorWeight |
−58.8 | 대응 없음 |
| report | ReportWeight |
−234.0 | 2023 report −369 → 완화 방향 |
| not_dwelled | NotDwelledWeight |
−0.02 | 대응 없음 (정본이 유일하게 확인했던 새 부정 헤드) |
가중치는 행동이 랭킹에서 갖는 가치와, 그 행동이 네트워크에서 보통 일어나는 빈도(propensity)를 함께 반영한다 확인. 가중치 블록 바로 위의 주석 세 줄이 이렇게 쓰고, 두 요소를 어떻게 합치는지 식은 적지 않는다.
"These weights reflect a combination of how much an action is valued in ranking and typical propensities of these actions across the X network (e.g. negative feedback is overall rare)." —
home-mixer/params/param.rs:279-281
이 노트는 report −234의 크기를 "리포트 한 번의 상대 중요도"가 아니라 가치 × 1/propensity의 곱으로 읽는다 추정. 리포트가 워낙 드물어서 절대값이 크게 붙었다고 보는 근거는 주석의 "negative feedback is overall rare"다.
새로 알게 된 것B. OON 배수와 다양성, VMRanker 상수도 모두 공개됐다
정본이 오랫동안 "네 값 전부 비공개"라고 기록해 왔던 OON 배수와 다양성, VMRanker(피드에 내보낼 후보 묶음을 다시 정렬하는 원격 서비스) 상수가 전부 공개됐다.
- OON 포스트에 곱하는 감쇠 계수는 2023-04-05 스냅샷의 값과 같다 확인.
OonWeightFactor = 0.75이고, 스냅샷의out_of_network_scale_factor도 0.75다.
- 토픽 요청일 때에는 OON 감쇠를 더 엄격하게 적용한다 확인.
TopicOonWeightFactor = 0.5
- 신규 유저 라우팅 임계는 0초다 확인. 임계가 0초라는 것은 사실상 이 코드 경로가 비활성 상태로 미러링돼 있다는 뜻이다 추정.
NewUserAgeThresholdSecs = 0
- 작성자 다양성 감쇠는 켜져 있고, 감쇠율과 하한 값이 공개됐다 확인.
AuthorDiversityDecay = 0.5,AuthorDiversityFloor = 0.25,EnableAuthorDiversity = true- 같은 작성자의 2번째 포스트에는
(1−0.25)·0.5¹+0.25=0.625배가 곱해지고, k번째 포스트에는 (1−0.25)·0.5ᵏ⁻¹+0.25 배가 곱해진다. - 코드의 지수는 같은 작성자의 앞선 포스트 수이고, 첫 포스트는 0이다 확인 —
home-mixer/scorers/ranking_scorer.rs:614-665.
- VMRanker는 켜져 있고, DPP(서로 비슷한 후보가 함께 뽑히지 않게 하는 선택 기법)를 사용하며, 폴백은 없다 확인. 따라서 실패했을 때 fail-open으로 조용히 건너뛴다는 정본의 관찰이 그대로 유효하다.
- 정본이 남긴 열린 질문 "VMRanker/DPP가 켜져 있는가"에 대한 직접적인 답이다.
VMRankerDppTheta = 0.65,VMRankerDppMaxSelectedRank = 150,EnableVMRanker = trueVMRankerValueModelId = "dpp",VMRankerClusterId = "Experiment3",VMRankerEnableFallback = false
- 레거시 tweet-mixer는 기본 off로 미러링됐고, SimClusters가 그 자리를 대체한다 확인.
- 소스별 최대 결과 수:
PhoenixMaxResults = 1000,ThunderMaxResults = 1200,TweetMixerMaxResults = 800 - 소스 스위치:
EnableTweetMixerSource = false,EnableSimclustersSource = true,EnablePhoenixSource = true
- 소스별 최대 결과 수:
- 새 Phoenix 클러스터에는 shadow 트래픽 30%가 기본으로 흐른다 확인.
ShadowTrafficDefaultPercent = 0.3
- 정본이 "신규 아이템에 아무 장치 없다"고 기록했던 지점은 실제로는 임프레션 임계로 정의되어 있다 확인.
ColdStartImpressionThreshold = 1000- 임프레션이 1000회 미만이면 "새 작성자·포스트"로 분류하고, 아래 C의
PostUnexploredWeight로 부스트한다.
새로 알게 된 것C. 점수 조정 인자는 세 개이고, 정본에 없던 세 번째가 새-작성자 부스트다
새 README가 스코어링 조정 인자를 세 개로 명시한다 확인. 세 번째인 새-작성자 부스트(New-Author Boost)는 임프레션이 임계보다 적은 작성자의 포스트를 목표 위치 쪽으로 끌어올린다 확인. 세 인자는 README.md #scoring-and-ranking 절에 이렇게 적혀 있다.
"Author Diversity ... Out-of-Network Discount ... New-Author Boost: posts from authors whose impressions are below a threshold are lifted toward a target position." — README.md
#scoring-and-ranking
정본은 조정 인자를 두 개로만 기록해 왔다.
- 작성자 다양성 감쇠
- OON 배수
여기에 세 번째로 새-작성자 부스트가 있다.
- 기본값은 가산형 부스트이고, 곱셈형은 비활성이며, 인네트워크에만 적용된다 확인.
- param.rs의 정의:
PostUnexploredWeight = 0.02·PostUnexploredWeightInNetworkOnly = true EnableMultiplicativePostUnexplored = false·MultiplicativePostUnexploredAlpha = 0.0ColdStartImpressionThreshold = 1000
- param.rs의 정의:
새로 알게 된 것D. SimClusters가 팔로우하지 않는 계정의 포스트를 찾는 후보 소스로 돌아왔다
후보 소스가 아래 넷으로 재편됐다.
- Thunder(팔로우한 계정의 최근 포스트를 메모리에 두는 인네트워크 소스)
- Phoenix retrieval
- SimClusters
- 기본 off로 설정된 레거시 tweet-mixer
정본은 오랫동안 "SimClusters, TwHIN, UTEG/GraphJet, FRS, Earlybird, Lists, Communities — 이 이름들은 home-mixer/ 어디에도 안 나온다"고 기록해 왔는데, 이 가운데 SimClusters가 뒤집혔다. 새 README는 후보 소스를 이렇게 서술한다.
"In-Network
thunder/keeps recent posts from the accounts a viewer follows in memory · Out-of-Networkphoenix/retrieval andsimclusters/find posts from accounts the viewer does not follow" — README.md#overview
README의 이 서술은 SimClusters 서브레포가 새로 생겼고, simclusters/의 코어 알고리즘(2020 KDD)이 여기 들어와 있다는 뜻이다. 그 코어는 SVD가 아니라 Metropolis-Hastings 기반 Sparse Binary Factorization으로 KnownFor 커뮤니티를 찾는 방식이다 확인 — UpdateKnownForSBFRunner.scala:5-9.
- 이 파일은
com.twitter.sbf.core.MHAlgorithm과SparseBinaryMatrix를 import한다 확인. topics/embedding-retrieval.md도 같은 단계를 Metropolis-Hastings 커뮤니티 탐지로 적는다.
세부 내용은 simclusters/ 전체를 심층 분석해야 확인할 수 있다.
새로 알게 된 것E. 필터가 늘었고, 정본이 놓친 필터도 하나 있었다
필터는 14개에서 17개로 늘었다 확인 — README.md #filtering. 새로 추가된 필터는 3개이고, 여기에 정본이 놓쳤던 필터를 하나 더 적는다.
OONRetweetReplyFilter는 팔로우하지 않는 계정의 리트윗과 답글, 그리고 부모 포스트가 없는 답글을 걸러낸다. 기존RetweetDeduplicationFilter와는 별개다 확인(README).OONNsfwSimclustersFilter는 SimClusters 소스에서 나온 성인 콘텐츠 계정의 포스트를, 팔로우하지 않는 유저에게는 드롭한다. SimClusters 도입에 맞춰 신설된 필터다 확인(README).NewUserMinEngagementFilter는 신규 유저에게 노출되는 OON 포스트 가운데 참여 임계에 미달하는 것을 제거한다 확인(README).- 관련 param은
NewUserMinEngagementThreshold,NewUserMinEngagementFilterMetric,NewUserMinEngagementFilterUseRatio,NewUserMinEngagementFilterMaxAccountAgeSecs,NewUserMinEngagementFilterMaxResurrectionAgeSecs이다.
- 관련 param은
InventoryHoldoutFilter는 유저×포스트를 결정론적으로 해싱해, 설정된 비율만큼 인벤토리를 홀드아웃한다(노출 대상에서 떼어 둔다). 정본이 놓쳐 기재하지 않았던 필터다 확인(README).
정본이 기록한 BackupFilter의 no-op 동작, TopicIdsFilter의 하드코딩된 supertopic 같은 관찰은 그대로 유효하다.
새로 알게 된 것F. 문서상 예측 헤드는 24개다
새 README가 헤드를 카테고리 5개, 총 24개로 재배치했다 확인 — README.md #scoring-and-ranking.
- Engagement (7): favorite · reply · repost · quote · share · share via DM · share via copy link
- Clicks (6): post · profile · link · photo expand · video open · quoted post
- Attention (5): video quality view · dwell · dwell time · click dwell time · active seconds
- Author (1): follow author
- Negative (5): not interested · mute author · block author · report · not dwelled
정본은 헤드 개수가 세 갈래로 갈린다고 기록해 왔다. 공개 체크포인트가 19개, Rust 스코어러가 22개, VMRanker proto가 21개다. 새 README는 문서상 24개를 명시한다. param.rs의 *Weight param은 26개(양수 21, 부정 5)이고, README 목록에 없는 둘을 빼면 24개와 맞는다 확인. 빠지는 둘은 헤드 예측값이 아닌 heuristic weight PostUnexploredWeight와, README에 이름이 없는 QuotedVqvWeight다 확인. 소스 코드상의 실제 개수는 새 phoenix 학습 코드를 심층 분석해야 확정할 수 있다.
새로 알게 된 것G. 노출 판정 규칙은 팔로잉 포스트에 28개, 추천 포스트에 54개가 적용된다
visibility-filtering 서브레포의 규칙 파일이 정책 세 개를 정의한다 확인.
FilterAll은 모든 것을 드롭한다 확인.TimelineHome은 팔로잉 대상에 적용하는 기본 규칙이다 확인.TimelineHomeRecommendations는 추천 대상에 적용되며, 기본 규칙에 OON 전용 드롭을 더한다 확인.- 규칙 파일은
visibility-filtering/rules/registry.rs이고, 912줄이다 확인.
팔로잉과 추천에 공통으로 적용되는 규칙은 28개다 확인. base_home_rules()에 있는 이 규칙은 아래 순서로 이어진다.
- 계정 상태:
SUSPENDED_AUTHOR_DROP,DEACTIVATED_AUTHOR_DROP,ERASED_AUTHOR_DROP,OFFBOARDED_AUTHOR_DROP,ProtectedAuthorDropRule - 뷰어 관계:
ViewerBlocksAuthorRule,ViewerMutesAuthorRule,MutedRetweetsRule - 트윗 라벨:
PDNA_DROP,BOUNCE_DROP,SPAM_DROP,FOR_EMERGENCY_USE_ONLY_DROP,FOSNR_HATEFUL_CONDUCT_DROP,FOSNR_VIOLENT_SPEECH_DROP,FOSNR_ABUSE_DROP,FOSNR_CIVIC_INTEGRITY_DROP - 트윗 상태:
NullcastedTweetDropRule,DropStaleTweetsRule,DropLegalTakendownPostRule,DropLocalLawsTakendownPostRule - NSFW 뷰어 게이팅:
SensitiveViewerLoggedOutDropRule,SensitiveViewerUnderageDropRule,SensitiveViewerNoStatedAgeDropRule - 배제 트윗:
DropExclusiveTweetContentRule - NSFW 인터스티셜(포스트를 피드에 둔 채 경고 화면을 씌우는 처리):
NSFW_HIGH_PRECISION_INTERSTITIAL,GORE_AND_VIOLENCE_INTERSTITIAL,NSFW_CARD_IMAGE_INTERSTITIAL,NsfwAuthorInterstitialRule
추천 포스트에는 위 28개에 OON 전용 26개를 더해 54개가 적용된다 확인. timeline_home_recommendations_policy()가 더하는 규칙은 아래 순서로 이어진다.
- DMCA·지리 제한 미디어 2개
- NSFW 계정 4개
- NSFW·폭력·DoNotAmplify·스팸 라벨이 붙은 트윗 9개
- NSFW·스팸·impersonation·deactivated·adult 관련 유저 라벨 11개
canon(정본 x.md) 필터 절의 '주목할 것' 불릿이 이미 관찰했던 "인네트워크와 OON에 다른 안전 레벨"의 실체가 여기에 있다. 팔로잉 유저에게는 28개 규칙만 적용되고, OON 추천에는 54개 규칙이 적용된다. 평가는 첫 번째 드롭 판정에서 끝나는 short-circuit 방식이고, OON 전용 규칙군은 캐치업 드롭만 내릴 수 있으며 인터스티셜이나 알로우 판정은 없다(canon의 같은 불릿과 일치한다).
canon 필터 절의 fail-closed 불릿이 가리킨 실체를 확인했다. visibility-filtering/rules/registry.rs의 정책 반환값은 Verdict 구조체이고, README는 interstitial을 UI 처리로 넘기며 drop이 실제 필터링에 해당한다고 명시한다 확인 — README.md #labeling-path.
"interstitial ──► the post stays in the feed; nothing in this repository draws the interstitial"
새로 알게 된 것H. 라벨을 붙이는 서브시스템들의 역할이 처음으로 공식 문서화됐다
새 README는 라벨이 붙는 과정을 4단계 "Labeling Path"로 정리한다. 단계는 Content Understanding → Labeling Rules → Storage → Visibility Filtering 순서다. 각 서브시스템의 역할이 처음으로 공식 문서화됐다 확인.
grox/: nearline 콘텐츠 분류기다. 정본에는 이미 부분적으로 반영돼 있다.media-model-proxy/: 이미지·비디오 모델(NSFW, 폭력/고어, 혐오 심볼, 주제 분류, 알려진 미디어 매칭)을 서빙하는 프록시다.clip/: CLIP 이미지·텍스트 임베딩 모델을 학습한다. 미디어 분류기의 입력이 된다.adult-content/: 성인 미디어 분류기를 학습하고 캘리브레이션한다.pnsfwmedia/: CLIP 임베딩과 계정 스코어를 결합한 성인 미디어 판별기다.agatha/: 오프라인 배치다. 다른 계정이 이 계정의 포스트에 어떻게 반응했는가를 기준으로 라벨을 붙인다. 블록·리포트·스팸 리포트 대비 favorite 비율을 쓴다.bdsm/: 계정의 시계열 행동 시퀀스에서 inauthentic/abusive 신호를 추출한다. Rust, proto, training, tests 서브디렉토리로 구성된다.user-cred-v2/: 팔로우와 엔게이지먼트 엣지 위에서 PageRank를 돌려 계정 신뢰도 스코어를 만든다.scarecrow/: 이벤트 반응형 규칙 러너다.botmaker/를 규칙 엔진으로 임베드한다.botmaker/: 규칙 DSL과 컴파일러, 런타임을 담는다.botmaker-rules/: scarecrow가 로드하는 실제 규칙이다. 일부는 게이밍 방지를 위해 공개하지 않았다.abuse-enforcement-service/: 모델 스코어를 근거로 계정 조치(라벨링·챌린지·서스펜션)를 결정한다.safety-label-user-agg/: 계정이 소유한 포스트가 받은 라벨을 계정 레벨로 집계한다.visibility-filtering-client/: visibility-filtering 서비스의 클라이언트 라이브러리다.under-the-hood/: 계정 단위 라벨 투명성 리포트 빌더다. 일일 배치와 서빙 층 집계로 구성된다.
이 15개 가운데 grox를 뺀 나머지 서브시스템은 오늘까지 정본에 한 줄도 반영되지 않았다.
새로 알게 된 것I. Phoenix만은 학습부터 서빙까지 실행할 수 있게 됐다
정본이 "소스 읽는 법 — 주의 목록" #1에서 관찰했던 "레포 전체가 빌드되지 않는다"는 진술이 부분적으로 해소됐다. Phoenix만은 학습과 서빙까지 end-to-end로 실행할 수 있는 형태로 배포됐다. 나머지 크레이트에는 여전히 미공개 의존이 남아 있다 확인.
- 남은 미공개 의존의 예는
xai_service_runner·xai_kafka다. - 3세대에 없던
crate::params·crate::util·crate::clients는 이번에 파일과 함께 공개됐다 확인 —home-mixer/lib.rs.lib.rs가pub mod params;,pub mod clients;,pub mod util;을 선언하고, 트리에home-mixer/params/·util/·clients/파일이 있다.
- 새 커밋에 추가된
Cargo.toml은 여러 개이며 phoenix 서브트리에 몰려 있다.
새 README의 서술은 이렇다.
"Elsewhere, code may not necessarily include build- or deployment-related files or generally self-explanatory infrastructure imports (e.g.
xai_service_runnerorxai_kafka). ...phoenix/ships a Cargo workspace, apyproject.toml, aquickstartand synthetic data generation, so a small model can be trained and served end-to-end." — README.md#deployment-related-code
새로 알게 된 것J. Phoenix retrieval 인덱스는 포스트를 넣기 전에 visibility 판정을 먼저 참조한다
Phoenix retrieval을 위한 새 인덱스 서비스도 공개됐다 확인 — README.md #retrieval-index.
phoenix-rankall/은 Phoenix retrieval이 조회하는 포스트 인덱스를 유지한다. 이벤트가 도착할 때마다 갱신된다 확인(README).phoenix-rankall-strato/는 어떤 인덱스에 포스트가 속하는지 결정하는 이벤트 층이다. 이 층은 visibility-filtering을 먼저 참조한다 확인(README).
인덱싱 파이프라인이 랭킹 쪽 visibility 규칙과 이미 sync되어 있어서, 포스트가 인덱스에 들어가기 전에 visibility 판단이 먼저 붙는다. 이것은 정본이 전혀 파악하지 못했던 아키텍처 사실이다.
새로 알게 된 것K. 위 진술을 다룰 때는 주의 사항 다섯 가지를 반드시 함께 밝혀야 한다
- 가중치는 크론이 매일 밀어 넣는 미러이므로 시차가 있다. 헤더에 적힌 sync 시각 이후에 프로덕션에서 일어난 변경은 아직 반영되지 않았을 수 있다 확인.
- 가중치의 부호와 크기를 해석할 때에는 propensity를 함께 고려해야 한다. 파일 주석(
param.rs:279-281)은 가중치가 행동의 가치와 propensity를 함께 반영한다고만 쓴다 확인. 이것을 가치 × 1/propensity로 읽는 것은 이 노트의 해석이다 추정.- 리포트 −234와 favorite 0.5의 절대값 비율(468배)이 곧바로 "리포트가 favorite보다 468배 중요하다"는 뜻은 아니다.
- 미러링 범위는
home-mixer안의 param으로 한정된다.- VMRanker 원격 서비스의 내부 상수, phoenix 학습 hyperparameter, botmaker 규칙 상수는 여전히 레포 밖에 있다 확인.
- 3세대 정본이
crate::util에 있으리라 본 score normalizer는 4세대 트리에 없고,home-mixer/util/mod.rs도 선언하지 않는다 확인. - 같은 정본이 꼽은
vqv_weight는 이번에 공개됐다 확인 —home-mixer/util/candidates_util.rs:19.
- Phoenix 학습 코드는 "학습이 가능한" 것이지 "프로덕션과 같은" 것이 아니다.
- README는 규모가 다르다는 점을 이렇게 분명히 한다: "a small model can be trained and served end-to-end".
- 실제 프로덕션 checkpoint와 데이터, infra는 공개되지 않았다.
- 일부 botmaker rules는 게이밍 방지를 위해 공개되지 않았다. README가 이를 명시한다. visibility-filtering이 참조하는 라벨 가운데 일부는 규칙이 공개되지 않은 상태라는 뜻이다 확인.
새로 알게 된 것L. 파라미터 하나를 바꾼 과정이 A/B 시작부터 하향 조정까지 문서로 공개됐다
새 문서 하나가 앞으로 파라미터 변경을 코드 diff로 어떻게 문서화할지 보여 주는 견본이다. 문서는 docs/BIDIRECTIONAL_BOOST_CHANGE.md이고, 다루는 사례는 2026-07의 양방향 팔로우 답글 부스트다.
- 2026-07-10에 A/B를 시작했다.
BidirectionalFollowReplyWeightBoost값을 5/10/15/20 중에서 무작위로 배정했고, 대다수 유저에게는 0을 적용했다. - 2026-07-13에 초기 광범위 롤아웃을 진행하면서 20으로 확대했다.
- 2026-07-24에는 X에서 받은 유저 피드백을 반영해 20에서 15로 낮췄다. 피드백은 월드컵이 진행 중인데 관련 포스트가 부족하다는 지적이었다.
문서는 이 요약을 그대로 싣는다.
"In plain language, the bidirectional follow boost boosts original posts from people you mutually follow by increasing the weight on the predicted probability that you'll reply to a post from one of those authors who you mutually follow." —
docs/BIDIRECTIONAL_BOOST_CHANGE.md
- 코드를 보면 원본 포스트에 한해서만 부스트가 붙고, 답글과 리트윗은 대상이 아니다 확인. 이 규칙은 정본에 없던 매우 구체적인 로직이다 확인.
home-mixer/candidate_hydrators/bidirectional_follow_hydrator.rs(신규): SocialGraphClient로 상호팔로우 여부를 조회해PostCandidate.is_mutual_follow_author에 설정한다.home-mixer/models/candidate.rs: 필드 하나를 추가했다.home-mixer/scorers/ranking_scorer.rs:bidirectional_boost_eligible(c)를in_reply_to_tweet_id.is_none() && retweeted_tweet_id.is_none() && is_mutual_follow_author == Some(true)로 정의하고, 조건을 만족하면 reply와 dwell 가중치에 boost를 더한다.- 조건은 순수 원본에만 적용되고, 답글과 리트윗은 제외되며, 상호팔로우가 아니면 pass-through로 통과시킨다.
정본 반영
- services/x.md를 대폭 개정했다. 주요 변경 사항은 다음과 같다.
- "공개 소스 3세대" 표에 4세대 행을 추가했다(2026-08-13, +363k/−12k 라인, 파일 300개 이상, visibility-filtering·labeling 서브레포 15개 신설,
phoenix/학습 코드 포함). - 후보 소스 표에 SimClusters를 추가하고
TweetMixer를 기본 off로 표시했으며,EnableSimclustersSource=true·EnablePhoenixSource=true값을 삽입했다. - 후보 배분 절을 갱신했다.
TweetMixerMaxResults=800,PhoenixMaxResults=1000,ThunderMaxResults=1200값과OonWeightFactor=0.75,TopicOonWeightFactor=0.5값을 삽입했다. 정본의 "네 값 전부 비공개"는 "세 값 공개(신규 유저용 하나는 임계가 0이라 사실상 비활성)"로 다시 썼다. - 랭킹 절에서는 Phoenix 예측 헤드 표를 새 README의 24개 카테고리 배치로 재작성하고, param.rs의
*Weightparam 26개(양수 21, 부정 5)와 대응시켰다. - 가중치 절을 전면 재작성했다. "결론: 값 미공개"를 "결론: 2026-08-13 이후 프로덕션 미러 공개"로 뒤집었다. 상세 표(favorite 0.5, reply 5.0, +상호팔로우 원본 15.0, retweet 1.0, ..., report −234)를 삽입했고, 2023 스냅샷과 세부를 대비하는 절을 추가했다.
- VMRanker 절에는
EnableVMRanker=true,VMRankerDppTheta=0.65,VMRankerDppMaxSelectedRank=150,VMRankerValueModelId="dpp"값을 삽입했다. 열린 질문 "VMRanker/DPP가 켜져 있는가"는 해소 항목으로 옮겼다. - 필터 절을 14개에서 17개로 갱신했다.
OONRetweetReplyFilter,OONNsfwSimclustersFilter,NewUserMinEngagementFilter,InventoryHoldoutFilter항목을 새로 추가했다. - 새-작성자 부스트 서브절을 신설했다. Author Diversity Decay와 OON Discount에 이은 세 번째 조정 인자다.
- visibility-filtering / labeling 파이프라인 절을 신설했다. 규칙 개수는 base 28 + OON 추가 26 = 54, 서브레포 표에는 아래 이름을 담았다.
agatha·bdsm·user-cred-v2·pnsfwmedia·scarecrow·botmaker·abuse-enforcement-service·safety-label-user-agg·under-the-hood·clip·media-model-proxy
- Phoenix 학습·인덱스 절을 신설했다. Cargo workspace와 pyproject.toml, QUICKSTART, synthetic data, phoenix-rankall / phoenix-rankall-strato를 담았다. 인덱싱이 visibility 판단을 먼저 참조한다는 아키텍처 사실을 함께 담았다.
docs/BIDIRECTIONAL_BOOST_CHANGE.md사례를 "가중치가 어떻게 바뀌는가" 서브절로 반영했다(2026-07-10 A/B → 07-13 롤아웃 → 07-24 20→15).- "소스 읽는 법 — 주의 목록"의 canon 주의 항목 #1(레포가 빌드되지 않는다)이 절반 해소됐다. Phoenix는 이제 빌드된다.
- 열린 질문을 대량으로 해소했다: 가중치 실제 값, VMRanker on/off,
has_cached_posts비중(여전히 미해소), Phoenix 헤드 개수(24개로 확정), SimClusters 부활 여부(부활로 확인). - 새 열린 질문을 추가했다.
- SimClusters 서브레포의 코어 알고리즘 세부(SVD 파이프라인과 k)
- agatha·bdsm·user-cred-v2 각각의 스코어링 세부와 업데이트 주기
phoenix/학습 파이프라인의 loss·negative sampling·optimizer- Under the Hood 도구가 노출하는 라벨 taxonomy
- InventoryHoldoutFilter의 홀드아웃 비율 param
- "공개 소스 3세대" 표에 4세대 행을 추가했다(2026-08-13, +363k/−12k 라인, 파일 300개 이상, visibility-filtering·labeling 서브레포 15개 신설,
assets/x-pipeline.svg를 갱신했다.- 후보 소스에 SimClusters를 추가하고 tweet-mixer를 기본 off로 표시했다.
- 필터 개수를 14개에서 17개로 고쳤다.
- 가중치 절의 "값 비공개"를 "정본 참조 (예: reply 5.0 + 상호팔로우 부스트 15.0)"로 수정했다.
- 예측 헤드를 24개로 갱신했다.
- VMRanker의 "실패 시 조용히 스킵"에 "DPP θ=0.65 · K=150 · 기본 on" 값을 추가했다.
- radar.md를 갱신했다. 이번 릴리스는 추적 서비스(X)에 직접 반영되므로 레이더를 거치지 않고 정본에 바로 넣었다. 레이더에는 아래 arXiv triage 관련 1건만 추가했다.
의미 ⚠ 주장 대량 변경. 오늘 이전까지 X 정본에서 가장 크게 비어 있던 절 두 개(가중치 값과 labeling 파이프라인)가 하루에 동시에 해소됐다. 이 저장소의 성격상 이 정도 규모의 정본 재작성은 드문 일이다. 정본 x.md에서 300줄이 넘는 분량이 오늘 바뀌거나 새로 쓰였다.
- 첫 번째 의미는 연구 방향의 재정렬이다.
- 지난 3개월 동안 x.md의 열린 질문들이 다른 서비스(Meta·Netflix)를 관측하는 방향을 이끌어 왔다. "X 광고 스택은 어디까지 공개됐나", "SimClusters의 실 부활 여부", "VMRanker DPP의 배포 상태" 같은 질문이 topics/ 노트 여러 개의 방향을 정했다.
- 오늘 이 질문들이 답을 얻었으므로, 이 저장소는 이제 "X가 공개한 값이 왜 이런가 / 다른 회사의 대응 지점은 무엇인가"라는 다음 단계의 질문으로 옮겨간다.
- 예를 들어 X의 report 가중치 −234와 Netflix GenRec의 catalog softmax는 완전히 다른 손실 함수의 두 극단이다. 이 두 숫자가 정본에 나란히 놓여 있다는 사실 자체가 다음 topics 확장의 기준점이 된다.
- 두 번째 의미는 투명성 아키텍처의 산업 표준화가 시작된다는 신호다.
docs/BIDIRECTIONAL_BOOST_CHANGE.md가 보여 주는 문서화 방식은 A/B 시작에서 결과 관찰과 파라미터 조정까지를 3주 안에 코드 diff로 공개하는 방식이다. 이런 방식은 다른 회사(Meta·Netflix·YouTube 어느 곳)에서도 지금까지 사례가 없었다.- X가 이것을 "example algorithm diff"라고 부르며 앞으로도 반복하겠다고 예고했다면, 비교 가능한 프로덕션 diff 시계열이 처음으로 존재하게 되는 셈이다.
- 그렇다면 이 저장소가 앞으로 X 커밋 로그를 매일 추적하는 작업의 가치도 상당히 커진다. 다음 커밋에서 어떤 param이 어떻게 바뀌는지가 곧 A/B 결과의 지연 지표가 되기 때문이다.
- 세 번째 의미는 정본 주의 목록의 일부를 다시 조정해야 한다는 점이다.
- "소스 읽는 법 — 주의 목록"의 주의 항목 #1(레포가 빌드되지 않는다) 가운데 Phoenix 부분은 해소됐지만, 나머지는 부분적으로만 해소됐다.
crate::params는 param.rs로 채워졌고,crate::util·crate::clients도 같은 커밋에서 공개됐다 확인. - 주의 항목 #2(README가 지목한 스코어러 3개가 죽은 파일이다)는 아직 검증이 필요하다. 새 릴리스에서 정리됐을 수 있다.
- 주의 항목 #6(has_cached_posts 비중)은 미해소 상태다.
- canon 주의 목록은 다음 배치에서 파일별로 재검증할 예정이다(심층 분석 필요).
- "소스 읽는 법 — 주의 목록"의 주의 항목 #1(레포가 빌드되지 않는다) 가운데 Phoenix 부분은 해소됐지만, 나머지는 부분적으로만 해소됐다.
아래 항목은 심층 분석이 필요하며, 사람이 트리거해 개별 세션에서 확인해야 한다. 이번 릴리스의 규모를 감안하면 파일별 검증은 오늘 배치 예산을 넘어선다.
simclusters/서브레포: 코어 알고리즘(해소: Metropolis-Hastings SBF다, 위 D 참조), 인덱스 형식,home-mixer가 호출하는 API surface, 2020 KDD 논문과의 diffagatha//bdsm//user-cred-v2/: 각 계정 스코어러의 실제 모델과 업데이트 주기, 라벨 임계pnsfwmedia/캘리브레이션: CLIP 임베딩과 agatha 스코어를 어떻게 결합하는가phoenix/학습 코드: loss, negative sampling, optimizer, synthetic data 형식phoenix-rankall/·phoenix-rankall-strato/: 인덱싱 파이프라인과 visibility 사전 참조 로직abuse-enforcement-service/: 어떤 스코어가 어떤 조치(라벨/챌린지/서스펜션)로 매핑되는가scarecrow/·botmaker/·botmaker-rules/: 규칙 DSL과 컴파일러, 공개된 규칙과 미공개 규칙의 비율 및 카테고리under-the-hood/: 유저에게 노출되는 라벨 taxonomy와 규칙 코드의 연결 관계home-mixer/나머지 신규 파일: 새 hydrator·filter·scorer·side-effect (canon 주의 목록 재검증)visibility-filtering/rules/개별 규칙 파일: 각 규칙의 판정 조건과 canon 필터 절의 안전 레벨 불릿 최종 검증
2영상 추천 논문 1건을 레이더 관찰로 올렸고, 정본 반영은 0건이다 — arXiv
자료 arXiv API cs.IR 최근 30건 (2026-08-12~13) — arXiv API, 신규 논문 목록.
배경 매일 배치는 arXiv cs.IR 신규 30건을 제목과 초록으로 훑는다. 그 뒤 프로덕션 저자, A/B 주장, 메커니즘 신규성, 스케일 결과 가운데 하나라도 걸리는 것만 원문을 확인한다. 오늘은 30건 중 대부분이 RAG/QA/text-to-SQL/멀티모달 벤치마크 같은 학술 증분이거나, 음악·POI·의료 등 도메인이 한정된 연구였다. 이번 triage는 통과 후보 3건의 원문을 확인했다.
새로 알게 된 것A. 원문을 확인한 후보 가운데 DrEM 하나가 관찰을 통과했다
- STAR (2608.12986)는 탈락했다. 대회용 프레임워크는 프로덕션 진술이 아니다.
- 제목은 "Structured Tokenization and Target-Aware Interest Representation for PCVR Prediction"이다.
- 초록에서 스스로 "KDD Cup 2026 Tencent UniRec Challenge를 위한 프레임워크"라고 규정한다. 프로덕션 배포 진술은 없다.
- HCGRec (2608.11980)은 탈락했다. SID(semantic ID, 아이템을 의미 기반 코드 열로 나타낸 ID) 계열의 학술 증분이다.
- 제목은 "Hint-Conditioned Generative Recommendation with Semantic IDs"이다.
- 저자 소속이 공개돼 있지 않다(arXiv 페이지에 affiliation 없음). CIKM 2026 accepted로 표기돼 있고, GitHub 링크가 있다. 프로덕션 배포 진술은 없다.
- DrEM (2608.12778)은 관찰을 통과했다. 저자 소속은 공개돼 있지 않으나, 초록에서 실제 배포를 주장한다.
- 제목은 "Dual-Side Robust Ensemble Ranking from Noisy User Preference Predictions in Video Recommendation"이다.
- 배포 주장의 근거로 초록은 이렇게 쓴다: "large-scale online A/B tests".
- 저자 이름(Xiaoxiao Xu, Kaiqiao Zhan 등)이 Kuaishou 계열과 통계적으로 일치할 가능성이 있다 추정.
- radar.md의 "이번 달 신규"에 3~4줄 포인터를 추가했다(심층 분석은 하지 않았다). 회사 확정과 프로덕션 지면 확정은 다음 배치에서 크로스체크한다.
정본 반영
- radar.md의 "이번 달 신규"에 DrEM (video rec, unknown company) 항목을 새로 넣었다. 3~4줄 포인터에 A/B 주장이 있다는 점, 저자 소속이 확인되지 않았다는 점, Kuaishou 라인일 가능성 추정을 적었다.
의미 레이더의 하루 통과 건수는 기대치인 0~2건 안에 들어온다. 이번 주에는 SID와 생성형 랭킹 계열이 계속 증분되고 있으나(Alibaba·Kuaishou·Yandex 라인은 이미 정본에서 관찰 중이다), 새로운 회사나 새로운 메커니즘에 대한 진술은 아직 없다.
검증에서 뒤집힌 것
- x.md 정본의 "가중치 값은 어느 세대에서도 1차 출처가 없다. 유일한 수치 출처는 2023년 4월 5일 시점 스냅샷 하나뿐"이라는 진술이 2026-08-13에 뒤집혔다.
home-mixer/params/param.rs가 프로덕션 크론 미러로서*Weightparam 26개(양수 21, 부정 5)와 상호팔로우 boost 2개, OON 배수, 다양성 상수를 전부 실제 값으로 공개했다.
- x.md 정본의 "SimClusters ... 이 이름들은
home-mixer/어디에도 안 나온다"는 진술이 2026-08-13에 부분적으로 뒤집혔다.simclusters/서브레포가 OON retrieval 소스로 home-mixer에 연결됐다.- 다만 정본의 "2023 세대에서 살아남은 retrieval은 사실상 tweet-mixer 하나뿐"이라는 문장은 이제 "2023 세대에서 살아남은 retrieval은 tweet-mixer(기본 off로 미러) + SimClusters(부활)"로 다시 썼다.
- x.md 정본의 "가중치 값·params 모듈은 레포 밖 — 비공개"라는 진술을 담고 있던 pipeline 다이어그램(assets/x-pipeline.svg)을 갱신해야 했고, 갱신을 마쳤다.
- x.md 정본의 열린 질문 "VMRanker/DPP가 켜져 있는가"에 대해서는 켜져 있다는 사실을 param으로 확인했고, DPP는 θ=0.65, K=150이다. 이 항목은 열린 질문 목록에서 제거했다.
- x.md 정본의 "필터 17개(스코어링 전 14 + 후 3)"를 20개(스코어링 전 17 + 후 3)로 갱신했다.
- x.md 정본의 "2026 코드에 [신규 아이템 콜드스타트] 아무 장치가 없다"는 진술이 뒤집혔다.
PostUnexploredWeight = 0.02와ColdStartImpressionThreshold = 1000, 그리고 신규 유저용NewUserMinEngagementFilter가 각각 존재한다. 정본의 "부재" 관찰은 3개월 전 스냅샷을 기준으로 한 것이었을 뿐이다.
레이더
- radar.md의 "이번 달 신규"에 DrEM (2608.12778) 관찰 항목을 새로 추가했다. video rec 분야의 A/B 주장이 있고, 저자 소속은 확인되지 않았다.
다음에 볼 것
- X 4세대 릴리스 심층 분석 — 위의 심층 분석 필요 10개 항목 가운데 우선순위는 아래 순서다.
home-mixer/신규 파일로 canon 주의 목록을 재검증하는 일simclusters/서브레포로 정본의 SimClusters "부활" 진술을 확정하는 일abuse-enforcement-service/와visibility-filtering/rules/의 개별 규칙으로 안전 파이프라인을 재구성하는 일
- DrEM 저자 소속 확정 — Kuaishou 계열이면 이미 정본에서 관찰 중인 회사이고, 다른 곳이면 radar의 신규 스레드 후보가 된다.
- BIDIRECTIONAL_BOOST_CHANGE 이후의 X 커밋 추적 — 다음 param diff가 언제 어떤 형태로 올라오는지 확인한다. 저장소의 매일 배치가 X 커밋을 이미 확인하고 있으므로 자동으로 감지될 예정이다.
- EU DSA 투명성 보고서 — X가 이번 8-13 공개 이후 무엇을 새로 제출하거나 삭제하는지 살펴본다. 규제 문서와 코드가 sync되어 있는지가 새로운 검증 각도가 된다.