0x00

리서치 / 일일 리포트

  • 읽은 자료 1건
  • 정본 반영 1개 파일
  • 레이더 0건
한 줄 요약X가 generative SID retrieval의 서버 크레이트를 공개했다. 서버는 미리 만들어 둔 SID 스냅샷에서 접두사 범위 검색만 한다.

1SID retrieval 서버가 공개되고 인기 포스트 후보 소스가 생겼다 — X

자료 xai-org/x-algorithm@b412112 — xai-org, 2026-10-03T03:26:56Z, 코드. 이 노트들은 4세대 공개 뒤의 X 커밋에 차례로 번호를 붙여 부르며, 이 커밋은 4세대+35다. 커밋 전체는 +9,128/−2,356, 파일 148개다.

배경 SID(semantic ID)는 RQ-VAE 계열 양자화로 포스트를 다단계 토큰 시퀀스로 압축한 코드를 말한다. generative SID retrieval은 유저 히스토리를 입력으로 받은 Transformer가 다음 포스트의 SID 토큰을 autoregressive로 생성하고, 그 코드가 가리키는 포스트들을 candidate로 돌려주는 접근이다. Pinterest TIGER(2024) · Alibaba PailitaoGR(2025) · Kuaishou OneRec(2025) · Tencent BARGE(2026) · ByteDance GEAR(2026-09-30 arXiv) 라인이 이 접근을 쓴다. X에서는 지난 사흘(2026-10-01 ~ 2026-10-03) 사이 이 라인이 세 단계로 쌓여 왔다.

  • 첫 단계는 2026-10-01 커밋(4세대+33, b79b947)이다. Phoenix(For You의 후보 검색과 랭킹에 쓰이는 Grok 기반 트랜스포머)의 retrieval wire에 SID를 뽑는 자리의 밑그림이 보였다.
  • 둘째 단계인 2026-10-02 커밋(4세대+34, 76843a5)에서는 Phoenix에 전용 Transformer의 학습 config/모델/트레이너/러너 4-파일이 공개됐다. 홈믹서(For You 피드를 조립하는 서비스)에는 SidSource 후보 소스 뼈대와 SidRetrievalClient gRPC 클라이언트가 공개됐다.
  • 다만 그 커밋에는 실제 요청을 받아 응답을 돌려줄 서버 크레이트가 없었다. 홈믹서는 xai-recsys-sid-retrieval.prod.fou.twitter.biz:443로 호출을 보내지만, 그 endpoint 뒤의 Rust 서버가 어떻게 생겼는지는 외부에서 알 수 없었다.

이번 커밋은 그 서버 크레이트를 공개했고, 그 밖에 세 가지를 바꿨다.

  • 서버 크레이트: phoenix/crates/serving/xai-recsys-sid-retrieval/ 아래 src 7개 파일, 1,018줄이 새로 생겼다(Cargo.toml 포함 8개 1,050줄).
  • 인기 포스트 후보 소스: 홈믹서에 새 OON(팔로우하지 않은 계정의 포스트) 후보 소스 PopularPostsSource가 생겼다. top-K 인기 저자를 Thunder(팔로우한 계정의 최신 포스트를 담는 in-network 인덱스)에 "가상 following"으로 넣어, OON 추천의 공백을 메우는 방식이다.
  • 광고 브랜드 안전: EnableAdsBrandSafetyVerdictV2의 기본값이 false → true로 바뀌었다. 포스트 라벨이 없을 때 작성자 수준 Grok 라벨을 대신 쓰는 EnableAdsAuthorBrandSafetyFallback 파라미터도 새로 생겼다(기본 off).
  • 리플레이·캡처: VF(visibility-filtering, 포스트를 뷰어에게 보여도 되는지 판정하는 서비스) 쪽 visibility-filtering/staging/ 아래에 새 파일 6개, 1,334줄짜리 서브시스템이 새로 생겼다. 옮겨 온 파일 3개까지 합한 추가분은 1,636줄이다.

새로 알게 된 것A. SID retrieval 서버는 SID 스냅샷으로 인덱스를 만들고 접두사 범위로 후보를 찾는다

  • SID retrieval 서버 크레이트가 src 7개 파일(Cargo.toml 포함 8개)로 새로 공개됐다 확인 — phoenix/crates/serving/xai-recsys-sid-retrieval/.

    • 구성 파일: src/service.rs:208, src/index.rs:223, src/loader.rs:170, src/http_api.rs:109, src/main.rs:115, src/seed_sids.rs:114, src/metrics.rs:79.
  • 서비스 인터페이스는 별도 proto 크레이트가 정의하고, RPC는 하나뿐이다 확인 — sid_retrieval.proto:46.

    • proto 크레이트는 xai-recsys-sid-retrieval-proto이고, RPC는 rpc Retrieve(RetrieveRequest) returns (RetrieveResponse)다.
    • 요청 필드는 seed_post_ids/max_results/max_per_seed/min_prefix_depth/max_prefix_depth/caller다.
    • 응답에는 candidates, seeds(각 seed가 어디서 왔는지를 Index/SidService/Missing 라벨로 표시), snapshot_timestamp_secs, index_posts가 담긴다.
  • 인덱스는 SID를 정수 키 하나로 패킹하고, 포스트 목록 두 벌을 서로 다른 순서로 정렬해 둔다 확인 — src/index.rs:5-110.

    • SID_LEVELS = 6, BITS_PER_LEVEL = 8, MAX_CODE = 255다. 각 레벨은 2^8=256개 코드를 가진다.
    • 전체 SID는 상위 레벨부터 왼쪽으로 8비트씩 shift해 48-bit u64 key에 패킹된다. 이론상 키 공간은 256^6 ≈ 2.8 × 10^14다.
    • IndexedPost { key, post_id, author_id } 벡터 2개를 유지한다. by_key는 (key ASC, post_id DESC)로 정렬해 접두사 범위 검색에 쓴다. by_post는 (post_id ASC)로 정렬해 seed post_id → SID key 이진탐색에 쓴다.
    • prefix_range(key, depth)는 상위 depth 레벨만 남기고 하위 (6-depth)*8 비트를 0으로 지운 [lo, hi)를 돌려준다. 이 범위로 by_key.partition_point를 불러 범위 안의 포스트를 뽑는다. 깊이 수준마다 O(log N) + O(결과 크기)가 든다.
  • 검색은 접두사 깊이를 깊은 쪽부터 얕은 쪽으로 내려가며 후보를 모은다 확인 — src/index.rs:138-193.

    • 각 포스트는 "그 포스트가 공유한 가장 깊은 접두사 수준에서 한 번만" 결과에 들어간다. 깊이 6에서 뽑힌 포스트는 깊이 5~3에서 다시 뽑히지 않는다. 깊이를 역순으로 돌면서 이미 훑은 영역(consumed)을 빼는 방식으로 구현했다.
    • 같은 깊이 안에서는 post_id가 큰(=최근) 포스트가 먼저다. select_nth_unstable_by(post_id DESC)로 상위 K개만 자른 뒤 정렬한다.
    • seed 포스트 자신은 전역 excluded set으로 걸러진다. 여러 seed로 요청할 때 seed₁의 결과에 seed₂가 섞이지 않는다.
    for depth in (params.min_prefix_depth..=max_depth).rev() {
        let (lo, hi) = prefix_range(seed.key, depth);
        let (start, end) = self.key_range(lo, hi);
        let mut level: Vec<&IndexedPost> = match consumed {
            None => self.by_key[start..end].iter().collect(),
            Some((inner_start, inner_end)) => self.by_key[start..inner_start]
                .iter()
                .chain(self.by_key[inner_end..end].iter())
                .collect(),
        };
        level.retain(|p| !excluded.contains(&p.post_id));
        ...
        picked.extend(level.into_iter().map(|p| Candidate {
            post_id: p.post_id, author_id: p.author_id,
            seed_post_id, shared_prefix_depth: depth as u32,
        }));
        consumed = Some((start, end));
    }
    

    — src/index.rs:138-179

  • 여러 seed의 후보는 round-robin으로 번갈아 뽑는다 확인 — src/index.rs:196-222.

    • seed 1 → seed 2 → ... → seed N → seed 1 → ... 순서로 돌며, 전역 HashSet<post_id> emitted로 중복을 뺀다.
    • max_results에 이르거나 더 뽑을 것이 없으면 멈춘다.
    • 그 결과 포지션 바이어스가 특정 seed로 쏠리지 않도록 균등화된다.
  • 스냅샷 로더는 30초마다 경로를 확인하고, 바뀌었으면 인덱스를 전부 다시 만들어 원자적으로 바꿔 끼운다 확인 — src/loader.rs:1-170.

    • 입력 포맷은 Arrow Parquet(post_sid_snapshot.parquet)다. 컬럼은 post_id: int64, author_id: int64, post_sid: list<int64> 세 개이고, 배치 크기는 65,536이다.
    • timestamp는 파일명 suffix(*_<unix_ts>.parquet)에서 뽑고, 파싱에 실패하면 파일 mtime으로 대신한다.
    • watch_snapshots(path, poll_interval=30s, index, ready_tx)는 30초마다 canonicalize(path)를 하고, 경로가 바뀌었으면 전부 다시 적재한다. 빌드는 tokio::spawn_blocking에서 돌고, 성공하면 ArcSwapOption<SidIndex>로 atomic swap한다. 이어서 ready_tx.send(true)로 /readyz의 초기 ready 플래그를 올린다.
    • 즉 실시간 업서트는 없고, 모델 쪽에서 생성한 코드 테이블을 배치로 밀어 넣는 패턴이다.
    • 잘못된 SID는 조용히 버린다. pack_full_key(row_codes)는 len != 6이거나 코드가 하나라도 0..=255 범위 밖이면 None을 돌려주고, 그때 skipped 카운터가 오른다.
  • seed의 SID는 로컬 트라이에서 먼저 찾고, 없으면 별도 gRPC 서비스에 묻는다 확인 — src/seed_sids.rs:1-114.

    • 외부 서비스는 SidLookupService(xai-recsys-sid-proto, endpoint는 --sid-endpoint 플래그)다. batch로 조회하고, 결과를 moka 캐시(2백만 엔트리, TTL 6시간)에 넣는다.
    • 즉 서비스가 seed SID를 두 곳에서 받는다. 하나는 자신의 parquet 스냅샷(= 코퍼스 측 모든 코드)이고, 다른 하나는 외부 서비스(= 아마도 Phoenix 측 실시간 코드 발행 라인)다.

    역사적 맥락: SidLookupService는 4세대+15(2026-09-04, 9b0dc31)에서 "Phoenix 서빙 엔진에서 SID retrieval 사이드카가 통째 제거"됐을 때 사라진 그 lookup 서비스가 이번 자리에서 별도 외부 서비스로 환생한 셈이다. 당시 사이드카는 Phoenix 요청 상에서 "유저 히스토리의 각 포스트 ID를 SID로 변환"해 주는 lookup 역할이었고, 사라진 뒤 히스토리 SID는 요청에 미리 실려 들어오는 형태로 흡수됐다. 지금은 retrieval 서버가 seed → SID 변환이 필요할 때 그 서비스를 호출하는 축으로 모양이 바뀌었다.

  • 서버는 메트릭 3종을 남긴다 확인 — src/metrics.rs.

    • sid_retrieve_requests{caller, result=ok|empty|unavailable} 카운터
    • sid_retrieve_seeds{source=index|sid_service|missing} 카운터
    • sid_retrieve_candidates{caller}와 sid_retrieve_latency_seconds{caller} 히스토그램
  • 서버의 기본 동작은 실행 플래그로 정한다. 기본값으로 결과는 800개, seed당 100개까지 돌려주고, 접두사 깊이 3~6을 검색한다 확인 — src/main.rs:26-52.

    • --grpc-port=9090 · --http-port=8080 · --snapshot-poll-secs=30 · --sid-timeout-ms=200 · --sid-cache-size=2_000_000 · --max-seeds=200 · --default-max-results=800 · --default-max-per-seed=100 · --default-min-prefix-depth=3 · --default-max-prefix-depth=6

새로 알게 된 것B. 인기 저자의 포스트를 Thunder에서 받아 OON 후보로 쓰는 소스가 생겼다

  • 새 소스는 팔로워 수 상위 저자들을 유저가 팔로우하는 것처럼 Thunder에 넘기고, Thunder가 돌려준 포스트를 후보로 낸다 확인 — home-mixer/sources/popular_posts_source.rs:68-115.

    1. PopularPostsSource는 !has_cached_posts && !in_network_only && EnablePopularPostsSource==true일 때만 돈다.
    2. PopularAuthorsCache.maybe_spawn_refresh(now_ms)를 호출한다. AtomicBool 하나로 중복을 막으면서 백그라운드 리프레시를 시작한다.
    3. top_author_ids(top_k)로 follower_count 내림차순 상위 K명(기본 1,000)의 author_id를 뽑는다.
    4. Thunder에 GetInNetworkPostsRequest { user_id, following_user_ids=[top K authors], max_results=500, per_author_limits={3, 0}, exclude_tweet_ids=seen_ids, algorithm, debug=false, is_video_request=false }를 보낸다. Thunder는 그 K명을 유저가 팔로우하는 것처럼 간주해, 자기 in-network 포스트 저장소에서 recency순으로 포스트를 돌려준다.
    5. 응답 포스트는 served_type=ForYouPhoenixRetrieval 라벨을 달고 PostCandidate에 담겨 나간다. PhoenixSource와 같은 라벨이다.
    let authors = self.popular_authors.top_author_ids(top_k);
    ...
    let request = GetInNetworkPostsRequest {
        user_id: query.user_id,
        following_user_ids: authors,
        max_results: query.params.get(PopularPostsMaxResults),
        exclude_tweet_ids: query.seen_ids.to_vec(),
        per_author_limits: Some(PerAuthorLimits {
            max_posts_per_author: Some(query.params.get(PopularPostsMaxPerAuthor)),
            max_replies_reposts_per_author: Some(
                query.params.get(PopularPostsMaxRepliesRepostsPerAuthor),
            ),
        }),
        ...
    };
    

    — popular_posts_source.rs:87-101

  • 인기 저자 캐시는 자체 바이너리 포맷 v1로 저장한다 확인 — util/popular_authors.rs:64-104.

    • 캐시는 PopularAuthorsCache이고, 포맷은 version=1(1B) + updated_at_ms(8B BE) + count(4B BE) + [author_id(8B BE), follower_count(8B BE)] * count다.
    • 1,000명이면 13 + 16,000 = 16,013바이트다. Manhattan(X 내부의 키-값 저장소) 한 키에 전부 저장되는 설계다.
    • 리프레시 주기는 캐시가 비어 있으면 60초, 비어 있지 않으면 60분이다. 빈 상태일 때만 공격적으로 재시도하는 흔한 패턴이다.
  • 파라미터 5개가 새로 생겼고, 소스 자체는 기본 off다 확인 — home-mixer/params/param.rs.

파라미터 기본값 역할
EnablePopularPostsSource false 소스 자체 켜기
PopularPostsTopAuthors 1000 KV 스토어에서 상위 몇 명을 "가상 following"으로 넣을지
PopularPostsMaxResults 500 Thunder 응답 상한
PopularPostsMaxPerAuthor 3 저자 1명당 최대 포스트 수
PopularPostsMaxRepliesRepostsPerAuthor 0 답글/리트윗은 소스에서 완전히 배제

새로 알게 된 것C. 광고 브랜드 안전 V2 판정이 처음 기본으로 켜졌고, 작성자 라벨 fallback 스위치가 생겼다

  • 광고 브랜드 안전 V2 판정 스위치의 기본값이 false에서 true로 바뀌었다 확인 — home-mixer/params/param.rs.

    • 스위치는 EnableAdsBrandSafetyVerdictV2다. 4세대+2(2026-08-17, b089ce6)에서 BrandSafetyVerdictV2 로직이 공개된 뒤 계속 off였던 기본값이 오늘 처음 on이 됐다.
    • 이 파일은 프로덕션 설정값을 매일 동기화해 옮겨 두는 크론 미러다.
    • 미러 sync 시점(last sync 2026-10-01T16:00:46Z → 2026-10-02T16:00:41Z)에 올라온 값으로, 2026-10-02 중 어느 시점의 프로덕션 cron에서 올라간 상태를 미러한 것으로 보인다 추정.
  • 작성자 라벨 fallback 스위치가 기본 off로 새로 생겼다 확인 — 같은 파일.

    • 스위치는 EnableAdsAuthorBrandSafetyFallback이다. 작성자 수준의 Grok 라벨(GrokSfa/GrokNsfaLimited/GrokNsfa)은 있는데 포스트 수준 라벨이 없을 때, 작성자 라벨을 포스트 라벨 자리에 fallback으로 넣는 경로다.
  • 판정 등급과 작성자 fallback 라벨은 두 enum으로 정의돼 있다 확인 — home-mixer/models/brand_safety.rs:6-80.

    #[repr(i32)]
    pub enum BrandSafetyVerdict {
        Unspecified = 0, Safe = 1, LowRisk = 2, MediumRisk = 3, HighRisk = 4,
    }
    pub enum AuthorBrandSafetyFallback { Sfa, NsfaLimited, Nsfa }
    

    — brand_safety.rs:6-21

  • 판정은 Safe / LowRisk / MediumRisk / HighRisk의 4단계다. 이 판정은 광고 블렌더 쪽 AdAdjacencyControl.brand_safety_risk와 짝을 이루는 인접성 매트릭스(4세대+10의 MultiRiskAdsBlender)가 소비한다.

    • 즉 광고 지면에서 "포스트 안전도 → 광고 삽입 가능 여부"를 정하는 축이 오늘부터 기본값으로 켜졌다.

새로 알게 된 것D. VF에 실 트래픽과 분리된 리플레이·캡처 서브시스템이 생겼다

  • 어제까지 없던 VF staging 폴더가 새 파일 6개, 1,334줄로 새로 생겼다 확인. 옮겨 온 파일 3개까지 합한 추가분은 1,636줄이다.
    • 폴더는 visibility-filtering/staging/이다.
    • 파일별 변경: recording.rs(+744 신규), replay_corpus.rs(+299 신규), capture.rs(+221 신규), reference/tweetypie.rs(+204/-81 renamed), reference_compare.rs(+63/-39 renamed), reference/mod.rs(+35/-72 renamed), main.rs(+39 신규), serve.rs(+29 신규), mod.rs(+6 신규).
  • 이 서브시스템은 별도 crate 엔트리 포인트를 가지며, VF를 실 트래픽과 완전히 분리된 리플레이·캡처 모드로 돌리기 위한 것이다 확인.
    • 엔트리 포인트는 staging/main.rs다.
    • 어제까지 VF 트리의 다른 곳에 흩어져 있던 referential 비교(Tweetypie reference) 코드도 이쪽으로 옮겨 왔다.
  • 다음 창에서 심층 분석할 것은 세 가지다.
    • recording.rs 744줄이 무엇을 어떤 포맷으로 기록해 두는지(parquet/jsonl 추정)
    • capture.rs가 라이브 트래픽을 어떻게 샘플링하는지
    • replay_corpus.rs의 재생 contract가 어떻게 생겼는지

새로 알게 된 것그 밖의 변경

  • 어제 커밋(4세대+34)에서 공개된 row-sharded 임베딩 CUDA 커널 묶음의 체크포인트 복원 쪽이 Python으로 완성됐다.
    • 커널 묶음은 cuda/row_emb/이고, 복원 파일은 phoenix/xrex/train/row_embedding_restore.py(+488 신규)다. 어제의 공유 adapter(recsys_async_emb.py)와 오늘의 복원 유틸이 함께 들어온 셈이다. 심층 분석이 필요하다.
  • Phoenix 랭킹 서버에 서버 측 레이턴시 전용 메트릭 모듈이 inflight 메트릭과 분리돼 생겼다. 운영 관측을 넓히는 변경이고, 모델 쪽 변경은 아니다.
    • phoenix/crates/serving/xai-recsys-engine/src/grpc_server_latency.rs(+361 신규)
  • 어제 분리된 SID retrieval trainer/모델이 공용 코드와 함께 쓰던 유틸을 깨끗이 떼어 내는 재배치가 있었다. 공용 코드는 순 감소(-477)다.
    • trainer_recsys.py(+376/-853), recsys_model.py(+786/-431)
  • 광고 쪽 작성자 수준 Grok 라벨을 가져오는 클라이언트가 생겼다. 위 C의 fallback 경로가 이 클라이언트를 쓴다.
    • home-mixer/clients/author_brand_safety_client.rs(+281 신규)
  • 어제 커밋(4세대+34)에서 삭제된 is_arm_gated_retrieval이 작성자 cold-start 쪽에서 다시 쓰였다. cold-start 특유의 다른 분기로 되살아났다.
    • home-mixer/scorers/author_cold_start.rs(+53)
    • 즉 어제의 삭제는 "이 축 자체를 폐기"가 아니라 "retrieval 분기에서 걷어 작성자 cold-start 쪽으로 이사"였다.
  • SimClusters ANN 캐시 클라이언트가 공유 crate에서 분리됐다.
    • home-mixer/clients/simclusters_ann_cache_client.rs(+211 신규)
  • VMRanker(피드에 내보낼 후보 묶음을 재정렬하는 단계)에 pacing-input 축이 선언됐다. 연계 param VMRankerSendPacingInputs는 기본 off다.
    • vm-ranker/scoring/value_model.rs(+96/-5), scoring/mod.rs(+85/-2)

정본 반영 services/x.md의 세 절을 고쳤다. 후보 생성(retrieval) 절에서는 SidSource 행에 "서버 측 알고리즘(parquet 30초 폴링 · 깊이 역순 · round-robin 인터리브) + 서버 상한값 5종"을 추가하고, PopularPostsSource 행을 새로 만들었다. 안전성/VF 파이프라인 절에는 ### 4세대+35 (2026-10-03, b412112) 섹션(A~G 7단계와 의미 3단계)을 새로 추가했다. 출처 절에서는 커밋 리스트 끝에 b412112를 추가했다.

의미 이번 공개로 SID retrieval 서버는 생성(beam search)을 하지 않고, 코퍼스 측에서 미리 만든 코드 표를 접두사 범위로 검색만 한다는 설계가 드러났다. 새 후보 소스 두 개(SID, 인기 포스트)는 모두 기본 off이므로, cron에서 켜지는 날이 실 트래픽 적용의 관측 지점이다. 광고 쪽 두 변경은 브랜드 안전 라벨링을 포스트 수준에서 작성자 수준으로 넓히는 방향이다.

  1. 어제 공개된 generative SID retrieval 세 축(home-mixer source, Phoenix 모델/트레이너, proto)에 오늘 "실제 서버 크레이트"가 붙었다. 사흘에 걸친 공개의 세 번째이자 마지막 조각이다.
    • 어제까지는 학습 레시피와 홈믹서 소스 뼈대만 있었고, 서버는 비어 있었다.
    • 오늘 공개된 xai-recsys-sid-retrieval 크레이트는 세 가지를 명시해, 이 서버의 실제 쿼리 복잡도를 공개된 코드만으로 측정할 수 있게 했다.
      • parquet 스냅샷을 30초마다 전부 다시 적재하는 완전 정적 인덱스다. 실시간 업서트는 없다.
      • 48-bit u64 key에 패킹된 6-level 트라이를 partition_point 기반으로 범위 검색한다.
      • 깊이 역순과 round-robin 인터리브로 recall을 자르는 알고리즘을 쓴다.
    • 어제까지 이 자리는 "generative decoding을 서버가 할 거다"로 읽혔다. 오늘 공개는 generation을 코퍼스 측에서 미리 해 두고(배치 코드 테이블) 서버는 접두사 범위 검색만 한다는 설계 선택을 드러낸다.
    • 즉 추론 시점의 beam search는 서버에 없다. 모델이 뽑은 코드가 코퍼스에 담겨 들어오고, 서버는 seed 코드와 공유 접두사 길이로 검색하는 KNN-like 서버다.
    • EnableSidSource=false가 여전히 기본값이므로, 실 트래픽 적용은 FeatureSwitches cron에서 ON 되는 날이 관측 지점이다.
  2. PopularPostsSource는 Thunder의 in-network 인덱스를 "global popularity" 용도로 재활용하는 접근이다. 결과를 ForYouPhoenixRetrieval 라벨로 담아 Phoenix two-tower retrieval(유저와 포스트를 각각 임베딩해 맞춰 보는 검색) 응답과 섞는다.
    • 라벨에서 PhoenixSource와 구분되지 않도록 설계된 점이 흥미롭다. scorer/filter 입장에서는 "Phoenix retrieval이 K명 더 돌려줬다"처럼 보여서, 상위 랭킹 단계에서 PhoenixScore와 같은 분포로 섞인다.
    • 메커니즘은 임베딩 기반 retrieval이 아니다. "follow graph의 global popularity centroid"를 "가상 following"으로 Thunder에 넣는 복고적 접근이다.
    • "유저가 아무도 안 팔로우해도 Thunder가 뭔가 응답하도록" 또는 "유저 engagement 신호가 너무 적어서 다른 OON 소스가 결과를 못 돌려줄 때 공백을 메우도록" 쓰이는 전형적 global popularity backfill 패턴이다 추정.
    • EnablePopularPostsSource=false가 여전히 기본값이므로, 실제 활성 시점이 다음 창의 관측 지점이다.
  3. 광고 쪽 두 변경은 모두 "SFA(Suitable For Advertising) 라벨링을 포스트 수준 → 작성자 수준으로 확장"하는 변화다.
    • EnableAdsBrandSafetyVerdictV2=true 전환과 EnableAdsAuthorBrandSafetyFallback 신설이 같은 날 올라온 것은 우연이 아니다. 포스트 수준 Grok 라벨이 아직 없는 포스트에 작성자의 과거 라벨 패턴을 fallback으로 쓰는 방향이다.
    • 이는 Grok 분류기가 포스트 단위로는 커버가 성긴 상황(특히 신규 포스트)을 작성자 수준 집계로 보완하려는 신호다 추정.

레이더

오늘 레이더에 올린 논문은 없다. arXiv cs.IR 2026-10-01 ~ 2026-10-02 창에서 요청한 30건 중 <entry> 30건을 모두 파싱했고, 그중 세 수용 기준을 모두 넘는 항목은 0건이다.

  • ① 플랫폼 저자 또는 프로덕션 A/B
  • ② 메커니즘 신규성
  • ③ 대규모 결과

경계에 있던 세 항목도 모두 탈락했다.

  • arXiv 2609.39312는 Weihao Shen 외 7인의 Learning Multiresolution Relevance for Hierarchical Generative Retrieval이다. hierarchical generative retrieval에서 멀티해상도 관련성을 학습한다. ①의 플랫폼·배포 축이 비어 있어 탈락했다.
    • 저자 소속을 arXiv 1차 메타데이터로 바로 확인할 수 없었고, abstract에 프로덕션/배포 주장이 없다.
  • arXiv 2609.39319는 같은 7인 저자의 Residual Trajectory Distillation for Generative Retrieval이다. SID RQ(residual quantization)의 중간 trajectory를 distillation하는 접근이다. 같은 이유로 탈락했다.
    • 2609.39312와 짝을 이루는 아카데믹 라인이고, 어느 쪽도 industry 배포 주장이 없다.
  • arXiv 2609.39828는 Kuaishou 저자의 KUAISHOU Explorer LLM-Rec Challenge 2026: Reasoning Generative Recommendation이다. 본문이 챌린지 개요이고 메커니즘 신규성이 없어, ②의 메커니즘 신규성에서 탈락했다.
    • OneRec/OneRec-V2가 Kuaishou에 배포됐다는 사실(이미 레이더에 있는 라인)을 재확인하는 자료일 뿐이다.

어제 레이더에서 탈락한 Meta ETT% 추천 학습 인프라 논문(arXiv 2610.02057) 뒤 창에 올라온 2609.39xxx 번호대에서도, 추적할 가치가 있는 플랫폼 소속 신규 메커니즘은 발견되지 않았다.

다음에 볼 것