0x00

리서치 / 일일 리포트

  • 읽은 자료 2건
  • 정본 반영 2개 파일
  • 레이더 0건
한 줄 요약X 랭킹 점수식(value model)에 "열 확률 × 열었을 때 머무는 초" 꼴의 기대 체류 시간 항 3개가 처음 코드로 들어왔다. 가중치가 아직 0이라 서빙 점수는 그대로다.

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

  • X는 같은 커밋에서 사흘 전 생긴 인기 포스트 후보 소스를 조회수 기반 오프라인 잡으로 다시 만들었다.
  • Meta는 Facebook Feed 시스템 카드를 2026-10-06자로 갱신했고, 카드의 유일한 임베딩 피처 문장이 사라졌다.

1랭킹 점수식에 기대 체류 시간 항이 생겼다 — X

자료 xai-org/x-algorithm@e62790c — xai-org, 2026-10-06T04:59:30Z, 코드. 이 노트들은 4세대 공개 뒤의 X 커밋에 차례로 번호를 붙여 부르며, 이 커밋은 4세대+36이다. 바뀐 파일은 103개이고, 줄 수는 +6,916/−1,393이다. 직전 커밋은 2026-10-03의 b412112(4세대+35)다.

배경 X의 For You 랭킹에서는 Phoenix(Grok 기반 Transformer 랭커)가 포스트마다 행동 확률 수십 개를 예측한다. value model은 그 확률들을 가중합해 점수 하나로 만든다. head는 모델이 내는 예측값 하나하나를 가리킨다. 가중합에는 "좋아요할 확률" 같은 확률 head 외에 "머문 시간(dwell time)" 같은 연속값 head도 들어간다. 지금까지 연속값 head는 예측값을 그대로 가중치와 곱했다.

이번 커밋은 다른 방식을 추가한다. "영상을 열 확률"과 "열었을 때 이어서 볼 초"를 따로 예측하고, 둘을 곱해 기대 시청 초를 만드는 방식이다. 이런 분해를 조건부 기대값 분해라고 부른다(전체 기대값 = 사건 확률 × 사건이 일어났을 때의 기대값). 같은 커밋은 사흘 전 공개된 인기 포스트 후보 소스(PopularPostsSource)의 구조도 완전히 바꿨다.

새로 알게 된 것A. value model에 '확률 × 조건부 초' 꼴의 기대 체류 시간 항 3개가 생겼다

  • value model에 확률과 조건부 초를 곱하는 항 세 개가 추가됐다 확인 — xai-value-model/scoring.rs:61-63, 111-128.

    • 첫째 항은 "영상을 열 확률 × 열면 이어서 볼 초", 셋째 항은 "프로필을 누를 확률 × 누르면 프로필에 머물 초"다.

    • 세 항을 만드는 코드는 다음과 같다.

      fn product(probability: Option<f64>, conditional_value: Option<f64>) -> Option<f64> {
          Some(probability? * conditional_value?)
      }
      ...
      apply(product(scores.video_open_score, scores.home_video_continuation_secs), weights.video_continuation),
      apply(product(scores.video_open_score, candidate.user_video_continuation_secs), weights.user_video_continuation),
      apply(product(scores.profile_click_score, scores.home_profile_visit_secs), weights.profile_visit_secs),
      
  • 둘째 항은 후보가 아니라 유저의 값이다. 한 요청에 들어온 후보 전체에서 열 확률로 가중한 평균 시청 초를 구해, 모든 후보에 같은 값을 넣는다 확인 — scoring.rs:141-158.

    • 이 값은 set_user_video_continuation이 Σ P(open)·secs / Σ P(open)으로 계산한다.
    • 값이 후보마다 같으므로 이 항은 결국 가중치 × (유저 평균 시청 초) × P(open)이다. 영상을 오래 보는 유저일수록 "영상을 열 확률"의 계수가 커지는 효과를 낸다 추정.
  • 세 가중치의 크론 미러(프로덕션 파라미터 값을 매일 동기화해 공개하는 파일) 기본값은 모두 0.0이다 확인 — vm-ranker/params.rs.

    • 가중치 이름은 VideoContinuationWeight·UserVideoContinuationWeight·ProfileVisitSecsWeight다.
  • For You 피드 요청을 처리하는 home-mixer의 내부 경로(weights_for)는 세 값을 코드에서 0.0으로 고정한다 확인 — home-mixer/scorers/value_model.rs:37-39. 따라서 이 항을 켤 수 있는 곳은 VM-Ranker(value model을 직접 계산하는 별도 서비스)뿐이다.

  • Phoenix의 연속값 head 목록에 '프로필 방문 초'와 '영상 이어 보기 초' head가 생겼다 확인 — recsys.proto:594-599.

    • 목록 이름은 ContinuousActionName이고, 새 값은 HOME_PROFILE_VISIT_SECS = 0과 HOME_VIDEO_CONTINUATION_SECS = 3이다.
    • 3번은 그동안 ACTIVE_SECS_5M_RESIDUAL_NORM(가중치 0으로 묶여 있던 "5분 활동 초" 잔차 head)이 쓰던 번호다. 이 head는 proto와 value model 양쪽에서 사라졌다.
  • home-mixer가 두 head 값을 Phoenix 응답에서 꺼내는 것도 EnableHomeExcursionScores(기본 false) 뒤에 있다 확인 — home-mixer/scorers/phoenix_scorer.rs:109-117, 141-153.

  • 학습 데이터 쪽에는 비어 있던 자리에 새 집계 타입이 생겼다 확인.

    • PLACEHOLDER_30 자리에 DENSE_WITH_LONG_DWELL_HOME_EXCURSION = 30이 들어갔다.
  • README의 Phoenix 예측 목록도 바뀌었다 확인 — README.md:341.

    "Attention video quality view · dwell · dwell time · click dwell time · video continuation seconds · profile visit seconds"

    직전 판의 같은 줄은 ... click dwell time · active seconds였다.

새로 알게 된 것B. 인기 포스트 소스는 이제 오프라인 잡이 미리 만든 목록을 읽기만 한다

이번 판은 요청 경로에서 Thunder(팔로우 그래프 기반 최신 포스트 저장소) 호출을 없앴다. 사흘 전 판은 요청이 들어올 때마다 "인기 작성자 1,000명"을 Thunder에 가짜 팔로잉 목록처럼 넘겨, 그들의 최신 글을 받아 왔다.

처리는 다음 순서로 이뤄진다.

  1. 작성자 잡은 기본 1시간 주기로 돈다. BigQuery 테이블 popular_posting_authors의 팔로워 순위 스냅샷에서 최근 7일 안에 글을 쓴 작성자 수 × 0.00005명, 즉 팔로워 수 상위 0.005%를 고른다. 스냅샷이 30시간보다 오래되면 실패로 처리한다.
  2. 포스트 잡은 기본 5분 주기로 돈다. 그 작성자들을 20명씩 묶어 Thunder에서 작성자당 최대 50개 포스트를 받고, 답글과 리트윗은 버린다.
  3. 24시간 이내 포스트의 조회수(view_count)를 engagement counts 서비스에서 500개씩 받는다.
  4. 점수 계산은 조회 속도가 8시간마다 절반으로 줄어든다고 가정하고 지금까지의 조회수를 24시간 누적 조회수로 늘려 잡는 식으로 읽힌다 추정.
    • 식은 quality = views × (1 − e^{−λ·24}) / (1 − e^{−λ·max(age_h, 0.5)})이고, λ = ln2 / 8(반감기 8시간)이다.
    • 분모는 "지금 나이까지 쌓였을 비율", 분자는 "24시간까지 쌓일 비율"이다.
    • 나이 하한 0.5시간은 막 올라온 글의 점수가 폭주하지 않게 막는다.
  5. 작성자당 상위 5개, 전체 상위 500개를 남겨 Manhattan(KV 저장소)에 쓰고, 다시 읽어서 생성 시각이 같은지 확인한다.
  6. 서빙 소스는 60초마다 목록을 다시 읽고, 유저가 이미 본 포스트만 빼고 최대 500개를 후보로 낸다.
  • 사흘 전 판의 파라미터 세 개는 삭제됐다 확인.
    • PopularPostsTopAuthors(1000)·PopularPostsMaxPerAuthor(3)·PopularPostsMaxRepliesRepostsPerAuthor(0)
  • 유저별 입력이 "이미 본 포스트" 하나뿐이므로, 이 소스는 모든 유저에게 같은 전역 인기 목록이다 확인.
  • 소스 자체는 여전히 기본 off(EnablePopularPostsSource=false)다.

새로 알게 된 것C. 노출 판정에 '알림을 붙여 보여 주는' 네 번째 등급이 생겼다

visibility filtering(VF)은 후보 포스트를 이 뷰어에게 노출해도 되는지 판정하는 서비스다.

  • VF 판정이 4등급이 됐다 확인 — README.md:205-232. 기존 세 등급에 NOTICE가 추가됐다.

    • 기존 등급: ALLOW(그대로 표시), INTERSTITIAL(경고 화면 뒤에 표시), DROP(제거)

    • README는 새 등급을 이렇게 설명한다.

      "NOTICE show the post with a notice attached to it"

  • 내부 표현은 SoftIntervention { policy: AppealablePolicy, level, proactive, appeal_submitted }다 확인 — visibility-filtering/models/verdict.rs. 포스트는 피드에 남는다.

새로 알게 된 것D. "Under the Hood" 요청에는 파이프라인 처리 내역과 포스트별 점수를 함께 돌려준다

  • 요청에 Under the Hood 표시가 켜져 있으면, 응답에 파이프라인 처리 내역과 포스트별 점수가 함께 실린다 확인 — home-mixer/util/under_the_hood.rs.
    • 요청 필드는 is_under_the_hood_request다.
    • 단계별 지연·유지·제거 건수와 포스트별 Phoenix head 점수, 최종 점수, 사용한 value model 이름이 실린다.
    • 단계마다 github.com/xai-org/x-algorithm/blob/main/home-mixer/... 형태의 공개 코드 링크가 붙는다.
    • 플래그 EnableUnderTheHood의 기본값은 false다.
    • 공개 저장소 링크를 응답에 넣는 것으로 보아, "이 포스트가 왜 떴나"를 보여 주는 화면용 기능으로 보인다 추정. 어느 화면에 나오는지는 저장소에 없다.

새로 알게 된 것그 밖의 변경

  • 새-작성자 부스트(아직 노출되지 않은 작성자의 포스트에 주는 가산점)는 지금까지 in-network 후보에만 붙었다. 스위치를 켜면 OON(팔로우하지 않는 계정) 후보에도 붙는다 확인 — scoring.rs:85-90.
    • 항 이름은 post_unexplored이고, 스위치는 PostUnexploredIncludeOutOfNetwork(기본 false)다.
  • RetrievalCandidatesKafkaMaxCandidates가 200에서 100,000으로 바뀌었다 확인. retrieval(후보 생성 단계) 후보를 Kafka로 기록하는 상한이 사실상 풀렸다 추정.
  • VMRankerClusterId가 "Experiment6"에서 "Experiment1"로 바뀌었다 확인. 실험 클러스터 간 차이는 공개되지 않았다.

정본 반영 services/x.md에서 다음을 고쳤다.

  • 후보 생성 절 소스 표의 PopularPostsSource 행을 새 구조로 덮어썼다.
  • 가중치 절 헤드 표에서 cont_active_secs_5m_residual_norm을 제거 표시하고, 새 항 3개 행을 추가했다.
  • VMRanker 파라미터 표의 VMRankerClusterId 값을 갱신했다.
  • ### 4세대+36 절을 새로 만들었다. 출처 절에는 기준 커밋 e62790c를 추가했다.

의미 X value model의 연속값 항은 지금까지 "head 값 × 가중치" 한 가지였는데, 이번에 확률 head × 조건부 초 head라는 두 번째 형태가 생겼다. 가중치가 0이므로 서빙 점수는 아직 바뀌지 않았다 확인.

  • 프로필 클릭 확률(profile_click)의 가중치는 4세대 공개 시점부터 0.0이다. 프로필 클릭 확률 자체에는 보상하지 않으면서 클릭 뒤 머문 시간에는 보상할 수 있는 경로가 따로 생겼다 추정. 확률 head가 이번 항에서는 곱의 인자로만 쓰인다.
  • 인기 포스트 소스(PopularPostsSource)는 공개 사흘 만에 정의가 "인기 작성자의 최신 글"에서 "인기 작성자의 글 중 조회수가 빨리 늘어나는 글"로 바뀌었다. 요청당 Thunder 호출이 사라져 요청 비용이 일정해졌다 확인.

2Facebook Feed 시스템 카드에서 임베딩 피처 문장이 사라졌다 — Facebook

자료 Facebook Feed AI system — Meta Transparency Center, 카드 표기 "UPDATED OCT 6, 2026"(2026-10-06), 시스템 카드(규제 대응 설명 문서). 직전 판은 2026-06-24자였다.

배경 Meta는 지면마다 "시스템 카드"를 공개한다. 그 지면의 피드가 어떤 단계로 만들어지는지, 어떤 예측 head가 있고 head마다 어떤 입력 시그널이 들어가는지를 일반인용 문장으로 적은 문서다. 이 저장소는 2026-08-09에 이 카드를 읽고 Facebook 정본의 예측 head와 피처 목록을 만들었다. 오늘 카드 날짜가 바뀐 것을 확인했고, 헤드리스 Chrome으로 영문 판을 렌더링해 전문을 다시 읽었다. 카드에 변경 내역은 없다.

새로 알게 된 것A. 카드의 유일한 임베딩 피처였던 문장이 지금 판에는 없다

  • 카드의 유일한 임베딩 피처였던 문장이 없다 관찰 2026-10-07.
    • 2026-08-09에 읽은 판에는 이 문장이 있었다: "An embedding to represent the viewer".
    • 오늘 렌더링한 전문에서 "embedding"이라는 단어는 한 번도 나오지 않는다.
    • 현재 시그널 50개는 모두 횟수·비율·시간 창 집계다.
    • 카드 날짜가 그 사이 바뀐 것은 이번 한 번뿐이므로 10-06 갱신에서 빠졌다고 본다 추정. 다만 이전 판 원문을 보관하지 않았고 Wayback이 오늘 응답하지 않아, 직접 비교하지는 못했다.
    • 카드에서 문장이 빠졌다고 모델이 viewer embedding을 쓰지 않게 됐다는 뜻은 아니다. 카드는 "significant predictions" 일부만 싣는다.

새로 알게 된 것B. 카드는 integrity 처리를 두 단계에 나눠 적고 있다

  • integrity(정책 위반·문제 콘텐츠 처리)가 두 단계에 나뉘어 적혀 있다 관찰 2026-10-07.
    • 위반으로 플래그된 포스트는 후보를 모을 때 빠진다. 카드에서 이 내용은 "Gather inventory"(인벤토리 수집) 단계 아래에 있다.

      "First, the system gathers all potential posts shared by friends, Pages you follow and groups you've joined, which excludes posts flagged for going against our Community Standards."

    • 분포를 줄이는 처리는 경량 모델이 약 500개를 고르는 단계(pass 0)와 같은 단락에 있다. 카드에서 이 내용은 "Leverage signals"(시그널 활용) 단계 아래에 있다.

      "A lightweight model is run to select approximately 500 of the most relevant posts. The system also applies certain integrity processes to help reduce the distribution of problematic content." — Facebook Feed AI system, 2026-10-06 판

    • 정본은 그동안 "fb-feed 카드는 integrity 단계를 말하지 않는다"라고 적어 왔다. 인벤토리 단계의 제외 문장이 이번에 새로 들어간 것인지, 2026-08-09에 놓친 것인지는 판정할 수 없다.

새로 알게 된 것C. head 수와 순서는 직전 판과 같고, 5번 head 이름과 lookback 창은 정본에 적힌 것과 달랐다

  • 예측 head는 10개이고, head마다 시그널 5개로 모두 50개다. head의 수와 순서는 직전 판과 같다 관찰 2026-10-07.

  • 5번 head는 interested/not interested 선택지가 제시됐을 때 'Interested'를 누를 확률로 적혀 있다 관찰 2026-10-07.

    "How likely you are to click 'Interested' if the interested/not interested options are presented to you." — Facebook Feed AI system, 2026-10-06 판

    • 정본은 이 head를 'Show more' 클릭으로 적어 두었다.
    • Meta는 2025-03-11에 Show more를 Interested로 이름을 바꿨다고 이미 밝혔으므로 같은 head다. 정본 문구를 현재 이름으로 고쳤다.
  • lookback 창(피처가 집계하는 과거 기간)은 1시간·2시간·1일·7일·14일·28일·30일·180일이다 관찰 2026-10-07. 정본에 있던 "3개월" 창은 현재 판에 없다.

새로 알게 된 것그 밖의 관찰

  • "How to customize" 절에 Instagram 앱 설명 문단이 섞여 있다 관찰 2026-10-07.

    "You can click the Instagram logo on your home screen and then click on either “Following” or “Favorites” on mobile app."

    • Facebook 카드에 Instagram 카드의 문구가 복사돼 들어간 편집 오류로 보인다 추정. 같은 절에 Facebook의 "See newest content first" 항목이 따로 있다.
  • 이 페이지는 자바스크립트로 렌더링되므로 curl로는 본문이 나오지 않고, /en-us/ 없이 열면 한국어 판이 나온다. 재현하려면 헤드리스 Chrome으로 DOM을 받아 텍스트를 뽑는다.

    • 명령은 "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --headless=new --lang=en-US --virtual-time-budget=15000 --dump-dom https://transparency.meta.com/en-us/features/explaining-ranking/fb-feed/다.

정본 반영 services/facebook.md에서 다음을 고쳤다.

  • 랭킹 절의 integrity 단계 불릿을 두 문장 구조로 덮어썼다.
  • 예측 헤드 절의 카드 갱신일을 2026-10-06으로 올리고, 5번 head를 'Interested' 원문으로 바꿨다.
  • 실제 피처 이름 절에서 viewer embedding 문장에 ⚠ 표시를 하고, 현재 판에는 없다는 관찰을 적었다. lookback 창 목록도 고쳤고, Instagram 문단 혼입을 기록했다.
  • 열린 질문에 14번(10-06 갱신의 정확한 diff)을 추가했다.

의미

  • ⚠ 주장 변경: 정본의 "viewer embedding은 fb-feed 카드에 명시된 유일한 임베딩 피처다"는 현재 판 기준으로 성립하지 않는다. 지금 카드에는 임베딩 피처가 하나도 없다.
  • ⚠ 주장 변경: "fb-feed 카드는 integrity 단계를 말하지 않는다"도 현재 판 기준으로 성립하지 않는다. 삭제형 처리는 인벤토리 수집 단계에, 감점형 처리는 pass 0 단락에 놓여 있다.

다음에 볼 것