0x00

리서치 / 일일 리포트

한 줄 요약X 조사를 시작했다. 리서치 저장소를 새로 만들었고, X가 공개한 소스 3세대를 전부 분석했다.

이 글은 작업 기록이다. 근거 등급과 file:line 인용은 모두 services/x.md와 topics/*.md에 정리했고, 여기서는 되풀이하지 않는다.

읽은 것

X가 공개한 소스 3세대와 2023년 머신러닝 저장소에서 아래 디렉터리를 읽었다.

  • 3세대: xai-org/x-algorithm(2026-01-20 aaa167b, 2026-05-15 e414c17·0bfc279)의 다음 디렉터리 전체
    • home-mixer/(For You 피드를 조립하는 서비스)
    • thunder/(Thunder, 팔로우한 계정의 최신 포스트를 꺼내 주는 인메모리 인덱스)
    • phoenix/(Phoenix, 트랜스포머 랭킹 모델과 two-tower retrieval 모델)
    • grox/(nearline LLM 주석 파이프라인)
    • candidate-pipeline/
  • 2세대: twitter/the-algorithm @ c54bec0(2025-09-03 리프레시)의 home-mixer/, tweet-mixer/
  • 1세대: twitter/the-algorithm @ 72eda9a(2023)의 simclusters_v2/, simclusters-ann/, ann/, cr-mixer/
  • twitter/the-algorithm-ml(2023)의 projects/home/recap/, projects/twhin/

↑ 목차

오늘 새로 알게 된 것 중 가장 중요한 5가지

  1. 1세대와 2세대 사이에는 26개월의 공백이 있고, 2세대에서 삭제된 파일은 0건이다. 2023년 파일 집합은 2025년 파일 집합의 진부분집합이다. 따라서 저장소에 파일이 남아 있다고 해서 그 파일이 현역이라는 뜻은 전혀 아니다. 폐기 여부는 README 한 줄이 바뀌는 방식으로만 드러난다.
  2. "인네트워크 50:50"이라는 규칙은 코드에 존재하지 않는다. 2026 코드에는 배분기 자체가 없다. OON(out-of-network, 팔로우하지 않은 계정의 포스트)은 쿼터가 아니라 점수 배수로 조절된다. 배분 문제가 랭킹 문제로 옮겨 간 셈이다.
    • 이 배수는 effective_oon이다.
  3. xai-org/x-algorithm은 빌드되지 않는다. Cargo.toml이 0개이고, crate::params와 util, clients는 모듈 전체가 빠져 있다. 60개 파일이 params를 참조하지만 그 정의는 어디에도 없다. 즉 로직의 형태만 공개하고 값과 연결 관계는 제외했다. 우연이 아니라 일관된 설계다.
  4. README가 지목하는 스코어러 3개는 모듈 트리에서 끊겨 있다. 실제로 연결되어 있는 것은 vec![phoenix_scorer, ranking_scorer, vm_ranker]다.
    • 죽은 파일 11개를 목록으로 확정했다.
    • models/와 candidate_pipeline/의 이중 레이아웃이 세대를 구분하는 기준이라는 점도 확인했다.
  5. 가중치 값은 어느 세대에도 1차 출처가 없다.
    • 널리 인용되는 "reply 13.5 / report −369" 표는 블로그가 아니라 the-algorithm-ml의 README에서 나왔다. 그 문서는 "2023-04-05 기준, 언제든 바뀔 수 있다"고 스스로 밝힌다.
    • 2025 Scala는 ModelWeights 30개를 전부 default = 0.0으로 지웠다. 같은 파일의 나머지 default 203개는 실제 값을 가지고 있으므로, 이것은 코딩 스타일이 아니라 의도적인 삭제로 보아야 한다.

부수적으로 알게 된 것은 다음과 같다.

  • has_cached_posts라는 캐시 플래그 하나가 모든 소스와 하이드레이터, Phoenix를 한꺼번에 끄는 가장 큰 스위치다.
  • 이미 본 포스트를 거르기 위한 백업 필터(PreviouslySeenPostsBackupFilter)는 영구 no-op이다.
  • VMRanker(후보 순서를 다시 매겨 다양성을 반영하는 원격 서비스)는 실패해도 로그를 남기지 않고 조용히 넘어간다. 그래서 다양성이 사라진 것을 알아채기 어렵다.
  • grox/에 있는 파이썬 파일 두 개는 리터럴 치환 때문에 import 자체가 되지 않는다.

↑ 목차

검증에서 뒤집힌 것 (중요)

초안을 verifier로 다시 검증했더니 결론 하나가 반대로 나왔고, 상수를 인용할 때 지켜야 할 규칙도 하나 새로 배웠다.

  • 뒤집힘: "2025 tweet-mixer의 u2i 후보는 상한 절단 뒤에 붙어서 특혜를 받는다"는 결론은 틀렸다. 절단선을 하나만 보고 결론을 내리면 방향이 반대로 나온다.
    • tweet-mixer는 2025 세대에서 OON 후보 생성을 맡은 서비스다. u2i는 유저에서 포스트로 후보를 찾는 경로(user→post)다.
    • DropMaxResults가 result만 자르고 remainingCandidates는 남기기 때문에, u2i는 리스트 뒤쪽에 놓인다.
    • 그 뒤의 최종 절단선이 400이라(라이트랭커 상한 500보다 작다), 앞이 다 차면 u2i가 먼저 사라진다.
  • 새 규칙: grep으로 찾아낸 숫자를 프로덕션 값으로 그대로 쓰면 안 된다. 주의할 점 세 가지가 모두 실제로 나타났다.
    • args.int(name, default)의 default: SimClusters(팔로우 그래프를 커뮤니티로 나눠 만든 임베딩)의 maxNeighbors는 코드에 400으로 적혀 있다. 그러나 같은 파일이 적어 둔 프로덕션 실행 명령은 --maxNeighbors 100이다. maxEpochs도 코드값 3과 프로덕션값 4가 서로 다르다.
    • 벤치마크와 warmup에 쓰인 리터럴: HNSW(근사 최근접 이웃 검색 인덱스)의 efConstruction=200과 maxM=16은 experimental/Runner.scala에 있는 실험용 값이다. ef=800은 warmup() 안에 들어 있다.
    • 모듈 트리에서 끊긴 파일의 상수: 2026 죽은 스코어러의 p::AUTHOR_DIVERSITY_DECAY가 그 예다.
  • 얻은 것: 2026 코드가 공개하지 않은 상수 하나를 2025 코드로 복원했다.
    • 2026 offset_score는 2025 RerankerUtil.weightedScoresSum을 그대로 옮긴 코드다. 그래서 비공개 상수 NEGATIVE_SCORES_OFFSET을 2025의 Epsilon = 0.001로 복원했다.
    • 이 사례는 두 저장소 사이에 코드 중복이 0이라는 통설의 예외다.
    • 다른 비공개 상수도 같은 방법으로 복원할 수 있을 것으로 보인다.
  • 그 밖의 수정: 다른 사실 몇 가지도 바로잡았다.
    • FailOpenPolicy.Always는 9개 가운데 8개에만 적용되어, ContentExploration만 fail-closed다.
    • 2025 MMR(관련성과 다양성을 함께 따져 순서를 다시 매기는 기법)은 리스트 앞쪽 (1-diversityRatio)×n개에는 다양성을 전혀 적용하지 않는다.
    • QuoteDeduplicationFilter는 인용문이 아니라 인용당한 원본을 지운다.
    • tweet-mixer 파이프라인은 35개가 아니라 34개다.

↑ 목차

정본 반영

X 정본과 topics 노트를 모두 새로 만들었다.

  • services/x.md: 3세대 비교표, 지면, 후보 생성(retrieval) 소스 11개, Phoenix 예측 헤드 22개, 필터 17개, 광고 블렌딩, 콜드스타트, 주의 목록 11개
  • topics/sequence-transformer-ranking.md: Phoenix 구조와 마스크
  • topics/llm-in-recsys.md: Grok/Grox 주석 파이프라인
  • topics/multi-task-ranking.md: 세대별 헤드 목록, 가중치 불투명성
  • topics/candidate-allocation.md: 비율, 상한, 인터리브와 "50:50" 반박
  • topics/feed-diversity.md: 감쇠, MMR, DPP(서로 비슷한 항목이 함께 뽑히지 않게 고르는 확률 모형), dedup
  • topics/embedding-retrieval.md: SimClusters, TwHIN, two-tower, ANN 인덱스

↑ 목차

다음에 볼 것

↑ 목차